
    x[h                        d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZmZm	Z	m
Z
mZ d dlmZmZ d dlmZ  ej"                  e      ZdZdZg dZg dZ ej0                  d	      fd
Zd ZdddZ	 	 	 	 dedZdfdZd Zd Zd Z d Z!d Z"d Z#d Z$d Z% ejL                  d      de'fd       Z( ejL                  d      de)fd       Z*de+de'fdZ,dfdZ-d Z.d Z/dfde'fd Z0dfd!Z1dfd"Z2d# Z3d$ Z4d% Z5d& Z6d' Z7 G d( d)e8      Z9d* Z:de	e+   fd+Z;de
e+   fd,Z<de	e+   fd-Z=de
e+   fd.Z>de	e+   fd/Z?de
e+   fd0Z@de	e+   fd1ZAde
e+   fd2ZBdfde
eC   fd3ZDd4 ZEdgd5ZFdhd6ZG	 did7ZHd8 ZId9 ZJdeCfd:ZKd;e+de
e+   fd<ZLdeCfd=ZMdeCfd>ZNdeCfd?ZOdeCfd@ZP	 	 	 	 	 	 	 djdAe'dBe'dCe'dDe'dEe'dFe'dGe'de)fdHZQdIedJ   dKe	ee+e+e+e+f      ddfdLZRdM ZSdNedOe+fdPZTdOe+de'fdQZUdOe+de'fdRZVdOe+de'fdSZWdOe+de'fdTZXdOe+de'fdUZYdOe+de'fdVZZdOe+dWe+de'fdXZ[dYe+dWe+de'fdZZ\de'fd[Z]de+fd\Z^de_fd]Z`de_fd^Zad_e+d`e+de+fdaZb G db dcec      Zdy)k    N)CallableDictListOptionalTuple)subputil)Iproute2z/sys/class/net/eth0)dhcp6
ipv6_slaaczipv6_dhcpv6-statelesszipv6_dhcpv6-stateful)	ovs-vsctlz--formatcsvz--no-headingsz	--timeout10z	--columnsnamefind	interfaceztype=internalz([0-9]+)c                     t        j                  ||       D cg c]-  }|j                         rt        |      n|j	                         / c}S c c}w )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'].)resplitisdigitintlower)s_nsretexts      8/usr/lib/python3/dist-packages/cloudinit/net/__init__.pynatural_sort_keyr   +   sF     HHUA& \\^D	5  s   2Ac                      t         S )z3Simple function to return the global SYS_CLASS_NET.)SYS_CLASS_NET     r   get_sys_class_pathr#   8   s    r"   c                 (    t               | z   dz   |z   S )N/)r#   devnamepaths     r   sys_dev_pathr)   =   s    ')C/$66r"   c                    t        | |      }	 t        j                  |      }|j                         }||S 	 ||   S # t        t        f$ rf}t        |dd       }	|	t        j                  t        j                  fv r| ||      cY d }~S |	t        j                  fv r| ||      cY d }~S  d }~ww xY w# t        $ r,}| ||      cY d }~S t        j                  d||        d }~ww xY w)Nerrnoz5Found unexpected (not translatable) value '%s' in '%s)r)   r	   load_text_fileOSErrorIOErrorgetattrr+   ENOENTENOTDIREINVALstripKeyErrorLOGdebug)
r'   r(   	translate	on_enoenton_keyerror	on_einvaldev_pathcontentsee_errnos
             r   read_sys_netr?   A   s     GT*H
&&x0 ~~H"" W !Wd+u||U]]33$ |#u||o%$ |#  	"q>!IIG
 	sP   = B5 B28B-B2
