U
    Ld:U                     @   s$  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
 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d5d6 Zd7d8 ZG d9d: d:ejZd@d;d<ZdAd=d>ZdS )B    N)Optional)log)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_subnet@   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    



rA   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 )Nr0   r,   auto)Zhotplugzallow-z
# control-)fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}r5   z    hwaddress {mac_address})copyupdater"   r=   r!   )r$   r-   render_hwaddressrC   r,   rD   Zsubstlinesr)   r)   r*   _iface_start_entry   s    


rI   c                    sL  d}|  D ]}| }|dr&q|d}|d }|dkr|d }|ds`tj||}t|D ]n t }	 fdd	|	D }	|	D ]H}
t	|
d
}|
  }W 5 Q R X tj|
}t| |tj|| qqjq|dkr`|d }|dstj||}t|D ]J t	 d
}|
  }W 5 Q R X tj }t| |tj|| qq|dkr|dd D ](}|| krd|i| |< d| | d< qvq|dkr|dd \}}}|| krd|i| |< nd| | krtd||f || | d< || | d< |}q|dkrJ|d dkr4|d }n|d }|| | d< q|tkrf|d | | |< q|tkr|| | krg | | |< | | | d|dd  q|dr^d| | 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ri | | d< |tkr|ddd}|d | | d |< q|d krg | | d d!< |dd D ]}| | d d! | qn|d"krB|d  d#kr,|d | | d d#< n|d | | d d#< n|d$krd%| | d krni | | 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 configration 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).0rN   Zexpanded_pathr)   r*   
<listcomp>   s   z*_parse_deb_config_data.<locals>.<listcomp>rsourcerB   Z_source_pathTr$      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodr6   Zether   zdns-dnsz
dns-searchsearchzdns-nameserversnameserversZbridge_r8    Zbridge_portsZportsZ	bridge_hwZmacr3   Zpathcostr4   Zportpriozbond-r7   F)
splitlinesstrip
startswithsplitrM   rN   r   globlistdiropenreadabspath_parse_deb_config_datadirnamer   NET_CONFIG_OPTIONSNET_CONFIG_COMMANDSr!   NET_CONFIG_BRIDGE_OPTIONSr    lowerkeys)ifacescontentssrc_dirsrc_pathZcurriflinerb   ZoptionZparsed_src_dirZdir_contentsentryfpZsrc_dataZ	abs_entryZnew_src_pathZabs_pathr$   rX   rY   valZdomainr   Zbridge_optionZbond_optionr)   rS   r*   rh      s    




  
 

  
 


 

 




"







rh   c                 C   s   i }t || d d d t|S )N)rq   rr   )rh   _ifaces_to_net_config_data)Zeni_dataro   r)   r)   r*   convert_eni_data7  s    rx   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)r2   r0   r1   r6   r5   rY   )Z_orig_eni_namer2   rB   r,   Zmanualstaticr   )r   r   r   r[   )r]   r\   Zdns_r1   rK   c                    s   g | ]} | qS r)   r)   )rR   dZdevsr)   r*   rT   d  s     z._ifaces_to_net_config_data.<locals>.<listcomp>)versionconfig)r   	partitionr=   r!   r#   )ro   r0   dataZdevnameZdtyper%   Zcopy_keynr)   r   r*   rw   >  s2    


rw   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__j  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 %sry   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_routes  s>    



zRenderer._render_routeFc                    s,  g }  di } dd } dd }|r4d 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rd d< |d k	r|rdnd d< nn|d dkrd
 d< d d< nN|d dkr"d
 d< d d< n.t|rPd d< |d k	rP|rHdnd d< d fdd|D krpd d	< tt ||dt | t ||	 }| dg D ]}|| j	|dd q|
| qBnZg }d  ksd! kr|
d"jf   |
d#jf   |t d$d d% |
| |S )&Nr1   z	accept-raZ	wakeonlangzethernet-wolr-   r2   r/   r,   rB   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 %sr0   r)   )rR   rs   r$   r)   r*   rT     s    z*Renderer._render_iface.<locals>.<listcomp>aliasrG   Zroutesz    )r   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )r-   r>   )r=   pop	enumerater   r   rI   r+   rA   extendr   r!   r"   )r   r$   rG   sectionsr1   r   Zethernet_wolr-   r%   r>   Zsubnet_inetrH   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.rz   r|   r.   r{   rB   )r2   r,   )r0   r2   r.   r1   r0   r   r1   r   r   r   rK   rZ      rW      )r{   r|   r9   r7   r8   r:   c                    s    | d  | d fS )Nr2   r0   r)   )r   orderr)   r*   <lambda>      z-Renderer._render_interfaces.<locals>.<lambda>)r'   r   z

c                 S   s   g | ]}d  |qS )
)r   )rR   sr)   r)   r*   rT   &  s     z/Renderer._render_interfaces.<locals>.<listcomp>r   )Ziter_interfacesr=   rE   deepcopyr   r   Zdns_searchdomainsr   r   r#   Ziter_routesr!   r   )	r   network_staterG   rz   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_dirrM   rN   ri   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   g  s   
	
4
M
7  r   c                 C   sF   d}t ||d dd}|sd}|ds0|d7 }|j| |d}|| S )Nr   )r   r   r   )r   r^   r   r   )r   endswithr   )r   r   rG   r   r   rp   r)   r)   r*   network_state_to_eni=  s     
 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   rM   rN   rO   )r   Zexpectedr\   pZenir)   r)   r*   	availableQ  s    
r   )F)NF)N) rE   rc   rM   rP   typingr   Z	cloudinitr   Zloggingr   r   Zcloudinit.netr   r   r   Zcloudinit.net.network_stater	   Z	getLoggerr   r<   rk   rl   rj   r+   rA   rI   rh   rx   rw   r   r   r   r)   r)   r)   r*   <module>   sx   

<
 ) W
