a 'Dg @s6ddlZddlZddlZddlZddlZddlZddlmZmZm Z m Z m Z ddl m Z mZddlmZeeZdZdZgdZgdZed fd d Zd d ZdddZdddZdddZddZddZddZ ddZ!ddZ"dd Z#d!d"Z$d#d$Z%ej&dd%e'd&d'd(Z(ej&dd%e)d&d)d*Z*e+e'd+d,d-Z,dd.d/Z-d0d1Z.d2d3Z/de'd&d4d5Z0dd6d7Z1dd8d9Z2d:d;Z3dd?Z5d@dAZ6dBdCZ7GdDdEdEe8Z9dFdGZ:e e+d&dHdIZ;e e+d&dJdKZe e+d&dPdQZ?e e+d&dRdSZ@e e+d&dTdUZAe e+d&dVdWZBde eCd&dXdYZDdZd[ZEdd]d^ZFdd`daZGddbdcZHdddeZIdfdgZJeCd&dhdiZKe+e e+djdkdlZLeCd&dmdnZMeCd&dodpZNeCd&dqdrZOeCd&dsdtZPde'e'e'e'e'e'e'e)dudvdwZQedxe e e+e+e+e+fddydzd{ZRd|d}ZSee+d~ddZTe+e'dddZUe+e'dddZVe+e'dddZWe+e'dddZXe+e'dddZYe+e'dddZZe+e+e'dddZ[e+e+e'dddZ\e'd&ddZ]e+d&ddZ^e_d&ddZ`e_d&ddZae+e+e+dddZbGdddecZddS)N)CallableDictListOptionalTuple)subputil)Iproute2z/sys/class/net/Zeth0)dhcp6Z ipv6_slaaczipv6_dhcpv6-statelesszipv6_dhcpv6-stateful) ovs-vsctlz--formatZcsvz --no-headingsz --timeoutZ10z --columnsnamefind interfacez type=internalz([0-9]+)cCsddt||DS)aDSorting for Humans: natural sort order. Can be use as the key to sort functions. This will sort ['eth0', 'ens3', 'ens10', 'ens12', 'ens8', 'ens0'] as ['ens0', 'ens3', 'ens8', 'ens10', 'ens12', 'eth0'] instead of the simple python way which will produce ['ens0', 'ens10', 'ens12', 'ens3', 'ens8', 'eth0'].cSs$g|]}|rt|n|qS)isdigitintlower).0textrr:/usr/lib/python3.9/site-packages/cloudinit/net/__init__.py 2sz$natural_sort_key..)resplit)sZ_nsrerrrnatural_sort_key+s rcCstS)z3Simple function to return the global SYS_CLASS_NET.) SYS_CLASS_NETrrrrget_sys_class_path8srcCst|d|S)N/)rdevnamepathrrr sys_dev_path=sr"c Cst||}zt|}Wnttfy}znt|dd} | tjtjfvrd|durd||WYd}~S| tj fvr|dur||WYd}~SWYd}~n d}~00| }|dur|Sz ||WSt y}z8|dur||WYd}~St d||WYd}~n d}~00dS)Nerrnoz5Found unexpected (not translatable) value '%s' in '%s)r"rZload_text_fileOSErrorIOErrorgetattrr#ENOENTENOTDIREINVALstripKeyErrorLOGdebug) r r! translate on_enoent on_keyerror on_einvalZdev_pathcontentseZe_errnorrr read_sys_netAs4    r4cCsdd}t||||||dS)NcSsdSNFr)r3rrr on_excp_falsegsz(read_sys_net_safe..on_excp_false)r0r/r1r.)r4)ifacefieldr.r6rrrread_sys_net_safefsr9cCs:t||}|durdSz t|WSty4YdS0dSr5)r9r ValueError)r7r8valrrrread_sys_net_intts   r<cCsdddd}t|d|dS)NTF)upunknowndown operstate)r.r9)r r.rrris_up~s rBcCstjt|dS)Nbridgeosr!existsr"r rrr is_bridgesrHcCstjt|dS)NbondingrDrGrrris_bondsrJcCs t|dd}tj|r|SdS)z8Return the master path for devname, or None if no mastermasterr!N)r"rEr!rFrrrr get_masters  rMcCsHt|}|durdStj|d}tj|d}tj|pFtj|S)z@Return a bool indicating if devname's master is a bridge or bondNFrIrC)rMrEr!joinrF)r master_pathZ bonding_pathZ bridge_pathrrrmaster_is_bridge_or_bonds rPcCs,t|}|durdSt|dd}tj|S)z;Return a bool indicating if devname's master is openvswitchNFzupper_ovs-systemrL)rMr"rEr!rF)r rOZovs_pathrrrmaster_is_openvswitchs  rQcCst|ddkS)Ntype32rArGrrris_ib_interfacesrT)maxsize)returncCs ttd}|std|S)zDReturn a bool indicating if Open vSwitch is installed in the system.r z/device/features.rzdevice/features)r4 Exceptionr Zfeaturesrrrget_dev_featuress  rlcCs(t|}|rt|dkrdS|ddkS)zReturn True if VIRTIO_NET_F_STANDBY bit (62) is set. https://github.com/torvalds/linux/blob/ 089cf7f6ecb266b6a4164919a2e69bd2f938374a/ include/uapi/linux/virtio_net.h#L60 @F>1)rllenrkrrrhas_netfail_standby_featuresrqcCs<t|durdS|dur t|}|dkr,dSt|s8dSdS)zA device is a "netfail master" device if: - The device does NOT have the 'master' sysfs attribute - The device driver is 'virtio_net' - The device has the standby feature bit set Return True if all of the above is True. NF virtio_netTrMrdrqrgrrris_netfail_masters rtcCstt|dd}tj|sdS|dur,t|}|dkr8dStjtj|}t|}|dkr`dSt|}|spdSdS)a7A device is a "netfail primary" device if: - the device has a 'master' sysfs file - the device driver is not 'virtio_net' - the 'master' sysfs file points to device with virtio_net driver - the 'master' device has the 'standby' feature bit set Return True if all of the above is True. rKrLFNrrT)r"rEr!rFrdbasenamerealpathrq)r rhZmaster_sysfs_pathZmaster_devnameZ master_driverZmaster_has_standbyrrrres  recCs<t|durdS|dur t|}|dkr,dSt|s8dSdS)zA device is a "netfail standby" device if: - The device has a 'master' sysfs attribute - The device driver is 'virtio_net' - The device has the standby feature bit set Return True if all of the above is True. NFrrTrsrgrrrrf9s rfcCst|d}|r|dvrdSdS)a /* interface name assignment types (sysfs name_assign_type attribute) */ #define NET_NAME_UNKNOWN 0 /* unknown origin (not exposed to user) */ #define NET_NAME_ENUM 1 /* enumerated by kernel */ #define NET_NAME_PREDICTABLE 2 /* predictably named by the kernel */ #define NET_NAME_USER 3 /* provided by user-space */ #define NET_NAME_RENAMED 4 /* renamed by user-space */ name_assign_type)34TFrA)r rwrrr is_renamedQs  rzcCstt|d}d|vS)Nueventz DEVTYPE=vlan)strr9r^)r r{rrris_vlan`sr}cCs0d}t|d}tj|r,tjt|}|S)z8Return the device driver for net device named 'devname'.Nz device/driver)r"rEr!islinkrureadlink)r rhZ driver_pathrrrrdes   rdcCst|d}|durdS|S)z;Return the device id string for net device named 'devname'.z device/deviceFNrA)r Zdev_idrrr device_devidps rc CsltstrttSztt}Wn8t yf}z |j t j krPg}nWYd}~n d}~00|SN) r is_FreeBSDis_DragonFlyBSDlistget_interfaces_by_macvaluesrElistdirrr$r#r')devsr3rrrget_devicelistys rc@seZdZdZdS) ParserErrorz6Raised when a parser has issue parsing a file/content.N)__name__ __module__ __qualname____doc__rrrrrsrcCs |rt|tsdS|ddkS)NFconfigZdisabled) isinstancedictget)cfgrrris_disabled_cfgsrcCs6tstrtSts&tr,tStSdS)zqGet the list of network interfaces viable for networking. @return List of interfaces, sorted naturally. N)rrrfind_candidate_nics_on_freebsd is_NetBSD is_OpenBSD(find_candidate_nics_on_netbsd_or_openbsdfind_candidate_nics_on_linuxrrrrfind_candidate_nicss rcCs6tstrtSts&tr,tStSdS)z.Get the name of the 'fallback' network device.N)rrrfind_fallback_nic_on_freebsdrr&find_fallback_nic_on_netbsd_or_openbsdfind_fallback_nic_on_linuxrrrrfind_fallback_nics rcCstttdS)zmGet the names of the candidate network devices on NetBSD/OpenBSD. @return list of sorted interfaces key)sortedrrrrrrrrsrcCst}|r|dSdS)zfGet the 'fallback' network device name on NetBSD/OpenBSD. @return default interface, or None rN)rnamesrrrrsrcCs4tgd\}}|}|r"|StttdS)zgGet the names of the candidate network devices on FreeBSD. @return List of sorted interfaces. )ifconfigz-lz-uetherr)rrrrrr)stdout_stderrrrrrrs rcCst}|r|dSdS)z_Get the 'fallback' network device name on FreeBSD. @return List of sorted interfaces. rN)rrrrrrsrc CsFdtvrtdn,ddtD}t|rDtd|tg}g}tdddddddD]\}}}}|d krvq`|d rtd |q`t |d }|r| |q`td |t |d}|r| |q`t |d}|dvr| |q`td|q`g}||fD]:} t | t d} t| vr6| t| dt|| 7}q|S)zeGet the names of the candidate network devices on Linux. @return List of sorted interfaces. z net.ifnames=0z9Stable ifnames disabled by net.ifnames=0 in /proc/cmdlinecSs g|]}|dkrt|s|qS)lo)rz)rZdevicerrrrsz0find_candidate_nics_on_linux..z4Found unstable nic names: %s; calling udevadm settleFT)filter_openvswitch_internal2filter_slave_if_master_not_bridge_bond_openvswitch filter_vlanfilter_without_own_macfilter_zero_maclog_filtered_reasonsrZvethzIgnoring veth interface: %scarrierzInterface has no carrier: %sdormantr@)rr?Zlowerlayerdownr>zInterface ignored: %srr)rZ get_cmdliner,r-rrpZudevadm_settleget_interfaces startswithr<appendr9rrDEFAULT_PRIMARY_INTERFACEremoveinsert) ZunstableZ connectedZpossibly_connectedr_rrr@Zsorted_interfaces interfacesrrrrs`                 rcCst}|r|dSdS)z]Get the 'fallback' network device name on Linux. @return List of sorted interfaces. rN)rrrrrrsrcCsjt}|sdSt|r d|i}ndt|di}|rJt|}|rJ||d<dd||d}||idd }|S) zBGenerate network cfg v2 for dhcp on the NIC most likely connected.Nr macaddressaddressrhT)Zdhcp4r set-namematch) ethernetsversion)rrtr9rrd)Z config_driverZ target_namerrhrZnconfrrrgenerate_fallback_config+s$ rcCsJdd}dd}|d}|dkr*||S|dkr:||Std|dS) NcSsg}|diD]|}|ddkr$q|d}|s4q|d}|did}|did}|snt|}|szt|}|||||gq|S) NrrRZphysicalZ mac_addressr paramsrh device_id)rrdrr)netcfgphysdevsentmacr rhrrrr _version_1Is   z$extract_physdevs.._version_1cSsg}|diD]z}|d}|s(q|did}|s@q|did}|did}|spt|}|s|t|}|||||gq|S)Nrrrrrhr)rrrdrr)rrrr rrhrrrr _version_2[s  z$extract_physdevs.._version_2rrz"Unknown network config version: %s)r RuntimeError)rrrrrrrextract_physdevsHs rFcCs*t|d}|dur"|rtddS|dvS)areturn True if the provided interface has its own address. Based on addr_assign_type in /sys. Return true for any interface that does not have a 'stolen' address. Examples of such devices are bonds or vlans that inherit their mac from another device. Possible values are: 0: permanent address 2: stolen from another device 1: randomly generated 3: set using dev_set_mac_addressZaddr_assign_typeNz%s had no addr_assign_type.T)rr)r<r:)ifnamestrictZ assign_typerrrinterface_has_own_macxs rTc Csi}tD]*\}}}}d||||t|d||<q |rtd}tjgddd\}}tjgddd\} }t} || fD]} | || q~| D] } | dd up| d | v| d <q|S) aCollect information necessary for rename_interfaces. returns a dictionary by mac address like: {name: { 'downable': None or boolean indicating that the device has only automatically assigned ip addrs. 'device_id': Device id value (if it has one) 'driver': Device driver (if it has one) 'mac': mac address (in lower case) 'name': name 'up': boolean: is_up(name) }} N)downablerrhrr r=z[0-9]+:\s+(\w+)[@:])ipz-6addrshowZ permanentZscopeglobalT)Zcapture)rz-4rrr=Fr r) rrrBrcompilersetupdatefindallr) Zcheck_downablecur_infor rrhrZnmatchZipv6r`Zipv4Znics_with_addressesZ bytes_outdrrr_get_current_rename_infos.     rc svt|stddS|dur$t}i|D]:\}}|}|drZ|d|d<||d<||<q0tddd}g}g} g} |} d} d} d d fd d }|D]\}}}}|r|}g}||||}|s|r| d ||fq|d}||krq|s0|r| d ||fq|drd}|dsb|r| ||||fqd|d<|d|||ff| d|||ff|| vr\| |}|drd}|ds|r| ||||fqn|d|||ffd}|dus|| vr| d7} | | }q|d||||ff||d<|} |dr\| d|||ff|d|||d|ff||d<|} ||7}qt j t j t j d}t|t| dkrt| rt d|| n td|nztd||| || D]^\}}}}z|||Wn>tyT}z$| d|||||fWYd}~n d}~00qt| rrtd| dS)Nzno interfaces to renamerr zDetected interfaces %scSstdd|DS)Ncss|]}|d|fVqdS)r Nrrdatarrr z<_rename_interfaces..update_byname..)rr)Zbymacrrr update_bynamesz)_rename_interfaces..update_bynamez cirename%dcSsd|r0|r0|r0|d|ko.|d|ko.|d|kS|rP|rP|d|koN|d|kS|r`|d|kSdS)zmatch if set and in datarrhrFr)rrrhrrrr entry_matchs     z'_rename_interfaces..entry_matchcsTfddD}t|rPt|dkrHd|f}t||dSdS)Ncsg|]}|r|qSrrr)rrhrrrrrsz:_rename_interfaces..find_entry..rzjFailed to match a single device. Matched devices "%s" with search values "(mac:%s driver:%s device_id:%s)"r)rrpr:)rrhrrmsgrr)rrhrr find_entrys  z&_rename_interfaces..find_entryz<[nic not present] Cannot rename mac=%s to %s, not available.r=z*[busy] Error renaming mac=%s from %s to %srFr?z2[busy-target] Error renaming mac=%s from %s to %s.rrename)rr?r=rz1Unable to rename interfaces: %s due to errors: %sz$no work necessary for renaming of %szRenamed %s with ops %sz.[unknown] Error performing %s%s for %s, %s: %s )rpr,r-ritemscopyrrrr Z link_renameZ link_downZlink_upwarningrjrrN)renamesZstrict_presentZ strict_busyZ current_infor rZcurropserrorsZupsZ cur_bynameZ tmpname_fmtZtmpirrnew_namerhrZcur_opsZcur_namertargetZtmp_nameZopmapoprr3rrr_rename_interfacess                  rcCs$d}tjt|drd}t||S)z6Returns the string value of an interface's MAC AddressrZ bonding_slavezbonding_slave/perm_hwaddr)rEr!isdirr"r9)rr!rrrget_interface_macXsrcCs>t|ddkr:t|}|r6|r6|dd|dd}|SdS)zReturns the string value of an Infiniband interface's hardware address. If ethernet_format is True, an Ethernet MAC-style 6 byte representation of the address will be returned. rRrS$i3N)r9r)rZethernet_formatrrrrget_ib_interface_hwaddrbs rcCs<tstrtStr$tStr2tStSdSr) rrr get_interfaces_by_mac_on_freebsdrget_interfaces_by_mac_on_netbsdr get_interfaces_by_mac_on_openbsdget_interfaces_by_mac_on_linuxrrrrrpsr)rrVcCs0tD] \}}||kr |Sq dSr)rrr)rZ interface_macZinterface_namerrrfind_interface_name_from_mac{s rcCs<tgd\}}dd}dd}dd|||D}|S)N)r-arcss@d}|dD]&}|dr&||7}q|r0|V|}q|VdS)Nrr )rr)r_Z curr_blocklinerrrflattens  z1get_interfaces_by_mac_on_freebsd..flattencss4|D]*}td|}|r|d|dfVqdS)Nz2^(?P\S*): .*ether\s(?P[\da-f:]{17}).*rr)rsearchgroup)Z flat_listblockmrrrfind_macs z2get_interfaces_by_mac_on_freebsd..find_maccSsi|]\}}||qSrr)rrrrrr rz4get_interfaces_by_mac_on_freebsd..)r)r_rrrresultsrrrrs  rcCsbi}d}tddg\}}tdd|}|D],}t||}|r0|}|d||d<q0|S)NzE(?P\w+).*address:\s(?P([\da-f]{2}[:-]){5}([\da-f]{2})).*rr\n\s+ rrrrsubr^r groupdictrYZre_field_matchr_rZif_linesrrfieldsrrrrs rcCsbi}d}tddg\}}tdd|}|D],}t||}|r0|}|d||d<q0|S)NzC(?P\w+).*lladdr\s(?P([\da-f]{2}[:-]){5}([\da-f]{2})).*rrrrrrr r rrrrs rcCsi}tD]\}}}}||vrV|dvrIgnoring duplicate macs from '%s' and '%s' due to driver '%s'.z6duplicate mac found! both '%s' and '%s' have mac '%s'.Tz^Ethernet and InfiniBand interfaces have the same address both '%s' and '%s' have address '%s'.)rr,r-rrr)rYr rrhZ_devidrib_macrrrrs:  r)filter_hyperv_vf_with_syntheticrrrrrrrVcCs$|r tjndd}g}t} dd} | D]} |rrz get_interfaces..:)00rrrrrrrrrrrrrrrzIgnoring bridge interface: %szIgnoring bond interface: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %sr)r,r-rrNrrHr}rJrMrPrQrirrprcrdrr)filter_hyperv_vf_with_synthetic_interface)rrrrrrrfiltered_loggerrYrZzero_macr rrhrrrrsT           r).N)rrrVcsXdd|Dfdd|D}|D].}|\}}}}|d||||||q$dS)aFilter Hyper-V SR-IOV/VFs when used with synthetic hv_netvsc. Hyper-V's netvsc driver may register an SR-IOV/VF interface with a mac that matches the synthetic (hv_netvsc) interface. This VF will be enslaved to the synthetic interface, but cloud-init may be racing this process. The [perhaps-yet-to-be-enslaved] VF should never be directly configured, so we filter interfaces that duplicate any hv_netvsc mac address, as this the most reliable indicator that it is meant to be subordinate to the synthetic interface. VF drivers will be mlx4_core, mlx5_core, or mana. However, given that this list of drivers has changed over time and mana's dependency on hv_netvsc is expected to be removed in the future, we no longer rely on these names. Note that this will not affect mlx4/5 instances outside of Hyper-V, as it only affects environments where hv_netvsc is present. cSs&i|]}|ddkr|d|dqS)r hv_netvscrrrrirrrrUsz=filter_hyperv_vf_with_synthetic_interface..cs(g|] }|dvr|ddkr|qS)rrrrrZhv_netvsc_mac_to_namerrrXsz=filter_hyperv_vf_with_synthetic_interface..zdIgnoring %r VF interface with driver %r due to synthetic hv_netvsc interface %r with mac address %r.N)r)rrZinterfaces_to_removerr rrhrrrrrAs   rcCsPi}tD]@\}}}}t|d}|r ||vrBtd||||f|||<q |S)zTBuild a dictionary mapping Infiniband interface names to their hardware address.Fz5duplicate mac found! both '%s' and '%s' have mac '%s')rrr)rYr rrrrrget_ib_hwaddrs_by_interfaceks   r)convert_to_addressrcKs,z||fi|WSty&YdS0dS)aUse a function to return an address. If conversion throws a ValueError exception return False. :param check_cb: Test function, must return a truthy value :param address: The string to test. :return: Address or False FN)r:)rrkwargsrrrmaybe_get_address{s  r)rrVcCstttj|S)zReturns a bool indicating if ``s`` is an IP address. :param address: The string to test. :return: A bool indicating if the string is an IP address or not. )rWr ipaddress ip_addressrrrr is_ip_addresss r!cCstttj|S)zReturns a bool indicating if ``s`` is an IPv4 address. :param address: The string to test. :return: A bool indicating if the string is an IPv4 address or not. )rWrr IPv4Addressr rrris_ipv4_addresss r#cCstttj|S)zReturns a bool indicating if ``s`` is an IPv6 address. :param address: The string to test. :return: A bool indicating if the string is an IPv4 address or not. )rWrr IPv6Addressr rrris_ipv6_addresss r%cCstttj|ddS)zReturns a bool indicating if ``s`` is an IPv4 or IPv6 network. :param address: The string to test. :return: A bool indicating if the string is an IPv4 address or not. Fr)rWrr ip_networkr rrr is_ip_networks r(cCstttj|ddS)zReturns a bool indicating if ``s`` is an IPv4 network. :param address: The string to test. :return: A bool indicating if the string is an IPv4 address or not. Fr&)rWrr IPv4Networkr rrris_ipv4_networks r*cCstttj|ddS)zReturns a bool indicating if ``s`` is an IPv6 network. :param address: The string to test. :return: A bool indicating if the string is an IPv4 address or not. Fr&)rWrr IPv6Networkr rrris_ipv6_networks r,)rsubnetrVcCs t|}tj|dd}||vS)zReturns a bool indicating if ``s`` is in subnet. :param address: The string of IP address. :param subnet: The string of subnet. :return: A bool indicating if the string is in subnet. Fr&)rrr')rr-rZsubnet_networkrrris_ip_in_subnets r.)gatewayr-rVc CsJzt|| WStyD}ztd|||WYd}~dSd}~00dS)zReturns a bool indicating if should add gateway onlink flag. :param gateway: The string of gateway address. :param subnet: The string of subnet. :return: A bool indicating if the string is in subnet. zDFailed to check whether gateway %s is contained within subnet %s: %sNF)r.r:r,r)r/r-r3rrrshould_add_gateway_onlink_flags r0cCs@|dds|dtvrdS|ddkr "255.255.255.0" Also supports input as a string.0.0.0.0/)r|rr)netmask)prefixrrrnet_prefix_to_ipv4_masksr8cCstd|jS)aConvert an ipv4 netmask into a network prefix length. If the input is already an integer or a string representation of an integer, then int(mask) will be returned. "255.255.255.0" => 24 str(24) => 24 "24" => 24 r5)rr' prefixlen)maskrrripv4_mask_to_net_prefixs r;cCsztd|j}|WSty*Yn0t|}t|}|dkrJ|Sttj||d@}||?}tj|}d|>d}||krtd||S)zConvert an ipv6 netmask (very uncommon) or prefix (64) to prefix. If the input is already an integer or a string representation of an integer, then int(mask) will be returned. "ffff:ffff:ffff::" => 48 "48" => 48 z::/rrzInvalid network mask '%s') rr'r9r:rrmin IPV6LENGTH bit_length)r:r9r6Zmask_inttrailing_zeroes leading_onesall_onesrrripv6_mask_to_net_prefix's$     rB)r:rrVcCsttj|d|ddjS)zCGet string representation of broadcast address from an ip/mask pairrFr&)r|rr)broadcast_address)r:rrrrmask_and_ipv4_to_bcast_addrJsrDc@s eZdZdS)RendererNotFoundErrorN)rrrrrrrrEQsrE)r)NNNN)N)N)N)N)N)N)F)T)TTN)TTTTTTF)er# functoolsrZloggingrErtypingrrrrrZ cloudinitrrZcloudinit.net.netops.iproute2r Z getLoggerrr,rrr3r[rrrr"r4r9r<rBrHrJrMrPrQrT lru_cacherWrZrrbr|rcrirlrqrtrerfrzr}rdrrrjrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!r#r%r(r*r,r.r0r4r8rr;rBrDrrErrrrs     %          !       H 0  /   H = *      #