o
    x[hª§  ã                   @   s~  d dl Z 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mZm	Z	m
Z
mZ d dlmZmZ d dlmZ e e¡ZdZdZg d¢Zg d¢Ze d	¡fd
d„Zdd„ Zd©dd„Z				dªdd„Zd«dd„Zdd„ Zdd„ Zdd„ Z dd„ Z!dd„ Z"dd „ Z#d!d"„ Z$d#d$„ Z%ej&dd%�d&e'fd'd(„ƒZ(ej&dd%�d&e)fd)d*„ƒZ*d+e+d&e'fd,d-„Z,d«d.d/„Z-d0d1„ Z.d2d3„ Z/d«d&e'fd4d5„Z0d«d6d7„Z1d«d8d9„Z2d:d;„ Z3d<d=„ Z4d>d?„ Z5d@dA„ Z6dBdC„ Z7G dDdE„ dEe8ƒZ9dFdG„ Z:d&e	e+ fdHdI„Z;d&e
e+ fdJdK„Z<d&e	e+ fdLdM„Z=d&e
e+ fdNdO„Z>d&e	e+ fdPdQ„Z?d&e
e+ fdRdS„Z@d&e	e+ fdTdU„ZAd&e
e+ fdVdW„ZBd«d&e
eC fdXdY„ZDdZd[„ ZEd¬d]d^„ZFd­d`da„ZG	d®dbdc„ZHddde„ ZIdfdg„ ZJd&eCfdhdi„ZKdje+d&e
e+ fdkdl„ZLd&eCfdmdn„ZMd&eCfdodp„ZNd&eCfdqdr„ZOd&eCfdsdt„ZP	_	_	_	_	_	_	\d¯due'dve'dwe'dxe'dye'dze'd{e'd&e)fd|d}„ZQd~ed d€e	ee+e+e+e+f  d&dfd�d‚„ZRdƒd„„ ZSd…ed†e+fd‡dˆ„ZTd†e+d&e'fd‰dŠ„ZUd†e+d&e'fd‹dŒ„ZVd†e+d&e'fd�dŽ„ZWd†e+d&e'fd�d�„ZXd†e+d&e'fd‘d’„ZYd†e+d&e'fd“d”„ZZd†e+d•e+d&e'fd–d—„Z[d˜e+d•e+d&e'fd™dš„Z\d&e'fd›dœ„Z]d&e+fd�dž„Z^d&e_fdŸd „Z`d&e_fd¡d¢„Zad£e+d¤e+d&e+fd¥d¦„ZbG d§d¨„ d¨ecƒZddS )°é    N)ÚCallableÚDictÚListÚOptionalÚTuple)ÚsubpÚutil)ÚIproute2z/sys/class/net/Úeth0)Údhcp6Ú
ipv6_slaaczipv6_dhcpv6-statelesszipv6_dhcpv6-stateful)ú	ovs-vsctlz--formatÚcsvz--no-headingsz	--timeoutÚ10z	--columnsÚnameÚfindÚ	interfaceztype=internalz([0-9]+)c                 C   s   dd„ t  || ¡D ƒS )aD  Sorting 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'].c                 S   s$   g | ]}|  ¡ rt|ƒn| ¡ ‘qS © )ÚisdigitÚintÚlower)Ú.0Útextr   r   ú8/usr/lib/python3/dist-packages/cloudinit/net/__init__.pyÚ
<listcomp>2   s    ÿÿz$natural_sort_key.<locals>.<listcomp>)ÚreÚsplit)ÚsÚ_nsrer   r   r   Únatural_sort_key+   s   
þr   c                   C   s   t S )z3Simple function to return the global SYS_CLASS_NET.)ÚSYS_CLASS_NETr   r   r   r   Úget_sys_class_path8   s   r!   Ú c                 C   s   t ƒ |  d | S )Nú/)r!   ©ÚdevnameÚpathr   r   r   Úsys_dev_path=   ó   r'   c           
   
   C   sü   t | |ƒ}zt |¡}W n? ttfyK } z1t|dd ƒ}	|	tjtjfv r2|d ur2||ƒW  Y d }~S |	tj	fv rF|d urF||ƒW  Y d }~S ‚ d }~ww | 
