o
    w7e2                     @   sv  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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.Z0dd/d0Z1d1d2 Z2d3d4 Z3dd'e+fd5d6Z4dd7d8Z5dd9d:Z6d;d< Z7d=d> Z8d?d@ Z9dAdB Z:dCdD Z;G dEdF dFe<Z=dGdH Z>d'e
e/ fdIdJZ?d'ee/ fdKdLZ@d'e
e/ fdMdNZAd'ee/ fdOdPZBd'e
e/ fdQdRZCd'ee/ fdSdTZDd'e
e/ fdUdVZEd'ee/ fdWdXZFddYdZZGd[d\ ZHdd^d_ZIddadbZJ	ddcddZKdedf ZLdgdh ZMd'eNfdidjZOdke/d'ee/ fdldmZPd'eNfdndoZQd'eNfdpdqZRd'eNfdrdsZSd'eNfdtduZT	`	`	`	`	`	`	]ddve+dwe+dxe+dye+dze+d{e+d|e+d'e-fd}d~ZUded de
ee/e/e/e/f  d'dfddZVdd ZWde	e/ef d'e+fddZXdede/fddZYde/d'e+fddZZde/d'e+fddZ[de/d'e+fddZ\de/d'e+fddZ]de/d'e+fddZ^de/d'e+fddZ_d'e+fddZ`d'e/fddZad'ebfddZcd'ebfddZdde/de/d'e/fddZeG dd defZgdS )    N)AnyCallableDictListOptionalTuple)urlparse)subputil)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>3   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_path9   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_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_netB   s<   
	
r@   c                 C   s   dd }t | |||||dS )Nc                 S   s   dS NFr   )r>   r   r   r   on_excp_falseh   s   z(read_sys_net_safe.<locals>.on_excp_false)r:   r9   r;   r8   )r@   )ifacefieldr8   rB   r   r   r   read_sys_net_safeg   s   rE   c                 C   s6   t | |}|du rd S zt|W S  ty   Y d S w rA   )rE   r   
ValueError)rC   rD   valr   r   r   read_sys_net_intu   s   

rH   c                 C   s   dddd}t | d|dS )NTF)upunknowndown	operstate)r8   rE   )r(   r8   r   r   r   is_up   s   rN   c                 C      t jt| dS )Nbridgeosr)   existsr*   r(   r   r   r   	is_bridge   r+   rU   c                 C   rO   )NbondingrQ   rT   r   r   r   is_bond   r+   rW   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*   rR   r)   rS   r'   r   r   r   
get_master   s   rZ   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 bondNFrV   rP   )rZ   rR   r)   joinrS   )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-systemrY   )rZ   r*   rR   r)   rS   )r(   r\   ovs_pathr   r   r   master_is_openvswitch   s
   ra   c                 C   s   t | ddkS )Ntype32rM   rT   r   r   r   is_ib_interface   s   rd   )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	   whichr6   r7   )retr   r   r   openvswitch_is_installed   s   rj   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stderrr6   info
splitlines)out_errexcr   r   r   get_ovs_internal_interfaces   s   

rs   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)rj   rs   r6   r7   )r(   ovs_bridgesr   r   r   !is_openvswitch_internal_interface   s   ru   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)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   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rZ   rv   r   ry   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.
    rX   rY   FNr   T)r*   rR   r)   rS   rv   basenamerealpathr   )r(   rz   master_sysfs_pathmaster_devnamemaster_drivermaster_has_standbyr   r   r   rw     s   rw   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   ry   r   r   r   rx   :  r   rx   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4TFrM   )r(   r   r   r   r   
is_renamedR  s   
	r   c                 C   s   t t| d}d| v S )NueventzDEVTYPE=vlan)strrE   ro   )r(   r   r   r   r   is_vlana  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*   rR   r)   islinkr   readlink)r(   rz   driver_pathr   r   r   rv   f  s
   
rv   c                 C   s   t | d}|du rdS |S )z;Return the device id string for net device named 'devname'.zdevice/deviceFNrM   )r(   dev_idr   r   r   device_devidq  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valuesrR   listdirr$   r.   r,   r1   )devsr>   r   r   r   get_devicelistz  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dormantrL   )r   rK   lowerlayerdownrJ   zInterface ignored: %sr   r   )r
   get_cmdliner6   r7   r   r   log_timeudevadm_settleget_interfaces
startswithrH   appendrE   r   r"   DEFAULT_PRIMARY_INTERFACEremoveinsert)unstablemsg	connectedpossibly_connectedr   _r   r   rL   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   st   | sd} t  }|sdS t|rd|i}n	dt|d i}d||d}| r1t|}|r1||d d	< ||id
d}|S )zBGenerate network cfg v2 for dhcp on the NIC most likely connected.FNr   
macaddressaddressT)dhcp4set-namematchr   rz      )	ethernetsversion)r   r   rE   r   rv   )config_drivertarget_namer   r   rz   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   rb   physicalmac_addressr   paramsrz   	device_id)r   rv   r   r   )netcfgphysdevsentmacr   rz   r   r   r   r   
_version_1H  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   rz   r   )r   r   rv   r   r   )r   r   r   r   r   rz   r   r   r   r   
_version_2Z  s    
z$extract_physdevs.<locals>._version_2r      r   z"Unknown network config version: %s)r   RuntimeError)r   r   r   r   r   r   r   extract_physdevsG  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      )rH   rF   )ifnamestrictassign_typer   r   r   interface_has_own_macw  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   rz   r   r   rI   z[0-9]+:\s+(\w+)[@:])ipz-6addrshow	permanentscopeglobalTcapture)r  z-4r  r  rI   Fr   r  )
r   r   rN   r   compiler	   setupdatefindallr   )check_downablecur_infor   r   rz   r   nmatchipv6rq   ipv4nics_with_addresses	bytes_outdr   r   r   _get_current_rename_info  s.   	

