3 \me@sUddlZddlZddlZddlmZmZmZmZddlm Z m Z ddl m Z m Z mZmZmZmZmZmZmZer~ddlmZejeZdZdddd giZd d d d dddddddddddgZdddddddd d!d"d#d$d%d&d'd(d)d*d+dd,d-dd.d/d0dd1 d2Zeeeeeffedd3d4d5Z d6d7Z!Gd8d9d9e"Z#d:d;Z$Gdd?d?Z&d@dAZ'ffdBdCZ(dDdEZ)dFdGZ*dLee+e%dIdJdKZ,dS)MN) TYPE_CHECKINGAnyDictOptional)safeyamlutil) find_interface_name_from_macget_interfaces_by_macipv4_mask_to_net_prefixipv6_mask_to_net_prefix is_ip_networkis_ipv4_networkis_ipv6_addressis_ipv6_networknet_prefix_to_ipv4_mask)Rendererversionconfig network_state addressesdhcp4zdhcp4-overridesdhcp6zdhcp6-overridesgateway4gateway6 interfacesmatchmtu nameserversrendererzset-name wakeonlanz accept-raz ad-selectz arp-intervalz arp-ip-targetz arp-validatez down-delayzfail-over-mac-policyz lacp-ratezmii-monitor-intervalz min-linksmodezgratuitous-arpZprimaryzprimary-reselect-policyzup-delayztransmit-hash-policy)zbond-ad-selectzbond-arp-intervalzbond-arp-ip-targetzbond-arp-validatezbond-downdelayzbond-fail-over-maczbond-lacp-ratez bond-miimonzbond-min-linksz bond-modezbond-num-grat-arpz bond-primaryzbond-primary-reselectz bond-updelayzbond-xmit-hash-policyz ageing-timeZpriorityz forward-delayz hello-timezmax-agez path-costz port-prioritystp) Z bridge_ageingZbridge_bridgeprioZ bridge_fdZ bridge_gcintZ bridge_helloZ bridge_maxageZbridge_maxwaitZbridge_pathcostZbridge_portprio bridge_stpZbridge_waitport)bondbridge)diktreturncCs$d|ksd|kr tjdddddS)z8Warn about deprecations of v2 properties for all devicesrrz$The use of `gateway4` and `gateway6`z22.4zhFor more info check out: https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html)Z deprecatedZdeprecated_versionZ extra_messageN)rZ deprecate)r&r(#/usr/lib/python3.6/network_state.pywarn_deprecated_all_devicesVs r*cCs$t|}x|D]}|j|qW|S)N)setdiscard)ZexpectedactualZmissingkeyr(r(r) diff_keysas r/c@s eZdZdS)InvalidCommandN)__name__ __module__ __qualname__r(r(r(r)r0hsr0csfdd}|S)Ncstjfdd}|S)Ncs4r"t|}|r"td|f||f||S)Nz&Command missing %s of required keys %s)r/r0)selfcommandargskwargs missing_keys)func required_keysr(r) decoratorns  z7ensure_command_keys..wrapper..decorator) functoolswraps)r9r;)r:)r9r)wrapperms z$ensure_command_keys..wrapperr()r:r>r()r:r)ensure_command_keysls r?c@seZdZefeedddZeedddZeddZ ed d Z ed d Z ed dZ dddZ dddZddZddZeeddddZdS) NetworkState)rrcCs*tj||_||_|jdd|_d|_dS)Nuse_ipv6F)copydeepcopy_network_state_versiongetrA_has_default_route)r4rrr(r(r)__init__s zNetworkState.__init__)r'cCs |jdS)Nr)rD)r4r(r(r)rszNetworkState.configcCs|jS)N)rE)r4r(r(r)rszNetworkState.versionc Cs(y|jddStk r"gSXdS)Ndnsr)rDKeyError)r4r(r(r)dns_nameserversszNetworkState.dns_nameserversc Cs(y|jddStk r"gSXdS)NrIsearch)rDrJ)r4r(r(r)dns_searchdomainsszNetworkState.dns_searchdomainscCs|jdkr|j|_|jS)N)rG_maybe_has_default_route)r4r(r(r)has_default_routes  zNetworkState.has_default_routeNccsB|jjdi}x.|jD]"}|dkr,|Vq||r|VqWdS)Nr)rDrFvalues)r4 filter_funcZifacesifacer(r(r)iter_interfacess zNetworkState.iter_interfacesccs:x4|jjdgD]"}|dk r,||r2|Vq|VqWdS)Nroutes)rDrF)r4rQrouter(r(r) iter_routess zNetworkState.iter_routescCspx|jD]}|j|r dSq WxJ|jD]>}x8|jdgD](}x"|jdgD]}|j|rNdSqNWqd?Zd@dAZ dBdCZ!dd dDdEZ"dMdFdGZ#dHdIZ$dS)NNetworkStateInterpreter)rrLFN)rrTrIrArzOptional[Renderer])rcCsv||_||_tj|j|_||jd<d|_i|_||_|j |j |j |j |j |j|j|j|j|j|j|j|jd |_dS)NrF) r$Zbondsr%ZbridgesZ ethernetsZ infinibandZloopback nameserverphysicalrUvlanZvlansZwifis)rE_configrBrCinitial_network_staterD_parsed_interface_dns_map _renderer handle_bond handle_bonds handle_bridgehandle_bridgeshandle_ethernetshandle_infinibandhandle_loopbackhandle_nameserverhandle_physical handle_route handle_vlan handle_vlans handle_wifiscommand_handlers)r4rrrr(r(r)rHs( z NetworkStateInterpreter.__init__)r'cCsHddlm}|jdkr8t|j|r8tjdtj|j St|j |jdS)Nr)rzPassthrough netplan v2 config)r) cloudinit.net.netplanrrE isinstancermLOGdebugr@r_rirD)r4NetplanRendererr(r(r)rs    z%NetworkStateInterpreter.network_statecCs |jjdS)NrA)rDrF)r4r(r(r)rAsz NetworkStateInterpreter.use_ipv6cCs|jjd|idS)NrA)rDupdate)r4valr(r(r)rA scCs|j|j|jd}tj|S)N)rrr)rErirDrdumps)r4stater(r(r)dumps zNetworkStateInterpreter.dumpcCszd|krtjdtdt|d}t||}|rNd|}tj|t|x&dd|DD]}t||||q^WdS)Nrz$Invalid state, missing version fieldzInvalid state, missing keys: %scSsg|]}|dkr|qS)r)rr().0kr(r(r) #sz0NetworkStateInterpreter.load..)rerror ValueErrorNETWORK_STATE_REQUIRED_KEYSr/setattr)r4rr:r8msgr.r(r(r)loads    zNetworkStateInterpreter.loadcCs tj|jS)N)rrrD)r4r(r(r)dump_network_state&sz*NetworkStateInterpreter.dump_network_statecCs|j|jdS)N)rr)rEri)r4r(r(r)as_dict)szNetworkStateInterpreter.as_dictTcCs>|jdkr|j|dd|_n|jdkr:|j|dd|_dS)Nr) skip_brokenTr|)rEparse_config_v1rkparse_config_v2)r4rr(r(r) parse_config,s     z$NetworkStateInterpreter.parse_configc Cs x|jD]}|d}y|j|}Wn0tk rR}ztd||WYdd}~XnXy ||Wqtk r|sxntjd|ddtj|jYqXqWxz|j j D]l\}}d}y|j d|}Wn2tk r}zt dj ||WYdd}~XnX|r|\} } | | d|d <qWdS) Ntypez"No handler found for command '%s'zSkipping invalid command: %sT)exc_inforzINameserver specified for interface {0}, but interface {0} does not exist!)rrLrI)rir{rJ RuntimeErrorr0rwarningrrrlitemsrDrformat) r4rr5 command_typehandlere interfacerIrRrrLr(r(r)r4s:   z'NetworkStateInterpreter.parse_config_v1cCsddlm}t|j|rdSx|jjD]\}}|d kr:q(y|j|}Wn0tk rx}ztd||WYdd}~XnXy|||j |Wq(t k r|snt j d|ddt j |jYq(Xq(WdS) Nr)rrrz!No handler found for command '%s'zSkipping invalid command: %sT)r)rr)r}rr~rmrirr{rJr _v2_commonr0rrrr)r4rrrr5rrr(r(r)rWs*   z'NetworkStateInterpreter.parse_config_v2namecCs |j|S)N)rv)r4r5r(r(r)rtssz'NetworkStateInterpreter.handle_loopbackc Cs.|jjdi}|j|di}x*|jdijD]\}}|j||iq0Wt|jd}|jsx2|D]*}|jdjdst|jdrdd|_PqdW|jd d }|d k rtj |}|jd d } | d k rtj | } |j|jd|jd|jd d d|jdd d ||| d |jdj|jd|i|j d S)z command = { 'type': 'physical', 'mac_address': 'c0:d6:9f:2c:e8:80', 'name': 'eth0', 'subnets': [ {'type': 'dhcp4'} ], 'accept-ra': 'true' } rrparamsrWr6addressTz accept-raNr mac_addressinetZmanualr) rrrrr!rrgatewayrWz accept-rar ) rDrFrr_normalize_subnetsrAendswithrrZis_truer) r4r5rrRparamrrWrYZ accept_rar r(r(r)rvws>       z'NetworkStateInterpreter.handle_physicalvlan_id vlan_linkcCs\|jjdi}|j||j|jdi}|jd|d<|jd|d<|j|d|idS)z auto eth0.222 iface eth0.222 inet static address 10.10.10.1 netmask 255.255.255.0 hwaddress ether BC:76:4E:06:96:B3 vlan-raw-device eth0 rrrzvlan-raw-devicerN)rDrFrvr)r4r5rrRr(r(r)rxs  z#NetworkStateInterpreter.handle_vlanbond_interfacesrc Cs|j||jjd}|j|jdi}x(|jdjD]\}}|j||iq8W|jddi|jdj|d|ix|jdD]}||kr|dd}|j||jjdi}|j|}|jd|d <x(|jdjD]\}}|j||iqW|jdj||iqWd S) aU #/etc/network/interfaces auto eth0 iface eth0 inet manual bond-master bond0 bond-mode 802.3ad auto eth1 iface eth1 inet manual bond-master bond0 bond-mode 802.3ad auto bond0 iface bond0 inet static address 192.168.0.10 gateway 192.168.0.1 netmask 255.255.255.0 bond-slaves none bond-mode 802.3ad bond-miimon 100 bond-downdelay 200 bond-updelay 200 bond-lacp-rate 4 rrrz bond-slavesZnonerr$)rrz bond-masterN)rvrDrFrr) r4r5rrRrrifnamecmdZbond_ifr(r(r)rns$    z#NetworkStateInterpreter.handle_bondbridge_interfacesc Cs|jjdi}x.|jdD] }||kr(qd|i}|j|qW|jjdi}|j||j|jdi}|d|d<x*|jdijD]\}}|j||iqW|jd}|dk ot|t r|dkrd }n|dkrd}ntdj|d|jd|i|j|d|idS)a auto br0 iface br0 inet static address 10.10.10.1 netmask 255.255.255.0 bridge_ports eth0 eth1 bridge_stp off bridge_fd 0 bridge_maxwait 0 bridge_params = [ "bridge_ports", "bridge_ageing", "bridge_bridgeprio", "bridge_fd", "bridge_gcint", "bridge_hello", "bridge_hw", "bridge_maxage", "bridge_maxwait", "bridge_pathcost", "bridge_portprio", "bridge_stp", "bridge_waitport", ] rrrZ bridge_portsrr#Non1rToff0rFz2Cannot convert bridge_stp value ({stp}) to boolean)r")rrr)rrr) rDrFrvrrr~boolrr) r4r5rrrrRrrr#r(r(r)rps.    z%NetworkStateInterpreter.handle_bridgecCs|j|dS)N)rv)r4r5r(r(r)rs5sz)NetworkStateInterpreter.handle_infinibandcCsg}g}d|kr@|d}t|ts(|g}x|D]}|j|q.Wd|krx|d}t|ts`|g}x|D]}|j|qfW||fS)NrrL)r~listappend)r4r5rrLZaddrsaddrpathspathr(r(r) _parse_dns9s    z"NetworkStateInterpreter._parse_dnsrcCsV|jjd}|j|\}}d|kr6||f|j|d<n|dj||dj|dS)NrIrrrL)rDrFrrlextend)r4r5rIrrLr(r(r)ruJs z)NetworkStateInterpreter.handle_nameservercCs0|jjd}|j|\}}||d||d<dS)Nr)rrLrI)rDrFr)r4r5rRZ_ifacerrLr(r(r)_handle_individual_nameserverWs z5NetworkStateInterpreter._handle_individual_nameserver destinationcCs|jdjt|dS)NrT)rDr_normalize_route)r4r5r(r(r)rw]sz$NetworkStateInterpreter.handle_routecCs|j|dddS)a v2_command = { bond0: { 'interfaces': ['interface0', 'interface1'], 'parameters': { 'mii-monitor-interval': 100, 'mode': '802.3ad', 'xmit_hash_policy': 'layer3+4'}}, bond1: { 'bond-slaves': ['interface2', 'interface7'], 'parameters': { 'mode': 1, } } } v1_command = { 'type': 'bond' 'name': 'bond0', 'bond_interfaces': [interface0, interface1], 'params': { 'bond-mode': '802.3ad', 'bond_miimon: 100, 'bond_xmit_hash_policy': 'layer3+4', } } r$)cmd_typeN)_handle_bond_bridge)r4r5r(r(r)robsz$NetworkStateInterpreter.handle_bondscCs|j|dddS)a v2_command = { br0: { 'interfaces': ['interface0', 'interface1'], 'forward-delay': 0, 'stp': False, 'maxwait': 0, } } v1_command = { 'type': 'bridge' 'name': 'br0', 'bridge_interfaces': [interface0, interface1], 'params': { 'bridge_stp': 'off', 'bridge_fd: 0, 'bridge_maxwait': 0 } } r%)rN)r)r4r5r(r(r)rqsz&NetworkStateInterpreter.handle_bridgescCs$t}x|jD]\}}ddi}|jdi}|jdd}|sRtjd|t|||d<|}|jd} | rr| }n |r|r|j} t| } | r| }||d <|jd d} | rd | i|d <x dD]} | |kr|| || <qWt||j |}t |dkr|j d|itjd||j |qWdS)a ethernets: eno1: match: macaddress: 00:11:22:33:44:55 driver: hv_netvsc wakeonlan: true dhcp4: true dhcp6: false addresses: - 192.168.14.2/24 - 2001:1::1/64 gateway4: 192.168.14.1 gateway6: 2001:1::2 nameservers: search: [foo.local, bar.local] addresses: [8.8.8.8, 8.8.4.4] lom: match: driver: ixgbe set-name: lom1 dhcp6: true accept-ra: true switchports: match: name: enp2* mtu: 1280 command = { 'type': 'physical', 'mac_address': 'c0:d6:9f:2c:e8:80', 'name': 'eth0', 'subnets': [ {'type': 'dhcp4'} ] } rrgr macaddressNzHNetworkState Version2: missing "macaddress" info in config entry: %s: %srzset-namerdriverrrr accept-rarrWz!v2(ethernets) -> v1(physical): %s)rrr r) r rrFrrstrlowerrr*_v2_to_v1_ipcfglenrrv)r4r5Z ifaces_by_macZethcfgZphy_cmdrrrZset_nameZlcase_mac_addressZmacrr.rWr(r(r)rrsB-         z(NetworkStateInterpreter.handle_ethernetscCsx|jD]x\}}d||jd|jdd}d|kr@|d|d<t||j|}t|dkrl|jd|itjd||j|q Wd S) aq v2_vlans = { 'eth0.123': { 'id': 123, 'link': 'eth0', 'dhcp4': True, } } v1_command = { 'type': 'vlan', 'name': 'eth0.123', 'vlan_link': 'eth0', 'vlan_id': 123, 'subnets': [{'type': 'dhcp4'}], } rhidlink)rrrrrrrWzv2(vlans) -> v1(vlan): %sN) rrFr*rrrrrrx)r4r5rhrZvlan_cmdrWr(r(r)rys    z$NetworkStateInterpreter.handle_vlanscCstjddS)NzOWifi configuration is only available to distros with netplan rendering support.)rr)r4r5r(r(r)rzsz$NetworkStateInterpreter.handle_wifisc Cstjd|x|jD]\}}d|kr8|jd}|r8|}d|kr|jdjdg}|jdjdg}ddi}t|dkr|jd|it|dkr|jd |i|j||jd ijd }|rt|} | r| }|j||qWdS) Nzv2_common: handling config: %szset-namerrLrrrfrrrr) rrrrFrrrurr) r4rrRZdev_cfgZset_name_ifacerLrIZname_cmdrZ real_if_namer(r(r)r s,      z"NetworkStateInterpreter._v2_commonc s4tddtj|jDx|jD]\}}tdd|jD}|jdi}|jdd}|rl||d<d|d ||d |jd d tfd d|jDi}d|kr|d|d<t||j|} t| dkr|jd| it j d||||dkr|j |q(|dkr|j |q(t dj|dq(WdS)z(Common handler for bond and bridge typescss|]\}}||fVqdS)Nr()rrvr(r(r) @sz>NetworkStateInterpreter._handle_bond_bridge..css"|]\}}|tkr||fVqdS)N)NETWORK_V2_KEY_FILTER)rr.valuer(r(r)rEsZ parameterszgratuitious-arpNzgratuitous-arprrZ _interfacesrrc3s|]\}}||fVqdS)Nr()rrr) v2key_to_v1r(r)rTsrrrWzv2(%s) -> v1(%s): %sr%r$z Unknown command type: {cmd_type})r)raNET_CONFIG_TO_V2rFrpopr*rrrrrrprnrr) r4r5rZ item_nameZitem_cfgZ item_paramsrZ grat_valueZv1_cmdrWr()rr)r;s8         z+NetworkStateInterpreter._handle_bond_bridgec Csdd}g}|jdr:ddi}||jdi||j||jdrnddi}d|_||jdi||j|d }d }i}x|jd gD]}d |d }d |krd|kr|d kr|jd}|jd|in(d|kr|d kr|jd}|jd|id|ko| rF|jdjd } | r| |d<|jdjd} | r<| |d<|j||j|qWg} x>|jdgD].} | jt| jd| jd| jddqfWt|rt| r| |dd<|S)z7Common ipconfig extraction from v2 to v1 subnets array.cSsd|kr|d|d<dS)Nz route-metricmetricr()Z overridesrYr(r(r)_add_dhcp_overridesmszDNetworkStateInterpreter._v2_to_v1_ipcfg.._add_dhcp_overridesrrzdhcp4-overridesrTzdhcp6-overridesNrstatic)rr:rrrrrKrL dns_searchrTZtoZviar)rrrr)rFrrArrr) r4rrrWrYrrrrrrLrTrUr(r(r)rjsV        z'NetworkStateInterpreter._v2_to_v1_ipcfg)T)T)T)N)%r1r2r3rjr`rHrcr@rrAsetterrrrrrrrr?rtrvrxrnrprsrrurrwrorqrrryrzrrrr(r(r(r)resL   # 75A ^" /recCs~tj|}tdd|jD}|jddkr@|jt|ddd d |jd gD|d <d d }xdD]}|||qhW|S)Ncss|]\}}|r||fVqdS)Nr()rrrr(r(r)rsz$_normalize_subnet..rrstatic6r ip_address) address_keyscSsg|] }t|qSr()r)rrr(r(r)rsz%_normalize_subnet..rTcSs,||kr(t||t r(||j||<dS)N)r~rsplit)Zsnetrr(r(r)listifysz"_normalize_subnet..listifyrrK)rr)rr)rrK)rBrCrarrFr_normalize_net_keys)rYZ normal_subnetrrr(r(r)_normalize_subnets   rcCsdd|jD}d}x|D]}|j|r|}PqW|s\ddj||f}tj|t|t|j|}t|stjd|td|dt|}t |}|jd } d |kr|j d \} } } | ||<|rt | } n*|rt | } ntjd|td|dnRd |krt |d } n:| r2|r2t | } n$| rH|rHt | } n|rRd nd } d |krt|d t| krtjd| || |d <|rd |kr|d =n|rt|d |d <|S)aNormalize dictionary network keys returning prefix and address keys. @param network: A dict of network-related definition containing prefix, netmask and address_keys. @param address_keys: A tuple of keys to search for representing the address or cidr. The first address_key discovered will be used for normalization. @returns: A dict containing normalized prefix and matching addr_key. cSs"i|]\}}|s|dkr||qS)rr()rrrr(r(r) sz'_normalize_net_keys..Nz/No config network address keys [%s] found in %s,z$Address %s is not a valid ip networkzAddress z is not a valid ip addressnetmask/r\@z;Overwriting existing 'prefix' with '%s' in network info: %s)rrFjoinrrrrr rr partitionr r rbrr)r]rZnetZaddr_keyr.messagerZipv6Zipv4rZ addr_part_Z maybe_prefixr\r(r(r)rs^                 rcCstdd|jD}d|kr0|d|d<|d=|jt|d d|jd}|ryt||d<Wn2tk r}ztdj||WYdd}~XnX|S) anormalize a route. return a dictionary with only: 'type': 'route' (only present if it was present in input) 'network': the network portion of the route as a string. 'prefix': the network prefix for address as an integer. 'metric': integer metric (only if present in input). 'netmask': netmask (string) equivalent to prefix iff network is ipv4. css"|]\}}|dkr||fVqdS)N)rNr()rrrr(r(r)r!sz#_normalize_route..rr])rrz(Route config metric {} is not an integerN)r]r) rarrrrFrbr TypeErrorr)rUZ normal_routerrr(r(r)rs"     rcCs|sg}dd|DS)NcSsg|] }t|qSr()r)rsr(r(r)r;sz&_normalize_subnets..r()rWr(r(r)r8srT) net_configrr'cCsfd}|jd}|jd}|dkr$|}|rP|dk rPt|||d}|j|d|j}|sbtd||S)zfParses the config, returns NetworkState object :param net_config: curtin network config dict Nrrr|)rrr)rzpNo valid network_state object created from network config. Did you specify the correct version? Network config: )rFrerrr)rrrrrrZnsir(r(r)parse_net_config_data>s       r)TN)-rBr<ZloggingZtypingrrrrZ cloudinitrrZ cloudinit.netrr r r r r rrrZcloudinit.net.rendererrZ getLoggerr1rr`rrrrrar*r/ Exceptionr0r?r@rerrrrrrr(r(r(r)s,     V^ L"