o
    x[hbŽ  ã                   @   sŽ  U d dl Z d dlZd dlZd dlmZmZmZmZ d dlm	Z	m
Z
mZ d dlmZmZmZmZmZmZmZmZmZ erAd dlmZ e e¡ZdZdg d¢iZg d¢Zd	d
ddddddddddddddœdddddddddd dd!œd"œZeeeeef f e d#< d$e!d%dfd&d'„Z"d(d)„ Z#G d*d+„ d+e$ƒZ%d,d-„ Z&G d.d/„ d/ƒZ'G d0d1„ d1ƒZ(d2d3„ Z)d@d5d6„Z*d7d8„ Z+d9d:„ Z,	;	dAd<e!d=e-d%e'fd>d?„Z.dS )Bé    N)ÚTYPE_CHECKINGÚAnyÚDictÚOptional)Ú	lifecycleÚsafeyamlÚutil)	Úfind_interface_name_from_macÚget_interfaces_by_macÚipv4_mask_to_net_prefixÚipv6_mask_to_net_prefixÚis_ip_networkÚis_ipv4_networkÚis_ipv6_addressÚis_ipv6_networkÚnet_prefix_to_ipv4_mask©ÚRendereré   ©ÚversionÚconfigÚnetwork_state)Ú	addressesÚdhcp4údhcp4-overridesÚdhcp6údhcp6-overridesÚgateway4Úgateway6Ú
interfacesÚmatchÚmtuÚnameserversÚrendererúset-nameÚ	wakeonlanú	accept-raÚoptionalz	ad-selectzarp-intervalzarp-ip-targetzarp-validatez
down-delayzfail-over-mac-policyz	lacp-ratezmii-monitor-intervalz	min-linksÚmodeúgratuitous-arpÚprimaryzprimary-reselect-policyzup-delayztransmit-hash-policy)zbond-ad-selectzbond-arp-intervalzbond-arp-ip-targetzbond-arp-validatezbond-downdelayzbond-fail-over-maczbond-lacp-ratezbond-miimonzbond-min-linksz	bond-modezbond-num-grat-arpzbond-primaryzbond-primary-reselectzbond-updelayzbond-xmit-hash-policyzageing-timeÚpriorityzforward-delayz
hello-timezmax-agez	path-costzport-priorityÚstp)Úbridge_ageingÚbridge_bridgeprioÚ	bridge_fdÚbridge_gcintÚbridge_helloÚbridge_maxageÚbridge_maxwaitÚbridge_pathcostÚbridge_portprioÚ
bridge_stpÚbridge_waitport)ÚbondÚbridgeÚNET_CONFIG_TO_V2ÚdiktÚreturnc                 C   s(   d| v sd| v rt jdddd� dS dS )z8Warn about deprecations of v2 properties for all devicesr   r   z$The use of `gateway4` and `gateway6`z22.4zbFor more info check out: https://docs.cloud-init.io/en/latest/topics/network-config-format-v2.html)Ú
deprecatedÚdeprecated_versionÚextra_messageN)r   Ú	deprecate)r<   © rB   ú=/usr/lib/python3/dist-packages/cloudinit/net/network_state.pyÚwarn_deprecated_all_devicesW   s   
ýÿrD   c                 C   s    t | ƒ}|D ]}| |¡ q|S ©N)ÚsetÚdiscard)ÚexpectedÚactualÚmissingÚkeyrB   rB   rC   Ú	diff_keysb   s   rL   c                   @   s   e Zd ZdS )ÚInvalidCommandN)Ú__name__Ú
__module__Ú__qualname__rB   rB   rB   rC   rM   i   s    rM   c                    s   ‡ fdd„}|S )Nc                    s   t  ˆ ¡‡ ‡fdd„ƒ}|S )Nc                    s:   ˆrt ˆ|ƒ}|rtd|ˆf ƒ‚ˆ | |g|¢R i |¤ŽS )Nz&Command missing %s of required keys %s)rL   rM   )ÚselfÚcommandÚargsÚkwargsÚmissing_keys)ÚfuncÚrequired_keysrB   rC   Ú	decoratoro   s   
ÿÿz7ensure_command_keys.<locals>.wrapper.<locals>.decorator)Ú	functoolsÚwraps)rV   rX   ©rW   )rV   rC   Úwrappern   s   
z$ensure_command_keys.<locals>.wrapperrB   )rW   r\   rB   r[   rC   Úensure_command_keysm   s   r]   c                   @   sž   e Zd Zefdedefdd„Zedefdd„ƒZedd	„ ƒZ	ed
d„ ƒZ
edd„ ƒZedd„ ƒZddd„Zddd„Zdd„ Zdd„ Zededd fdd„ƒZdS )ÚNetworkStater   r   c                 C   s*   t  |¡| _|| _| dd¡| _d | _d S )NÚuse_ipv6F)ÚcopyÚdeepcopyÚ_network_stateÚ_versionÚgetr_   Ú_has_default_route)rQ   r   r   rB   rB   rC   Ú__init__€   s   
zNetworkState.__init__r=   c                 C   s
   | j d S )Nr   )rb   ©rQ   rB   rB   rC   r   ˆ   ó   
