U
    Ad;                     @   st  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 d dlmZmZ d dlmZmZ eeZdZdZdd	d
dgZdddddddddddg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/d0 Z'ej(dd1e)d2d3d4Z*ej(dd1e+d2d5d6Z,e-e)d7d8d9Z.dd:d;Z/d<d= Z0d>d? Z1de)d2d@dAZ2ddBdCZ3ddDdEZ4dFdG Z5dHdI Z6dJdK Z7dLdM Z8dNdO Z9G dPdQ dQe:Z;dRdS Z<dee
e-  e
e- dTdUdVZ=dee
e-  ee- dTdWdXZ>dee
e-  e
e- dTdYdZZ?dee
e-  ee- dTd[d\Z@dee
e-  e
e- dTd]d^ZAdee
e-  ee- dTd_d`ZBdee
e-  e
e- dTdadbZCdee
e-  ee- dTdcddZDddedfZEdgdh ZFddjdkZGddmdnZHddodpZIdqdr ZJdsdt ZKdeLd2dudvZMe-ee- dwdxdyZNdeLd2dzd{ZOdeLd2d|d}ZPdeLd2d~dZQdeLd2ddZRde+d2ddZSdd ZTe	e-ef e)dddZUee-dddZVe-e)dddZWe-e)dddZXe-e)dddZYe-e)dddZZe-e)dddZ[e-e)dddZ\e)d2ddZ]e-d2ddZ^e_d2ddZ`e_d2ddZae-e-e-dddZbG dd decZddS )    N)AnyCallableDictListOptional)urlparse)subputil)UrlErrorreadurlz/sys/class/net/Zeth0Zdhcp6Z
ipv6_slaaczipv6_dhcpv6-statelesszipv6_dhcpv6-stateful	ovs-vsctlz--formatZcsvz--no-headingsz	--timeoutZ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)sZ_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>   s    r#   c           
   
   C   s
  t | |}zt|}W n ttfk
r } z^t|dd }	|	tjtjfkrb|d k	rb|| W Y ,S |	tj	fkr|d k	r|| W Y S  W 5 d }~X Y nX |
 }|d kr|S z
|| W S  tk
r } z,|d k	r|| W Y S td||  W 5 d }~X Y nX d S )Nerrnoz5Found unexpected (not translatable) value '%s' in '%s)r#   r	   Z	load_fileOSErrorIOErrorgetattrr$   ENOENTZENOTDIRZEINVALstripKeyErrorLOGdebug)
r!   r"   	translate	on_enoenton_keyerror	on_einvalZdev_pathcontentseZe_errnor   r   r   read_sys_netB   s4    

r3   c                 C   s   dd }t | |||||dS )Nc                 S   s   dS NFr   )r2   r   r   r   on_excp_falseh   s    z(read_sys_net_safe.<locals>.on_excp_false)r/   r.   r0   r-   )r3   )ifacefieldr-   r5   r   r   r   read_sys_net_safeg   s    r8   c                 C   s<   t | |}|dkrd S z
t|W S  tk
r6   Y d S X d S r4   )r8   r   
ValueError)r6   r7   valr   r   r   read_sys_net_intu   s    

r;   c                 C   s   dddd}t | d|dS )NTF)upunknowndown	operstate)r-   r8   )r!   r-   r   r   r   is_up   s    rA   c                 C   s   t jt| dS )Nbridgeosr"   existsr#   r!   r   r   r   	is_bridge   s    rG   c                 C   s   t jt| dS )NbondingrC   rF   r   r   r   is_bond   s    rI   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#   rD   r"   rE   r    r   r   r   
get_master   s    rL   c                 C   sH   t | }|dkrdS tj|d}tj|d}tj|pFtj|S )z@Return a bool indicating if devname's master is a bridge or bondNFrH   rB   )rL   rD   r"   joinrE   )r!   master_pathZbonding_pathZbridge_pathr   r   r   master_is_bridge_or_bond   s    rO   c                 C   s,   t | }|dkrdS t| dd}tj|S )z;Return a bool indicating if devname's master is openvswitchNFzupper_ovs-systemrK   )rL   r#   rD   r"   rE   )r!   rN   Zovs_pathr   r   r   master_is_openvswitch   s
    rP   )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   Zwhichr+   r,   )retr   r   r   openvswitch_is_installed   s    rU   c               
   C   sf   zt  t\} }W nF t jk
