
    }f                        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Zd dlZd dlZd dl	m
Z
 d dlmZ d dlmZ d dlmZmZmZmZmZmZ d dlZd dlmZmZmZ d dlmZmZ  ej<                  e      Z dZ!d	Z"d
Z#dZ$ G d de%      Z& G d de&      Z' G d de&      Z( G d de&      Z)	 d!dee*ef   fdZ+d Z,d"dZ-d"dZ. G d de j^                        Z0 G d de0      Z1 G d de0      Z2 G d d e0      Z3e2e1e3gZ4y)#    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                       e Zd ZdZy)NoDHCPLeaseErrorz'Raised when unable to get a DHCP lease.N__name__
__module____qualname____doc__     4/usr/lib/python3/dist-packages/cloudinit/net/dhcp.pyr   r   A   s    1r   r   c                       e Zd ZdZy)InvalidDHCPLeaseFileErrorzRaised when parsing an empty or invalid dhclient.lease file.

    Current uses are DataSourceAzure and DataSourceEc2 during ephemeral
    boot to scrape metadata.
    Nr   r   r   r   r   r   E   s    r   r   c                       e Zd ZdZy)NoDHCPLeaseInterfaceErrorz7Raised when unable to find a viable interface for DHCP.Nr   r   r   r   r   r   M   s    Ar   r   c                       e Zd ZdZy)NoDHCPLeaseMissingDhclientErrorz$Raised when unable to find dhclient.Nr   r   r   r   r    r    Q   s    .r   r    returnc                     |xs | j                   }|t        j                  d       t               | j                  j                  |||       S )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_discoveryr,   U   sK     0v00I		EF')),,YvNNr   c                 T    t        t        j                  t        |       d            S )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_leaser3   l   s!     	##HW$55IJJr   c           	         | t         } i }t        j                  j                  |       s|S t        j                  |       D ]A  }t        t        j                  t        j                  j                  | |                  ||<   C |S )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listdirr3   r   load_text_filejoin)leases_dretlfiles      r   networkd_load_leasesr?   w   ss     &
C77=="
H% 
)Xu =>
E

 Jr   c                     |t         }t        |      }t        |j                               D ]  \  }}|j	                  |       s||    c S  y )N)r<   )r5   r?   sorteditemsget)keynamer<   leases_ifindexdatas        r   networkd_get_option_from_leasesrH      sP    &!84F 0 !$88G= ! r   c            
       .   e Zd ZdZdZd Zed        Zed        Zede	fd       Z
ede	fd       Zej                  d	e	d
ee	ef   fd       Zeej                  de	d
eee	e	f      fd              Zej                  	 	 dd	e	dee   d
ee	ef   fd       Zy)
DhcpClient 
   c                 x    t        j                  | j                        | _        | j                  s
t	               y N)r   whichclient_namedhcp_client_pathr    )selfs    r   __init__zDhcpClient.__init__   s0     $

