o
    x[hÐ�  ã                   @   s˜  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 e¡Z dZ!d	Z"d
Z#dZ$G dd„ de%ƒZ&G dd„ de&ƒZ'G dd„ de&ƒZ(G dd„ de&ƒZ)	d%dee*ef fdd„Z+dd„ Z,d&dd„Z-d&dd„Z.G dd„ de j/ƒZ0G dd „ d e0ƒZ1G d!d"„ d"e0ƒZ2G d#d$„ d$e0ƒZ3e2e1e3gZ4dS )'é    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dS )ÚNoDHCPLeaseErrorz'Raised when unable to get a DHCP lease.N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   ú4/usr/lib/python3/dist-packages/cloudinit/net/dhcp.pyr   A   ó    r   c                   @   r   )ÚInvalidDHCPLeaseFileErrorz§Raised 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   r   r   c                   @   r   )ÚNoDHCPLeaseInterfaceErrorz7Raised when unable to find a viable interface for DHCP.Nr   r   r   r   r   r   M   r   r   c                   @   r   )ÚNoDHCPLeaseMissingDhclientErrorz$Raised when unable to find dhclient.Nr   r   r   r   r   r   Q   r   r   Úreturnc                 C   s2   |p| j }|du rt d¡ tƒ ‚| 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.
    Nz1Skip dhcp_discovery: Unable to find fallback nic.)Úfallback_interfaceÚLOGÚdebugr   Údhcp_clientÚdhcp_discovery)ÚdistroÚnicÚdhcp_log_funcÚ	interfacer   r   r   Úmaybe_perform_dhcp_discoveryU   s
   

r'   c                 C   s   t tjt| ƒdd�ƒS )zÛParse 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   )Úcontentr   r   r   Únetworkd_parse_leasel   s   r-   c                 C   sP   | du rt } i }tj | ¡s|S t | ¡D ]}tt tj | |¡¡ƒ||< q|S )zŸReturn 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.N)	ÚNETWORKD_LEASES_DIRÚosÚpathÚisdirÚlistdirr-   r   Úload_text_fileÚjoin)Úleases_dÚretÚlfiler   r   r   Únetworkd_load_leasesw   s   
ÿr8   c                 C   sF   |d u rt }t|d�}t| ¡ ƒD ]\}}| | ¡r ||    S qd S )N)r5   )r.   r8   ÚsortedÚitemsÚget)Úkeynamer5   ÚleasesÚ_ifindexÚdatar   r   r   Únetworkd_get_option_from_leasesŠ   s   

ÿr@   c                
   @   sÎ   e Zd ZdZdZdd„ Zedd„ ƒZedd„ ƒZed	e	fd
