
"T`Q?                 @   s   d  d l  Z  d  d l Z d d l m Z d d l m Z m Z 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 m Z d
 Z e
 j e  Z d d   Z d d d  Z d d   Z d d d  Z Gd d   d e j  Z d d d  Z d d d  Z d S)    N   )renderer)subnet_is_ipv6NET_CONFIG_TO_V2IPV6_DYNAMIC_TYPES)log)util)subp)safeyaml)SYS_CLASS_NETget_devicelists4  # This is the initial network config.
# It can be overwritten by cloud-init or console-conf.
network:
    version: 2
    ethernets:
        all-en:
            match:
                name: "en*"
            dhcp4: true
        all-eth:
            match:
                name: "eth*"
            dhcp4: true
c                s#   t    f d d   |  j   D  S)Nc             3   s0   |  ]& \ } } | j     r | | f Vq d  S)N)
startswith).0keyvalue)match 7/usr/lib/python3/dist-packages/cloudinit/net/netplan.py	<genexpr>#   s    	z,_get_params_dict_by_match.<locals>.<genexpr>)dictitems)configr   r   )r   r   _get_params_dict_by_match"   s    r   c             C   s  d d d  } | d k r! g  } g  } g  } g  } g  } |  j  d g   }	 |	 d k r] g  }	 xV|	 D]N}
 |
 j  d  } | j d  r | d k r | d 7} | j | d	 i  qd | t k r | j d
 d	 i  qd | d& k rd d |
 j  d  } d |
 k r| d |
 j  d  7} d |
 k rw|
 j  d  rw|
 j  d  } d | k rd| j d | i  n | j d | i  d |
 k r| | |
 j  d g    7} d |
 k r| | |
 j  d g    7} d |
 k rd } t |
  rd | k rd } | j | |
 j  d  i  x |
 j  d g   D]{ } d | j  d  | j  d  f } d | j  d  d | i } d | k r| j d | j  d d  i  | j |  q&W| j |  qd Wd |  k r| j  d  } | r|  d | k rt j d  | |  d |  n |  d | d <t |  d! k r7| j d" | i  t |  d! k r\| j d | i  t |  d! k rd" | i } | j d# | i  t |  d! k r| j  d# i   } | j d$ | i  | j d# | i  d% |  k r|  d% d k	 r| j d% t	 j
 |  j  d%   i  d S)'a  This method parse a cloudinit.net.network_state dictionary (config) and
       maps netstate keys/values into a dictionary (entry) to represent
       netplan yaml.

    An example config dictionary might look like:

    {'mac_address': '52:54:00:12:34:00',
     'name': 'interface0',
     'subnets': [
        {'address': '192.168.1.2/24',
         'mtu': 1501,
         'type': 'static'},
        {'address': '2001:4800:78ff:1b:be76:4eff:fe06:1000",
         'mtu': 1480,
         'netmask': 64,
         'type': 'static'}],
      'type: physical',
      'accept-ra': 'true'
    }

    An entry dictionary looks like:

    {'set-name': 'interface0',
     'match': {'macaddress': '52:54:00:12:34:00'},
     'mtu': 1501}

    After modification returns

    {'set-name': 'interface0',
     'match': {'macaddress': '52:54:00:12:34:00'},
     'mtu': 1501,
     'address': ['192.168.1.2/24', '2001:4800:78ff:1b:be76:4eff:fe06:1000"],
     'ipv6-mtu': 1480}

     c             S   sD   |  s t  |   t g k r  |  S| |  k r9 |  j |  S|  g Sd S)zBHelper to convert strings to list of strings, handle single stringN)typestrsplit)objtokenr   r   r   _listifyL   s
    z$_extract_addresses.<locals>._listifyNsubnetsr   Zdhcp4TZdhcp6staticstatic6z%sZaddressprefixz/%dgateway:Zgateway6Zgateway4dns_nameserversZ
