U
    ӇgS                     @   s0  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 d dl	m
Z
mZmZ d dlmZmZmZ d dlmZ eeZddd	d
ddgZddddddddgZdddddddddddd d!d"d#d$d%d&d'd(d)d*d+gZd,d- Zd.d/ Zd>d1d2Zd3d4 Ze
d5d6d7 Zd8d9 ZG d:d; d;ej Z d?d<d=Z!dS )@    N)suppress)Optional)performancesubputil)ParserErrorrenderersubnet_is_ipv6)NetworkStatezpre-upupzpost-updownzpre-downz	post-downZbridge_ageingZbridge_bridgeprioZ	bridge_fdZbridge_gcinitZbridge_helloZbridge_maxageZbridge_maxwaitZ
bridge_stpaddressnetmask	broadcastnetworkmetricgatewayZpointtopointZmediamtuZhostnameZ
leasehoursZ	leasetimeZvendorZclientZbootfileserverZhwaddrZproviderframeZnetnumZendpointZlocalZttlc              
   C   s   g }ddddddddd	d
g
}|  D ]t\}}|dkr6q$|dkrRd|d |d f }|r$||kr$t|trrd|}d|kr|dd}|d|| q$t|S )Nr   r   r   r   r   Zpointopointr   Zscope
dns_searchdns_nameserversz%s/%sprefix _-    {0} {1})items
isinstancelistjoinreplaceappendformatsorted)ifacesubnetcontentZ	valid_mapkeyvalue r*   3/usr/lib/python3/dist-packages/cloudinit/net/eni.py_iface_add_subnetA   s0    

r,   c           
   
   C   s  |dkrg S g }dddddddd	d
g	}dddg}ddi}| d
 dkrN| d |  D ]\}}t|trx| | rtdnd}|rV||krqV|dkr|r||krVtd| d || qV||kr|D ]}	| d||||	 qqVt|trd	|}| d|||| qVt
|S )Nr   controlZ	device_idZdriverindexinetmodenamesubnetstypebridge_pathcostbridge_portprioZbridge_waitportmac_address	hwaddress)bondbridge
infinibandvlanZonZoffr   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.r   r   )r"   r   r   boolLOGZwarningr#   getr   r    r$   )
r%   r.   ipv4_subnet_mtur'   Z
ignore_mapZmultiline_keysrenamesr(   r)   vr*   r*   r+   _iface_add_attrs_   sT    



rB   Fc                 C   s   | d }| d }|dkrd}n|dkr0d| }nd| }|   }|||d djf |d	jf |g}|r| d
r|djf | |S )Nr1   r-   auto)Zhotplugzallow-z
# control-)fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}r6   z    hwaddress {mac_address})copyupdater#   r>   r"   )r%   r.   render_hwaddressrD   r-   rE   Zsubstlinesr*   r*   r+   _iface_start_entry   s    