4+;+; <$$133 %r   c                 N    t        j                   d| j                  gddg       y )Npkillr      rcs)r   rP   )clss    r   kill_dhcp_clientzDhcpClient.kill_dhcp_client   s    		7COO,1a&9r   c                     | j                          t        j                  d      }|D ]  }t        j                  |        y )Nz/var/lib/dhcp/*)rZ   globr6   remove)rY   filesfiles      r   clear_leaseszDhcpClient.clear_leases   s7    		+, 	DIIdO	r   dhcp_interfacec                 F    |j                  d| j                  |ddg       y )Nstartr   rV   rW   manage_servicerP   rY   ra   r(   s      r   start_servicezDhcpClient.start_service   s&    S__n1a& 	 	
r   c                 D    |j                  d| j                  ddg       y )Nstopr   rV   rW   rd   rf   s      r   stop_servicezDhcpClient.stop_service   s    fcooAq6Br   r+   r!   c                     i S )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   rR   r+   s     r   get_newest_leasezDhcpClient.get_newest_lease   s	     	r   routesc                     g S )ap  
        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   )rn   s    r   parse_static_routeszDhcpClient.parse_static_routes   s	     	r   Nr*   c                     i S )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   )rR   r+   r*   r(   s       r   r'   zDhcpClient.dhcp_discovery   s	    $ 	r   NN)r   r   r   rP   timeoutrS   classmethodrZ   r`   strrg   rj   abcabstractmethodr   r   rm   staticmethodr	   r   rp   r
   r   r'   r   r   r   rJ   rJ      s*   KG4
 : :   
3 
 

 C# C C 	# $sCx.   C DsCx,A    	 -1	  )
 
c3h r   rJ   c            	            e Zd ZdZ fdZededeeee	f      fd       Z
ed        Zdedeee	f   fdZ	 	 dded	ee   deee	f   fd
Zededeeeef      fd       Zedee   fd       ZdefdZ xZS )IscDhclientdhclientc                 0    t         |           d| _        y )Nz/run/dhclient.leasesuperrS   
lease_filerR   	__class__s    r   rS   zIscDhclient.__init__   s    /r   lease_contentr!   c                    t        j                  dt         j                        }g }t        |       dk(  rg S |j	                  |       D ]  }g }|j                  d      D ]V  }|j                         j                  dd      j                  dd      }|s6|j                  |j                  dd             X t        |      }|j                  d	      }|rt        j                  |      |d	<   |j                  |        |S )
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>.*?)}\nr   ;"rK   zoption  rV   unknown-245)recompileDOTALLlenfindallsplitstripreplaceappendr/   rC   rz   get_ip_from_lease_value)r   lease_regexdhcp_leasesleaselease_optionslineoptionsopt_245s           r   parse_leaseszIscDhclient.parse_leases   s     jj!<biiH"$}"I ((7 	(EMC( =zz|++C4<<YK!((C);<	=
 =)Gkk-0G)4)L)L*& w'	( r   c           	      P   | j                  dd      }t        |      dkD  rad}|j                  d      D ]  }t        |      dk(  rd|z   }||z  } t        j                  dt        |j                  dd      d            }n|j                  d	      }t        j                  |      S )
N\rK      :rV   0z>L   zutf-8)	r   r   r   structpackintencodesocket	inet_ntoa)fallback_lease_valueunescaped_value
hex_stringhex_pairpacked_bytess        r   r   z#IscDhclient.get_ip_from_lease_value  s    .66tR@!#J+11#6 'x=A%"X~Hh&
' ";;c*,,S"5r:L +11':L--r   r+   c                     t        t              5  t        j                  | j                        }|r!| j                  |      }|r|d   cddd       S ddd       i S # 1 sw Y   i S xY w)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   )rR   r+   r2   r   s       r   rm   zIscDhclient.get_newest_lease  sf     '( 	+))$//:G"//8&r?	+ 	+ 	+ 		+ 	s   9AA'r*   c           	         t         j                  d|       d}d}d}t        | j                  |z        }t        | j                  dz        }t	        t
              5  t        j                  |       t        j                  | j                         ddd       |j                  j                  |       t        |      ridt        |      dd z  }	d|d	|	d
}
t        j                  d      }t        j                  j!                  ||dz         }t#        j$                  ||
       	 t'        j&                  |j)                  | j*                  | j                  |||            \  }}t#        j6                  || j                  g|d      }|r.t         j9                  ddj!                  d |D                     i S d}d}d}d}t;        |      D ]  }	 t#        j<                  |      j?                         }t        |      }|jA                  |      }|dk(  r>t         j                  d|       t        jB                  |tD        jF                         d} n,tK        jL                  |        t         j                  |       |st         jO                  d||d       |	 |||       | jQ                  |      }|r|S tS               # 1 sw Y   6xY w# t&        j,                  $ rB}t         j                  d|j.                  |j0                  |j2                         t4        |d}~ww xY w# t
        $ r	 d| d}Y tH        $ r	 d| d}Y w xY w)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   Z   K   | ]#  }t         j                  j                  |       % y wrN   )r6   r7   basename).0fs     r   	<genexpr>z-IscDhclient.dhcp_discovery.<locals>.<genexpr>}  s     ?!"''**1-?s   )+unknownFrK   rV   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   rs   r   r   r6   r]   r   net_opslink_upr   r   r   get_tmp_ancestorr7   r;   r   
write_filer   build_dhclient_cmdrQ   ProcessExecutionError	exit_codestderrstdoutr   wait_for_fileswarningranger:   r   get_proc_ppidkillsignalSIGKILL
ValueErrortimesleeperrorrm   r   )rR   r+   r*   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'   z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)CD	.yy))))OOHC2 %%t'
 KK=		?w?? I
	|$ 	!A"11(;AAC+& ++C019II<cBGGC0!%JJJz"+	!. IIi II $#s#%%i0L'))Q	' 	'H )) 	.IIE	 #-	.D % +H: 60 0   *;- 80 0 s<   5K)?K .L*KL'%=L""L'*M;MMrn   c           
         | j                  d      t        j                  d      D cg c]  }|s|	 }}g }dv r"|D cg c]  }t        t	        |d             }}fd}d}t        |      D ]  \  }}||k  rt	        |      }|t        dd      v rhd	}t        ||d
       |k  r |||t        ||d
              |c S dj                  ||dz   |dz          }	dj                  ||dz   ||z          }
||z   }n|t        dd      v rld}t        ||d
       |k  r |||t        ||d
              |c S dj                  ||dz   |dz    dgz         }	dj                  ||dz   ||z          }
||z   }nb|t        d	d      v rld}t        ||d
       |k  r |||t        ||d
              |c S dj                  ||dz   |dz    ddgz         }	dj                  ||dz   ||z          }
||z   }n|t        dd	      v rld}t        ||d
       |k  r |||t        ||d
              |c S dj                  ||dz   |dz    g dz         }	dj                  ||dz   ||z          }
||z   }nn|dk(  rOd}t        ||d
       |k  r |||t        ||d
              |c S d}	dj                  ||dz   ||z          }
||z   }nt        j                  d|       |c S |j                  |	d||
f        |S c c}w c c}w )a(  
        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                 L    d| d|d|d}t         j                  |       y )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_errorz5IscDhclient.parse_static_routes.<locals>._trunc_error  s%    
 674  IIcNr   r      !   	   N.rV            r   r            r   )r   r   r   z0.0.0.0zSParsed invalid net length "%s".  Verify DHCP rfc3442-classless-static-routes value./)rstripr   r   ru   r   	enumerater   r   r;   r$   r   r   )rn   toktokensstatic_routesr   current_idxidx
net_lengthreq_toksnet_addressgatewayr   s              @r   rp   zIscDhclient.parse_static_routes  s~   T --$!#*g!>F###FF/1 '>39:Cc#c2,':F:	 !&) 8	HC[ SJU2r]*vcd|$x/ Xs6#$<7HI((!hhvcAga'@A((6#'C(N#CD!HnuR},vcd|$x/ Xs6#$<7HI((!hhvcAga'@C5'HI((6#'C(N#CD!HnuQ|+vcd|$x/ Xs6#$<7HI((!hhvcAga'@C:'MN((6#'C(N#CD!HnuQ{*vcd|$x/ Xs6#$<7HI((!hh37S1W-? ((6#'C(N#CD!Hnqvcd|$x/ Xs6#$<7HI(('((6#'C(N#CD!Hn		=
 %$  '4g>m8	t W G
 ;s   K:K:K?c                    d}| j                   | j                  ft        t        ffD ]  \  }}|s	g }	 t	        j
                  |      }d}|D ]b  }t        j                  ||      st        j                  j                  ||      }t        j                  j                  |      }||kD  s_|}|}d |s|c S  y# t        $ r Y w xY w)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_REGEXr6   r9   r   r   searchr7   r;   getmtime)	r(   latest_file	directoryregexlease_fileslatest_mtimefnameabs_pathmtimes	            r   !get_newest_lease_file_from_distroz-IscDhclient.get_newest_lease_file_from_distro%  s     
 //00 )*GH!
 	#Iu K jj3  L$ +yy.77<<	59((2<'#(L"*K+ "";	#< # % s   B::	CCkeyc                     | j                  |      }|rOt        j                  |      }|r7t        | j	                  |            D ]  }|j                  |      }|s|c S  yyy)a8  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   rC   )rR   r(   r  r   r2   r   servers          r   get_key_from_latest_leasez%IscDhclient.get_key_from_latest_leaseQ  sh     ;;FC
))*5G%d&7&7&@A &E"YYs^F%&  r   rr   )r   r   r   rP   rS   rx   ru   r	   r   r   r   r   rm   r
   r   r'   r   rp   r  r  __classcell__r   s   @r   rz   rz      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   rz   c            	           e Zd ZdZdZ	 	 ddedee   deee	f   fdZ
eded	edee   fd
       Zedededefd       Zdedeee	f   fdZededeeeef      fd       Zy)Dhcpcddhcpcdi,  Nr+   r*   r!   c                 B   t         j                  d|       d}t        | j                  |z        }g }|j                  j                  |       	 t        |      rdg}| j                  dddddg||}t        j                  || j                  	      \  }}	|	 |||	       | j                  |      }
|
rt        j                  g |d      j                  j                         }d
}d}d}t        |      D ]  }	 t        j                  |      j                         }t        |      }|j                  |      }|r>t         j                  d||       t!        j"                  |t$        j&                          |
S 	 |
c S  t         j                  |       |
S t3        d      # t(        $ r t         j                  d|       Y  |
S t*        $ r	 d| d}Y nt,        $ r	 d| d}Y nw xY wt/        j0                  |       	# t4        $ rB}t         j                  d|j                  |j6                  |j                         t2        |d
}~wt        j8                  $ rB}t         j                  d|j:                  |j6                  |j                         t2        |d
}~ww xY w)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)rs   Nz-PFrK   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   rs   r   r   r   rQ   r   rm   r   r   r   r   r:   get_proc_pgidr6   killpgr   r   ProcessLookupErrorr   r   r   r   r   r   r   r   r   )rR   r+   r*   r(   r   r   infiniband_argumentcommandr   r   r   r   r   gidr   r   r   r   s                     r   r'   zDhcpcd.dhcp_discoveryh  s     			5yA
4<<*45  	y)[	. y)'3n#%%$	 %	 	G yyHC (c3')))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   B+H  ;A<F"7H  ;H  ?H  H  "G&H  G&H  G&#H  %G&&H   	J	=IJ=JJrG   dhcp_option_numberc                 \    d}dt         dt        fd} || |      D ]  \  }}||k(  s|c S  y)aV  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
           rG   indexc              3      K   t        |       |dz   k\  r<| |   }| d|z      }| d|z   d|z   |z    }||f d|z   |z   }t        |       |dz   k\  r;yyw)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   rV   N)r   )rG   r'  codelengthoptions        r   iter_optionsz>Dhcpcd.parse_unknown_options_from_packet.<locals>.iter_options  sq      d)uqy(E{a%ia%i!e)f*<=Fl"F
U* d)uqy(s   AAAN)bytesr   )rG   r$  INDEXr,  r)  r+  s         r   !parse_unknown_options_from_packetz(Dhcpcd.parse_unknown_options_from_packet  sK    . 	+u 	+S 	+ )u5 	LD&))	 r   
lease_dumpc           	         t         j                  d||        	 t        | j                         j	                  dd      j                  d      D cg c]  }d|v r|j                  dd       c}      }|s&d}t         j                  ||        t        || z        	 ||d<   |j                         D ci c]  \  }}|j	                  dd      | }}}ddd}|j                         D ]  \  }	}
|	|v s|j                  |	      ||
<     t        j                  d| d      }t        j                  |d      }|rt        j                   |      |d<   |S c c}w # t        $ r"}t         j                  d	|        t        |d
}~ww xY wc c}}w )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'rK   
=rV   )maxsplitz;No valid DHCP lease configuration found in dhcpcd lease: %rzError parsing dhcpcd lease: %rNr+   r   -zfixed-addressr   )z
ip-addresszclassless-static-routesz/var/lib/dhcpcd/z.lease   r   )r$   r%   r/   r   r   r   r   r   r   rB   popr   load_binary_filer  r/  r   r   )r0  r+   ar   r   r   r  valuename_mapsourcedestinationdhcp_messager   s                r   parse_dhcpcd_leasezDhcpcd.parse_dhcpcd_lease  s   , 			7J	

	7 (--/77R@FFtLax GGC!G,E 0  		#z*/j0@AA  'k AFN*#uS#&-NN *'6
 $,>>#3 	7FK%*YYv%6k"	7 ,,yk0
 ::<M#)#3#3G#<E- U  	7II6
