o
    itm                  
   @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlm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 d dlmZ eeZg dZg dZg d	Z d
e!de!de"dee# fddZ$d
e!de%dee# dee# fddZ&	d+d
e!de"dee# fddZ'de!de#de#de#ddf
ddZ(e)dde#de!fd d!Z*de!de!fd"d#Z+d$e#de"de"fd%d&Z,G d'd( d(ej-Z-de"fd)d*Z.dS ),    N)suppress)AnyDictListOptional)performancesubputil)ParserErroris_ipv4_addressis_ipv4_networkis_ipv6_addressis_ipv6_networkrenderersubnet_is_ipv6)NetworkState)zpre-upupzpost-updownzpre-downz	post-down)bridge_ageingbridge_bridgeprio	bridge_fdbridge_gcinitbridge_hellobridge_maxagebridge_maxwait
bridge_stp)addressnetmask	broadcastnetworkmetricgatewaypointtopointmediamtuhostname
leasehours	leasetimevendorclientbootfileserverhwaddrproviderframenetnumendpointlocalttlifacesubnetis_ipv6returnc                 C   s  g }g d}|  D ]\}}|dkrq
|dkr!d|d |d f }|r||v rt|tr~|dkrAtttjt|d|}|g krAq
|dkrxt|dtr_tttjt|d|dg g kswt|dtrx|dd	kswt|dd	|sxq
d
	|}nA|dkrt||sq
|dkrt|dtrtttjt|d|dg g kst|dtr|dd	kst|dd	|sq
d|v r|
dd}|d|| q
t|S )N)
r   r   r   r    r!   pointopointr$   scope
dns_searchdns_nameserversr   r   z%s/%sprefixr:   )r5   r9     _-    {0} {1})items
isinstancelistfilter	functoolspartialhas_same_ip_versiongetstrjoinreplaceappendformatsorted)r3   r4   r5   content	valid_mapkeyvalue rS   3/usr/lib/python3/dist-packages/cloudinit/net/eni.py_iface_add_subnetJ   s   


	


	rU   indexipv4_subnet_mtuc                 C   s  |dkrg S g }g d}g d}ddi}| d dvr| d |  D ]c\}}|||}	d|	v r7|	dd	}	t|trD| | rBd
nd}|rJ||v rKq#|dkr`|r`||kr_td| d || q#||v rs|D ]}
| d|	|
 qfq#t|t	r}d
