o
    th                     @   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m	Z	 d dl
mZmZmZmZmZmZmZ d dlmZmZmZmZ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!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Z0dZ1dZ2dZ3dZ4dZ5dZ6dZ7e8e9Z:d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@G d(d) d)e>ZAdWd,d-ZBe4fd.d/ZCG d0d1 d1eZDG d2d3 d3eZEG d4d5 d5eZFG d6d de(e jGd7ZHd8d9 ZId:eeHeJf fd;d<ZKd=d> ZL	?dXd@eJd:eMfdAdBZNdCdD ZOdYdFdGZPG dHdI dIeQZRdJdK ZSdLeHdMeJd:eMfdNdOZTdMeJd:eeH fdPdQZUd:eJfdRdSZVdTeJd:eJfdUdVZWdS )Z    N)Enumunique)AnyDictList
NamedTupleOptionalTupleUnion)	atomic_helperdmiimporter	lifecyclenetperformance
type_utils	user_datautil)
write_json)Distro)
EventScope	EventType)launch_index)Paths)CloudInitPickleMixin)eventsdisabledlocalr   pass
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-name_unsetunknownz	aws-chinac                 C      | dkS Naws cr(   r(   </usr/lib/python3/dist-packages/cloudinit/sources/__init__.py<lambda>F       r,   zaws-govc                 C   r%   r&   r(   r)   r(   r(   r+   r,   G   r-   zazure-chinac                 C   r%   )Nazurer(   r)   r(   r(   r+   r,   H   r-   )zcn-zus-gov-chinac                   @   s2   e Zd ZdZdZdZdZdZdZde	fdd	Z
d
S )NetworkConfigSourcezb
    Represents the canonical list of network config sources that cloud-init
    knows about.
    cmdlineds
system_cfgfallback	initramfsreturnc                 C      | j S Nvalueselfr(   r(   r+   __str__Y      zNetworkConfigSource.__str__N)__name__
__module____qualname____doc__CMD_LINEDS
SYSTEM_CFGFALLBACK	INITRAMFSstrr=   r(   r(   r(   r+   r0   L   s    r0   c                   @   s&   e Zd ZdZdZdZdefddZdS )NicOrderzRepresents ways to sort NICsmacnic_namer6   c                 C   r7   r8   r9   r;   r(   r(   r+   r=   c   r>   zNicOrder.__str__N)r?   r@   rA   rB   MACNIC_NAMErH   r=   r(   r(   r(   r+   rI   ]   s
    rI   c                   @      e Zd ZdZdS )DatasourceUnpickleUserDataErrorzERaised when userdata is unable to be unpickled due to python upgradesNr?   r@   rA   rB   r(   r(   r(   r+   rO   g       rO   c                   @      e Zd ZdS )DataSourceNotFoundExceptionNr?   r@   rA   r(   r(   r(   r+   rS   k       rS   c                   @   rN   )InvalidMetaDataExceptionz8Raised when metadata is broken, unavailable or disabled.NrP   r(   r(   r(   r+   rV   o   rQ   rV    r(   c           
      C   s   t | }g }g }|  D ]V\}}|r|d | }n|}| |v s(| |v r-|| t|trD|drD|| |dd||< t|t	rct
|||}	||	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:rW   base64_encoded_keyssensitive_keys)copydeepcopyitemslowerappend
isinstancerH   
startswithreplacedictprocess_instance_metadataextendpopsorted)
metadatakey_pathrZ   md_copyrY   	sens_keyskeyvalsub_key_path
return_valr(   r(   r+   rd   s   s0   



rd   c                 C   s   |  dg s| S t| }|  dD ]+}|d}|}|D ]}||v r4t|| tr4||d kr4|| }q||v r=|||< q|S )zRedact any sensitive keys from to provided metadata dictionary.

    Replace any keys values listed in 'sensitive_keys' with redact_value.
    rZ   rX   )getr[   r\   splitr`   rc   )rh   redact_valuerj   ri   
path_partsobjpathr(   r(   r+   redact_sensitive_keys   s"   

rw   c                   @   s.   e Zd ZU eed< eed< eed< eed< dS )	URLParamsmax_wait_secondstimeout_secondsnum_retriessec_between_retriesN)r?   r@   rA   int__annotations__r(   r(   r(   r+   rx      s
   
 rx   c                   @   s"   e Zd ZU ee ed< eed< dS )DataSourceHostnamehostname
is_defaultN)r?   r@   rA   r   rH   r~   boolr(   r(   r(   r+   r      s   
 r   c                   @   s*   e Zd ZU dZeed< eed< eed< dS )HotplugRetrySettingsz
in secondsforce_retrysleep_periodsleep_totalN)r?   r@   rA   rB   r   r~   r}   r(   r(   r(   r+   r      s
   
 r   c                	   @   s  e Zd ZU eZdZdZdZee	 e
d< dZdZdZeeee	f  e
d< 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)e*dddZ+dZ,ee	 e
d< dZ-dde.de/fddZ0de1d dfd!d"Z2d#d$ Z3d e4fd%d&Z5d e4fd'd(Z6d)d* Z7d+d, Z8dd.d/Z9e:j;d0d1d2d e4fd3d4Z<dd6d7Z=d e4fd8d9Z>d:d; Z?dd<d=Z@d>d? ZAd@dA ZBeCdBdC ZDeCdDdE ZEdFdG ZFeCdHdI ZGdJdK ZHeCdLdM ZIdNdO ZJdPdQ ZKdRdS ZLdTdU ZMdVdW ZNdXdY ZOdZd[ ZPd\d] ZQd^d_ ZRd`da ZSeCdbdc ZTeCddde ZUdfdg ZVddhdiZWdjdk ZXdleYe fdmdnZZdleYe d e4fdodpZ[dqdr Z\dsdt Z]e^ddudvZ_eCdwdx Z`dydz Zad{d| Zbd}d~ ZcdS )r!   zen_US.UTF-8_undefN_cloud_name_crawled_metadata.network_config_sourcesrp   
         ec2_metadatanetwork_jsonrh   )userdataN)userdata_rawN)
vendordataN)vendordata_rawN)vendordata2N)vendordata2_rawNcached_attr_defaultsF)
combined_cloud_config
merged_cfgmerged_system_cfgzsecurity-credentialsr   	user-datar   r   vendor-datazds/vendor_datasensitive_metadata_keysr   extra_hotplug_udev_rulesdistropathsc                 C   s   || _ || _|| _d | _i | _d | _d | _d | _d | _d | _	d | _
t| _t| _t| j d| jfi | _| js9i | _|sDt| j| _d S || _d S )N
datasource)sys_cfgr   r   r   rh   r   r   r   r   r   metadata_addressUNSETr   r   r   get_cfg_by_pathdsnameds_cfgr   UserDataProcessorud_proc)r<   r   r   r   r   r(   r(   r+   __init__O  s*   
zDataSource.__init__ci_pkl_versionr6   c                 C   s   dddt ddt dddtdddd}| D ]\}}t| |s%t| || qt| ds3t| ddd  t| dr\| jdur^zt| j W dS  ty[ } z
t	d	| t
 |d}~ww dS dS )
z(Perform deserialization fixes for Paths.NFr   )r   _platform_type_subplatformr   r   r   r   skip_hotplug_detectr   r   hotplug_retry_settingscheck_if_fallback_is_allowedc                   S      dS NFr(   r(   r(   r(   r+   r,   }      z&DataSource._unpickle.<locals>.<lambda>r   z:Unable to unpickle datasource: %s. Ignoring current cache.)r   r   r]   hasattrsetattrr   rH   AttributeErrorLOGdebugrO   )r<   r   expected_attrsrl   r:   er(   r(   r+   	_unpicklei  s<   


zDataSource._unpicklec                 C   s
   t | S r8   r   obj_namer;   r(   r(   r+   r=     s   
zDataSource.__str__c                 C   r   )z#Check if running on this datasourceTr(   r;   r(   r(   r+   	ds_detect     zDataSource.ds_detectc                 C   sN   | j  t  krtd|  dS | jdg | j gkr%td|  dS dS )aJ  Override if either:
        - only a single datasource defined (nothing to fall back to)
        - command line 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.
        z6Kernel command line set to use a single datasource %s.Tdatasource_listz2Datasource list set to use a single datasource %s.F)r   r^   parse_cmdliner   r   r   rq   r;   r(   r(   r+   override_ds_detect  s   	zDataSource.override_ds_detectc                 C   s<   |   r|  S |  rtd|  |  S td|  dS )z&Overrides runtime datasource detectionzDetected %szDid not detect %sF)r   	_get_datar   r   r   r;   r(   r(   r+   _check_and_get_data  s   zDataSource._check_and_get_datac                 C   s   |   j}|  }| j}|d }di ddgd|d|dt| j| j| jd| jd	| jd
|d d d|d d d|d d d| jd|  d|d d|d|d|d d d|d||d d | j| j	|d |d diS )z2Return a dictionary of standardized metadata keys.sys_infov1
_beta_keyssubplatformavailability-zoneavailability_zonecloud_idr"   
cloud_namer   distr   distro_versionr   distro_release   platformpublic_ssh_keyspython_versionpythoninstance-idinstance_idkernel_releaseunamelocal-hostnamelocal_hostname   variant)machineregionr   system_platformr   )
get_hostnamer   get_instance_idr   canonical_cloud_idr   r   platform_typeget_public_ssh_keysr   )r<   instance_datar   r   r   sysinfor(   r(   r+   _get_standardized_metadata  s`   
	

z%DataSource._get_standardized_metadatar(   c                 C   sP   | j sdS |r
|}n| j}|D ]\}}t| |rt| || q|s&d| _ dS 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_cacher   r   r   )r<   attr_defaultsattr_values	attributer:   r(   r(   r+   clear_cached_attrs  s   

zDataSource.clear_cached_attrszGetting metadataalways)log_modec                 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<   return_valuer(   r(   r+   get_data  s   zDataSource.get_dataTc              
   C   sX  |rt j| jjrt| | jd | jdur/t	| j}|
dd |
dd d|i}ndd| jii}| jtkrB| j|d d< | jtkrN| j|d d< t|d d	< t	| j|d
< d|d
 d	< t	|d
 |d< d|d d	< t |d< || | zt|}tt|| jd}W n5 ty } ztdt| W Y d}~dS d}~w ty } ztdt| W Y d}~dS d}~ww | 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.
        obj_pklNr   r   r2   	meta_datar   r   _docr   z<DEPRECATED: Use merged_system_cfg. Will be dropped from 24.1r   zUMerged cloud-init system config from /etc/cloud/cloud.cfg and /etc/cloud/cloud.cfg.d/r   )rZ   z'Error persisting instance-data.json: %sFinstance_data_sensitiver   r   nonezcloud-id-
