o
    thm                     @   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dddZ				dddZdd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,dd.d/Z-d0d1 Z.d2d3 Z/dd&e'fd4d5Z0dd6d7Z1dd8d9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ZBdd&e
eC fdXdYZDdZd[ ZEdd]d^ZFdd`daZG	ddbdcZHddde ZIdfdg ZJd&eCfdhdiZKdje+d&e
e+ fdkdlZLd&eCfdmdnZMd&eCfdodpZNd&eCfdqdrZOd&eCfdsdtZP	_	_	_	_	_	_	\ddue'dve'dwe'dxe'dye'dze'd{e'd&e)fd|d}ZQd~ed de	ee+e+e+e+f  d&dfddZRdd ZSdede+fddZTde+d&e'fddZUde+d&e'fddZVde+d&e'fddZWde+d&e'fddZXde+d&e'fddZYde+d&e'fddZZde+de+d&e'fddZ[de+de+d&e'fddZ\d&e'fddZ]d&e+fddZ^d&e_fddZ`d&e_fddZade+de+d&e+fddZbG dd dec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 )zReturn 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 )zReturns 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 )znetfailover 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 )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)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 )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_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 )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.
    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   s  dt  v rtd n9dd t D } t| rEtd|  zt   W n  tjyD } zt	d|j
|j|j|j W Y d}~nd}~ww g }g }tdddddd	d
D ]L\}}}}|dkr^qS|drjtd| qSt|d}|rw|| qStd| t|d}|r|| qSt|d}|dv r|| qStd| qSg }	||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 settlezAudevadm failed to settle: cmd=%r stderr=%r stdout=%r exit_code=%sNFT)filter_openvswitch_internal2filter_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_settler   ri   warningcmdrj   r   	exit_codeget_interfaces
startswithrE   appendrB   r   r   DEFAULT_PRIMARY_INTERFACEremoveinsert)unstableerror	connectedpossibly_connectedr   _r   r   rI   sorted_interfaces
interfacesr   r   r   r     sv   








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_config5  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_1S  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_2e  s    
z$extract_physdevs.<locals>._version_2r      r   z"Unknown network config version: %s)r   RuntimeError)r   r   r   r   r   r   r   extract_physdevsR  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_mac  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rq[|s|r|	d||f  q[|d rd}|d s|r|	||||f  q[d|d< |d|||ff |
d|||ff ||v r+|| }|d rd}|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 |	rt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%dc                 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_upr   ry   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   








r8  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_macb  s   
r;  c                 C   s>   t | ddkrt| }|r|r|dd |dd  }|S dS )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.
    r_   r`   $   i3   N)rB   r;  )r   ethernet_formatr   r   r   r   get_ib_interface_hwaddrl  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   z  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
   rF  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   rK  rQ  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   rG  \n\s+ r   r   r   r   subrl   r   	groupdictrf   re_field_matchrm   r   if_linesrJ  rP  fieldsr   r   r   rA       rA  c                  C   rT  )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   rG  rU  rV  r   r   rW  rZ  r   r   r   rB    r^  rB  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   rC    s<   

rC  filter_hyperv_vf_with_syntheticr   r   r   r   r   r   c                 C   s,  |rt jndd }g }t }	dd}
|	D ]w}t|r!|d| q|r(t|r(qt|r2|d| q|r>t|s>|d| q|rOt|durOt	|sOt
|sOqt|rY|d	| qt|}|se|d
| q|rv|dkrv||
dt| krvq|r}t|r}qt|}||||t|f q| rt|| |S )zReturn 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>:)00rh  rh  rh  rh  rh  rh  rh  rh  rh  rh  rh  rh  rh  rh  rh  zIgnoring bridge interface: %szIgnoring bond interface: %sz)Ignoring interface with inherited MAC: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %sr   )r3   r4   r   rX   rR   r   rT   r   rW   r\   r^   rx   r;  r   rr   rs   r   r   )filter_hyperv_vf_with_synthetic_interface)rd  r   r   r   r   r   r   filtered_loggerrf   r   zero_macr   r   rw   r   r   r   r     sT   





 
r   rj  ).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   rR  `  s     z=filter_hyperv_vf_with_synthetic_interface.<locals>.<dictcomp>c                    s(   g | ]}|d   v r|d dkr|qS )r   r   rl  r   rm  hv_netvsc_mac_to_namer   r   r   c  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   )rj  r   interfaces_to_remover   r   r   rw   r   r   ro  r   ri  L  s"   
ri  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   rc  r   r   r   get_ib_hwaddrs_by_interfacev  s   
rr  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   )rs  r   kwargsr   r   r   maybe_get_address  s
   ru  c                 C      t ttj| 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.
    )rd   ru  	ipaddress
ip_addressr   r   r   r   is_ip_address     	rz  c                 C   rv  )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.
    )rd   ru  rw  IPv4Addressry  r   r   r   is_ipv4_address  r{  r}  c                 C   rv  )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.
    )rd   ru  rw  IPv6Addressry  r   r   r   is_ipv6_address  r{  r  c                 C      t ttj| ddS )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.
    Fr   )rd   ru  rw  
ip_networkry  r   r   r   is_ip_network  s   	r  c                 C   r  )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  )rd   ru  rw  IPv4Networkry  r   r   r   is_ipv4_network     	r  c                 C   r  )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  )rd   ru  rw  IPv6Networkry  r   r   r   is_ipv6_network  r  r  subnetc                 C   s    t | }t j|dd}||v S )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  )rw  rx  r  )r   r  rx  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 )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  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 )zConvert 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   rw  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  )rw  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 )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::/r   r   zInvalid network mask '%s')	rw  r  r  rC   rx  r   min
IPV6LENGTH
bit_length)r  r  r  mask_inttrailing_zeroesleading_onesall_onesr   r   r   ipv6_mask_to_net_prefix2  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   rw  r  broadcast_address)r  r  r   r   r   mask_and_ipv4_to_bcast_addrU  s   r  c                   @   s   e Zd ZdS )RendererNotFoundErrorN)r   r   r   r   r   r   r   r  \  s    r  )r"   )NNNNr   )F)T)TTN)TTTTTTF)er)   	functoolsrw  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  r8  r;  r?  r   rF  r@  rA  rB  rC  r   ri  rr  ru  rz  r}  r  r  r  r  r  r  r  r  r   r  r  r  r   r  r   r   r   r   <module>   s   



%

	






!	
R
0
/
 
H
=
*	#