rX } z&d|jkrFtd g  W Y S  W 5 d}~X Y n
X |  S dS )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_CMDZProcessExecutionErrorstderrr+   info
splitlines)out_errexcr   r   r   get_ovs_internal_interfaces   s    
r]   )r!   rR   c                 C   s,   t  s
dS t }| |k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)rU   r]   r+   r,   )r!   Zovs_bridgesr   r   r   !is_openvswitch_internal_interface   s    r^   c                 C   s,   |dk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     rd   c                 C   s,   d}zt | d}W n tk
r&   Y nX |S )zDReturns a str from reading /sys/class/net/<devname>/device/features.r   zdevice/features)r3   	Exceptionr!   Zfeaturesr   r   r   get_dev_features   s    rg   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)rg   lenrf   r   r   r   has_netfail_standby_feature   s    rl   c                 C   s<   t | dk	rdS |dkr t| }|dkr,dS t| s8d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rL   r_   rl   rb   r   r   r   is_netfail_master   s    	ro   c                 C   st   t | dd}tj|sdS |dkr,t| }|dkr8dS tjtj|}t|}|dkr`dS t|}|spd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.
    rJ   rK   FNrm   T)r#   rD   r"   rE   r_   basenamerealpathrl   )r!   rc   Zmaster_sysfs_pathZmaster_devnameZmaster_driverZmaster_has_standbyr   r   r   r`     s    r`   c                 C   s<   t | dkrdS |dkr t| }|dkr,dS t| s8d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.
    NFrm   Trn   rb   r   r   r   ra   6  s    	ra   c                 C   s   t | d}|r|dk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4TFr@   )r!   rr   r   r   r   
is_renamedN  s    	
ru   c                 C   s   t t| d}d| kS )NueventzDEVTYPE=vlan)strr8   rY   )r!   rv   r   r   r   is_vlan]  s    rx   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#   rD   r"   islinkrp   readlink)r!   rc   Zdriver_pathr   r   r   r_   b  s
    
r_   c                 C   s   t | d}|dkrdS |S )z;Return the device id string for net device named 'devname'.zdevice/deviceFNr@   )r!   Zdev_idr   r   r   device_devidm  s    
r{   c               
   C   sj   t  st  rtt  S ztt } W n6 t	k
rd } z|j
t
jkrRg } n W 5 d }~X Y nX | S N)r	   
is_FreeBSDis_DragonFlyBSDlistget_interfaces_by_macvaluesrD   listdirr   r%   r$   r(   )devsr2   r   r   r   get_devicelistv  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configZdisabled)
isinstancedictget)cfgr   r   r   is_disabled_cfg  s    r   )blacklist_driversrR   c                 C   s<   t  st  rt| S t  s(t  r0t| S t| S dS )zqGet the list of network interfaces viable for networking.

    @return List of interfaces, sorted naturally.
    N)r	   r}   r~   find_candidate_nics_on_freebsd	is_NetBSD
is_OpenBSD(find_candidate_nics_on_netbsd_or_openbsdfind_candidate_nics_on_linuxr   r   r   r   find_candidate_nics  s
    r   c                 C   s<   t  st  rt| S t  s(t  r0t| S t| S dS )z.Get the name of the 'fallback' network device.N)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 )zGet the names of the candidate network devices on NetBSD/OpenBSD.

    @param blacklist_drivers: currently ignored
    @return list of sorted interfaces
    key)sortedr   r   r   r   r   r   r   r     s    r   c                 C   s   t | }|r|d S dS )zGet the 'fallback' network device name on NetBSD/OpenBSD.

    @param blacklist_drivers: currently ignored
    @return default interface, or None
    r   N)r   r   namesr   r   r   r     s    r   c                 C   s8   t  ddddg\}}| }|r&|S tt  tdS )zGet the names of the candidate network devices on FreeBSD.

    @param blacklist_drivers: Currently ignored.
    @return List of sorted interfaces.
    ifconfigz-lz-uetherr   )r   r   r   r   r   r   )r   stdoutZ_stderrr   r   r   r   r     s
    r   c                 C   s   t | }|r|d S dS )zGet the 'fallback' network device name on FreeBSD.

    @param blacklist_drivers: Currently ignored.
    @return List of sorted interfaces.
    r   N)r   r   r   r   r   r     s    r   c                 C   s  | sg } dt  k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krzqjt|}|| krtd	|| qjt	|d
std| qj|
drtd| qjt|rtd| qjt|rtd| qjt|rtd| qjt|d}|r*|| qjtd| t|d}|rR|| qjt	|d}	|	dkrr|| qjtd| qjg }
||fD ]:}t|td}t|kr|t |dt |
|7 }
q|
S )zGet the names of the candidate network devices on Linux.

    @param blacklist_drivers: Filter out NICs with these drivers.
    @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)ru   )r   Z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)funcr   z%Ignoring interface with %s driver: %saddressz"Ignoring interface without mac: %sZvethzIgnoring veth interface: %szIgnoring bridge interface: %szIgnoring bond interface: %szIgnoring failover interface: %scarrierzInterface has no carrier: %sdormantr?   )r   r>   Zlowerlayerdownr=   zInterface ignored: %sr   r   )r	   Zget_cmdliner+   r,   r   rk   Zlog_timeZudevadm_settler_   r8   
startswithrG   rI   rd   r;   appendr   r   DEFAULT_PRIMARY_INTERFACEremoveinsert)r   ZunstablemsgZ	connectedZpossibly_connectedr   rc   r   r   r?   Zsorted_interfacesZ
interfacesr   r   r   r     s      











r   c                 C   s   t | }|r|d S dS )zGet the 'fallback' network device name on Linux.

    @param blacklist_drivers: Ignore devices with these drivers.
    @return List of sorted interfaces.
    r   N)r   r   r   r   r   r   >  s    r   c                 C   sx   |sd}t | d}|sdS t|r,d|i}ndt|d i}d||d}|rft|}|rf||d	 d
< ||idd}|S )zBGenerate network cfg v2 for dhcp on the NIC most likely connected.Fr   Nr   
macaddressr   T)Zdhcp4set-namematchr   rc      )	ethernetsversion)r   ro   r8   r   r_   )r   Zconfig_driverZtarget_namer   r   rc   Znconfr   r   r   generate_fallback_configM  s"    

 r   c                 C   sJ   dd }dd }|  d}|dkr*|| S |dkr:|| S td| d S )	Nc                 S   s   g }|  di D ]|}| ddkr$q| d}|s4q| d}| di  d}| di  d}|snt|}|szt|}|||||g q|S )	Nr   typeZphysicalZmac_addressr   paramsrc   	device_id)r   r_   r{   r   )netcfgphysdevsentmacr   rc   r   r   r   r   
_version_1h  s     

z$extract_physdevs.<locals>._version_1c                 S   s   g }|  di  D ]z}| d}|s(q| di  d}|s@q| di  d}| di  d}|spt|}|s|t|}|||||g q|S )Nr   r   r   r   rc   r   )r   r   r_   r{   r   )r   r   r   r   r   rc   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kr"|rtddS |dk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_addressZaddr_assign_typeNz%s had no addr_assign_type.T)r   r      )r;   r9   )ifnamestrictZassign_typer   r   r   interface_has_own_mac  s    

r   Tc                 C   s   i }t  D ]*\}}}}d||| |t|d||< q
| rtd}tjdddddd	d
gdd\}}tjddddgdd\}	}t }
||	fD ]}|
|| q|	 D ] }|d dkp|d |
k|d< q|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   rc   r   r   r<   z[0-9]+:\s+(\w+)[@:]ipz-6ZaddrZshowZ	permanentZscopeglobalTZcapturez-4r<   Fr   r   )
get_interfacesr   rA   r   compiler   setupdatefindallr   )Zcheck_downablecur_infor   r   rc   r   ZnmatchZipv6r[   Zipv4Znics_with_addressesZ	bytes_outdr   r   r   _get_current_rename_info  s.    	

r   c                    s  t | std d S |d kr$t }i  | D ]:\}}| }|drZ|d  |d< ||d< | |< q0td   fdd}dd }d	d
 }	dd }
g }g }g }| }d}d}dd  fdd}| D ]\}}}}|r| }g }||||}|s|r|d||f  q|d}||kr0q|sN|r|d||f  q|d rd}|d s|r|||||f  qd|d< |d|||ff |d|||ff ||krz|| }|d r
d}|d s|r|||||f  qn|d|||ff d }|d ks"||kr6|d7 }|| }q|d||||ff ||d< | }|d rz|d|||ff |d|||d |ff ||d< | }||7 }q||	|
d}t |t | dkrt |rtd|  ntd|  nztd | ||  || D ]^\}}}}z|||  W n< t	k
rj } z|d!|||||f  W 5 d }~X Y nX q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   )Z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   s   t j ddd| dgdd d S )Nr   r   r   r>   Tr   r   r   r   r   r   r>     s    z _rename_interfaces.<locals>.downc                 S   s   t j ddd| dgdd d S )Nr   r   r   r<   Tr   r   r   r   r   r   r<     s    z_rename_interfaces.<locals>.upz
cirename%dc                 S   sd   |r0|r0|r0| d |ko.| d |ko.| d |kS |rP|rP| d |koN| d |kS |r`| d |kS dS )zmatch if set and in datar   rc   r   Fr   )r   r   rc   r   r   r   r   entry_match  s    