B-&B2,B--B25	C*>	C%C*C%%C*c                 *    d }t        | |||||      S )Nc                      yNFr!   )r=   s    r   on_excp_falsez(read_sys_net_safe.<locals>.on_excp_falseg   s    r"   )r9   r8   r:   r7   )r?   )ifacefieldr7   rC   s       r   read_sys_net_saferF   f   s(     ! r"   c                 Z    t        | |      }|du ry 	 t        |      S # t        $ r Y y w xY wrB   )rF   r   
ValueError)rD   rE   vals      r   read_sys_net_intrJ   t   s8    
E5
)C
e|3x s   
 	**c                 *    dddd}t        | d|      S )NTF)upunknowndown	operstate)r7   rF   )r'   r7   s     r   is_uprQ   ~   s     e<IWkYGGr"   c                 T    t         j                  j                  t        | d            S )Nbridgeosr(   existsr)   r'   s    r   	is_bridgerX      s    77>>,w9::r"   c                 T    t         j                  j                  t        | d            S )NbondingrT   rW   s    r   is_bondr[      s    77>>,w	:;;r"   c                 `    t        | d      }t        j                  j                  |      r|S y)z8Return the master path for devname, or None if no mastermasterr(   N)r)   rU   r(   rV   r&   s     r   
get_masterr_      s&    h/D	ww~~dr"   c                    t        |       }|yt        j                  j                  |d      }t        j                  j                  |d      }t        j                  j	                  |      xs t        j                  j	                  |      S )z@Return a bool indicating if devname's master is a bridge or bondFrZ   rS   )r_   rU   r(   joinrV   )r'   master_pathbonding_pathbridge_paths       r   master_is_bridge_or_bondre      sb    W%K77<<Y7L'',,{H5K77>>,'F277>>++FFr"   c                 v    t        |       }|yt        | d      }t        j                  j	                  |      S )z;Return a bool indicating if devname's master is openvswitchFzupper_ovs-systemr^   )r_   r)   rU   r(   rV   )r'   rb   ovs_paths      r   master_is_openvswitchrh      s5    W%KG*<=H77>>(##r"   c                      t        | d      dk(  S )Ntype32rP   rW   s    r   is_ib_interfacerl      s    Wf-55r"   )maxsizereturnc                  p    t        t        j                  d            } | st        j	                  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   whichr5   r6   )rets    r   openvswitch_is_installedrs      s0     tzz+&
'C		J	
 Jr"   c                      	 t        j                   t              \  } }| j                         S # t         j                  $ r0}d|j                  v rt
        j                  d       g cY d}~S  d}~ww xY 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
splitlinesProcessExecutionErrorstderrr5   info)out_errexcs      r   get_ovs_internal_interfacesr}      sh     II?@	T ~~ %% '3::5HH  Is!   . A1$A,%A1+A,,A1r'   c                 d    t               syt               }| |v rt        j                  d|        yy)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)rs   r}   r5   r6   )r'   ovs_bridgess     r   !is_openvswitch_internal_interfacer      s2    
 $%-/K+		3W=r"   c                 P    |t        |       }t        | |      st        | |      ryy)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.
    TF)device_driveris_netfail_primaryis_netfail_standbyr'   drivers     r   is_netfailoverr      s2    
 ~w''6*.@/ r"   c                 D    d}	 t        | d      }|S # t        $ r Y |S w xY w)zDReturns a str from reading /sys/class/net/<devname>/device/features. zdevice/features)r?   	Exceptionr'   featuress     r   get_dev_featuresr      s9    H):; O  Os    	c                 J    t        |       }|rt        |      dk  ry|d   dk(  S )zReturn True if VIRTIO_NET_F_STANDBY bit (62) is set.

    https://github.com/torvalds/linux/blob/         089cf7f6ecb266b6a4164919a2e69bd2f938374a/         include/uapi/linux/virtio_net.h#L60
    @   F>   1)r   lenr   s     r   has_netfail_standby_featurer      s.      (Hs8}r)B<3r"   c                 Z    t        |       y|t        |       }|dk7  ryt        |       syy)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.
    F
virtio_netTr_   r   r   r   s     r   is_netfail_masterr      s:     '&~w'&w/r"   c                 :   t        | d      }t        j                  j                  |      sy|t	        |       }|dk(  ryt        j                  j                  t        j                  j                  |            }t	        |      }|dk7  ryt        |      }|syy)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.
    r]   r^   Fr   T)r)   rU   r(   rV   r   basenamerealpathr   )r'   r   master_sysfs_pathmaster_devnamemaster_drivermaster_has_standbys         r   r   r     s     %W8<77>>+,~w'WW%%bgg&6&67H&IJN!.1M$4^Dr"   c                 Z    t        |       y|t        |       }|dk7  ryt        |       syy)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.
    Fr   Tr   r   s     r   r   r   9  s:     '"~w'&w/r"   c                 *    t        | d      }|r|dv ryy)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4TFrP   )r'   r   s     r   
is_renamedr   Q  s#     )2DE,
:r"   c                 P    t        t        | d            }d|j                         v S )NueventzDEVTYPE=vlan)strrF   rv   )r'   r   s     r   is_vlanr   `  s(    "7H56FV..000r"   c                     d}t        | d      }t        j                  j                  |      r2t        j                  j	                  t        j
                  |            }|S )z8Return the device driver for net device named 'devname'.Nzdevice/driver)r)   rU   r(   islinkr   readlink)r'   r   driver_paths      r   r   r   e  sE    Fw8K	ww~~k"!!"++k":;Mr"   c                 (    t        | d      }|du ry|S )z;Return the device id string for net device named 'devname'.zdevice/deviceFNrP   )r'   dev_ids     r   device_devidr   p  s    w8FMr"   c                  D   t        j                         st        j                         r!t        t	               j                               S 	 t        j                  t                     } | S # t        $ r,}|j                  t        j                  k(  rg } n Y d }~| S d }~ww xY wN)r	   
