o
    x[hÓm  ã                   @   s6  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m	Z	m
Z
mZ d dlmZ d dlmZ e e¡Zddd„ dfd	eji fd
dd„ dfdœZdZdZdZdZdZdZdZdZdZdZeeeeeeeefZdZ G dd„ de!ƒZ"G dd„ dƒZ#G dd„ de j$d�Z%G dd „ d e%ƒZ&G d!d"„ d"e%ƒZ'd%d#d$„Z(dS )&é    N)ÚnetÚsourcesÚsubpÚ
url_helperÚutil)ÚBrokenMetadata)Úec2Únetwork_configc                 C   ó   | S ©N© ©Úxr   r   úE/usr/lib/python3/dist-packages/cloudinit/sources/helpers/openstack.pyÚ<lambda>   ó    r   Ú Úmeta_jsÚauthorized_keysc                 C   r
   r   r   r   r   r   r   r      r   )zetc/network/interfaceszmeta.jszroot/.ssh/authorized_keys))zlocal-hostnameÚhostnameF)úinstance-idÚuuidTÚlatestz
2012-08-10z
2013-04-04z
2013-10-17z
2015-10-15z
2016-06-30z
2016-10-06z
2017-02-22z
2018-08-27)NÚbgpovsÚbridgeÚ	cascadingÚdvsÚethernetÚhw_vebÚhypervÚovsÚphyÚtapÚ	vhostuserÚvifc                   @   s   e Zd ZdS )ÚNonReadableN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r%   Q   s    r%   c                   @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚSourceMixinc                 C   s>   | j sd S | j  di ¡}| ¡ D ]\}}||kr|  S qd S )Nzblock-device-mapping)Úec2_metadataÚgetÚitems)ÚselfÚnameÚbdmÚent_nameÚdevicer   r   r   Ú_ec2_name_to_deviceV   s   ÿzSourceMixin._ec2_name_to_devicec                 C   s$   d}| j dkr	d}t | j |¡¡S )NÚpublic_keysé   úpublic-keys)Úversionr   Únormalize_pubkey_dataÚmetadatar+   )r-   r.   r   r   r   Úget_public_ssh_keys_   s   
zSourceMixin.get_public_ssh_keysc                 C   sV   d }zd| }|dkrd| }t  |¡}|r|d }W |S W |S  tjy*   Y |S w )NzLABEL=%sÚswapzTYPE=%sr   )r   Úfind_devs_withr   ÚProcessExecutionError)r-   r.   r1   ÚcriteriaÚdev_entriesr   r   r   Ú_os_name_to_devicee   s   

üþþzSourceMixin._os_name_to_devicec                 C   sV   |sd S |  d¡sd| }tj |¡r|S |  tj |¡¡}|r)t d||¡ |S d S )Nú/z/dev/%szRemapped device name %s => %s)Ú
startswithÚosÚpathÚexistsÚ_remap_deviceÚbasenameÚLOGÚdebug)r-   r1   Úremappedr   r   r   Ú_validate_device_namer   s   
z!SourceMixin._validate_device_namec                 C   sº   |sd S |g}|dkr|  dd¡ |dkr| d¡ d }t d|¡ |D ]}|  |¡}|  |¡}|r4 nq$|sPt d|¡ |D ]}|  |¡}|  |¡}|rO nq?|sTd S t d||¡ |S )NÚrootr   Úamiz(Using ec2 style lookup to find device %sz.Using openstack style lookup to find device %szMapped %s to device %s)ÚinsertÚappendrG   rH   r2   rJ   r?   )r-   r.   Únamesr1   Únr   r   r   Údevice_name_to_device€   s6   


ÿ

ÿz!SourceMixin.device_name_to_deviceN)r&   r'   r(   r2   r9   r?   rJ   rQ   r   r   r   r   r)   U   s    	r)   c                   @   sh   e Zd Zdd„ Zejdd„ ƒZejddd„ƒZejdd	„ ƒZejd
d„ ƒZ	dd„ Z
ddd„Zdd„ ZdS )Ú
BaseReaderc                 C   s
   || _ d S r   )Ú	base_path©r-   rS   r   r   r   Ú__init__¢   s   