|}| d|	| q#t|S )Nr   )
control	device_iddnsdriverrV   inetmodenamesubnetstype)bridge_pathcostbridge_portpriobridge_waitportmac_address	hwaddressr`   )bondbridge
infinibandvlanr>   r?   onoffr$   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.r^   r@   r=   )rL   rA   rH   rK   rB   boolLOGwarningrM   rC   rJ   rN   )r3   rV   rW   rO   
ignore_mapmultiline_keysrenamesrQ   rR   	key_writevrS   rS   rT   _iface_add_attrs   sB   



rt   Frender_hwaddressc                 C   s   | d }| d }|dkrd}n|dv rd| }nd| }|   }|||d djdi |d	jdi |g}|rJ| d
rJ|djdi | |S )Nr^   rX   auto)hotplugzallow-z
# control-)fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}rd   z    hwaddress {mac_address}rS   )copyupdaterM   rH   rL   )r3   rV   ru   rx   rX   ry   substlinesrS   rS   rT   _iface_start_entry   s   
r~   ifacescontentssrc_dirsrc_pathc              
      s<  d}|  D ]}| }|drq|d}|d }|dkrd|d }|ds0tj||}t|D ]- t }	 fdd	|	D }	|	D ]}
t	
|
 }tj|
}t| |tj|| qGq5q|d
kr|d }|dsxtj||}t|D ]. t d}|  }W d   n1 sw   Y  tj }t| |tj|| q}q|dkr|dd D ]}|| vrd|i| |< d| | d< qq|dkr|dd \}}}|| vrd|i| |< nd| | v rtd||f || | d< || | d< |}q|dkr|d dkr|d }n|d }|| | d< q|tv r+|d | | |< q|tv rN|| | vr=g | | |< | | | d|dd  q|drd| | vrai | | d< |dkrg | | d d< |dd D ]}| | d d | qtq|dkrg | | d d< |dd D ]}| | d d | qq|drbd| | vri | | d< |tv r|ddd}|d | | d |< q|d krg | | d d!< |dd D ]}| | d d! | qq|d"kr|d  d#kr|d | | d d#< q|d | | d d#< q|d$kr=d%| | d vr.i | | d d%< |d | | d d% |d < q|d&krad'| | d vrSi | | d d'< |d | | d d' |d < q|d(rd)| | vrui | | d)< |d(dd}|d | | d) |< q|  D ]}d| | vrd*| | d< qdS )+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#r=   r   zsource-directory   /c                    s@   g | ]}t jt j |rtd |durt j |qS )z^[a-zA-Z0-9_-]+$N)ospathisfilerJ   rematch).0r   expanded_pathrS   rT   
<listcomp>"  s    z*_parse_deb_config_data.<locals>.<listcomp>sourcerrv   _source_pathTr3      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodre   ether   zdns-rZ   z
dns-searchsearchzdns-nameserversnameserversbridge_rg   r<   bridge_portsports	bridge_hwmacra   pathcostrb   portpriozbond-rf   F)
splitlinesstrip
startswithsplitr   r   rJ   globlistdirr	   load_text_fileabspath_parse_deb_config_datadirnameopenreadr
   NET_CONFIG_OPTIONSNET_CONFIG_COMMANDSrL   NET_CONFIG_BRIDGE_OPTIONSrK   lowerkeys)r   r   r   r   currifliner   optionparsed_src_dirdir_contentsentrysrc_data	abs_entrynew_src_pathfpabs_pathr3   r   r   valdomainr+   bridge_optionbond_optionrS   r   rT   r     s   











"






r   zConverting eni dataeni_datac                 C   s   i }t || ddd t|S )z=Return a network config representation of what is in eni_dataNone)r   r   )r   _ifaces_to_net_config_data)r   r   rS   rS   rT   convert_eni_data  s   r   c                    s4  i  |   D ]\}}|dd }| vr2|dkrd}nd}||g d |< d|v r2|d  | d< ||d	 d
}|drCd|d< nd|d< |d	dkrT|d |d< dD ]}||v rb|| ||< qVd|v rdD ]}||d v r|d | r|d | |d| < qi | d | qd fddt D dS )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).:r   loloopbackphysical)r`   r^   r_   re   rd   r   )_orig_eni_namer`   rv   rX   manualstaticr   )r   r!   r   rZ   )r   r   dns_r_   r   c                    s   g | ]} | qS rS   rS   )r   ddevsrS   rT   r         z._ifaces_to_net_config_data.<locals>.<listcomp>)versionconfig)rA   	partitionrH   rL   rN   )r   r^   datadevnamedtyper4   copy_keynrS   r   rT   r     s6   

r   addr_or_netc                 C   s$   |s
t | p	t| S t| pt| S N)r   r   r   r   )r   r5   rS   rS   rT   rG     s   rG   c                	   @   s   e Zd ZdZddee fddZddeded	ee fd
dZ		ddede
d	eee  fddZ	ddede
d	efddZ		ddedee dee d	dfddZdS )Rendererz@Renders network information in a /etc/network/interfaces format.Nr   c                 C   s6   |si }| dd| _| dd | _| dd| _d S )Neni_pathzetc/network/interfaces
eni_headernetrules_pathz(etc/udev/rules.d/70-persistent-net.rules)rH   r   r   r   )selfr   rS   rS   rT   __init__  s   
zRenderer.__init__r<   routeindentr6   c                 C   s  g }t dr
d}nd}|r|d }|d }ddd}n|d	 }|d
 }ddd}d}d}	|d dkrF|d dkrF|rC|d7 }|d7 }d}	n|d dkra|d dkra|r_|d7 }|d7 }d}	nd}	d}
dD ]t}|	rn|dkrnqe|dkr|
d|	|| || f 7 }
qe||v r|dkr|rt|| r|d7 }|d7 }|d7 }|d7 }nt|| r|
d7 }
n|ddkr|
d 7 }
n|
d!7 }
d|v r|
d"|| |d f 7 }
qe|
d#|| || f 7 }
qe|||
 |  |||
 |  |S )$a  When 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
        ipTFz
post-up ipzpre-down ipviar    )r!   r    zpost-up route addzpre-down route delgwz || truer<   r   z0.0.0.0r   z
 route addz
 route delz defaultz::r;   r   z -family inet6 route addz -family inet6 route delz -A inet6 default)r   r!   r    r!   z%s %s %sz -family inet6z	 -A inet6    z -hostz -netz %s/%sz %s %s)r   whichr   rH   rL   )r   r   r   rO   
use_ip_cmdr   r   mappingor_true
default_gw
route_linekrS   rS   rT   _render_route  sn   



zRenderer._render_routeFr3   ru   c                    s  t   tt  d W d    n1 sw   Y  g } di } dd } dd }|r8d d< |rd }g }t|D ]\}	d }
|	 d< d  d	< d
d d
< d}trid}|d7 }nd}d}
| d< d dksd dksd dkrd d	< |d ur|rdnd d< n2d dkrd d	< d d< n#d dkrd d	< d d< ntrd d	< |d ur|rdnd d< d fdd|D v rd d
< dv pdv }|d u r|rtfd d!d"D }|d ur|si |t	t
 |	|d#t | t |	|
 }d$g D ]"}t|d%d&}|r/|s/|| q|| j|d'd( q|rU|rU|D ]}|| j|d'd( qC|  || qC|r d)  d
 dd*d+ d|d,|d uryi |t	t
 d-|d#t d }d$ D ]}|| j|d'd( q|| |S g }d. v sd/ v r|d0jd4i   |d1jd4i   |t d2d d3 || |S )5N	config_idr_   z	accept-ra	wakeonlangzethernet-wolrV   r`   r]   rX   rv   r\   T6Fr$   dhcp4dhcp6zipv6_dhcpv6-statefuldhcp10	accept_razipv6_dhcpv6-stateless