C+6	7 Os/   6E E-/E 5F	E 	F$FFc                 .   	 | j                  t        j                  | j                  dd|g      j                  |      S # t        j                  $ rB}t
        j                  d|j                  |j                  |j                         t        |d}~ww xY w)zReturn a dict of dhcp options.

        @param interface: which interface to dump the lease from
        @raises: InvalidDHCPLeaseFileError on empty or unparsable leasefile
            content.
        z--dumpleaser  r  N)
r@  r   rQ   r   r   r$   r%   r   r   r   )rR   r+   r   s      r   rm   zDhcpcd.get_newest_leaseT  s    	.**		--%$!	 &
 
 )) 	.IIC	 #-	.s   <? B=BBrn   c                     | j                         }|r&t        |ddd   |ddd         D cg c]  }| c}S t        j                  d|        g S c c}w )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   rV   z'Malformed classless static routes: [%s])r   zipr$   r   rn   r   is      r   rp   zDhcpcd.parse_static_routesq  sX    . "=1#5}QTT7JKL!ALL=vF	 Ms   	Arr   )r   r   r   rP   rs   ru   r
   r   r   r   r'   rx   r-  r   r/  r@  rm   r	   r   rp   r   r   r   r  r  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   r  c            	            e Zd ZdZ fdZ	 	 d