zBaseReader.__init__c                 G   ó   d S r   r   ©r-   ÚbaseÚadd_onsr   r   r   Ú
_path_join¥   ó   zBaseReader._path_joinFc                 C   rV   r   r   ©r-   rC   Údecoder   r   r   Ú
_path_read©   r[   zBaseReader._path_readc                 C   rV   r   r   ©r-   r   r   r   Ú_fetch_available_versions­   r[   z$BaseReader._fetch_available_versionsc                 C   rV   r   r   r_   r   r   r   Ú_read_ec2_metadata±   r[   zBaseReader._read_ec2_metadatac              
   C   sŠ   z|   ¡ }W n ty" } zt d| j|¡ g }W Y d }~nd }~ww dd„ tttƒƒD ƒ}t}|D ]	}||vr9q2|} t d||¡ |S )Nz4Unable to read openstack versions from %s due to: %sc                 S   s   g | ]}|‘qS r   r   )Ú.0Úvr   r   r   Ú
<listcomp>Â   s    z4BaseReader._find_working_version.<locals>.<listcomp>zSelected version '%s' from %s)	r`   Ú	ExceptionrG   rH   rS   ÚreversedÚlistÚOS_VERSIONSÚ	OS_LATEST)r-   Úversions_availableÚeÚ	supportedÚselected_versionÚpotential_versionr   r   r   Ú_find_working_versionµ   s0   ý€ú
ýz BaseReader._find_working_versionc                 C   s^   |  dd¡ d¡}| d¡}dd„ |D ƒ}|std| ƒ‚| j| jdg|¢R Ž }| j||d�S )	NÚcontent_pathr   r@   c                 S   s   g | ]}t |ƒr|‘qS r   )Úlen)rb   Úpr   r   r   rd   Õ   s    z1BaseReader._read_content_path.<locals>.<listcomp>z!Item %s has no valid content pathÚ	openstack©r]   )r+   ÚlstripÚsplitr   rZ   rS   r^   )r-   Úitemr]   rC   Úpath_piecesÚvalid_piecesr   r   r   Ú_read_content_pathÒ   s   
zBaseReader._read_content_pathc                    s¾  t jtjtttfd�‰ ‡ ‡fdd„}dddœ}|ˆ ¡ ƒ}| ¡ D ]o\}\}}}ˆ 	ˆj
|¡}d}d}zˆ |¡}W n# ty] }	 z|sLt d	||	¡ nt d
||	¡ W Y d}	~	nd}	~	ww d}|rj|sjtd| ƒ‚|rŠ|rŠz||ƒ}W n ty‰ }	 z	td||	f ƒ|	‚d}	~	ww |r�|||< q!|d }
d|
v r¼|
d }z	t |¡|
d< W n ttfy» }	 ztd|	 ƒ|	‚d}	~	ww i }|
 dg ¡}|D ])}d|vrÍqÆ|d }z	ˆ |¡||< W qÆ tyï }	 z	td||	f ƒ|	‚d}	~	ww ||d< |
 dd¡}|�rzˆj|dd�}||d< W n t�y }	 ztd|	 ƒ|	‚d}	~	ww z
|
d d |d< W n
 t�y3   Y nw ˆ ¡ |d< tD ] \}}}|�rO||
v�rOtd| ƒ‚||
v �r[|
 |¡|
|< �q<|S )zäReads a version 2 formatted location.

        Return a dict with metadata, userdata, ec2-metadata, dsmode,
        network_config, files and version (2).

        If not a valid location, raise a NonReadable exception.
        )Ú
root_typesc                    s†   i }ˆ  d| d¡dtjf|d< ˆ  d| d¡ddd„ f|d	< ˆ  d| d
¡dˆ f|d< ˆ  d| d¡dˆ f|d< ˆ  d| d¡dˆ f|d< |S )Nrs   zmeta_data.jsonTr8   Ú	user_dataFc                 S   r
   r   r   r   r   r   r   r   õ   r   z7BaseReader.read_v2.<locals>.datafiles.<locals>.<lambda>Úuserdatazvendor_data.jsonÚ
vendordatazvendor_data2.jsonÚvendordata2znetwork_data.jsonÚnetworkdata)rZ   r   Ú	load_json)r6   Úfiles©Úload_json_anytyper-   r   r   Ú	datafilesè   s,   ú	ýýýýz%BaseReader.read_v2.<locals>.datafilesr   é   )r}   r6   NFz*Failed reading optional path %s due to: %sz+Failed reading mandatory path %s due to: %sTzMissing mandatory path: %súFailed to process path %s: %sr8   Úrandom_seedz.Badly formatted metadata random_seed entry: %sr‚   rC   z#Failed to read provided file %s: %sr	   rt   z(Failed to read network configuration: %sÚmetaÚdsmodezec2-metadatazNo '%s' entry in metadata)Ú	functoolsÚpartialr   r�   Údictrg   Ústrro   r,   rZ   rS   r^   ÚIOErrorrG   rH   r%   re   r   Úbase64Ú	b64decodeÚ
ValueErrorÚ	TypeErrorr+   rz   ÚKeyErrorra   Ú
KEY_COPIES)r-   r…   ÚresultsÚdatar.   rC   ÚrequiredÚ
translatorÚfoundrk   r8   rˆ   r‚   Úmetadata_filesrw   Únet_itemÚcontentÚ
target_keyÚ
source_keyÚis_requiredr   rƒ   r   Úread_v2Û   sÂ   	ÿ!þÿÿ€ú

ÿþ€ÿ€ÿþ€ÿ
ÿþ€ÿÿþ€ÿ	ÿ
€zBaseReader.read_v2N©F)r&   r'   r(   rU   ÚabcÚabstractmethodrZ   r^   r`   ra   ro   rz   r¡   r   r   r   r   rR   ¡   s    



	rR   )Ú	metaclassc                       sF   e Zd Z‡ fdd„Zdd„ Zddd„Zdd	„ Zd
d„ Zdd„ Z‡  Z	S )ÚConfigDriveReaderc                    s   t t| ƒ |¡ d | _d S r   )Úsuperr¦   rU   Ú	_versionsrT   ©Ú	__class__r   r   rU   f  s   
zConfigDriveReader.__init__c                 G   s   |gt |ƒ }tjj|Ž S r   )rg   rB   rC   Újoin)r-   rX   rY   Ú
componentsr   r   r   rZ   j  s   zConfigDriveReader._path_joinFc                 C   s   |rt  |¡S t  |¡S r   )r   Úload_text_fileÚload_binary_filer\   r   r   r   r^   n  s
   
ÿÿýzConfigDriveReader._path_readc                    s@   | j d u r|  | jd¡‰ ‡ fdd„t ˆ ¡D ƒ}t|ƒ| _ | j S )Nrs   c                    s$   g | ]}t j t j ˆ ¡¡r|‘qS r   )rB   rC   Úisdirr«   ©rb   Úd©rC   r   r   rd   x  s    ýÿz?ConfigDriveReader._fetch_available_versions.<locals>.<listcomp>)r¨   rZ   rS   rB   ÚlistdirÚsorted)r-   rš   r   r²   r   r`   u  s   

þ
z+ConfigDriveReader._fetch_available_versionsc              
   C   s`   |   | jddd¡}tj |¡si S z	t |  |¡¡W S  ty/ } z	t	d||f ƒ|‚d }~ww )Nr   r   zmeta-data.jsonr‡   )
rZ   rS   rB   rC   rD   r   r�   r^   re   r   )r-   rC   rk   r   r   r   ra   €  s   
ÿ
ÿþ€ÿz$ConfigDriveReader._read_ec2_metadatac                 C   sz  i }t  ¡ D ]}|  | j|¡}tj |¡r|||< q|s#td| j ƒ‚i }t  ¡ D ]O\}\}}}||v rq|| }z|  	|¡}W n t
yR }	 ztd| ƒ|	‚d}	~	ww z||ƒ||< W q) typ }	 z	td||	f ƒ|	‚d}	~	ww t |¡||< q)|d }
|d }| d|
¡}
|
r–|
 ¡ }dd	„ |D ƒ|d< d