T)forcei  )moder   )+osrv   lexistsr   instance_link	pkl_storeget_ipath_curr   r[   r\   rf   rh   r   r   r   EXPERIMENTAL_TEXTr   r   system_infoupdater   r   
json_dumpsrd   jsonloadsr   	TypeErrorr   warningrH   UnicodeDecodeErrorget_runpathrq   joinrun_dir
write_fileexistsrealpathsym_linkdel_filer   rw   )r<   write_cachecrawled_metadatar   contentprocessed_datar   json_sensitive_filer   cloud_id_fileprev_cloud_id_filenew_cloud_id_file	json_filer(   r(   r+   r     sn   







z DataSource.persist_instance_datac                 C   s   t d)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.)NotImplementedErrorr;   r(   r(   r+   r   Q  s   zDataSource._get_datac              
   C   sB  | j }zt| jd| j }W n ty$   ttd| jd| Y nw | j}zt	dt| jd| j}W n tyO   | j}ttd| jd| Y nw | j
}zt| jd| j
}W n tyt   ttd| jd| Y nw | j}zt| jd| j}W n ty   ttd	| jd| Y nw 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_waitr}   r   rq   
ValueErrorr   logexcr   url_timeoutmaxurl_retries	Exceptionurl_sec_between_retriesrx   )r<   r  r  r  r|   r(   r(   r+   get_url_paramsX  sd   

	

	zDataSource.get_url_paramsc                 C   s2   | j d u r| j|  | _ |r| | j S | j S r8   )r   r   processget_userdata_raw_filter_xdata)r<   apply_filterr(   r(   r+   get_userdata  s
   
zDataSource.get_userdatac                 C   "   | j d u r| j|  | _ | j S r8   )r   r   r&  get_vendordata_rawr;   r(   r(   r+   get_vendordata     
zDataSource.get_vendordatac                 C   r+  r8   )r   r   r&  get_vendordata2_rawr;   r(   r(   r+   get_vendordata2  r.  zDataSource.get_vendordata2c                 C   s   | j s	| j | _ | j S r8   )r   r   r^   r;   r(   r(   r+   r     s   zDataSource.platform_typec                 C   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)
        )r   _get_subplatformr;   r(   r(   r+   r     s   
zDataSource.subplatformc                 C   s   | j r
d| j  dS tS )z?Subclasses should implement to return a "slug (detail)" string.z
metadata ())r   METADATA_UNKNOWNr;   r(   r(   r+   r1    s   zDataSource._get_subplatformc                 C   s~   | j r| j S | jr5| jtr5| jt}t|tr"| | _ | j S |   | _ t	dtt
| | j S |   | _ | 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)r   rh   rq   METADATA_CLOUD_NAME_KEYr`   rH   r^   _get_cloud_namer   r   type)r<   r   r(   r(   r+   r     s    


zDataSource.cloud_namec                 C   r7   )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.
        )r   r;   r(   r(   r+   r5    s   zDataSource._get_cloud_namec                 C   s"   | j sd S d| j v r| j d S d S )Nzlaunch-index)rh   r;   r(   r(   r+   r     s
   

zDataSource.launch_indexc                 C   s0   t t| j g}|}|D ]}||}q|S r8   )r   Filterr   safe_intapply)r<   processed_udfiltersnew_udfr(   r(   r+   r(    s   zDataSource._filter_xdatac                 C   r7   r8   )r   r;   r(   r(   r+   r'    r>   zDataSource.get_userdata_rawc                 C   r7   r8   )r   r;   r(   r(   r+   r,    r>   zDataSource.get_vendordata_rawc                 C   r7   r8   )r   r;   r(   r(   r+   r/    r>   zDataSource.get_vendordata2_rawc                 C   s   i S r8   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_datarh   rq   r;   r(   r(   r+   r     s   zDataSource.get_public_ssh_keysc                 C   r   )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<   hostkeysr(   r(   r+   publish_host_keys  r   zDataSource.publish_host_keysc                 C   sd   ddi}|  D ]'\}}||sq|D ]}d||t|d  f }tj|r.|    S qqd S )Nsd)vdxvdvtbz	/dev/%s%s)r]   ra   lenr   rv   r  )r<   
short_namemappingsnfromtlistntocandr(   r(   r+   _remap_device  s   
zDataSource._remap_devicec                 C      d S r8   r(   )r<   _namer(   r(   r+   device_name_to_device     z DataSource.device_name_to_devicec                 C   s,   | j }z| j }W |S  ty   Y |S w )z<Default locale is en_US.UTF-8, but allow distros to override)default_localer   
get_localer  )r<   localer(   r(   r+   rS  %  s   zDataSource.get_localec                 C   s2   | j d| j d}|r|S | j di dS )Nr   r   	placementrh   rq   )r<   top_level_azr(   r(   r+   r   .  s   zDataSource.availability_zonec                 C   s   | j dS )Nr   rV  r;   r(   r(   r+   r   7  s   zDataSource.regionc                 C   s"   | j rd| j vr
dS t| j d S )Nr   ziid-datasource)rh   rH   r;   r(   r(   r+   r   ;  s   zDataSource.get_instance_idc                 C   sX  d}d}|}d}| j r| j dsW|rtd|S g }t }	|	dkr$d}t|	}
|
r:|
ddkr:t|
d}nI|	rK|	ddkrKt|	d}n8|	rR|	|g}n1||g}n,| j d }t	
|r~g }|rjt|}|rtt|d}nd	|dd
 g}n|d}t|dkr|d }	d|dd }n|d }	|r||krd|	|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.
        localdomain	localhostFr   NT.r   zip-%sr   r   z%s.%s)rh   rq   r   r   r   get_fqdn_from_hostsfindrH   rr   r   is_ipv4_addressgethostbyaddrrb   rF  r	  )r<   fqdn
resolve_ipmetadata_only	defdomaindefhostdomainr   toksr   
hosts_fqdnlhostr(   r(   r+   r   A  sF   








zDataSource.get_hostnamec                 C   s   | j j| dS )N)data_source)r   get_package_mirror_infor;   r(   r(   r+   ri    s   z"DataSource.get_package_mirror_infosource_event_typesc                 C   sP   i }|D ]!}| j  D ]\}}||v r$||st ||< || | qq|S r8   )supported_update_eventsr]   rq   setadd)r<   rj  supported_eventseventupdate_scopeupdate_eventsr(   r(   r+   get_supported_events  s   

zDataSource.get_supported_eventsc              	   C   s   |  |}| D ]\}}td|jddd |D  | d| tff q	|r6|   |  }|r6d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      g | ]}|j qS r(   r9   .0ro  r(   r(   r+   
<listcomp>      z;DataSource.update_metadata_if_supported.<locals>.<listcomp>z
_%s_configTz(Datasource %s not updated for events: %sc                 S   rt  r(   r9   ru  r(   r(   r+   rw    rx  F)	rr  r]   r   r   r:   r	  r   r   r   )r<   rj  rn  scopematched_eventsresultr(   r(   r+   update_metadata_if_supported  s&   
z'DataSource.update_metadata_if_supportedc                 C   r   r   r(   )r<   r   r(   r(   r+   check_instance_id  r   zDataSource.check_instance_idc                 C   r   )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+   r     s   z'DataSource.check_if_fallback_is_allowedc                 C   sT   |d u rt }|d u rt}| D ]}|d u rq||v r|  S td|| |  S |S )Nz%invalid dsmode '%s', using default=%s)DSMODE_NETWORKVALID_DSMODESr   r  )
candidatesdefaultvalid	candidater(   r(   r+   _determine_dsmode  s   zDataSource._determine_dsmodec                 C   rN  r8   r(   r;   r(   r(   r+   network_config  r   zDataSource.network_configc                 C   r   )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   r   )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<   cfgr  r(   r(   r+   activate  s   zDataSource.activatec                 C   r   )z
        Called when the user issues 'cloud-init clean -c datasource'
        command.
        Individual data sources should implement their own cleanup handler.
        Nr(   r;   r(   r(   r+   clean   rQ  zDataSource.cleanr8   )r(   T)F)FFF)NN)dr?   r@   rA   r~  dsmoderR  r   r   r   rH   r~   r   r   r   r
   r   r0   rC   rG   rE   rD   r   r	   r  r   r"  r$  r   r    r   BOOT_NEW_INSTANCEBOOTBOOT_LEGACYHOTPLUGrk  default_update_eventsr   r   r   r   r   r   r   r   r   _ci_pkl_versionr   r   r   r}   r   r=   r   r   r   r   r   r   r   timedr   r   r   r%  r*  r-  r0  propertyr   r   r1  r   r5  r   r(  r'  r,  r/  r>  r   rA  rM  rP  rS  r   r   r   r   ri  r   rr  r|  r}  r   staticmethodr  r  r  r  r  r(   r(   r(   r+   r!      s   
  
%
&
L
<



			


H
&

)	metaclassc                 C   s   g }| s|S t | tr|  S t | ttfrt| S t | trC|  D ]\}}t |tr/|g}t |ttfrB|D ]	}|rA|| q8q#|S r8   )r`   rH   
splitlineslistrl  rc   r]   r_   )pubkey_datakeys_keynameklistpkeyr(   r(   r+   r?  	  s"   



r?  r6   c              	   C   s.  t |||}dd |D }t|v rdnd}	td|	| t||D ]j\}
}tjd|
dd d	|	|
f d
|	|
f |d}z?|3 td| || ||}|t	j
grkd|	|
f |_|t|fW  d    W   S W d    n1 suw   Y  W q! ty   ttd| Y q!w dd| }t|)Nc                 S   s   g | ]}t |qS r(   r   )rv  r=  r(   r(   r+   rw  *  s    zfind_source.<locals>.<listcomp>networkr   z#Searching for %s data source in: %sz	search-%sr!   rW   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)rs  )list_sourcesDEP_NETWORKr   r   zipr   ReportEventStackrb   r|  r   r  r  r   r   r#  r   r  r	  rS   )r   r   r   ds_depscfg_listpkg_listreporterds_listds_namesr   r  clsmyrepsmsgr(   r(   r+   find_source&  s>   

r  c                 C   s   g }t d| || | D ]5}t|}t||dg\}}|s%t d| |D ]}t|}	t|	d}
|
|}|r@||  nq'q|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 %sget_datasource_listzDCould not import %s. Does the DataSource exist and is it importable?)	r   r   r   "match_case_insensitive_module_namefind_moduleerrorimport_modulegetattrre   )r  dependsr  src_listr2   ds_namem_locs_looked_locsm_locmodlistermatchesr(   r(   r+   r  G  s6   



