o
    x[hLT  ã                   @   s"  d 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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mZmZmZ ddlmZ e e¡Zdd	iZd
Z dZ!dZ"e!d Z#e"d Z$ddiZ%dZ&G dd„ de
ƒZ'G dd„ dej(ƒZ)deddfdd„Z*G dd„ dej+ƒZ,G dd„ de,ƒZ-de.fdd„Z/dee. fd d!„Z0de1fd"d#„Z2d$e.de3fd%d&„Z4d$e.deee.e.f  fd'd(„Z5d$e.de.fd)d*„Z6d	e,j7e,j8e#gd+œd,e1d-e	e. dee' fd.d/„Z9e,ej:ffe-ej:ej;ffgZ<d0d1„ Z=ed2k�rd3Z>e?e @e9e$e#gd4�e2ƒ d5œ¡ƒ dS dS )6a3  Datasource for Oracle (OCI/Oracle Cloud Infrastructure)

Notes:
 * This datasource does not support OCI Classic. OCI Classic provides an EC2
   lookalike metadata service.
 * The UUID provided in DMI data is not the same as the meta-data provided
   instance-id, but has an equivalent lifespan.
 * We do need to support upgrade from an instance that cloud-init
   identified as OpenStack.
 * Bare metal instances use iSCSI root, virtual machine instances do not.
 * Both bare metal and virtual machine instances provide a chassis-asset-tag of
   OracleCloud.com.
é    N)ÚAnyÚDictÚListÚ
NamedTupleÚOptionalÚTuple)Úatomic_helperÚdmiÚnetÚsourcesÚutil)ÚNetworkConfig)ÚcmdlineÚ	ephemeralÚget_interfaces_by_macÚis_netfail_master)Úwait_for_urlÚconfigure_secondary_nicsFzOracleCloud.comz&http://169.254.169.254/opc/v{version}/z+http://[fd00:c1::a9fe:a9fe]/opc/v{version}/z{path}/ÚAuthorizationzBearer Oraclei(#  c                   @   sB   e Zd ZU eed< eeef ed< eeeef  ed< eed< dS )ÚReadOpcMetadataResponseÚversionÚinstance_dataÚ
vnics_dataÚimds_url_usedN)	Ú__name__Ú
__module__Ú__qualname__ÚintÚ__annotations__r   Ústrr   r   © r    r    úD/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceOracle.pyr   4   s
   
 r   c                   @   s   e Zd ZdZdefdd„ZdS )ÚKlibcOracleNetworkConfigSourcezÃOverride super class to lower the applicability conditions.

    If any `/run/net-*.cfg` files exist, then it is applicable. Even if
    `/run/initramfs/open-iscsi.interface` does not exist.
    Úreturnc                 C   s
   t | jƒS )zOverride is_applicable)ÚboolÚ_files©Úselfr    r    r!   Úis_applicableB   ó   
z,KlibcOracleNetworkConfigSource.is_applicableN)r   r   r   Ú__doc__r$   r(   r    r    r    r!   r"   ;   s    r"   Únetwork_configr#   c                 C   s  d| vrdS | d dvrt  d| d ¡ dS tƒ }| d dkrJdd„ | d D ƒD ]}|d	 d
krGd|v rG|d }| |¡}|s@q(t|ƒrG|d= q(dS | d dkr†|  di ¡ ¡ D ]/\}}d|v r…| di ¡ d¡}|r…| |¡}|ssqXt|ƒr…|d d= |d= ||d d< qXdS dS )aP  
    Search network config physical interfaces to see if any of them are
    a netfailover master.  If found, we prevent matching by MAC as the other
    failover devices have the same MAC but need to be ignored.

    Note: we rely on cloudinit.net changes which prevent netfailover devices
    from being present in the provided network config.  For more details about
    netfailover devices, refer to cloudinit.net module.

    :param network_config
       A v1 or v2 network config dict with the primary NIC, and possibly
       secondary nic configured.  This dict will be mutated.

    r   N)é   é   z+Ignoring unknown network config version: %sr,   c                 S   s   g | ]}d |v r|‘qS )Útyper    )Ú.0Úcr    r    r!   Ú
<listcomp>c   s    z,_ensure_netfailover_safe.<locals>.<listcomp>Úconfigr.   ÚphysicalÚmac_addressr-   Ú	ethernetsÚmatchÚ
macaddresszset-nameÚname)ÚLOGÚdebugr   Úgetr   Úitems)r+   Úmac_to_nameÚcfgÚmacÚcur_nameÚ_Úmacaddrr    r    r!   Ú_ensure_netfailover_safeG   sH   þ
€ø


