o
    x[h„S  ã                   @   sò   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g d¢Zg d¢Zg d	¢Zd
d„ Zdd„ Zddd„Zdd„ Ze
 d¡dd„ ƒZdd„ 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)Ú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Úttlc                 C   s’   g }g d¢}|  ¡ D ]:\}}|dkrq
|dkr!d|d |d f }|rD||v rDt|tƒr1d |¡}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Úprefixú Ú_ú-ú    {0} {1})ÚitemsÚ
isinstanceÚlistÚjoinÚreplaceÚappendÚformatÚsorted)ÚifaceÚsubnetÚcontentÚ	valid_mapÚkeyÚvalue© rC   ú3/usr/lib/python3/dist-packages/cloudinit/net/eni.pyÚ_iface_add_subnetA   s   

€rE   c           
   
   C   s  |dkrg S g }g d¢}g d¢}ddi}| d dvr|  d¡ |  ¡ D ][\}}t|tƒr4| | r2dnd	}|r:||v r;q#|d
krP|rP||krOt d| d ||¡ q#||v rg|D ]}	|  d | ||¡|	¡¡ qVq#t|tƒrqd 	|¡}|  d | ||¡|¡¡ q#t
|ƒS )Nr   )	ÚcontrolÚ	device_idÚdriverÚindexÚinetÚmodeÚnameÚsubnetsÚtype)Úbridge_pathcostÚbridge_portprioÚbridge_waitportÚmac_addressÚ	hwaddressrN   )ÚbondÚbridgeÚ
infinibandÚvlanÚonÚoffr   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.rL   r4   r1   )r:   r5   r6   ÚboolÚLOGÚwarningr;   Úgetr7   r8   r<   )
r=   rI   Úipv4_subnet_mtur?   Ú
ignore_mapÚmultiline_keysÚrenamesrA   rB   ÚvrC   rC   rD   Ú_iface_add_attrs_   s<   

û

rc   Fc                 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 )NrL   rF   Úauto)Úhotplugzallow-z
# control-)ÚfullnameÚcverbz{cverb} {fullname}ziface {fullname} {inet} {mode}rR   z    hwaddress {mac_address}rC   )ÚcopyÚupdater;   r]   r:   )r=   rI   Úrender_hwaddressrf   rF   rg   ÚsubstÚlinesrC   rC   rD   Ú_iface_start_entry›   s   
þrm   c              
      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 s•w   Y  tj ˆ ¡}t| |tj |¡|ƒ q}q|dkrË|dd… D ]}|| vrÃd|i| |< d| | d< q·q|dk�r|dd… \}}}|| vräd|i| |< nd| | v ròt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¡�r§d| | v�rai | | d< |dk�r„g | | d d< |dd… D ]}| | d d  |¡ �qtq|dk�r¦g | | d d< |dd… D ]}| | d d  |¡ �q—q| d¡�rbd| | v�rºi | | d< |tv �rÑ| ddd¡}|d | | d |< q|d k�rôg | | d d!< |dd… D ]}| | d d!  |¡ �qäq|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(¡�r†d)| | v�rui | | d)< | d(dd¡}|d | | d) |< q|  ¡ D ]}d| | v�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ú#r1   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Úisfiler8   ÚreÚmatch)Ú.0rr   ©Úexpanded_pathrC   rD   Ú
<listcomp>Ë   s    üüz*_parse_deb_config_data.<locals>.<listcomp>ÚsourceÚrrd   Ú_source_pathTr=   é   Úfamilyz:Interface %s can only be defined once. Re-defined in '%s'.ÚmethodrS   Úetheré   zdns-Údnsz
dns-searchÚsearchzdns-nameserversÚnameserversÚbridge_rU   Ú Úbridge_portsÚportsÚ	bridge_hwÚmacrO   ÚpathcostrP   Úportpriozbond-rT   F)Ú
splitlinesÚstripÚ
startswithÚsplitrq   rr   r8   ÚglobÚlistdirr   Úload_text_fileÚabspathÚ_parse_deb_config_dataÚdirnameÚopenÚreadr   ÚNET_CONFIG_OPTIONSÚNET_CONFIG_COMMANDSr:   ÚNET_CONFIG_BRIDGE_OPTIONSr9   ÚlowerÚkeys)ÚifacesÚcontentsÚsrc_dirÚsrc_pathÚcurrifÚliner�   ÚoptionÚparsed_src_dirÚdir_contentsÚentryÚsrc_dataÚ	abs_entryÚnew_src_pathÚfpÚabs_pathr=   r~   r   ÚvalÚdomainr$   Úbridge_optionÚbond_optionrC   rw   rD   r•   ³   sê   




þÿýö
ÿÿüþú

þÿÿ



"
ÿ
€

ÿ


€€€þr•   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)r    r¡   )r•   Ú_ifaces_to_net_config_data)Úeni_datarž   rC   rC   rD   Úconvert_eni_data7  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 r‚dD ]}||d v r�|d | r�|d | |d| < qiˆ | d  |¡ qd‡ fdd„tˆ ƒD ƒdœS )zÂReturn 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)rN   rL   rM   rS   rR   r   )Ú_orig_eni_namerN   rd   rF   ÚmanualÚstaticr   )r   r   r   r‚   )r„   rƒ   Údns_rM   ro   c                    s   g | ]}ˆ | ‘qS rC   rC   )rv   Úd©ÚdevsrC   rD   ry   e  ó    z._ifaces_to_net_config_data.<locals>.<listcomp>)ÚversionÚconfig)r5   Ú	partitionr]   r:   r<   )rž   rL   ÚdataÚdevnameÚdtyper>   Úcopy_keyÚnrC   r½   rD   r±   ?  s6   

€€r±   c                   @   sX   e Zd ZdZddd„Zddd„Zdd	d
„Zddd„Z		ddede	e
 ddf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Á   rC   rC   rD   Ú__init__k  s   
ÿzRenderer.__init__r†   c                 C   sH  g }|d }|d }d}dddœ}d}|d d	kr"|d
 d	kr"d}n|d dkr0|d dkr0d}d}	dD ][}
|r=|
dkr=q4|
dkrO|	d|||
 ||
 f 7 }	q4|
|v r�|
dkrƒd||
 v rb|	d7 }	n|  d¡dkrn|	d7 }	n|	d7 }	d|v r‚|	d||
 |d f 7 }	q4|	d||
 ||
 f 7 }	q4| ||	 | ¡ | ||	 | ¡ |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 || trueÚgwr   )r   r   r†   r   z0.0.0.0r   z defaultz::r0   r   z -A inet6 default)r   r   r   r   z%s %s %sr´   z	 -A inet6é    z -hostz -netz %s/%sz %s %s)r]   r:   )rÍ   ÚrouteÚindentr?   r   r   Úor_trueÚmappingÚ
default_gwÚ
route_lineÚkrC   rC   rD   Ú_render_routet  sB   þ

€€zRenderer._render_routeFc                    s`  t  ˆ ¡‰ ttƒ� ˆ  d¡ W d   ƒ n1 sw   Y  g }ˆ  di ¡}ˆ  dd ¡}ˆ  dd ¡}|r8dˆ d< |rýt|ƒD ]¼\}}d }	|ˆ d< |d ˆ d	< | d
d¡ˆ d
< d}
t|ƒra|
d7 }
n| d¡}	|
ˆ d< |d dks||d dks||d dkr�dˆ d	< |d urŒ|rˆdndˆ d< n2|d dkrœdˆ d	< dˆ d< n#|d dkr«dˆ d	< dˆ d< nt|ƒr¿dˆ d	< |d ur¿|r»dndˆ d< d‡ fdd„|D ƒv rÎdˆ d
< tt	ˆ ||d�t
ˆ |ƒ tˆ ||	ƒ ƒ}| dg ¡D ]}| | j|dd �¡ qè| |¡ q>|S g }d!ˆ v �s	d"ˆ v �r| d#jd'i ˆ ¤Ž¡ | d$jd'i ˆ ¤Ž¡ | tˆ d%d d&�¡ | |¡ |S )(NÚ	config_idrM   z	accept-raÚ	wakeonlanÚgzethernet-wolrI   rN   rK   rF   rd   rJ   Ú6r   Údhcp4Údhcp6zipv6_dhcpv6-statefulÚdhcpÚ1Ú0Ú	accept_razipv6_dhcpv6-statelessÚ
ipv6_slaacrº   Tc                    s   g | ]
}d ˆ d  |v ‘qS )zauto %srL   rC   )rv   r£   ©r=   rC   rD   ry   Þ  s    ÿz*Renderer._render_iface.<locals>.<listcomp>Úalias©rj   Úroutesz    )rÒ   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )rI   r^   rC   )rh   Údeepcopyr   ÚKeyErrorÚpopr]   Ú	enumerater	   r7   rm   rE   rc   ÚextendrØ   r:   r;   )rÍ   r=   rj   ÚsectionsrM   râ   Úethernet_wolrI   r>   r^   Úsubnet_inetrl   rÑ   rC   rä   rD   Ú_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rgq]| | j||d�¡ q]| 
¡ D ]
}| |  |¡¡ qvd dd„ |D ƒ¡d S )z1Given state, emit etc/network/interfaces content.rµ   r·   rJ   r¶   rd   )rN   rF   )rL   rN   rJ   rM   rL   r1   rM   r   r/   r.   ro   r�   é   r}   é   )r¶   r·   rV   rT   rU   rW   c                    s   ˆ | d  | d fS )NrN   rL   rC   )r×   ©ÚorderrC   rD   Ú<lambda>   r¿   z-Renderer._render_interfaces.<locals>.<lambda>)rA   ræ   z

c                 S   s   g | ]}d   |¡‘qS )Ú
)r8   )rv   ÚsrC   rC   rD   ry   ,  s    z/Renderer._render_interfaces.<locals>.<listcomp>rö   )Úiter_interfacesr]   rh   rè   r/   r8   Údns_searchdomainsrì   rð   r<   Úiter_routesr:   rØ   )	rÍ   Únetwork_staterj   rµ   r=   r„   Úsearchdomainsrí   rÑ   rC   ró   rD   Ú_render_interfacesú  sH   
ü
€ú	

þÿzRenderer._render_interfacesrû   Ú	templatesÚreturnc                 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)r?   Úpreserve_mode)r   Útarget_pathrÉ   r   Ú
ensure_dirrq   rr   r–   rË   Ú
write_filerý   rÌ   Ú_render_persistent_net)rÍ   rû   rþ   ÚtargetÚfpeniÚheaderÚnetrulesrC   rC   rD   Úrender_network_state.  s   
ýýzRenderer.render_network_state©N)r†   ©F)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÎ   rØ   rð   rý   r
   r   Údictr	  rC   rC   rC   rD   rÈ   h  s    

	
4
R7üþýûrÈ   c                 C   sP   g d¢}ddg}|D ]}t j||| d�s dS q
t  | d¡}tj |¡s&dS dS )N)ÚifqueryÚifupÚifdownz/sbinz	/usr/sbin)rƒ   r  FrÊ   T)r   Úwhichr  rq   rr   rs   )r  Úexpectedrƒ   ÚpÚenirC   rC   rD   Ú	availableC  s   ÿr  r  r
  )"rh   r‘   Úloggingrq   rt   Ú
contextlibr   Útypingr   Ú	cloudinitr   r   r   Úcloudinit.netr   r   r	   Úcloudinit.net.network_stater
   Ú	getLoggerr  r[   rš   r›   r™   rE   rc   rm   r•   Útimedr³   r±   rÈ   r  rC   rC   rC   rD   Ú<module>   s2   
	
< 
) \