
    x[hЏ                        S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	J
r
  S SKJr  S SKJr  S SKJrJrJrJrJrJr  S SKrS SKJrJrJr  S SKJrJr  \R<                  " \5      r Sr!S	r"S
r#Sr$ " S S\%5      r& " S S\&5      r' " S S\&5      r( " S S\&5      r) S!S\\*\4   4S jjr+S r,S"S jr-S"S jr. " S S\ R^                  5      r0 " S S\05      r1 " S S\05      r2 " S S \05      r3\2\1\3/r4g)#    N)suppress)StringIO)TimeoutExpired)AnyCallableDictListOptionalTuple)subp
temp_utilsutil)get_interface_macis_ib_interfacez/run/systemd/netif/leasesz/var/lib/dhclientz.+\.leases?$aN  #!/bin/sh
log() {
    echo "udhcpc[$PPID]" "$interface: $2"
}
[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
case $1 in
    bound|renew)
    cat <<JSON > "$LEASE_FILE"
{
    "interface": "$interface",
    "fixed-address": "$ip",
    "subnet-mask": "$subnet",
    "routers": "${router%% *}",
    "static_routes" : "${staticroutes}"
}
JSON
    ;;
    deconfig)
    log err "Not supported"
    exit 1
    ;;
    leasefail | nak)
    log err "configuration failed: $1: $message"
    exit 1
    ;;
    *)
    echo "$0: Unknown udhcpc command: $1" >&2
    exit 1
    ;;
esac
c                       \ rS rSrSrSrg)NoDHCPLeaseErrorA   z'Raised when unable to get a DHCP lease. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       4/usr/lib/python3/dist-packages/cloudinit/net/dhcp.pyr   r   A   s    1r   r   c                       \ rS rSrSrSrg)InvalidDHCPLeaseFileErrorE   zRaised when parsing an empty or invalid dhclient.lease file.

Current uses are DataSourceAzure and DataSourceEc2 during ephemeral
boot to scrape metadata.
r   Nr   r   r   r   r   r   E   s    r   r   c                       \ rS rSrSrSrg)NoDHCPLeaseInterfaceErrorM   z7Raised when unable to find a viable interface for DHCP.r   Nr   r   r   r   r"   r"   M   s    Ar   r"   c                       \ rS rSrSrSrg)NoDHCPLeaseMissingDhclientErrorQ   z$Raised when unable to find dhclient.r   Nr   r   r   r   r%   r%   Q   s    .r   r%   returnc                     U=(       d    U R                   nUc  [        R                  S5        [        5       eU R                  R                  X2U 5      $ )a  Perform dhcp discovery if nic valid and dhclient command exists.

If the nic is invalid or undiscoverable or dhclient command is not found,
skip dhcp_discovery and return an empty dict.

@param nic: Name of the network interface we want to run dhclient on.
@param dhcp_log_func: A callable accepting the dhclient output and error
    streams.
@return: A list of dicts representing dhcp options for each lease obtained
    from the dhclient discovery if run, otherwise an empty list is
    returned.
z1Skip dhcp_discovery: Unable to find fallback nic.)fallback_interfaceLOGdebugr"   dhcp_clientdhcp_discovery)distronicdhcp_log_func	interfaces       r   maybe_perform_dhcp_discoveryr2   U   sI     0v00I		EF')),,YvNNr   c                 P    [        [        R                  " [        U 5      SS95      $ )zParse a systemd lease file content as in /run/systemd/netif/leases/

Parse this (almost) ini style file even though it says:
  # This is private data. Do not parse.

Simply return a dictionary of key/values.F)list_values)dict	configobj	ConfigObjr   )contents    r   networkd_parse_leaser9   l   s!     	##HW$55IJJr   c           	         U c  [         n 0 n[        R                  R                  U 5      (       d  U$ [        R                  " U 5       HA  n[        [        R                  " [        R                  R                  X5      5      5      X'   MC     U$ )zReturn a dictionary of dictionaries representing each lease
found in lease_d.i