is_FreeBSDis_DragonFlyBSDlistget_interfaces_by_macvaluesrU   listdirr#   r-   r+   r0   )devsr=   s     r   get_devicelistr   y  s    D002)+22455zz,./ K  77ell"D  Ks   A* *	B3!BBc                       e Zd ZdZy)ParserErrorz6Raised when a parser has issue parsing a file/content.N)__name__
__module____qualname____doc__r!   r"   r   r   r     s    @r"   r   c                 P    | rt        | t              sy| j                  d      dk(  S )NFconfigdisabled)
isinstancedictget)cfgs    r   is_disabled_cfgr     s%    jd+778
**r"   c                      t        j                         st        j                         r
t               S t        j                         st        j
                         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   find_candidate_nicsr     sG    
 D002-//		T__.799+--r"   c                      t        j                         st        j                         r
t               S t        j                         st        j
                         r
t               S t               S )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   find_fallback_nicr     sE    D002+--		T__.577)++r"   c                  P    t        t               j                         t              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    
 ')0028HIIr"   c                  &    t               } | r| d   S y)zfGet the 'fallback' network device name on NetBSD/OpenBSD.

    @return default interface, or None
    r   N)r   namess    r   r   r     s    
 56EQxr"   c                      t        j                   g d      \  } }| j                         }|r|S t        t               j	                         t
              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   s      r   r   r     sG    
 ii ABOFG\\^F ')0028HIIr"   c                  &    t               } | r| d   S y)z_Get the 'fallback' network device name on FreeBSD.

    @return List of sorted interfaces.
    r   N)r   r   s    r   r   r     s    
 +,EQxr"   c                  ~   dt        j                         v rt        j                  d       n\t	               D  cg c]  } | dk7  rt        |       s|  }} t        |      r*t        j                  d|       t        j                          g }g }t        dddddd      D ]  \  }}}}|dk(  r|j                  d      rt        j                  d	|       6t        |d
      }|r|j                  |       Vt        j                  d|       t        |d      }|r|j                  |       t        |d      }|dv r|j                  |       t        j                  d|        g }	||fD ]K  }
