
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
cj                 @   sJ  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j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j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(d1d2 Z)ej*dd3e+d4d5d6Z,ej*dd3e-d4d7d8Z.e/e+d9d:d;Z0dd<d=Z1d>d? Z2d@dA Z3de+d4dBdCZ4ddDdEZ5ddFdGZ6dHdI Z7dJdK Z8dLdM Z9dNdO Z:dPdQ Z;G dRdS dSe<Z=dTdU Z>e
e/ d4dVdWZ?ee/ d4dXdYZ@e
e/ d4dZd[ZAee/ d4d\d]ZBe
e/ d4d^d_ZCee/ d4d`daZDe
e/ d4dbdcZEee/ d4dddeZFddfdgZGdhdi ZHddkdlZIddndoZJddpdqZKdrds ZLdtdu ZMeNd4dvdwZOe/ee/ dxdydzZPeNd4d{d|ZQeNd4d}d~ZReNd4ddZSeNd4ddZTde+e+e+e+e+e+e+e-dddZUed e
ee/e/e/e/f  ddddZVdd ZWe	e/ef e+dddZXee/dddZYe/e+dddZZe/e+dddZ[e/e+dddZ\e/e+dddZ]e/e+dddZ^e/e+dddZ_e+d4ddZ`e/d4ddZaebd4ddZcebd4ddZde/e/e/dddZeG dd defZgdS )    N)AnyCallableDictListOptionalTuple)urlparse)subputil)UrlErrorreadurlz/sys/class/net/Zeth0dhcp6Z
ipv6_slaaczipv6_dhcpv6-statelesszipv6_dhcpv6-statefulz	ovs-vsctlz--formatZcsvz--no-headingsz	--timeoutZ10z	--columnsnamefind	interfaceztype=internalz([0-9]+)c             C   s   dd t j|| 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 | ]}|j  rt|n|j qS  )isdigitintlower).0textr   r   /usr/lib/python3.6/__init__.py
<listcomp>4   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 | |}ytj|}W np ttfk
r } zPt|dd }	|	tjtjfkrZ|d k	rZ||S |	tj	fkrv|d k	rv||S  W Y d d }~X nX |j
 }|d kr|S y|| S  tk
r } z&|d k	r||S tjd||  W Y d d }~X nX d S )Nerrnoz5Found unexpected (not translatable) value '%s' in '%s)r#   r
   Z	load_fileOSErrorIOErrorgetattrr$   ENOENT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   s2    
r4   c             C   s   dd }t | |||||dS )Nc             S   s   dS )NFr   )r3   r   r   r   on_excp_falseh   s    z(read_sys_net_safe.<locals>.on_excp_false)r0   r/   r1   r.   )r4   )ifacefieldr.   r5   r   r   r   read_sys_net_safeg   s    r8   c             C   s8   t | |}|dkrd S yt|S  tk
r2   d S X d S )NF)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    r@   c             C   s   t jjt| dS )Nbridge)osr"   existsr#   )r!   r   r   r   	is_bridge   s    rD   c             C   s   t jjt| dS )Nbonding)rB   r"   rC   r#   )r!   r   r   r   is_bond   s    rF   c             C   s    t | dd}tjj|r|S dS )z8Return the master path for devname, or None if no mastermaster)r"   N)r#   rB   r"   rC   )r!   r"   r   r   r   
get_master   s    rH   c             C   sH   t | }|dkrdS tjj|d}tjj|d}tjj|pFtjj|S )z@Return a bool indicating if devname's master is a bridge or bondNFrE   rA   )rH   rB   r"   joinrC   )r!   master_pathZbonding_pathZbridge_pathr   r   r   master_is_bridge_or_bond   s    rK   c             C   s,   t | }|dkrdS t| dd}tjj|S )z;Return a bool indicating if devname's master is openvswitchNFzupper_ovs-system)r"   )rH   r#   rB   r"   rC   )r!   rJ   Zovs_pathr   r   r   master_is_openvswitch   s
    rL   c             C   s   t | ddkS )Ntype32)r8   )r!   r   r   r   is_ib_interface   s    rO   )maxsize)returnc              C   s    t tjd} | stjd | S )zDReturn a bool indicating if Open vSwitch is installed in the system.z	ovs-vsctlz<ovs-vsctl not in PATH; not detecting Open vSwitch interfaces)boolr	   Zwhichr,   r-   )retr   r   r   openvswitch_is_installed   s
    rT   c              C   s^   yt j t\} }W n> t jk
