
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
cj                 @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZ d dl	m
Z
mZ d dlmZmZmZmZmZ d dlmZmZmZmZmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lm Z m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z) dZ*dZ+dZ,dZ-e*e+e,gZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6ej7e8Z9ddd fddd fd d!d fd"Z:eG d#d$ d$e
Z;G d%d& d&e<Z=G d'd( d(e<Z>G d)d* d*e<Z?d+f fd,d-Z@e3fd.d/ZAed0d1d2d3d4gZBed5d6d7gZCG d8d de'e jDd9ZEd:d; ZFeeEeGf d<d=d>ZHd?d@ ZIdVeGeJdBdCdDZKdEdF ZLdWdHdIZMG dJdK dKeNZOdLdM ZPeEeGeJdNdOdPZQeGeeE dQdRdSZReGd<dTdUZSdS )X    N)
namedtuple)Enumunique)AnyDictListOptionalTuple)atomic_helperdmiimporternet
type_utils)	user_data)util)
write_json)Distro)
EventScope	EventType)launch_index)Paths)CloudInitPickleMixin)eventsZdisabledlocalr   passZ
FILESYSTEMNETWORK
DataSourcez|EXPERIMENTAL: The structure and format of content scoped under the 'ds' key may change in subsequent releases of cloud-init.zredacted for non-root userz
cloud-nameZ_unsetunknownz	aws-chinac             C   s   | dkS )Naws )cr   r   /usr/lib/python3.6/__init__.py<lambda>?   s    r"   zaws-govc             C   s   | dkS )Nr   r   )r    r   r   r!   r"   @   s    zazure-chinac             C   s   | dkS )NZazurer   )r    r   r   r!   r"   A   s    )zcn-zus-gov-Zchinac               @   s2   e Zd ZdZdZdZdZdZdZe	ddd	Z
d
S )NetworkConfigSourcezb
    Represents the canonical list of network config sources that cloud-init
    knows about.
    cmdlinedsZ
system_cfgZfallbackZ	initramfs)returnc             C   s   | j S )N)value)selfr   r   r!   __str__R   s    zNetworkConfigSource.__str__N)__name__
__module____qualname____doc__CMD_LINEDS
SYSTEM_CFGZFALLBACK	INITRAMFSstrr)   r   r   r   r!   r#   E   s   r#   c               @   s   e Zd ZdZdS )DatasourceUnpickleUserDataErrorzERaised when userdata is unable to be unpickled due to python upgradesN)r*   r+   r,   r-   r   r   r   r!   r3   V   s   r3   c               @   s   e Zd ZdS )DataSourceNotFoundExceptionN)r*   r+   r,   r   r   r   r!   r4   Z   s   r4   c               @   s   e Zd ZdZdS )InvalidMetaDataExceptionz8Raised when metadata is broken, unavailable or disabled.N)r*   r+   r,   r-   r   r   r   r!   r5   ^   s   r5    c       
      C   s   t j| }g }g }x| j D ]\}}|r6|d | }n|}|j |ksR|j |kr\|j| t|tr|jdr|j| |jdd||< t|t	rt
|||}	|j|	jd |j|	jd |	||< qW t||d< t||d< |S )zProcess all instance metadata cleaning it up for persisting as json.

    Strip ci-b64 prefix and catalog any 'base64_encoded_keys' as a list

    @return Dict copy of processed metadata.
    /zci-b64:r6   base64_encoded_keyssensitive_keys)copydeepcopyitemslowerappend
isinstancer2   
startswithreplacedictprocess_instance_metadataextendpopsorted)
metadatakey_pathr9   md_copyr8   Z	sens_keyskeyvalZsub_key_pathZ
return_valr   r   r!   rC   b   s,    




rC   c             C   s   | j dg s| S tj| }xh| j dD ]Z}|jd}|}x6|D ].}||kr>t|| tr>||d kr>|| }q>W ||kr&|||< q&W |S )zRedact any sensitive keys from to provided metadata dictionary.

    Replace any keys values listed in 'sensitive_keys' with redact_value.
    r9   r7      )getr:   r;   splitr?   rB   )rG   Zredact_valuerI   rH   
