\`f 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 dZ*dZ+d!dZ,d!dZ-Gddej\Z/Gdde/Z0Gdde/Z1Gdde/Z2e1e0e2gZ3y)"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 c|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_leaser2js!  ##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_DIRospathisdirlistdirr2rload_text_filejoin)leases_dretlfiles rnetworkd_load_leasesr>uss & C 77== " H% )    Xu = > E   Jrc|t}t|}t|jD]\}}|j |s||cSy)N)r;)r4r>sorteditemsget)keynamer;leases_ifindexdatas rnetworkd_get_option_from_leasesrGsP& !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 rO)clss rkill_dhcp_clientzDhcpClient.kill_dhcp_clients 7COO,1a&9rc|jtjd}|D]}tj|y)Nz/var/lib/dhcp/*)rYglobr5remove)rXfilesfiles r clear_leaseszDhcpClient.clear_leasess7  +, D IIdO rdhcp_interfacecF|jd|j|ddgy)NstartrrUrVmanage_servicerOrXr`r's r start_servicezDhcpClient.start_services& S__n1a&  rcD|jd|jddgy)NstoprrUrVrcres r stop_servicezDhcpClient.stop_servicesfcooAq6Brr*returnciS)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. rrQr*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)rQr*r)r's rr&zDhcpClient.dhcp_discoverys $ rNN)rrrrOtimeoutrR classmethodrYr_strrfriabcabstractmethodrrrm staticmethodr r rpr rr&rrrrIrIs*KG4 ::  3  C#CC #$sCx. C DsCx,A   -1  ) c3h rrIc eZdZdZfdZededeeee ffdZ edZ dedeee ffdZ dded e edeee ffd Zed edeeeeffd Zede efd ZdefdZxZS) IscDhclientdhclientc0t|d|_y)Nz/run/dhclient.leasesuperrR lease_filerQ __class__s rrRzIscDhclient.__init__s /r lease_contentrjctjdtj}g}t|dk(rgS|j |D]}g}|j dD]V}|j jddjdd}|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.*?)}\nr;"rJzoption  rU unknown-245) recompileDOTALLlenfindallsplitstripreplaceappendr.rBrzget_ip_from_lease_value)r lease_regex dhcp_leaseslease lease_optionslineoptionsopt_245s r parse_leaseszIscDhclient.parse_leasessjj!Lzutf-8) rrrstructpackintencodesocket 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)rFileNotFoundErrorrr9rr)rQr*r1rs 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|%ywrM)r5r6basename).0fs r z-IscDhclient.dhcp_discovery..{s?!"''**1-?s)+unknownFrJrUzkilling 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$rrsrrr5r\rnet_opslink_uprrr get_tmp_ancestorr6r:r write_filer build_dhclient_cmdrPProcessExecutionError exit_codestderrstdoutrwait_for_fileswarningranger9r get_proc_ppidkillsignalSIGKILL ValueErrortimesleeperrorrmr)rQr*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.rUrrr)rrrz0.0.0.0zSParsed invalid net length "%s". Verify DHCP rfc3442-classless-static-routes value./) rstriprr enumeraterrrr:r#rr) rntoktokens static_routesr current_idxidx net_lengthreq_toks net_addressgatewayrs @rrpzIscDhclient.parse_static_routessRB--$!#(G!<D##DD/1   !&)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 tOEs KKcd}|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_REGEXr5r8rrsearchr6r:getmtime) r' latest_file directoryregex lease_files latest_mtimefnameabs_pathmtimes r!get_newest_lease_file_from_distroz-IscDhclient.get_newest_lease_file_from_distros //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)rrr9reversedrrB)rQr'rrr1rservers rget_key_from_latest_leasez%IscDhclient.get_key_from_latest_leaseBsh;;FC ))*5G%d&7&7&@A&E"YYs^F% & rrr)rrrrOrRrxrur rrrrrmr rr&r rprr __classcell__rs@rrzrzsK0CDc3h,@6 . .#$sCx..-1 E*E* )E* c3h E*NhChDsCx,AhhT)Xc]))V&S&rrzc eZdZdZdZ ddedeedeee ffdZ e de d e dee fd Ze d ededefd Zdedeee ffd Ze dedeeeeffdZy)Dhcpcddhcpcdi,Nr*r)rjcBtjd|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-PFrJz!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 rmrrrrr9 get_proc_pgidr5killpgrrProcessLookupErrorrrrrrrrrr)rQr*r)r'rrinfiniband_argumentcommandrrrrrgidrrrrs rr&zDhcpcd.dhcp_discoveryYs 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)rFr$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'rJ =rU)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.rrrrrrrApoprload_binary_filerr/rr) r0r*arrrrvaluename_mapsource destination dhcp_messagers rparse_dhcpcd_leasezDhcpcd.parse_dhcpcd_leases, 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{}rrrJ LEASE_FILE) update_envcapturez1udhcpc exited with code: %s stderr: %r stdout: %r)r#r$r rr5r6r:rrrr\rrrr UDHCPC_SCRIPTrPrextendformatrrr rrrrrrm) rQr*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_jsonr9rrls rrmzUdhcpc.get_newest_leases"~~d11$//BCCrrnc|j}|r&t|ddd|dddDcgc]}|c}SgScc}w)NrrU)rrCrDs rrpzUdhcpc.parse_static_routessG  "=1#5}QTT7JKL!AL L Ms ;rr)rrrrOrRrur rrrr&rmrxr r rprrs@rrGrGsK-1 F0F0 )F0 c3h F0P D# D$sCx. DCDsCx,ArrGrrrM)4rvr[loggingr5rrrrr contextlibrior subprocessrtypingrrrr r r r/ cloudinitr r r cloudinit.netrr getLoggerrr#r4rrrP Exceptionrrrr r+r2r>rGABCrIrzrrGALL_DHCP_CLIENTSrrrrbs  %==,,<g!11 / B2y2 0B 0B/&6/O*K&HHVu&*u&p iZiX cZcLK0r