dedee   deee	f   fdZ
dedeee	f   fdZededeeeef      fd	       Z xZS )Udhcpcudhcpcc                 0    t         |           d | _        y rN   r}   r   s    r   rS   zUdhcpc.__init__  s    r   r+   r*   r!   c                    t         j                  d|       t        j                  d      }t        j
                  j                  ||dz         | _        t        t              5  t	        j                  | j                         ddd       |j                  j                  |       t        j
                  j                  |d      }t        j                  |t        d       | j                   dd	d
|d|ddddg}t#        |      r>|j%                  ddj'                  t)        |      dd j+                  dd            g       	 t-        j,                  |d| j                  id      \  }}|	 |||       | j9                  |      S # 1 sw Y   xY w# t,        j.                  $ rB}	t         j                  d|	j0                  |	j2                  |	j4                         t6        |	d}	~	ww xY w)ar  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   rK   
LEASE_FILE)
update_envcapturez1udhcpc exited with code: %s stderr: %r stdout: %r)r$   r%   r   r   r6   r7   r;   r   r   r   r]   r   r   r   r   UDHCPC_SCRIPTrQ   r   extendformatr   r   r   r   r   r   r   r   rm   )
rR   r+   r*   r(   r   rK  cmdr   r   r   s
             r   r'   zUdhcpc.dhcp_discovery  s    			5yA--='',,w	M0IJ'( 	'IIdoo&	' 	y)Wo>}e< !!