zNetworkState.configc                 C   s   | j S rE   )rc   rg   rB   rB   rC   r   Œ   s   zNetworkState.versionc                 C   ó(   z| j d d W S  ty   g  Y S w )NÚdnsr#   ©rb   ÚKeyErrorrg   rB   rB   rC   Údns_nameservers�   ó
   ÿzNetworkState.dns_nameserversc                 C   ri   )Nrj   Úsearchrk   rg   rB   rB   rC   Údns_searchdomains—   rn   zNetworkState.dns_searchdomainsc                 C   s   | j d u r
|  ¡ | _ | j S rE   )re   Ú_maybe_has_default_routerg   rB   rB   rC   Úhas_default_routež   s   

zNetworkState.has_default_routeNc                 c   s@   � | j  di ¡}| ¡ D ]}|d u r|V  q||ƒr|V  qd S )Nr    )rb   rd   Úvalues)rQ   Úfilter_funcÚifacesÚifacerB   rB   rC   Úiter_interfaces¤   s   €€ûzNetworkState.iter_interfacesc                 c   s8   � | j  dg ¡D ]}|d ur||ƒr|V  q|V  qd S ©NÚroutes©rb   rd   )rQ   rt   ÚrouterB   rB   rC   Úiter_routes­   s   €€ûzNetworkState.iter_routesc                 C   sh   |   ¡ D ]
}|  |¡r dS q|  ¡ D ]}| dg ¡D ]}| dg ¡D ]}|  |¡r/   dS q#qqdS )NTÚsubnetsry   F)r|   Ú_is_default_routerw   rd   )rQ   r{   rv   ÚsubnetrB   rB   rC   rq   µ   s   
ÿ

ÿÿÿz%NetworkState._maybe_has_default_routec                 C   s    d}|  d¡dko|  d¡|v S )N)z::z0.0.0.0Úprefixr   Únetwork)rd   )rQ   r{   Údefault_netsrB   rB   rC   r~   À   s   ÿzNetworkState._is_default_routec                 C   s,   i }d|v r|d |d< | d|ifi |¤ŽS )záInstantiates a `NetworkState` without interpreting its data.

        That means only `config` and `version` are copied.

        :param network_state: Network state data.
        :return: Instance of `NetworkState`.
        r   r   rB   )Úclsr   rT   rB   rB   rC   Úto_passthroughÆ   s   	zNetworkState.to_passthroughrE   )rN   rO   rP   ÚNETWORK_STATE_VERSIONÚdictÚintrf   Úpropertyr   r   rm   rp   rr   rw   r|   rq   r~   Úclassmethodr„   rB   rB   rB   rC   r^      s.    ÿÿ
ÿ





	r^   c                   @   s”  e Zd Zi g g g dœdddœZeddf	dHdd„Zed	efd
d„ƒZedd„ ƒZ	e	j
dd„ ƒZ	dd„ Zdd„ Zdd„ Zdd„ ZdIdd„ZdIdd„ZdIdd„Zedgƒdd „ ƒZedgƒd!d"„ ƒZeg d#¢ƒd$d%„ ƒZeg d&¢ƒd'd(„ ƒZedd)gƒd*d+„ ƒZedgƒd,d-„ ƒZd.d/„ Zed0gƒd1d2„ ƒZed0gƒd3d4„ ƒZed5gƒd6d7„ ƒZd8d9„ Zd:d;„ Zd<d=„ Zd>d?„ Z d@dA„ Z!dJdBdC„Z"dKdDdE„Z#dFdG„ Z$dS )LÚNetworkStateInterpreter©r#   ro   FN)r    ry   rj   r_   r   r$   úOptional[Renderer]c                 C   sv   || _ || _t | j¡| _|| jd< d| _i | _|| _| j	| j
| j| j| j| j| j| j| j| j| j| j| jdœ| _d S )Nr   F)r9   Úbondsr:   ÚbridgesÚ	ethernetsÚ
infinibandÚloopbackÚ
nameserverÚphysicalr{   ÚvlanÚvlansÚwifis)rc   Ú_configr`   ra   Úinitial_network_staterb   Ú_parsedÚ_interface_dns_mapÚ	_rendererÚhandle_bondÚhandle_bondsÚhandle_bridgeÚhandle_bridgesÚhandle_ethernetsÚhandle_infinibandÚhandle_loopbackÚhandle_nameserverÚhandle_physicalÚhandle_routeÚhandle_vlanÚhandle_vlansÚhandle_wifisÚcommand_handlers)rQ   r   r   r$   rB   rB   rC   rf   á   s*   
óz NetworkStateInterpreter.__init__r=   c                 C   sH   ddl m} | jdkrt| j|ƒrt d¡ t | j	¡S t| j
| jd�S )Nr   r   é   zPassthrough netplan v2 config©r   )Úcloudinit.net.netplanr   rc   Ú
isinstancer›   ÚLOGÚdebugr^   r„   r—   rb   )rQ   ÚNetplanRendererrB   rB   rC   r   þ   s
   
z%NetworkStateInterpreter.network_statec                 C   s   | j  d¡S ©Nr_   rz   rg   rB   rB   rC   r_     s   z NetworkStateInterpreter.use_ipv6c                 C   s   | j  d|i¡ d S r±   )rb   Úupdate)rQ   ÚvalrB   rB   rC   r_     s   c                 C   s   | j | j| jdœ}t |¡S )Nr   )rc   r—   rb   r   Údumps)rQ   ÚstaterB   rB   rC   Údump  s
   ý
zNetworkStateInterpreter.dumpc                 C   sv   d|vrt  d¡ tdƒ‚t|d  }t||ƒ}|r'd| }t  |¡ t|ƒ‚dd„ |D ƒD ]
}t| ||| ƒ q.d S )Nr   z$Invalid state, missing version fieldzInvalid state, missing keys: %sc                 S   s   g | ]}|d vr|‘qS )r«   rB   )Ú.0ÚkrB   rB   rC   Ú
<listcomp>$  s    z0NetworkStateInterpreter.load.<locals>.<listcomp>)r®   ÚerrorÚ
ValueErrorÚNETWORK_STATE_REQUIRED_KEYSrL   Úsetattr)rQ   rµ   rW   rU   ÚmsgrK   rB   rB   rC   Úload  s   


ÿzNetworkStateInterpreter.loadc                 C   s   t  | j¡S rE   )r   r´   rb   rg   rB   rB   rC   Údump_network_state'  s   z*NetworkStateInterpreter.dump_network_statec                 C   s   | j | jdœS )N)r   r   )rc   r—   rg   rB   rB   rC   Úas_dict*  s   zNetworkStateInterpreter.as_dictTc                 C   sD   | j dkr| j|d� d| _d S | j dkr | j|d� d| _d S d S )Nr   ©Úskip_brokenTrª   )rc   Úparse_config_v1r™   Úparse_config_v2)rQ   rÃ   rB   rB   rC   Úparse_config-  s   



þz$NetworkStateInterpreter.parse_configc                 C   sþ   | j D ]B}|d }z| j| }W n ty# } ztd| ƒ|‚d }~ww z||ƒ W q tyE   |s4‚ tjd|dd� t |  ¡ ¡ Y qw | j	 
¡ D ]1\}}d }z	| jd | }W n tyn } ztd |¡ƒ|‚d }~ww |r||\}	}
|	|
dœ|d	< qKd S )
NÚtypez"No handler found for  command '%s'úSkipping invalid command: %sT©Úexc_infor    zINameserver specified for interface {0}, but interface {0} does not exist!r‹   rj   )r—   r©   rl   ÚRuntimeErrorrM   r®   Úwarningr¯   rÀ   rš   Úitemsrb   r»   Úformat)rQ   rÃ   rR   Úcommand_typeÚhandlerÚeÚ	interfacerj   rv   r#   ro   rB   rB   rC   rÄ   5  sT   
ÿþ€ÿÿùþý€ÿ
þ€õz'NetworkStateInterpreter.parse_config_v1c                 C   sÀ   ddl m} t| j|ƒrd S | j ¡ D ]J\}}|dv rqz| j| }W n ty6 } ztd| ƒ|‚d }~ww z||ƒ |  	|¡ W q t
y]   |sL‚ tjd|dd� t |  ¡ ¡ Y qw d S )Nr   r   )r   r$   z!No handler found for command '%s'rÈ   TrÉ   )r¬   r   r­   r›   r—   rÍ   r©   rl   rË   Ú
_v2_commonrM   r®   rÌ   r¯   rÀ   )rQ   rÃ   r°   rÏ   rR   rÐ   rÑ   rB   rB   rC   rÅ   X  s8   ÿþ€ÿÿùôz'NetworkStateInterpreter.parse_config_v2Únamec                 C   s
   |   |¡S rE   ©r¤   ©rQ   rR   rB   rB   rC   r¢   t  rh   z'NetworkStateInterpreter.handle_loopbackc                 C   s\  | j  di ¡}| |d i ¡}| di ¡ ¡ D ]\}}| ||i¡ qt| d¡ƒ}| jsF|D ]}| d¡ d¡s@t| d¡ƒrEd| _ nq/| d	d
¡}|d
urUt 	|¡}| dd
¡}	|	d
urdt 	|	¡}	| dd
¡}
|
d
urst 	|
¡}
| | d¡| d¡| d¡| d¡dd| d¡d
d
|||	|
dœ¡ | d| d¡¡}| j d  ||i¡ |  
¡  d
S )zþ
        command = {
            'type': 'physical',
            'mac_address': 'c0:d6:9f:2c:e8:80',
            'name': 'eth0',
            'subnets': [
                {'type': 'dhcp4'}
             ],
            'accept-ra': 'true'
        }
        r    rÔ   Úparamsr}   rÇ   Ú6ÚaddressTr'   Nr&   r(   Ú	config_idÚmac_addressÚinetÚmanualr"   )rÚ   rÔ   rÇ   rÛ   rÜ   r)   r"   rÙ   Úgatewayr}   r'   r&   r(   )rb   rd   rÍ   r²   Ú_normalize_subnetsr_   Úendswithr   r   Úis_truerÀ   )rQ   rR   r    rv   Úparamr³   r}   r   Ú	accept_rar&   r(   Ú	iface_keyrB   rB   rC   r¤   x  sR   ÿü


óÿz'NetworkStateInterpreter.handle_physical)rÔ   Úvlan_idÚ	vlan_linkc                 C   s\   | j  di ¡}|  |¡ | | d¡i ¡}| d¡|d< | d¡|d< | |d |i¡ dS )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
        r    rÔ   ræ   zvlan-raw-devicerå   N)rb   rd   r¤   r²   )rQ   rR   r    rv   rB   rB   rC   r¦   µ  s   

z#NetworkStateInterpreter.handle_vlan)rÔ   Úbond_interfacesr×   c           	      C   s  |   |¡ | j d¡}| | d¡i ¡}| d¡ ¡ D ]\}}| ||i¡ q| ddi¡ | jd  |d |i¡ | d¡D ]@}||vrO|ddœ}|   |¡ | j di ¡}| |¡}| d¡|d	< | d¡ ¡ D ]\}}| ||i¡ qi| jd  ||i¡ q?d
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
        r    rÔ   r×   zbond-slavesÚnonerç   r9   )rÔ   rÇ   zbond-masterN)r¤   rb   rd   rÍ   r²   )	rQ   rR   r    rv   râ   r³   ÚifnameÚcmdÚbond_ifrB   rB   rC   rœ   Æ  s(   
þ

ñz#NetworkStateInterpreter.handle_bondÚbridge_interfacesc           	      C   s  | j  di ¡}| d¡D ]}||v rqd|i}|  |¡ q| j  di ¡}|  |¡ | | d¡i ¡}|d |d< | di ¡ ¡ D ]\}}| ||i¡ q@| d¡}|durwt|tƒsw|dv rad	}n|d
v rhd}ntdj|d�ƒ‚| d|i¡ | |d |i¡ dS )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",
        ]
        r    rì   rÔ   Úbridge_portsr×   r7   N)ÚonÚ1r   T)ÚoffÚ0r   Fz2Cannot convert bridge_stp value ({stp}) to boolean)r-   )	rb   rd   r¤   rÍ   r²   r­   Úboolr»   rÎ   )	rQ   rR   r    ré   rê   rv   râ   r³   r7   rB   rB   rC   rž   û  s4   ÿ

ÿÿz%NetworkStateInterpreter.handle_bridgec                 C   s   |   |¡ d S rE   rÕ   rÖ   rB   rB   rC   r¡   <  s   z)NetworkStateInterpreter.handle_infinibandc                 C   sx   g }g }d|v r|d }t |tƒs|g}|D ]}| |¡ qd|v r8|d }t |tƒs.|g}|D ]}| |¡ q0||fS )NrÙ   ro   )r­   ÚlistÚappend)rQ   rR   r#   ro   ÚaddrsÚaddrÚpathsÚpathrB   rB   rC   Ú
_parse_dns@  s   

z"NetworkStateInterpreter._parse_dnsrÙ   c                 C   sX   | j  d¡}|  |¡\}}d|v r||f| j|d < d S |d  |¡ |d  |¡ d S )Nrj   rÒ   r#   ro   )rb   rd   rù   rš   Úextend)rQ   rR   rj   r#   ro   rB   rB   rC   r£   Q  s   þz)NetworkStateInterpreter.handle_nameserverc                 C   s0   | j  d¡}|  |¡\}}||dœ|| d< d S )Nr    r‹   rj   )rb   rd   rù   )rQ   rR   rv   Ú_ifacer#   ro   rB   rB   rC   Ú_handle_individual_nameserver^  s   z5NetworkStateInterpreter._handle_individual_nameserverÚdestinationc                 C   s   | j d  t|ƒ¡ d S rx   )rb   rô   Ú_normalize_routerÖ   rB   rB   rC   r¥   d  s   z$NetworkStateInterpreter.handle_routec                 C   ó   | j |dd� dS )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',
            }
        }

        r9   ©Úcmd_typeN©Ú_handle_bond_bridgerÖ   rB   rB   rC   r�   i  s   z$NetworkStateInterpreter.handle_bondsc                 C   rÿ   )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:   r   Nr  rÖ   rB   rB   rC   rŸ   ˆ  s   z&NetworkStateInterpreter.handle_bridgesc                 C   s  t ƒ }| ¡ D ]‚\}}|ddœ}| di ¡}| dd¡}|s't d|t|ƒ¡ ||d< |}| d¡}	|	r7|	}n|rG|rG| ¡ }
t|
ƒ}|rG|}||d	< | d
d¡}|rYd
|i|d< dD ]}||v rg|| ||< q[t|ƒ |  	|¡}t
|ƒdkr~| d|i¡ t d|¡ |  |¡ qdS )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'}
             ]
        }
        r“   )rÚ   rÇ   r!   Ú
macaddressNzHNetworkState Version2: missing "macaddress" info in config entry: %s: %srÛ   r%   rÔ   Údriverr×   )r"   r!   r&   r'   r(   r   r}   z!v2(ethernets) -> v1(physical):
%s)r
   rÍ   rd   r®   r¯   ÚstrÚlowerr	   rD   Ú_v2_to_v1_ipcfgÚlenr²   r¤   )rQ   rR   Úifaces_by_macÚethÚcfgÚphy_cmdr!   rÛ   rÔ   Úset_nameÚlcase_mac_addressÚmacr  rK   r}   rB   rB   rC   r    ¡  sL   -þü
€
Òz(NetworkStateInterpreter.handle_ethernetsc                 C   s†   |  ¡ D ]<\}}d|| d¡| d¡dœ}d|v r|d |d< t|ƒ |  |¡}t|ƒdkr5| d|i¡ t d|¡ |  |¡ qd	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'}],
        }
        r”   ÚidÚlink)rÇ   rÔ   rå   ræ   r"   r   r}   zv2(vlans) -> v1(vlan):
%sN)	rÍ   rd   rD   r  r	  r²   r®   r¯   r¦   )rQ   rR   r”   r  Úvlan_cmdr}   rB   rB   rC   r§      s   ü
òz$NetworkStateInterpreter.handle_vlansc                 C   s   t  d¡ d S )NzOWifi configuration is only available to distros with netplan rendering support.)r®   rÌ   rÖ   rB   rB   rC   r¨   "  s   ÿz$NetworkStateInterpreter.handle_wifisc                 C   sv   t  d|¡ | ¡ D ].\}}d|v r8| d¡ d¡}| d¡ d¡}ddi}|r,||d< |r2||d< |  ||¡ q
d S )Nzv2_common: handling config:
%sr#   ro   r   rÇ   r’   rÙ   )r®   r¯   rÍ   rd   rü   )rQ   r  rv   Údev_cfgro   rj   Úname_cmdrB   rB   rC   rÓ   (  s   €öz"NetworkStateInterpreter._v2_commonc           
         s&  t dd„ t |¡ ¡ D ƒƒ‰ | ¡ D ]~\}}t dd„ | ¡ D ƒƒ}| di ¡}| dd¡}|r3||d< d|d	||d
 | d¡dt ‡ fdd„| ¡ D ƒƒi}d|v rW|d |d< t|ƒ |  |¡}	t|	ƒdkrm| d|	i¡ t	 
d|||¡ |dkr|  |¡ q|dkr‰|  |¡ qtdj|d�ƒ‚dS )z(Common handler for bond and bridge typesc                 s   s   � | ]	\}}||fV  qd S rE   rB   ©r·   r¸   ÚvrB   rB   rC   Ú	<genexpr>:  s   € 
ÿz>NetworkStateInterpreter._handle_bond_bridge.<locals>.<genexpr>c                 s   s$   � | ]\}}|t vr||fV  qd S rE   )ÚNETWORK_V2_KEY_FILTER)r·   rK   ÚvaluerB   rB   rC   r  ?  s   € þýÚ
parameterszgratuitious-arpNr*   rÇ   rÔ   Ú_interfacesr    r×   c                 3   s    � | ]\}}ˆ | |fV  qd S rE   rB   r  ©Úv2key_to_v1rB   rC   r  O  ó   € r"   r   r}   zv2(%s) -> v1(%s):
%sr:   r9   z Unknown command type: {cmd_type}r   )r†   r;   rd   rÍ   ÚpoprD   r  r	  r²   r®   r¯   rž   rœ   r»   rÎ   )
rQ   rR   r  Ú	item_nameÚitem_cfgÚitem_paramsr×   Ú
grat_valueÚv1_cmdr}   rB   r  rC   r  6  sB   ÿþü
ÿÿßz+NetworkStateInterpreter._handle_bond_bridgec              
   C   s®  dd„ }g }|  d¡rddi}||  di ¡|ƒ | |¡ |  d¡r7ddi}d| _||  di ¡|ƒ | |¡ d	}d	}i }|  d
g ¡D ]`}d|dœ}d|v rcd|v rb|d	u rb|  d¡}| d|i¡ nd|v rw|d	u rw|  d¡}| d|i¡ d|v rž|sž|  d¡  d
¡}	|	r‹|	|d< |  d¡  d¡}
|
r™|
|d< | |¡ | |¡ qCg }|  dg ¡D ]}| t|  d¡|  d¡|  d¡|  d¡dœƒ¡ q¬t|ƒrÕt|ƒrÕ||d d< |S )z7Common ipconfig extraction from v2 to v1 subnets array.c                 S   s   d| v r| d |d< d S d S )Nzroute-metricÚmetricrB   )Ú	overridesr   rB   rB   rC   Ú_add_dhcp_overridesh  s   ÿzDNetworkStateInterpreter._v2_to_v1_ipcfg.<locals>._add_dhcp_overridesr   rÇ   r   r   Tr   Nr   Ústatic)rÇ   rÙ   ú:r   rÞ   r   r#   rm   ro   Ú
dns_searchry   ÚtoÚviar&  r"   )rý   rÞ   r&  r"   r   )rd   rô   r_   r²   rþ   r	  )rQ   r  r(  r}   r   r   r   r#   rÙ   r   ro   ry   r{   rB   rB   rC   r  e  sb   



þ
€

üÿÿz'NetworkStateInterpreter._v2_to_v1_ipcfg)r$   rŒ   )T)r=   NrE   )%rN   rO   rP   r˜   r…   rf   rˆ   r^   r   r_   Úsetterr¶   r¿   rÀ   rÁ   rÆ   rÄ   rÅ   r]   r¢   r¤   r¦   rœ   rž   r¡   rù   r£   rü   r¥   r�   rŸ   r    r§   r¨   rÓ   r  r  rB   rB   rB   rC   rŠ   Õ   sn    þøü
ü




#


<



4
@



_"

/rŠ   c                 C   sz   t  | ¡} tdd„ |  ¡ D ƒƒ}|  d¡dv r | t|dd�¡ dd„ |  d	g ¡D ƒ|d	< d
d„ }dD ]}|||ƒ q3|S )Nc                 s   s    � | ]\}}|r||fV  qd S rE   rB   r  rB   rB   rC   r  ¬  r  z$_normalize_subnet.<locals>.<genexpr>rÇ   )r)  Ústatic6)rÙ   Ú
ip_address©Úaddress_keysc                 S   ó   g | ]}t |ƒ‘qS rB   )rþ   )r·   ÚrrB   rB   rC   r¹   ¸  s    ÿz%_normalize_subnet.<locals>.<listcomp>ry   c                 S   s2   || v rt | | tƒs| |  ¡ | |< d S d S d S rE   )r­   ró   Úsplit)ÚsnetrÔ   rB   rB   rC   Úlistify¼  s   ÿz"_normalize_subnet.<locals>.listify)r+  rm   )r`   ra   r†   rÍ   rd   r²   Ú_normalize_net_keys)r   Únormal_subnetr7  r¸   rB   rB   rC   Ú_normalize_subnet©  s    
þÿ	

