U
    Ad+                     @   s  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 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 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Z/dZ0dZ1dZ2dZ3dZ4dZ5e6e7Z8ddd fd d!d fd"d#d fd$Z9e	G d%d& d&eZ:G d'd( d(e;Z<G d)d* d*e;Z=G d+d, d,e;Z>dWd/d0Z?e2fd1d2Z@ed3d4d5d6d7gZAed8d9d:gZBG d;d de&e jCd<ZDd=d> ZEeeDeFf d?d@dAZGdBdC ZHdXeFeIdEdFdGZJdHdI ZKdYdKdLZLG dMdN dNeMZNdOdP ZOeDeFeIdQdRdSZPeFeeD dTdUdVZQdS )Z    N)
namedtuple)Enumunique)AnyDictListOptionalTuple)dmiimporter)log)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 user
cloud-nameZ_unsetunknownz	aws-chinac                 C   s   | dkS NZaws cr    r    </usr/lib/python3/dist-packages/cloudinit/sources/__init__.py<lambda>?       r$   zaws-govc                 C   s   | dkS r   r    r!   r    r    r#   r$   @   r%   zazure-chinac                 C   s   | dkS )NZazurer    r!   r    r    r#   r$   A   r%   )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.
    Z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r0   r1   r2   r3   r    r    r    r#   r9   V   s   r9   c                   @   s   e Zd ZdS )DataSourceNotFoundExceptionNr0   r1   r2   r    r    r    r#   r;   Z   s   r;   c                   @   s   e Zd ZdZdS )InvalidMetaDataExceptionz8Raised when metadata is broken, unavailable or disabled.Nr:   r    r    r    r#   r=   ^   s   r=    r    c           
      C   s   t | }g }g }|  D ]\}}|r4|d | }n|}| |ksP| |krZ|| t|tr|dr|| |dd||< t|t	rt
|||}	||	d ||	d |	||< q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:r>   base64_encoded_keyssensitive_keys)copydeepcopyitemslowerappend
isinstancer8   
startswithreplacedictprocess_instance_metadataextendpopsorted)
metadatakey_pathrA   md_copyr@   Z	sens_keyskeyvalZsub_key_pathZ
return_valr    r    r#   rK   b   s6    





  
rK   c                 C   s   |  dg s| S t| }|  dD ]V}|d}|}|D ].}||kr:t|| tr:||d kr:|| }q:||kr$|||< q$|S )zRedact any sensitive keys from to provided metadata dictionary.

    Replace any keys values listed in 'sensitive_keys' with redact_value.
    rA   r?   )getrB   rC   splitrG   rJ   )rO   Zredact_valuerQ   rP   
path_partsobjpathr    r    r#   redact_sensitive_keys   s"    




rZ   	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 ed< 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dddf	Z!eee"e#f df ed< dZ$dZ%ee"df ed< dZ&d	Z'dze(e)dddZ*e+ddddZ,dd Z-e.dd d!Z/d"d# Z0d$d% Z1d&d' Z2d{d)d*Z3e.dd+d,Z4d|d.d/Z5e.dd0d1Z6d2d3 Z7d}d4d5Z8d6d7 Z9d8d9 Z:e;d:d; Z<e;d<d= Z=e;d>d? Z>d@dA Z?e;dBdC Z@dDdE ZAe;dFdG ZBdHdI ZCe;dJdK ZDdLdM ZEdNdO ZFdPdQ ZGdRdS ZHdTdU ZIdVdW ZJdXdY ZKdZd[ ZLd\d] ZMe;d^d_ ZNe;d`da ZOdbdc ZPd~dddeZQdfdg ZReSe dhdidjZTeSe e.dkdldmZUdndo ZVeWddpdqZXe;drds ZYe;dtdu ZZdvdw Z[dxdy Z\dS )r   zen_US.UTF-8Z_undefN.network_config_sourcesrT   
         ec2_metadatanetwork_jsonrO   )userdataN)userdata_rawN)
vendordataN)vendordata_rawN)vendordata2N)vendordata2_rawNcached_attr_defaultsF)
merged_cfgzsecurity-credentialsrf   	user-datar   rh   vendor-datazds/vendor_datasensitive_metadata_keys)distropathsc                 C   s~   || _ || _|| _d | _i | _d | _d | _d | _d | _d | _	t
| j d| jfi | _| js`i | _|stt| j| _n|| _d S )NZ
datasource)sys_cfgrq   rr   rf   rO   rg   rh   rj   ri   rk   r   Zget_cfg_by_pathdsnameds_cfgudZUserDataProcessorud_proc)r.   rs   rq   rr   rw   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r| jdk	rzt| j W n6 tk
r } ztd| t	 |W 5 d}~X Y nX dS )z(Perform deserialization fixes for Paths.rj   Nrk   skip_hotplug_detectFrf   z:Unable to unpickle datasource: %s. Ignoring current cache.)
hasattrrj   rk   rz   rf   r8   AttributeErrorLOGdebugr9   )r.   ry   er    r    r#   	_unpickle1  s    


