a 'Dgl@s6ddlZddlZddlZddlZddlZddlZddlmZmZm Z m Z m Z ddl m Z ddlmZeeZddddfd e jifd d ddfd Zd ZdZdZdZdZdZdZdZdZdZeeeeeeeefZdZ Gddde!Z"GdddZ#Gdddej$dZ%Gdd d e%Z&Gd!d"d"e%Z'd%d#d$Z(dS)&N)netsourcessubp url_helperutil)BrokenMetadata)ec2network_configcCs|SNxr r G/usr/lib/python3.9/site-packages/cloudinit/sources/helpers/openstack.pyrmeta_jsauthorized_keyscCs|Sr r r r r rrr)zetc/network/interfaceszmeta.jszroot/.ssh/authorized_keys))zlocal-hostnamehostnameF) instance-idZuuidTlatestz 2012-08-10z 2013-04-04z 2013-10-17z 2015-10-15z 2016-06-30z 2016-10-06z 2017-02-22z 2018-08-27) NZbgpovsZbridgeZ cascadingZdvsZethernetZhw_vebZhypervZovsZphyZtapZ vhostuserZvifc@s eZdZdS) NonReadableN)__name__ __module__ __qualname__r r r rrQsrc@s4eZdZddZddZddZddZd d Zd S) SourceMixincCs>|js dS|jdi}|D]\}}||kr |Sq dS)Nzblock-device-mapping)Z ec2_metadatagetitems)selfnameZbdmZent_namedevicer r r_ec2_name_to_deviceVs zSourceMixin._ec2_name_to_devicecCs$d}|jdkrd}t|j|S)NZ public_keys public-keys)versionrZnormalize_pubkey_datametadatar)rrr r rget_public_ssh_keys_s zSourceMixin.get_public_ssh_keyscCsPd}z2d|}|dkrd|}t|}|r4|d}WntjyJYn0|S)NzLABEL=%sZswapzTYPE=%sr)rZfind_devs_withrZProcessExecutionError)rrr ZcriteriaZ dev_entriesr r r_os_name_to_devicees  zSourceMixin._os_name_to_devicecCsV|sdS|dsd|}tj|r*|S|tj|}|rRtd|||SdS)N/z/dev/%szRemapped device name %s => %s) startswithospathexistsZ _remap_devicebasenameLOGdebug)rr Zremappedr r r_validate_device_namers  z!SourceMixin._validate_device_namecCs|sdS|g}|dkr"|dd|dkr4|dd}td||D] }||}||}|rHqjqH|std||D] }||}||}|r~qq~|sdStd|||SdS)NrootrZamiz(Using ec2 style lookup to find device %sz.Using openstack style lookup to find device %szMapped %s to device %s)insertappendr.r/r!r0r')rrnamesr nr r rdevice_name_to_devices2        z!SourceMixin.device_name_to_deviceN)rrrr!r&r'r0r6r r r rrUs   rc@sheZdZddZejddZejdddZejdd Zejd d Z d d Z dddZ ddZ dS) BaseReadercCs ||_dSr ) base_pathrr8r r r__init__szBaseReader.__init__cGsdSr r rbaseadd_onsr r r _path_joinszBaseReader._path_joinFcCsdSr r rr+decoder r r _path_readszBaseReader._path_readcCsdSr r rr r r_fetch_available_versionssz$BaseReader._fetch_available_versionscCsdSr r rBr r r_read_ec2_metadataszBaseReader._read_ec2_metadatac Csz |}Wn8tyD}z td|j|g}WYd}~n d}~00ddtttD}t}|D]}||vrrqd|}q|qdtd|||S)Nz4Unable to read openstack versions from %s due to: %scSsg|]}|qSr r ).0vr r r rz4BaseReader._find_working_version..zSelected version '%s' from %s) rC Exceptionr.r/r8reversedlist OS_VERSIONS OS_LATEST)rZversions_availableeZ supportedZselected_versionZpotential_versionr r r_find_working_versions, z BaseReader._find_working_versioncCs^|ddd}|d}dd|D}|s:td||j|jdg|R}|j||dS) NZ content_pathrr(cSsg|]}t|r|qSr )len)rEpr r rrGrz1BaseReader._read_content_path..z!Item %s has no valid content path openstackr@)rlstripsplitrr>r8rA)ritemr@r+Z path_piecesZ valid_piecesr r r_read_content_paths  zBaseReader._read_content_pathc stjtjtttfdfdd}ddd}|}|D]\}\}}} j |}d}d}z |}WnFt y} z.|st d || nt d || WYd} ~ nd} ~ 00d }|r|std ||r&|r&z ||}Wn8ty$} ztd || f| WYd} ~ n d} ~ 00|rB|||<qB|d} d| vr| d} zt| | d<Wn8ttfy} ztd| | WYd} ~ n d} ~ 00i} | dg} | D]h}d|vrq|d}z|| |<Wn8ty} ztd|| f| WYd} ~ n d} ~ 00q| |d<| dd}|rzj|d d}||d<Wn4t y} ztd| | WYd} ~ n d} ~ 00z| dd|d<WntyYn0|d<tD]@\}}}|r|| vrtd||| vr| || |<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_typescsi}d|ddtjf|d<d|ddddf|d <d|d df|d <d|d df|d <d|ddf|d<|S)NrQzmeta_data.jsonTr%Z user_dataFcSs|Sr r r r r rrrz7BaseReader.read_v2..datafiles..userdatazvendor_data.jsonZ vendordatazvendor_data2.jsonZ vendordata2znetwork_data.jsonZ networkdata)r>r load_json)r$filesZload_json_anytyperr r datafiless,     z%BaseReader.read_v2..datafilesr)rWr$NFz*Failed reading optional path %s due to: %sz+Failed reading mandatory path %s due to: %sTzMissing mandatory path: %sFailed to process path %s: %sr% random_seedz.Badly formatted metadata random_seed entry: %srYr+z#Failed to read provided file %s: %sr rRz(Failed to read network configuration: %smetadsmodez ec2-metadatazNo '%s' entry in metadata) functoolspartialrrXdictrJstrrNrr>r8rAIOErrorr.r/rrHrbase64Z b64decode ValueError TypeErrorrrVKeyErrorrD KEY_COPIES)rr[resultsdatarr+required translatorfoundrMr%r^rYZmetadata_filesrUZnet_itemcontentZ target_keyZ source_keyZ is_requiredr rZrread_v2s  !               zBaseReader.read_v2N)F)F) rrrr:abcabstractmethodr>rArCrDrNrVrqr r r rr7s     r7) metaclasscsFeZdZfddZddZdddZdd Zd d Zd d ZZ S)ConfigDriveReadercstt||d|_dSr )superrur: _versionsr9 __class__r rr:fszConfigDriveReader.__init__cGs|gt|}tjj|Sr )rJr*r+join)rr<r= componentsr r rr>jszConfigDriveReader._path_joinFcCs|rt|St|Sr )rZload_text_fileZload_binary_filer?r r rrAns zConfigDriveReader._path_readcs@|jdur:||jdfddtD}t||_|jS)NrQcs$g|]}tjtjr|qSr )r*r+isdirrzrEdr+r rrGxsz?ConfigDriveReader._fetch_available_versions..)rwr>r8r*listdirsorted)rror rrrCus   z+ConfigDriveReader._fetch_available_versionsc Csp||jddd}tj|s"iSzt||WStyj}zt d||f|WYd}~n d}~00dS)Nrrzmeta-data.jsonr]) r>r8r*r+r,rrXrArHr)rr+rMr r rrDs   z$ConfigDriveReader._read_ec2_metadatac Csi}tD]&}||j|}tj|r |||<q t|dkrNtd|ji}t D]\}\}}}||vr||}z| |}Wn2t y} zt d|| WYd} ~ n d} ~ 00z||||<Wn8t y} zt d|| f| WYd} ~ n d} ~ 00qZt|||<qZ|d} |d} | d| } | rT| } d d | D|d<d | vrj| d |d <d |d } d| vr| d| d<| dd| 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. rz%s: no files foundzFailed to read: %sNr]rrr#cSs"g|]}t|r|ds|qS)#)rOr))rEliner r rrGsz-ConfigDriveReader.read_v1..rr")r$r%r`z user-datarrWrY)FILES_V1keysr>r8r*r+r,rOrrrArerrHcopydeepcopyr splitlines)rrorr+ZmdkeyrndefaultcontentsrMZkeydatarlinesrkr r rread_v1sT     $       zConfigDriveReader.read_v1)F) rrrr:r>rArCrDr __classcell__r r rxrrues    rucs@eZdZdfdd ZddZddd Zd d Zd d ZZS)MetadataReaderNcs4tt||||_t||_t||_d|_dSr ) rvrr: ssl_detailsfloattimeoutintretriesrw)rZbase_urlrrrrxr rr:s   zMetadataReader.__init__cCsb|jdur|jSg}||jd}|j|dd}|D]}|}|sJq8||q8||_|jS)NrQTrR)rwr>r8rArstripr3)rroZ version_pathrprr r rrCs   z(MetadataReader._fetch_available_versionsFcCs:dd}tj||j|j|j|d}|r0|jS|jSdS)Nc Ss8zt|j}|dkrWdSWnttfy2Yn0dS)NiFT)rcoderhrg)Z _request_argscauserr r rshould_retry_cbs  z2MetadataReader._path_read..should_retry_cb)rrrZ exception_cb)rZreadurlrrrrr@)rr+r@rZresponser r rrAs  zMetadataReader._path_readcGstj|g|RSr )rZ combine_urlr;r r rr>szMetadataReader._path_joincCstj|j|j|jdS)N)rrr)rZget_instance_metadatarrrrBr r rrD s z!MetadataReader._read_ec2_metadata)Nrr)F) rrrr:rCrAr>rDrr r rxrrs  rc s|dur dSgdgdgdd|dg}|dg}|dg}g}id }d }g}|D]g} tfd d D} d vrd | d <d} drd} | d<| d | ddd} fdd|DD]} tfdd | D}fdd| dgD}|r<|d|i| ddkrZ|ddin| ddkrx|ddinz| ddvr|d| dinX| ddvr|d| ddn2| dd vr| d!d"i|d#| ddd$d| dgD}| dgD]:}|dd%kr,q|d&|vr>q||d&q|r^||d'<| dd(vrz| d!d)i| dd*krd)|d*<| dd+krd)|d+<| |q| d,| idd-vri}| r| d.| iD]J\}}|d/krqn0|d0rd1|d2d3d4}|||iq||}|d37}|| d5d6t d/f| ||d7|| d <ndd8vrd9d:d;f}| |d;d<|| d:d6d:f|| d d=d;d:f| d>|d?n.dt vrt d@d| dA| dB|| | | d<q`dCd|D}|s`|rR|durrt}D]:\}}|d rqz|dD|vrz||dD|d <qz|D]D}|d.}|stdE|||vrtdF||||d <q|D]L\} }}t|ttfr:fdGd|D| |<n|d | |<qt}|r|D],} | d |vrd|| d | d.<dH| d<qd|D](}t |} | ddIi|| qd3|dJS)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)rtype mac_addresssubnetsparamsZmtu) raddressnetmask broadcastmetricgatewayZ pointopointZscopedns_nameserversZ dns_search)networkZ destinationrrr)physicalsubnetrouteslinksnetworksserviceszbond%drc3s&|]\}}|dvr||fVqdS)rNr rEkrF valid_keysr r Tsz#convert_net_json..rZethernet_mac_addressidr)rmacrrcs g|]}|ddkr|qS)linkrr )rEr5)rr rrGjrz$convert_net_json..c3s&|]\}}|dvr||fVqdS)rNr rrr rrkscs&g|]}tfdd|DqS)c3s&|]\}}|dvr||fVqdS)rNr rrr rrrs z.convert_net_json...)rcr)rErouterr rrGqs rZ ipv4_dhcpZdhcp4 ipv6_dhcpZdhcp6)Z ipv6_slaaczipv6_dhcpv6-statelessipv6_dhcpv6-stateful)ipv4staticr ip_address)rr)ipv6static6z accept-raFrcSs4g|],}|dgD]}|ddkr|dqqS)rrdnsrr)rErservicer r rrGsrrr)rrTrrr)bondrZ bond_linksrzbond-{}Zbond_r"Zbond_interfacesz%s)rr)Zvlanz%s.%sZ vlan_linkvlan_id)rrz%%s.%sZvlan_mac_address)rrz9Unknown network_data link type (%s); treating as physicalr)rrcSs&g|]}|ddkrd|vr|qS)rrrrr}r r rrGsrz#No mac_address or name entry for %sz"Unable to find a system nic for %scsg|]}|dqS)rr )rEtarget)fmt link_id_infor rrG sZ infinibandZ nameserver)r$config)rrcrlowerupdater3r)formatrTrrKNOWN_PHYSICAL_TYPESr.ZwarningrZget_interfaces_by_macrg isinstancerJtupleZget_ib_hwaddrs_by_interface) Z network_jsonZ known_macsrrrZ link_updatesZ bond_name_fmtZ bond_numberrrZcfgZ link_mac_addrZcurinforrrrrrrrFZtranslated_keyZ link_namerZ need_namesZ_link_idinfor~rrtargetsZib_known_hwaddrsr )rrrrrconvert_net_jsons2                                r)NN))rrrfrraZloggingr*Z cloudinitrrrrrZcloudinit.sourcesrZcloudinit.sources.helpersrZ getLoggerrr.rXrrjrLZ OS_FOLSOMZ OS_GRIZZLYZ OS_HAVANAZ OS_LIBERTYZ OS_NEWTON_ONEZ OS_NEWTON_TWOZOS_OCATAZOS_ROCKYrKrrerrABCMetar7rurrr r r r sP       LEs: