o x[hS@sddlZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z ddl mZmZmZddlmZeeZgdZgdZgd Zd d Zd d ZdddZddZe dddZddZGdddej Z dddZ!dS)N)suppress)Optional) performancesubputil) ParserErrorrenderersubnet_is_ipv6) NetworkState)zpre-upupzpost-updownzpre-downz post-down) bridge_ageingbridge_bridgeprio bridge_fd bridge_gcinit bridge_hello bridge_maxagebridge_maxwait bridge_stp)addressnetmask broadcastnetworkmetricgateway pointtopointmediamtuhostname leasehours leasetimevendorclientbootfileserverhwaddrproviderframenetnumendpointlocalttlcCsg}gd}|D]:\}}|dkrq |dkr!d|d|df}|rD||vrDt|tr1d|}d|vr;|dd}|d ||q t|S) N) rrrrr pointopointrscope dns_searchdns_nameserversrrz%s/%sprefix _- {0} {1})items isinstancelistjoinreplaceappendformatsorted)ifacesubnetcontent valid_mapkeyvaluerC3/usr/lib/python3/dist-packages/cloudinit/net/eni.py_iface_add_subnetAs     rEc Cs|dkrgSg}gd}gd}ddi}|ddvr|d|D][\}}t|tr4||r2dnd }|r:||vr;q#|d krP|rP||krOtd |d ||q#||vrg|D]} |d |||| qVq#t|trqd |}|d ||||q#t |S)Nr) control device_iddriverindexinetmodenamesubnetstype)bridge_pathcostbridge_portpriobridge_waitport mac_address hwaddressrN)bondbridge infinibandvlanonoffrzZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.rLr4r1) r:r5r6boolLOGwarningr;getr7r8r<) r=rIipv4_subnet_mtur? ignore_mapmultiline_keysrenamesrArBvrCrCrD_iface_add_attrs_s<       rcFcCs|d}|d}|dkrd}n |dvrd|}nd|}|}|||ddjd i|d jd i|g}|rJ|d rJ|d jd i||S) NrLrFauto)hotplugzallow-z # control-)fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}rRz hwaddress {mac_address}rC)copyupdater;r]r:)r=rIrender_hwaddressrfrFrgsubstlinesrCrCrD_iface_start_entrys rmc s<d}|D]}|}|drq|d}|d}|dkrd|d}|ds0tj||}t|D]-t} fdd | D} | D]} t | } tj | } t || tj | | qGq5q|d kr|d} | dsxtj|| } t| D].td }|} Wdn1swYtj }t || tj ||q}q|d kr|ddD]}||vrd |i||<d||d <qq|dkr|dd\}}}||vrd |i||<nd||vrtd||f|||d<|||d<|}q|dkr|ddkr|d}n|d}|||d<q|tvr+|d|||<q|tvrN|||vr=g|||<|||d|ddq|drd||vrai||d<|dkrg||dd<|ddD]}||dd|qtq|dkrg||dd<|ddD]}||dd|qq|drbd||vri||d<|tvr|ddd}|d||d|<q|d krg||dd!<|ddD]}||dd!|qq|d"kr|dd#kr |d||dd#<q|d||dd#<q|d$kr=d%||dvr.i||dd%<|d||dd%|d<q|d&krad'||dvrSi||dd'<|d||dd'|d<q|d(rd)||vrui||d)<|d(dd}|d||d)|<q|D]}d ||vrd*||d <qdS)+a~Parses the file contents, placing result into ifaces. '_source_path' is added to every dictionary entry to define which file the configuration information came from. :param ifaces: interface dictionary :param contents: contents of interfaces file :param src_dir: directory interfaces file was located :param src_path: file path the `contents` was read N#r1rzsource-directory/cs@g|]}tjtj|rtd|durtj|qS)z^[a-zA-Z0-9_-]+$N)ospathisfiler8rematch).0rr expanded_pathrCrD s z*_parse_deb_config_data..sourcerrd _source_pathTr=familyz:Interface %s can only be defined once. Re-defined in '%s'.methodrSetherzdns-dnsz dns-searchsearchzdns-nameservers nameserversbridge_rU bridge_portsports bridge_hwmacrOpathcostrPportpriozbond-rTF) splitlinesstrip startswithsplitrqrrr8globlistdirrload_text_fileabspath_parse_deb_config_datadirnameopenreadrNET_CONFIG_OPTIONSNET_CONFIG_COMMANDSr:NET_CONFIG_BRIDGE_OPTIONSr9lowerkeys)ifacescontentssrc_dirsrc_pathcurriflineroptionparsed_src_dir dir_contentsentrysrc_data abs_entry new_src_pathfpabs_pathr=r~rvaldomainr$ bridge_option bond_optionrCrwrDrs                   "               rzConverting eni datacCsi}t||dddt|S)z=Return a network config representation of what is in eni_dataN)rr)r_ifaces_to_net_config_data)eni_datarrCrCrDconvert_eni_data7srcs4i|D]\}}|dd}|vr2|dkrd}nd}||gd|<d|vr2|d|d<||d d }|d rCd |d <nd |d <|d dkrT|d|d<dD] }||vrb||||<qVd|vrdD]}||dvr|d|r|d||d|<qi|d|qdfddtDdS)zReturn network config that represents the ifaces data provided. ifaces = _parse_deb_config_data(...) config = ifaces_to_net_config_data(ifaces) state = parse_net_config_data(config).:rloloopbackphysical)rNrLrMrSrRr)_orig_eni_namerNrdrFmanualstaticr)rrrr)rrdns_rMrocsg|]}|qSrCrC)rvddevsrCrDryez._ifaces_to_net_config_data..)versionconfig)r5 partitionr]r:r<)rrLdatadevnamedtyper>copy_keynrCrrDr?s6    rc@sXeZdZdZdddZdddZdd d Zdd d Z  dd ede e ddfddZ dS)Rendererz@Renders network information in a /etc/network/interfaces format.NcCs6|si}|dd|_|dd|_|dd|_dS)Neni_pathetc/network/interfaces eni_header netrules_pathz(etc/udev/rules.d/70-persistent-net.rules)r]rrr)selfrrCrCrD__init__ks zRenderer.__init__rc CsHg}|d}|d}d}ddd}d}|dd kr"|d d kr"d }n|dd kr0|d dkr0d}d} dD][} |r=| dkr=q4| dkrO| d||| || f7} q4| |vr| dkrd|| vrb| d7} n|d dkrn| d7} n| d7} d |vr| d|| |d f7} q4| d|| || f7} q4||| |||| ||S)aWhen rendering routes for an iface, in some cases applying a route may result in the route command returning non-zero which produces some confusing output for users manually using ifup/ifdown[1]. To that end, we will optionally include an '|| true' postfix to each route line allowing users to work with ifup/ifdown without using --force option. We may at somepoint not want to emit this additional postfix, and add a 'strict' flag to this function. When called with strict=True, then we will not append the postfix. 1. http://askubuntu.com/questions/168033/ how-to-set-static-routes-in-ubuntu-server zpost-up route addzpre-down route delz || truegwr)rrrrz0.0.0.0rz defaultz::r0rz -A inet6 default)rrrrz%s %s %srz -A inet6 z -hostz -netz %s/%sz %s %s)r]r:) rrouteindentr?r r or_truemapping default_gw route_linekrCrCrD _render_routetsB    zRenderer._render_routeFc s`ttt dWdn1swYg}di}dd}dd}|r8dd<|rt|D]\}}d} |d<|dd <|d d d <d } t|ra| d 7} n|d} | d <|ddks||ddks||ddkrdd <|dur|rdndd<n2|ddkrd d <dd<n#|ddkrd d <dd<nt|rdd <|dur|rdndd<dfdd|Dvrdd <tt ||dt |t || } |dgD] } | |j | dd q|| q>|Sg} d!vs d"vr| d#jd'i| d$jd'i| t d%dd&|| |S)(N config_idrMz accept-ra wakeonlangz ethernet-wolrIrNrKrFrdrJ6rdhcp4dhcp6zipv6_dhcpv6-statefuldhcp10 accept_razipv6_dhcpv6-stateless ipv6_slaacrTcsg|] }dd|vqS)zauto %srLrC)rvrr=rCrDrysz*Renderer._render_iface..aliasrjroutesz )rz bond-masterz bond-slavesz auto {name}ziface {name} {inet} {mode}r)rIr^rC)rhdeepcopyrKeyErrorpopr] enumerater r7rmrErcextendrr:r;) rr=rjsectionsrMr ethernet_wolrIr>r^ subnet_inetrlrrCrrD _render_ifaces                      zRenderer._render_ifacec sddddddgd}|D]}|ddkrt|}q|j}|r.d ||d d d <|j}|r>d ||d d d <d ddddddg}|||t |fdddD]}|ddkrgq]||j||dq]| D] }| | |qvddd|DdS)z1Given state, emit etc/network/interfaces content.rrrJrrd)rNrF)rLrNrJrMrLr1rMrr/r.rorr})rrrVrTrUrWcs|d|dfS)NrNrLrC)rorderrCrD rz-Renderer._render_interfaces..)rArz cSsg|]}d|qS) )r8)rvsrCrCrDry,sz/Renderer._render_interfaces..r) iter_interfacesr]rhrr/r8dns_searchdomainsrrr< iter_routesr:r) r network_staterjrr=r searchdomainsrrrCrrD_render_interfacessH        zRenderer._render_interfacesr templatesreturncCst||j}ttj||jr|jnd}t ||| ||j rCt||j }ttj|tj || |dddSdS)NrT)r? preserve_mode) r target_pathrr ensure_dirrqrrrr write_filerr_render_persistent_net)rrrtargetfpeniheadernetrulesrCrCrDrender_network_state.s zRenderer.render_network_stateN)rF)NN) __name__ __module__ __qualname____doc__rrrrr rdictr rCrCrCrDrhs  4 R7rcCsPgd}ddg}|D] }tj|||dsdSq t|d}tj|s&dSdS)N)ifqueryifupifdownz/sbinz /usr/sbin)rrFrT)rwhichrrqrrrs)rexpectedrpenirCrCrD availableCs  rr r )"rhrloggingrqrt contextlibrtypingr cloudinitrrr cloudinit.netrrr cloudinit.net.network_stater getLoggerr r[rrrrErcrmrtimedrrrrrCrCrCrDs2       < )\