¡ }|d u rV|S z|| W S  ty} } z|d urq||ƒW  Y d }~S t d||¡ ‚ d }~ww )NÚerrnoz5Found unexpected (not translatable) value '%s' in '%s)r'   r   Úload_text_fileÚOSErrorÚIOErrorÚgetattrr)   ÚENOENTÚENOTDIRÚEINVALÚstripÚKeyErrorÚLOGÚdebug)
r%   r&   Ú	translateÚ	on_enoentÚon_keyerrorÚ	on_einvalÚdev_pathÚcontentsÚeÚe_errnor   r   r   Úread_sys_netA   s<   
€ø	
ý€÷r=   c                 C   s   dd„ }t | |||||d�S )Nc                 S   s   dS ©NFr   )r;   r   r   r   Úon_excp_falseg   s   z(read_sys_net_safe.<locals>.on_excp_false)r7   r6   r8   r5   )r=   )ÚifaceÚfieldr5   r?   r   r   r   Úread_sys_net_safef   s   úrB   c                 C   s6   t | |ƒ}|du rd S zt|ƒW S  ty   Y d S w r>   )rB   r   Ú
ValueError)r@   rA   Úvalr   r   r   Úread_sys_net_intt   s   

ÿrE   c                 C   s   ddddœ}t | d|d�S )NTF)ÚupÚunknownÚdownÚ	operstate)r5   ©rB   )r%   r5   r   r   r   Úis_up~   s   rK   c                 C   ó   t j t| dƒ¡S )NÚbridge©Úosr&   Úexistsr'   ©r%   r   r   r   Ú	is_bridge†   r(   rR   c                 C   rL   )NÚbondingrN   rQ   r   r   r   Úis_bondŠ   r(   rT   c                 C   s    t | dd�}tj |¡r|S dS )z8Return the master path for devname, or None if no masterÚmaster©r&   N)r'   rO   r&   rP   r$   r   r   r   Ú
get_masterŽ   s   rW   c                 C   sH   t | ƒ}|du r
dS tj |d¡}tj |d¡}tj |¡p#tj |¡S )z@Return a bool indicating if devname's master is a bridge or bondNFrS   rM   )rW   rO   r&   ÚjoinrP   )r%   Úmaster_pathÚbonding_pathÚbridge_pathr   r   r   Úmaster_is_bridge_or_bond–   s   r\   c                 C   s,   t | ƒ}|du r
dS t| dd�}tj |¡S )z;Return a bool indicating if devname's master is openvswitchNFzupper_ovs-systemrV   )rW   r'   rO   r&   rP   )r%   rY   Úovs_pathr   r   r   Úmaster_is_openvswitch    s
   r^   c                 C   s   t | dƒdkS )NÚtypeÚ32rJ   rQ   r   r   r   Úis_ib_interface©   s   ra   )ÚmaxsizeÚreturnc                  C   s    t t d¡ƒ} | st d¡ | S )zDReturn a bool indicating if Open vSwitch is installed in the system.r   z<ovs-vsctl not in PATH; not detecting Open vSwitch interfaces)Úboolr   Úwhichr3   r4   )Úretr   r   r   Úopenvswitch_is_installed­   s   ÿrg   c               
   C   sZ   zt   t¡\} }W |  ¡ S  t jy, } zd|jv r't d¡ g W  Y d}~S ‚ d}~ww )zÎReturn a list of the names of OVS internal interfaces on the system.

    These will all be strings, and are used to exclude OVS-specific interface
    from cloud-init's network configuration handling.
    zdatabase connection failedzJOpen vSwitch is not yet up; no interfaces will be detected as OVS-internalN)r   Ú!OVS_INTERNAL_INTERFACE_LOOKUP_CMDÚProcessExecutionErrorÚstderrr3   ÚinfoÚ