zDataSource._unpicklec                 C   s
   t | S r*   r   obj_namer-   r    r    r#   r/   I  s    zDataSource.__str__r(   c                 C   s   dS )z#Check if running on this datasourceTr    r-   r    r    r#   	ds_detectL  s    zDataSource.ds_detectc                 C   s    | j dg | jg| jdgfkS )zOverride if either:
        - only a single datasource defined (nothing to fall back to)
        - TODO: commandline argument is used (ci.ds=OpenStack)
        Zdatasource_listNone)rs   rU   rt   r-   r    r    r#   override_ds_detectP  s    zDataSource.override_ds_detectc                 C   sD   |   rtd|  n&|  r,td|  ntd|  dS |  S )z&Overrides runtime datasource detectionz5Machine is configured to run on single datasource %s.zMachine is running on %s.z#Datasource type %s is not detected.F)r   r}   r~   r   	_get_datar-   r    r    r#   _check_and_get_dataZ  s     zDataSource._check_and_get_datac                 C   s   |   j}|  }| j}|d }ddg||t| j| j| j| j| j|d d |d d |d d | 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   rc      pythonuname   platformvariant)Z
_beta_keysavailability-zoneavailability_zonecloud_idr   
cloud_namerq   Zdistro_versionZdistro_releaser   Zpublic_ssh_keysZpython_versioninstance-idinstance_idZkernel_releaselocal-hostnamelocal_hostnamemachineregionr   Zsystem_platformr   )
get_hostnamer^   get_instance_idr   canonical_cloud_idr   r   platform_typeget_public_ssh_keysr   )r.   instance_datar   r   r   Zsysinfor    r    r#   _get_standardized_metadatag  sB    
  