dns_searchZmtuzipv6-mturoutesz%s/%snetworkZviaZtoZmetricd   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.r   	addressesnameserverssearchz	accept-ra)r"   r#   )getr   updater   r   appendLOGZwarninglenr   Zis_true)r   entryifnamefeaturesr   r+   r(   r,   searchdomainsr    ZsubnetZsn_typeZaddrr%   ZmtukeyZrouteZto_netZ	new_routeZ	entry_mtunsr   r   r   _extract_addresses'   s    %	
r8   c                sN   t    f d d   |  j   D  } t |  d k rJ | j d | i  d  S)Nc                s4   g  |  ]* \ } } | j  d  d    k r |  q S)zbond-masterN)r.   )r   namecfg)bond_masterr   r   
<listcomp>   s   	 	z0_extract_bond_slaves_by_name.<locals>.<listcomp>r   
interfaces)sortedr   r2   r/   )r=   r3   r;   Zbond_slave_namesr   )r;   r   _extract_bond_slaves_by_name   s    %r?   c                s   t  j   d  } t j j |  s( d  St j | d d } | t k rM d  S  f d d   d D } d	 d   | D } t j	 d
 | |  x" | g | D] } t j
 |  q Wd  S)Nz etc/netplan/00-snapd-config.yamldecodeFc                s"   g  |  ] } t  j   |   q Sr   )r	   target_path)r   f)targetr   r   r<      s   	 z"_clean_default.<locals>.<listcomp>-run/systemd/network/10-netplan-all-en.network.run/systemd/network/10-netplan-all-eth.network#run/systemd/generator/netplan.stampc             S   s(   g  |  ] } t  j j |  r |  q Sr   )ospathisfile)r   rB   r   r   r   r<      s   	 z9removing known config '%s' and derived existing files: %s)rD   rE   rF   )r	   rA   rG   rH   rI   r   Z	load_fileKNOWN_SNAPD_CONFIGr1   debugunlink)rC   ZtpathcontentZderivedZexistingrB   r   )rC   r   _clean_default   s      
	
rN   c               @   s   e  Z d  Z d Z d d g Z d d g Z d d d  Z e d d	    Z d d d
 d  Z	 d d d  Z
 d d d  Z d d   Z d S)RendererzBRenders network information in a /etc/netplan/network.yaml format.netplanZgenerateinfoNc             C   sy   | s i  } | j  d d  |  _ | j  d d   |  _ | j  d d  |  _ | j  d d  |  _ | j  d d   |  _ d  S)	Nnetplan_pathzetc/netplan/50-cloud-init.yamlnetplan_headerZpostcmdsFclean_defaultTr5   )r.   rR   rS   	_postcmdsrT   	_features)selfr   r   r   r   __init__   s    	zRenderer.__init__c             C   s   |  j  d  k r yB t j |  j d d \ } } t j |  } | d d |  _  WnO t j k
 rh Yn; t t f k
 r } z t j	 d |  WYd  d  } ~ Xn X|  j  S)NcaptureTz
netplan.ior5   z-Failed to list features from netplan info: %s)
rV   r	   NETPLAN_INFOr   Z	load_yamlZProcessExecutionError	TypeErrorKeyErrorr1   rK   )rW   Z	info_blobZ_errrQ   er   r   r   r5      s    #zRenderer.featuresc             C   s   t  j j t j |  |  j  } t j t  j j |   |  j	 rL |  j	 n d } |  j
 |  } | j d  sz | d 7} t j | | |  |  j r t d |  |  j d |  j  |  j d |  j  d  S)N 