rP } z d|jkr>tjd g S  W Y dd}~X n
X | j 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!   rQ   c             C   s,   t  s
dS t }| |kr(tj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)rT   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    rb   c             C   s,   d}y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)r4   	Exception)r!   featuresr   r   r   get_dev_features   s    re   c             C   s*   t | }| s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)re   len)r!   rd   r   r   r   has_netfail_standby_feature   s    rj   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)rH   r^   rj   )r!   ra   r   r   r   is_netfail_master  s    	rl   c             C   st   t | dd}tjj|sdS |dkr,t| }|dkr8dS tjjtj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.
    rG   )r"   FNrk   T)r#   rB   r"   rC   r^   basenamerealpathrj   )r!   ra   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.
    NFrk   T)rH   r^   rj   )r!   ra   r   r   r   r`   :  s    	r`   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4TF)rp   rq   )r8   )r!   ro   r   r   r   
is_renamedR  s    	
rr   c             C   s   t t| d}d|j kS )NueventzDEVTYPE=vlan)strr8   rX   )r!   rs   r   r   r   is_vlana  s    ru   c             C   s0   d}t | d}tjj|r,tjjtj|}|S )z8Return the device driver for net device named 'devname'.Nzdevice/driver)r#   rB   r"   islinkrm   readlink)r!   ra   Zdriver_pathr   r   r   r^   f  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/deviceFN)r8   )r!   Zdev_idr   r   r   device_devidq  s    
rx   c              C   sj   t j st j rtt j S ytjt } W n6 t	k
rd } z|j
t
jkrRg } n W Y d d }~X nX | S )N)r
   