z%DataSource._get_standardized_metadatar    c                 C   sL   | j s
dS |r|}n| j}|D ]\}}t| |rt| || q|sHd| _ 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_cacherl   r{   setattr)r.   Zattr_defaultsZattr_valuesZ	attributer,   r    r    r#   clear_cached_attrs  s    
zDataSource.clear_cached_attrsc                 C   s"   d| _ |  }|s|S |   |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   sf  |r&t j| jjr&t| | jd t| drbt	t
| d}|dd |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|d< d|d d
< t |d< || | z"t|}tt|| jd}W nr tk
r` } ztdt| W Y dS d}~X Y n: tk
r } ztdt| W Y dS d}~X Y nX | jd}	|d dd}
t j | jj!d}t"| d|
 |
 d d}| d|
 }t j#|rt j$|}tj%||dd |r:||kr:t&| t'|	|dd | 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_metadatarn   Nro   r'   Z	meta_datare   rd   Z_docrm   zUMerged cloud-init system config from /etc/cloud/cloud.cfg and /etc/cloud/cloud.cfg.d/r   )rA   z'Error persisting instance-data.json: %sFZinstance_data_sensitiver   r   Znonezcloud-id-
T)Zforcei  )moder   ))osrY   lexistsrr   Zinstance_link	pkl_storeZget_ipath_curr{   rB   rC   getattrrM   rO   UNSETEXPERIMENTAL_TEXTrs   r   Zsystem_infoupdater   Z
json_dumpsrK   jsonloadsrp   	TypeErrorr}   warningr8   UnicodeDecodeErrorZget_runpathrU   joinZrun_dir
write_fileexistsrealpathZsym_linkZdel_filer   rZ   )r.   Zwrite_cacheZcrawled_metadatar   re   rd   ZcontentZprocessed_datar   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)NotImplementedErrorr-   r    r    r#   r     s    zDataSource._get_datac              
   C   sL  | j }zt| jd| j }W n, tk
rJ   ttd| jd| Y nX | j}zt	dt| jd| j}W n2 tk
r   | j}ttd| jd| Y nX | j
}zt| jd| j
}W n, tk
r   ttd| jd| Y nX | j}zt| jd| j}W n. tk
r<   ttd	| 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'r\   zAConfig sec_between_retries '%s' is not an int, using default '%s')url_max_waitintru   rU   
ValueErrorr   logexcr}   url_timeoutmaxurl_retries	Exceptionurl_sec_between_retriesr[   )r.   r   r   r   r\   r    r    r#   get_url_params  s^    





 

zDataSource.get_url_paramsc                 C   s2   | j d kr| j|  | _ |r,| | j S | j S r*   )rf   rw   processget_userdata_raw_filter_xdata)r.   Zapply_filterr    r    r#   get_userdata:  s
    
zDataSource.get_userdatac                 C   s"   | j d kr| j|  | _ | j S r*   )rh   rw   r   get_vendordata_rawr-   r    r    r#   get_vendordataA  s    
zDataSource.get_vendordatac                 C   s"   | j d kr| j|  | _ | j S r*   )rj   rw   r   get_vendordata2_rawr-   r    r    r#   get_vendordata2F  s    
zDataSource.get_vendordata2c                 C   s2   | j dkr,t | _ | j dkr,t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_nicr}   r   r   r-   r    r    r#   fallback_interfaceK  s    


 zDataSource.fallback_interfacec                 C   s.   t | ds| j | _| js(| j | _| jS )N_platform_type)r{   rt   rE   r   r-   r    r    r#   r   V  s
    
zDataSource.platform_typec                 C   s*   t | ds|  | _| js$|  | _| 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)r{   _get_subplatformr   r-   r    r    r#   r   _  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))r{   r   METADATA_UNKNOWNr-   r    r    r#   r   r  s    
zDataSource._get_subplatformc                 C   sv   | j r| j S | jrb| jtrb| jt}t|tr@| | _ qp|   | _ t	dtt
| n|   | _ | 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_namerO   rU   METADATA_CLOUD_NAME_KEYrG   r8   rE   _get_cloud_namer}   r~   type)r.   r   r    r    r#   r   x  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.
        )rt   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)rO   r-   r    r    r#   r     s
    

zDataSource.launch_indexc                 C   s0   t t| j g}|}|D ]}||}q|S r*   )r   Z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 r*   )rg   r-   r    r    r#   r     s    zDataSource.get_userdata_rawc                 C   s   | j S r*   )ri   r-   r    r    r#   r     s    zDataSource.get_vendordata_rawc                 C   s   | j S r*   )rk   r-   r    r    r#   r     s    zDataSource.get_vendordata2_rawc                 C   s   i S r*   r    r-   r    r    r#   get_config_obj  s    zDataSource.get_config_objc                 C   s   t | jdS )Nzpublic-keys)normalize_pubkey_datarO   rU   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}|  D ]N\}}||s$q|D ]4}d||t|d  f }tj|r(|    S q(qd S )NZsd)ZvdZxvdZvtbz	/dev/%s%s)rD   rH   lenr   rY   r   )r.   Z
short_nameZmappingsZnfromZtlistZntoZcandr    r    r#   _remap_device  s    
zDataSource._remap_devicec                 C   s   d S r*   r    )r.   _namer    r    r#   device_name_to_device  s    z DataSource.device_name_to_devicec                 C   s.   | j }z| j }W n tk
r(   Y nX |S )z<Default locale is en_US.UTF-8, but allow distros to override)default_localerq   
get_localer   )r.   Zlocaler    r    r#   r     s    zDataSource.get_localec                 C   s2   | j d| j d}|r|S | j di dS )Nr   r   Z	placementrO   rU   )r.   Ztop_level_azr    r    r#   r     s     
zDataSource.availability_zonec                 C   s   | j dS )Nr   r   r-   r    r    r#   r     s    zDataSource.regionc                 C   s"   | j rd| j krdS t| j d S )Nr   ziid-datasource)rO   r8   r-   r    r    r#   r     s    zDataSource.get_instance_idc                 C   s^  d}d}|}d}| j r"| j ds|r0td|S g }t }	|	dkrHd}t|	}
|
rt|
ddkrtt|
d}n8|	r|	ddkrt|	d}n|	r|	|g}n||g}nX| j d }t	
|rg }|rt|}|rt|d}nd	|dd
 g}n
|d}t|dkr0|d }	d|dd }n|d }	|rT||krTd|	|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	localhostFr   NT.r   zip-%sr   rc   z%s.%s)rO   rU   r]   r   r   Zget_fqdn_from_hostsfindr8   rV   r   Zis_ipv4_addressZgethostbyaddrrI   r   r   )r.   ZfqdnZ
resolve_ipZmetadata_onlyZ	defdomainZdefhostZdomainr_   Ztoksr^   Z
hosts_fqdnZlhostr    r    r#   r     sF    







zDataSource.get_hostnamec                 C   s   | j j| dS )N)Zdata_source)rq   get_package_mirror_infor-   r    r    r#   r   D  s    z"DataSource.get_package_mirror_info)source_event_typesc                 C   sP   i }|D ]B}| j  D ]2\}}||kr||s:t ||< || | qq|S r*   )supported_update_eventsrD   rU   setadd)r.   r   supported_eventseventZupdate_scopeZupdate_eventsr    r    r#   get_supported_eventsG  s    

zDataSource.get_supported_events)r   r)   c              	   C   s   |  |}| D ]<\}}td|jddd |D  | d| tff q|rl|   |  }|rldS td| d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: %s, c                 S   s   g | ]
}|j qS r    r+   .0r   r    r    r#   
<listcomp>h  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   v  s     F)	r   rD   r}   r~   r,   r   r   r   r   )r.   r   r   ZscopeZmatched_eventsresultr    r    r#   update_metadata_if_supportedT  s&    
z'DataSource.update_metadata_if_supportedc                 C   s   dS r   r    )r.   rs   r    r    r#   check_instance_idz  s    zDataSource.check_instance_idc                 C   sV   |d krt }|d krt}| D ]4}|d kr*q||kr:|  S td|| |  S q|S )Nz%invalid dsmode '%s', using default=%s)DSMODE_NETWORKVALID_DSMODESr}   r   )Z
candidatesdefaultZvalid	candidater    r    r#   _determine_dsmode~  s       
zDataSource._determine_dsmodec                 C   s   d S r*   r    r-   r    r    r#   network_config  s    zDataSource.network_configc                 C   s   d S r*   r    r-   r    r    r#   first_instance_boot  s    zDataSource.first_instance_bootc                 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.activate)N)r    )T)F)FFF)NN)]r0   r1   r2   r   Zdsmoder   rt   r   r   r   r   r&   r4   r7   r6   r5   r`   r	   __annotations__r   r   r   r   r   r   r   BOOT_NEW_INSTANCEZBOOTZBOOT_LEGACYZHOTPLUGr   Zdefault_update_eventsr   rl   r8   r   r   rp   rz   Z_ci_pkl_versionr   r   rx   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   staticmethodr   r   r   r  r  r    r    r    r#   r      s   
	