The top level key will be the filename, which is typically the ifindex.)	NETWORKD_LEASES_DIRospathisdirlistdirr9   r   load_text_filejoin)leases_dretlfiles      r   networkd_load_leasesrE   w   sm     &C77==""
H%)X =>

 & Jr   c                     Uc  [         n[        US9n[        UR                  5       5       H!  u  p4UR	                  U 5      (       d  M  X@   s  $    g )N)rB   )r;   rE   sorteditemsget)keynamerB   leases_ifindexdatas        r   networkd_get_option_from_leasesrN      sJ    &!84F 088G=  1 r   c            
       B   \ rS rSrSrSrS r\S 5       r\S 5       r	\S\
4S j5       r\S\
4S	 j5       r\R                  S
\
S\\
\4   4S j5       r\\R                  S\
S\\\
\
4      4S j5       5       r\R                    SS
\
S\\   S\\
\4   4S jj5       rSrg)
DhcpClient    
   c                     [         R                  " U R                  5      U l        U R                  (       d
  [	        5       eg N)r   whichclient_namedhcp_client_pathr%   )selfs    r   __init__DhcpClient.__init__   s0     $

4+;+; <$$133 %r   c                 J    [         R                   " SU R                  /SS/S9  g )Npkillr      rcs)r   rW   )clss    r   kill_dhcp_clientDhcpClient.kill_dhcp_client   s    		7COO,1a&9r   c                     U R                  5         [        R                  " S5      nU H  n[        R                  " U5        M     g )Nz/var/lib/dhcp/*)rb   globr<   remove)ra   filesfiles      r   clear_leasesDhcpClient.clear_leases   s2    		+,DIIdO r   dhcp_interfacec                 @    UR                  SU R                  USS/S9  g )Nstartr   r^   r_   manage_servicerW   ra   rk   r.   s      r   start_serviceDhcpClient.start_service   s&    S__n1a& 	 	
r   c                 >    UR                  SU R                  SS/S9  g )Nstopr   r^   r_   rn   rp   s      r   stop_serviceDhcpClient.stop_service   s    fcooAq6Br   r1   r'   c                     0 $ )zGet the most recent lease from the ephemeral phase as a dict.

Return a dict of dhcp options. The dict contains key value
pairs from the most recent lease.
r   rY   r1   s     r   get_newest_leaseDhcpClient.get_newest_lease   s	     	r   routesc                     / $ )a8  
parse classless static routes from string

The tuple is composed of the network_address (including net length) and
gateway for a parsed static route.

@param routes: string containing classless static routes
@returns: list of tuple(str, str) for all valid parsed routes until the
          first parsing error.
r   )r{   s    r   parse_static_routesDhcpClient.parse_static_routes   s	     	r   Nr0   c                     0 $ )a  Run dhcp client on the interface without scripts or filesystem
artifacts.

@param interface: Name of the network interface on which to send a
    dhcp request
@param dhcp_log_func: A callable accepting the client output and
    error streams.
@param distro: a distro object for network interface manipulation
@return: dict of lease options representing the most recent dhcp lease
    parsed from the dhclient.lease file
r   )rY   r1   r0   r.   s       r   r-   DhcpClient.dhcp_discovery   s	    $ 	r   )rX   NN)r   r   r   r   rW   timeoutrZ   classmethodrb   ri   strrq   ru   abcabstractmethodr   r   ry   staticmethodr	   r   r}   r
   r   r-   r   r   r   r   rP   rP      s*   KG4
 : :   
3 
 

 C# C C 	# $sCx.   C DsCx,A    	 -1	  )
 
c3h r   rP   c            	       
  ^  \ rS rSrSrU 4S jr\S\S\\	\\
4      4S j5       r\S 5       rS\S\	\\
4   4S	 jr  SS\S
\\   S\	\\
4   4S jjr\S\S\\\\4      4S j5       r\S\\   4S j5       rS\4S jrSrU =r$ )IscDhclient   dhclientc                 0   > [         TU ]  5         SU l        g )Nz/run/dhclient.leasesuperrZ   
lease_filerY   	__class__s    r   rZ   IscDhclient.__init__   s    /r   lease_contentr'   c                    [         R                  " S[         R                  5      n/ nU (       d  / $ UR                  U 5       H  n/ nUR	                  S5       H]  nUR                  5       R                  SS5      R                  SS5      nU(       d  M<  UR                  UR	                  SS5      5        M_     [        U5      nUR                  S5      nU(       a  [        R                  U5      US'   UR                  U5        M     U$ )	zparse the content of a lease file

