o x[hm@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_configcC|SNxr r E/usr/lib/python3/dist-packages/cloudinit/sources/helpers/openstack.pyrmeta_jsauthorized_keyscCr r r r r r rrr)zetc/network/interfaceszmeta.jszroot/.ssh/authorized_keys))zlocal-hostnamehostnameF) instance-iduuidTlatestz 2012-08-10z 2013-04-04z 2013-10-17z 2015-10-15z 2016-06-30z 2016-10-06z 2017-02-22z 2018-08-27) Nbgpovsbridge cascadingdvsethernethw_vebhypervovsphytap vhostuservifc@s eZdZdS) NonReadableN)__name__ __module__ __qualname__r r r rr%Qsr%c@s4eZdZddZddZddZddZd d Zd S) SourceMixincCs>|jsdS|jdi}|D] \}}||kr|SqdS)Nzblock-device-mapping) ec2_metadatagetitems)selfnamebdment_namedevicer r r_ec2_name_to_deviceVszSourceMixin._ec2_name_to_devicecCs$d}|jdkr d}t|j|S)N public_keys public-keys)versionrnormalize_pubkey_datametadatar+)r-r.r r rget_public_ssh_keys_s zSourceMixin.get_public_ssh_keyscCsVd}zd|}|dkrd|}t|}|r|d}W|SW|Stjy*Y|Sw)NzLABEL=%sswapzTYPE=%sr)rfind_devs_withrProcessExecutionError)r-r.r1criteria dev_entriesr r r_os_name_to_devicees  zSourceMixin._os_name_to_devicecCsV|sdS|ds d|}tj|r|S|tj|}|r)td|||SdS)N/z/dev/%szRemapped device name %s => %s) startswithospathexists _remap_devicebasenameLOGdebug)r-r1remappedr r r_validate_device_namers  z!SourceMixin._validate_device_namecCs|sdS|g}|dkr|dd|dkr|dd}td||D]}||}||}|r4nq$|sPtd||D]}||}||}|rOnq?|sTdStd|||S)Nrootramiz(Using ec2 style lookup to find device %sz.Using openstack style lookup to find device %szMapped %s to device %s)insertappendrGrHr2rJr?)r-r.namesr1nr r rdevice_name_to_devices6        z!SourceMixin.device_name_to_deviceN)r&r'r(r2r9r?rJrQr r r rr)Us   r)c@sheZdZddZejddZejdddZejdd Zejd d Z d d Z dddZ ddZ dS) BaseReadercCs ||_dSr ) base_pathr-rSr r r__init__s zBaseReader.__init__cGdSr r r-baseadd_onsr r r _path_joinzBaseReader._path_joinFcCrVr r r-rCdecoder r r _path_readr[zBaseReader._path_readcCrVr r r-r r r_fetch_available_versionsr[z$BaseReader._fetch_available_versionscCrVr r r_r r r_read_ec2_metadatar[zBaseReader._read_ec2_metadatac Csz|}Wnty"}ztd|j|g}WYd}~nd}~wwddtttD}t}|D] }||vr9q2|}td|||S)Nz4Unable to read openstack versions from %s due to: %scSsg|]}|qSr r ).0vr r r sz4BaseReader._find_working_version..zSelected version '%s' from %s) r` ExceptionrGrHrSreversedlist OS_VERSIONS OS_LATEST)r-versions_availablee supportedselected_versionpotential_versionr r r_find_working_versions0  z BaseReader._find_working_versioncCs^|ddd}|d}dd|D}|std||j|jdg|R}|j||dS) N content_pathrr@cSsg|]}t|r|qSr )len)rbpr r rrdsz1BaseReader._read_content_path..z!Item %s has no valid content path openstackr])r+lstripsplitrrZrSr^)r-itemr]rC path_pieces valid_piecesr r r_read_content_paths  zBaseReader._read_content_pathc stjtjtttfdfdd}ddd}|}|D]o\}\}}} j |}d}d}z |}Wn#t y]} z|sLt d || nt d || WYd} ~ nd} ~ wwd }|rj|sjtd ||r|rz||}Wnty} z td || f| d} ~ ww|r|||<q!|d} d| vr| d} z t| | d<Wnttfy} ztd| | d} ~ wwi} | dg} | D])}d|vrq|d}z || |<Wqty} z td|| f| d} ~ ww| |d<| dd}|rz j|d d}||d<Wnt y} ztd| | d} ~ wwz | dd|d<Wn ty3Ynw|d<tD] \}}}|rO|| vrOtd||| 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. ) root_typescsi}d|ddtjf|d<d|ddddf|d <d|d df|d <d|d df|d <d|ddf|d<|S)Nrszmeta_data.jsonTr8 user_dataFcSr r r r r r rrrz7BaseReader.read_v2..datafiles..userdatazvendor_data.json vendordatazvendor_data2.json vendordata2znetwork_data.json networkdata)rZr load_json)r6filesload_json_anytyper-r r datafiless,     z%BaseReader.read_v2..datafilesr)r}r6NFz*Failed reading optional path %s due to: %sz+Failed reading mandatory path %s due to: %sTzMissing mandatory path: %sFailed to process path %s: %sr8 random_seedz.Badly formatted metadata random_seed entry: %srrCz#Failed to read provided file %s: %sr rtz(Failed to read network configuration: %smetadsmodez ec2-metadatazNo '%s' entry in metadata) functoolspartialrrdictrgstrror,rZrSr^IOErrorrGrHr%rerbase64 b64decode ValueError TypeErrorr+rzKeyErrorra KEY_COPIES)r-rresultsdatar.rCrequired translatorfoundrkr8rrmetadata_filesrwnet_itemcontent target_key source_key is_requiredr rrread_v2s !             zBaseReader.read_v2NF) r&r'r(rUabcabstractmethodrZr^r`rarorzrr r r rrRs      rR) metaclasscsFeZdZfddZddZdddZdd Zd d Zd d ZZ S)ConfigDriveReadercstt||d|_dSr )superrrU _versionsrT __class__r rrUfs zConfigDriveReader.__init__cGs|gt|}tjj|Sr )rgrBrCjoin)r-rXrY componentsr r rrZjs zConfigDriveReader._path_joinFcCs|rt|St|Sr )rload_text_fileload_binary_filer\r r rr^ns  zConfigDriveReader._path_readcs@|jdur||jdfddtD}t||_|jS)Nrscs$g|]}tjtjr|qSr )rBrCisdirrrbdrCr rrdxs z?ConfigDriveReader._fetch_available_versions..)rrZrSrBlistdirsorted)r-rr rrr`us   z+ConfigDriveReader._fetch_available_versionsc Cs`||jddd}tj|siSz t||WSty/}z t d||f|d}~ww)Nrrzmeta-data.jsonr) rZrSrBrCrDrrr^rer)r-rCrkr r rras   z$ConfigDriveReader._read_ec2_metadatac Cszi}tD]}||j|}tj|r|||<q|s#td|ji}tD]O\}\}}}||vrq||}z| |}Wnt yR} zt d|| d} ~ wwz||||<Wq)t yp} z t d|| f| d} ~ wwt |||<q)|d} |d} | d| } | r| } dd | D|d<d | vr| 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. z%s: no files foundzFailed to read: %sNrrrr5cSs"g|] }t|r|ds|qS)#)rqrA)rbliner r rrdsz-ConfigDriveReader.read_v1..rr4)r6r8rz user-datarr}r)FILES_V1keysrZrSrBrCrDr%r,r^rrrecopydeepcopyr+ splitlines)r-rr.rCmdkeyrdefaultcontentsrkkeydatarlinesrr r rread_v1s^       zConfigDriveReader.read_v1r) r&r'r(rUrZr^r`rar __classcell__r r rrres   rcs@eZdZdfdd ZddZddd Zd d Zd d ZZS)MetadataReaderNcs4tt||||_t||_t||_d|_dSr ) rrrU ssl_detailsfloattimeoutintretriesr)r-base_urlrrrrr rrUs    zMetadataReader.__init__cCsb|jdur|jSg}||jd}|j|dd}|D]}|}|s%q||q||_|jS)NrsTrt)rrZrSr^rstriprN)r-r version_pathrrr r rr`s   z(MetadataReader._fetch_available_versionsFcCs6dd}tj||j|j|j|d}|r|jS|jS)Nc SsFzt|j}|dkr|dvrWdSWdSWdSttfy"YdSw)Ni)iiiiiiFT)rcoderr)causerr r rshould_retry_cbs z2MetadataReader._path_read..should_retry_cb)rrr exception_cb)rreadurlrrrrr])r-rCr]rresponser r rr^s  zMetadataReader._path_readcGstj|g|RSr )r combine_urlrWr r rrZszMetadataReader._path_joincCstj|j|j|jdS)N)rrr)rget_instance_metadatarrrr_r r rra s z!MetadataReader._read_ec2_metadata)Nrrr) r&r'r(rUr`r^rZrarr r rrrs  rc s|durdSgdgdgdd|dg}|dg}|dg}g}id }d }g}|D]g} tfd d D} d vrLd | d <d} dr`d} | d<| d | ddd} fdd|DD]} tfdd | D}fdd| dgD}|r|d|i| ddkr|ddinH| ddkr|ddin:| ddvr|d| din*| ddvr|d| ddn| dd vr| d!d"i|d#| ddd$d| dgD}| dgD]}|dd%krq|d&|vrq||d&q|r(||d'<| dd(vr6| d!d)i| dd*krAd)|d*<| dd+krLd)|d+<| |qw| d,| idd-vri}| rl| d.| iD]$\}}|d/kr{qp|d0rd1|d2d3d4}|||iqp||}|d37}|| d5d6t d/f| ||d7|| d <nZdd8vrd9d:d;f}| |d;d<d=|| d:d6d:f|| d d>d;d:f| d<|d?ndt vr t d@d| dA| dB|| | | d<q0dCd|D}|s+|r|dur4t}D]\}}|d rDq8|dD|vrT||dD|d <q8|D]/}|d.}|shtdE|||vrtt}||vrtdF||||d <qX|D]'\} }}t|ttfrfdGd|D| |<q|d | |<qt}|r|D]} | d |vr|| d | d.<dH| d<q|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)r.type mac_addresssubnetsparamsmtu) raddressnetmask broadcastmetricgateway pointopointscopedns_nameservers dns_search)network destinationrrr)physicalsubnetrouteslinksnetworksserviceszbond%drc3(|]\}}|dvr||fVqdS)rNr rbkrc valid_keysr r Tz#convert_net_json..r.ethernet_mac_addressidr)r.macrrcs g|] }|ddkr|qS)linkrr )rbrP)rr rrdjs z$convert_net_json..c3r)rNr rrr rrkrcs&g|]}tfdd|DqS)c3r)rNr rrr rrrs z.convert_net_json...)rr,)rbrouterr rrdqs  r ipv4_dhcpdhcp4 ipv6_dhcpdhcp6) ipv6_slaaczipv6_dhcpv6-statelessipv6_dhcpv6-stateful)ipv4staticr ip_address)rr)ipv6static6z accept-raFrcSs4g|]}|dgD] }|ddkr |dq qS)rrdnsrr+)rbrservicer r rrds rrr)rrTrrr)bondr bond_linksrzbond-{}bond_r4bond_interfacesz%s)rr.)vlanz%s.%s vlan_linkvlan_idvlan_mac_address)r.r rz%%s.%s)rr.z9Unknown network_data link type (%s); treating as physicalr)rrcSs&g|]}|ddkrd|vr|qS)rrr.rrr r rrds rz#No mac_address or name entry for %sz"Unable to find a system nic for %scsg|] }|dqS)r.r )rbtarget)fmt link_id_infor rrds infiniband nameserver)r6config)r+rr,lowerupdaterNrAformatrvrrKNOWN_PHYSICAL_TYPESrGwarningrget_interfaces_by_macrrudevadm_settle isinstancergtupleget_ib_hwaddrs_by_interface) network_json known_macsrrr link_updates bond_name_fmt bond_numberrrcfg link_mac_addrcurinforrrrrrrrctranslated_key link_namer. need_names_link_idinforrrtargetsib_known_hwaddrsr )rrrrrconvert_net_jsons@                                    r.)NN))rrrrloggingrB cloudinitrrrrrcloudinit.sourcesrcloudinit.sources.helpersr getLoggerr&rGrrrri OS_FOLSOM OS_GRIZZLY OS_HAVANA OS_LIBERTY OS_NEWTON_ONE OS_NEWTON_TWOOS_OCATAOS_ROCKYrhrrr%r)ABCMetarRrrr.r r r rsR       LEs: