
"T`%T                 @   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 d  d l	 m
 Z d  d l	 m Z d  d l	 m Z e j 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 d0 d1   Z d2 d3 d4  Z d5 d6   Z d7 d8   Z d9 d:   Z d; d<   Z Gd= d>   d> e j  Z d d2 d? d@  Z d dA dB  Z d S)C    N   )ParserError)renderer)subnet_is_ipv6)log)subp)utilz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
 } x | j    D] \ } } | d k rR q7 | d k rv d | d | d f } | r7 | | k r7 t |  t k r d j |  } d | k r | j d d  } | j d j | |   q7 Wt |  S)Nr   r   r   r   r   Zpointopointr   Zscope
dns_searchdns_nameserversz%s/%sprefix _-z    {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&   s.    	r)   c       
   	   C   s  | d k r g  Sg  } d d d d d d d d	 d
 g	 } d d d g } d d i } |  d
 d k ro | j  d  x|  j   D]\ } } t |  t k r |  | r d n d } | s| | | k r q| | d k r| r| | k r| t j d |  d | |  q| | | k rFx3 | D]+ }	 | j  d j | j | |  |	   qWq| t |  t k rgd j	 |  } | j  d j | j | |  |   q| Wt
 |  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.z    {0} {1}r   )r4   r5   r6   r7   )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_attrsD   sJ    		))r>   Fc             C   s   |  d } |  d } | d k r) d } n# | d k rB d | } n
 d | } |  j    } | j d | d | i  d	 j |   d
 j |   g } | r |  j d  r | j d j |    | S)Nr.   r*   autohotplugzallow-z
# control-fullnamecverbz{cverb} {fullname}ziface {fullname} {inet} {mode}r2   z    hwaddress {mac_address})r@   )copyupdater    r:   r   )r"   r+   render_hwaddressrA   r*   rB   Zsubstlinesr'   r'   r(   _iface_start_entry}   s    

	
rG   c                s  d } xl| j    D]^} | j   } | j d  r7 q | j d  } | d } | d k r<| d } | j d  s t j j | |  } xt j |  D]   t j    }	   f d d	   |	 D }	 xj |	 D]b }
 t	 |
 d
   } | j
   j   } Wd QRXt j j |
  } t |  | t j j |  |  q Wq Wq | d k r| d } | j d  svt j j | |  } xt j |  D]b   t	   d
   } | j
   j   } Wd QRXt j j    } t |  | t j j |  |  qWq | d k rCxs| d d  D]0 } | |  k r.d | i |  | <d |  | d <qWq | d k r| d d  \ } } } | |  k rd | i |  | <n& d |  | k rt d | | f   | |  | d <| |  | d <| } q | d k r| d d k r| d } n
 | d } | |  | d <q | t k r7| d |  | | <q | t k r| |  | k rag  |  | | <|  | | j d j | d d    q | j d  rcd |  | k ri  |  | d <| d k rg  |  | d d <x | d d  D] } |  | d d j |  qWqq| d k rqg  |  | d d <xB| d d  D] } |  | d d j |  q=Wq | j d  rd |  | k ri  |  | d <| t k r| j d d d  } | d |  | d | <qq| d  k rg  |  | d d! <x+| d d  D] } |  | d d! j |  qWqq| d" k rs| d j   d# k rZ| d |  | d d# <q| d |  | d d# <qq| d$ k rd% |  | d k ri  |  | d d% <| d |  | d d% | d <qq| d& k rqd' |  | d k ri  |  | d d' <| d |  | d d' | d <q | j d(  r d) |  | k rFi  |  | d) <| j d( d d  } | d |  | d) | <q Wx2 |  j   D]$ } d |  | k rd* |  | d <qWd 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-directoryr   /c                s^   g  |  ]T } t  j j t  j j   |   r t j d  |  d k	 r t  j j   |   q S)z^[a-zA-Z0-9_-]+$N)ospathisfiler   rematch).0rK   )expanded_pathr'   r(   
<listcomp>   s   	!z*_parse_deb_config_data.<locals>.<listcomp>rsourcer?   Z_source_pathTr"      familyz:Interface %s can only be defined once. Re-defined in '%s'.methodr3   Zether   zdns-dnsz
dns-searchsearchzdns-nameserversnameserversZbridge_r5    Zbridge_portsZportsZ	bridge_hwZmacr0   Zpathcostr1   Zportpriozbond-r4   F)
splitlinesstrip
startswithsplitrJ   rK   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liner_   ZoptionZparsed_src_dirZdir_contentsentryfpZsrc_dataZ	abs_entryZnew_src_pathabs_pathr"   rU   rV   valZdomainr   Zbridge_optionZbond_optionr'   )rP   r(   re      s    


!
	
+   !!re   c             C   sf   i  } t  |  d   } | j   j   } Wd QRXt j j |   } t | | t j j |  |  | S)z+Parses a debian network configuration file.rR   N)rb   rc   r]   rJ   rK   rd   re   rf   )rK   rl   rr   rm   rs   r'   r'   r(   parse_deb_config  s    ru   c             C   s)   i  } t  | |  d d  d d  t |  S)Nrn   ro   )re   _ifaces_to_net_config_data)Zeni_datarl   r'   r'   r(   convert_eni_data"  s    rw   c                s  i    x~|  j    D]p\ } } | j d  d } |   k r | d k rS d } n d } d | d | d g  i   | <d	 | k r | d	   | d
 <d | d | d i } | j d  r d | d <n
 d | d <| j d  d k r | d | d <x( d D]  } | | k r | | | | <q Wd | k rnxB d D]: } | | d k r0| d | r0| d | | d | <q0W  | d j |  q Wd d d   f d d   t    D i 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physicalr   r.   r/   r3   r2   Z_orig_eni_namerV   r?   r*   Zmanualstaticr   r   r   r   rX   rZ   rY   Zdns_versionr   configc                s   g  |  ] }   |  q Sr'   r'   )rO   d)devsr'   r(   rQ   P  s   	 z._ifaces_to_net_config_data.<locals>.<listcomp>)znetmaskzgatewayz	broadcast)znameserverszsearch)r   	partitionr:   r   r!   )rl   r.   dataZdevnameZdtyper#   Zcopy_keynr'   )r   r(   rv   )  s4    	