z'_rename_interfaces.<locals>.entry_matchc                    sT    fdd  D }t|rPt|dkrHd| f }t||d S d S )Nc                    s   g | ]}| r|qS r   r   r   )r   rc   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   rk   r9   )r   rc   r   r   r   r   r   )r   rc   r   r   
find_entry  s    
z&_rename_interfaces.<locals>.find_entryz<[nic not present] Cannot rename mac=%s to %s, not available.r<   z*[busy] Error renaming mac=%s from %s to %sr   Fr>   z2[busy-target] Error renaming mac=%s from %s to %s.r   r   )r   r>   r<   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
)rk   r+   r,   r   itemscopyr   r   r   re   rM   )renamesZstrict_presentZstrict_busyZcurrent_infor   r   r   r   r   r>   r<   ZopserrorsZupsZ
cur_bynameZtmpname_fmtZtmpir   r   new_namerc   r   Zcur_opsZcur_namer   targetZtmp_nameZopmapopr   r2   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   Zbonding_slavezbonding_slave/perm_hwaddr)rD   r"   isdirr#   r8   )r   r"   r   r   r   get_interface_macx  s    r   c                 C   s>   t | ddkr:t| }|r6|r6|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   Z32$   i3   N)r8   r   )r   Zethernet_formatr   r   r   r   get_ib_interface_hwaddr  s
    r   c                 C   sL   t  st  rt| dS t  r,t| dS t  r>t| dS t| dS d S )Nr   )	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    r   )r   rR   c                 C   s0   t   D ] \}}|  | kr
