x[hЏddlZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZddlmZmZmZmZmZmZddlZddlmZmZmZddlmZmZej<eZ dZ!d Z"d Z#d Z$Gd d e%Z&Gdde&Z'Gdde&Z(Gdde&Z) d!dee*effdZ+dZ,d"dZ-d"dZ.Gddej^Z0Gdde0Z1Gdde0Z2Gdd e0Z3e2e1e3gZ4y)#N)suppress)StringIO)TimeoutExpired)AnyCallableDictListOptionalTuple)subp temp_utilsutil)get_interface_macis_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 < "$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 ceZdZdZy)NoDHCPLeaseErrorz'Raised when unable to get a DHCP lease.N__name__ __module__ __qualname____doc__4/usr/lib/python3/dist-packages/cloudinit/net/dhcp.pyrrAs1rrceZdZdZy)InvalidDHCPLeaseFileErrorzRaised when parsing an empty or invalid dhclient.lease file. Current uses are DataSourceAzure and DataSourceEc2 during ephemeral boot to scrape metadata. NrrrrrrEsrrceZdZdZy)NoDHCPLeaseInterfaceErrorz7Raised when unable to find a viable interface for DHCP.NrrrrrrMsArrceZdZdZy)NoDHCPLeaseMissingDhclientErrorz$Raised when unable to find dhclient.Nrrrrr r Qs.rr returnc|xs |j}|tjdt|jj |||S)aPerform 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_interfaceLOGdebugr dhcp_clientdhcp_discovery)distronic dhcp_log_func interfaces rmaybe_perform_dhcp_discoveryr,UsK0v00I EF'))    , ,Y v NNrcTttjt|dS)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 rnetworkd_parse_leaser3ls!  ##HW$55I JJrc |t}i}tjj|s|Stj|D]A}t t jtjj||||<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_DIRospathisdirlistdirr3rload_text_filejoin)leases_dretlfiles rnetworkd_load_leasesr?wss &C 77== " H% )    Xu = > E   Jrc|t}t|}t|jD]\}}|j |s||cSy)N)r<)r5r?sorteditemsget)keynamer<leases_ifindexdatas rnetworkd_get_option_from_leasesrHsP& !8 4F 0!$ 88G = ! rc .eZdZdZdZdZedZedZede fdZ ede fdZ e jd e d ee effd Zee jd e d eee e ffd Ze j dd e deed ee effdZy) DhcpClient cxtj|j|_|js t yN)r which client_namedhcp_client_pathr )selfs r__init__zDhcpClient.__init__s0 $ 4+;+; <$$13 3%rcNtjd|jgddgy)Npkillrrcs)r rP)clss rkill_dhcp_clientzDhcpClient.kill_dhcp_clients 7COO,1a&9rc|jtjd}|D]}tj|y)Nz/var/lib/dhcp/*)rZglobr6remove)rYfilesfiles r clear_leaseszDhcpClient.clear_leasess7  +, D IIdO rdhcp_interfacecF|jd|j|ddgy)NstartrrVrWmanage_servicerPrYrar(s r start_servicezDhcpClient.start_services& S__n1a&  rcD|jd|jddgy)NstoprrVrWrdrfs r stop_servicezDhcpClient.stop_servicesfcooAq6Brr+r!ciS)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. rrRr+s rget_newest_leasezDhcpClient.get_newest_leases  rroutescgS)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)rns rparse_static_routeszDhcpClient.parse_static_routess  rNr*ciS)aRun 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)rRr+r*r(s rr'zDhcpClient.dhcp_discoverys $ rNN)rrrrPtimeoutrS classmethodrZr`strrgrjabcabstractmethodrrrm staticmethodr r rpr rr'rrrrJrJs*KG4 ::  3  C#CC #$sCx. C DsCx,A   -1  ) c3h rrJc eZdZdZfdZededeeee ffdZ edZ dedeee ffdZ dded e edeee ffd Zed edeeeeffd Zede efd ZdefdZxZS) IscDhclientdhclientc0t|d|_y)Nz/run/dhclient.leasesuperrS lease_filerR __class__s rrSzIscDhclient.__init__s /r lease_contentr!ctjdtj}g}|sgS|j|D]}g}|j dD]V}|j j ddj dd}|s6|j|j ddXt|}|jd}|rtj||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 zlease {(?P.*?)}\n;"rKzoption  rV unknown-245) recompileDOTALLfindallsplitstripreplaceappendr/rCrzget_ip_from_lease_value)r lease_regex dhcp_leaseslease lease_optionslineoptionsopt_245s r parse_leaseszIscDhclient.parse_leasessjj!Lzutf-8) rlenrstructpackintencodesocket inet_ntoa)fallback_lease_valueunescaped_value hex_stringhex_pair packed_bytess rrz#IscDhclient.get_ip_from_lease_values.66tR@  ! #J+11#6 'x=A%"X~Hh&  '";;c*,,S"5r:L+11':L --rr+ctt5tj|j}|r!|j |}|r|dcdddSdddiS#1swYiSxYw)aGet 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)rFileNotFoundErrorrr:rr)rRr+r2rs rrmzIscDhclient.get_newest_leasesf' ( +))$//:G"//8 &r?  + + +   +  s 9AA'r*c tjd|d}d}d}t|j|z }t|jdz }t t 5t j|t j|jddd|jj|t|ridt|ddz} d|d | d } tjd } t jj!| |d z}t#j$||  t'j&|j)|j*|j|||\} } t#j6||jg|d}|r.tj9ddj!d|DiSd}d}d}d}t;|D]} t#j<|j?}t|}|jA|}|dk(r>tjd|t jB|tDjFd }n,tKjL|tj||stjOd||d| || | |jQ|}|r|StS#1swY6xYw#t&j,$rB}tjd|j.|j0|j2t4|d}~wwxYw#t $r d|d}YtH$r d|d}YwxYw)aRun 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?z20:%s$z interface "z" {send dhcp-client-identifier z;}T needs_exez-dhclient.confz3dhclient exited with code: %s stderr: %r stdout: %r)maxwaitnaplenz+dhclient did not produce expected files: %sz, c3ZK|]#}tjj|%ywrN)r6r7basename).0fs r z-IscDhclient.dhcp_discovery..}s?!"''**1-?s)+unknownFrKrVzkilling dhclient with pid=%sNo PID file found at z, dhclient is still runningPID file contained [z], dhclient is still runningzCdhclient(pid=%s, parentpid=%s) failed to daemonize after %s secondsg$@)*r$r%rrsrrr6r]rnet_opslink_uprrr get_tmp_ancestorr7r;r write_filer build_dhclient_cmdrQProcessExecutionError exit_codestderrstdoutrwait_for_fileswarningranger:r get_proc_ppidkillsignalSIGKILL ValueErrortimesleeperrorrmr)rRr+r*r(pid_file config_file sleep_time sleep_cyclesrdhcp_client_identifierinterface_dhclient_contenttmp_dirouterrrmissingppid daemonized pid_content debug_msg_pidrs rr'zIscDhclient.dhcp_discovery&s" 5yA '  4<<*45 dllQ&'' ( ' IIh  IIdoo & ' y) 9 %+I6rs;; # 46 ' !11DAG'',,w ._trunc_errors% 674  IIcNrr! N.rVrrr)rrrz0.0.0.0zSParsed invalid net length "%s". Verify DHCP rfc3442-classless-static-routes value./) rstriprrrur enumeraterrr;r$rr) rntoktokens static_routesr current_idxidx net_lengthreq_toks net_addressgatewayrs @rrpzIscDhclient.parse_static_routess~T--$!#*g!>F###FF/1  '>39:Cc#c2,':F:  !&)8 HC[ SJU2r]*vcd|$x/ Xs6#$<7HI((!hhvcAga'@A ((6#'C(N#CD!Hn uR},vcd|$x/ Xs6#$<7HI((!hhvcAga'@C5'HI ((6#'C(N#CD!Hn uQ|+vcd|$x/ Xs6#$<7HI((!hhvcAga'@C:'MN ((6#'C(N#CD!Hn uQ{*vcd|$x/ Xs6#$<7HI((!hh37S1W-? ((6#'C(N#CD!Hn qvcd|$x/ Xs6#$<7HI((' ((6#'C(N#CD!Hn  = %$  '4g> m8 tWG ;sK:K:K?cd}|j|jfttffD]\}}|s g} t j |}d}|D]b}tj||stjj||}tjj|}||kDs_|}|}d|s|cSy#t $rYwxYw)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_directorydhclient_lease_file_regexDHCLIENT_FALLBACK_LEASE_DIRDHCLIENT_FALLBACK_LEASE_REGEXr6r9rrsearchr7r;getmtime) r( latest_file directoryregex lease_files latest_mtimefnameabs_pathmtimes r!get_newest_lease_file_from_distroz-IscDhclient.get_newest_lease_file_from_distro%s //00 )*G H !  # IuK  jj3  L$ +yy.77<< 59((2<'#(L"*K +""; #<#%  sB:: CCkeyc|j|}|rOtj|}|r7t|j |D]}|j |}|s|cSyyy)a8Get 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)rrr:reversedrrC)rRr(rrr2rservers rget_key_from_latest_leasez%IscDhclient.get_key_from_latest_leaseQsh;;FC ))*5G%d&7&7&@A&E"YYs^F% & rrr)rrrrPrSrxrur rrrrrmr rr'r rprr __classcell__rs@rrzrzsK0CDc3h,@6 . .#$sCx..-1 E*E* )E* c3h E*NuCuDsCx,Auun)Xc]))V&S&rrzc eZdZdZdZ ddedeedeee ffdZ e de d e dee fd Ze d ededefd Zdedeee ffd Ze dedeeeeffdZy)Dhcpcddhcpcdi,Nr+r*r!cBtjd|d}t|j|z }g}|jj | t |rdg}|jdddddg||}tj||j \}} | ||| |j|} | rtjg|d jj} d } d } d }t|D]} tj| j} t| }|j|} | r>tjd|| t!j"| t$j&| S | cStj|| St3d#t($rtjd| Y| St*$r d| d}Ynt,$r d| d}YnwxYwt/j0| #t4$rB}tjd|j|j6|jt2|d }~wtj8$rB}tjd|j:|j6|jt2|d }~wwxYw)aRun 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 rrz --clientid --ipv4onlyz--waitipz --persistentz--noarpz--script=/bin/true)rsNz-PFrKz!killing dhcpcd with pid=%s gid=%sz9Process group id [%s] has already exited, nothing to killrz, dhcpcd is still runningrz], dhcpcd is still runningzNo lease foundz8dhcpcd timed out after %s seconds: stderr: %r stdout: %r1dhcpcd exited with code: %s stderr: %r stdout: %r)r$r%rrsrrrrPr rmrrrrr: get_proc_pgidr6killpgrrProcessLookupErrorrrrrrrrrr)rRr+r*r(rrinfiniband_argumentcommandrrrrrgidrrrrs rr'zDhcpcd.dhcp_discoveryhs 5yA 4<<*45   y)[ .y)'3n#  $ %  Gyy HC(c3')))4E 99%5w%5%56==CCE"  |, )A%&*&9&9(&C&I&I&K !+.$2237II CS#IIc6>>:!. 90 % ; )@IIi( "#34 4/. .   -3H:>66"&2;-@66"JJz*  . IIJ     # -)) . IIC    # - .stB+H;ADhcpcd.parse_unknown_options_from_packet..iter_optionssqd)uqy(E{a%ia%i!e)f*<=Fl"F U* d)uqy(s A AAN)bytesr)rGr$INDEXr,r)r+s r!parse_unknown_options_from_packetz(Dhcpcd.parse_unknown_options_from_packetsK. +u +S +)u5 LD&))  r lease_dumpc tjd|| t|jj ddj dDcgc]}d|vr|j ddc}}|s&d}tj ||t||z ||d <|jDcic]\}}|j d d |}}}ddd}|jD]\} } | |vs |j| || < tjd|d} tj| d} | rtj | |d<|Scc}w#t$r"}tj d |t|d }~wwxYwcc}}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: %rzError parsing dhcpcd lease: %rNr+r-z fixed-addressr)z ip-addresszclassless-static-routesz/var/lib/dhcpcd/z.leaser)r$r%r/rrrrrrrBpoprload_binary_filerr/rr) r0r+arrrrvaluename_mapsource destination dhcp_messagers rparse_dhcpcd_leasezDhcpcd.parse_dhcpcd_lease s, 7J  7(--/77R@FFtLaxGGC!G,E0 #z*/j0@AA 'kAF N*#uS#&-NN*'6 $,>>#3 7 FK%*YYv%6k" 7,,yk 0 ::<M #)#3#3G#|j%ddj't)|ddj+ddg t-j,|d|jid\}}| ||||j9|S#1swYxYw#t,j.$rB} tjd| j0| j2| j4t6| d} ~ wwxYw)arRun 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. rTrz .lease.jsonN udhcpc_scriptiz-O staticroutesz-iz-sz-nz-qz-fz-vz-xz 0x3d:20{}rrrK LEASE_FILE) update_envcapturez1udhcpc exited with code: %s stderr: %r stdout: %r)r$r%r rr6r7r;rrrr]rrrr UDHCPC_SCRIPTrPrextendformatrrr rrrrrrm) rRr+r*r(rrKcmdrrrs rr'zUdhcpc.dhcp_discoverys 5yA--='',,w M0IJ ' ( ' IIdoo & ' y) Wo>   }e<               $ 9 % JJ&&))4RS9AA#rJ  .yyt ?HC  $ #s #$$Y//i ' 'P)) . IIC    # - .s$$ F'FFG(&=G##G(cftjtj|jS)aGet 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:rrls rrmzUdhcpc.get_newest_leases"~~d11$//BCCrrnc|j}|r&t|ddd|dddDcgc]}|c}SgScc}w)NrrV)rrCrDs rrpzUdhcpc.parse_static_routessG  "=1#5}QTT7JKL!AL L Ms ;rr)rrrrPrSrur rrrr'rmrxr r rprrs@rrGrGsK-1 F0F0 )F0 c3h F0P D# D$sCx. DCDsCx,ArrGrrrN)5rvr\loggingr6rrrrr contextlibrior subprocessrtypingrrrr r r r0 cloudinitr r r cloudinit.netrr getLoggerrr$r5rrrP Exceptionrrrr rur,r3r?rHABCrJrzrrGALL_DHCP_CLIENTSrrrrbs  %==,,<g!11 / B2y2 0B 0B/&6/ %)O #s(^O.K&HHVB&*B&J iZiX cZcLK0r