o
    x[hó°  ã                   @   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 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Z0dZ1dZ2dZ3dZ4dZ5dZ6dZ7dZ8e 9e:¡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?ƒZAG d*d+„ d+e?ƒZBdYd.d/„ZCe5fd0d1„ZDG d2d3„ d3eƒZEG d4d5„ d5eƒZFG d6d7„ d7eƒZGG d8d„ de)e jHd9�ZId:d;„ ZJd<eeIeKf fd=d>„ZLd?d@„ ZM	AdZdBeKd<eNfdCdD„ZOdEdF„ ZPd[dHdI„ZQG dJdK„ dKeRƒZSdLdM„ ZTdNeIdOeKd<eNfdPdQ„ZUdOeKd<eeI fdRdS„ZVd<eKfdTdU„ZWdVeKd<eKfdWdX„ZXdS )\é    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 )zÀProcess 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 )z�Redact 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,„ Z8d~d.d/„Z9e:j;d0d1d2�d e4fd3d4„ƒZ<dd6d7„Z=d e4fd8d9„Z>d:d;„ Z?d€d<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„ ZVd�dhdi„ZWdjdk„ ZXdleYe fdmdn„ZZdleYe d e4fdodp„Z[dqdr„ Z\dsdt„ Z]e^d‚dudv„ƒZ_eCdwdx„ ƒZ`dydz„ Zad{d|„ Zbd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_cfgÚudÚ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 )z½Reset 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 )z˜Datasources 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 )
zîReturn 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+   r2  »  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 )z¡Return 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   )zºReturn 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+   r6  Ù  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+   r0  ø  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  s   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r§d|	|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   rG  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   rO  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.activater8   )r(   ©T)F)FFF)NN)cr?   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.  r1  Úpropertyrã   rÈ   r2  rÌ   r6  r   r)  r(  r-  r0  r?  rä   rB  rN  rQ  rS  rÊ   rÞ   rá   rà   ri  r   rr  r|  r}  r°   Ústaticmethodr„  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 )zèReturn 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¢  ?  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_uuidc  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.)r4  ÚCLOUD_ID_REGION_PREFIX_MAPr]   ra   )rÌ   rÞ   rÑ   ÚprefixÚcloud_id_testrË   Úvalid_cloudr(   r(   r+   râ   q  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  r7  )Ú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 )z…Check 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Š  )YÚabcr[   r  Úloggingrû   rÕ  râ  Úenumr   r   Útypingr   r   r   r   r   r	   r
   Ú	cloudinitr   r   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_VALUEr5  r£   r4  Ú	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–   
$$	
ÿ



ý

#      @

þ!%ÿÿ
þ
	