
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
\mevK                 @   s   d dl Z 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mZ d dl	m
Z
mZmZmZ d dlmZmZmZmZmZ d dlmZmZ dZejeZdd Zdeed	d
dZdd ZdddZG dd dej Z dddZ!dS )    N)Optionalcast)featuressafeyamlsubputil)IPV6_DYNAMIC_TYPESSYS_CLASS_NETget_devicelistrenderersubnet_is_ipv6)NET_CONFIG_TO_V2NetworkStates4  # 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   s$   | ]\}}|j  r||fV  qd S )N)
startswith).0keyvalue)match /usr/lib/python3.6/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   )r   entryc             C   sl  d(dd}|dkrg }g }g }g }g }| j dg }	|	dkr>g }	x|	D ]}
|
j d}|jdr|dkrp|d7 }|j|d	i qF|tkr|jd
d	i qF|d)krFd|
j d }d|
kr|d|
j d 7 }|
j drl|
j ddd}yDtj|
d }tj|dd}||kr&tjd|
d | d	|d< W n8 t	k
r` } ztj
d|
d || W Y dd}~X nX |j| d|
kr|||
j dg 7 }d|
kr|||
j dg 7 }d|
krd}t|
rd|krd}|j||
j di xh|
j dg D ]X}d|j d|j df }|j d|d}d |kr<|jd |j d d!i |j| qW |j| qFW d| kr|j d}|r| d |krtj
d"|| d | n| d |d< t|d#kr|jd$|i t|d#kr|jd|i t|d#kr d$|i}|jd%|i t|d#kr6|j d%i }|jd&|i |jd%|i d'| krh| d' dk	rh|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. (config v1 -> netplan)

    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   s2   |  st | t r| S || kr(| j|S | gS dS )zT
        Helper to convert strings to list of strings, handle single string
        N)
isinstancestrsplit)objtokenr   r   r   _listifyU   s
    
z$_extract_addresses.<locals>._listifyNsubnetstypeZdhcp4TZdhcp6staticstatic6z%sZaddressprefixz/%dZgatewaydefault)ZviaZtoF)strictzAGateway %s is not contained within subnet %s, adding on-link flagzon-linkzDFailed to check whether gateway %s is contained within subnet %s: %sdns_nameserversZ
dns_searchZmtuzipv6-mturoutesz%s/%snetworkZmetricd   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.r   	addressesnameserverssearchz	accept-ra)r   )r&   r'   )getr   updater   	ipaddressZ
ip_addressZ
ip_networkLOGdebug
ValueErrorZwarningappendr   lenr   Zis_true)r   r   ifnamer   r"   r/   r,   r0   searchdomainsr#   ZsubnetZsn_typeZaddrZ	new_routeZsubnet_gatewayZsubnet_networkeZmtukeyZrouteZto_netZ	entry_mtunsr   r   r   _extract_addresses0   s    %










r>   c                s8   t  fdd| j D }t|dkr4|jd|i d S )Nc                s$   g | ]\}}|j d d kr|qS )zbond-masterN)r2   )r   namecfg)bond_masterr   r   
<listcomp>   s   z0_extract_bond_slaves_by_name.<locals>.<listcomp>r   
interfaces)sortedr   r9   r3   )rC   r   rA   Zbond_slave_namesr   )rA   r   _extract_bond_slaves_by_name   s
    
rE   c                s   t j d}tjj|sd S tj|dd}|tkr6d S  fdddD }d	d |D }tj	d
|| x|g| D ]}tj
| qpW d S )Nz etc/netplan/00-snapd-config.yamlF)decodec                s   g | ]}t j |qS r   )r   target_path)r   f)targetr   r   rB      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S r   )ospathisfile)r   rH   r   r   r   rB      s    z9removing known config '%s' and derived existing files: %s)rJ   rK   rL   )r   rG   rM   rN   rO   r   Z	load_fileKNOWN_SNAPD_CONFIGr5   r6   unlink)rI   ZtpathcontentZderivedZexistingrH   r   )rI   r   _clean_default   s"    
  rS   c               @   sz   e Zd ZdZddgZddgZdddZedd	 Zde	e
e dd
ddZdeedddZdddZe	edddZdS )RendererzBRenders network information in a /etc/netplan/network.yaml format.netplanZgenerateinfoNc             C   sR   |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_defaultTr   )r2   rW   rX   	_postcmdsrY   	_features)selfr   r   r   r   __init__   s    
zRenderer.__init__c             C   s   | j d kry0tj| jdd\}}tj|}|d d | _ W nF tjk
rP   Y n2 ttfk
r } ztj	d| W Y d d }~X nX | j S )NT)capturez
netplan.ior   z-Failed to list features from netplan info: %s)
r[   r   NETPLAN_INFOr   Z	load_yamlProcessExecutionError	TypeErrorKeyErrorr5   r6   )r\   Z	info_blobZ_errrV   r<   r   r   r   r      s    

zRenderer.features)network_state	templatesreturnc             C   s*  t jjtj|| j}tjt jj| | j	|}| j
r>| j
nd}|jdsT|d7 }|| }d}t jj|rtjtj|j }t|d}	tj|	}
W d Q R X ||
krd}tjrdnd}| rt jj|rtj|}||@ |kr|}tj|||d | jrt|d	 | j| j|d
 | j| jd d S )N 
FrbTi  i  )mode)rI   )runsame_content)rj   )rM   rN   joinr   rG   rW   r   Z
ensure_dirdirname_render_contentrX   endswithexistsZhash_bufferioBytesIOencodeopenr   ZNETPLAN_CONFIG_ROOT_READ_ONLYZget_permissionsZ
write_filerY   rS   _netplan_generaterZ   _net_setup_link)r\   rc   rd   rI   ZfpnplanrR   headerrk   Zhashed_contentrH   Zhashed_original_contentri   Zcurrent_moder   r   r   render_network_state  s0    	



zRenderer.render_network_stateF)rj   rk   c             C   s8   |st jd d S |r$t jd d S tj| jdd d S )Nz!netplan generate postcmd disabledzEskipping call to `netplan generate`. reason: identical netplan configT)r^   )r5   r6   r   NETPLAN_GENERATE)r\   rj   rk   r   r   r   ru   8  s    
zRenderer._netplan_generatec             C   s   |st jd dS dddg}t}xtdD ]l}y>x6t D ],}tjjt| r8t	j	|t| g dd q8W P W q* t	j
k
r } z
|}W Y dd}~X q*X q*W td	|d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_link   T)r^   zQ'udevadm test-builtin net_setup_link' unable to run successfully for all devices.)r5   r6   	Exceptionranger
   rM   rN   islinkr	   r   r`   RuntimeError)r\   rj   Z	setup_lnkZlast_exception_Zifacer<   r   r   r   rv   D  s"    