ÿr:  rB   c                 C   s¤  dd„ |   ¡ D ƒ}d}|D ]}| |¡r|} nq|s-dd |¡| f }t |¡ t|ƒ‚t| |¡ƒ}t|ƒsFt d|¡ td|› d�ƒ‚t|ƒ}t	|ƒ}| d	¡}	d
|v r| 
d
¡\}
}}|
||< |rjt|ƒ}n8|rqt|ƒ}n1t d|¡ td|› d�ƒ‚d|v rŠt|d ƒ}n|	r“|r“t|	ƒ}n|	rœ|rœt|	ƒ}n|r dnd}d|v r·t|d ƒt|ƒkr·t d||¡ ||d< |rÆd	|v rÄ|d	= |S |rÐt|d ƒ|d	< |S )a¬  Normalize 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.
    c                 S   s"   i | ]\}}|s|d kr||“qS )r   rB   r  rB   rB   rC   Ú
<dictcomp>Ñ  s   " z'_normalize_net_keys.<locals>.<dictcomp>Nz/No config network address keys [%s] found in %sú,z$Address %s is not a valid ip networkzAddress z is not a valid ip addressÚnetmaskú/r€   é@   é   z;Overwriting existing 'prefix' with '%s' in network info: %s)rÍ   rd   Újoinr®   rº   r»   r  r   r   r   Ú	partitionr   r   r‡   rÌ   r   )r�   r2  ÚnetÚaddr_keyrK   Úmessagerö   Úipv6Úipv4r=  Ú	addr_partÚ_Úmaybe_prefixr€   rB   rB   rC   r8  Æ  sf   
þþ





