U
    Ldf                     @   s:  d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZm	Z	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)log)netsourcessubp
url_helperutil)BrokenMetadata)ec2network_configc                 C   s   | S N xr   r   E/usr/lib/python3/dist-packages/cloudinit/sources/helpers/openstack.py<lambda>       r    meta_jsauthorized_keysc                 C   s   | S r   r   r   r   r   r   r      r   )zetc/network/interfaceszmeta.jszroot/.ssh/authorized_keys))zlocal-hostnameZhostnameF)instance-idZ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)NZbgpovsZbridgeZ	cascadingZdvsZethernetZhw_vebZhypervZovsZphyZtapZ	vhostuserZ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)Zec2_metadatagetitems)selfnameZbdmZ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 )NZpublic_keys   public-keys)versionr   Znormalize_pubkey_datametadatar   )r   r   r   r   r   get_public_ssh_keys_   s    
zSourceMixin.get_public_ssh_keysc                 C   sR   d }z2d| }|dkrd| }t |}|r4|d }W n tjk
rL   Y nX |S )NzLABEL=%sZswapzTYPE=%sr   )r   Zfind_devs_withr   ZProcessExecutionError)r   r   r    ZcriteriaZ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|}|rRtd|| |S d S )N/z/dev/%szRemapped device name %s => %s)
startswithospathexistsZ_remap_devicebasenameLOGdebug)r   r    Z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r4|d d }td| |D ] }| |}| |}|rH qjqH|std| |D ] }| |}| |}|r~ qq~|sd S td|| |S d S )Nrootr   Zamiz(Using ec2 style lookup to find device %sz.Using openstack style lookup to find device %szMapped %s to device %s)insertappendr.   r/   r!   r0   r'   )r   r   namesr    nr   r   r   device_name_to_device   s2    




z!SourceMixin.device_name_to_deviceN)r   r   r   r!   r&   r'   r0   r6   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   r8   r   r   r   __init__   s    zBaseReader.__init__c                 G   s   d S r   r   r   baseadd_onsr   r   r   
_path_join   s    zBaseReader._path_joinFc                 C   s   d S r   r   r   r+   decoder   r   r   
_path_read   s    zBaseReader._path_readc                 C   s   d S r   r   r   r   r   r   _fetch_available_versions   s    z$BaseReader._fetch_available_versionsc                 C   s   d S r   r   rB   r   r   r   _read_ec2_metadata   s    zBaseReader._read_ec2_metadatac              
   C   s   z|   }W n6 tk
rB } ztd| j| g }W 5 d }~X Y nX dd tttD }t}|D ]}||krpqb|} qzqbt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)	rC   	Exceptionr.   r/   r8   reversedlistOS_VERSIONS	OS_LATEST)r   Zversions_availableeZ	supportedZselected_versionZpotential_versionr   r   r   _find_working_version   s,    z BaseReader._find_working_versionc                 C   s\   | ddd}|d}dd |D }|s:td| | j| jdf| }| j||dS )	NZcontent_pathr   r(   c                 S   s   g | ]}t |r|qS r   )len)rE   pr   r   r   rG      s      z1BaseReader._read_content_path.<locals>.<listcomp>z!Item %s has no valid content path	openstackr@   )r   lstripsplitr   r>   r8   rA   )r   itemr@   r+   Zpath_piecesZ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 ]\}\}}}	j
|}d}d}z|}W nD tk
r }	 z&|std	||	 ntd
||	 W 5 d}	~	X Y nX d}|r|std| |r"|r"z||}W n6 tk
r  }	 ztd||	f |	W 5 d}	~	X Y nX |rB|||< qB|d }
d|
kr|
d }zt||
d< W n6 ttfk
r }	 ztd|	 |	W 5 d}	~	X Y nX i }|
dg }|D ]f}d|krq|d }z|||< W n6 tk
r
 }	 ztd||	f |	W 5 d}	~	X Y nX q||d< |
dd}|rxzj|dd}||d< W n2 tk
rv }	 ztd|	 |	W 5 d}	~	X Y nX z|
d d |d< W n tk
r   Y nX  |d< tD ]@\}}}|r||
krtd| ||
kr|
||
|< q|S )zReads 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.
        )Z
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 )NrQ   zmeta_data.jsonTr%   Z	user_dataFc                 S   s   | S r   r   r   r   r   r   r      r   z7BaseReader.read_v2.<locals>.datafiles.<locals>.<lambda>userdatazvendor_data.jsonZ
vendordatazvendor_data2.jsonZvendordata2znetwork_data.jsonZnetworkdata)r>   r   	load_json)r$   filesZload_json_anytyper   r   r   	datafiles   s,    	z%BaseReader.read_v2.<locals>.datafilesr      )rW   r$   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: %sr%   random_seedz.Badly formatted metadata random_seed entry: %srY   r+   z#Failed to read provided file %s: %sr
   rR   z(Failed to read network configuration: %smetadsmodezec2-metadatazNo '%s' entry in metadata)	functoolspartialr   rX   dictrJ   strrN   r   r>   r8   rA   IOErrorr.   r/   r   rH   r   base64Z	b64decode