is_FreeBSDis_DragonFlyBSDlistget_interfaces_by_macvaluesrB   listdirr   r%   r$   r(   )devsr3   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$   |  st | t rdS | jddkS )NFconfigZdisabled)
isinstancedictget)cfgr   r   r   is_disabled_cfg  s    r   c               C   s6   t j st j rt S t j s&t j r,t S t S dS )zqGet the list of network interfaces viable for networking.

    @return List of interfaces, sorted naturally.
    N)r
   ry   rz   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   s6   t j st j rt S t j s&t j r,t S t S dS )z.Get the name of the 'fallback' network device.N)r
   ry   rz   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 j 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   s   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     s    r   c              C   s8   t j ddddg\} }| j }|r&|S tt j tdS )zgGet the names of the candidate network devices on FreeBSD.

    @return List of sorted interfaces.
    ifconfigz-lz-uether)r   )r	   r   r   r|   r}   r   )stdoutZ_stderrr}   r   r   r   r     s
    r   c              C   s   t  } | r| d S dS )z_Get the 'fallback' network device name on FreeBSD.

    @return List of sorted interfaces.
    r   N)r   )r   r   r   r   r     s    r   c              C   s`  dt j krtjd n<dd t D } t| rTtjd|  d}t jtj|t jd g }g }xtdddddd	d
D ]\}}}}|dkrqr|j	drtjd| qrt
|d}|r|j| qrtjd| t
|d}|r|j| qrt|d}|dkr |j| qrtjd| qrW g }	xF||gD ]:}
t|
td}
t|
krN|
jt |
jdt |	|
7 }	qW |	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 | r|qS )lo)rr   )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)funcFT)filter_openvswitch_internal2filter_slave_if_master_not_bridge_bond_openvswitchfilter_vlanfilter_without_own_macfilter_zero_maclog_filtered_reasonsr   ZvethzIgnoring veth interface: %scarrierzInterface has no carrier: %sdormantr?   r>   lowerlayerdownr=   zInterface ignored: %s)r   r   )r   r>   r   r=   )r
   Zget_cmdliner,   r-   r   ri   Zlog_timeZudevadm_settleget_interfaces
startswithr;   appendr8   r   r   DEFAULT_PRIMARY_INTERFACEremoveinsert)ZunstablemsgZ	connectedZpossibly_connectedr   _r   r   r?   Zsorted_interfaces
interfacesr   r   r   r     s\    










r   c              C   s   t  } | r| d S dS )z]Get the 'fallback' network device name on Linux.

    @return List of sorted interfaces.
    r   N)r   )r   r   r   r   r   !  s    r   c             C   sv   | sd} t  }|sdS t|r(d|i}ndt|dj i}dd||d}| rdt|}|rd||d d	< ||id
d}|S )zBGenerate network cfg v2 for dhcp on the NIC most likely connected.FNr   
macaddressaddressT)Zdhcp4r   zset-namematchr   ra      )	ethernetsversion)r   rl   r8   r   r^   )Zconfig_driverZtarget_namer   r   ra   Znconfr   r   r   generate_fallback_config-  s$    
r   c             C   sJ   dd }dd }| j d}|dkr*|| S |dkr:|| S td| d S )	Nc             S   s   g }x| j di D ]|}|j ddkr&q|j d}|s6q|j d}|j di j d}|j di j d}|spt|}|s|t|}|j||||g qW |S )	Nr   rM   ZphysicalZmac_addressr   paramsra   	device_id)r   r^   rx   r   )netcfgphysdevsentmacr   ra   r   r   r   r   
_version_1M  s     

z$extract_physdevs.<locals>._version_1c             S   s   g }x| j di j D ]z}|j d}|s*q|j di j d}|sBq|j di j d}|j di j d}|srt|}|s~t|}|j||||g qW |S )Nr   zset-namer   r   ra   r   )r   r}   r^   rx   r   )r   r   r   r   r   ra   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_physdevsL  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.Tr   r      )r   r   r   )r;   r9   )ifnamestrictZassign_typer   r   r   interface_has_own_mac|  s    

r   Tc             C   s   i }x4t  D ]*\}}}}d|||j |t|d||< qW | rtjd}tjdddddd	d
gdd\}}tjddddgdd\}	}t }
x ||	fD ]}|
j|j| qW x,|j	 D ] }|d dkp|d |
k|d< qW |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   ra   r   r   r<   z[0-9]+:\s+(\w+)[@:]ipz-6ZaddrZshowZ	permanentZscopeglobalT)capturez-4r<   Fr   r   )
r   r   r@   r   compiler	   setupdatefindallr}   )Zcheck_downablecur_infor   r   ra   r   ZnmatchZipv6rZ   Zipv4Znics_with_addressesZ	bytes_outdr   r   r   _get_current_rename_info  s(    
 r   c                s  t | stjd d S |d kr$t }i  xF|j D ]:\}}|j }|jdr\|d j |d< ||d< | |< q2W tjd   fdd}dd }d	d
 }	dd }
g }g }g }| }d}d"}dd  fdd}x| D ]\}}}}|r|j }g }||||}|s"|r|jd||f  q|jd}||kr8q|sV|r|jd||f  q|d rd}|d s|r|j||||f  qd|d< |jd|||ff |jd|||ff ||kr|| }|d rd}|d s|r|j||||f  qn|jd|||ff d }x*|d ks,||kr@|d7 }|| }qW |jd||||ff ||d< | }|d r|jd|||ff |jd|||d |ff ||d< | }||7 }qW ||	|
d}t |t | dkrt |rtjd|  ntjd|  n~tjd| ||  xj|| D ]^\}}}}y|j||  W n< t	k
rz } z|jd |||||f  W Y d d }~X nX q W t |rt
d!j|d S )#Nzno interfaces to renamer   r   zDetected interfaces %sc                s   t dd  j 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   T)r   )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>   T)r   )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<   T)r   )r	   )r   r   r   r   r<     s    z_rename_interfaces.<locals>.upz
cirename%dr   c             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   ra   r   Fr   )r   r   ra   r   r   r   r   entry_match  s    z'_rename_interfaces.<locals>.entry_matchc                sT    fddj  D }t|rPt|dkrHd| f }t||d S d S )Nc                s   g | ]}| r|qS r   r   )r   r   )r   ra   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}   ri   r9   )r   ra   r   r   r   )r   r   )r   ra   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   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
)ri   r,   r-   r   itemscopyr   r   r   rc   r   rI   )renamesZstrict_presentZstrict_busyZcurrent_infor   r   r   r   r   r>   r<   ZopserrorsZupsZ
cur_bynameZtmpname_fmtZtmpir   r   new_namera   r   Zcur_opsZcur_namer   targetZtmp_nameZopmapopr   r3   r   )r   r   r   _rename_interfaces  s    










*
r   c             C   s$   d}t jjt| drd}t| |S )z6Returns the string value of an interface's MAC Addressr   Zbonding_slavezbonding_slave/perm_hwaddr)rB   r"   isdirr#   r8   )r   r"   r   r   r   get_interface_mac]  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.
    rM   rN   $      3   Ni)r8   r   )r   Zethernet_formatr   r   r   r   get_ib_interface_hwaddrg  s
    r   c               C   s<   t j st j rt S t j r$t S t j r2t S t S d S )N)	r
   ry   rz    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|   u  s    r|   )r   rQ   c             C   s0   x*t  j D ]\}}| j |j kr|S qW d S )N)r|   r   r   )r   Zinterface_macZinterface_namer   r   r   find_interface_name_from_mac  s    r   c              C   s>   t j dddg\} }dd }dd }dd	 ||| D }|S )
Nr   z-ar   c             s   sD   d}x4| j dD ]&}|jdr(||7 }q|r2|V  |}qW |V  d S )Nr   r   	)r   r   )rY   Z
curr_blockliner   r   r   flatten  s    

z1get_interfaces_by_mac_on_freebsd.<locals>.flattenc             s   s8   x2| D ]*}t jd|}|r|jd|jdfV  qW 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	   )rY   r   r   r   resultsr   r   r   r     s
    r   c              C   sf   i } d}t j ddg\}}tjdd|j }x4|D ],}tj||}|r2|j }|d | |d < q2W | S )NzE(?P<ifname>\w+).*address:\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   z-az\n\s+ r   r   )r	   r   subrX   r   	groupdict)rS   re_field_matchrY   r   if_linesr   r   fieldsr   r   r   r     s    
r   c              C   sf   i } d}t j ddg\}}tjdd|j }x4|D ],}tj||}|r2|j }|d | |d < q2W | S )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   z-az\n\s+r   r   r   )r	   r   r   rX   r   r   )rS   r   rY   r   r   r   r   r   r   r   r   r     s    
r   c              C   s   i } xt  D ]\}}}}|| krX|dkr>tjd|| | | qd|| | |f }t||| |< t|d}|r|| kr|| |< qtjd|| | | qW | 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   r   r  )r   r,   r-   r   r   warning)rS   r   r   ra   Z_devidr   ib_macr   r   r   r     s4    


r   )filter_hyperv_vf_with_syntheticr   r   r   r   r   r   rQ   c             C   s0  |r
t jndd }g }t }	djd}
x|	D ]}|r@t| r@q,t|rT|d| q,|rbt|rbq,t|rv|d| q,|rt|dk	rt	| rt
| rq,t|r|d	| q,t|}|s|d
| q,|r|dkr||
dt| krq,|ot| rq,t|}|j|||t|f q,W | r,t|| |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 )Nr   )argsr   r   r   <lambda>  s    z get_interfaces.<locals>.<lambda>:00   zIgnoring bridge interface: %szIgnoring bond interface: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %sr   )r  )r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  )r,   r-   r   rI   r   rD   ru   rF   rH   rK   rL   rb   r   ri   r]   r^   r   rx   )filter_hyperv_vf_with_synthetic_interface)r  r   r   r   r   r   r   filtered_loggerrS   r   Zzero_macr   r   ra   r   r   r   r   
  sJ    







 
r   .)r  r   rQ   c                s\   dd |D   fdd|D }x6|D ].}|\}}}}| d|| | | |j | q&W 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   r   Z  s   z=filter_hyperv_vf_with_synthetic_interface.<locals>.<dictcomp>c                s(   g | ] }|d   kr|d dkr|qS )r   r   r  r   )r   r  )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   )r  r   Zinterfaces_to_remover   r   r   ra   r   r   )r  r   r
  F  s    

r
  c              C   sT   i } xJt  D ]@\}}}}t|d}|r|| krDtd|| | |f || |< qW | 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   )rS   r   r   r  r   r   r   get_ib_hwaddrs_by_interfacep  s    
r  )url_datarQ   c             C   s   d| krt jd|  dS | d }y6t|}t|jdk|jdkgsTt jd|j dS W n, tk
r } zt jd| dS d}~X nX d	| krd
| d	< ytf |  W n tk
r   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   anyschemer9   r   r   )r  r  resulterrr   r   r   has_url_connectivity  s,    r  )convert_to_addressr   c             K   s&   y| |f|S  t k
r    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   rQ   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.
    )rR   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.
    )rR   r  r  ZIPv4Address)r   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.
    )rR   r  r  ZIPv6Address)r   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   )rR   r  r  
ip_network)r   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.
    F)r   )rR   r  r  IPv4Network)r   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.
    F)r   )rR   r  r  ZIPv6Network)r   r   r   r   is_ipv6_network  s    	r$  c             C   s@   | d j ds| d tkrdS | d dkr<t| jdr<dS dS )z:Common helper for checking network_state subnets for ipv6.rM   6TZstaticr   F)endswithIPV6_DYNAMIC_TYPESr  r   )Zsubnetr   r   r   subnet_is_ipv6  s
    r(  c             C   s   t tj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.z0.0.0.0/)rt   r  r"  netmask)prefixr   r   r   net_prefix_to_ipv4_mask  s    r+  c             C   s   t j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
    z0.0.0.0/)r  r   	prefixlen)maskr   r   r   ipv4_mask_to_net_prefix  s    	r.  c             C   s   yt jd|  j}|S  tk
r*   Y nX t j| }t|}|dkrJ|S tt j| |d @ j }||? }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"    

r1  )r-  r   rQ   c             C   s   t tj| d|  ddjS )zCGet string representation of broadcast address from an ip/mask pairr    F)r   )rt   r  r"  Zbroadcast_address)r-  r   r   r   r   mask_and_ipv4_to_bcast_addrL  s    r2  c               @   s   e Zd ZdS )RendererNotFoundErrorN)r   r   r   r   r   r   r   r3  S  s   r3  )r   )NNNN)N)N)N)N)N)N)F)T)TTN)TTTTTTF).N)hr$   	functoolsr  ZloggingrB   r   Ztypingr   r   r   r   r   r   Zurllib.parser   Z	cloudinitr	   r
   Zcloudinit.url_helperr   r   Z	getLoggerr   r,   r   r   r'  rU   r   r   r   r#   r4   r8   r;   r@   rD   rF   rH   rK   rL   rO   	lru_cacherR   rT   r{   r\   rt   r]   rb   re   rj   rl   r_   r`   rr   ru   r^   rx   r   rc   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.  r1  r2  r   r3  r   r   r   r   <module>   s    

   



	





!
	
I
0

/
 
H      5''	#