|  S q
d S r|   )r   r   r   )r   Zinterface_macZinterface_namer   r   r   find_interface_name_from_mac  s    
r   c                 C   s>   t  dddg\}}dd }dd }dd	 |||D }|S )
Nr   -ar   c                 s   s@   d}|  dD ]&}|dr&||7 }q|r0|V  |}q|V  d S )Nr   r   	)r   r   )rZ   Z
curr_blockliner   r   r   flatten  s    

z1get_interfaces_by_mac_on_freebsd.<locals>.flattenc                 s   s4   | 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)Z	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   )r   rZ   _r   r   Zresultsr   r   r   r     s
    r   c           	      C   sb   i }d}t  ddg\}}tdd| }|D ],}t||}|r0| }|d ||d < q0|S )NzE(?P<ifname>\w+).*address:\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   r   \n\s+ r   r   r   r   subrY   r   	groupdict	r   rT   Zre_field_matchrZ   r   Zif_linesr   r   Zfieldsr   r   r   r     s    r   c           	      C   sb   i }d}t  ddg\}}tdd| }|D ],}t||}|r0| }|d ||d < q0|S )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   r   r   r   r   r   r   r  r   r   r   r     s    r   c           
   	   C   s  i }i }t | dD ]\}}}}||krd}d||| |f }||| kr|| dkrtt|d|||| f   q|dkrd}t|d|| || |f   |dks|dkrtd	||| | q|rt||||< |||< t|d}	|	r|	|kr|||	< qtd
|||	 |	 q|S )zmBuild a dictionary of tuples {mac: name}.

    Bridges and any devices that have a 'stolen' mac are excluded.r   Tz6duplicate mac found! both '%s' and '%s' have mac '%s'.Z	hv_netvsczC Ignoring '%s' due to driver '%s' and '%s' having driver hv_netvsc.FZ
mscc_felixZ	fsl_enetcz>Ignoring duplicate macs from '%s' and '%s' due to driver '%s'.z^Ethernet and InfiniBand interfaces have the same address both '%s' and '%s' have address '%s'.)r   r+   warningr,   r   r   )
r   rT   Z
driver_mapr   r   rc   Z_devidZraise_duplicate_mac_errorr   ib_macr   r   r   r     sd    


