a '¡DgÅRã@s ddlZddlZddlZddlZddlZddlmZddlmZm Z m Z ddl m Z m Z mZmZddlmZmZmZmZmZmZddlmZmZdZdZe e¡Zd d „Ze e ed œd d „Z!dd„Z"ddd„Z#e$e%dœdd„Z&e$e$e%dœdd„Z'e$e$dœdd„Z(Gdd„dej)ƒZ)d dd„Z*dS)!éN)ÚSpooledTemporaryFile)ÚCallableÚListÚOptional)ÚfeaturesÚsafeyamlÚsubpÚutil)ÚIPV6_DYNAMIC_TYPESÚ SYS_CLASS_NETÚget_devicelistÚrendererÚshould_add_gateway_onlink_flagÚsubnet_is_ipv6)ÚNET_CONFIG_TO_V2Ú NetworkStatez/etc/netplan/50-cloud-init.yamls4# This is the initial network config. # It can be overwritten by cloud-init or console-conf. network: version: 2 ethernets: all-en: match: name: "en*" dhcp4: true all-eth: match: name: "eth*" dhcp4: true cst‡fdd„| ¡DƒƒS)Nc3s$|]\}}| ˆ¡r||fVqdS)N)Ú startswith)Ú.0ÚkeyÚvalue©Úmatch©ú9/usr/lib/python3.9/site-packages/cloudinit/net/netplan.pyÚ ,s þz,_get_params_dict_by_match..)ÚdictÚitems)ÚconfigrrrrÚ_get_params_dict_by_match+s þr)rÚentryrc Csd$dd„}g}g}g}g}| dg¡} | dur2g} | D]¸} |  d¡} |  d¡rp| dkr`| d7} | | d i¡q6| tvrˆ| d d i¡q6| d vr6d |  d ¡} d| vr¸| d|  d¡7} |  d¡r|  d¡ddœ} t| d| ƒrþt d| d| ¡d | d<| | ¡d| vr&|||  dg¡ƒ7}d| vrD|||  dg¡ƒ7}d| vr€d}t| ƒrld|ƒvrld}| ||  d¡i¡|  dg¡D]X}d| d¡| d¡f}| d¡|dœ} d|vrØ|  d| dd¡i¡| | ¡qŒ| | ¡q6d|vr<| d¡}|r0|d|kr0t  d||d|¡n |d|d<t |ƒdkrX| d |i¡t |ƒdkrt| d|i¡t |ƒdkr˜d |i}| d!|i¡t |ƒdkrÎ| d!i¡}| d"|i¡| d!|i¡d#|vr|d#dur| d#t   | d#¡¡i¡dS)%aÖThis method parse a cloudinit.net.network_state dictionary (config) and maps netstate keys/values into a dictionary (entry) to represent netplan yaml. (config v1 -> netplan) An example config dictionary might look like: {'mac_address': '52:54:00:12:34:00', 'name': 'interface0', 'subnets': [ {'address': '192.168.1.2/24', 'mtu': 1501, 'type': 'static'}, {'address': '2001:4800:78ff:1b:be76:4eff:fe06:1000", 'mtu': 1480, 'netmask': 64, 'type': 'static'}], 'type: physical', 'accept-ra': 'true' } An entry dictionary looks like: {'set-name': 'interface0', 'match': {'macaddress': '52:54:00:12:34:00'}, 'mtu': 1501} After modification returns {'set-name': 'interface0', 'match': {'macaddress': '52:54:00:12:34:00'}, 'mtu': 1501, 'address': ['192.168.1.2/24', '2001:4800:78ff:1b:be76:4eff:fe06:1000"], 'ipv6-mtu': 1480} ú cSs.|rt|tƒs|S||vr$| |¡S|gSdS)zT Helper to convert strings to list of strings, handle single string N)Ú isinstanceÚstrÚsplit)ÚobjÚtokenrrrÚ_listifyXs  ÿz$_extract_addresses.._listifyÚsubnetsNÚtypeZdhcpÚ4TZdhcp6)ZstaticZstatic6z%sÚaddressÚprefixz/%dZgatewayÚdefault)ZviaÚtozAGateway %s is not contained within subnet %s, adding on-link flagzon-linkÚdns_nameserversZ dns_searchZmtuzipv6-mtuÚroutesz%s/%sÚnetworkZmetricédzZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.rÚ addressesÚ nameserversÚsearchz accept-ra)r ) ÚgetrÚupdater rÚLOGÚdebugÚappendrÚwarningÚlenr Zis_true)rrÚifnamerr&r2r/r3Ú searchdomainsr'ZsubnetZsn_typeÚaddrZ new_routeZmtukeyZrouteZto_netZ entry_mtuÚnsrrrÚ_extract_addresses3s’%      þü    þ    û  r@cs8t‡fdd„| ¡Dƒƒ}t|ƒdkr4| d|i¡dS)Ncs$g|]\}}| dd¡ˆkr|‘qS)z bond-masterN)r5)rÚnameÚcfg©Ú bond_masterrrÚ »sþz0_extract_bond_slaves_by_name..rÚ interfaces)Úsortedrr;r6)rFrrDZbond_slave_namesrrCrÚ_extract_bond_slaves_by_name¹s þÿ rHcs~t ˆd¡}tj |¡sdSt |¡}|tkr2dS‡fdd„dDƒ}dd„|Dƒ}t  d||¡|g|D]}t  |¡qjdS)Nz etc/netplan/00-snapd-config.yamlcsg|]}t ˆ|¡‘qSr)rÚ target_path©rÚf©ÚtargetrrrEÏsÿz"_clean_default..)z-run/systemd/network/10-netplan-all-en.networkz.run/systemd/network/10-netplan-all-eth.networkz#run/systemd/generator/netplan.stampcSsg|]}tj |¡r|‘qSr)ÚosÚpathÚisfilerJrrrrE×óz9removing known config '%s' and derived existing files: %s) rrIrNrOrPr Zload_binary_fileÚKNOWN_SNAPD_CONFIGr7r8Úunlink)rMZtpathÚcontentZderivedÚexistingrKrrLrÚ_clean_defaultÅs"    þýrV)Únet_config_contentÚreturnc Cszddlm}ddlm}Wn ty<t dt¡YdS0z€tddb}|  |¡|  ¡|  dt j ¡|ƒ}| |¡|ƒ}| |¡| tj t¡¡Wdƒn1s²0YWn6tyô}zt d t|¡WYd}~dSd}~00t d ¡d S) adUse netplan.State._write_yaml_file to write netplan config Where netplan python API exists, prefer to use of the private _write_yaml_file to ensure proper permissions and file locations are chosen by the netplan python bindings in the environment. By calling the netplan API, allow netplan versions to change behavior related to file permissions and treatment of sensitive configuration under the API call to _write_yaml_file. In future netplan releases, security-sensitive config may be written to separate file or directory paths than world-readable configuration parts. r)ÚParser)ÚStatez.No netplan python module. Fallback to write %sFÚw©ÚmodeNzUUnable to render network config using netplan python module. Fallback to write %s. %sz0Rendered netplan config using netplan python APIT)Znetplan.parserrYZ netplan.staterZÚ ImportErrorr7r8ÚCLOUDINIT_NETPLAN_FILErÚwriteÚflushÚseekÚioÚSEEK_SETÚ load_yamlZimport_parser_resultsZ_write_yaml_filerNrOÚbasenameÚ Exceptionr:)rWrYrZrKÚparserZstate_output_fileÚerrrÚnetplan_api_write_yaml_fileâs<  þ     ÿ&ü rj)Úcfg_filerTrXcCs.tj |¡sdSt t |¡¡}|t |¡kS)z|j nd}|  d¡sT|d7}||}t ||ƒ}t |ƒsxt||ƒ|jrˆt|d|j|j|d|j|jddS)NÚÚ rL©ÚrunÚconfig_changed)rƒ)rNrOÚjoinrrIrrr Z ensure_dirÚdirnameÚ_render_contentrsÚendswithrmrjrnrtrVÚ_netplan_generateruÚ_net_setup_link)rwr~rrMZfpnplanrTÚheaderZnetplan_config_changedrrrÚrender_network_stateHs      ÿzRenderer.render_network_stater‚cCs8|st d¡dS|s$t d¡dStj|jdddS)Nz"netplan generate postcmds disabledzEskipping call to `netplan generate`. reason: identical netplan configTry)r7r8rÚNETPLAN_GENERATE)rwrƒr„rrrr‰is ÿzRenderer._netplan_generateFc Csº|st d¡dSdt ¡vr,t d¡dSgd¢}tdƒD]n}z>tƒD],}tj t |¡rHt j |t |gddqHWq¶Wq<t j y¨}z|}WYd}~q¯rQz*Renderer._render_content..r(Zphysicalr)úset-namerZ mac_addressZ macaddressr™Úbond)Zbond_zbond-r’ú-rÚ parametersz bond-slavesZnoneÚbridgeÚ bridge_portszInvalid config. The keyz'bridge_ports' is required in Ú.Zbridge_)z path-costz port-priorityÚvlanZvlan_idzvlan-raw-device)ÚidÚlink)r2r4r3r2cSs0|r,tj||idddd}t |d¡}|gSgS)NFT)r”r•Znoaliasz )rÚdumpsÚtextwrapÚindent)rAÚsectionÚdumpZtxtrrrÚ_render_section sü z1Renderer._render_content.._render_sectionznetwork: version: 2 Ú ethernetsÚwifisÚbondsÚbridgesÚvlansr€)Úversionr7r8rr£rZ_network_stater5r.Zdns_searchdomainsZiter_interfacesrÚfilterrÚlowerr@rr6rrÚreplacer;rHr:rGÚcopyr#Úintr9r…)+rwr~r©rªr¬r«r­rTrFr3r=rr<ZifcfgZif_typeZethZmacaddrršZ bond_configZ v2_bond_maprZ bond_paramsZparamrZnewnameZslave_interfacesržZportsrZ match_prefixÚparamsZ br_configZ v2_bridge_mapZnewvalueÚvalÚportZportvalr Znscfgr¦Ú_namerBr¨rrrr‡–sØ  ý    þ             þÿ      þ      zRenderer._render_content)N)NN)F)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrzrxrr"rrrrrŒÚboolr‰rŠr‡rrrrro+s üû ! !rocCs2dg}ddg}|D]}tj|||dsdSqdS)Nrpz /usr/sbinz/sbin)r4rMFT)rÚwhich)rMZexpectedr4ÚprrrÚ available6s r¿)N)N)+r²rcZloggingrNr¤ZtempfilerÚtypingrrrZ cloudinitrrrr Z cloudinit.netr r r r rrZcloudinit.net.network_staterrr_rRZ getLoggerr¸r7rrr@rHrVr"r¼rjrmrnror¿rrrrÚs0    4