€õrC   c                       sì   e Zd ZU dZdZejjejjejj	ejj
fZeejdf ed< dZdZdZ‡ fdd	„Zd
eddf‡ fdd„Zdefdd„Zedefdd„ƒZdd„ Zdefdd„Zdd„ Zdefdd„Zdefdd„Zedd„ ƒZd"defd d!„Z ‡  Z!S )#ÚDataSourceOracleÚOracleN.Únetwork_config_sourcesTé   é   c                    st   t t| ƒj|g|¢R i |¤Ž d | _t t |d| jgi ¡tg¡| _	t
ƒ | _g ddœ| _|  ¡ }|j| _|j| _d S )NÚ
datasourcer,   ©r2   r   )ÚsuperrD   Ú__init__Ú_vnics_datar   ÚmergemanydictÚget_cfg_by_pathÚdsnameÚBUILTIN_DS_CONFIGÚds_cfgr"   Ú_network_config_sourceÚ_network_configÚget_url_paramsÚmax_wait_secondsÚurl_max_waitÚtimeout_secondsÚurl_timeout)r'   Úsys_cfgÚargsÚkwargsÚ
url_params©Ú	__class__r    r!   rL   �   s   þÿzDataSourceOracle.__init__Úci_pkl_versionr#   c                    sX   t ƒ  |¡ t| dƒst| dd ƒ t| dƒst| dtƒ ƒ t| dƒs*g ddœ| _d S d S )NrM   rS   rT   r,   rJ   )rK   Ú	_unpickleÚhasattrÚsetattrr"   rT   )r'   r`   r^   r    r!   ra   ž   s   

ý
ÿzDataSourceOracle._unpicklec                 C   s   t | j dg ¡ƒS )Nr2   )r$   rT   r;   r&   r    r    r!   Ú_has_network_config«   ó   z$DataSourceOracle._has_network_configc                   C   s   t ƒ S )z@Check platform environment to report if this datasource may run.)Ú_is_platform_viabler    r    r    r!   Ú	ds_detect®   s   zDataSourceOracle.ds_detectc           	      C   sd  t ƒ | _tjddd�tdœdtjddd�itjddd�tdœdtjddd�if}| jr;t ¡ }t	j
| j|dd|d�}nt ¡ }|  ¡  }| j d	td	 ¡}|� t|pT|| j| jttgd
�}W d   ƒ n1 shw   Y  |sqdS t|jd�| _|j }| _|j| _|d |d d|d |d dœ| _d|v r°|d  d¡}|r¦t |¡| _|d  d¡| jd< dS )Nr-   Úinstance©r   Úpath)ÚurlÚheadersrk   r,   T)ÚdistroÚ	interfaceÚipv6Úipv4Úconnectivity_urls_datar   ©Úfetch_vnics_dataÚmax_waitÚtimeoutÚmetadata_patternsF©rk   Ú	ociAdNameÚidr   ÚhostnameÚdisplayName)zavailability-zonezinstance-idzlaunch-indexzlocal-hostnamer8   ÚmetadataÚ	user_dataÚssh_authorized_keysÚpublic_keys) Ú_read_system_uuidÚsystem_uuidÚIPV4_METADATA_PATTERNÚformatÚ
V2_HEADERSÚIPV6_METADATA_PATTERNÚperform_dhcp_setupr
   Úfind_fallback_nicr   ÚEphemeralIPNetworkrm   r   ÚnullcontextÚ_is_iscsi_rootrR   r;   rQ   Úread_opc_metadatarW   rY   Ú _get_versioned_metadata_base_urlr   Úmetadata_addressr   Ú_crawled_metadatar   rM   r|   Úbase64Ú	b64decodeÚuserdata_raw)	r'   rq   Únic_nameÚnetwork_contextÚfetch_primary_nicÚfetch_secondary_nicsÚfetched_metadataÚdatar}   r    r    r!   Ú	_get_data³   s„   ÿüÿÿÿüÿÿîû
þþüÿÿû
ÿzDataSourceOracle._get_datac                 C   s   t  | j¡S )z¯quickly check (local only) if self.instance_id is still valid

        On Oracle, the dmi-provided system uuid differs from the instance-id
        but has the same life-span.)r   Úinstance_id_matches_system_uuidr�   )r'   rZ   r    r    r!   Úcheck_instance_id	  s   z"DataSourceOracle.check_instance_idc                 C   s   t  | j d¡¡S )Nr   )r   Únormalize_pubkey_datar|   r;   r&   r    r    r!   Úget_public_ssh_keys  re   z$DataSourceOracle.get_public_ssh_keysc                 C   ó
   | j  ¡ S )z)Return whether we are on a iscsi machine.)rS   r(   r&   r    r    r!   rŠ     r)   zDataSourceOracle._is_iscsi_rootc                 C   r�   ©N)rS   Úrender_configr&   r    r    r!   Ú_get_iscsi_config  s   