r  system-uuidfieldc                 C   s*   | sdS t |}|sdS |  | kS r   )r   read_dmi_datar^   )r   r  	dmi_valuer(   r(   r+   instance_id_matches_system_uuidk  s   
r  c                 C   sl   | st } |st }|t kr| t kr| S |S t D ]\}}|\}}||r-|| r-|  S q| t kr4| S |S )z@Lookup the canonical cloud-id for a given cloud_name and region.)r3  CLOUD_ID_REGION_PREFIX_MAPr]   ra   )r   r   r   prefixcloud_id_testr   valid_cloudr(   r(   r+   r   y  s    r   Tc                 C   sf   | sdS t | tr| S t | trt| S t | tr+|du r't| dddS tdtdt	|  )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`   rH   r  r[   r\   rc   convert_vendordatarq   r  r6  )datar  r(   r(   r+   r    s   



r  c                   @   rR   )BrokenMetadataNrT   r(   r(   r(   r+   r    rU   r  c                 C   s4   g }t | }|D ]\}}|t |kr|| q|S r8   )rl  r_   )r  r  ret_listdepsetr  depsr(   r(   r+   list_from_depends  s   
r  ru   fnamec                 C   sn   zt | }W n ty   ttd|  Y dS w ztj||ddd W dS  ty6   ttd| Y dS w )z[Use pickle to serialize Datasource to a file as a cache.

    :return: True on success
    zFailed pickling datasource %sFwb   )omoder   z Failed pickling datasource to %sT)pickledumpsr#  r   r  r   r  )ru   r  pk_contentsr(   r(   r+   r     s   r   c              
   C   s   d}zt | }W n ty( } ztj| rtd| | W Y d}~nd}~ww |s-dS zt	|W S  t