t        |
t              }
t        |
v r+|
j!                  t               |
j#                  dt               |	|
z  }	M |	S c c} w )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/cmdlineloz4Found unstable nic names: %s; calling udevadm settleFT)filter_openvswitch_internal2filter_slave_if_master_not_bridge_bond_openvswitchfilter_vlanfilter_without_own_macfilter_zero_maclog_filtered_reasonsvethzIgnoring veth interface: %scarrierzInterface has no carrier: %sdormantrO   )r   rN   lowerlayerdownrM   zInterface ignored: %sr   r   )r	   get_cmdliner5   r6   r   r   r   udevadm_settleget_interfaces
startswithrJ   appendrF   r   r   DEFAULT_PRIMARY_INTERFACEremoveinsert)deviceunstable	connectedpossibly_connectedr   _r   r   rO   sorted_interfaces
interfacess              r   r   r     s   
 $**,,		MN )*
~j&8 
 

 x=IIF ! I,$);@$! 6	1a 'II3Y?"9i8Y'		0)< #9i8%%i0%i=	HH%%i0		)95=6J  "45 (
J,<=
$
278a!:;Z'( {
s   F:c                  &    t               } | r| d   S y)z]Get the 'fallback' network device name on Linux.

    @return List of sorted interfaces.
    r   N)r   r   s    r   r   r     s    
 )*EQxr"   c                     t               }|syt        |      rd|i}ndt        |d      j                         i}| rt	        |      }|r||d<   dd||d}||idd	}|S )