r  c                    s  t | std d S |d u rt }i  | D ]\}}| }|dr-|d  |d< ||d< | |< qtd   fdd}dd }d	d
 }	dd }
g }g }g }| }d}d}dd  fdd}| D ]\}}}}|ru| }g }||||}|s|r|d||f  qi|d}||krqi|s|r|d||f  qi|d rd}|d s|r|||||f  qid|d< |d|||ff |d|||ff ||v r<|| }|d rd}|d s|r|||||f  qi|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 }qi||	|
d}t |t | dkrzt |rstd|  nEtd|  n>td | ||  || D ]0\}}}}z
|||  W q t	y } z|d!|||||f  W Y d }~qd }~ww t |rt
d"|d S )#Nzno interfaces to renamer   r   zDetected interfaces %sc                    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   )bymac)r  r   r   update_byname  s   z)_rename_interfaces.<locals>.update_bynamec                 S   s   t j ddd| d|gdd d S )Nr  linkr  r   Tr	  r	   )curnewr   r   r   rename  s   z"_rename_interfaces.<locals>.renamec                 S      t j ddd| dgdd d S )Nr  r  r  rK   Tr	  r  r   r   r   r   rK        z _rename_interfaces.<locals>.downc                 S   r"  )Nr  r  r  rI   Tr	  r  r#  r   r   r   rI     r$  z_rename_interfaces.<locals>.upz
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   rz   r   Fr   )r  r   rz   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   rz   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   rF   )r   rz   r   r   r   r  r&  )r   rz   r   r   
find_entry  s   
z&_rename_interfaces.<locals>.find_entryz<[nic not present] Cannot rename mac=%s to %s, not available.rI   z*[busy] Error renaming mac=%s from %s to %sr  FrK   z2[busy-target] Error renaming mac=%s from %s to %s.r   r!  )r!  rK   rI   r   z(unable to do any work for renaming of %sz$no work necessary for renaming of %sz$achieving renaming of %s with ops %sz.[unknown] Error performing %s%s for %s, %s: %s
)r   r6   r7   r  itemscopyr   r   r   r|   r   r[   )renamesstrict_presentstrict_busycurrent_infor   r  r  r  r!  rK   rI   opserrorsups
cur_bynametmpname_fmttmpir(  r   new_namerz   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)rR   r)   isdirr*   rE   )r   r)   r   r   r   get_interface_macX  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.
    rb   rc   $   i3   N)rE   r@  )r   ethernet_formatr   r   r   r   get_ib_interface_hwaddrb  s   rD  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
   rK  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   )rp   
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  )rp   r   rP  rV  resultsr   r   r   rE    s
   rE  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   rL  \n\s+ r   r   r	   r   subro   r   	groupdictri   re_field_matchrp   r   if_linesrO  rU  fieldsr   r   r   rF       rF  c                  C   rY  )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   rL  rZ  r[  r   r   r\  r_  r   r   r   rG    rc  rG  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   r6   r7   r   rD  warning)ri   r   r   rz   _devidr   ib_macr   r   r   rH    s<   

rH  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>:)00rn  rn  rn  rn  rn  rn  rn  rn  rn  rn  rn  rn  rn  rn  rn  zIgnoring bridge interface: %szIgnoring bond interface: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %sr   )r6   r7   r   r[   r  rU   r   rW   rZ   r_   ra   r{   r@  r   ru   rv   r   r   )filter_hyperv_vf_with_synthetic_interface)rj  r   r   r   r   r   r   filtered_loggerri   r   zero_macr   r   rz   r   r   r   r     sR   




 
r   rp  ).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   rW  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   rr  r   rs  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   )rp  r   interfaces_to_remover   r   r   rz   r   r   ru  r   ro  A  s"   
ro  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   rD  r   )ri   r   r   ri  r   r   r   get_ib_hwaddrs_by_interfacek  s   
rx  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   )r6   rg  r   anyschemerF   r   r   )ry  rz  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)rF   )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.
    )rg   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.
    )rg   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.
    )rg   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   )rg   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  )rg   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  )rg   r  r  IPv6Networkr  r   r   r   is_ipv6_network  r  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.rb   6Tstaticr   F)endswithIPV6_DYNAMIC_TYPESr  r   )subnetr   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_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')	r  r  r  rF   r  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   r  r  broadcast_address)r  r  r   r   r   mask_and_ipv4_to_bcast_addrE  s   r  c                   @   s   e Zd ZdS )RendererNotFoundErrorN)r   r   r   r   r   r   r   r  L  s    r  )r%   )NNNNr   )F)T)TTN)TTTTTTF)hr,   	functoolsr  loggingrR   r   typingr   r   r   r   r   r   urllib.parser   	cloudinitr	   r
   cloudinit.url_helperr   r   	getLoggerr   r6   r#   r   r  rk   r  r"   r$   r*   r@   rE   rH   rN   rU   rW   rZ   r_   ra   rd   	lru_cacherg   rj   r   rs   r   ru   r{   r   r   r   rw   rx   r   r   rv   r   r   r|   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r=  r@  rD  r   r   rK  rE  rF  rG  rH  r   ro  rx  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
<
*'	#