$ 9%JJ&&))4RS9AA#rJ	.yyt ?HC $#s#$$Y//i	' 	'P )) 	.IIC	 #-	.s$   $ F'F FG(&=G##G(c                 f    t        j                  t        j                  | j                              S )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   rl   s     r   rm   zUdhcpc.get_newest_lease  s"     ~~d11$//BCCr   rn   c                     | j                         }|r&t        |d d d   |dd d         D cg c]  }| c}S g S c c}w )Nr   rV   )r   rC  rD  s      r   rp   zUdhcpc.parse_static_routes  sG    "=1#5}QTT7JKL!ALL	 Ms   	;rr   )r   r   r   rP   rS   ru   r
   r   r   r   r'   rm   rx   r	   r   rp   r  r  s   @r   rG  rG    s    K -1	F0F0  )F0
 
c3hF0PD# D$sCx. D C DsCx,A  r   rG  rr   rN   )5rv   r\   loggingr6   r   r   r   r   r   
contextlibr   ior   
subprocessr   typingr   r   r   r	   r
   r   r0   	cloudinitr   r   r   cloudinit.netr   r   	getLoggerr   r$   r5   r  r  rP  	Exceptionr   r   r   r    ru   r,   r3   r?   rH   ABCrJ   rz   r  rG  ALL_DHCP_CLIENTSr   r   r   <module>rb     s      	 	       % = =  , , <g!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   