splitlines)ÚoutÚ_errÚexcr   r   r   Úget_ovs_internal_interfaces¸   s   
÷
ÿ€ùrp   r%   c                 C   s,   t ƒ sdS tƒ }| |v rt d| ¡ dS dS )z€Returns True if this is an OVS internal interface.

    If OVS is not installed or not yet running, this will return False.
    FzDetected %s as an OVS interfaceT)rg   rp   r3   r4   )r%   Úovs_bridgesr   r   r   Ú!is_openvswitch_internal_interfaceÍ   s   rr   c                 C   s,   |du rt | ƒ}t| |ƒst| |ƒrdS dS )z®netfailover driver uses 3 nics, master, primary and standby.
    this returns True if the device is either the primary or standby
    as these devices are to be ignored.
    NTF)Údevice_driverÚis_netfail_primaryÚis_netfail_standby©r%   Údriverr   r   r   Úis_netfailoverÛ   s   ÿrx   c                 C   s*   d}zt | dƒ}W |S  ty   Y |S w )zDReturns a str from reading /sys/class/net/<devname>/device/features.r"   zdevice/features)r=   Ú	Exception©r%   Úfeaturesr   r   r   Úget_dev_featuresé   s   þþr|   c                 C   s(   t | ƒ}|rt|ƒdk rdS |d dkS )zÄReturn 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)r|   Úlenrz   r   r   r   Úhas_netfail_standby_featureó   s   r�   c                 C   s<   t | ƒdurdS |du rt| ƒ}|dkrdS t| ƒsdS dS )zòA 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_netT©rW   rs   r�   rv   r   r   r   Úis_netfail_master   ó   	r„   c                 C   st   t | dd�}tj |¡sdS |du rt| ƒ}|dkrdS tj tj |¡¡}t|ƒ}|dkr0dS t|ƒ}|s8dS dS )a7  A 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.
    rU   rV   FNr‚   T)r'   rO   r&   rP   rs   ÚbasenameÚrealpathr�   )r%   rw   Úmaster_sysfs_pathÚmaster_devnameÚmaster_driverÚmaster_has_standbyr   r   r   rt     s   rt   c                 C   s<   t | ƒdu rdS |du rt| ƒ}|dkrdS t| ƒsdS dS )zçA 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.
    NFr‚   Trƒ   rv   r   r   r   ru   9  r…   ru   c                 C   s   t | dƒ}|r|dv rdS dS )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)Ú3Ú4TFrJ   )r%   rŒ   r   r   r   Ú
is_renamedQ  s   
	r�   c                 C   s   t t| dƒƒ}d| ¡ v S )NÚueventzDEVTYPE=vlan)ÚstrrB   rl   )r%   r�   r   r   r   Úis_vlan`  s   r’   c                 C   s0   d}t | dƒ}tj |¡rtj t |¡¡}|S )z8Return the device driver for net device named 'devname'.Nzdevice/driver)r'   rO   r&   Úislinkr†   Úreadlink)r%   rw   Údriver_pathr   r   r   rs   e  s
   
rs   c                 C   s   t | dƒ}|du rdS |S )z;Return the device id string for net device named 'devname'.zdevice/deviceFNrJ   )r%   Údev_idr   r   r   Údevice_devidp  s   
r—   c               
   C   sl   t  ¡ st  ¡ rttƒ  ¡ ƒS z	t tƒ ¡} W | S  t	y5 } z|j
t
jkr)g } n‚ W Y d }~| S d }~ww ©N)r   Ú
is_FreeBSDÚis_DragonFlyBSDÚlistÚget_interfaces_by_macÚvaluesrO   Úlistdirr!   r+   r)   r.   )Údevsr;   r   r   r   Úget_devicelisty  s   û
þ€ûr    c                   @   s   e Zd ZdZdS )ÚParserErrorz6Raised when a parser has issue parsing a file/content.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r¡   ‡  s    r¡   c                 C   s    | rt | tƒs	dS |  d¡dkS )NFÚconfigÚdisabled)Ú
isinstanceÚdictÚget)Úcfgr   r   r   Úis_disabled_cfg‹  s   r¬   c                   C   ó2   t  ¡ st  ¡ rtƒ S t  ¡ st  ¡ rtƒ S tƒ S )zqGet the list of network interfaces viable for networking.

    @return List of interfaces, sorted naturally.
    )r   r™   rš   Úfind_candidate_nics_on_freebsdÚ	is_NetBSDÚ
is_OpenBSDÚ(find_candidate_nics_on_netbsd_or_openbsdÚfind_candidate_nics_on_linuxr   r   r   r   Úfind_candidate_nics‘  s
   r³   c                   C   r­   )z.Get the name of the 'fallback' network device.)r   r™   rš   Úfind_fallback_nic_on_freebsdr¯   r°   Ú&find_fallback_nic_on_netbsd_or_openbsdÚfind_fallback_nic_on_linuxr   r   r   r   Úfind_fallback_nicž  s
   r·   c                   C   s   t tƒ  ¡ td�S )zmGet the names of the candidate network devices on NetBSD/OpenBSD.

    @return list of sorted interfaces
    ©Úkey)Úsortedrœ   r�   r   r   r   r   r   r±   ¨  s   r±   c                  C   ó   t ƒ } | r	| d S dS )zfGet the 'fallback' network device name on NetBSD/OpenBSD.

    @return default interface, or None
    r   N)r±   ©Únamesr   r   r   rµ   °  ó   rµ   c                  C   s4   t   g d¢¡\} }|  ¡ }|r|S ttƒ  ¡ td�S )zgGet the names of the candidate network devices on FreeBSD.

    @return List of sorted interfaces.
    )Úifconfigz-lz-uÚetherr¸   )r   r   rº   rœ   r�   r   )ÚstdoutÚ_stderrr�   r   r   r   r®   ¼  s
   r®   c                  C   r»   )z_Get the 'fallback' network device name on FreeBSD.

    @return List of sorted interfaces.
    r   N)r®   r¼   r   r   r   r´   Ë  r¾   r´   c            
      C   sB  dt  ¡ v rt d¡ ndd„ tƒ D ƒ} t| ƒr"t d| ¡ t  ¡  g }g }tddddddd�D ]L\}}}}|d	kr;q0| d
¡rGt d|¡ q0t	|dƒ}|rT| 
|¡ q0t d|¡ t	|dƒ}|rg| 
|¡ q0t|dƒ}|dv rv| 
|¡ q0t d|¡ q0g }||fD ]}	t|	td�}	t|	v rš|	 t¡ |	 dt¡ ||	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/cmdlinec                 S   s    g | ]}|d krt |ƒs|‘qS )Úlo)r�   )r   Údevicer   r   r   r   ß  s
    þz0find_candidate_nics_on_linux.<locals>.<listcomp>z4Found unstable nic names: %s; calling udevadm settleFT)Úfilter_openvswitch_internalÚ2filter_slave_if_master_not_bridge_bond_openvswitchÚfilter_vlanÚfilter_without_own_macÚfilter_zero_macÚlog_filtered_reasonsrÃ   ÚvethzIgnoring veth interface: %sÚcarrierzInterface has no carrier: %sÚdormantrI   )rÍ   rH   ÚlowerlayerdownrG   zInterface ignored: %sr¸   r   )r   Úget_cmdliner3   r4   r    r€   Úudevadm_settleÚget_interfacesÚ
startswithrE   ÚappendrB   rº   r   ÚDEFAULT_PRIMARY_INTERFACEÚremoveÚinsert)
ÚunstableÚ	connectedÚpossibly_connectedr   Ú_rÌ   rÍ   rI   Úsorted_interfacesÚ
interfacesr   r   r   r²   ×  s`   þþú