r   c                 C   s   g }| dkrg } t  }dd}|D ]}t|s2q$t|r<q$t|rFq$t|rPq$t|dk	rnt|snt|snq$t	|rxq$t
|}|sq$|dkr||dt| krq$t|rq$t|}|| krq$||||t|f q$|S )zReturn list of interface tuples (name, mac, driver, device_id)

    Bridges and any devices that have a 'stolen' mac are excluded.N:)00r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   )r   rM   r   rG   rx   rI   rL   rO   rP   rd   r   rk   r^   r_   r   r{   )r   rT   r   Zzero_macr   r   rc   r   r   r   r   I  sF    
r   c                  C   sP   i } t  D ]@\}}}}t|d}|r
|| krBt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   )rT   r   r   r  r   r   r   get_ib_hwaddrs_by_interfacet  s    

r  )url_datarR   c              
   C   s   d| krt d|  dS | d }z8t|}t|jdk|jdkgsVt d|j W dS W n4 tk
r } zt d| W Y dS d}~X Y nX d	| krd
| d	< ztf |  W n tk
r   Y dS X dS )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 %sFZhttpZhttpsz2Ignoring connectivity check. Invalid URL scheme %sz+Ignoring connectivity check. Invalid URL %sNZtimeout   T)r+   r  r   anyZschemer9   r   r
   )r	  r
  resulterrr   r   r   has_url_connectivity  s2     
r  )convert_to_addressr   c                 K   s*   z| |f|W S  t k
r$   Y dS X dS )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

    FN)r9   )r  r   kwargsr   r   r   maybe_get_address  s    r  )r   rR   c                 C   s   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.
    )rS   r  	ipaddress
ip_addressr   r   r   r   is_ip_address  s    	r  c                 C   s   t ttj| S )zReturns a bool indicating if ``s`` is an IPv4 address.

    :param address:
        The string to test.

    :return:
        A bool indicating if the string is an IPv4 address or not.
    )rS   r  r  ZIPv4Addressr  r   r   r   is_ipv4_address  s    	r  c                 C   s   t ttj| S )zReturns a bool indicating if ``s`` is an IPv6 address.

    :param address:
        The string to test.

    :return:
        A bool indicating if the string is an IPv4 address or not.
    )rS   r  r  ZIPv6Addressr  r   r   r   is_ipv6_address  s    	r  c                 C   s   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   )rS   r  r  
ip_networkr  r   r   r   is_ip_network  s    	r  c                 C   s   t ttj| ddS )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  )rS   r  r  IPv4Networkr  r   r   r   is_ipv4_network  s    	r  c                 C   s   t ttj| ddS )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  )rS   r  r  ZIPv6Networkr  r   r   r   is_ipv6_network  s    	r  c                 C   s@   | d  ds| d tk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   6TZstaticr   F)endswithIPV6_DYNAMIC_TYPESr  r   )Z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/)rw   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k
r,   Y nX t | }t|}|dkrL|S tt j| |d @  }||? }t j| }d|> d }||krt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'  r9   r  r   minZ
IPV6LENGTH
bit_length)r(  r'  r$  Zmask_intZtrailing_zeroesZleading_onesZall_onesr   r   r   ipv6_mask_to_net_prefix+  s&    
 
r,  )r(  r   rR   c                 C   s   t tj| d|  ddjS )zCGet string representation of broadcast address from an ip/mask pairr   Fr  )rw   r  r  Zbroadcast_address)r(  r   r   r   r   mask_and_ipv4_to_bcast_addrN  s    r-  c                   @   s   e Zd ZdS )RendererNotFoundErrorN)r   r   r   r   r   r   r   r.  U  s   r.  )r   )NNNN)N)N)N)N)N)N)N)N)N)N)N)N)N)NN)F)T)TTN)N)N)N)N)N)N)er$   	functoolsr  ZloggingrD   r   typingr   r   r   r   r   Zurllib.parser   Z	cloudinitr   r	   Zcloudinit.url_helperr
   r   Z	getLoggerr   r+   r   r   r!  rV   r   r   r   r#   r3   r8   r;   rA   rG   rI   rL   rO   rP   	lru_cacherS   rU   r   r]   rw   r^   rd   rg   rl   ro   r`   ra   ru   rx   r_   r{   r   re   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r  r"  r&  r   r)  r,  r-  r   r.  r   r   r   r   <module>   s  

    
%


	





!
	 
 
 
 
 
 
 
[ 

0

/     
  
c+'	#