o
    thGd                  
   @   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 ]U\}}|dkrq
|dkr!d|d |d f }|r_||v r_t|trB|dkr<tttjt|d|}d|}n
|dkrLt||sLq
d	|v rV|d	d
}|	d
|| q
t|S )N)
r   r   r   r    r!   pointopointr$   scope
dns_searchdns_nameserversr   r   z%s/%sprefixr:   )r5    _-    {0} {1})items
isinstancelistfilter	functoolspartialhas_same_ip_versionjoinreplaceappendformatsorted)r3   r4   r5   content	valid_mapkeyvalue rP   3/usr/lib/python3/dist-packages/cloudinit/net/eni.py_iface_add_subnetJ   s8   

rR   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driverrS   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<   )rI   r@   getrH   rA   boolLOGwarningrJ   rB   rG   rK   )r3   rS   rT   rL   
ignore_mapmultiline_keysrenamesrN   rO   	key_writevrP   rP   rQ   _iface_add_attrsv   sB   



rr   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[   rU   auto)hotplugzallow-z
# control-)fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}ra   z    hwaddress {mac_address}rP   )copyupdaterJ   ri   rI   )r3   rS   rs   rv   rU   rw   substlinesrP   rP   rQ   _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isfilerG   rematch).0r   expanded_pathrP   rQ   
<listcomp>   s    z*_parse_deb_config_data.<locals>.<listcomp>sourcerrt   _source_pathTr3      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodrb   ether   zdns-rW   z
dns-searchsearchzdns-nameserversnameserversbridge_rd    bridge_portsports	bridge_hwmacr^   pathcostr_   portpriozbond-rc   F)
splitlinesstrip
startswithsplitr   r   rG   globlistdirr	   load_text_fileabspath_parse_deb_config_datadirnameopenreadr
   NET_CONFIG_OPTIONSNET_CONFIG_COMMANDSrI   NET_CONFIG_BRIDGE_OPTIONSrH   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_optionrP   r   rQ   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}   rP   rP   rQ   convert_eni_dataX  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\   rb   ra   r   )_orig_eni_namer]   rt   rU   manualstaticr   )r   r!   r   rW   )r   r   dns_r\   r   c                    s   g | ]} | qS rP   rP   )r   ddevsrP   rQ   r         z._ifaces_to_net_config_data.<locals>.<listcomp>)versionconfig)r@   	partitionri   rI   rK   )r}   r[   datadevnamedtyper4   copy_keynrP   r   rQ   r   `  s6   

r   addr_or_netc                 C   s$   |s
t | p	t| S t| pt| S N)r   r   r   r   )r   r5   rP   rP   rQ   rF     s   rF   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)ri   r   r   r   )selfr   rP   rP   rQ   __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   ri   rI   )r   r   r   rL   
use_ip_cmdr   r   mappingor_true
default_gw
route_linekrP   rP   rQ   _render_route  sn   



zRenderer._render_routeFr3   rs   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-wolrS   r]   rZ   rU   rt   rY   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[   rP   )r   r   )r3   rP   rQ   r   (  s    z*Renderer._render_iface.<locals>.<listcomp>aliasr9   r:   c                 3   s    | ]
}|  |fV  qd S r   )ri   )r   r   )r4   rP   rQ   	<genexpr>3  s
    
z)Renderer._render_iface.<locals>.<genexpr>)r9   r:   rs   routesr   r   z    )r   r[   inet6)r[   rU   rZ   rY   )r]   r   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )rS   rT   rP   )rx   deepcopyr   KeyErrorpopri   	enumerater   dictrB   r|   rR   rr   r   rI   extendr   clearrJ   )r   r3   rs   sectionsr\   r   ethernet_wolrW   routes6rS   rT   subnet_inetr5   dns_presentr{   r   ipv6_networkrP   )r3   r4   rQ   _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   rY   r   rt   )r]   rU   )r[   r]   rY   r\   r[   r\   r   r:   r9   r   r      r      )r   r   re   rc   rd   rf   c                    s    | d  | d fS )Nr]   r[   rP   )r   orderrP   rQ   <lambda>  r   z-Renderer._render_interfaces.<locals>.<lambda>)rN   r   z

c                 S   s   g | ]}d  |qS )
)rG   )r   srP   rP   rQ   r     s    z/Renderer._render_interfaces.<locals>.<listcomp>r  )iter_interfacesri   rx   r   r:   dns_searchdomainsr  r  rK   iter_routesrI   r   rG   )	r   r  rs   r   r3   r   searchdomainsr  r   rP   r  rQ   _render_interfacesp  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)rL   preserve_mode)r   target_pathr   r	   
ensure_dirr   r   r   r   
write_filer  r   _render_persistent_net)r   r  r  r  fpeniheadernetrulesrP   rP   rQ   render_network_state  s   
zRenderer.render_network_stater   )r   F)NN)__name__
__module____qualname____doc__r   r  r   strr   r   rj   r  r   r  r#  rP   rP   rP   rQ   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enirP   rP   rQ   	available  s   r0  r$  )/rx   rD   r   loggingr   r   
contextlibr   typingr   r   r   r   	cloudinitr   r   r	   cloudinit.netr
   r   r   r   r   r   r   cloudinit.net.network_stater   	getLoggerr%  rk   r   r   r   r  rj   r)  rR   intrr   r|   r   timedr   r   rF   r   r0  rP   rP   rP   rQ   <module>   sj   $	
	,
C

 )  .