r²   c                  C   r»   )z]Get the 'fallback' network device name on Linux.

    @return List of sorted interfaces.
    r   N)r²   r¼   r   r   r   r¶     r¾   r¶   c                 C   sj   t ƒ }|sdS t|ƒrd|i}n	dt|dƒ ¡ i}| r%t|ƒ}|r%||d< dd||dœ}||idd	œ}|S )
zBGenerate network cfg v2 for dhcp on the NIC most likely connected.Nr   Ú
macaddressÚaddressrw   T)Údhcp4r   úset-nameÚmatché   )Ú	ethernetsÚversion)r·   r„   rB   r   rs   )Úconfig_driverÚtarget_namerá   rw   r«   Únconfr   r   r   Úgenerate_fallback_config+  s$   
ÿürè   c                 C   sF   dd„ }dd„ }|   d¡}|dkr|| ƒS |dkr|| ƒS td| ƒ‚)	Nc                 S   s’   g }|   di ¡D ]>}|  d¡dkrq|  d¡}|sq|  d¡}|  di ¡  d¡}|  di ¡  d¡}|s7t|ƒ}|s=t|ƒ}| ||||g¡ q|S )	Nr¦   r_   ÚphysicalÚmac_addressr   Úparamsrw   Ú	device_id)rª   rs   r—   rÓ   )ÚnetcfgÚphysdevsÚentÚmacr   rw   rì   r   r   r   Ú
_version_1I  s    

z$extract_physdevs.<locals>._version_1c                 S   s”   g }|   di ¡ ¡ D ]=}|  d¡}|sq
|  di ¡  d¡}|s q
|  di ¡  d¡}|  di ¡  d¡}|s8t|ƒ}|s>t|ƒ}| ||||g¡ q
|S )Nrã   rà   rá   rÝ   rw   rì   )rª   r�   rs   r—   rÓ   )rí   rî   rï   r   rð   rw   rì   r   r   r   Ú
_version_2[  s    
z$extract_physdevs.<locals>._version_2rä   é   râ   z"Unknown network config version: %s)rª   ÚRuntimeError)rí   rñ   rò   rä   r   r   r   Úextract_physdevsH  s   
rõ   Fc                 C   s*   t | dƒ}|du r|rtdƒ‚dS |dv S )aš  return 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_addressÚaddr_assign_typeNz%s had no addr_assign_type.T)r   ró   é   )rE   rC   )ÚifnameÚstrictÚassign_typer   r   r   Úinterface_has_own_macx  s   

rû   Tc                 C   sÂ   i }t ƒ D ]\}}}}d||| ¡ |t|ƒdœ||< q| r_t d¡}tjg d¢dd�\}}tjg d¢dd�\}	}tƒ }
||	fD ]
}|
 | |¡¡ q?| 	¡ D ]}|d d	u p[|d
 |
v|d< qN|S )aà  Collect 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)Údownablerì   rw   rð   r   rF   z[0-9]+:\s+(\w+)[@:])Úipz-6ÚaddrÚshowÚ	permanentÚscopeÚglobalT)Úcapture)rý   z-4rþ   rÿ   rF   Fr   rü   )
rÑ   r   rK   r   Úcompiler   ÚsetÚupdateÚfindallr�   )Úcheck_downableÚcur_infor   rð   rw   rì   ÚnmatchÚipv6rn   Úipv4Únics_with_addressesÚ	bytes_outÚdr   r   r   Ú_get_current_rename_infoŒ  s.   ú	

þÿr  c                    sf  t | ƒst d¡ d S |d u rtƒ }i ‰ | ¡ D ]\}}| ¡ }| d¡r-|d  ¡ |d< ||d< |ˆ |< qt dˆ ¡ dd„ }g }g }	g }
|ˆ ƒ}d}d}d	d
„ ‰‡ ‡fdd„}| D ]é\}}}}|rg| ¡ }g }||||ƒ}|s}|r||	 d||f ¡ q[| d¡}||kr‡q[|s•|r”|	 d||f ¡ q[|d rÄd}|d s¬|r«|	 ||||f ¡ q[d|d< | d|||ff¡ |
 d|||ff¡ ||v �r+|| }|d rîd}|d sä|rã|	 ||||f ¡ q[| d|||ff¡ d }|d u sù||v �r	|d7 }|| }|d u sù||v sù| d||||ff¡ ||d< |ˆ ƒ}|d �r+|
 d|||ff¡ | d|||d |ff¡ ||d< |ˆ ƒ}||7 }q[t	j
t	jt	jdœ}|�sh|
�sht |	ƒ�rat d| |	¡ nDt d| ¡ n=t d| ||
 ¡ ||
 D ]/\}}}}z	|| |Ž  W �qu t�y¤ } z|	 d|||||f ¡ W Y d }~�qud }~ww t |	ƒ�r±td |	¡ƒ‚d S )Nzno interfaces to renamerð   r   zDetected interfaces %sc                 S   s   t dd„ |  ¡ D ƒƒS )Nc                 s   s   � | ]	}|d  |fV  qdS )r   Nr   ©r   Údatar   r   r   Ú	<genexpr>Ð  s   € z<_rename_interfaces.<locals>.update_byname.<locals>.<genexpr>)r©   r�   )Úbymacr   r   r   Úupdate_bynameÏ  s   z)_rename_interfaces.<locals>.update_bynamez