|v r |d
 |d
< d|dœ}d|v r¯|d |d< | dd¡|d< i |d< |S )zºReads a version 1 formatted location.

        Return a dict with metadata, userdata, dsmode, files and version (1).

        If not a valid path, raise a NonReadable exception.
        z%s: no files foundzFailed to read: %sNr‡   r   r   r5   c                 S   s"   g | ]}t |ƒr| d ¡s|‘qS )ú#)rq   rA   )rb   Úliner   r   r   rd   ¹  s    ýýÿz-ConfigDriveReader.read_v1.<locals>.<listcomp>r   r4   )r6   r8   rŠ   z	user-datar   r}   r‚   )ÚFILES_V1ÚkeysrZ   rS   rB   rC   rD   r%   r,   r^   r�   r   re   ÚcopyÚdeepcopyr+   Ú
splitlines)r-   rš   r.   rC   ÚmdÚkeyr™   ÚdefaultÚcontentsrk   Úkeydatar   Úlinesr–   r   r   r   Úread_v1Ž  s^   €€ÿ
ÿþ€ÿ
þþzConfigDriveReader.read_v1r¢   )
r&   r'   r(   rU   rZ   r^   r`   ra   rÂ   Ú__classcell__r   r   r©   r   r¦   e  s    
r¦   c                       s@   e Zd Zd‡ fdd„	Zdd„ Zddd	„Zd
d„ Zdd„ Z‡  ZS )ÚMetadataReaderNé   c                    s4   t t| ƒ |¡ || _t|ƒ| _t|ƒ| _d | _d S r   )	r§   rÄ   rU   Ússl_detailsÚfloatÚtimeoutÚintÚretriesr¨   )r-   Úbase_urlrÆ   rÈ   rÊ   r©   r   r   rU   Ù  s
   


zMetadataReader.__init__c                 C   sb   | j d ur| j S g }|  | jd¡}| j|dd�}| ¡ D ]}| ¡ }|s%q| |¡ q|| _ | j S )Nrs   Trt   )r¨   rZ   rS   r^   r»   ÚstriprN   )r-   rš   Úversion_pathr�   r¶   r   r   r   r`   à  s   
z(MetadataReader._fetch_available_versionsFc                 C   s6   dd„ }t j|| j| j| j|d�}|r|j ¡ S |jS )Nc              	   S   sF   zt | jƒ}|dkr|dvrW dS W dS W dS  ttfy"   Y dS w )Ni�  )i˜  i­  iô  iö  i÷  iø  FT)rÉ   Úcoder“   r’   )ÚcauserÎ   r   r   r   Úshould_retry_cbð  s   
ÿûýýz2MetadataReader._path_read.<locals>.should_retry_cb)rÊ   rÆ   rÈ   Úexception_cb)r   ÚreadurlrÊ   rÆ   rÈ   r¿   r]   )r-   rC   r]   rÐ   Úresponser   r   r   r^   ï  s   
û
zMetadataReader._path_readc                 G   s   t j|g|¢R Ž S r   )r   Úcombine_urlrW   r   r   r   rZ     s   zMetadataReader._path_joinc                 C   s   t j| j| j| jd�S )N)rÆ   rÈ   rÊ   )r   Úget_instance_metadatarÆ   rÈ   rÊ   r_   r   r   r   ra   	  s
   ýz!MetadataReader._read_ec2_metadata)NrÅ   rÅ   r¢   )	r&   r'   r(   rU   r`   r^   rZ   ra   rÃ   r   r   r©   r   rÄ   Ø  s    