@param lease_content: a string containing the contents of an
    isc-dhclient lease
@return: a list of leases, most recent last
zlease {(?P<lease>.*?)}\n;"rR   zoption  r^   unknown-245)recompileDOTALLfindallsplitstripreplaceappendr5   rI   r   get_ip_from_lease_value)r   lease_regexdhcp_leasesleaselease_optionslineoptionsopt_245s           r   parse_leasesIscDhclient.parse_leases   s     jj!<biiH"$I ((7EMC(zz|++C4<<YK4!((C);<	 )
 =)Gkk-0G)4)L)L*& w' 8 r   c           	      Z   U R                  SS5      n[        U5      S:  ad  SnUR                  S5       H  n[        U5      S:X  a  SU-   nX#-  nM     [        R                  " S[        UR                  SS5      S5      5      nOUR                  S	5      n[        R                  " U5      $ )
N\rR      :r^   0z>L   zutf-8)	r   lenr   structpackintencodesocket	inet_ntoa)fallback_lease_valueunescaped_value
hex_stringhex_pairpacked_bytess        r   r   #IscDhclient.get_ip_from_lease_value  s    .66tR@!#J+11#6x=A%"X~H&
 7 ";;c*,,S"5r:L +11':L--r   r1   c                     [        [        5         [        R                  " U R                  5      nU(       a&  U R                  U5      nU(       a  US   sSSS5        $ SSS5        0 $ ! , (       d  f       0 $ = f)a  Get the most recent lease from the ephemeral phase as a dict.

Return a dict of dhcp options. The dict contains key value
pairs from the most recent lease.

@param interface: an interface string - not used in this class, but
    required for function signature compatibility with other classes
    that require a distro object
@raises: InvalidDHCPLeaseFileError on empty or unparsable leasefile
    content.
N)r   FileNotFoundErrorr   r@   r   r   )rY   r1   r8   r   s       r   ry   IscDhclient.get_newest_lease  s`     '())$//:G"//8&r? )(( 	 )( 	s   AA((
A7r0   c           	         [         R                  SU5        SnSnSn[        U R                  U-  5      n[        U R                  S-  5      n[	        [
        5         [        R                  " U5        [        R                  " U R                  5        SSS5        UR                  R                  U5        [        U5      (       ah  S[        U5      SS -  n	SU< S	U	< S
3n
[        R                  " SS9n[        R                  R!                  XS-   5      n["        R$                  " XZ5         [&        R&                  " UR)                  U R*                  U R                  UUU5      5      u  p["        R6                  " X@R                  /USS9nU(       a.  [         R9                  SSR!                  S U 5       5      5        0 $ SnSnSnSn[;        U5       H  n ["        R<                  " U5      R?                  5       n[        U5      nURA                  U5      nUS:X  a?  [         R                  SU5        [        RB                  " U[D        RF                  5        Sn  O0 [J        RL                  " U5        M     [         R                  U5        U(       d  [         RO                  SUUS5        Ub  U" X5        U RQ                  U5      nU(       a  U$ [S        5       e! , (       d  f       GNR= f! [&        R,                   aB  n[         R                  SUR.                  UR0                  UR2                  5        [4        UeSnAff = f! [
         a	    SU S3n N[H         a
    SU S3n GNf = f)a  Run dhclient on the interface without scripts/filesystem artifacts.

@param interface: Name of the network interface on which to send a
    dhcp request
@param dhcp_log_func: A callable accepting the dhclient output and
    error streams.
@param distro: a distro object for network interface manipulation
@return: dict of lease options representing the most recent dhcp lease
    parsed from the dhclient.lease file
!Performing a dhcp discovery on %sz/run/dhclient.pidN{Gz?   z20:%s$   zinterface "z" {send dhcp-client-identifier z;}T	needs_exez-dhclient.confz3dhclient exited with code: %s stderr: %r stdout: %r)maxwaitnaplenz+dhclient did not produce expected files: %sz, c              3   `   #    U  H$  n[         R                  R                  U5      v   M&     g 7frU   )r<   r=   basename).0fs     r   	<genexpr>-IscDhclient.dhcp_discovery.<locals>.<genexpr>}  s"     ?w!"''**1--ws   ,.unknownFrR   r^   zkilling dhclient with pid=%sNo PID file found at z, dhclient is still runningPID file contained [z], dhclient is still runningzCdhclient(pid=%s, parentpid=%s) failed to daemonize after %s secondsg      $@)*r*   r+   r   r   r   r   r<   rf   r   net_opslink_upr   r   r   get_tmp_ancestorr=   rA   r   
write_filer   build_dhclient_cmdrX   ProcessExecutionError	exit_codestderrstdoutr   wait_for_fileswarningranger@   r   get_proc_ppidkillsignalSIGKILL
ValueErrortimesleeperrorry   r   )rY   r1   r0   r.   pid_fileconfig_file
sleep_timesleep_cyclesr   dhcp_client_identifierinterface_dhclient_contenttmp_dirouterrr   missingppid
daemonizedpid_content	debug_msg_pidr   s                          r   r-   IscDhclient.dhcp_discovery&  s     			5yA
 '