ValueError	TypeErrorr   rV   KeyErrorrD   
KEY_COPIES)r   r[   resultsdatar   r+   Zrequired
translatorfoundrM   r%   r^   rY   Zmetadata_filesrU   Znet_itemcontentZ
target_keyZ
source_keyZis_requiredr   rZ   r   read_v2   s    	 !    





zBaseReader.read_v2N)F)F)r   r   r   r:   abcabstractmethodr>   rA   rC   rD   rN   rV   rp   r   r   r   r   r7      s   



	r7   )	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   )superrt   r:   	_versionsr9   	__class__r   r   r:   f  s    zConfigDriveReader.__init__c                 G   s   |gt | }tjj| S r   )rJ   r*   r+   join)r   r<   r=   Z
componentsr   r   r   r>   j  s    zConfigDriveReader._path_joinFc                 C   s   t j||dS )NrR   )r   Z	load_filer?   r   r   r   rA   n  s    zConfigDriveReader._path_readc                    s@   | j d kr:| | jd  fddt D }t|| _ | j S )NrQ   c                    s$   g | ]}t jt j r|qS r   )r*   r+   isdirry   rE   dr+   r   r   rG   t  s   z?ConfigDriveReader._fetch_available_versions.<locals>.<listcomp>)rv   r>   r8   r*   listdirsorted)r   rn   r   r}   r   rC   q  s    


z+ConfigDriveReader._fetch_available_versionsc              
   C   sn   |  | jddd}tj|s"i S zt| |W S  tk
rh } zt	d||f |W 5 d }~X Y nX d S )Nr	   r   zmeta-data.jsonr]   )
r>   r8   r*   r+   r,   r   rX   rA   rH   r   )r   r+   rM   r   r   r   rD   |  s        
z$ConfigDriveReader._read_ec2_metadatac                 C   s  i }t  D ]&}| | j|}tj|r|||< qt|dkrNtd| j i }t 	 D ]\}\}}}||kr|| }z| 
|}W n0 tk
r }	 ztd| |	W 5 d}	~	X Y nX z||||< W n4 tk
r }	 ztd||	f |	W 5 d}	~	X Y nX qZt|||< qZ|d }
|d }|d|
}
|
rN|
 }d	d
 |D |d< d|krd|d |d< d|d}d|kr|d |d< |dd|d< i |d< |S )zReads 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.
        r   z%s: no files foundzFailed to read: %sNr]   r   r   r#   c                 S   s"   g | ]}t |r|d s|qS )#)rO   r)   )rE   liner   r   r   rG     s    
z-ConfigDriveReader.read_v1.<locals>.<listcomp>r   r"   )r$   r%   r`   z	user-datar   rW   rY   )FILES_V1keysr>   r8   r*   r+   r,   rO   r   r   rA   re   r   rH   copydeepcopyr   
splitlines)r   rn   r   r+   Zmdkeyrm   defaultcontentsrM   Zkeydatar   linesrk   r   r   r   read_v1  sT    

 



zConfigDriveReader.read_v1)F)
r   r   r   r:   r>   rA   rC   rD   r   __classcell__r   r   rw   r   rt   e  s   
rt   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   )	ru   r   r:   ssl_detailsfloattimeoutintretriesrv   )r   Zbase_urlr   r   r   rw   r   r   r:     s
    

zMetadataReader.__init__c                 C   sb   | j d k	r| j S g }| | jd}| j|dd}| D ]}| }|sJq8|| q8|| _ | j S )NrQ   TrR   )rv   r>   r8   rA   r   stripr3   )r   rn   Zversion_pathro   r   r   r   r   rC     s    
z(MetadataReader._fetch_available_versionsFc                 C   s:   dd }t j|| j| j| j|d}|r0|j S |jS d S )Nc              	   S   s:   zt |j}|dkrW dS W n ttfk
r4   Y nX dS )Ni  FT)r   coderh   rg   )Z_request_argscauser   r   r   r   should_retry_cb  s    

z2MetadataReader._path_read.<locals>.should_retry_cb)r   r   r   Zexception_cb)r   Zreadurlr   r   r   r   r@   )r   r+   r@   r   Zresponser   r   r   rA     s    

