o
    fi;                     @   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rd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
    MAASNx   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 )zReturn 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   sL   |  dr| dd  } tj| rtt| dkrtdtd|  d dS )Nfile://   r   z%s: not a directoryz	file://%s)version)
startswithr   r   isdirlen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t|dkrHtd| |rRtd||f d}|drot }tj	|d|td}||u rotd|d	|d
|fS )zValidate if dictionary content valid as a return for a datasource.
    Either return a (userdata, metadata, vendordata) tuple or
    Raise MAASSeedDirMalformed or MAASSeedDirNone
    rG   r   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.   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 rd!D ] }
d"|
 d# }tj|rt|tjr|jd$|  ||_q||jrt|j}d%|v r|d% d& }|	 D ]}||v r|	| du r|| |	|< q|jdu rd'|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sd<|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   

 
	
:'
 
 