4<<*45dllQ&' '(IIhIIdoo& ) 	y)
 9%%+I6rs;; # 46 '
 !11DAG'',,w<L0LMKOOKD	.yy))))OOHC2 %%'
 KK=		?w?? I
	|$A"11(;AAC+& ++C019II<cBGGC0!%J	 
 JJz"+ %. IIi II $##%%i0L'))Q )(H )) 	.IIE	 #-	.D % +H: 60 0   *;- 80 0 s<   7K/?K0 /M	
K-0M=MM	M.M.-M.r{   c           
        ^ U R                  S5      m[        R                  " ST5       Vs/ s H  o(       d  M  UPM     nn/ nST;   a%  U Vs/ s H  n[        [	        US5      5      PM     nnU4S jnSn[        U5       GHp  u  paXe:  a  M  [	        U5      nU[        SS5      ;   ab  S	n[        X&S
 5      U:  a  U" Xx[        X&S
 5      5        Us  $ SR                  X&S-   US-    5      n	SR                  X&S-   Xh-    5      n
Xh-   nGOU[        SS5      ;   af  Sn[        X&S
 5      U:  a  U" Xx[        X&S
 5      5        Us  $ SR                  X&S-   US-    S/-   5      n	SR                  X&S-   Xh-    5      n
Xh-   nGOVU[        S	S5      ;   af  Sn[        X&S
 5      U:  a  U" Xx[        X&S
 5      5        Us  $ SR                  X&S-   US-    SS/-   5      n	SR                  X&S-   Xh-    5      n
Xh-   nOU[        SS	5      ;   af  Sn[        X&S
 5      U:  a  U" Xx[        X&S
 5      5        Us  $ SR                  X&S-   US-    / SQ-   5      n	SR                  X&S-   Xh-    5      n
Xh-   nOjUS:X  aJ  Sn[        X&S
 5      U:  a  U" Xx[        X&S
 5      5        Us  $ Sn	SR                  X&S-   Xh-    5      n
Xh-   nO[        R                  SU5        Us  $ UR                  U	< SU< 3U
45        GMs     U$ s  snf s  snf )aX  
parse rfc3442 format and return a list containing tuple of strings.

The tuple is composed of the network_address (including net length) and
gateway for a parsed static route.  It can parse two formats of
rfc3442, one from dhcpcd and one from dhclient (isc).

@param rfc3442: string in rfc3442 format (isc or dhcpd)
@returns: list of tuple(str, str) for all valid parsed routes until the
    first parsing error.

e.g.:

sr=parse_static_routes(        "32,169,254,169,254,130,56,248,255,0,130,56,240,1")
sr=[
    ("169.254.169.254/32", "130.56.248.255"),         ("0.0.0.0/0", "130.56.240.1")
]

sr2 = parse_static_routes(        "24.191.168.128 192.168.128.1,0 192.168.128.1")
sr2 = [
    ("191.168.128.0/24", "192.168.128.1"),        ("0.0.0.0/0", "192.168.128.1")
]

# unknown-121 option format
sr3 = parse_static_routes(        "0:a:0:0:1:20:a8:3f:81:10:a:0:0:1:20:a9:fe:a9:fe:a:0:0:1")
sr3 = [
    ("0.0.0.0/0", "10.0.0.1"),
    ("168.63.129.16/32", "10.0.0.1"),
    ("169.254.169.254/32", "10.0.0.1"),
]

Python version of isc-dhclient's hooks:
   /etc/dhcp/dhclient-exit-hooks.d/rfc3442-classless-routes
r   z[, . :]r   r   c                 T   > SU < SU< SU< ST< 3n[         R                  U5        g )Nz5RFC3442 string malformed.  Current route has CIDR of z and requires z significant octets, but only z< remain. Verify DHCP rfc3442-classless-static-routes value: )r*   r   )cidrrequiredremainmsgrfc3442s       r   _trunc_error5IscDhclient.parse_static_routes.<locals>._trunc_error  s%    
 674  IIcNr   r      !   	   N.r^            r   r            r   )r   r   r   z0.0.0.0zSParsed invalid net length "%s".  Verify DHCP rfc3442-classless-static-routes value./)rstripr   r   r   r   	enumerater   r   rA   r*   r   r   )r{   toktokensstatic_routesr   current_idxidx
net_lengthreq_toksnet_addressgatewayr   s              @r   r}   IscDhclient.parse_static_routes  s5   T --$!#*g!>F!>###!>F/1 '>39:6Cc#c2,'6F:	 !&)HC SJU2r]*vd|$x/ s6$<7HI((!hhvAga'@A((6'CN#CD!nuR},vd|$x/ s6$<7HI((!hhvAga'@C5'HI((6'CN#CD!nuQ|+vd|$x/ s6$<7HI((!hhvAga'@C:'MN((6'CN#CD!nuQ{*vd|$x/ s6$<7HI((!hh7S1W-? ((6'CN#CD!nqvd|$x/ s6$<7HI(('((6'CN#CD!n		=
 %$  '4g>m *t W G
 ;s   
K9K9K>c                    SnU R                   U R                  4[        [        44 H  u  p#U(       d  M  / n [        R
                  " U5      nSnU Hi  n[        R                  " X65      (       d  M   [        R                  R                  X&5      n[        R                  R                  U5      nX:  d  Me  UnUnMk     U(       d  M  Us  $    g! [         a     M  f = f)zGet the latest lease file from a distro-managed dhclient

Doesn't consider the ephemeral timeframe lease.

@param distro: used for distro-specific lease location and filename
@return: The most recent lease file, or None
Ng      )dhclient_lease_directorydhclient_lease_file_regexDHCLIENT_FALLBACK_LEASE_DIRDHCLIENT_FALLBACK_LEASE_REGEXr<   r?   r   r   searchr=   rA   getmtime)	r.   latest_file	directoryregexlease_fileslatest_mtimefnameabs_pathmtimes	            r   !get_newest_lease_file_from_distro-IscDhclient.get_newest_lease_file_from_distro%  s     
 //00 )*GH!
I K jj3  L$yy..77<<	9((2'#(L"*K % {"";!
< # % s   C
CCkeyc                     U R                  U5      nU(       a\  [        R                  " U5      nU(       a>  [        U R	                  U5      5       H  nUR                  U5      nU(       d  M  Us  $    ggg)a  Get a key from the latest lease from distro-managed dhclient

Doesn't consider the ephemeral timeframe lease.

@param lease_dir: distro-specific lease to check
@param lease_file_regex: distro-specific regex to match lease name
@return: The most recent lease file, or None
N)r(  r   r@   reversedr   rI   )rY   r.   r*  r   r8   r   servers          r   get_key_from_latest_lease%IscDhclient.get_key_from_latest_leaseQ  sf     ;;FC
))*5G%d&7&7&@AE"YYs^Fv% B  r   r   r   )r   r   r   r   rW   rZ   r   r   r	   r   r   r   r   ry   r
   r   r-   r   r}   r(  r.  r   __classcell__r   s   @r   r   r      s   K0 C Dc3h,@  6 . .# $sCx. . -1	E*E*  )E*
 
c3hE*N uC uDsCx,A u un )Xc] ) )V&S & &r   r   c            	           \ rS rSrSrSr  SS\S\\   S\	\\
4   4S jjr\S	\S
\S\\   4S j5       r\S\S\S\	4S j5       rS\S\	\\
4   4S jr\S\S\\\\4      4S j5       rSrg)Dhcpcdid  dhcpcdi,  Nr1   r0   r'   c                 p   [         R                  SU5        Sn[        U R                  U-  5      n/ nUR                  R                  U5         [        U5      (       a  S/nU R                  SSSSS/UQUPn[        R                  " UU R                  S	9u  pUb  U" X5        U R                  U5      n
U
(       a  [        R                  " / UQSP5      R                  R                  5       nS
nSnSn[        U5       H  n [        R                  " U5      R                  5       n[        U5      nUR                  U5      nU(       a?  [         R                  SUU5        [         R"                  " U[$        R&                  5          U
$  U
s  $    [         R                  U5        U
$ [3        S5      e! [(         a    [         R                  SU5           U
$ [*         a	    SU S3n O[,         a	    SU S3n Of = f[.        R0                  " U5        GM  ! [4         aB  n[         R                  SUR                  UR6                  UR                  5        [2        UeS
nAf[        R8                   aB  n[         R                  SUR:                  UR6                  UR                  5        [2        UeS
nAff = f)a  Run dhcpcd on the interface without scripts/filesystem artifacts.

@param interface: Name of the network interface on which to send a
    dhcp request
@param dhcp_log_func: A callable accepting the client output and
    error streams.
@param distro: a distro object for network interface manipulation
@return: dict of lease options representing the most recent dhcp lease
    parsed from the dhclient.lease file
r   r   z
--clientid
--ipv4onlyz--waitipz--persistentz--noarpz--script=/bin/true)r   Nz-PFrR   z!killing dhcpcd with pid=%s gid=%sz9Process group id [%s] has already exited, nothing to killr   z, dhcpcd is still runningr   z], dhcpcd is still runningzNo lease foundz8dhcpcd timed out after %s seconds: stderr: %r stdout: %r1dhcpcd exited with code: %s stderr: %r stdout: %r)r*   r+   r   r   r   r   r   rW   r   ry   r   r   r   r   r@   get_proc_pgidr<   killpgr   r   ProcessLookupErrorr   r   r   r   r   r   r   r   r   )rY   r1   r0   r.   r   r   infiniband_argumentcommandr   r   r   r   r   gidr   r   r   r   s                     r   r-   Dhcpcd.dhcp_discoveryh  s     			5yA
4<<*45  	y)[	. y))'3n#  $	 %	 	G yyHC (c')))4E   99%5w%5%56==CCE"	|,A%&*&9&9(&C&I&I&K!+.$2237II CS# IIc6>>:!. 9 0  %; -@ IIi("#344/ . 		.
    - 3H: >6 6 " & 2;- @6 6 " JJz*  	.IIJ	 #-)) 	.IIC	 #-	.st   B3H BF2H 
H H 'H 2 G9H G9%H 'G96H 8G99H 
J5=IJ53=J00J5rM   dhcp_option_numberc                 ^    SnS[         S[        4S jnU" X5       H  u  pEXA:X  d  M  Us  $    g)a&  get a specific option from a binary lease file

This is required until upstream dhcpcd supports unknown option 245
upstream bug: https://github.com/NetworkConfiguration/dhcpcd/issues/282

@param data: Binary lease data
@param number: Option number to return
@return: the option (bytes) or None
   rM   indexc              3      #    [        U 5      US-   :  a<  X   nU SU-      nU SU-   SU-   U-    nX$4v   SU-   U-   n[        U 5      US-   :  a  M;  gg7f)zoptions are variable length, and consist of the following format

option number: 1 byte
option length: 1 byte
option data: variable length (see length field)
r   r^   N)r   )rM   rC  codelengthoptions        r   iter_options>Dhcpcd.parse_unknown_options_from_packet.<locals>.iter_options  sl      d)uqy({a%ia%i!e)f*<=l"F
U* d)uqy(s   AAAN)bytesr   )rM   r@  INDEXrH  rE  rG  s         r   !parse_unknown_options_from_packet(Dhcpcd.parse_unknown_options_from_packet  s?    . 	+u 	+S 	+ )5LD) 6 r   
lease_dumpc           
      @   [         R                  SX5         [        U R                  5       R	                  SS5      R                  S5       Vs/ s H  nSU;   d  M  UR                  SSS9PM     sn5      nU(       d$  Sn[         R                  X@5        [        X@-  5      e XS'   UR                  5        VVs0 s H  u  pgUR	                  SS5      U_M     nnnSSS.nUR                  5        H  u  pX;   d  M  UR                  U	5      X:'   M!     [        R                  " SU S35      n[        R                  US5      nU(       a  [        R                   " U5      US'   U$ s  snf ! [         a"  n[         R                  S	U 5        [        UeS
nAff = fs  snnf )a  parse the output of dhcpcd --dump

map names to the datastructure we create from dhclient

example dhcpcd output:

broadcast_address='192.168.15.255'
dhcp_lease_time='3600'
dhcp_message_type='5'
dhcp_server_identifier='192.168.0.1'
domain_name='us-east-2.compute.internal'
domain_name_servers='192.168.0.2'
host_name='ip-192-168-0-212'
interface_mtu='9001'
ip_address='192.168.0.212'
network_number='192.168.0.0'
routers='192.168.0.1'
subnet_cidr='20'
subnet_mask='255.255.240.0'
z)Parsing dhcpcd lease for interface %s: %r'rR   
=r^   )maxsplitz;No valid DHCP lease configuration found in dhcpcd lease: %rzError parsing dhcpcd lease: %rNr1   r   -zfixed-addressr  )z
ip-addresszclassless-static-routesz/var/lib/dhcpcd/z.lease   r   )r*   r+   r5   r   r   r   r   r   r   rH   popr   load_binary_filer4  rL  r   r   )rN  r1   ar   r   r   r*  valuename_mapsourcedestinationdhcp_messager   s                r   parse_dhcpcd_leaseDhcpcd.parse_dhcpcd_lease  s   , 			7	

	7 (--/77R@FFtLLax -AGGC!G,LE 0  		#*/0@AA  'k AFN*#S#&-N *'6
 $,>>#3F%*YYv%6" $4 ,,yk0
 ::<M#)#3#3G#<E- U  	7II6
C+6	7 Os5   6E+ 
E&E&02E+ :F&E+ +
F5FFc                 2    U R                  [        R                  " U R                  SSU/5      R                  U5      $ ! [        R                   aB  n[
        R                  SUR                  UR                  UR                  5        [        UeSnAff = f)zReturn a dict of dhcp options.

@param interface: which interface to dump the lease from
@raises: InvalidDHCPLeaseFileError on empty or unparsable leasefile
    content.
z--dumpleaser7  r8  N)
r^  r   rW   r   r   r*   r+   r   r   r   )rY   r1   r   s      r   ry   Dhcpcd.get_newest_leaseT  s    	.**		((%$!	 &
 
 )) 	.IIC	 #-	.s   =A   B=BBr{   c                     U R                  5       nU(       a(  [        USSS2   USSS2   5       Vs/ s H  o"PM     sn$ [        R                  SU 5        / $ s  snf )a  
classless static routes as returned from dhcpcd --dumplease and return
a list containing tuple of strings.

The tuple is composed of the network_address (including net length) and
gateway for a parsed static route.

@param routes: string containing classless static routes
@returns: list of tuple(str, str) for all valid parsed routes until the
          first parsing error.

e.g.:

sr=parse_static_routes(
    "0.0.0.0/0 10.0.0.1 168.63.129.16/32 10.0.0.1"
)
sr=[
    ("0.0.0.0/0", "10.0.0.1"),
    ("169.63.129.16/32", "10.0.0.1"),
]
Nr   r^   z'Malformed classless static routes: [%s])r   zipr*   r   r{   r  is      r   r}   Dhcpcd.parse_static_routesq  s^    . "=1#5}QTT7JKLK!AKLL=vF	 Ms   Ar   r   )r   r   r   r   rW   r   r   r
   r   r   r   r-   r   rJ  r   rL  r^  ry   r	   r   r}   r   r   r   r   r4  r4  d  s    KG
 -1	u.u.  )u.
 
c3hu.n ))),)	%) )V Fs Fs Ft F FP.# .$sCx. .: C DsCx,A  r   r4  c            	          ^  \ rS rSrSrU 4S jr  SS\S\\   S\	\\
4   4S jjrS\S\	\\
4   4S jr\S	\S\\\\4      4S
 j5       rSrU =r$ )Udhcpci  udhcpcc                 0   > [         TU ]  5         SU l        g )NrR   r   r   s    r   rZ   Udhcpc.__init__  s    r   r1   r0   r'   c                    [         R                  SU5        [        R                  " SS9n[        R
                  R                  XAS-   5      U l        [        [        5         [        R                  " U R                  5        SSS5        UR                  R                  U5        [        R
                  R                  US5      n[        R                  " U[        S5        U R                   SS	S
USUSSSS/n[#        U5      (       a>  UR%                  SSR'                  [)        U5      SS R+                  SS5      5      /5         [,        R,                  " USU R                  0SS9u  pxUb  U" Xx5        U R9                  U5      $ ! , (       d  f       GN= f! [,        R.                   aB  n	[         R                  SU	R0                  U	R2                  U	R4                  5        [6        U	eSn	A	ff = f)aB  Run udhcpc on the interface without scripts or filesystem artifacts.

@param interface: Name of the network interface on which to run udhcpc.
@param dhcp_log_func: A callable accepting the udhcpc output and
    error streams.
@return: A list of dicts of representing the dhcp leases parsed from
    the udhcpc lease file.
r   Tr   z.lease.jsonNudhcpc_scripti  z-Ostaticroutesz-iz-sz-nz-qz-fz-vz-xz	0x3d:20{}r   r   rR   
LEASE_FILE)
update_envcapturez1udhcpc exited with code: %s stderr: %r stdout: %r)r*   r+   r   r   r<   r=   rA   r   r   r   rf   r   r   r   r   UDHCPC_SCRIPTrW   r   extendformatr   r   r   r   r   r   r   r   ry   )
rY   r1   r0   r.   r   rm  cmdr   r   r   s
             r   r-   Udhcpc.dhcp_discovery  s    			5yA--='',,wM0IJ'(IIdoo& ) 	y)Wo>}e< 
$ 9%%JJ&&))4RS9AA#rJ	.yyt ?HC $##$$Y//i )(P )) 	.IIC	 #-	.s$   !!F$F 
FG/-=G**G/c                 j    [         R                  " [         R                  " U R                  5      5      $ )a  Get the most recent lease from the ephemeral phase as a dict.