path_partsobjpathr   r   r!   redact_sensitive_keys   s    


rS   	URLParamsZmax_wait_secondsZtimeout_secondsZnum_retriessec_between_retriesDataSourceHostnamehostname
is_defaultc            
   @   s  e Zd ZU eZdZdZdZdZdZ	dZ
ejejejejfZeedf d|ZdZdZdZejejejejejhiZejejhiZdefd	efd
i fd}d~ddddf	Z eee!e"f df  dZ#dZ$ee!df $dZ%dZ&de'e(dddZ)e*ddddZ+d d! Z,e-d"d#d$Z.e-d"d%d&Z/d'd( Z0d)d* Z1f fd+d,Z2e-d"d-d.Z3dd0d1Z4e-d"d2d3Z5d4d5 Z6dd6d7Z7d8d9 Z8d:d; Z9e:d<d= Z;e:d>d? Z<e:d@dA Z=dBdC Z>e:dDdE Z?dFdG Z@e:dHdI ZAdJdK ZBe:dLdM ZCdNdO ZDdPdQ ZEdRdS ZFdTdU ZGdVdW ZHdXdY ZIdZd[ ZJd\d] ZKd^d_ ZLe:d`da ZMe:dbdc ZNddde ZOddfdgZPdhdi ZQeRe djdkdlZSeRe e-dmdndoZTdpdq ZUdrds ZVeWddtduZXe:dvdw ZYdxdy ZZdzd{ Z[dS )r   zen_US.UTF-8Z_undefN.rL   
      ec2_metadatanetwork_jsonrG   userdatauserdata_raw
vendordatavendordata_rawvendordata2vendordata2_rawFcombined_cloud_config
merged_cfgmerged_system_cfgsecurity-credentials	user-datar   vendor-datads/vendor_data)distropathsc             C   s~   || _ || _|| _d | _i | _d | _d | _d | _d | _d | _	t
j| j d| jfi | _| js`i | _|sttj| j| _n|| _d S )NZ
datasource)sys_cfgrj   rk   r]   rG   r^   r_   ra   r`   rb   r   Zget_cfg_by_pathdsnameds_cfgudZUserDataProcessorud_proc)r(   rl   rj   rk   rp   r   r   r!   __init__  s"    zDataSource.__init__)ci_pkl_versionr&   c             C   s   t | dsd| _t | ds d| _t | ds0d| _t | dsJt| ddd  t | d	r| jdk	ryt| j W n6 tk
r } ztj	d
| t
 |W Y dd}~X nX dS )z(Perform deserialization fixes for Paths.ra   Nrb   skip_hotplug_detectFcheck_if_fallback_is_allowedc               S   s   dS )NFr   r   r   r   r!   r"   =  s    z&DataSource._unpickle.<locals>.<lambda>r]   z:Unable to unpickle datasource: %s. Ignoring current cache.)hasattrra   rb   rs   setattrr]   r2   AttributeErrorLOGdebugr3   )r(   rr   er   r   r!   	_unpickle3  s     



zDataSource._unpicklec             C   s
   t j| S )N)r   obj_name)r(   r   r   r!   r)   O  s    zDataSource.__str__)r&   c             C   s   dS )z#Check if running on this datasourceTr   )r(   r   r   r!   	ds_detectR  s    zDataSource.ds_detectc             C   sN   | j j t j kr$tjd|  dS | jjdg | j gkrJtjd|  dS dS )aI  Override if either:
        - only a single datasource defined (nothing to fall back to)
        - commandline argument is used (ci.ds=OpenStack)

        Note: get_cmdline() is required for the general case - when ds-identify
        does not run, _something_ needs to detect the kernel command line
        definition.
        zOMachine is configured by the kernel commandline to run on single datasource %s.TZdatasource_listz5Machine is configured to run on single datasource %s.F)rm   r=   parse_cmdlinerx   ry   rl   rN   )r(   r   r   r!   override_ds_detectV  s    	zDataSource.override_ds_detectc             C   s@   | j  r| j S | j r,tjd|  | j S tjd|  dS dS )z&Overrides runtime datasource detectionz8Detected platform: %s. Checking for active instance dataz#Datasource type %s is not detected.FN)r   	_get_datar}   rx   ry   )r(   r   r   r!   _check_and_get_datam  s    zDataSource._check_and_get_datac             C   s   | j  j}| j }| j}|d }ddg||t| j| j| j| j| j|d d |d d |d d | j| j |d |||d	 d |||d	 d
 | j| j	|d |d diS )z2Return a dictionary of standardized metadata keys.sys_infov1subplatformZdistr   rL      pythonuname   platformvariant)Z