d„ƒZ
ed	e	fdd„ƒZejde	dee	ef fdd„ƒZeejde	deee	e	f  fdd„ƒƒZej		dde	dee dee	ef fdd„ƒZdS )Ú
DhcpClientÚ é
   c                 C   s   t  | j¡| _| jstƒ ‚d S ©N)r   ÚwhichÚclient_nameÚdhcp_client_pathr   ©Úselfr   r   r   Ú__init__˜   s   ÿzDhcpClient.__init__c                 C   s   t j d| jgddgd� d S )NÚpkillr   é   ©Úrcs)r   rF   )Úclsr   r   r   Úkill_dhcp_client�   s   zDhcpClient.kill_dhcp_clientc                 C   s*   |   ¡  t d¡}|D ]}t |¡ qd S )Nz/var/lib/dhcp/*)rP   Úglobr/   Úremove)rO   ÚfilesÚfiler   r   r   Úclear_leases¡   s
   
ÿzDhcpClient.clear_leasesÚdhcp_interfacec                 C   s   |j d| j|ddgd� d S )NÚstartr   rL   rM   ©Úmanage_servicerF   ©rO   rV   r#   r   r   r   Ústart_service¨   s   
ÿzDhcpClient.start_servicec                 C   s   |j d| jddgd� d S )NÚstopr   rL   rM   rX   rZ   r   r   r   Ústop_service®   s   zDhcpClient.stop_servicer&   r   c                 C   ó   i S )z´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.
        r   ©rI   r&   r   r   r   Úget_newest_lease²   s   zDhcpClient.get_newest_leaseÚroutesc                 C   s   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   )ra   r   r   r   Úparse_static_routes»   s   zDhcpClient.parse_static_routesNr%   c                 C   r^   )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   )rI   r&   r%   r#   r   r   r   r"   Ê   s   zDhcpClient.dhcp_discovery©NN)r   r   r   rF   ÚtimeoutrJ   ÚclassmethodrP   rU   Ústrr[   r]   ÚabcÚabstractmethodr   r   r`   Ústaticmethodr   r
   rb   r	   r   r"   r   r   r   r   rA   ”   s6    

"üþý
ûrA   c                	       sÖ   e Zd ZdZ‡ fdd„Zededeeee	f  fdd„ƒZ
edd	„ ƒZd
edeee	f fdd„Z		dd
edee deee	f fdd„Zededeeeef  fdd„ƒZedee fdd„ƒZdefdd„Z‡  ZS )ÚIscDhclientÚdhclientc                    ó   t ƒ  ¡  d| _d S )Nz/run/dhclient.lease©ÚsuperrJ   Ú
lease_filerH   ©Ú	__class__r   r   rJ   â   ó   

zIscDhclient.__init__Úlease_contentr   c                 C   sž   t  dt j¡}g }| sg S | | ¡D ]:}g }| d¡D ]}| ¡  dd¡ dd¡}|r4| | dd¡¡ qt|ƒ}| 	d¡}|rGt
 |¡|d< | |¡ q|S )	zÃparse 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ú;ú"rB   zoption ú rL   úunknown-245)ÚreÚcompileÚDOTALLÚfindallÚsplitÚstripÚreplaceÚappendr)   r;   rj   Úget_ip_from_lease_value)rs   Úlease_regexÚdhcp_leasesÚleaseÚlease_optionsÚlineÚoptionsÚopt_245r   r   r   Úparse_leasesæ   s&   €
ÿzIscDhclient.parse_leasesc                 C   sx   |   dd¡}t|ƒdkr2d}| d¡D ]}t|ƒdkrd| }||7 }qt dt|  dd¡dƒ¡}n| d	¡}t |¡S )
Nú\rB   é   ú:rL   Ú0z>Lé   zutf-8)	r~   Úlenr|   ÚstructÚpackÚintÚencodeÚsocketÚ	inet_ntoa)Úfallback_lease_valueÚunescaped_valueÚ
hex_stringÚhex_pairÚpacked_bytesr   r   r   r€     s   
ÿ

z#IscDhclient.get_ip_from_lease_valuer&   c                 C   sr   t tƒ�+ t | j¡}|r|  |¡}|r'|d W  d  ƒ S W d  ƒ i S W d  ƒ i S 1 s2w   Y  i 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 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   r3   ro   rˆ   )rI   r&   r,   r‚   r   r   r   r`     s   

û
þþ
üúzIscDhclient.get_newest_leaseNr%   c              
   C   sh  t  d|¡ d}d}d}t| j| ƒ}t| jd ƒ}ttƒ� t |¡ t | j¡ W d  ƒ n1 s4w   Y  |j	 
|¡ t|ƒrhdt|ƒdd…  }	d||	f }
tjd	d
�}tj ||d ¡}t ||
¡ zt | | j| j|||¡¡\}}W n tjy• } zt  d|j|j|j¡ t|‚d}~ww tj|| jg|dd�}|r³t  dd dd„ |D ƒ¡¡ i S d}d}d}d}t|ƒD ]M}zt |¡ ¡ }t|ƒ}W n tyÝ   d|› d�}Y n* t yë   d|› d�}Y nw | !|¡}|dk�rt  d|¡ t "|t#j$¡ d	} nt% &|¡ q¿t  |¡ |�st  'd||d¡ |du�r'|||ƒ |  (|¡}|�r1|S t)ƒ ‚)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ç{®Gáz„?é   z20:%sé$   z0interface "%s" {send dhcp-client-identifier %s;}T©Ú	needs_exez-dhclient.confz3dhclient exited with code: %s stderr: %r stdout: %r)ÚmaxwaitÚnaplenz+dhclient did not produce expected files: %sz, c                 s   s   � | ]	}t j |¡V  qd S rD   )r/   r0   Úbasename)Ú.0Úfr   r   r   Ú	<genexpr>}  s   € z-IscDhclient.dhcp_discovery.<locals>.<genexpr>ÚunknownFrB   úNo PID file found at z, dhclient is still runningúPID file contained [z], dhclient is still runningrL   zkilling dhclient with pid=%szCdhclient(pid=%s, parentpid=%s) failed to daemonize after %s secondsg      $@)*r   r    r‘   rd   r   r›   r/   rR   ro   Únet_opsÚlink_upr   r   r   Úget_tmp_ancestorr0   r4   r   Ú
write_filer   Úbuild_dhclient_cmdrG   ÚProcessExecutionErrorÚ	exit_codeÚstderrÚstdoutr   Úwait_for_filesÚwarningÚranger3   r}   Ú
ValueErrorÚget_proc_ppidÚkillÚsignalÚSIGKILLÚtimeÚsleepÚerrorr`   r   )rI   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ƒ   r   r   r   r"   &  s¬   

þÿþÿûÿ	ü€ùÿþ
ÿ
ÿÿ


û


zIscDhclient.dhcp_discoveryra   c                    s8  |   d¡‰ dd„ t dˆ ¡D ƒ}g }dˆ v rdd„ |D ƒ}‡ fdd„}d	}t|ƒD �]o\}}||k r3q)t|ƒ}|td
dƒv rzd}t||d… ƒ|k rZ|||t||d… ƒƒ |  S d ||d |d … ¡}	d ||d || … ¡}
|| }�n|tdd
ƒv r¿d}t||d… ƒ|k r�|||t||d… ƒƒ |  S d ||d |d … dg ¡}	d ||d || … ¡}
|| }nÏ|tddƒv �rd}t||d… ƒ|k rã|||t||d… ƒƒ |  S d ||d |d … ddg ¡}	d ||d || … ¡}
|| }nˆ|tddƒv �rNd}t||d… ƒ|k �r+|||t||d… ƒƒ |  S d ||d |d … g d¢ ¡}	d ||d || … ¡}
|| }n@|d	k�r„d}t||d… ƒ|k �rp|||t||d… ƒƒ |  S d}	d ||d || … ¡}
|| }n
t 	d|¡ |  S | 
d|	|f |
f¡ q)|S )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
        rt   c                 S   s   g | ]}|r|‘qS r   r   ©r¥   Útokr   r   r   Ú
<listcomp>Ø  s    z3IscDhclient.parse_static_routes.<locals>.<listcomp>z[, . :]r‹   c                 S   s   g | ]	}t t|d ƒƒ‘qS )r�   )rf   r‘   rÏ   r   r   r   rÑ   Ý  s    c                    s   d| ||ˆ f }t  |¡ d S )Nz¥RFC3442 string malformed.  Current route has CIDR of %s and requires %s significant octets, but only %s remain. Verify DHCP rfc3442-classless-static-routes value: %s)r   r¾   )ÚcidrÚrequiredÚremainÚmsg©Úrfc3442r   r   Ú_trunc_errorß  s
   
ýÿz5IscDhclient.parse_static_routes.<locals>._trunc_errorr   é   é!   é	   NÚ.rL   é   é   é   rŠ   rŒ   é   é   é   rž   )rŒ   rŒ   rŒ   z0.0.0.0zSParsed invalid net length "%s".  Verify DHCP rfc3442-classless-static-routes value.z%s/%s)Úrstriprx   r|   Ú	enumerater‘   r¶   rŽ   r4   r   r¾   r   )ra   ÚtokensÚstatic_routesrØ   Úcurrent_idxÚidxrÐ   Ú
net_lengthÚreq_toksÚnet_addressÚgatewayr   rÖ   r   rb   ­  s|   
*	 
"
ÿ


ýÿzIscDhclient.parse_static_routesc           	   	   C   s¤   d}| j | jfttffD ]C\}}|sqg }zt |¡}W n	 ty%   Y qw d}|D ]}t ||¡s3q*tj	 
||¡}tj	 |¡}||krH|}|}q*|rO|  S qdS )züGet 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/   r2   r›   rx   Úsearchr0   r4   Úgetmtime)	r#   Úlatest_fileÚ	directoryÚregexÚlease_filesÚlatest_mtimeÚfnameÚabs_pathÚmtimer   r   r   Ú!get_newest_lease_file_from_distro%  s8   	þûÿ€ÿz-IscDhclient.get_newest_lease_file_from_distroÚkeyc                 C   sR   |   |¡}|r#t |¡}|r%t|  |¡ƒD ]}| |¡}|r"|  S qdS dS dS )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   r3   Úreversedrˆ   r;   )rI   r#   rü   ro   r,   rƒ   Úserverr   r   r   Úget_key_from_latest_leaseQ  s   
	

ÿûz%IscDhclient.get_key_from_latest_leaserc   )r   r   r   rF   rJ   ri   rf   r   r   r   rˆ   r€   r`   r	   r   r"   r
   rb   rû   rÿ   Ú__classcell__r   r   rp   r   rj   ß   s.     
üþý

û  w+rj   c                	   @   s°   e Zd ZdZdZ		ddedee deee	f fdd„Z
ed	ed
edee fdd„ƒZedededefdd„ƒZdedeee	f fdd„Zededeeeef  fdd„ƒZdS )ÚDhcpcdÚdhcpcdi,  Nr&   r%   r   c              
   C   sþ  t  d|¡ d}t| j| ƒ}g }|j |¡ z³t|ƒrdg}| jdddddg|¢|‘}tj|| jd	�\}}	|d
ur?|||	ƒ |  	|¡}
|
rÇt g |¢d‘¡j
 ¡ }d
}d}d}t|ƒD ]b}z't |¡ ¡ }t|ƒ}| |¡}|r„t  d||¡ t |tj¡ W  |
W S W n. ty—   t  d|¡ Y  |
W S  ty¥   d|› d�}Y n ty³   d|› d�}Y nw |
  W S t |¡ q\t  |¡ |
W S tdƒ‚ tyä } zt  d|j|j|j
¡ t|‚d
}~w tjyþ } zt  d|j|j|j
¡ t|‚d
}~w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)rd   Nz-PFrB   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: %rú1dhcpcd exited with code: %s stderr: %r stdout: %r)r   r    r‘   rd   r«   r¬   r   rF   r   r`   r³   r}   r¶   r   r3   Úget_proc_pgidr/   Úkillpgrº   r»   ÚProcessLookupErrorr›   r·   r¼   r½   r   r   r²   r°   r±   )rI   r&   r%   r#   rÁ   rÂ   Úinfiniband_argumentÚcommandrÆ   rÇ   rƒ   r¿   rË   ÚgidrÌ   rÍ   rÎ   r¾   r   r   r   r"   h  s¤   úùø

þ


ÿäýñ
ÿ
ÿÿ

ü€ü€ùzDhcpcd.dhcp_discoveryr?   Údhcp_option_numberc                 C   s>   d}dt dtfdd„}|| |ƒD ]\}}||kr|  S qdS )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
        éð   r?   Úindexc                 s   sl   � t | ƒ|d kr4| | }| d|  }| d| d| | … }||fV  d| | }t | ƒ|d ks	dS dS )zÎoptions 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ž   rL   N)rŽ   )r?   r  ÚcodeÚlengthÚoptionr   r   r   Úiter_optionsø  s   €
ûz>Dhcpcd.parse_unknown_options_from_packet.<locals>.iter_optionsN)Úbytesr‘   )r?   r  ÚINDEXr  r  r  r   r   r   Ú!parse_unknown_options_from_packetß  s   ÿz(Dhcpcd.parse_unknown_options_from_packetÚ
lease_dumpc           
   
   C   s  t  d|| ¡ z$tdd„ |  ¡  dd¡ d¡D ƒƒ}|s*d}t  || ¡ t||  ƒ‚W n ty@ } z	t  d| ¡ t|‚d	}~ww ||d
< dd„ | 	¡ D ƒ}dddœ}| 	¡ D ]\}}||v rf| 
|¡||< qWt d|› d�¡}t |d¡}	|	rt |	¡|d< |S )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: %rc                 S   s"   g | ]}d |v r|j d dd�‘qS )ú=rL   )Úmaxsplit)r|   )r¥   Úar   r   r   rÑ   (  s
    þz-Dhcpcd.parse_dhcpcd_lease.<locals>.<listcomp>ú'rB   Ú
z;No valid DHCP lease configuration found in dhcpcd lease: %rzError parsing dhcpcd lease: %rNr&   c                 S   s   i | ]\}}|  d d¡|“qS )rÍ   ú-)r~   )r¥   rü   Úvaluer   r   r   Ú
<dictcomp>=  s    z-Dhcpcd.parse_dhcpcd_lease.<locals>.<dictcomp>zfixed-addressræ   )z
ip-addresszclassless-static-routesz/var/lib/dhcpcd/z.leaseéõ   rw   )r   r    r)   r}   r~   r|   r¾   r   r·   r:   Úpopr   Úload_binary_filer  r  r“   r”   )
r  r&   rƒ   rÕ   r¾   Úname_mapÚsourceÚdestinationÚdhcp_messager‡   r   r   r   Úparse_dhcpcd_lease  sH   ÿþÿÿú€þ	þ€
ÿzDhcpcd.parse_dhcpcd_leasec              
   C   sX   z|   t | jdd|g¡j|¡W S  tjy+ } zt d|j|j|j¡ t	|‚d}~ww )zÊReturn 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   rF   r³   r°   r   r    r±   r²   r   )rI   r&   r¾   r   r   r   r`   T  s,   üÿ÷ü€ùzDhcpcd.get_newest_leasera   c                 C   sD   |   ¡ }|rdd„ t|ddd… |ddd… ƒD ƒS t d| ¡ g S )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"),
        ]
        c                 S   ó   g | ]}|‘qS r   r   ©r¥   Úir   r   r   rÑ   ‹  ó    z.Dhcpcd.parse_static_routes.<locals>.<listcomp>Nrž   rL   z'Malformed classless static routes: [%s])r|   Úzipr   rµ   ©ra   ræ   r   r   r   rb   q  s
   (zDhcpcd.parse_static_routesrc   )r   r   r   rF   rd   rf   r	   r   r   r   r"   ri   r  r‘   r  r%  r`   r   r
   rb   r   r   r   r   r  d  s2    üþý

ûwÿÿþ+H$r  c                	       s„   e Zd ZdZ‡ fdd„Z		ddedee deee	f fdd	„Z
dedeee	f fd
d„Zededeeeef  fdd„ƒZ‡  ZS )ÚUdhcpcÚudhcpcc                    rl   )NrB   rm   rH   rp   r   r   rJ   “  rr   zUdhcpc.__init__Nr&   r%   r   c           
      C   sF  t  d|¡ tjdd�}tj ||d ¡| _tt	ƒ� t 
| j¡ W d  ƒ n1 s+w   Y  |j |¡ tj |d¡}t |td¡ | jdd	d
|d|ddddg}t|ƒrj| dd t|ƒdd…  dd¡¡g¡ ztj|d| jidd�\}}W n tjy” }	 zt  d|	j|	j|	j¡ t|	‚d}	~	ww |durž|||ƒ |  |¡S )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‹   rB   Ú
LEASE_FILE)Ú
update_envÚcapturez1udhcpc exited with code: %s stderr: %r stdout: %r)r   r    r   r­   r/   r0   r4   ro   r   r›   rR   r«   r¬   r   r®   ÚUDHCPC_SCRIPTrF   r   ÚextendÚformatr   r~   r   r°   r±   r²   r³   r   r`   )
rI   r&   r%   r#   rÅ   r.  ÚcmdrÆ   rÇ   r¾   r   r   r   r"   —  s\   
ÿõÿþÿÿü€ù	

zUdhcpc.dhcp_discoveryc                 C   s   t  t  | 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_jsonr3   ro   r_   r   r   r   r`   ß  s   zUdhcpc.get_newest_leasera   c                 C   s8   |   ¡ }|rdd„ t|d d d… |dd d… ƒD ƒS g S )Nc                 S   r&  r   r   r'  r   r   r   rÑ   ò  r)  z.Udhcpc.parse_static_routes.<locals>.<listcomp>rž   rL   )r|   r*  r+  r   r   r   rb   í  s   (zUdhcpc.parse_static_routesrc   )r   r   r   rF   rJ   rf   r	   r   r   r   r"   r`   ri   r   r
   rb   r   r   r   rp   r   r,  �  s    üþý

ûH(r,  rc   rD   )5rg   rQ   Úloggingr/   rx   rº   r“   r�   r¼   Ú
contextlibr   Úior   Ú
subprocessr   Útypingr   r   r   r   r	   r
   r*   Ú	cloudinitr   r   r   Úcloudinit.netr   r   Ú	getLoggerr   r   r.   rï   rð   r3  Ú	Exceptionr   r   r   r   rf   r'   r-   r8   r@   ÚABCrA   rj   r  r,  ÚALL_DHCP_CLIENTSr   r   r   r   Ú<module>   sT    
!ÿ

þ


K     .f