y=   Y dS  tyM   t td|  Y dS w )zBUse pickle to deserialize a instance Datasource from a cache file.Nzfailed loading pickle in %s: %sz#Failed loading pickled blob from %s)r   load_binary_filer#  r   rv   isfiler   r  r  r  rO   r  )r  pickle_contentsr   r(   r(   r+   pkl_load  s$   r  c                   C   s   t t S )zCheck if command line argument for this datasource was passed
    Passing by command line overrides runtime datasource detection
    )parse_cmdline_or_dmir   get_cmdliner(   r(   r(   r+   r     s   r   inputc                 C   s   t d| }t d| }t d| }|p|p|}|p|}|r7|d }tjd| d| dd| d	d
 |rC|drC|dS dS )Nz(?:^|\s)ds=([^\s;]+)z(?:^|\s)ci\.ds=([^\s;]+)z (?:^|\s)ci\.datasource=([^\s;]+)r   z8Defining the datasource on the command line using ci.ds=z or ci.datasource=z23.2zUse ds=z instead)
deprecateddeprecated_versionextra_messagerW   )researchgroupstripr   	deprecate)r  
ds_parse_0
ds_parse_1
ds_parse_2r2   r  r   r(   r(   r+   r    s&   
	
r  )rW   r(   )r  r  )Xabcr[   r  loggingr   r  r  enumr   r   typingr   r   r   r   r   r	   r
   	cloudinitr   r   r   r   r   r   r   r   r   cloudinit.atomic_helperr   cloudinit.distrosr   cloudinit.eventr   r   cloudinit.filtersr   cloudinit.helpersr   cloudinit.persistencer   cloudinit.reportingr   DSMODE_DISABLEDDSMODE_LOCALr~  DSMODE_PASSr  DEP_FILESYSTEMr  	DS_PREFIXr   REDACT_SENSITIVE_VALUEr4  r   r3  	getLoggerr?   r   r  r0   rI   r#  rO   rS   rV   rd   rw   rx   r   r   ABCMetar!   r?  rH   r  r  r   r  r   r  IOErrorr  r  r   r  r   r  r(   r(   r(   r+   <module>   s   
$,






#      H

!%

	