ipv6_slaacr   c                    s   g | ]
}d  d  |v qS )zauto %sr^   rS   )r   r   )r3   rS   rT   r   ^  s    z*Renderer._render_iface.<locals>.<listcomp>aliasr9   r:   c                 3   s    | ]
}|  |fV  qd S r   )rH   )r   r   )r4   rS   rT   	<genexpr>i  s
    
z)Renderer._render_iface.<locals>.<genexpr>)r9   r:   ru   routesr   r<   z    )r   r^   inet6)r^   rX   r]   r\   )r`   r   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )rV   rW   rS   )rz   deepcopyr   KeyErrorpoprH   	enumerater   dictrC   r~   rU   rt   r   rL   extendr   clearrM   )r   r3   ru   sectionsr_   r   ethernet_wolrZ   routes6rV   rW   subnet_inetr5   dns_presentr}   r   ipv6_networkrS   )r3   r4   rT   _render_iface"  s   













zRenderer._render_ifacenetwork_statec           	         s  ddddddgd}|  D ]}|ddkrt|}q|j}|r+||d	 d
 d< |j}|r8||d	 d
 d< d
dddddd g }|| | t|   fdddD ]}|ddkraqW|| j||d qW|	 D ]
}|
| | qpddd |D d S )z1Given state, emit etc/network/interfaces content.r   r   r\   r   rv   )r`   rX   )r^   r`   r\   r_   r^   r_   r   r:   r9   r   r      r      )r   r   rh   rf   rg   ri   c                    s    | d  | d fS )Nr`   r^   rS   )r   orderrS   rT   <lambda>  r   z-Renderer._render_interfaces.<locals>.<lambda>)rQ   r   z

c                 S   s   g | ]}d  |qS )
)rJ   )r   srS   rS   rT   r     s    z/Renderer._render_interfaces.<locals>.<listcomp>r  )iter_interfacesrH   rz   r   r:   dns_searchdomainsr  r  rN   iter_routesrL   r   rJ   )	r   r  ru   r   r3   r   searchdomainsr  r   rS   r  rT   _render_interfaces  sH   

	

zRenderer._render_interfaces	templatestargetc                 C   s   t || j}ttj| | jr| jnd}t	||| 
|  | jrCt || j}ttj| tj	|| |dd d S d S )Nr<   T)rO   preserve_mode)r   target_pathr   r	   
ensure_dirr   r   r   r   
write_filer  r   _render_persistent_net)r   r  r  r  fpeniheadernetrulesrS   rS   rT   render_network_state  s   
zRenderer.render_network_stater   )r<   F)NN)__name__
__module____qualname____doc__r   r  r   rI   r   r   rl   r  r   r  r$  rS   rS   rS   rT   r     s@    	R

 
9r   c                  C   sF   g d} ddg}| D ]}t j||ds dS q
d}tj|s!dS dS )N)ifqueryifupifdownz/sbinz	/usr/sbin)r   Fz/etc/network/interfacesT)r   r   r   r   r   )expectedr   penirS   rS   rT   	available  s   r0  r%  )/rz   rE   r   loggingr   r   
contextlibr   typingr   r   r   r   	cloudinitr   r   r	   cloudinit.netr
   r   r   r   r   r   r   cloudinit.net.network_stater   	getLoggerr&  rm   r   r   r   r  rl   rI   rU   intrt   r~   r   timedr   r   rG   r   r0  rS   rS   rS   rT   <module>   sj   $	
	b
C

 )  .