o
    f                     @   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mZ d dlmZ d dlmZmZ d dlmZ d dlmZ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,Z0d-e1d(e-fd.d/Z2dd0d1Z3d2d3 Z4d4d5 Z5dd(e-fd6d7Z6dd8d9Z7dd:d;Z8d<d= Z9d>d? Z:d@dA Z;dBdC Z<dDdE Z=G dFdG dGe>Z?dHdI Z@d(e
e1 fdJdKZAd(ee1 fdLdMZBd(e
e1 fdNdOZCd(ee1 fdPdQZDd(e
e1 fdRdSZEd(ee1 fdTdUZFd(e
e1 fdVdWZGd(ee1 fdXdYZHdd(eeI fdZd[ZJd\d] ZKdd_d`ZLddbdcZM	ddddeZNdfdg ZOdhdi ZPd(eIfdjdkZQdle1d(ee1 fdmdnZRd(eIfdodpZSd(eIfdqdrZTd(eIfdsdtZUd(eIfdudvZV	a	a	a	a	a	a	^ddwe-dxe-dye-dze-d{e-d|e-d}e-d(e/fd~dZWded de
ee1e1e1e1f  d(dfddZXdd ZYde	e1ef d(e-fddZZdede1fddZ[de1d(e-fddZ\de1d(e-fddZ]de1d(e-fddZ^de1d(e-fddZ_de1d(e-fddZ`de1d(e-fddZade1de1d(e-fddZbde1de1d(e-fddZcd(e-fddZdd(e1fddZed(effddZgd(effddZhde1de1d(e1fddZiG dd dejZkdS )    N)AnyCallableDictListOptionalTuple)urlparse)subputil)Iproute2)UrlErrorreadurlz/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>4   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_path:   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_netC   s<   
	
rA   c                 C   s   dd }t | |||||dS )Nc                 S   s   dS NFr   )r?   r   r   r   on_excp_falsei   s   z(read_sys_net_safe.<locals>.on_excp_false)r;   r:   r<   r9   )rA   )ifacefieldr9   rC   r   r   r   read_sys_net_safeh   s   rF   c                 C   s6   t | |}|du rd S zt|W S  ty   Y d S w rB   )rF   r   
ValueError)rD   rE   valr   r   r   read_sys_net_intv   s   

rI   c                 C   s   dddd}t | d|dS )NTF)upunknowndown	operstate)r9   rF   )r)   r9   r   r   r   is_up   s   rO   c                 C      t jt| dS )Nbridgeosr*   existsr+   r)   r   r   r   	is_bridge   r,   rV   c                 C   rP   )NbondingrR   rU   r   r   r   is_bond   r,   rX   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+   rS   r*   rT   r(   r   r   r   
get_master   s   r[   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 bondNFrW   rQ   )r[   rS   r*   joinrT   )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-systemrZ   )r[   r+   rS   r*   rT   )r)   r]   ovs_pathr   r   r   master_is_openvswitch   s
   rb   c                 C   s   t | ddkS )Ntype32rN   rU   r   r   r   is_ib_interface   s   re   )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	   whichr7   r8   )retr   r   r   openvswitch_is_installed   s   rk   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stderrr7   info
splitlines)out_errexcr   r   r   get_ovs_internal_interfaces   s   

rt   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)rk   rt   r7   r8   )r)   ovs_bridgesr   r   r   !is_openvswitch_internal_interface   s   rv   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   r|   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)rA   	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   lenr~   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r[   rw   r   rz   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.
    rY   rZ   FNr   T)r+   rS   r*   rT   rw   basenamerealpathr   )r)   r{   master_sysfs_pathmaster_devnamemaster_drivermaster_has_standbyr   r   r   rx     s   rx   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   rz   r   r   r   ry   ;  r   ry   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4TFrN   )r)   r   r   r   r   
is_renamedS  s   
	r   c                 C   s   t t| d}d| v S )NueventzDEVTYPE=vlan)strrF   rp   )r)   r   r   r   r   is_vlanb  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+   rS   r*   islinkr   readlink)r)   r{   driver_pathr   r   r   rw   g  s
   
rw   c                 C   s   t | d}|du rdS |S )z;Return the device id string for net device named 'devname'.zdevice/deviceFNrN   )r)   dev_idr   r   r   device_devidr  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valuesrS   listdirr%   r/   r-   r2   )devsr?   r   r   r   get_devicelist{  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   sR  dt  v rtd ndd t D } t| r*td|  d}t jtj|t jd g }g }tdddddd	d
D ]L\}}}}|dkrCq8|	drOtd| q8t
|d}|r\|| q8td| t
|d}|ro|| q8t|d}|dv r~|| q8td| q8g }	||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 settlez!Waiting for udev events to settle)funcFT)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dormantrM   )r   rL   lowerlayerdownrK   zInterface ignored: %sr   r   )r
   get_cmdliner7   r8   r   r   log_timeudevadm_settleget_interfaces
startswithrI   appendrF   r   r#   DEFAULT_PRIMARY_INTERFACEremoveinsert)unstablemsg	connectedpossibly_connectedr   _r   r   rM   sorted_interfaces
interfacesr   r   r   r     sb   








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addressr{   T)dhcp4r   set-namematch   )	ethernetsversion)r   r   rF   r   rw   )config_drivertarget_namer   r{   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   rc   physicalmac_addressr   paramsr{   	device_id)r   rw   r   r   )netcfgphysdevsentmacr   r{   r   r   r   r   
_version_1L  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   r{   r   )r   r   rw   r   r   )r   r   r   r   r   r{   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_physdevsK  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      )rI   rG   )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   r{   r   r   rJ   z[0-9]+:\s+(\w+)[@:])ipz-6addrshow	permanentscopeglobalT)capture)r  z-4r  r  rJ   Fr   r  )
r   r   rO   r   compiler	   setupdatefindallr   )check_downablecur_infor   r   r{   r   nmatchipv6rr   ipv4nics_with_addresses	bytes_outdr   r   r   _get_current_rename_info  s.   	

r  c                    sr  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}t |t |
 dkrmt |	rftd| |	 nEtd|  n>td| ||
  ||
 D ]0\}}}}z