rv   c               @   sd   e  Z d  Z d Z d d d  Z d d d  Z d d	 d
  Z d d d  Z d d d d  Z d S)Rendererz@Renders network information in a /etc/network/interfaces format.Nc             C   sO   | s i  } | j  d d  |  _ | j  d d   |  _ | j  d d  |  _ d  S)Neni_pathz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   s  g  } | d } | d } d } d d d d i } d } | d d	 k ra | d
 d	 k ra d } n& | d d k r | d d k r d } d }	 xd d d g D] }
 | r |
 d k r q |
 d k r |	 d | | |
 | |
 f 7}	 q |
 | k r |
 d k rrd | |
 k r|	 d 7}	 n, | j  d  d k r=|	 d 7}	 n
 |	 d 7}	 d | k r|	 d | |
 | d f 7}	 q |	 d | |
 | |
 f 7}	 q W| j | |	 |  | j | |	 |  | 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 || truer   Zgwr   r[   r   z0.0.0.0r   z defaultz::r   r   z -A inet6 defaultz%s %s %srx   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  }   j  d i   }   j d d   }   j d d   } | rL d   d <| rjxt |  D]\ } } d  }	 |   d <| d   d <| j  d	 d
    d	 <d }
 t |  r |
 d 7}
 n | j  d  }	 |
   d <| d d k s| d d k s| d d k r6d   d <| d  k	 r| r)d n d   d <n | d d k r]d
   d <d   d <n_ | d d k rd
   d <d   d <n8 t |  rd   d <| d  k	 r| rd n d   d <d   f d d   | D k rd   d	 <t t   | d | t   |  t   | |	   } x6 | j  d g   D]" } | j |  j	 | d d  q0W| j
 |  q_ Wnv g  } d    k sd!   k r| j
 d" j      | j
 d# j      | j t   d d$ d% d   | j
 |  | S)&Nr/   z	accept-raZ	wakeonlangzethernet-wolr+   r   r-   r*   r?   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 %sr.   r'   )rO   rp   )r"   r'   r(   rQ     s   	z*Renderer._render_iface.<locals>.<listcomp>aliasrE   Zroutesr   z    zbond-masterzbond-slaveszauto {name}ziface {name} {inet} {mode}r   r;   )r:   pop	enumerater   r   rG   r)   r>   extendr   r   r    )r   r"   rE   sectionsr/   r   Zethernet_wolr+   r#   r;   Zsubnet_inetrF   r   r'   )r"   r(   _render_iface  sb    


 




 zRenderer._render_ifacec       	         s  d d d d d d d d d d d	 i g i } x8 | j    D]* } | j d  d k r: t j |  } q: W| j } | r d
 j |  | d d d <| j } | r d
 j |  | d d d <d d d d d d d d d d d d i   g  } | j |  j |   x` t	 | j    d   f d d   D]: } | j d  d k rEq'| j |  j | d |  q'Wx* | j
   D] } | j |  j |   qrWd j d d   | D  d S)z1Given state, emit etc/network/interfaces content.r.   ry   r   r{   r,   r/   rz   r*   r?   r   r   r   r   r   r6   rW   r4      r5   rT   r7      r%   c                s     |  d |  d f S)Nr   r.   r'   )r   )orderr'   r(   <lambda>  s    z-Renderer._render_interfaces.<locals>.<lambda>rE   z

c             S   s   g  |  ] } d  j  |   q S)
)r   )rO   sr'   r'   r(   rQ     s   	 z/Renderer._render_interfaces.<locals>.<listcomp>r   )Ziter_interfacesr:   rC   deepcopyr   r   Zdns_searchdomainsr   r   r!   Ziter_routesr   r   )	r   network_staterE   ry   r"   rZ   Zsearchdomainsr   r   r'   )r   r(   _render_interfaces  s8    		zRenderer._render_interfacesc             C   s   t  j | |  j  } t j t j j |   |  j r@ |  j n d } t j	 | | |  j
 |   |  j r t  j | |  j  } t j t j j |   t j	 | |  j |   d  S)Nr[   )r   target_pathr   r   Z
ensure_dirrJ   rK   rf   r   Z
write_filer   r   Z_render_persistent_net)r   r   Z	templatestargetZfpeniheaderZnetrulesr'   r'   r(   render_network_state  s    		zRenderer.render_network_state)	__name__
__module____qualname____doc__r   r   r   r   r   r'   r'   r'   r(   r   S  s   4G-r   c             C   si   d } t  d d | d | d d  i  } | s3 d } | j d  sL | d 7} | j |  d | } | | S)	Nzetc/network/interfacesr~   r   r   r   r[   r   rE   )r   endswithr   )r   r   rE   r   r   rm   r'   r'   r(   network_state_to_eni  s    
r   c             C   sw   d d d g } d d g } x- | D]% } t  j | d | d |  s" d Sq" Wt  j |  d	  } t j j |  ss d Sd
 S)NZifqueryZifupZifdownz/sbinz	/usr/sbinrY   r   Fzetc/network/interfacesT)r   Zwhichr   rJ   rK   rL   )r   ZexpectedrY   pZenir'   r'   r(   	available$  s    r   )rC   r`   rJ   rM   r[   r   r   r   r   Z	cloudinitr   Zloggingr   r   Z	getLoggerr   r9   rh   ri   rg   r)   r>   rG   re   ru   rw   rv   r   r   r   r'   r'   r'   r(   <module>   s6   9*