_beta_keyszavailability-zoneavailability_zonecloud_idz
cloud-name
cloud_namerj   Zdistro_versionZdistro_releaser   Zpublic_ssh_keysZpython_versionzinstance-idinstance_idZkernel_releasezlocal-hostnamelocal_hostnamemachineregionr   Zsystem_platformr   )
get_hostnamerW   get_instance_idr   canonical_cloud_idr   r   platform_typeget_public_ssh_keysr   )r(   instance_datar   r   r   Zsysinfor   r   r!   _get_standardized_metadata{  s8    





z%DataSource._get_standardized_metadatac             C   sP   | j s
dS |r|}n| j}x&|D ]\}}t| |r t| || q W |sLd| _ dS )zReset any cached metadata attributes to datasource defaults.

        @param attr_defaults: Optional tuple of (attr, value) pairs to
           set instead of cached_attr_defaults.
        NF)_dirty_cachecached_attr_defaultsru   rv   )r(   Zattr_defaultsZattr_valuesZ	attributer'   r   r   r!   clear_cached_attrs  s    
zDataSource.clear_cached_attrsc             C   s"   d| _ | j }|s|S | j  |S )zDatasources implement _get_data to setup metadata and userdata_raw.

        Minimally, the datasource should return a boolean True on success.
        T)r   r   persist_instance_data)r(   Zreturn_valuer   r   r!   get_data  s    zDataSource.get_dataTc             C   st  |r&t jj| jjr&t| | jjd t| drbtj	t
| d}|jdd |jdd d|i}n^dd| jii}t| drt
| d}|tkr||d d< t| d	rt
| d	}|tkr||d d	< t|d d
< tj	| j|d< d|d d
< tj	|d |d< d|d d
< tj |d< |j| j| y"tj|}ttj|| jd}W nb tk
rv } ztjdt| dS d}~X n2 tk
r } ztjdt| dS d}~X nX | jjd}	|d j dd}
t jj!| jj"d}tj#| d|
 |
 d d}| d|
 }t jj$|rt jj%|}tj&||dd |rH||krHtj'| t(|	|dd | jjd}t(|t)| dS )aP  Process and write INSTANCE_JSON_FILE with all instance metadata.

        Replace any hyphens with underscores in key names for use in template
        processing.

        :param write_cache: boolean set True to persist obj.pkl when
            instance_link exists.

        @return True on successful write, False otherwise.
        Zobj_pklZ_crawled_metadataz	user-dataNzvendor-datar%   Z	meta_datar\   r[   Z_docrd   z<DEPRECATED: Use merged_system_cfg. Will be dropped from 24.1re   zUMerged cloud-init system config from /etc/cloud/cloud.cfg and /etc/cloud/cloud.cfg.d/r   )r9   z'Error persisting instance-data.json: %sFZinstance_data_sensitiver   r   Znonezcloud-id-
T)forcei  )moder   )*osrR   lexistsrk   Zinstance_link	pkl_storeZget_ipath_curru   r:   r;   getattrrE   rG   UNSETEXPERIMENTAL_TEXTrl   r   Zsystem_infoupdater   r
   Z