z"DataSourceOracle._get_iscsi_configc                 C   s’   |   ¡ r| jS d}|  ¡ r|  ¡ | _|   ¡ st d¡ d}| j dtd ¡}|s*|rAz|  	|¡ W n t
y@   t td¡ Y nw t| jƒ | jS )zÞNetwork config is read from initramfs provided files

        Priority for primary network_config selection:
        - iscsi
        - imds

        If none is present, then we fall back to fallback configuration.
        FzLCould not obtain network configuration from initramfs. Falling back to IMDS.Tr   z+Failed to parse IMDS network configuration!)rd   rT   rŠ   r    r9   ÚwarningrR   r;   rQ   Ú!_add_network_config_from_opc_imdsÚ	Exceptionr   ÚlogexcrC   )r'   Úset_primaryÚset_secondaryr    r    r!   r+     s2   

ÿþþÿ
	zDataSourceOracle.network_configFr¥   c                 C   sH  | j du rt d¡ dS |sd| j d v rt d¡ dS tƒ }|r$| j n| j dd… }t|ƒD ]ò\}}|o8|dk}|d  ¡ }| dd	¡oK| d
d	¡ }||vrWt d|¡ q/|| }	|rgt |d d ¡}
nt |d ¡}
| j	d dkrÄ|r…|rddig}n4ddig}n.g }| d
¡rœ| 
d|d
 › d|
j› �dœ¡ | d¡r³| 
d|d d › d|
j› �dœ¡ |	d|t|dœ}| j	d  
|¡ q/| j	d dk�r!td|idœ}|| j	d |	< |oÝ||d< |oä| |d< |�sg |d< | d
¡�r|d  
|d
 › d|
j› �¡ | d¡�r|d  
|d d › d|
j› �¡ || j	d |	< q/dS )aœ  Generate primary and/or secondary NIC config from IMDS and merge it.

        It will mutate the network config to include the secondary VNICs.

        :param set_primary: If True set primary interface.
        :raises:
        Exceptions are not handled within this function.  Likely
            exceptions are KeyError/IndexError
            (if the IMDS returns valid JSON with unexpected contents).
        Nz#NIC data is UNSET but should not beÚnicIndexr   z\VNIC metadata indicates this is a bare metal machine; skipping secondary VNIC configuration.r,   ÚmacAddrÚipv6SubnetCidrBlockFÚ	privateIpz)Interface with MAC %s not found; skippingÚipv6AddressesÚsubnetCidrBlockr   r.   Údhcp6ÚdhcpÚstaticú/)r.   Úaddressr3   )r8   r.   r4   ÚmtuÚsubnetsr2   r-   r7   )r²   r6   r5   Údhcp4Ú	addresses)rM   r9   r¡   r   Ú	enumerateÚlowerr;   Ú	ipaddressÚ
ip_networkrT   ÚappendÚ	prefixlenÚMTU)r'   r¥   Úinterfaces_by_macr   ÚindexÚ	vnic_dictÚ
is_primaryr4   Úis_ipv6_onlyr8   Únetworkr³   Úinterface_configr    r    r!   r¢   H  s¢   

ÿÿþþ
ÿ

ÿýÿ
	ÿýÿ
ûþÿÿÿ€²z2DataSourceOracle._add_network_config_from_opc_imds)F)"r   r   r   rP   r�   r   ÚNetworkConfigSourceÚCMD_LINEÚ
SYSTEM_CFGÚDSÚ	INITRAMFSrF   r   r   r†   rW   rY   rL   r   ra   r$   rd   Ústaticmethodrg   r˜   rš   rœ   rŠ   Údictr    Úpropertyr+   r¢   Ú__classcell__r    r    r^   r!   rD   {   s0   
 üV
-rD   c                   @   s   e Zd ZdZdS )ÚDataSourceOracleNetFN)r   r   r   r†   r    r    r    r!   rÍ   ¼  s    rÍ   r�   c                 C   s   | sdS |   t d¡d ¡S )NFÚopcr   )Ú
startswithÚIPV4_METADATA_ROOTÚsplit)r�   r    r    r!   Ú_is_ipv4_metadata_urlÀ  s   rÒ   c                  C   s   t  d¡} | d u rd S |  ¡ S )Nzsystem-uuid)r	   Úread_dmi_datar·   )Úsys_uuidr    r    r!   r€   Æ  s   
r€   c                  C   s   t  d¡} | tkS )Nzchassis-asset-tag)r	   rÓ   ÚCHASSIS_ASSET_TAG)Ú	asset_tagr    r    r!   rf   Ë  s   
rf   rk   c                 C   s   d| v rdS dS )Nz/opc/v2/r-   r,   r    rw   r    r    r!   Ú_url_versionÐ  s   r×   c                 C   s   t | ƒdkrtS d S )Nr-   )r×   r„   rw   r    r    r!   Ú_headers_cbÔ  s   rØ   c                 C   sH   | s| S d| v r|   d¡d d S d| v r|   d¡d d S td|  ƒ‚)zQ
    Remove everything following the version number in the metadata address.
    Úv2r   zv2/Úv1zv1/zInvalid metadata address: )rÑ   Ú
