U
    AdAV                     @   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dAd1d2Zd3d4 Zd5d6 Zd7d8 Zd9d: ZG d;d< d<ejZdBd=d>ZdCd?d@Z dS )D    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 ]v\}}|dkr6q$|dkrRd|d |d f }|r$||kr$t|tkrtd|}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type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krz| | rvdnd}|rV||krqV|dkr|r||krVtd| d || qV||kr|D ]}	| d||||	 qqVt|tkrd	|}| d|||| qVt
|S )Nr   controlZ	device_idZdriverindexinetmodenamesubnetsr   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    

r@   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}r4   z    hwaddress {mac_address})copyupdater"   r<   r!   )r$   r-   render_hwaddressrB   r,   rC   Zsubstlinesr)   r)   r*   _iface_start_entry   s    


rH   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).0rM   Zexpanded_pathr)   r*   
<listcomp>   s   z*_parse_deb_config_data.<locals>.<listcomp>rsourcerA   Z_source_pathTr$      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodr5   Zether   zdns-dnsz
dns-searchsearchzdns-nameserversnameserversZbridge_r7    Zbridge_portsZportsZ	bridge_hwZmacr2   Zpathcostr3   Zportpriozbond-r6   F)
splitlinesstrip
startswithsplitrL   rM   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linera   ZoptionZparsed_src_dirZdir_contentsentryfpZsrc_dataZ	abs_entryZnew_src_pathabs_pathr$   rW   rX   valZdomainr   Zbridge_optionZbond_optionr)   rR   r*   rg      s    




  
 

  
 


 

 




"







rg   c              	   C   sL   i }t | d}|  }W 5 Q R X tj| }t||tj|| |S )z+Parses a debian network configuration file.rT   )rd   re   r_   rL   rM   rf   rg   rh   )rM   rn   rt   ro   ru   r)   r)   r*   parse_deb_config7  s      
 rw   c                 C   s   i }t || d d d t|S )N)rp   rq   )rg   _ifaces_to_net_config_data)Zeni_datarn   r)   r)   r*   convert_eni_dataC  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("/etc/network/interfaces")
    config = ifaces_to_net_config_data(ifaces)
    state = parse_net_config_data(config).:r   loloopbackphysical)r   r0   r1   r5   r4   rX   )Z_orig_eni_namer   rA   r,   Zmanualstaticr   )r   r   r   rZ   )r\   r[   Zdns_r1   rJ   c                    s   g | ]} | qS r)   r)   )rQ   dZdevsr)   r*   rS   p  s     z._ifaces_to_net_config_data.<locals>.<listcomp>)versionconfig)r   	partitionr<   r!   r#   )rn   r0   dataZdevnameZdtyper%   Zcopy_keynr)   r   r*   rx   J  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__v  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_route  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-   r   r/   r,   rA   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)   )rQ   rr   r$   r)   r*   rS     s    z*Renderer._render_iface.<locals>.<listcomp>aliasrF   Zroutesz    )r   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )r-   r=   )r<   pop	enumerater   r   rH   r+   r@   extendr   r!   r"   )r   r$   rF   sectionsr1   r   Zethernet_wolr-   r%   r=   Zsubnet_inetrG   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|   rA   )r   r,   )r0   r   r.   r1   r0   r   r1   r   r   r   rJ   rY      rV      )r|   r}   r8   r6   r7   r9   c                    s    | d  | d fS )Nr   r0   r)   )r   orderr)   r*   <lambda>&      z-Renderer._render_interfaces.<locals>.<lambda>)r'   r   z

c                 S   s   g | ]}d  |qS )
)r   )rQ   sr)   r)   r*   rS   2  s     z/Renderer._render_interfaces.<locals>.<listcomp>r   )Ziter_interfacesr<   rD   deepcopyr   r   Zdns_searchdomainsr   r   r#   Ziter_routesr!   r   )	r   network_staterF   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r~t || j}ttj| t	|| | d S )Nr]   )r   target_pathr   r   Z
ensure_dirrL   rM   rh   r   Z
write_filer   r   Z_render_persistent_net)r   r   r   targetZfpeniheaderZnetrulesr)   r)   r*   render_network_state4  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   s  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   rF   r   r   ro   r)   r)   r*   network_state_to_eniG  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   rL   rM   rN   )r   Zexpectedr[   pZenir)   r)   r*   	available[  s    
r   )F)NF)N)!rD   rb   rL   rO   typingr   Z	cloudinitr   Zloggingr   r   Zcloudinit.netr   r   r   Zcloudinit.net.network_stater	   Z	getLoggerr   r;   rj   rk   ri   r+   r@   rH   rg   rw   ry   rx   r   r   r   r)   r)   r)   r*   <module>   sz   

<
 ) U