rJ   c                    s4  d}|  D ]}| }|dr&q|d}|d }|dkr|d }|ds`tj||}t|D ]Z t }	 fdd	|	D }	|	D ]4}
t	
|
 }tj|
}t| |tj|| qqjq|d
krH|d }|dstj||}t|D ]H t d}|  }W 5 Q R X tj }t| |tj|| qq|dkr|dd D ](}|| krxd|i| |< d| | d< q^q|dkr|dd \}}}|| krd|i| |< nd| | krtd||f || | d< || | d< |}q|dkr2|d dkr|d }n|d }|| | d< q|tkrN|d | | |< q|tkr|| | krrg | | |< | | | d|dd  q|drFd| | kri | | d< |dkr g | | d d< |dd D ]}| | d d | qnD|dkrg | | d d< |dd D ]}| | d d | q&q|drd| | krli | | d< |tkr|ddd}|d | | d |< q|d krg | | d d!< |dd D ]}| | d d! | qn|d"kr*|d  d#kr|d | | d d#< n|d | | d d#< n|d$krtd%| | d krVi | | d d%< |d | | d d% |d < nH|d&krd'| | d kri | | d d'< |d | | d d' |d < q|d(rd)| | kri | | d)< |d(dd}|d | | d) |< q|  D ] }d| | krd*| | d< qd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 | ]8}t jt j |rtd |dk	rt j |qS )z^[a-zA-Z0-9_-]+$N)ospathisfiler    rematch).0rO   Zexpanded_pathr*   r+   
<listcomp>   s   z*_parse_deb_config_data.<locals>.<listcomp>sourcerrC   Z_source_pathTr%      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodr7   Zether   zdns-dnsz
dns-searchsearchzdns-nameserversnameserversZbridge_r9    Zbridge_portsZportsZ	bridge_hwZmacr4   Zpathcostr5   Zportpriozbond-r8   F)
splitlinesstrip
startswithsplitrN   rO   r    globlistdirr   Zload_text_fileabspath_parse_deb_config_datadirnameopenreadr   NET_CONFIG_OPTIONSNET_CONFIG_COMMANDSr"   NET_CONFIG_BRIDGE_OPTIONSr!   lowerkeys)ifacescontentssrc_dirsrc_pathZcurriflinerc   ZoptionZparsed_src_dirZdir_contentsentryZsrc_dataZ	abs_entryZnew_src_pathfpZabs_pathr%   rY   rZ   valZdomainr   Zbridge_optionZbond_optionr*   rT   r+   rg      s    




  
 


  
 

 

 




"







rg   zConverting eni datac                 C   s   i }t || ddd t|S )z=Return a network config representation of what is in eni_dataN)rr   rs   )rg   _ifaces_to_net_config_data)Zeni_datarp   r*   r*   r+   convert_eni_data7  s    ry   c                    s8  i  |   D ]\}}|dd }| krf|dkr:d}nd}||g d |< d|krf|d  | d< ||d	 d
}|drd|d< nd|d< |d	dkr|d |d< dD ]}||kr|| ||< qd|krdD ]0}||d kr|d | r|d | |d| < qֈ | 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)r3   r1   r2   r7   r6   rZ   )Z_orig_eni_namer3   rC   r-   Zmanualstaticr   )r   r   r   r\   )r^   r]   Zdns_r2   rL   c                    s   g | ]} | qS r*   r*   )rS   dZdevsr*   r+   rU   e  s     z._ifaces_to_net_config_data.<locals>.<listcomp>)versionconfig)r   	partitionr>   r"   r$   )rp   r1   dataZdevnameZdtyper&   Zcopy_keynr*   r   r+   rx   ?  s2    


rx   c                   @   sP   e Zd ZdZdddZdddZdd	d
ZdddZdee	e
 ddddZdS )Rendererz@Renders network information in a /etc/network/interfaces format.Nc                 C   s6   |si }| dd| _| dd | _| dd| _d S )Neni_pathetc/network/interfaces
eni_headernetrules_pathz(etc/udev/rules.d/70-persistent-net.rules)r>   r   r   r   )selfr   r*   r*   r+   __init__k  s     zRenderer.__init__r_   c                 C   sL  g }|d }|d }d}ddd}d}|d d	krD|d
 d	krDd}n|d dkr`|d dkr`d}d}	dD ]}
|rz|
dkrzqh|
dkr|	d|||
 ||
 f 7 }	qh|
|krh|
dkr
d||
 kr|	d7 }	n | ddkr|	d7 }	n|	d7 }	d|kr"|	d||
 |d f 7 }	qh|	d||
 ||
 f 7 }	qh|||	 |  |||	 |  |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
        zpost-up route addzpre-down route delz || trueZgwr   )r   r   r_   r   z0.0.0.0r   z defaultz::r   r   z -A inet6 default)r   r   r   r   z%s %s %srz   z	 -A inet6    z -hostz -netz %s/%sz %s %s)r>   r"   )r   routeindentr'   r   r   Zor_truemappingZ
default_gwZ
route_linekr*   r*   r+   _render_routet  s>    



zRenderer._render_routeFc              	      sZ  t   tt  d W 5 Q R X g } di } dd } dd }|r\d d< |rt|D ]\}}d }	| d< |d  d	< |d
d d
< d}
t|r|
d7 }
n
|d}	|
 d< |d dks|d dks|d dkrd d	< |d k	r~|rdnd d< nn|d dkr0d d	< d d< nN|d dkrPd d	< d d< n.t|r~d d	< |d k	r~|rvdnd d< d fdd|D krd d
< tt	 ||dt
 | t ||	 }|dg D ]}|| j|dd  q|| qjnZg }d! ksd" kr&|d#jf   |d$jf   |t d%d d& || |S )'NZ	config_idr2   z	accept-raZ	wakeonlangzethernet-wolr.   r3   r0   r-   rC   r/   6r   Zdhcp4Zdhcp6zipv6_dhcpv6-statefulZdhcp10	accept_razipv6_dhcpv6-statelessZ
ipv6_slaacr~   Tc                    s   g | ]}d  d  |kqS )zauto %sr1   r*   )rS   rt   r%   r*   r+   rU     s    z*Renderer._render_iface.<locals>.<listcomp>aliasrH   Zroutesz    )r   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )r.   r?   )rF   deepcopyr   KeyErrorpopr>   	enumerater	   r   rJ   r,   rB   extendr   r"   r#   )r   r%   rH   sectionsr2   r   Zethernet_wolr.   r&   r?   Zsubnet_inetrI   r   r*   r   r+   _render_iface  s    












  

zRenderer._render_ifacec           	         s  ddddddgd}|  D ]}|ddkrt|}q|j}|r\d	||d
 d d< |j}|r|d	||d
 d d< ddddddd g }|| | t	|   fdddD ](}|ddkrq|| j||d q|
 D ]}|| | qddd |D d S )z1Given state, emit etc/network/interfaces content.r{   r}   r/   r|   rC   )r3   r-   )r1   r3   r/   r2   r1   r   r2   r   r   r   rL   r[      rX      )r|   r}   r:   r8   r9   r;   c                    s    | d  | d fS )Nr3   r1   r*   )r   orderr*   r+   <lambda>       z-Renderer._render_interfaces.<locals>.<lambda>)r(   r   z

c                 S   s   g | ]}d  |qS )
)r    )rS   sr*   r*   r+   rU   ,  s     z/Renderer._render_interfaces.<locals>.<listcomp>r   )Ziter_interfacesr>   rF   r   r   r    Zdns_searchdomainsr   r   r$   Ziter_routesr"   r   )	r   network_staterH   r{   r%   r^   Zsearchdomainsr   r   r*   r   r+   _render_interfaces  sF    
	

zRenderer._render_interfaces)r   	templatesreturnc                 C   s   t || j}ttj| | jr,| jnd}t	||| 
|  | jrt || j}ttj| tj	|| |dd d S )Nr_   T)r'   Zpreserve_mode)r   target_pathr   r   Z
ensure_dirrN   rO   rh   r   Z
write_filer   r   Z_render_persistent_net)r   r   r   targetZfpeniheaderZnetrulesr*   r*   r+   render_network_state.  s    zRenderer.render_network_state)N)r_   )F)F)NN)__name__
__module____qualname____doc__r   r   r   r   r
   r   dictr   r*   r*   r*   r+   r   h  s   
	
4
R
7  r   c                 C   sR   dddg}ddg}|D ]}t j||| ds dS qt | d}tj|sNdS d	S )
NZifqueryZifupZifdownz/sbinz	/usr/sbin)r]   r   Fr   T)r   Zwhichr   rN   rO   rP   )r   Zexpectedr]   pZenir*   r*   r+   	availableC  s    
r   )F)N)"rF   rd   ZloggingrN   rQ   
contextlibr   typingr   Z	cloudinitr   r   r   Zcloudinit.netr   r   r	   Zcloudinit.net.network_stater
   Z	getLoggerr   r=   rl   rm   rk   r,   rB   rJ   rg   Ztimedry   rx   r   r   r*   r*   r*   r+   <module>   sz   

<
 
) \