3 \meS9@sdZddlZddlZddlmZddlmZmZmZm Z m Z ddl j Z ddl mZmZmZddlmZejeZGdddZGd d d ZGd d d ZGd ddZdS)z.Module for ephemeral network context managers N)partial)AnyCallableDictListOptional) IscDhclientNoDHCPLeaseErrormaybe_perform_dhcp_discovery)ProcessExecutionErrorc@sTeZdZdZdeeeefdddZddZ dd Z d d Z d d Z ddZ dS)EphemeralIPv4NetworkaContext manager which sets up temporary static network configuration. No operations are performed if the provided interface already has the specified configuration. This can be verified with the connectivity_url_data. If unconnected, bring up the interface with valid ip, prefix and broadcast. If router is provided setup a default route for that interface. Upon context exit, clean up the interface leaving no configuration behind. N)connectivity_url_datac Cst||||gs$tdj||||ytj||_Wn2tk rf} ztdj| | WYdd} ~ XnX||_||_||_||_ ||_ ||_ g|_ ||_ dS)aXSetup context manager and validate call signature. @param interface: Name of the network interface to bring up. @param ip: IP address to assign to the interface. @param prefix_or_mask: Either netmask of the format X.X.X.X or an int prefix. @param broadcast: Broadcast address for the IPv4 network. @param router: Optionally the default gateway IP. @param connectivity_url_data: Optionally, a URL to verify if a usable connection already exists. @param static_routes: Optionally a list of static routes from DHCP z5Cannot init network on {0} with {1}/{2} and bcast {3}z4Cannot setup network, invalid prefix or netmask: {0}N)all ValueErrorformatnetZipv4_mask_to_net_prefixprefixr interfaceip broadcastrouter static_routes cleanup_cmdsdistro) selfrrrprefix_or_maskrrr rer/usr/lib/python3.6/ephemeral.py__init__ s&zEphemeralIPv4Network.__init__c Cs||jr(tj|jr(tjd|jddSy*|j|jrB|jn|jrP|j Wn$t k rv|j dddYnXdS)z>Perform ephemeral network setup if interface is not connected.z=Skip ephemeral network setup, instance has connectivity to %sZurlN) r rhas_url_connectivityLOGdebug_bringup_devicer_bringup_static_routesr_bringup_routerr __exit__)rrrr __enter__Os    zEphemeralIPv4Network.__enter__cCsx|jD] }|qWdS)zTeardown anything we set up.N)r)r excp_type excp_valueexcp_tracebackcmdrrrr&qs zEphemeralIPv4Network.__exit__cCsdj|j|j}tjd|j||jy|jjj |j||jWnDt k r}z(dt |j kr`tjd|j|jWYdd}~XnPX|jjj |jdd|jjt|jjj|jdd|jjt|jjj|j|dS)z1Perform the ip comands to fully setup the device.z{0}/{1}z:Attempting setup of ephemeral network on %s with %s brd %sz File existsz7Skip ephemeral network setup, %s already has address %sNZinet)Zfamily)rrrr!r"rrrnet_opsZadd_addrr strstderrlink_uprappendrZ link_downZdel_addr)rZcidrrrrrr#vs. z$EphemeralIPv4Network._bringup_devicec CsNxH|jD]>\}}|jjj|j|||jjdt|jjj|j||dqWdS)Nr)gateway) rrr,Z append_routerrinsertr del_route)rZ net_addressr1rrrr$s z+EphemeralIPv4Network._bringup_static_routescCs|jjj}d|kr,tjd|j|jdS|jjj|j|j|j d|j j dt |jjj |j|j|j d|jjj|jd|jd|j j dt |jjj |jddS)zr rArrrrs zEphemeralDHCPv4.__init__cCs,|jr$tj|jr$tjd|jdS|jS)zUSetup sandboxed dhcp context, unless connectivity_url can already be reached.z:Skip ephemeral DHCP setup, instance has connectivity to %sN)r rr r!r" obtain_lease)rrrrr's zEphemeralDHCPv4.__enter__cCs |jdS)z Teardown sandboxed dhcp context.N) clean_network)rr(r)r*rrrr& szEphemeralDHCPv4.__exit__cCs d|_|jr|jjddddS)z@Exit _ephipv4 context to teardown of ip configuration performed.N)r@r?r&)rrrrrCszEphemeralDHCPv4.clean_networkcCs|jr |jSt|j|j|j}|s(t|d|_tjd|jd|jd|jdddddddgd d }|j|}|d st j |d |d |d <|drt j |d|d<|j r|j |d<t|jf|}|j||_|jS)a9Perform dhcp discovery in a sandboxed environment if possible. @return: A dict representing dhcp options on the most recent lease obtained from the dhclient discovery if run, otherwise an error is raised. @raises: NoDHCPLeaseError if no leases could be obtained. z#Received dhcp lease on %s for %s/%srz fixed-addressz subnet-maskzbroadcast-addresszrfc3442-classless-static-routeszclassless-static-routesZrouters)rrrrrrrrrrr )r@r rr>rAr r!r"extract_dhcp_options_mappingrZmask_and_ipv4_to_bcast_addrrZparse_static_routesr r r'r?)rZleasesnmapkwargsZephipv4rrrrBs@     zEphemeralDHCPv4.obtain_leasecCsHi}x>|jD]2\}}t|tr0|j|||q|jj|||<qW|S)N)items isinstancelistget_first_option_valuer@get)rrGresultZinternal_referencelease_option_namesrrrrFGs  z,EphemeralDHCPv4.extract_dhcp_options_mappingcCs,x&|D]}|j|s|jj|||<qWdS)N)rMr@)rZinternal_mappingrOrNZdifferent_namesrrrrLRs  z&EphemeralDHCPv4.get_first_option_value)NNN)r7r8r9rrr-rrr'r&rCrBrFrLrrrrr=s  2 r=c@s2eZdZdZd eedddZddZd d Zd S) EphemeralIPNetworkahCombined ephemeral context manager for IPv4 and IPv6 Either ipv4 or ipv6 ephemeral network may fail to initialize, but if either succeeds, then this context manager will not raise exception. This allows either ipv4 or ipv6 ephemeral network to succeed, but requires that error handling for networks unavailable be done within the context. FT)ipv6ipv4cCs,||_||_||_tj|_d|_||_dS)N)rrRrQ contextlib ExitStackstack state_msgr)rrrrQrRrrrrcs  zEphemeralIPNetwork.__init__cCs|jp |js|Sg}d}|jrzy|jjt|j|jd}Wn<ttfk rx}zt j d||j |WYdd}~XnX|jry0|jjt |j|jd}|s|j rd|_ Wn8tk r}zt j d||j |WYdd}~XnX|st jd|d|S)NFTzFailed to bring up %s for ipv4.zusing link-local ipv6zFailed to bring up %s for ipv6.zGFailed to bring up EphemeralIPNetwork. Datasource setup cannot continuer)rRrQrV enter_contextr=rrr r r!infor0r;rWerror)r exceptionsZephemeral_obtainedrrrrr'qs>       zEphemeralIPNetwork.__enter__cGs|jjdS)N)rVclose)rr<rrrr&szEphemeralIPNetwork.__exit__N)FT)r7r8r9r:boolrr'r&rrrrrPZs  ,rP)r:rTZlogging functoolsrZtypingrrrrrZ cloudinit.netrZcloudinit.net.dhcprr r Zcloudinit.subpr Z getLoggerr7r!r r;r=rPrrrrs    ; k