�
oB�]c@s�ddlmZddlZddlZddlZddlmZddlmZddlm Z ddlm
Z
eje�Z
dZddeefd d eefd
d
eefddeefd
d
eefgZdejfd��YZd�Zd�Zd�Zddeddd�Zd�Zdefd��YZdefd��YZeejejffgZd�Z edkr�d�Z!e!�ndS(i����(tprint_functionN(tlog(tsources(t
url_helper(tutils
2012-03-01smeta-data/instance-idsmeta-data/local-hostnamesmeta-data/public-keyssmeta-data/vendor-datasvendor-datas user-datatDataSourceMAAScBsneZdZdZd
Zd
Zd�Zed��Z d�Z
d�Zd�Zd�Z
d�Zd �ZRS(s�
DataSourceMAAS reads instance information from MAAS.
Given a config metadata_url, and oauth tokens, it expects to find
files under the root named:
instance-id
user-data
hostname
vendor-data
tMAAScCsStjj||||�d|_tjj|jd�|_t |j
�|_dS(Ntmaas(Rt
DataSourcet__init__tNonetbase_urltostpathtjointseed_dirtget_id_from_ds_cfgtds_cfgtid_hash(tselftsys_cfgtdistrotpaths((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR 0s cCs%|jst|j�|_n|jS(N(t
_oauth_helpertget_oauth_helperR(R((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pytoauth_helper6s cCs#tjj|�}d||jfS(Ns%s [%s](RRt__str__R(Rtroot((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR<sc
Cs|j}y$|j|jt|j��tSWn<tk
r@n,tk
rk}tjd|j|��nX|j dd�}|s�tSyL|j|�s�tS|j|t
|d|jjd|jdd��tSWn%tk
r�tjtd|�tSXdS(Ns%s was malformed: %stmetadata_urltread_file_or_urlRtretriesis$Failed fetching metadata from url %s(Rt _set_dataRtread_maas_seed_dirtTruetMAASSeedDirNonetMAASSeedDirMalformedtLOGtwarningtgetR
tFalsetwait_for_metadata_servicetread_maas_seed_urlRtreadurlRt ExceptionRtlogexc(Rtmcfgtexcturl((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyt _get_data@s.
cCs�||_|\}}}||_||_||_|r�ytj|�|_Wq�tk
r}}tj d|�d|_q�XndS(Ns"Invalid content in vendor-data: %s(Rtuserdata_rawtmetadatatvendordata_pureRtconvert_vendordatatvendordata_rawt
ValueErrorR$R%R
(RR/tdatatudtmdtvdte((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyRbs cCsd|jS(s/Return the subplatform metadata source details.s
seed-dir (%s)(R(R((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyt_get_subplatformpsc Cse|j}d}yt|jd|��}Wn$tk
rQtjtd|�nX|dkrbtSd}y+||kr�t|jd|��}nWn!tk
r�tjd|�nXt j �}|j
d�r�|d }nd
|tf}|g}|jj
d|d|d|�\}}|r8tjd|�n#tjd
|tt j �|��t|�S(Nixtmax_waits Failed to get max wait. using %sii2ttimeoutsFailed to get timeout, using %st/i����s%s/%s/meta-data/instance-idturlssUsing metadata source: '%s's(Giving up on md from %s after %i seconds(RtintR&R+RR,R$R'R%ttimetendswitht
MD_VERSIONRtwait_for_urltdebugtcriticaltbool( RR/R-R=R>t starttimet check_urlR@t _response((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR(ts4
cCsD|jdkrtStj|d|jfi�}|jt|�kS(slocally check if the current system is the same instance.
MAAS doesn't provide a real instance-id, and if it did, it is
still only available over the network. We need to check based
only on local resources. So compute a hash based on Oauth tokens.t
datasourceN(RR
R'Rtget_cfg_by_pathtdsnameR(RRtncfg((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pytcheck_instance_id�sN(t__name__t
__module__t__doc__RNR
RRR tpropertyRRR0RR<R(RP(((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR!s " "cCsAd}tg|D]}||j|�f^q�}tj|�S(s�Return an oauth helper instance for values in cfg.
@raises ValueError from OauthUrlHelper if some required fields have
true-ish values but others do not.tconsumer_keytconsumer_secrett token_keyttoken_secret(RURVRWRX(tdictR&RtOauthUrlHelper(tcfgtkeystrtkwargs((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR�s.cCsTd}djg|D]}|j|d�^q�}dtj|jd��j�S( s;Given a config, generate a unique identifier for this node.RURWRXttsv1:sutf-8(sconsumer_keys token_keystoken_secret(RR&thashlibtsha256tencodet hexdigest(Rtfieldstftidstr((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR�s.cCsm|jd�r|d}ntjj|�sJttj|��dkrYtd��ntd|dd�S(Nsfile://iis%s: not a directorys file://%stversion( t
startswithRR
tisdirtlentlistdirR"R)R
(tseed_d((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR �s
.c Csx|dkrtj}n|jd�r4|d }ni}x.tD]&\}}} }
|dkrrd||f}nd|||f}y�tj|�}||d|d|d|�}
|
j�r�| r�|
j||<qtj |
j�||<nt
jd||
j�WqAtj
k
rf}|jd krK|
rKtd
||f��qg|jd krg|�qgqAXqAWt||�S(s�
Read the maas datasource at seed_url.
read_file_or_url is a method that should provide an interface
like util.read_file_or_url
Expected format of seed_url is are the following files:
* <seed_url>/<version>/meta-data/instance-id
* <seed_url>/<version>/meta-data/local-hostname
* <seed_url>/<version>/user-data
If version is None, then <version>/ will not be used.
R?i����s%s/%ss%s/%s/%sRR>tssl_detailss4Fetching from %s resulted in an invalid http code %si�sMissing required %s: %sN(R
RRRCt DS_FIELDSRtfetch_ssl_detailstoktcontentst
decode_binaryR$R%tcodetUrlErrorR#tcheck_seed_contents(tseed_urlRR>RhRRR9R
t _dictnametbinarytoptionalR/RntrespR;((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR)�s4
c
Csti}g}x�tD]�\}}}}||krM|s|j|�qqnd|kr�|jd�\}} }
||kr�i||<n|||||
<q||||<qWt|�dkr�td|��n|r�td||f��nd}|jd�rUt�}t j
|jd�d|dt�}||krUtd��qUn|jd �|jd
�|fS(s�Validate if dictionary content valid as a return for a datasource.
Either return a (userdata, metadata, vendordata) tuple or
Raise MAASSeedDirMalformed or MAASSeedDirNone
R?is%s: no data files founds%s: missing files %ssvendor-datatdefaulttalloweds%vendor-data was not loadable as yaml.s user-datas meta-dataN(Rotappendt partitionRkR"R#R
R&tobjectRt load_yaml(
tcontenttseedtrettmissingtspathtdpatht_binaryRzttopt_tptvd_dataterr((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyRv�s2
R"cBseZRS((RQRR(((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR"sR#cBseZRS((RQRR(((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR#scCstj|t�S(N(Rtlist_from_dependstdatasources(tdepends((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pytget_datasource_list#st__main__c
s�ddl}ddl}ddl}|jdd�}|jddddd d
d�|jddddd
d
d�|jdddddd
d�|jdddddd
d�|jdddddd
d�|jdddddd
t�|jdddd�}xQdDdEdFfD]@\}}|j|d|�}|jd#dd$d%d&d
d�qW|j �}i|j
d'6|jd(6|jd)6|j
d*6} |jdkrxfdGD][}
d-|
d.}tjj|�r�tj|tj�r�|jjd/|�||_q�q�Wn|jr�tj|j�}d0|krF|d0d1}nxA| j�D]3}
|
|krS| |
dkrS||
| |
<qSqSW|jdkr�d2|kr�|d2|_q�n|jdkr�|jjd3�|jd4�nt| ���fd5���fd6�����fd7��|jd!kr1|jjd8|j��j}|jd9d:ksz|jjd;�r�t|j�\}}}n-t |jd|j!d<|d=d>�\}}}t"d?�t"|dkr�d@n |j#��t"dA�|j|�t"dB�|j|dkr'd@n|�nc|jdkrP�|j�nD|jdkr�|jj$d:�s�dC|j|_n�|j�ndS(Hs�
Call with single argument of directory or http or https url.
If url is given additional arguments are allowed, which will be
interpreted as consumer_key, token_key, token_secret, consumer_secret
i����NtdescriptionsInteract with MAAS DSs--configtmetavartfilethelpsspecify DS config fileR|s--ckeytkeysthe consumer key to auth withs--tkeysthe token key to auth withs--csectsecretsthe consumer secret (likely '')R`s--tsecsthe token secret to auth withs--apiverRhs the apiver to use ( can be used)ttitletsubcommandstdesttsubcmdtcrawlscrawl the datasourceR&sdo a single GET of provided urls
check-seedsread and verify seed at urlR/sthe datasource urltnargst?RURWRXRVt91_kernel_cmdline_urlt90_dpkg_maass/etc/cloud/cloud.cfg.d/s.cfgsUsed config in %s.
RLRRs)Must provide a url or a config with url.
ics�j|dd�jS(NRi(R*Rr(R/(R(sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pytgeturlescs$td|�|�j�f�dS(Ns== %s ==
%s
(tprinttdecode(R/(R�(sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pytprinturliscs�|jd�r�x��|�j�j�D]c}|jd�rT�d||f�q(|dkrw�d|df�q(�d||f�q(Wn
�|�dS(NR?s%s%ss meta-datas
meta-data/(RCR�t
splitlines(R/tline(R�R�R�(sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyR�lssChecking seed at %s
iR?sfile://RRis=== user-data ===sN/As=== meta-data ===s=== vendor-data ===s%s/(scrawlscrawl the datasource(sgetsdo a single GET of provided url(s
check-seedsread and verify seed at url(R�R�(%targparsetpprinttsystArgumentParsertadd_argumentR
RDtadd_subparserst
add_parsert
parse_argstckeyttkeyttsectcsectconfigRR
texiststaccesstR_OKtstderrtwriteRt read_confR\R/texitRR�R*RiR R)tapiverR�R�RC(R�R�R�tparsertsubcmdstnameR�R�targstcredstfnametfpathR[R�R*tuserdataR2R:((R�R�RR�sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pytmain(s�
'
%
"
"("t
__future__RRaRRBt cloudinitRtloggingRRRt getLoggerRQR$RDR'R!RoRRRRR R
R)RvR+R"R#tDEP_FILESYSTEMtDEP_NETWORKR�R�R�(((sD/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceMAAS.pyt<module> s8�
. & i |