zMetadataReader._path_readc                 G   s   t j|f| S r   )r   Zcombine_urlr;   r   r   r   r>     s    zMetadataReader._path_joinc                 C   s   t j| j| j| jdS )N)r   r   r   )r	   Zget_instance_metadatar   r   r   rB   r   r   r   rD     s
    z!MetadataReader._read_ec2_metadata)Nr   r   )F)	r   r   r   r:   rC   rA   r>   rD   r   r   r   rw   r   r     s
   
r   c                    sN  | dkrdS ddddddgddd	d
dddddddgd|  dg }|  dg }|  dg }g }i d}d}g }|D ]Xg }	tfdd D }
dkrd |
d< d} drԈ d }|d < |
 d|d d d}fdd|D D ]L}tfdd| D }|d d kr@|dd!i n|d d"kr^|dd#i nz|d d$kr|d|d i nX|d d%kr|d&| d'd( n2|d d)kr|
d*d+i |d,| d'd( d-d | dg D }|r||d< |d d.kr|
d*d/i |d d0kr.d/|d0< |d d1krDd/|d1< |	| q|
d|	i d d2kri }|r||d<  D ]4\}}|d3krqn|d4r|||i q|| }|d57 }||
d6d7td3 f |
||d8 ||d< nd d9krd:d; d< f }|
|d< d= d> ||
d;d7d; f ||
dd?d<  d; f |d= |d@ n.d t	krt
dAd  |
dB|dC ||
 ||d < qtdDd |D }|s|r|dkrt } D ]:\}}| drq| dE|kr||dE  |d< q|D ]D}| d}|sdtdF| ||krztdG| || |d< qD|D ]L\}
} }t|ttfrć fdHd|D |
|< n | d  |
|< qt }|r|D ],}
|
d |kr||
d  |
d< dI|
d< q|D ]"}|}
|
ddJi ||
 q d5|dKS )La)  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 superflous keys from the network_config yaml.
    Nr   typemac_addresssubnetsparamsZmtuaddressZnetmaskZ	broadcastZmetricZgatewayZpointopointZscopedns_nameserversZ
dns_searchZroutes)physicalsubnetlinksnetworksserviceszbond%dr   c                 3   s&   | ]\}}| d  kr||fV  qdS )r   Nr   rE   krF   
valid_keysr   r   	<genexpr>P  s     z#convert_net_json.<locals>.<genexpr>Zethernet_mac_addressid)r   macr   r   c                    s    g | ]}|d   d kr|qS )linkr   r   )rE   r5   )r   r   r   rG   f  s      z$convert_net_json.<locals>.<listcomp>c                 3   s&   | ]\}}| d  kr||fV  qdS )r   Nr   r   r   r   r   r   g  s     Z	ipv4_dhcpZdhcp4	ipv6_dhcpZdhcp6)Z
ipv6_slaaczipv6_dhcpv6-statelessipv6_dhcpv6-stateful)ipv4staticr   Z
ip_address)r   r   )ipv6static6z	accept-raFr   c                 S   s"   g | ]}| d dkr|d qS )r   Zdnsr   r   )rE   servicer   r   r   rG     s   )r   r   Tr   r   )bondZ
bond_linksr   r"   Zbond_interfacesz%s)r   r   )Zvlanz%s.%sZ	vlan_linkvlan_idZ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|kr|qS )r   r   r   r   r{   r   r   r   rG     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   )rE   target)fmtlink_id_infor   r   rG     s    Z
infinibandZ
nameserver)r$   config)r   rc   r   lowerupdater3   r)   r   r   KNOWN_PHYSICAL_TYPESr.   Zwarningr   Zget_interfaces_by_macrg   
isinstancerJ   tupleZget_ib_hwaddrs_by_interface)Znetwork_jsonZ
known_macsr   r   r   Zlink_updatesZbond_name_fmtZbond_numberr   r   ZcfgZlink_mac_addrZcurinfoZnetworkr   r   r   r   rF   Z	link_namer   Z
need_namesZ_link_idinfor|   r   r   ZtargetsZib_known_hwaddrsr   r   )r   r   r   r   r   convert_net_json  s<   	








r   )NN)*rq   rf   r   ra   r*   Z	cloudinitr   Zloggingr   r   r   r   r   Zcloudinit.sourcesr   Zcloudinit.sources.helpersr	   Z	getLoggerr   r.   rX   r   rj   rL   Z	OS_FOLSOMZ
OS_GRIZZLYZ	OS_HAVANAZ
OS_LIBERTYZOS_NEWTON_ONEZOS_NEWTON_TWOZOS_OCATAZOS_ROCKYrK   r   re   r   r   ABCMetar7   rt   r   r   r   r   r   r   <module>	   sP   

L Eo: