o
    x[h];  ã                   @   s  d dl Z d dlZd dlZd dlZd dlmZmZmZ d dlm	Z	 d dl
mZ e e¡ZdZg d¢ZG dd„ dejƒZG d	d
„ d
eƒZdd„ Zdd„ Zdd„ Zddeddfdd„Zdd„ ZG dd„ deƒZG dd„ deƒZeejffeejejffgZdd„ Zedkr‹dd„ Z e ƒ  dS dS )é    N)ÚsourcesÚ
url_helperÚutil)ÚKlibcNetworkConfigSource)ÚNetworkConfigSourcez
2012-03-01))úmeta-data/instance-idr   FF)úmeta-data/local-hostnamer   FF)úmeta-data/public-keysr	   FT)zmeta-data/vendor-dataúvendor-dataTT)ú	user-datar   TTc                   @   sh   e Zd ZdZdZdZdZdZdZdd„ Z	e
dd	„ ƒZd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚDataSourceMAASzç
    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
    ÚMAASNéx   é2   c                 C   s:   t j | |||¡ d | _tj |jd¡| _t| j	ƒ| _
d S )NÚmaas)r   Ú
DataSourceÚ__init__Úbase_urlÚosÚpathÚjoinÚseed_dirÚget_id_from_ds_cfgÚds_cfgÚid_hash)ÚselfÚsys_cfgÚdistroÚpaths© r   úB/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceMAAS.pyr   2   s   zDataSourceMAAS.__init__c                 C   s   | j s	t| jƒ| _ | j S ©N)Ú_oauth_helperÚget_oauth_helperr   ©r   r   r   r    Úoauth_helper8   s   zDataSourceMAAS.oauth_helperc                 C   s   t j | ¡}d|| jf S )Nz%s [%s])r   r   Ú__str__r   )r   Úrootr   r   r    r&   >   s   zDataSourceMAAS.__str__c              
   C   sÈ   | j }z|  | jt| jƒ¡ W dS  ty   Y n ty- } z	t d| j|¡ ‚ d }~ww | dd ¡}|s8dS z|  	|¡sAW dS |  |t
|| jj| jdd�¡ W dS  tyc   t td|¡ Y dS w )NTz%s was malformed: %sÚmetadata_urlFé   )Úread_file_or_urlr   Úretriesz$Failed fetching metadata from url %s)r   Ú	_set_datar   Úread_maas_seed_dirÚMAASSeedDirNoneÚMAASSeedDirMalformedÚLOGÚwarningÚgetÚwait_for_metadata_serviceÚread_maas_seed_urlr%   Úreadurlr   Ú	Exceptionr   Úlogexc)r   ÚmcfgÚexcÚurlr   r   r    Ú	_get_dataB   s>   €þ
üþ	þzDataSourceMAAS._get_datac              
   C   sp   || _ |\}}}|| _|| _|r6z	t |¡| _W d S  ty5 } zt d|¡ d | _W Y d }~d S d }~ww d S )Nz"Invalid content in vendor-data: %s)	r   Úuserdata_rawÚmetadatar   Úconvert_vendordataÚvendordata_rawÚ
ValueErrorr0   r1   )r   r:   ÚdataÚudÚmdÚvdÚer   r   r    r,   i   s   
€þýzDataSourceMAAS._set_datac                 C   s
   d| j  S )z/Return the subplatform metadata source details.zseed-dir (%s))r   r$   r   r   r    Ú_get_subplatformv   s   
zDataSourceMAAS._get_subplatformc                 C   sŽ   |   ¡ }|jdkrdS t ¡ }| d¡}d|tf }|g}| jj||j|jd�\}}|r6t	 
d|¡ t|ƒS t	 d|tt ¡ | ƒ¡ t|ƒS )Nr   Fú/z%s/%s/meta-data/instance-id)ÚurlsÚmax_waitÚtimeoutzUsing metadata source: '%s'z(Giving up on md from %s after %i seconds)Úget_url_paramsÚmax_wait_secondsÚtimeÚ	monotonicÚrstripÚ
MD_VERSIONr%   Úwait_for_urlÚtimeout_secondsr0   ÚdebugÚcriticalÚintÚbool)r   r:   Ú
url_paramsÚ	starttimeÚ	check_urlrH   Ú	_responser   r   r    r3   z   s*   


ýúýz(DataSourceMAAS.wait_for_metadata_servicec                 C   s0   | j du rdS t |d| jfi ¡}| j t|ƒkS )a  locally 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.NFÚ
datasource)r   r   Úget_cfg_by_pathÚdsnamer   )r   r   Úncfgr   r   r    Úcheck_instance_id”   s   
z DataSourceMAAS.check_instance_id)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r]   r   r"   Úurl_max_waitÚurl_timeoutr   Úpropertyr%   r&   r;   r,   rF   r3   r_   r   r   r   r    r      s     

'r   c                       s0   e Zd ZejejejejfZ‡ fdd„Z	‡  Z
S )ÚDataSourceMAASLocalc                    s,   t ƒ  ¡ st d¡ dS t d¡ tƒ  ¡ S )NzNo initramfs applicable configFz!Found initramfs applicable config)r   Úis_applicabler0   rS   Úsuperr;   r$   ©Ú	__class__r   r    r;   ¨   s
   



zDataSourceMAASLocal._get_data)r`   ra   rb   r   ÚCMD_LINEÚ
SYSTEM_CFGÚDSÚ	INITRAMFSÚnetwork_config_sourcesr;   Ú__classcell__r   r   rj   r    rg       s    ürg   c                    s*   d}t ‡ fdd„|D ƒƒ}tjdi |¤ŽS )z¢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.)Úconsumer_keyÚconsumer_secretÚ	token_keyÚtoken_secretc                    s   g | ]	}|ˆ   |¡f‘qS r   ©r2   )Ú.0Úr©Úcfgr   r    Ú
<listcomp>¸   s    z$get_oauth_helper.<locals>.<listcomp>Nr   )Údictr   ÚOauthUrlHelper)rz   ÚkeysÚkwargsr   ry   r    r#   ²   s   r#   c                    s4   d}d  ‡ fdd„|D ƒ¡}dt | d¡¡ ¡  S )z;Given a config, generate a unique identifier for this node.)rr   rt   ru   ú c                    s   g | ]}ˆ   |d ¡‘qS )Ú rv   )rw   Úf©r   r   r    r{   ¿   s    z&get_id_from_ds_cfg.<locals>.<listcomp>zv1:zutf-8)r   ÚhashlibÚsha256ÚencodeÚ	hexdigest)r   ÚfieldsÚidstrr   rƒ   r    r   ¼   s   r   c                 C   sD   |   d¡r| dd … } tj | ¡rt | ¡stdƒ‚td|  d d�S )Núfile://é   z%s: not a directoryz	file://%s)Úversion)Ú
startswithr   r   ÚisdirÚlistdirr.   r4   )Úseed_dr   r   r    r-   Å   s
   
r-   c                 C   s  |du rt j}|  d¡r| dd… } i }tD ]n\}}}	}
|du r'd| |f }nd| ||f }z,t |¡}|||||d�}| ¡ rQ|	rH|j||< nt |j¡||< nt	 
d||j¡ W q t jy„ } z|jdkrs|
sstd	||f ƒ|‚|jdkrz|‚W Y d}~qd}~ww t|| ƒS )
a›  
    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.
    NrG   éÿÿÿÿz%s/%sz%s/%s/%s)r+   rJ   Ússl_detailsz4Fetching from %s resulted in an invalid http code %si”  zMissing required %s: %s)r   r*   ÚendswithÚ	DS_FIELDSr   Úfetch_ssl_detailsÚokÚcontentsÚdecode_binaryr0   r1   ÚcodeÚUrlErrorr/   Úcheck_seed_contents)Úseed_urlr*   rJ   rŒ   r   r+   rC   r   Ú	_dictnameÚbinaryÚoptionalr:   r’   ÚresprE   r   r   r    r4   Ï   sJ   

ÿý€
ÿþ
ÿ€û
r4   c                 C   sì   i }g }t D ]5\}}}}|| vr|s| |¡ qd|v r5| d¡\}}	}
||vr,i ||< | | || |
< q| | ||< q|sDtd| ƒ‚|rNtd||f ƒ‚d}| d¡rktƒ }tj| d¡|td�}||u rktdƒ‚| d¡| d	¡|fS )
z·Validate if dictionary content valid as a return for a datasource.
    Either return a (userdata, metadata, vendordata) tuple or
    Raise MAASSeedDirMalformed or MAASSeedDirNone
    rG   z%s: no data files foundz%s: missing files %sNr
   )ÚdefaultÚallowedz%vendor-data was not loadable as yaml.r   ú	meta-data)	r”   ÚappendÚ	partitionr.   r/   r2   Úobjectr   Ú	load_yaml)ÚcontentÚseedÚretÚmissingÚspathÚdpathÚ_binaryrŸ   ÚtopÚ_ÚpÚvd_dataÚerrr   r   r    r›   	  s4   

ÿr›   c                   @   ó   e Zd ZdS )r.   N©r`   ra   rb   r   r   r   r    r.   0  ó    r.   c                   @   r´   )r/   Nrµ   r   r   r   r    r/   4  r¶   r/   c                 C   s   t  | t¡S r!   )r   Úlist_from_dependsÚdatasources)Údependsr   r   r    Úget_datasource_list@  s   rº   Ú__main__c                     s  ddl } ddl}ddl}| jdd�}|jddddd� |jd	d
ddd� |jdd
ddd� |jddddd� |jddddd� |jdddtd� |jddd�}dD ]\}}|j||d�}|jddddd� qQ| ¡ }|j	|j
|j|jd œ}	|jdu r�d!D ] }
d"|
 d# }tj |¡rœt |tj¡rœ|j d$| ¡ ||_q||jrÕt |j¡}d%|v r°|d% d& }|	 ¡ D ]}||v rÆ|	| du rÆ|| |	|< q´|jdu rÕd'|v rÕ|d' |_|jdu rå|j d(¡ | d)¡ t|	ƒ‰‡fd*d+„‰‡fd,d-„‰‡ ‡‡fd.d/„‰ |jd0k�rc|j d1|j ¡ ˆj}|jd d2k�s|j d3¡�r't|jƒ\}}}nt|j|j |d4d5�\}}}t!d6ƒ t!|du �r@d7n| "¡ ƒ t!d8ƒ | |¡ t!d9ƒ | |du �r^d7¡ dS |¡ dS |jd:k�rpˆ|jƒ dS |jd;k�rŠ|j #d2¡�sƒd<|j |_ˆ |jƒ dS dS )=zä
        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
        r   NzInteract with MAAS DS)Údescriptionz--configÚfilezspecify DS config file)ÚmetavarÚhelpr¡   z--ckeyÚkeyzthe consumer key to auth withz--tkeyzthe token key to auth withz--csecÚsecretzthe consumer secret (likely '')r�   z--tseczthe token secret to auth withz--apiverrŒ   z the apiver to use ( can be used)ÚsubcommandsÚsubcmd)ÚtitleÚdest))Úcrawlzcrawl the datasource)r2   zdo a single GET of provided url)ú