ýýr8  c              
   C   s�   t dd„ |  ¡ D ƒƒ}d|v r|d |d< |d= | t|dd�¡ | d¡}|rFz	t|ƒ|d< W |S  tyE } ztd |¡ƒ|‚d	}~ww |S )
aƒ  normalize 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.
    c                 s   s$   � | ]\}}|d vr||fV  qdS ))Ú NNrB   r  rB   rB   rC   r    s   € ÿz#_normalize_route.<locals>.<genexpr>rý   r�   )r�   rý   r1  r&  z(Route config metric {} is not an integerN)	r†   rÍ   r²   r8  rd   r‡   r»   Ú	TypeErrorrÎ   )r{   Únormal_router&  rÑ   rB   rB   rC   rþ     s2   
ÿÿÿ
üÿþ€ÿrþ   c                 C   s   | sg } dd„ | D ƒS )Nc                 S   r3  rB   )r:  )r·   ÚsrB   rB   rC   r¹   7  s    z&_normalize_subnets.<locals>.<listcomp>rB   )r}   rB   rB   rC   rß   4  s   rß   TÚ
net_configrÃ   c                 C   sf   d}|   d¡}|   d¡}|dkr| }|r(|dur(t|||d�}|j|d� |j}|s1td| › �ƒ‚|S )zfParses the config, returns NetworkState object

    :param net_config: curtin network config dict
    Nr   r   rª   )r   r   r$   rÂ   zpNo valid network_state object created from network config. Did you specify the correct version? Network config:
)rd   rŠ   rÆ   r   rË   )rO  rÃ   r$   rµ   r   r   ÚnsirB   rB   rC   Úparse_net_config_data:  s$   	

ÿþÿrQ  )rB   )TN)/r`   rY   ÚloggingÚtypingr   r   r   r   Ú	cloudinitr   r   r   Úcloudinit.netr	   r
   r   r   r   r   r   r   r   Úcloudinit.net.rendererr   Ú	getLoggerrN   r®   r…   r¼   r  r;   r  Ú__annotations__r†   rD   rL   Ú	ExceptionrM   r]   r^   rŠ   r:  r8  rþ   rß   rò   rQ  rB   rB   rB   rC   Ú<module>   s„   
,
ÿñõî"V     Y
L"ýÿþü