json_dumpsrC   jsonloadssensitive_metadata_keys	TypeErrorrx   warningr2   UnicodeDecodeErrorZget_runpathrN   joinZrun_dir
write_fileexistsrealpathZsym_linkZdel_filer   rS   )r(   Zwrite_cacheZcrawled_metadatar   r\   r[   ZcontentZprocessed_datarz   Zjson_sensitive_filer   Zcloud_id_fileZprev_cloud_id_fileZnew_cloud_id_fileZ	json_filer   r   r!   r     sf    







z DataSource.persist_instance_datac             C   s   t ddS )z@Walk metadata sources, process crawled data and save attributes.zlSubclasses of DataSource must implement _get_data which sets self.metadata, vendordata_raw and userdata_raw.N)NotImplementedError)r(   r   r   r!   r     s    zDataSource._get_datac          %   C   sL  | j }yt| jjd| j }W n, tk
rJ   tjtd| jjd| Y nX | j}yt	dt| jjd| j}W n2 tk
r   | j}tjtd| jjd| Y nX | j
}yt| jjd| j
}W n, tk
r   tjtd| jjd| Y nX | j}yt| jjd| j}W n. tk
r<   tjtd	| jjd| Y nX t||||S )
zReturn the Datasource's preferred url_read parameters.

        Subclasses may override url_max_wait, url_timeout, url_retries.

        @return: A URLParams object with max_wait_seconds, timeout_seconds,
            num_retries.
        max_waitz6Config max_wait '%s' is not an int, using default '%s'r   timeoutz5Config timeout '%s' is not an int, using default '%s'retriesz5Config retries '%s' is not an int, using default '%s'rU   zAConfig sec_between_retries '%s' is not an int, using default '%s')url_max_waitintrn   rN   