check-seedzread and verify seed at url)r¿   r:   zthe datasource urlú?)r¿   Únargsr¡   )rr   rt   ru   rs   )Ú91_kernel_cmdline_urlÚ90_dpkg_maasz/etc/cloud/cloud.cfg.d/z.cfgzUsed config in %s.
r[   r   r(   z)Must provide a url or a config with url.
r)   c                    s   ˆ j | dd�jS )Nr)   )r+   )r5   r—   ©r:   )r%   r   r    Úgeturl¡  s   zmain.<locals>.geturlc                    s   t d| ˆ | ƒ ¡ f ƒ d S )Nz== %s ==
%s
)ÚprintÚdecoderÌ   )rÍ   r   r    Úprinturl¥  s   zmain.<locals>.printurlc                    sv   |   d¡r5ˆ| ƒ ¡  ¡ D ]%}|  d¡rˆ d| |f ƒ q|dkr*ˆ d| df ƒ qˆd| |f ƒ qd S ˆ| ƒ d S )NrG   z%s%sr£   z
meta-data/)r“   rÏ   Ú
splitlines)r:   Úline)rÆ   rÍ   rÐ   r   r    rÆ   ¨  s   

ù	zmain.<locals>.crawlrÇ   zChecking seed at %s
rG   rŠ   é   )rŒ   r*   r+   z=== user-data ===zN/Az=== meta-data ===z=== vendor-data ===r2   rÆ   z%s/)$ÚargparseÚpprintÚsysÚArgumentParserÚadd_argumentrP   Úadd_subparsersÚ
add_parserÚ
parse_argsÚckeyÚtkeyÚtsecÚcsecÚconfigr   r   ÚexistsÚaccessÚR_OKÚstderrÚwriter   Ú	read_confr~   r:   Úexitr#   rÃ   r5   r�   r-   r4   ÚapiverrÎ   rÏ   r“   )rÔ   rÕ   rÖ   ÚparserÚsubcmdsÚnamer¿   r±   ÚargsÚcredsÚfnameÚfpathrz   rÀ   r5   Úuserdatar=   rD   r   )rÆ   rÍ   r%   rÐ   r    ÚmainF  sÈ   üüüüüüÿü
€€


ü
"ýrñ   )!r„   Úloggingr   rM   Ú	cloudinitr   r   r   Úcloudinit.net.cmdliner   Úcloudinit.sourcesr   Ú	getLoggerr`   r0   rP   r”   r   r   rg   r#   r   r-   r4   r›   r6   r.   r/   ÚDEP_FILESYSTEMÚDEP_NETWORKr¸   rº   rñ   r   r   r   r    Ú<module>   sF   

 
	
ú:'
þ 
 �ó