zRenderer._net_setup_link)rc   re   c       +      C   sd  |j dkr*tjd tjd|jidddS i }i }i }i }i }g }|jjdg }|j}	|j	}
x4|j
 D ]&}|jd}ttdd	 |j }|jd
}|dkr||jdd d}|d d kr|jdd }|d k	rd|j i|d< n|d= |d= t|||| j |j||i qh|dkri }i }tttjd}x^d/D ]V}t||}xD|j D ]8\}}|j|jdd}|d krzqR|j||i qRW q:W t|dkr|jd|i |jdr|d j |d< |jd}|dkrt||| t|||| j |j||i qh|dkr2|jd}ttj|}d|i}d}t||}i }tttjd} x|j D ]t\}}| j|}|d krqb|j||i |d0krbi }!x&|D ]}"|"j \}#}$t|$|!|#< qW |j||!i qbW t|dkr|jd|i |jdr|d j |d< t|||| j |j||i qh|dkrh|jd |jd!d"}%|jdd }|d k	rr|j |%d< t||%|| j |j||%i qhW |	s|
r|	|
d#}&xV|||||gD ]D}'x<|'j D ]0\}(})d$|)ksd%|)krq|)jd$|&i qW qW d&d' }*|jd( ||*d)|7 }||*d*|7 }||*d+|7 }||*d,|7 }||*d-|7 }d.j|S )1N   zV2 to V2 passthroughr-   F)explicit_startexplicit_endrC   r?   c             S   s   | d d k	S )N   r   )itr   r   r   <lambda>}  s    z*Renderer._render_content.<locals>.<lambda>r$   Zphysicalr   )zset-namer   Zmac_addressZ
macaddresszset-namebondbond_bond-r   -r   Z
parameterszbond-slavesZnonebridgebridge_portsZbridge_	path-costport-priorityvlanZvlan_idzvlan-raw-device)idlink)r/   r1   r0   r/   c             S   s0   |r,t j| |idddd}tj|d}|gS g S )NFT)r   r   Znoaliasr      z    )r   dumpstextwrapindent)r?   sectiondumpZtxtr   r   r   _render_section  s    z1Renderer._render_content.<locals>._render_sectionznetwork:
    version: 2
	ethernetswifisbondsbridgesvlansrf   )r   r   )r   r   )versionr5   r6   r   r   r   Z_network_stater2   r+   Zdns_searchdomainsZiter_interfacesr   filterr   lowerr>   r   r3   r   r   r   replacer9   rE   rD   copyr   intr8   rl   )+r\   rc   r   r   r   r   r   rR   rC   r0   r;   r   r:   ZifcfgZif_typeZethZmacaddrr   Zbond_configZv2_bond_mapr   Zbond_paramsZparamr   ZnewnameZslave_interfacesr   Zportsr   Zmatch_prefixZparamsZ	br_configZv2_bridge_mapZnewvaluevalZportZportvalr   Znscfgr   _namer@   r   r   r   r   rn   c  s    




















zRenderer._render_content)N)NN)FF)F)__name__
__module____qualname____doc__ry   r_   r]   propertyr   r   r   r   rx   boolru   rv   r   rn   r   r   r   r   rT      s   
 
'
rT   c             C   s4   dg}ddg}x |D ]}t j||| dsdS qW dS )NrU   z	/usr/sbinz/sbin)r1   rI   FT)r   Zwhich)rI   Zexpectedr1   pr   r   r   	available  s    
r   )N)N)N)"r   rq   r4   ZloggingrM   r   Ztypingr   r   Z	cloudinitr   r   r   r   Zcloudinit.netr   r	   r
   r   r   Zcloudinit.net.network_stater   r   rP   Z	getLoggerr   r5   r   r   r>   rE   rS   rT   r   r   r   r   r   <module>   s(   
 
  