cirename%déÿÿÿÿc                 S   sd   |r|r|r| d |ko| d |ko| d |kS |r(|r(| d |ko'| d |kS |r0| d |kS dS )zmatch if set and in datarð   rw   rì   Fr   )r  rð   rw   rì   r   r   r   Úentry_matchÙ  s   
ÿ
ýz'_rename_interfaces.<locals>.entry_matchc                    sT   ‡ ‡‡‡fdd„ˆ  ¡ D ƒ}t|ƒr(t|ƒdkr$d|ˆˆˆ f }t|ƒ‚|d S d S )Nc                    s   g | ]}ˆ|ˆˆˆ ƒr|‘qS r   r   r  )rì   rw   r  rð   r   r   r   é  s    ýÿz:_rename_interfaces.<locals>.find_entry.<locals>.<listcomp>ró   zjFailed to match a single device. Matched devices "%s" with search values "(mac:%s driver:%s device_id:%s)"r   )r�   r€   rC   )rð   rw   rì   rá   Úmsg©r	  r  )rì   rw   rð   r   Ú
find_entryè  s   þ
þÿz&_rename_interfaces.<locals>.find_entryz<[nic not present] Cannot rename mac=%s to %s, not available.rF   z*[busy] Error renaming mac=%s from %s to %srü   FrH   z2[busy-target] Error renaming mac=%s from %s to %s.ró   Úrename)r  rH   rF   z1Unable to rename interfaces: %s due to errors: %sz$no work necessary for renaming of %szRenamed %s with ops %sz.[unknown] Error performing %s%s for %s, %s: %sÚ
)r€   r3   r4   r  ÚitemsÚcopyrª   r   rÓ   r	   Úlink_renameÚ	link_downÚlink_upÚwarningry   rô   rX   )ÚrenamesÚstrict_presentÚstrict_busyÚcurrent_infor   r  Úcurr  ÚopsÚerrorsÚupsÚ
cur_bynameÚtmpname_fmtÚtmpir  rð   Únew_namerw   rì   Úcur_opsÚcur_namer  ÚtargetÚtmp_nameÚopmapÚoprë   r;   r   r  r   Ú_rename_interfacesº  sÒ   


ÿÿ
ÿÿ
þ

ý
ýÿÿ€ÿ
ÿr5  c                 C   s$   d}t j t| dƒ¡rd}t| |ƒS )z6Returns the string value of an interface's MAC AddressrÞ   Úbonding_slavezbonding_slave/perm_hwaddr)rO   r&   Úisdirr'   rB   )rø   r&   r   r   r   Úget_interface_macX  s   
r8  c                 C   s>   t | dƒdkrt| ƒ}|r|r|dd… |dd…  }|S dS )z½Returns 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.
    r_   r`   é$   iòÿÿÿé3   N)rB   r8  )rø   Úethernet_formatrð   r   r   r   Úget_ib_interface_hwaddrb  s   ûr<  c                   C   s8   t  ¡ st  ¡ rtƒ S t  ¡ rtƒ S t  ¡ rtƒ S tƒ S r˜   )	r   r™   rš   Ú get_interfaces_by_mac_on_freebsdr¯   Úget_interfaces_by_mac_on_netbsdr°   Ú get_interfaces_by_mac_on_openbsdÚget_interfaces_by_mac_on_linuxr   r   r   r   rœ   p  s   rœ   rð   c                 C   s0   t ƒ  ¡ D ]\}}|  ¡ | ¡ kr|  S qd S r˜   )rœ   r  r   )rð   Úinterface_macÚinterface_namer   r   r   Úfind_interface_name_from_mac{  s
   ÿrC  c                  C   s<   t   g d¢¡\} }dd„ }dd„ }dd„ ||| ƒƒD ƒ}|S )N)r¿   ú-arÀ   c                 s   sB   � d}|   d¡D ]}| d¡r||7 }q|r|V  |}q|V  d S )Nr"   r  ú	)r   rÒ   )rm   Ú
curr_blockÚliner   r   r   Úflatten†  s   €


z1get_interfaces_by_mac_on_freebsd.<locals>.flattenc                 s   s6   � | D ]}t  d|¡}|r| d¡| d¡fV  qd S )Nz2^(?P<ifname>\S*): .*ether\s(?P<mac>[\da-f:]{17}).*rð   rø   )r   ÚsearchÚgroup)Ú	flat_listÚblockÚmr   r   r   Úfind_mac’  s   €ÿ€ûz2get_interfaces_by_mac_on_freebsd.<locals>.find_macc                 S   s   i | ]\}}||“qS r   r   )r   rð   rø   r   r   r   Ú
<dictcomp>š  s    z4get_interfaces_by_mac_on_freebsd.<locals>.<dictcomp>)r   )rm   rÚ   rH  rN  Úresultsr   r   r   r=  ‚  s
   r=  c                  C   ób   i } d}t   ddg¡\}}t dd|¡ ¡ }|D ]}t ||¡}|r.| ¡ }|d | |d < q| S )NzE(?P<ifname>\w+).*address:\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r¿   rD  ú\n\s+ú rø   rð   ©r   r   Úsubrl   rá   Ú	groupdict©rf   Úre_field_matchrm   rÚ   Úif_linesrG  rM  Úfieldsr   r   r   r>  ž  ó   ÿ€r>  c                  C   rQ  )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r¿   rD  rR  rS  rø   rð   rT  rW  r   r   r   r?  ®  r[  r?  c                  C   s˜   i } t ƒ D ]D\}}}}|| v r+|dv rt d|| | |¡ qd|| | |f }t|ƒ‚|| |< t|dƒ}|rI|| vr?|| |< qt d|| | |¡ q| S )zmBuild a dictionary of tuples {mac: name}.

    Bridges and any devices that have a 'stolen' mac are excluded.)Ú	fsl_enetcÚ
mscc_felixÚqmi_wwanz>Ignoring 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'.)rÑ   r3   r4   rô   r<  r"  )rf   r   rð   rw   Ú_devidr  Úib_macr   r   r   r@  ¾  s<   ûý

û€r@  Úfilter_hyperv_vf_with_syntheticrÅ   rÆ   rÇ   rÈ   rÉ   rÊ   c                 C   s"  |rt jndd„ }g }tƒ }	d d¡}
|	D ]r}|rt|ƒsqt|ƒr(|d|ƒ q|r/t|ƒr/qt|ƒr9|d|ƒ q|rJt|ƒdurJt	|ƒsJt
|ƒsJqt|ƒrT|d|ƒ qt|ƒ}|s`|d	|ƒ q|rq|d
krq||
dt|ƒ… krqq|rxt|ƒrxqt|ƒ}| |||t|ƒf¡ q| r�t||ƒ |S )z‚Return list of interface tuples (name, mac, driver, device_id)

    Bridges and any devices that have a 'stolen' mac are excluded.c                  W   s   d S r˜   r   )Úargsr   r   r   Ú<lambda>  s    z get_interfaces.<locals>.<lambda>ú:)Ú00re  re  re  re  re  re  re  re  re  re  re  re  re  re  re  zIgnoring bridge interface: %szIgnoring bond interface: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %srÃ   )r3   r4   r    rX   rû   rR   r’   rT   rW   r\   r^   rx   r8  r€   rr   rs   rÓ   r—   Ú)filter_hyperv_vf_with_synthetic_interface)ra  rÅ   rÆ   rÇ   rÈ   rÉ   rÊ   Úfiltered_loggerrf   rŸ   Úzero_macr   rð   rw   r   r   r   rÑ     sR   