rC   run)rG   rH   joinr	   rA   rR   r   Z
ensure_dirdirnamerS   _render_contentendswithZ
write_filerT   rN   _netplan_generaterU   _net_setup_link)rW   network_stateZ	templatesrC   ZfpnplanheaderrM   r   r   r   render_network_state   s    !
	zRenderer.render_network_stateFc             C   s1   | s t  j d  d  St j |  j d d d  S)Nz!netplan generate postcmd disabledrY   T)r1   rK   r	   NETPLAN_GENERATE)rW   r`   r   r   r   re      s    zRenderer._netplan_generatec                sd   | s t  j d  d Sd d d g   x7   f d d   t   D D] } t j | d d	 qC Wd S)
zTo ensure device link properties are applied, we poke
           udev to re-evaluate networkd .link files and call
           the setup_link udev builtin command
        z'netplan net_setup_link postcmd disabledNZudevadmztest-builtinZnet_setup_linkc                s7   g  |  ]- } t  j j t |  r   t | g  q Sr   )rG   rH   islinkr   )r   Ziface)	setup_lnkr   r   r<      s   	z,Renderer._net_setup_link.<locals>.<listcomp>rY   T)r1   rK   r   r	   )rW   r`   cmdr   )rl   r   rf      s    zRenderer._net_setup_linkc       *      C   s  | j  d k r> t j d  t j d | j i d d d d Si  } i  } i  } i  } i  } g  } | j j d g   } | j }	 | j	 }
 xM| j
   D]?} | j d  } t d	 d
   | j   D  } | j d  } | d k rd | d | j d d   i } | d d  k rX| j d d   } | d  k	 rJd | j   i | d <n | d =| d =t | | | |  j  | j | | i  q | d k ri  } i  } t j d  } x} d d g D]o } t | |  } xW | j   D]I \ } } | j | j d d   } | d  k rq| j | | i  qWqWt |  d k rP| j d | i  | j d  rx| j d  j   | d <| j d  } | d k rt | | |  t | | | |  j  | j | | i  q | d k rNt t j | j d    } d | i } d } t | |  } i  } t j d  } x | j   D] \ } } | j |  } | d  k rfq<| j | | i  | d0 k r<i  }  x0 | D]( }! |! j   \ }" }# t |#  |  |" <qW| j | |  i  q<Wt |  d k r| j d | i  | j d  r"| j d  j   | d <t | | | |  j  | j | | i  q | d k r d  | j d!  d" | j d#  i }$ | j d d   } | d  k	 r| j   |$ d <t | |$ | |  j  | j | |$ i  q W|	 s|
 rbd$ |	 d% |
 i }% xh | | | | | g D]Q }& xH |& j   D]: \ }' }( d& |( k s d$ |( k rGq |( j d& |% i  q WqWd' d(   }) | j d)  | |) d* |  7} | |) d+ |  7} | |) d, |  7} | |) d- |  7} | |) d. |  7} d/ j |  S)1N   zV2 to V2 passthroughr)   explicit_startFexplicit_endr=   r9   c             s   s-   |  ]# \ } } | d  k	 r | | f Vq d  S)Nr   )r   r   r   r   r   r   r     s    	z+Renderer._render_content.<locals>.<genexpr>r   Zphysicalzset-namer   Zmac_addressZ
macaddressbondZbond_zbond-_-r   Z
parameterszbond-slavesZnonebridgeZbridge_portsZbridge_	path-costport-priorityvlanidZvlan_idlinkzvlan-raw-devicer+   r-   r,   c             S   sJ   | rF t  j |  | i d d d d d d } t j | d  } | g Sg  S)	Nro   Frp   ZnoaliasTr      z    )r
   dumpsr   indent)r9   sectiondumpZtxtr   r   r   _render_section  s    	z1Renderer._render_content.<locals>._render_sectionznetwork:
    version: 2
	ethernetswifisbondsbridgesvlansr^   )ru   rv   )versionr1   rK   r
   r{   r   Z_network_stater.   r'   Zdns_searchdomainsZiter_interfacesr   r   lowerr8   r5   r/   r   r   replacer2   r?   r>   copyr   intr0   ra   )*rW   rg   r   r   r   r   r   rM   r=   r,   r6   r   r4   ZifcfgZif_typeZethZmacaddrrq   Zbond_configZv2_bond_mapr   Zbond_paramsZparamr   ZnewnameZslave_interfacesZportsrt   Zmatch_prefixZparamsZ	br_configZv2_bridge_mapZnewvaluevalZportZportvalrw   Znscfgr}   _namer:   r   r   r   r   rc     s    		
zRenderer._render_content)__name__
__module____qualname____doc__rj   rZ   rX   propertyr5   ri   re   rf   rc   r   r   r   r   rO      s   
rO   c             C   sI   d g } d d g } x- | D]% } t  j | d | d |  s d Sq Wd S)NrP   z	/usr/sbinz/sbinr-   rC   FT)r	   Zwhich)rC   Zexpectedr-   pr   r   r   	available  s    	r   c             C   sZ   d } t  d | d | i  } | s* d } | j d  sC | d 7} | j |   } | | S)Nzetc/network/50-cloud-init.yamlrR   rS   r^   r_   )rO   rd   rc   )rg   rh   rR   r   contentsr   r   r   network_state_to_netplan  s    
r   )r   rG   r^   r   rg   r   r   r   Z	cloudinitr   Zloggingr   r	   r
   Zcloudinit.netr   r   rJ   Z	getLoggerr   r1   r   r8   r?   rN   rO   r   r   r   r   r   r   <module>   s"   w	