ValueErrorrw   r    r    r!   rŒ   Ø  s   rŒ   rr   rs   rv   c                    sì   ‡ fdd„dD ƒ}t  d|¡ t ¡ }t|||tddd�\}}|s,t  dd	 |¡¡ d
S t  d|¡ t 	| 
d¡¡}t|ƒ}	d
}
| rot| dd¡g|t ¡ |  |tddd�\}}|rjt 	| 
d¡¡}
t  d|¡ nt  d¡ t|	||
|ƒS )aã  
    Fetch metadata from the /opc/ routes from the IMDS.

    Returns:
        Optional[ReadOpcMetadataResponse]: If fetching metadata fails, None.
            If fetching metadata succeeds, a namedtuple containing:
            - The metadata version as an integer
            - The JSON-decoded value of the instance data from the IMDS
            - The JSON-decoded value of the vnics data from the IMDS if
                `fetch_vnics_data` is True, else None. Alternatively,
                None if fetching metadata failed
            - The url that was used to fetch the metadata.
                This allows for later determining if v1 or v2 endppoint was
                used and whether the IMDS was reached via IPv4 or IPv6.
    c                    s$   g | ]}ˆ D ]	}|j |d d�‘qqS )rh   ri   )rƒ   )r/   r   Úmetadata_pattern©rv   r    r!   r1   ü  s    ýþÿz%read_opc_metadata.<locals>.<listcomp>)r-   r,   z*Attempting to fetch IMDS metadata from: %sgš™™™™™¹?T)Úurlsrt   ru   Ú
headers_cbÚ
sleep_timeÚconnect_synchronouslyz-Failed to fetch IMDS metadata from any of: %sz, Nz7Successfully fetched instance metadata from IMDS at: %szutf-8rh   Úvnicsz4Successfully fetched vnics metadata from IMDS at: %sz+Failed to fetch IMDS network configuration!)r9   r:   ÚtimeÚ	monotonicr   rØ   r¡   ÚjoinÚjsonÚloadsÚdecoder×   Úreplacer   )rs   rt   ru   rv   rÞ   Ú
start_timeÚurl_that_workedÚinstance_responser   Úmetadata_versionr   Ú	vnics_urlÚvnics_responser    rÝ   r!   r‹   æ  s`   
þ
úþþ
úþ
ür‹   c                 C   s   t  | t¡S rž   )r   Úlist_from_dependsÚdatasources)Údependsr    r    r!   Úget_datasource_listG  s   ró   Ú__main__zú
        Query Oracle Cloud metadata and emit a JSON object with two keys:
        `read_opc_metadata` and `_is_platform_viable`.  The values of each are
        the return values of the corresponding functions defined in
        DataSourceOracle.py.rÝ   )r‹   rf   )Ar*   r�   r¸   ræ   Úloggingrã   Útypingr   r   r   r   r   r   Ú	cloudinitr   r	   r
   r   r   Úcloudinit.distros.networkingr   Úcloudinit.netr   r   r   r   Úcloudinit.url_helperr   Ú	getLoggerr   r9   rQ   rÕ   rÐ   ÚIPV6_METADATA_ROOTr‚   r…   r„   r¼   r   ÚKlibcNetworkConfigSourcer"   rC   Ú
DataSourcerD   rÍ   r   rÒ   r€   r$   rf   r   r×   rØ   rŒ   rW   rY   r‹   ÚDEP_FILESYSTEMÚDEP_NETWORKrñ   ró   ÚdescriptionÚprintÚ
json_dumpsr    r    r    r!   Ú<module>   s‚    
þ4  Cûþû
ú
Uþþþ
þúÿÿø