ValueErrorr   logexcrx   url_timeoutmaxurl_retries	Exceptionurl_sec_between_retriesrT   )r(   r   r   r   rU   r   r   r!   get_url_params  sP    



zDataSource.get_url_paramsc             C   s2   | j d kr| jj| j | _ |r,| j| j S | j S )N)r]   rp   processget_userdata_raw_filter_xdata)r(   Zapply_filterr   r   r!   get_userdataU  s
    
zDataSource.get_userdatac             C   s"   | j d kr| jj| j | _ | j S )N)r_   rp   r   get_vendordata_raw)r(   r   r   r!   get_vendordata\  s    
zDataSource.get_vendordatac             C   s"   | j d kr| jj| j | _ | j S )N)ra   rp   r   get_vendordata2_raw)r(   r   r   r!   get_vendordata2a  s    
zDataSource.get_vendordata2c             C   s2   | j dkr,tj | _ | j dkr,tjd| j | j S )zADetermine the network interface used during local network config.Nz(Did not find a fallback interface on %s.)_fallback_interfacer   Zfind_fallback_nicrx   r   r   )r(   r   r   r!   fallback_interfacef  s    



zDataSource.fallback_interfacec             C   s.   t | ds| jj | _| js(| jj | _| jS )N_platform_type)ru   rm   r=   r   )r(   r   r   r!   r   q  s
    
zDataSource.platform_typec             C   s*   t | ds| j | _| js$| j | _| jS )a  Return a string representing subplatform details for the datasource.

        This should be guidance for where the metadata is sourced.
        Examples of this on different clouds:
            ec2:       metadata (http://169.254.169.254)
            openstack: configdrive (/dev/path)
            openstack: metadata (http://169.254.169.254)
            nocloud:   seed-dir (/seed/dir/path)
            lxd:   nocloud (/seed/dir/path)
        _subplatform)ru   _get_subplatformr   )r(   r   r   r!   r   z  s
    


zDataSource.subplatformc             C   s   t | drdt| d S tS )z?Subclasses should implement to return a "slug (detail)" string.Zmetadata_addresszmetadata (%s))ru   r   METADATA_UNKNOWN)r(   r   r   r!   r     s    
zDataSource._get_subplatformc             C   sv   | j r| j S | jrb| jjtrb| jjt}t|tr@|j | _ qp| j j | _ tj	dtt
| n| j j | _ | j S )zReturn lowercase cloud name as determined by the datasource.

        Datasource can determine or define its own cloud product name in
        metadata.
        z5Ignoring metadata provided key %s: non-string type %s)_cloud_namerG   rN   METADATA_CLOUD_NAME_KEYr?   r2   r=   _get_cloud_namerx   ry   type)r(   r   r   r   r!   r     s    
zDataSource.cloud_namec             C   s   | j S )zReturn the datasource name as it frequently matches cloud name.

        Should be overridden in subclasses which can run on multiple
        cloud names, such as DatasourceEc2.
        )rm   )r(   r   r   r!   r     s    zDataSource._get_cloud_namec             C   s"   | j s
d S d| j kr| j d S d S )Nzlaunch-index)rG   )r(   r   r   r!   r     s
    

zDataSource.launch_indexc             C   s4   t jtj| j g}|}x|D ]}|j|}qW |S )N)r   Filterr   Zsafe_intZapply)r(   Zprocessed_udfiltersZnew_udfr   r   r!   r     s
    
zDataSource._filter_xdatac             C   s   dS )NFr   )r(   r   r   r!   is_disconnected  s    zDataSource.is_disconnectedc             C   s   | j S )N)r^   )r(   r   r   r!   r     s    zDataSource.get_userdata_rawc             C   s   | j S )N)r`   )r(   r   r   r!   r     s    zDataSource.get_vendordata_rawc             C   s   | j S )N)rb   )r(   r   r   r!   r     s    zDataSource.get_vendordata2_rawc             C   s   i S )Nr   )r(   r   r   r!   get_config_obj  s    zDataSource.get_config_objc             C   s   t | jjdS )Nzpublic-keys)normalize_pubkey_datarG   rN   )r(   r   r   r!   r     s    zDataSource.get_public_ssh_keysc             C   s   dS )a5  Publish the public SSH host keys (found in /etc/ssh/*.pub).

        @param hostkeys: List of host key tuples (key_type, key_value),
            where key_type is the first field in the public key file
            (e.g. 'ssh-rsa') and key_value is the key itself
            (e.g. 'AAAAB3NzaC1y...').
        Nr   )r(   Zhostkeysr   r   r!   publish_host_keys  s    zDataSource.publish_host_keysc             C   sd   ddi}xV|j  D ]J\}}|j|s&qx4|D ],}d||t|d  f }tjj|r,|S q,W qW d S )NZsdvdxvdvtbz	/dev/%s%s)r   r   r   )r<   r@   lenr   rR   r   )r(   Z
short_nameZmappingsZnfromZtlistZntoZcandr   r   r!   _remap_device  s    

zDataSource._remap_devicec             C   s   d S )Nr   )r(   _namer   r   r!   device_name_to_device  s    z DataSource.device_name_to_devicec             C   s.   | j }y| jj }W n tk
r(   Y nX |S )z<Default locale is en_US.UTF-8, but allow distros to override)default_localerj   
get_localer   )r(   Zlocaler   r   r!   r     s    zDataSource.get_localec             C   s2   | j jd| j jd}|r|S | j jdi jdS )Nzavailability-zoner   Z	placement)rG   rN   )r(   Ztop_level_azr   r   r!   r     s
    zDataSource.availability_zonec             C   s   | j jdS )Nr   )rG   rN   )r(   r   r   r!   r     s    zDataSource.regionc             C   s$   | j  sd| j krdS t| j d S )Nzinstance-idziid-datasource)rG   r2   )r(   r   r   r!   r     s    zDataSource.get_instance_idc             C   sd  d}d}|}d}| j  s&| j jd r|r4td|S g }tj }	|	dkrLd}tj|	}
|
rx|
jddkrxt|
jd}n8|	r|	jddkrt|	jd}n|	r|	|g}n||g}nZ| j d }t	j
|rg }|rtj|}|rt|jd}nd	|jdd
 g}n
|jd}t|dkr6|d }	dj|dd }n|d }	|rZ||krZd|	|f }	t|	|S )a  Get hostname or fqdn from the datasource. Look it up if desired.

        @param fqdn: Boolean, set True to return hostname with domain.
        @param resolve_ip: Boolean, set True to attempt to resolve an ipv4
            address provided in local-hostname meta-data.
        @param metadata_only: Boolean, set True to avoid looking up hostname
            if meta-data doesn't have local-hostname present.

        @return: a DataSourceHostname namedtuple
            <hostname or qualified hostname>, <is_default> (str, bool).
            is_default is a bool and
            it's true only if hostname is localhost and was
            returned by util.get_hostname() as a default.
            This is used to differentiate with a user-defined
            localhost hostname.
            Optionally return (None, False) when
            metadata_only is True and local-hostname data is not available.
        ZlocaldomainZ	localhostFzlocal-hostnameNT.r   zip-%sr   rL   z%s.%s)rG   rN   rV   r   r   Zget_fqdn_from_hostsfindr2   rO   r   Zis_ipv4_addressZgethostbyaddrrA   r   r   )r(   ZfqdnZ
resolve_ipZmetadata_onlyZ	defdomainZdefhostZdomainrX   ZtoksrW   Z
hosts_fqdnZlhostr   r   r!   r     sF    






zDataSource.get_hostnamec             C   s   | j j| dS )N)Zdata_source)rj   get_package_mirror_info)r(   r   r   r!   r   _  s    z"DataSource.get_package_mirror_info)source_event_typesc             C   sX   i }xN|D ]F}x@| j j D ]2\}}||kr|j|s>t ||< || j| qW q
W |S )N)supported_update_eventsr<   rN   setadd)r(   r   supported_eventseventZupdate_scopeZupdate_eventsr   r   r!   get_supported_eventsb  s    


zDataSource.get_supported_events)r   r&   c             C   s   | j |}xH|j D ]<\}}tjd|jdjdd |D  | jd| tff qW |rp| j  | j }|rpdS tjd| djdd |D  d	S )
a  Refresh cached metadata if the datasource supports this event.

        The datasource has a list of supported_update_events which
        trigger refreshing all cached metadata as well as refreshing the
        network configuration.

        @param source_event_types: List of EventTypes which may trigger a
            metadata update.

        @return True if the datasource did successfully update cached metadata
            due to source_event_type.
        z:Update datasource metadata and %s config due to events: %sz, c             S   s   g | ]
}|j qS r   )r'   ).0r   r   r   r!   
<listcomp>  s    z;DataSource.update_metadata_if_supported.<locals>.<listcomp>z
_%s_configTz(Datasource %s not updated for events: %sc             S   s   g | ]
}|j qS r   )r'   )r   r   r   r   r!   r     s    F)	r   r<   rx   ry   r'   r   r   r   r   )r(   r   r   ZscopeZmatched_eventsresultr   r   r!   update_metadata_if_supportedo  s"    
z'DataSource.update_metadata_if_supportedc             C   s   dS )NFr   )r(   rl   r   r   r!   check_instance_id  s    zDataSource.check_instance_idc             C   s   dS )a  check_if_fallback_is_allowed()
        Checks if a cached ds is allowed to be restored when no valid ds is
        found in local mode by checking instance-id and searching valid data
        through ds list.

        @return True if a ds allows fallback, False otherwise.
        Fr   )r(   r   r   r!   rt     s    z'DataSource.check_if_fallback_is_allowedc             C   sR   |d krt }|d krt}x4| D ],}|d kr,q||kr8|S tjd|| |S qW |S )Nz%invalid dsmode '%s', using default=%s)DSMODE_NETWORKVALID_DSMODESrx   r   )Z
candidatesdefaultZvalid	candidater   r   r!   _determine_dsmode  s    

zDataSource._determine_dsmodec             C   s   d S )Nr   )r(   r   r   r!   network_config  s    zDataSource.network_configc             C   s   dS )a(  setup(is_new_instance)

        This is called before user-data and vendor-data have been processed.

        Unless the datasource has set mode to 'local', then networking
        per 'fallback' or per 'network_config' will have been written and
        brought up the OS at this point.
        Nr   )r(   is_new_instancer   r   r!   setup  s    	zDataSource.setupc             C   s   dS )a  activate(cfg, is_new_instance)

        This is called before the init_modules will be called but after
        the user-data and vendor-data have been fully processed.

        The cfg is fully up to date config, it contains a merged view of
           system config, datasource config, user config, vendor config.
        It should be used rather than the sys_cfg passed to __init__.

        is_new_instance is a boolean indicating if this is a new instance.
        Nr   )r(   Zcfgr   r   r   r!   activate  s    zDataSource.activaterM   )r]   N)r^   N)r_   N)r`   N)ra   N)rb   N)