ÿÿþ

 ÿ
rÑ   rg  ).NrÜ   c                    sX   dd„ |D ƒ‰ ‡ fdd„|D ƒ}|D ]}|\}}}}| d||ˆ | |ƒ |  |¡ qdS )a�  Filter 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.
    c                 S   s&   i | ]}|d  dkr|d |d “qS )râ   Ú	hv_netvscró   r   r   ©r   Úir   r   r   rO  U  s     z=filter_hyperv_vf_with_synthetic_interface.<locals>.<dictcomp>c                    s(   g | ]}|d  ˆ v r|d dkr|‘qS )ró   râ   ri  r   rj  ©Úhv_netvsc_mac_to_namer   r   r   X  s
    þz=filter_hyperv_vf_with_synthetic_interface.<locals>.<listcomp>zdIgnoring %r VF interface with driver %r due to synthetic hv_netvsc interface %r with mac address %r.N)rÕ   )rg  rÜ   Úinterfaces_to_remover   r   rð   rw   rÚ   r   rl  r   rf  A  s"   ÿ
þúörf  c                  C   sP   i } t ƒ D ] \}}}}t|dƒ}|r%|| v r!td|| | |f ƒ‚|| |< q| S )zTBuild a dictionary mapping Infiniband interface names to their hardware
    address.Fz5duplicate mac found! both '%s' and '%s' have mac '%s')rÑ   r<  rô   )rf   r   rÚ   r`  r   r   r   Úget_ib_hwaddrs_by_interfacek  s   
ÿÿ€ro  Úconvert_to_addressrÞ   c                 K   s(   z	| |fi |¤ŽW S  t y   Y dS w )a  Use 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

    F)rC   )rp  rÞ   Úkwargsr   r   r   Úmaybe_get_address{  s
   ÿrr  c                 C   ó   t ttj| ƒƒS )z¹Returns 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.
    )rd   rr  Ú	ipaddressÚ
ip_address©rÞ   r   r   r   Úis_ip_addressŽ  ó   	rw  c                 C   rs  )z½Returns 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.
    )rd   rr  rt  ÚIPv4Addressrv  r   r   r   Úis_ipv4_addressš  rx  rz  c                 C   rs  )z½Returns 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.
    )rd   rr  rt  ÚIPv6Addressrv  r   r   r   Úis_ipv6_address¦  rx  r|  c                 C   ó   t ttj| dd�ƒS )zÅReturns 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.
    F©rù   )rd   rr  rt  Ú
ip_networkrv  r   r   r   Úis_ip_network²  s   	r€  c                 C   r}  )z½Returns 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~  )rd   rr  rt  ÚIPv4Networkrv  r   r   r   Úis_ipv4_network¾  ó   	ÿr‚  c                 C   r}  )z½Returns 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~  )rd   rr  rt  ÚIPv6Networkrv  r   r   r   Úis_ipv6_networkÌ  rƒ  r…  Úsubnetc                 C   s    t  | ¡}t j|dd�}||v S )zâReturns 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~  )rt  ru  r  )rÞ   r†  ru  Úsubnet_networkr   r   r   Úis_ip_in_subnetÚ  s   
rˆ  Úgatewayc              
   C   sF   zt | |ƒ W S  ty" } zt d| ||¡ W Y d}~dS d}~ww )zóReturns 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ˆ  rC   r3   r"  )r‰  r†  r;   r   r   r   Úshould_add_gateway_onlink_flagë  s   û€ørŠ  c                 C   s@   | d   d¡s| d tv rdS | d dkrt|  d¡ƒrdS dS )z:Common helper for checking network_state subnets for ipv6.r_   Ú6TÚstaticrÞ   F)ÚendswithÚIPV6_DYNAMIC_TYPESr|  rª   )r†  r   r   r   Úsubnet_is_ipv6  s
   r�  c                 C   s   t t d| › �¡jƒS )z¤Convert a network prefix to an ipv4 netmask.

    This is the inverse of ipv4_mask_to_net_prefix.
        24 -> "255.255.255.0"
    Also supports input as a string.ú0.0.0.0/)r‘   rt  r�  Únetmask)Úprefixr   r   r   Únet_prefix_to_ipv4_mask  s   r“  c                 C   s   t  d| › �¡jS )a  Convert 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
    r�  )rt  r  Ú	prefixlen)Úmaskr   r   r   Úipv4_mask_to_net_prefix  s   	r–  c                 C   sš   zt  d| › �¡j}|W S  ty   Y nw t  | ¡}t|ƒ}|dkr%|S tt j| |d @  ¡ ƒ}||? }t j| }d|> d }||krKtd|  ƒ‚|S )zÿConvert 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::/r   ró   zInvalid network mask '%s')	rt  r  r”  rC   ru  r   ÚminÚ
IPV6LENGTHÚ
bit_length)r•  r”  r‘  Úmask_intÚtrailing_zeroesÚleading_onesÚall_onesr   r   r   Úipv6_mask_to_net_prefix'  s&   ý
ÿ
rž  r•  rý   c                 C   s   t tj|› d| › �dd�jƒS )zCGet string representation of broadcast address from an ip/mask pairr#   Fr~  )r‘   rt  r�  Úbroadcast_address)r•  rý   r   r   r   Úmask_and_ipv4_to_bcast_addrJ  s   ÿr   c                   @   s   e Zd ZdS )ÚRendererNotFoundErrorN)r¢   r£   r¤   r   r   r   r   r¡  Q  s    r¡  )r"   )NNNNr˜   )F)T)TTN)TTTTTTF)er)   Ú	functoolsrt  ÚloggingrO   r   Útypingr   r   r   r   r   Ú	cloudinitr   r   Úcloudinit.net.netops.iproute2r	   Ú	getLoggerr¢   r3   r    rÔ   rŽ  rh   r  r   r!   r'   r=   rB   rE   rK   rR   rT   rW   r\   r^   ra   Ú	lru_cacherd   rg   r›   rp   r‘   rr   rx   r|   r�   r„   rt   ru   r�   r’   rs   r—   r    ry   r¡   r¬   r³   r·   r±   rµ   r®   r´   r²   r¶   r©   rè   rõ   rû   r  r5  r8  r<  rœ   rC  r=  r>  r?  r@  rÑ   rf  ro  rr  rw  rz  r|  r€  r‚  r…  rˆ  rŠ  r�  r“  r   r–  rž  r   rô   r¡  r   r   r   r   Ú<module>   sî   


ú
%

	






!	
H
0
/
ÿ 
Hùÿþýüûúù
ø<ÿþ
ý*	#