Return a dict of dhcp options. The dict contains key value
pairs from the most recent lease.

@param interface: an interface name - not used in this class, but
    required for function signature compatibility with other classes
    that require a distro object
@raises: InvalidDHCPLeaseFileError on empty or unparsable leasefile
    content.
)r   	load_jsonr@   r   rx   s     r   ry   Udhcpc.get_newest_lease  s"     ~~d11$//BCCr   r{   c                     U R                  5       nU(       a(  [        US S S2   USS S2   5       Vs/ s H  o"PM     sn$ / $ s  snf )Nr   r^   )r   rc  rd  s      r   r}   Udhcpc.parse_static_routes  sM    "=1#5}QTT7JKLK!AKLL	 Ms   Ar0  r   )r   r   r   r   rW   rZ   r   r
   r   r   r   r-   ry   r   r	   r   r}   r   r1  r2  s   @r   rh  rh    s    K -1	F0F0  )F0
 
c3hF0PD# D$sCx. D C DsCx,A  r   rh  r   rU   )5r   re   loggingr<   r   r   r   r   r   
contextlibr   ior   
subprocessr   typingr   r   r   r	   r
   r   r6   	cloudinitr   r   r   cloudinit.netr   r   	getLoggerr   r*   r;   r  r  rr  	Exceptionr   r   r"   r%   r   r2   r9   rE   rN   ABCrP   r   r4  rh  ALL_DHCP_CLIENTSr   r   r   <module>r     s      	 	       % = =  , , <!1 1  / B2y 2 0 B 0 B/&6 /
 %)O	#s(^O.K&H HVB&* B&JiZ iX	cZ cL K0 r   