&

K<






	
		


H&

)	metaclassc                 C   s   g }| s|S t | tr|  S t | ttfr4t| S t | tr|  D ]>\}}t |tr^|g}t |ttfrF|D ]}|rp|| qpqF|S r*   )rG   r8   
splitlineslistr   rJ   rD   rF   )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d|	| t||D ]\}
}tjd|
dd d	|	|
f d
|	|
f |d}zh|Z td| || ||}|t	j
grd|	|
f |_|t|fW  5 Q R  W   S W 5 Q R X W qB tk
r   ttd| Y qBX qBdd| }t|d S )Nc                 S   s   g | ]}t |qS 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   r>   zsearching for %s data from %szno %s data found from %s)nameZ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)r   )list_sourcesDEP_NETWORKr}   r~   zipr   ZReportEventStackrI   r   r   r  r  r   r   r   r   r   r   r;   )rs   rq   rr   Zds_depscfg_listpkg_listZreporterds_listZds_namesr   r  clsZmyrepsmsgr    r    r#   find_source  s4    

.r  c                 C   s   g }t d| || | D ]v}|ts2dt|f }t||dg\}}|sVt d| |D ]2}t|}t|d}	|	|}
|
rZ|	|
  qqZq|S )NzLLooking for data source in: %s, via packages %s that matches dependencies %sz%s%sZget_datasource_listzDCould not import %s. Does the DataSource exist and is it importable?)