rÄ   c               
      sÜ  | du rdS g d¢g d¢g d¢dœ‰|   dg ¡}|   dg ¡}|   dg ¡}g }i ‰d	}d
}g }|D �]ì‰g }	t‡fdd„ˆ ¡ D ƒƒ}
dˆv rLˆd |
d< d}ˆ  d¡r`ˆ  d¡ ¡ }|ˆˆd < |
  d¡|ˆd ˆd dœ}‡fdd„|D ƒD ]Ú}t‡fdd„| ¡ D ƒƒ}‡fdd„|  dg ¡D ƒ}|rœ| d|i¡ |d dkrª| ddi¡ nH|d dkr¸| ddi¡ n:|d dv rÈ| d|d i¡ n*|d dv rÚ| d|  d¡dœ¡ n|d d v rò|
 d!d"i¡ | d#|  d¡dœ¡ d$d„ |  dg ¡D ƒ}|  dg ¡D ]}|  d¡d%k�r�q|d& |v �r�q| |d& ¡ �q|�r(||d'< |d d(v �r6|
 d!d)i¡ |d d*k�rAd)|d*< |d d+k�rLd)|d+< |	 |¡ qw|
 d,|	i¡ ˆd d-v �r¸i }|�rl|
 d.|i¡ ˆ ¡ D ]$\}}|d/k�r{�qp| d0¡�r“d1 | d2d3¡d4 ¡}| ||i¡ �qp|| }|d37 }| |
d5d6t	 
ˆd/ ¡f¡ |
 ||d7œ¡ ||d< nZˆd d8v �rûd9ˆd: ˆd; f }|
 |ˆd; ˆd< d=œ¡ | |
d:d6ˆd: f¡ | |
dd>ˆd;  ˆd: f¡ | ˆd< |d?œ¡ nˆd tv�r
t d@ˆd ¡ |
 dA|dBœ¡ | |
¡ |ˆ|d < q0dCd„ |D ƒ}|�s+|�r²|du �r4t ¡ }ˆ ¡ D ]\}}|  d¡�rD�q8|  dD¡|v �rT||dD  |d< �q8|D ]/}|  d.¡}|�shtdE| ƒ‚||v�r€t ¡  t ¡ }||v�r€tdF| ƒ‚|| |d< �qX|D ]'\}
}‰ }t|ttfƒ�r¦‡ ‡fdGd„|D ƒ|
|< �qŠˆ ˆ| d  |
|< �qŠt ¡ }|�rÒ|D ]}
|
d |v �rÐ||
d  |
d.< dH|
d< �q»|D ]}t	 
|¡}
|
 ddIi¡ | |
¡ �qÔd3|dJœS )Ka*  Return a dictionary of network_config by parsing provided
       OpenStack ConfigDrive NetworkData json format

    OpenStack network_data.json provides a 3 element dictionary
      - "links" (links are network devices, physical or virtual)
      - "networks" (networks are ip network configurations for one or more
                    links)
      -  services (non-ip services, like dns)

    networks and links are combined via network items referencing specific
    links via a 'link_id' which maps to a links 'id' field.

    To convert this format to network_config yaml, we first iterate over the
    links and then walk the network list to determine if any of the networks
    utilize the current link; if so we generate a subnet entry for the device

    We also need to map network_data.json fields to network_config fields. For
    example, the network_data links 'id' field is equivalent to network_config
    'name' field for devices.  We apply more of this mapping to the various
    link types that we encounter.

    There are additional fields that are populated in the network_data.json
    from OpenStack that are not relevant to network_config yaml, so we
    enumerate a dictionary of valid keys for network_yaml and apply filtering
    to drop these superfluous keys from the network_config yaml.
    N)r.   ÚtypeÚmac_addressÚsubnetsÚparamsÚmtu)
rÖ   ÚaddressÚnetmaskÚ	broadcastÚmetricÚgatewayÚpointopointÚscopeÚdns_nameserversÚ
dns_search)ÚnetworkÚdestinationrÜ   rß   rÞ   )ÚphysicalÚsubnetÚroutesÚlinksÚnetworksÚserviceszbond%dr   c                 3   ó(   � | ]\}}|ˆ d  v r||fV  qdS )ræ   Nr   ©rb   Úkrc   ©Ú
valid_keysr   r   Ú	<genexpr>T  ó   € ÿz#convert_net_json.<locals>.<genexpr>r.   Úethernet_mac_addressÚidrÖ   )r.   Úmacrô   rÖ   c                    s    g | ]}|d  ˆ d kr|‘qS )Úlinkrô   r   )rb   rP   )rö   r   r   rd   j  s     z$convert_net_json.<locals>.<listcomp>c                 3   rì   )rç   Nr   rí   rï   r   r   rñ   k  rò   c                    s&   g | ]}t ‡ fd d„| ¡ D ƒƒ‘qS )c                 3   rì   )rè   Nr   rí   rï   r   r   rñ   r  s   € þýz.convert_net_json.<locals>.<listcomp>.<genexpr>)r�   r,   )rb   Úrouterï   r   r   rd   q  s    ûþÿrè   Ú	ipv4_dhcpÚdhcp4Ú	ipv6_dhcpÚdhcp6)Ú
ipv6_slaaczipv6_dhcpv6-statelessúipv6_dhcpv6-stateful)Úipv4Ústaticrÿ   Ú
ip_address)rÖ   rÛ   )Úipv6Ústatic6z	accept-raFr  c                 S   s4   g | ]}|  d g ¡D ]}|  d¡dkr
|d ‘q
qS )rë   rÖ   ÚdnsrÛ   ©r+   )rb   r÷   Úservicer   r   r   rd   š  s    
ýýr  rÛ   râ   )rý   rú   Trþ   r  rØ   )Úbondr×   Ú
bond_linksr  zbond-{}Úbond_r4   éÿÿÿÿÚbond_interfacesz%s)rÙ   r.   )Úvlanz%s.%sÚ	vlan_linkÚvlan_idÚvlan_mac_address)r.   r  r×   z%%s.%s)rõ   r.   z9Unknown network_data link type (%s); treating as physicalræ   )rÖ   r×   c                 S   s&   g | ]}|  d ¡dkrd|vr|‘qS )rÖ   ræ   r.   r  r°   r   r   r   rd   ó  s     rõ   z#No mac_address or name entry for %sz"Unable to find a system nic for %sc                    s   g | ]
}ˆ ˆ| d   ‘qS )r.   r   )rb   Útarget)ÚfmtÚlink_id_infor   r   rd     s    ÿÚ
infinibandÚ
nameserver)r6   Úconfig)r+   r�   r,   ÚlowerÚupdaterN   rA   Úformatrv   r¹   rº   ÚKNOWN_PHYSICAL_TYPESrG   Úwarningr   Úget_interfaces_by_macr’   r   Úudevadm_settleÚ
isinstancerg   ÚtupleÚget_ib_hwaddrs_by_interface) Únetwork_jsonÚ
known_macsré   rê   rë   Úlink_updatesÚbond_name_fmtÚbond_numberr  rØ   ÚcfgÚlink_mac_addrÚcurinforä   rç   rè   râ   r  rÙ   rî   rc   Útranslated_keyÚ	link_namer.   Ú
need_namesÚ_link_idÚinfor±   rõ   r½   ÚtargetsÚib_known_hwaddrsr   )r  rö   r  rð   r   Úconvert_net_json  s@  ë
ÿ
üÿ

ú	þÿþÿ

þ
€üÿ
ýÿÿý
ÿ
€


ÿ€

r.  )NN))r£   r�   r¹   r‹   ÚloggingrB   Ú	cloudinitr   r   r   r   r   Úcloudinit.sourcesr   Úcloudinit.sources.helpersr   Ú	getLoggerr&   rG   r�   r·   r•   ri   Ú	OS_FOLSOMÚ
OS_GRIZZLYÚ	OS_HAVANAÚ
OS_LIBERTYÚOS_NEWTON_ONEÚOS_NEWTON_TWOÚOS_OCATAÚOS_ROCKYrh   r  r�   r%   r)   ÚABCMetarR   r¦   rÄ   r.  r   r   r   r   Ú<module>   sR   

üøL Es: