o
    w7e: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g dZg dZg d	Zd
d Zdd ZdddZdd Zdd Zdd ZG dd dejZdddZdddZdS )     N)Optional)log)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 rB   3/usr/lib/python3/dist-packages/cloudinit/net/eni.py_iface_add_subnet@   s   

rD   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	hwaddressrM   )bondbridge
infinibandvlanonoffr   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.rK   r3   r0   )r9   r4   r5   boolLOGwarningr:   getr6   r7   r;   )
r<   rH   ipv4_subnet_mtur>   
ignore_mapmultiline_keysrenamesr@   rA   vrB   rB   rC   _iface_add_attrs^   s<   



rb   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 )NrK   rE   auto)hotplugzallow-z
# control-)fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}rQ   z    hwaddress {mac_address}rB   )copyupdater:   r\   r9   )r<   rH   render_hwaddressre   rE   rf   substlinesrB   rB   rC   _iface_start_entry   s   
rl   c                    sf  d}|  D ]}| }|drq|d}|d }|dkrx|d }|ds0tj||}t|D ]A t }	 fdd	|	D }	|	D ].}
t	|
d
}|
  }W d   n1 s_w   Y  tj|
}t| |tj|| qGq5q|dkr|d }|dstj||}t|D ]. t	 d
}|
  }W d   n1 sw   Y  tj }t| |tj|| qq|dkr|dd D ]}|| vrd|i| |< d| | d< qq|dkr|dd \}}}|| vrd|i| |< nd| | v rtd||f || | d< || | d< |}q|dkr2|d dkr'|d }n|d }|| | d< q|tv r@|d | | |< q|tv rc|| | vrRg | | |< | | | d|dd  q|drd| | vrvi | | d< |dkrg | | d d< |dd D ]}| | d d | qq|dkrg | | d d< |dd D ]}| | d d | qq|drwd| | vri | | d< |tv r|ddd}|d | | d |< q|d kr	g | | 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rRd%| | d vrCi | | d d%< |d | | d d% |d < q|d&krvd'| | d vrhi | | d d'< |d | | d d' |d < q|d(rd)| | vri | | 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 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#r0   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isfiler7   rematch).0rq   expanded_pathrB   rC   
<listcomp>   s    z*_parse_deb_config_data.<locals>.<listcomp>rsourcerc   _source_pathTr<      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodrR   ether   zdns-dnsz
dns-searchsearchzdns-nameserversnameserversbridge_rT    bridge_portsports	bridge_hwmacrN   pathcostrO   portpriozbond-rS   F)
splitlinesstrip
startswithsplitrp   rq   r7   globlistdiropenreadabspath_parse_deb_config_datadirnamer   NET_CONFIG_OPTIONSNET_CONFIG_COMMANDSr9   NET_CONFIG_BRIDGE_OPTIONSr8   lowerkeys)ifacescontentssrc_dirsrc_pathcurrifliner   optionparsed_src_dirdir_contentsentryfpsrc_data	abs_entrynew_src_pathabs_pathr<   r}   r~   valdomainr#   bridge_optionbond_optionrB   rv   rC   r      s   











"






r   c                 C   s   i }t || d d d t|S )N)r   r   )r   _ifaces_to_net_config_data)eni_datar   rB   rB   rC   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 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)rM   rK   rL   rR   rQ   r~   )_orig_eni_namerM   rc   rE   manualstaticr   )r   r   r   r   )r   r   dns_rL   rn   c                    s   g | ]} | qS rB   rB   )ru   ddevsrB   rC   rx   d      z._ifaces_to_net_config_data.<locals>.<listcomp>)versionconfig)r4   	partitionr\   r9   r;   )r   rK   datadevnamedtyper=   copy_keynrB   r   rC   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   rB   rB   rC   __init__j  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rd||
 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::r/   r   z -A inet6 default)r   r   r   r   z%s %s %sr   z	 -A inet6    z -hostz -netz %s/%sz %s %s)r\   r9   )r   routeindentr>   r
   r   or_truemapping
default_gw
route_linekrB   rB   rC   _render_routes  sB   

zRenderer._render_routeFc                    s   g }  di } dd } dd }|rd d< |rt|D ]\}}d }	| d< |d  d< | d	d
 d	< d}
t|rC|
d7 }
n| d}	|
 d< |d dks^|d dks^|d dkrod d< |d urn|rjdnd d< n2|d dkr~d
 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	< tt ||dt | t ||	 }| dg D ]}|| j	|dd q|
| q |S g }d  v sd! v r|
d"jd&i   |
d#jd&i   |t d$d d% |
| |S )'NrL   z	accept-ra	wakeonlangzethernet-wolrH   rM   rJ   rE   rc   rI   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 %srK   rB   )ru   r   r<   rB   rC   rx     s    z*Renderer._render_iface.<locals>.<listcomp>aliasri   routesz    )r   zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   )rH   r]   rB   )r\   pop	enumerater   r6   rl   rD   rb   extendr   r9   r:   )r   r<   ri   sectionsrL   r   ethernet_wolrH   r=   r]   subnet_inetrk   r   rB   r   rC   _render_iface  sx   





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   rI   r   rc   )rM   rE   )rK   rM   rI   rL   rK   r0   rL   r   r.   r-   rn   r      r|      )r   r   rU   rS   rT   rV   c                    s    | d  | d fS )NrM   rK   rB   )r   orderrB   rC   <lambda>  r   z-Renderer._render_interfaces.<locals>.<lambda>)r@   r   z

c                 S   s   g | ]}d  |qS )
)r7   )ru   srB   rB   rC   rx   &  s    z/Renderer._render_interfaces.<locals>.<listcomp>r   )iter_interfacesr\   rg   deepcopyr.   r7   dns_searchdomainsr   r   r;   iter_routesr9   r   )	r   network_stateri   r   r<   r   searchdomainsr   r   rB   r   rC   _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_dirrp   rq   r   r   
write_filer   r   _render_persistent_net)r   r   r   targetfpeniheadernetrulesrB   rB   rC   render_network_state(  s   
zRenderer.render_network_stateN)r   F)NN)__name__
__module____qualname____doc__r   r   r   r   r	   r   dictr  rB   rB   rB   rC   r   g  s    

	
4
M7r   c                 C   sF   d}t ||d dd}|sd}|ds|d7 }|j| |d}|| S )Nr   )r   r   r   )r   r   r   r   )r   endswithr   )r   r  ri   r   r   r   rB   rB   rC   network_state_to_eni=  s   
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   rp   rq   rr   )r  expectedr   penirB   rB   rC   	availableQ  s   r  r  )NFr  ) rg   r   rp   rs   typingr   	cloudinitr   loggingr   r   cloudinit.netr   r   r   cloudinit.net.network_stater	   	getLoggerr  rZ   r   r   r   rD   rb   rl   r   r   r   r   r  r  rB   rB   rB   rC   <module>   s0   
	
< ) 
W