rc   rd   re   rf   r]   rg   r   r_   rh   ri   )N)T)F)FFF)NN)\r*   r+   r,   r   Zdsmoder   rm   r   r   r   r   r#   r.   r1   r0   r/   Znetwork_config_sourcesr	   r   r   r   r   r   r   r   BOOT_NEW_INSTANCEZBOOTZBOOT_LEGACYZHOTPLUGr   Zdefault_update_eventsr   r   r2   r   r   r   rs   Z_ci_pkl_versionr   r   rq   r   r{   r)   boolr}   r   r   r   r   r   r   r   r   r   r   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rt   staticmethodr   r   r   r   r   r   r   r!   r      s   


         &
R<
					
H$
)	metaclassc             C   s   g }| s|S t | tr| j S t | ttfr4t| S t | trxN| j D ]B\}}t |tr`|g}t |ttfrHx|D ]}|rt|j| qtW qHW |S )N)r?   r2   
splitlineslistr   rB   r<   r>   )Zpubkey_datakeysZ_keynameZklistZpkeyr   r   r!   r     s     



r   )r&   c             C   s  t |||}dd |D }t|kr&dnd}	tjd|	| xt||D ]\}
}tjd|
jdd d	|	|
f d
|	|
f |d}yV|H tjd| || ||}|jt	j
grd|	|
f |_|tj|fS W d Q R X W qD tk
r   tjtd| Y qDX qDW ddj| }t|d S )Nc             S   s   g | ]}t j|qS r   )r   r|   )r   r   r   r   r!   r     s    zfind_source.<locals>.<listcomp>Znetworkr   z#Searching for %s data source in: %sz	search-%sr   r6   zsearching for %s data from %szno %s data found from %s)namedescriptionmessageparentz%Seeing if we can get any data from %szfound %s data from %szGetting data from %s failedz4Did not find any data source, searched classes: (%s)z, )list_sourcesDEP_NETWORKrx   ry   zipr   ZReportEventStackrA   r   r   r   r  r   r|   r   r   r   r   r4   )rl   rj   rk   Zds_depscfg_listpkg_listZreporterds_listZds_namesr   r  clsZmyrepsmsgr   r   r!   find_source  s.    


r  c             C   s   g }t jd| || xt| D ]l}tj|}tj||dg\}}|sLt jd| x8|D ]0}tj|}	t|	d}
|
|}|rR|j| P qRW qW |S )zReturn a list of classes that have the same depends as 'depends'
    iterate through cfg_list, loading "DataSource*" modules
    and calling their "get_datasource_list".
    Return an ordered list of classes that match (if any)
    zLLooking for data source in: %s, via packages %s that matches dependencies %sZget_datasource_listzDCould not import %s. Does the DataSource exist and is it importable?)	rx   ry   r   Z"match_case_insensitive_module_namefind_moduleerrorimport_moduler   rD   )r
  dependsr  Zsrc_listr%   Zds_nameZm_locsZ_looked_locsZm_locmodZlisterZmatchesr   r   r!   r    s,    






r  system-uuid)fieldr&   c             C   s*   | sdS t j|}|sdS | j |j kS )NF)r   Zread_dmi_datar=   )r   r  Z	dmi_valuer   r   r!   instance_id_matches_system_uuid9  s    
r  c             C   sl   | st } |st }|t kr(| t kr$| S |S x2tj D ]&\}}|\}}|j|r2|| r2|S q2W | t krh| S |S )z@Lookup the canonical cloud-id for a given cloud_name and region.)r   CLOUD_ID_REGION_PREFIX_MAPr<   r@   )r   r   r   prefixZcloud_id_testr   Zvalid_cloudr   r   r!   r   G  s    r   Tc             C   sj   | sdS t | tr| S t | tr*tj| S t | trV|dkrNt| jdddS tdtdt	|  dS )aL  data: a loaded object (strings, arrays, dicts).
    return something suitable for cloudinit vendordata_raw.

    if data is:
       None: return None
       string: return string
       list: return data
             the list is then processed in UserDataProcessor
       dict: return convert_vendordata(data.get('cloud-init'))
    NTz
cloud-initF)recursez'vendordata['cloud-init'] cannot be dictz$Unknown data type for vendordata: %s)
r?   r2   r  r:   r;   rB   convert_vendordatarN   r   r   )datar  r   r   r!   r  Z  s    



r  c               @   s   e Zd ZdS )BrokenMetadataN)r*   r+   r,   r   r   r   r!   r  r  s   r  c             C   s8   g }t | }x&|D ]\}}|t |kr|j| qW |S )N)r   r>   )r  r  Zret_listZdepsetr  Zdepsr   r   r!   list_from_depends}  s    r  )rQ   fnamer&   c             C   sp   yt j| }W n" tk
r0   tjtd|  dS X ytj||ddd W n" tk
rj   tjtd| dS X dS )z[Use pickle to serialize Datasource to a file as a cache.

    :return: True on success
    zFailed pickling datasource %sFwb   )Zomoder   z Failed pickling datasource to %sT)pickledumpsr   r   r   rx   r   )rQ   r   Zpk_contentsr   r   r!   r     s    r   )r   r&   c             C   s   d}yt j| dd}W n< tk
rR } z tjj| rBtjd| | W Y dd}~X nX |s\dS y
tj	|S  t
k
rz   dS  tk
r   t jtd|  dS X dS )zBUse pickle to deserialize a instance Datasource from a cache file.NF)decodezfailed loading pickle in %s: %sz#Failed loading pickled blob from %s)r   Z	load_filer   r   rR   isfilerx   r   r#  r   r3   r   )r   Zpickle_contentsrz   r   r   r!   pkl_load  s     
r'  c              C   s   t j } tjd| }tjd| }tjd| }|p6|p6|}|p>|}|rv|jdj }t jd| d| dd| d	d
 |r|jdr|jdS dS )zCheck if command line argument for this datasource was passed
    Passing by command line overrides runtime datasource detection
    zds=([^\s;]+)zci\.ds=([^\s;]+)zci\.datasource=([^\s;]+)rL   z7Defining the datasource on the commandline using ci.ds=z or ci.datasource=z23.2zUse ds=z instead)
deprecatedZdeprecated_versionZextra_messager6   )r   Zget_cmdlineresearchgroupstripZ	deprecate)r$   Z
ds_parse_0Z
ds_parse_1Z
ds_parse_2r%   r(  rm   r   r   r!   r~     s    
r~   )r  )T)Tabcr:   r   Zloggingr   r#  r)  collectionsr   enumr   r   Ztypingr   r   r   r   r	   Z	cloudinitr
   r   r   r   r   r   ro   r   Zcloudinit.atomic_helperr   Zcloudinit.distrosr   Zcloudinit.eventr   r   Zcloudinit.filtersr   Zcloudinit.helpersr   Zcloudinit.persistencer   Zcloudinit.reportingr   ZDSMODE_DISABLEDZDSMODE_LOCALr   ZDSMODE_PASSr   ZDEP_FILESYSTEMr  Z	DS_PREFIXr   ZREDACT_SENSITIVE_VALUEr   r   r   Z	getLoggerr*   rx   r  r#   r   r3   r4   r5   rC   rS   rT   rV   ABCMetar   r   r2   r  r  r   r  r   r  IOErrorr  r  r   r'  r~   r   r   r   r!   <module>   s   



#
      +%
	