r}   r~   rH   	DS_PREFIXr   find_moduleerrorimport_moduler   rL   )r  dependsr  Zsrc_listZds_nameZm_locsZ_looked_locsZm_locmodZlisterZmatchesr    r    r#   r    s8    
  


r  system-uuid)fieldr)   c                 C   s*   | sdS t |}|sdS |  | kS r   )r
   Zread_dmi_datarE   )r   r   Z	dmi_valuer    r    r#   instance_id_matches_system_uuid  s    
r!  c                 C   sl   | st } |st }|t kr(| t kr$| S |S t D ]*\}}|\}}||r0|| r0|  S q0| t krh| S |S )z@Lookup the canonical cloud-id for a given cloud_name and region.)r   CLOUD_ID_REGION_PREFIX_MAPrD   rH   )r   r   r   prefixZcloud_id_testr   Zvalid_cloudr    r    r#   r   %  s    
r   Tc                 C   sj   | sdS t | tr| S t | tr*t| S t | trV|dkrNt| 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)
rG   r8   r
  rB   rC   rJ   convert_vendordatarU   r   r   )datar$  r    r    r#   r%  8  s    



r%  c                   @   s   e Zd ZdS )BrokenMetadataNr<   r    r    r    r#   r'  P  s   r'  c                 C   s4   g }t | }|D ]\}}|t |kr|| q|S r*   )r   rF   )r  r  Zret_listZdepsetr  Zdepsr    r    r#   list_from_depends[  s    r(  )rX   fnamer)   c                 C   st   zt | }W n$ tk
r2   ttd|  Y dS X ztj||ddd W n$ tk
rn   ttd| Y 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   r}   r   )rX   r)  Zpk_contentsr    r    r#   r   d  s    r   )r)  r)   c              
   C   s   d}zt j| dd}W n< tk
rR } ztj| rBtd| | W 5 d}~X Y nX |s\dS zt	|W S  t
k
r~   Y dS  tk
r   t td|  Y 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   rY   isfiler}   r   r,  r   r9   r   )r)  Zpickle_contentsr   r    r    r#   pkl_loadv  s     r0  )r>   r    )r  )T)RabcrB   r   r   r,  collectionsr   enumr   r   typingr   r   r   r   r	   Z	cloudinitr
   r   r   Zloggingr   r   r   rv   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  r  r   ZREDACT_SENSITIVE_VALUEr   r   r   Z	getLoggerr0   r}   r"  r&   r   r9   r;   r=   rK   rZ   r[   r]   ABCMetar   r   r8   r  r  r  r!  r   r%  IOErrorr'  r(  r   r0  r    r    r    r#   <module>   s   





#
      

%  
	