zBGenerate network cfg v2 for dhcp on the NIC most likely connected.Nr   
macaddressaddressr   T)dhcp4r   set-namematch   )	ethernetsversion)r   r   rF   r   r   )config_drivertarget_namer  r   r   nconfs         r   generate_fallback_configr	  +  s     $%K %% +KCIIK
 {+$E(O	C ',;ELr"   c                     d }d }| j                  d      }|dk(  r ||       S |dk(  r ||       S t        d|z        )Nc                    g }| j                  di       D ]  }|j                  d      dk7  r|j                  d      }|s,|j                  d      }|j                  di       j                  d      }|j                  di       j                  d      }|st        |      }|st        |      }|j                  ||||g        |S )	Nr   rj   physicalmac_addressr   paramsr   	device_id)r   r   r   r   )netcfgphysdevsentmacr   r   r  s          r   
_version_1z$extract_physdevs.<locals>._version_1I  s    ::h+ 	<Cwwv*,''-(C776?DWWXr*..x8F"-11+>I&t,(.	OOS$	:;	< r"   c                    g }| j                  di       j                         D ]  }|j                  d      }|s|j                  di       j                  d      }|s;|j                  di       j                  d      }|j                  di       j                  d      }|st        |      }|st        |      }|j	                  ||||g        |S )Nr  r  r  r   r   r  )r   r   r   r   r   )r  r  r  r   r  r   r  s          r   
_version_2z$extract_physdevs.<locals>._version_2[  s    ::k2.557 	<C77:&D'''2&**<8CWWWb)--h7F,00=I&t,(.	OOS$	:;	<  r"   r     r  z"Unknown network config version: %s)r   RuntimeError)r  r  r  r  s       r   extract_physdevsr  H  sQ    $( jj#G!|&!!	A&!!
;gE
FFr"   c                 B    t        | d      }||rt        d      y|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_typez%s had no addr_assign_type.T)r   r     )rJ   rH   )ifnamestrictassign_types      r   interface_has_own_macr   x  s6     #6+=>K :;;)##r"   c           	         i }t               D ]*  \  }}}}d|||j                         |t        |      d||<   , | rt        j                  d      }t        j
                  g dd      \  }}t        j
                  g dd      \  }	}t               }
||	fD ]"  }|
j                  |j                  |             $ |j                         D ]  }|d   d	u xs |d
   |
v|d<    |S )a  Collect information necessary for rename_interfaces.

    returns a dictionary by mac address like:
       {name:
         {
          'downable': None or boolean indicating that the
                      device has only automatically assigned ip addrs.
          'device_id': Device id value (if it has one)
          'driver': Device driver (if it has one)
          'mac': mac address (in lower case)
          'name': name
          'up': boolean: is_up(name)
         }}
    N)downabler  r   r  r   rL   z[0-9]+:\s+(\w+)[@:])ipz-6addrshow	permanentscopeglobalT)capture)r#  z-4r$  r%  rL   Fr   r"  )
r   r   rQ   r   compiler   setupdatefindallr   )check_downablecur_infor   r  r   r  nmatchipv6r{   ipv4nics_with_addresses	bytes_outds                r   _get_current_rename_infor6    s    H(6(8 
$c69"99;+

 23YYH

d YY;TJ
d!e 	BI&&v~~i'@A	B " 	A$5 HAfI5H$H jM	
 Or"   c                    t        |       st        j                  d       y |
t               }i |j	                         D ]F  \  }}|j                         }|j                  d      r|d   j                         |d<   ||d<   ||<   H t        j                  d       d }g }g }	g }
 |      }d}d}d fd	}| D ]  \  }}}}|r|j                         }g } ||||      }|s|r|	j                  d
|d|d       D|j                  d      }||k(  r[|s|r|	j                  d
|d|d       x|d   rRd}|d   s|r|	j                  ||||fz         d|d<   |j                  d|||ff       |
j                  d|||ff       ||v r||   }|d   r7d}|d   s|r|	j                  ||||fz         |j                  d|||ff       d }|||v r|dz  }||z  }|||v r|j                  d||||ff       ||d<    |      }|d   r|
j                  d|||ff       |j                  d|||d   |ff       ||d<    |      }||z  } t        j                  t        j                  t        j                  d}|s<|
s:t        |	      rt        j                  d| |	       nIt        j                  d|        n2t        j                  d| ||
z          ||
z   D ]  \  }}}}	  ||   |   t        |	      rt        dj!                  |	            y # t        $ r)}|	j                  d||d|d|d|	       Y d }~fd }~ww xY w)Nzno interfaces to renamer  r   zDetected interfaces %sc                 B    t        d | j                         D              S )Nc              3   *   K   | ]  }|d    |f  yw)r   Nr!   ).0datas     r   	<genexpr>z<_rename_interfaces.<locals>.update_byname.<locals>.<genexpr>  s     DTT&\4(Ds   )r   r   )bymacs    r   update_bynamez)_rename_interfaces.<locals>.update_byname  s    DU\\^DDDr"   z
cirename%dc                     |r |r|r| d   |k(  xr | d   |k(  xr | d   |k(  S |r|r| d   |k(  xr | d   |k(  S |r| d   |k(  S y)zmatch if set and in datar  r   r  Fr!   )r;  r  r   r  s       r   entry_matchz'_rename_interfaces.<locals>.entry_match  sv    6iUs" 3Nf,3%2
 V;#%B$x.F*BB;#%%r"   c           	          j                         D cg c]  } || ||      r| }}t        |      r-t        |      dkD  rd|d| d|d|d	}t        |      |d   S y c c}w )Nr  z2Failed to match a single device. Matched devices "z" with search values "(mac:z driver:z device_id:z)"r   )r   r   rH   )r  r   r  r;  r  msgr/  rA  s         r   
find_entryz&_rename_interfaces.<locals>.find_entry  s}     !)
4fi8 
 

 u:5zA~ c696 
 !o%8O
s   A#z$[nic not present] Cannot rename mac=z to z, not available.rL   z*[busy] Error renaming mac=%s from %s to %sr"  FrN   z2[busy-target] Error renaming mac=%s from %s to %s.r  rename)rE  rN   rL   z1Unable to rename interfaces: %s due to errors: %sz$no work necessary for renaming of %szRenamed %s with ops %sz[unknown] Error performing z for z, z: 
)r   r5   r6   r6  itemscopyr   r   r   r
   link_rename	link_downlink_upwarningr   r  ra   )renamesstrict_presentstrict_busycurrent_infor   r;  curr>  opserrorsups
cur_bynametmpname_fmttmpirD  r  new_namer   r  cur_opscur_namerC  targettmp_nameopmapopr  r=   r/  rA  s                               @@r   _rename_interfacesr_    s    w<		+,/1H"((* 
diik775>U))+CJF II&1E CF
Cx(JKD$ -4 =(Xvy))+Cfi0*-x9 776?x*-x9 t9>Cz?MM#h(A"ABCINNFCH;?@JJc8h[9:z!)Fd|Jj)"cS(H,E&EFNNFCH;#GH&*H"h*&<	&- "h*&< NNHc8h5IJK%F6N&x0Jd|

D#x(=>#x#f+x1HIJF"8,
w{=@ &&"""E #v;KKC II<gF		*GS3Y?),s 	%BXvb	6"	 6{499V,--   63!5 s   3L##	M,MMc                 t    d}t         j                  j                  t        | d            rd}t	        | |      S )z6Returns the string value of an interface's MAC Addressr   bonding_slavezbonding_slave/perm_hwaddr)rU   r(   isdirr)   rF   )r  r(   s     r   get_interface_macrc  X  s2    D	ww}}\&/:; +VT**r"   c                 Z    t        | d      dk(  rt        |       }|r|r|dd |dd z   }|S y)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.
    rj   rk   $   i3   N)rF   rc  )r  ethernet_formatr  s      r   get_ib_interface_hwaddrrh  b  sB     (D0'?b+BC(C
 1r"   c                      t        j                         st        j                         r
t               S t        j                         r
t               S t        j                         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  sO    D002/11		.00		/11-//r"   r  c                     t               j                         D ]*  \  }}| j                         |j                         k(  s(|c S  y r   )r   rG  r   )r  interface_macinterface_names      r   find_interface_name_from_macrq  {  sD    )>)@)F)F)H "%~99;---//!!" r"   c                      t        j                   g d      \  } }d }d } | ||             D ci c]  \  }}||
 }}}|S c c}}w )N)r   -ar   c              3      K   d}| j                  d      D ]!  }|j                  d      r||z  }|r| |}# | y w)Nr   rF  	)r   r   )rz   
curr_blocklines      r   flattenz1get_interfaces_by_mac_on_freebsd.<locals>.flatten  sN     
IIdO 	"Dt$d"
$$!
	" s   =?c              3      K   | D ]?  }t        j                  d|      }|s|j                  d      |j                  d      f A y w)Nz2^(?P<ifname>\S*): .*ether\s(?P<mac>[\da-f:]{17}).*r  r  )r   searchgroup)	flat_listblockms      r   find_macz2get_interfaces_by_mac_on_freebsd.<locals>.find_mac  sI      	:E		EuA wwu~qwwx'899	:s
   A'A)r   )rz   r   rx  r  r  r  resultss          r   rj  rj    sP    yy45HS!	: /7ws|.DE{sFsF{EGEN Fs   Ac                     i } d}t        j                   ddg      \  }}t        j                  dd|      j                         }|D ]6  }t        j                  ||      }|s|j                         }|d   | |d   <   8 | S )NzE(?P<ifname>\w+).*address:\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   rs  \n\s+ r  r  r   r   subrv   r  	groupdictrr   re_field_matchrz   r   if_linesrw  r~  fieldss           r   rk  rk        
C	6  yy*d+,HS!vvhS)446H 2HH^T*[[]F!'!1Cu	2
 Jr"   c                     i } d}t        j                   ddg      \  }}t        j                  dd|      j                         }|D ]6  }t        j                  ||      }|s|j                         }|d   | |d   <   8 | S )NzC(?P<ifname>\w+).*lladdr\s(?P<mac>([\da-f]{2}[:-]){5}([\da-f]{2})).*r   rs  r  r  r  r  r  r  s           r   rl  rl    r  r"   c                      i } t               D ]~  \  }}}}|| v r:|dv rt        j                  d|| |   |       ,d|d| |   d|d}t        |      || |<   t	        |d      }|sZ|| vr|| |<   dt        j                  d|| |   |        | 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'.duplicate mac found! both '' and '' have mac 'z'.Tz^Ethernet and InfiniBand interfaces have the same address both '%s' and '%s' have address '%s'.)r   r5   r6   r  rh  rL  )rr   r   r  r   _devidrC  ib_macs          r   rm  rm    s     C%3%5 =!c66#: @@		#H  A CC
 s##C
 )t4* S "F=Ko=| Jr"   filter_hyperv_vf_with_syntheticr   r   r   r   r   r   c           	      `   |rt         j                  nd }g }t               }	dj                  d      }
|	D ]  }|rt	        |      st        |      r
 |d|       &|rt        |      r4t        |      r
 |d|       I|r"t        |      t        |      st        |      smt        |      r
 |d|       t        |      }|s
 |d|       |r|d	k7  r||
dt        |       k(  r|rt        |      rt        |      }|j!                  |||t#        |      f        | 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                       y r   r!   )argss    r   <lambda>z get_interfaces.<locals>.<lambda>  s    r"   :)00r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  zIgnoring bridge interface: %szIgnoring bond interface: %sNzIgnoring failover interface: %sz"Ignoring interface without mac: %sr   )r5   r6   r   ra   r   rX   r   r[   r_   re   rh   r   rc  r   r   r   r   r   )filter_hyperv_vf_with_synthetic_interface)r  r   r   r   r   r   r   filtered_loggerrr   r   zero_macr   r  r   s                 r   r   r     s=    $8cii=OO
CDxx%H "<!*?*ET?;TB74=4=94@>4 ,,T2)$/$=tD%@$Gtt|x
#c(7K0K&+L,
 t$

D#v|D'9:;E"<J '1/3GJr"   r  ).Nr   c                     |D ci c]  }|d   dk(  s|d   |d    }}|D cg c]  }|d   |v r
|d   dk7  r| }}|D ])  }|\  }}}}	 | d||||   |       |j                  |       + yc c}w c c}w )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.
    r  	hv_netvscr  r   zdIgnoring %r VF interface with driver %r due to synthetic hv_netvsc interface %r with mac address %r.N)r   )
r  r   ihv_netvsc_mac_to_nameinterfaces_to_remover   r   r  r   r   s
             r   r  r  A  s    * '!A$+*=!ad
 
 Q4((QqT[-@ 	
  * 
%	(c61D!#&	
 	)$
%s   A-A-A2c            
          i } t               D ]7  \  }}}}t        |d      }|s|| v rt        d|d| |   d|d      || |<   9 | S )zTBuild a dictionary mapping Infiniband interface names to their hardware
    address.Fr  r  r  ')r   rh  r  )rr   r   r   r  s       r   get_ib_hwaddrs_by_interfacer  k  sh     C') aA(u5}"S[&2  CI Jr"   convert_to_addressr   c                 4    	  | |fi |S # t         $ r Y yw xY 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)rH   )r  r   kwargss      r   maybe_get_addressr  {  s)    !'4V44 s    	c                 H    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.
    )rp   r  	ipaddress
ip_addressr   s    r   is_ip_addressr    s     !)"6"6@AAr"   c                 H    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.
    )rp   r  r  IPv4Addressr  s    r   is_ipv4_addressr         !)"7"7ABBr"   c                 H    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.
    )rp   r  r  IPv6Addressr  s    r   is_ipv6_addressr    r  r"   c                 L    t        t        t        j                  | 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  )rp   r  r  
ip_networkr  s    r   is_ip_networkr    s     !)"6"6NOOr"   c                 L    t        t        t        j                  | 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  )rp   r  r  IPv4Networkr  s    r   is_ipv4_networkr    #     )//G r"   c                 L    t        t        t        j                  | 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  )rp   r  r  IPv6Networkr  s    r   is_ipv6_networkr    r  r"   subnetc                 b    t        j                  |       }t        j                  |d      }||v S )zReturns a bool indicating if ``s`` is in subnet.

    :param address:
        The string of IP address.

    :param subnet:
        The string of subnet.

    :return:
        A bool indicating if the string is in subnet.
    Fr  )r  r  r  )r   r  r  subnet_networks       r   is_ip_in_subnetr    s1     %%g.J))&?N''r"   gatewayc                 z    	 t        | |       S # t        $ r"}t        j                  d| ||       Y d}~yd}~ww xY w)zReturns a bool indicating if should add gateway onlink flag.

    :param gateway:
        The string of gateway address.

    :param subnet:
        The string of subnet.

    :return:
        A bool indicating if the string is in subnet.
    zDFailed to check whether gateway %s is contained within subnet %s: %sNF)r  rH   r5   rL  )r  r  r=   s      r   should_add_gateway_onlink_flagr    sF    
"7F333 1	
 s    	:5:c                     | d   j                  d      s| d   t        v ry| d   dk(  rt        | j                  d            ryy)z:Common helper for checking network_state subnets for ipv6.rj   6Tstaticr   F)endswithIPV6_DYNAMIC_TYPESr  r   )r  s    r   subnet_is_ipv6r    sG     f~s#vf~9K'K	8	#

98M(Nr"   c                 X    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.0.0.0.0/)r   r  r  netmask)prefixs    r   net_prefix_to_ipv4_maskr    s'     y$$xx%89AABBr"   c                 F    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
    r  )r  r  	prefixlen)masks    r   ipv4_mask_to_net_prefixr    s"     (4& 12<<<r"   c                    	 t        j                  d|        j                  }|S # t        $ r Y nw xY wt        j                  |       }t        |      }|dk(  r|S t        t         j                  | |dz
  z  j                               }||z	  }t         j                  |z
  }d|z  dz
  }||k7  rt        d| z        |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  rH   r  r   min
IPV6LENGTH
bit_length)r  r  r  mask_inttrailing_zeroesleading_onesall_oness          r   ipv6_mask_to_net_prefixr  '  s    ((3tf6@@	  	
 ""4(G7|H1}yHqL9EEGO .L$$6IY!#Hx4t;<<s   #& 	22r  r#  c                 `    t        t        j                  | d|  d      j                        S )zCGet string representation of broadcast address from an ip/mask pairr%   Fr  )r   r  r  broadcast_address)r  r#  s     r   mask_and_ipv4_to_bcast_addrr  J  s/    AdVnU;MM r"   c                       e Zd Zy)RendererNotFoundErrorN)r   r   r   r!   r"   r   r  r  Q  s    r"   r  )r   )NNNNr   )F)T)TTN)TTTTTTF)er+   	functoolsr  loggingrU   r   typingr   r   r   r   r   	cloudinitr   r	   cloudinit.net.netops.iproute2r
   	getLoggerr   r5   r    r   r  ru   r*  r   r#   r)   r?   rF   rJ   rQ   rX   r[   r_   re   rh   rl   	lru_cacherp   rs   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   r6  r_  rc  rh  r   rq  rj  rk  rl  rm  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r!   r"   r   <module>r     sD       	 	 8 8   2g!!"  % ! )bjj4 

7 "JH;<G$6 T"$  # T" T   # (s t 
t 0B01
A) A+
.T#Y 
.,8C= ,J$s) J	 	JS	 J	hsm 	Ed3i EP	HSM 	HTN :-G`$(+^ BF[.|+0t 0c hsm $ 8  $  D DP -1(,?C#' !&9%)9!%9 9=9 	9
 !9 9 9 
9x'%i('%U3S#-./'% 
'%T ( S &	B3 	B4 	B	CS 	CT 	C	CS 	CT 	C	P3 	P4 	PS T S T (S (# ($ ("C   2d Cs C	=S 	= S  Fc s s 	L 	r"   