|||  W qz ty } z|	d|||||f  W Y d }~qzd }~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   r{   r   Fr   )r  r   r{   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   r{   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   rG   )r   r{   r   r   r   r  r  )r   r{   r   r   
find_entry  s   
z&_rename_interfaces.<locals>.find_entryz<[nic not present] Cannot rename mac=%s to %s, not available.rJ   z*[busy] Error renaming mac=%s from %s to %sr  FrL   z2[busy-target] Error renaming mac=%s from %s to %s.r   rename)r!  rL   rJ   r   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   r7   r8   r  itemscopyr   r   r   r   link_rename	link_downlink_upwarningr}   r   r\   )renamesstrict_presentstrict_busycurrent_infor   r  curr  opserrorsups
cur_bynametmpname_fmttmpir   r   new_namer{   r   cur_opscur_namer   targettmp_nameopmapopr   r?   r   r  r   _rename_interfaces  s   








r;  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)rS   r*   isdirr+   rF   )r   r*   r   r   r   get_interface_mac[  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.
    rc   rd   $   i3   N)rF   r>  )r   ethernet_formatr   r   r   r   get_ib_interface_hwaddre  s   rB  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   s  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
   rI  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   )rq   
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	   )rq   r   rN  rT  resultsr   r   r   rC    s
   rC  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   rJ  \n\s+ r   r   r	   r   subrp   r   	groupdictrj   re_field_matchrq   r   if_linesrM  rS  fieldsr   r   r   rD       rD  c                  C   rW  )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   rJ  rX  rY  r   r   rZ  r]  r   r   r   rE    ra  rE  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   r7   r8   r   rB  r(  )rj   r   r   r{   _devidr   ib_macr   r   r   rF    s<   

rF  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| 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>:)00rk  rk  rk  rk  rk  rk  rk  rk  rk  rk  rk  rk  rk  rk  rk  zIgnoring bridge interface: %szIgnoring bond interface: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %sr   )r7   r8   r   r\   r  rV   r   rX   r[   r`   rb   r|   r>  r   rv   rw   r   r   )filter_hyperv_vf_with_synthetic_interface)rg  r   r   r   r   r   r   filtered_loggerrj   r   zero_macr   r   r{   r   r   r   r     sR   




 
r   rm  ).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   rU  X  s     z=filter_hyperv_vf_with_synthetic_interface.<locals>.<dictcomp>c                    s(   g | ]}|d   v r|d dkr|qS )r   r   ro  r   rp  hv_netvsc_mac_to_namer   r   r   [  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   )rm  r   interfaces_to_remover   r   r   r{   r   r   rr  r   rl  D  s"   
rl  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   rB  r   )rj   r   r   rf  r   r   r   get_ib_hwaddrs_by_interfacen  s   
ru  url_datac              
   C   s   d| vrt d|  dS | d }zt|}t|jdk|jdkgs+t d|j W dS W n tyE } zt d| W Y d}~dS d}~ww d	| vrNd
| d	< z
tdi |  W dS  tyb   Y dS w )aD  Return true when the instance has access to the provided URL.

    Logs a warning if url is not the expected format.

    url_data is a dictionary of kwargs to send to readurl. E.g.:

    has_url_connectivity({
        "url": "http://example.invalid",
        "headers": {"some": "header"},
        "timeout": 10
    })
    urlz4Ignoring connectivity check. No 'url' to check in %sFhttphttpsz2Ignoring connectivity check. Invalid URL scheme %sz+Ignoring connectivity check. Invalid URL %sNtimeout   Tr   )r7   r(  r   anyschemerG   r   r   )rv  rw  resulterrr   r   r   has_url_connectivity~  s8   r  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)rG   )r  r   kwargsr   r   r   maybe_get_address  s
   r  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.
    )rh   r  	ipaddress
ip_addressr   r   r   r   is_ip_address     	r  c                 C   r  )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.
    )rh   r  r  IPv4Addressr  r   r   r   is_ipv4_address  r  r  c                 C   r  )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.
    )rh   r  r  IPv6Addressr  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   )rh   r  r  
ip_networkr  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  )rh   r  r  IPv4Networkr  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  )rh   r  r  IPv6Networkr  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  )r  r  r  )r   r  r  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  rG   r7   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.rc   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   r  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  )r  r  	prefixlen)maskr   r   r   ipv4_mask_to_net_prefixE  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')	r  r  r  rG   r  r   min
IPV6LENGTH
bit_length)r  r  r  mask_inttrailing_zeroesleading_onesall_onesr   r   r   ipv6_mask_to_net_prefixQ  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   r  r  broadcast_address)r  r  r   r   r   mask_and_ipv4_to_bcast_addrt  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)lr-   	functoolsr  loggingrS   r   typingr   r   r   r   r   r   urllib.parser   	cloudinitr	   r
   cloudinit.net.netops.iproute2r   cloudinit.url_helperr   r   	getLoggerr   r7   r$   r   r  rl   r  r#   r%   r+   rA   rF   rI   rO   rV   rX   r[   r`   rb   re   	lru_cacherh   rk   r   rt   r   rv   r|   r   r   r   rx   ry   r   r   rw   r   r   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r;  r>  rB  r   rI  rC  rD  rE  rF  r   rl  ru  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r   r  r   r   r   r   <module>   s    



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

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