U
    Ӈg                     @   s6  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 d dlmZmZ d dlmZmZmZmZmZ d dlmZ eeZddd	d
ddddddddddgZd,ddZdd Zdd ZG dd dZG dd deZG d d! d!eZ G d"d# d#ej!Z!d$d% Z"d-d&d'Z#d.d(d)Z$d/d*d+Z%dS )0    N)DictOptional)subputil)networkmanager_confresolv_conf)IPV6_DYNAMIC_TYPESis_ipv6_addressnet_prefix_to_ipv4_maskrenderersubnet_is_ipv6)NetworkStateZ	almalinuxZcentosZ
cloudlinuxZ	eurolinuxZfedoraZmiraclelinuxZ	openeulerZOpenCloudOSZopenmandrivarhelZrockysuseZ	TencentOSZ	virtuozzo#c                 C   sJ   ddg}t t|D ]*}|| r6| d ||  ||< q| ||< qd|S )Nz1Created by cloud-init automatically, do not edit.  
)rangelenjoin)seplinesi r   9/usr/lib/python3/dist-packages/cloudinit/net/sysconfig.py_make_header)   s    
r   c                 C   s   d}| d dko| d |kS )N)z::z0.0.0.0prefixr   networkr   )routeZdefault_netsr   r   r   _is_default_route6   s    r    c                 C   s6   t d| r.| dr$| dr$| S d|  S n| S d S )Nz\s"z"%s")research
startswithendswith)valuer   r   r   _quote_value;   s
    
r'   c                   @   sj   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )	ConfigMapz!Sysconfig like dictionary object.yesZno)TFc                 C   s
   i | _ d S N_confselfr   r   r   __init__O   s    zConfigMap.__init__c                 C   s   || j |< d S r*   r+   )r.   keyr&   r   r   r   __setitem__R   s    zConfigMap.__setitem__c                 C   s
   | j | S r*   r+   r.   r0   r   r   r   __getitem__U   s    zConfigMap.__getitem__c                 C   s   | j |S r*   )r,   getr2   r   r   r   r4   X   s    zConfigMap.getc                 C   s
   || j kS r*   r+   r2   r   r   r   __contains__[   s    zConfigMap.__contains__c                 C   s   | j |d  d S r*   )r,   popr2   r   r   r   drop^   s    zConfigMap.dropc                 C   s
   t | jS r*   )r   r,   r-   r   r   r   __len__a   s    zConfigMap.__len__c                 C   s   dS )z6Skip the pair key, value if it matches a certain rule.Fr   r.   r0   valr   r   r   skip_key_valued   s    zConfigMap.skip_key_valuec                 C   s   t  }|t  | jr$|d t| j D ]X}| j| }| ||rNq2t|t	rb| j
| }t|tstt|}|d|t|f  q2| S )Nr   %s=%s
)ioStringIOwriter   r,   sortedkeysr;   
isinstancebool	_bool_mapstrr'   getvalue)r.   bufr0   r&   r   r   r   	to_stringh   s    




zConfigMap.to_stringc                 C   s   | j | d S r*   )r,   update)r.   Zupdatesr   r   r   rI   x   s    zConfigMap.updateN)__name__
__module____qualname____doc__rD   r/   r1   r3   r4   r5   r7   r8   r;   rH   rI   r   r   r   r   r(   F   s   r(   c                       sR   e Zd ZdZ fddZdd Zedd Zedd	 Zd
d Z	dddZ
  ZS )Routez!Represents a route configuration.c                    s<   t t|   d| _d| _d| _|| _|| _|| _|| _	d S )N   F)
superrN   r/   last_idxhas_set_default_ipv4has_set_default_ipv6_route_name_base_sysconf_dirroute_fn_tpl_ipv4route_fn_tpl_ipv6)r.   Z
route_namebase_sysconf_diripv4_tplipv6_tpl	__class__r   r   r/      s    zRoute.__init__c                 C   s>   t | j| j| j| j}| j |_| j|_| j|_| j	|_	|S r*   )
rN   rT   rU   rV   rW   r,   copyrQ   rR   rS   )r.   rr   r   r   r]      s    z
Route.copyc                 C   s   | j | j| jd S N)basename)rV   rU   rT   r-   r   r   r   	path_ipv4   s    zRoute.path_ipv4c                 C   s   | j | j| jd S r_   )rW   rU   rT   r-   r   r   r   	path_ipv6   s    zRoute.path_ipv6c                 C   s   d|kS )N:r   )r.   addressr   r   r   is_ipv6_route   s    zRoute.is_ipv6_routeipv4c              	   C   s  |dkrt dt| t }|t  | jr<|d d}t| j D ]p}d|kr^qN|	dd}t| j| }t| jd|  }|dkrV| 
|sVt| jd	|  }|d
 }|ddt| t|f  |ddt| t|f  |dd	t| t|f  d| }	|	| jkrt| j|	 }
|ddt| t|
f  qN|dkrN| 
|rNt| jd|  }d| | jkrdt| jd|   nd}
|d||||
| jf  qN| S )N)rg   ipv6zUnknown protocol '%s'r   ADDRESSr   GATEWAYrg   NETMASKrO   r<   METRICrh   PREFIXzmetric z%s/%s via %s %s dev %s
)
ValueErrorrE   r=   r>   r?   r   r,   r@   rA   replacerf   r'   rT   rF   )r.   protorG   Zreindexr0   indexZaddress_valueZgateway_valueZnetmask_valueZ
metric_keyZmetric_valueZprefix_valuer   r   r   rH      sp    
zRoute.to_string)rg   )rJ   rK   rL   rM   r/   r]   propertyrb   rc   rf   rH   __classcell__r   r   r[   r   rN   |   s   


rN   c                       s   e Zd ZdZddddddZd fd	d
	Zedd Zejdd Zedd Z	e	jdd Z	edd Z
dddZdd Z  ZS )NetInterfacezERepresents a sysconfig/networking-script (and its config + children).ZEthernetZBondZBridgeZ
InfiniBandVlan)ethernetbondbridge
infinibandvlanrw   c                    sr   t t|   g | _|| _| jd}t|||d|dd| _| jd| _|| _	|| _
|| jd< || _d S )Nroute_templatesrg   rh   )rY   rZ   iface_templatesDEVICE)rP   ru   r/   children	templatesr4   rN   routesiface_fn_tplkind_iface_namer,   rU   )r.   
iface_namerX   r   r   Z	route_tplr[   r   r   r/      s    
zNetInterface.__init__c                 C   s   | j S r*   )r   r-   r   r   r   ra   	  s    zNetInterface.namec                 C   s   || _ || jd< d S )Nr~   )r   r,   )r.   r   r   r   r   ra     s    c                 C   s   | j S r*   )_kindr-   r   r   r   r     s    zNetInterface.kindc                 C   s,   || j krt||| _| j | | jd< d S )NTYPE)iface_typesro   r   r,   )r.   r   r   r   r   r     s    
c                 C   s   | j | j| jd S r_   )r   rU   ra   r-   r   r   r   path  s    zNetInterface.pathFc                 C   sH   t | j| j| j| jd}| j |_|r4t| j|_|rD| j	 |_	|S )N)r   )
ru   ra   rU   r   r   r,   r]   listr   r   )r.   Zcopy_childrenZcopy_routescr   r   r   r]   #  s       zNetInterface.copyc                 C   s   |dkr|dkrdS dS )Nr   rv   TFr   r9   r   r   r   r;   .  s    zNetInterface.skip_key_value)rw   )FF)rJ   rK   rL   rM   r   r/   rs   ra   setterr   r   r]   r;   rt   r   r   r[   r   ru      s*   	 





ru   c                   @   sD  e Zd ZU dZdddddddd	Zd
ddddddddddddd	Zeddddddddddd d!d"d#d$gZi Ze	e
d%< dEd'd(Zed)d* Zed+d, Zed-d. Zed/d0 Zed1d2 Zed3d4 Zed5d6 ZedFd7d8ZedGd9d:Zeed;d<d=Zed>d? ZedHed;d@dAZdIeee	 d&dBdCdDZd&S )JRendererz7Renders network information in a /etc/sysconfig format.TFnone)ONBOOTZUSERCTL	BOOTPROTOstaticauto)r   	STARTMODE)r   r   IPV6_FORCE_ACCEPT_RAZSTPZAGEINGZPRIOZHWADDRMTU)	accept-ra
bridge_stpbridge_ageingbridge_bridgepriomac_addressmtu
BRIDGE_STPZBRIDGE_AGEINGTIMEZBRIDGE_PRIORITYLLADDR)r   r   r   r   r   )Z	bond_modezmode=%s)Zbond_xmit_hash_policyzxmit_hash_policy=%s)Zbond_miimonz	miimon=%s)Zbond_min_linkszmin_links=%s)Zbond_arp_intervalzarp_interval=%s)Zbond_arp_ip_targetzarp_ip_target=%s)Zbond_arp_validatezarp_validate=%s)Zbond_ad_selectzad_select=%s)Zbond_num_grat_arpznum_grat_arp=%s)Zbond_downdelayzdowndelay=%s)Zbond_updelayz
updelay=%s)Zbond_lacp_ratezlacp_rate=%s)Zbond_fail_over_maczfail_over_mac=%s)Zbond_primaryz
primary=%s)Zbond_primary_reselectzprimary_reselect=%sr   Nc                 C   sv   |si }| dd| _| dd| _| dd| _d}| d|| _| d	| d
| dd| _| dd| _d S )Nsysconf_dirzetc/sysconfignetrules_pathz(etc/udev/rules.d/70-persistent-net.rulesdns_pathzetc/resolv.confz,etc/NetworkManager/conf.d/99-cloud-init.confnetworkmanager_conf_pathcontrolr}   r|   )r   r}   r|   flavorr   )r4   r   r   r   r   r   r   )r.   Zconfignm_conf_pathr   r   r   r/   p  s$      zRenderer.__init__c                 C   s   t | j|i }|| dD ]H}||}|d k	r"|dkrN|d dkrNq"| j| |}|r"|||< q"d|kr|d r|d dkrd|d< d S )	N)r   r   r   r   type)physicalrz   Z	wakeonlanr   zwol gZETHTOOL_OPTS)r]   deepcopyiface_defaultsr4   rI   cfg_key_maps)clsiface	iface_cfgr   Zflavor_defaultsold_key	old_valuenew_keyr   r   r   _render_iface_shared  s"    



zRenderer._render_iface_sharedc                 C   s  |dkr,d|d< d|kr4d|d< | d nd|d< t|t|jdD ]\}}d}|d	}|d
ksn|dkr|dkr|d dkrd|d< nd
|d< d|d< nB|dkr|dkrd|d< d|d< d|d< d|d< nd|d< d|d< n|dkrF|dkr"|d dkrd|d< nd
|d< d|d< n d|d< d|d< d|d< d|d< n|dkr|dkr|d dkrrd|d< nd
|d< d|d< nd|d< d|d< nD|dkr|d }	d|d< |dkr|	dkrd|d< n
|dkrt|r|dkrd}d|d< d|krtt||ko |d || k}
|
rDtd |j	|| |d  t|rh|dkrZn|d ||< n|d ||< t|r|dkrd|d!< d|d< nB|d"kr|dkrt
d#| n||k|d$< ntd%||j	f |d&d"krF|dkrd"|d'< qFd|d$< qFd(}d(}t|t|jdD ]x\}}|d	}d)|kr|dkrpt|rb|d) |d*< n|d) |d+< n|dkr|d) |d,< |d-kr|dkr"|r"|d dkr"d|d.< q"q"|tkrАq"q"|dkr"t|r~|d/ }d0|d1 |d2 f }|d3kr(|dkr||d4< n||d5< nT|d/krP|dkrF||d6< n||d7< n,|dkrh||d8| < n|d7  d9| 7  < nB|d/ }|d3krd:nt|}|d1 |d;| < t|d2 |d<| < d=|kr|dkrd|d>< t|d= r|d= |d?< n|d= |d@< dA|kr*|dkr*d9|dA |dB< dC|kr"|dkr"t|dC dDkrht
dE|j	t|dC  t|dC d dD d/D ]\}}||dFt| < q~q"d S )GNr   r   r   BRIDGEdhcpr   startr   r   dhcp6zipv6_dhcpv6-stateful)dhcp4r   ZmanagedZDHCLIENT6_MODEr   TZDHCPV6CZIPV6INITFZIPV6_AUTOCONFZIPV6_FAILURE_FATALzipv6_dhcpv6-statelessinfoz-SZDHCPV6C_OPTIONSZ
ipv6_slaac)r   r   r   )r   Zstatic6ZIPV6_MTUr   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.r   Zmanualz Unknown subnet type setting "%s"r   z1Unknown subnet type '%s' found for interface '%s'r   r   ri   metricIPV6_ROUTE_METRICIPV4_ROUTE_METRICrm   r   r   DHCLIENT_SET_DEFAULT_ROUTErO   z%s/%sre   r   r   ZIPADDR6ZIPV6ADDRZ	IPADDR6_1ZIPV6ADDR_SECONDARIESz
IPADDR6_%dr   r   ZIPADDRrl   gatewayDEFROUTEIPV6_DEFAULTGWrk   
dns_searchZDOMAINdns_nameservers   z6%s has %d entries in dns_nameservers. Only 3 are used.ZDNS)r7   	enumerater   r   r4   r   rC   LOGZwarningra   debugro   r   rE   r
   r	   r   )r   r   subnetshas_default_router   r   subnetZmtu_keysubnet_typeZbootproto_inZmtu_mismatchZ
ipv4_indexZ
ipv6_indexZ	ipv6_cidrZsuffkr   r   r   _render_subnets  s   













































zRenderer._render_subnetsc                 C   s|  |dkrd S t |t|jdD ]V\}}|d}|dg D ]4}|dpXt|d }	t|r2|tkr2|dr~|js|dr|jrt	d|j
 d	|d
< |d dkrd	|d< d|kr|	r|d |d< d	|_n|d |d< d	|_d|krt|dkr$t|r|d |d< n|d |d< n|d |d< q>dD ].\}
}|
|kr6| |j }||
 ||< q6| jd7  _q>qd S )Nr   r   r   r   rh   r   rg   z?Duplicate declaration of default route found for interface '%s'Tr   r   r   r   r   rk   r   r   r   r   rm   ))r   rk   )r   rm   )r   rn   )Znetmaskrl   )r   rj   rO   )r   r   r   r4   r	   r    r   rR   rS   ro   ra   r   rQ   )r   r   	route_cfgr   r   _r   r   r   Zis_ipv6r   new_namer   r   r   r   _render_subnet_routesj  sb    
	





zRenderer._render_subnet_routesc           	      C   s   g }| j D ]\\}}||ddg}|D ]>}||kr&|| }t|ttfrRd|}|||   q
q&q
|r|dkrd||d< nd||d< d S )Nr   -r   r   ZBONDING_MODULE_OPTSZBONDING_OPTS)bond_tpl_optsrp   rB   tupler   r   append)	r   r   r   r   Z	bond_optsZbond_keyZ	value_tplZ	bond_keysZ
bond_valuer   r   r   _render_bonding_opts  s    
zRenderer._render_bonding_optsc           
      C   sh   t j}||D ]R}|dp$|d }|dg }|| }|j}	| |||j| | ||	|| qd S )N	config_idra   r   )r   Zfilter_by_physicaliter_interfacesr4   r   r   r   r   )
r   network_stateiface_contentsr   Zphysical_filterr   r   iface_subnetsr   r   r   r   r   _render_physical_interfaces  s$       z$Renderer._render_physical_interfacesc                    sd  t d}t d}||D ]>}|d  |  }| ||| |g}||j |D ]}	d|	d< |dkrXd|	_qX|dr|dkr|d|d< n|d|d	< |d
g }
|j	}| 
||
|j| | |||
| t fdd||D }t|D ]`\}}|dkrd| }nd| }|||< || }|dkrLd|d< d|d< q |d< d|d< qqd S )Nrx   bond-masterra   TZBONDING_MASTERr   r   r   MACADDRr   c                    s    g | ]}|d   kr|d qS )r   ra   r   ).0Zslave_ifacer   r   r   
<listcomp>	  s   z4Renderer._render_bond_interfaces.<locals>.<listcomp>zBONDING_SLAVE_%szBONDING_SLAVE%sr   r   Zhotplugr   ZMASTERZSLAVE)r   filter_by_typeZfilter_by_attrr   r   extendr   r   r4   r   r   r   r   r@   r   )r   r   r   r   Zbond_filterZslave_filterr   r   Zmaster_cfgsZ
master_cfgr   r   Zbond_slavesrr   Z
bond_slaveZslavestrZ	slave_cfgr   r   r   _render_bond_interfaces  s`    


   





z Renderer._render_bond_interfacesc              	   C   s   t d}||D ]}|d }|| }|dkr^|d}|rF||d< |d |d |d< nJd|d	< d|_|d
 }	t|	|d }
||
krtd||	d	|
 |	|d< |dg }|j
}| |||j| | |||| qd S )Nr{   ra   r   vlan_idZVLAN_ID.ZETHERDEVICETZVLANzvlan-raw-devicezIName '%s' for vlan '%s' is not officially supportedby RHEL. Supported: %sr   ZPHYSDEVr   )r   r   r   r4   rfindr   _supported_vlan_namesr   r   r   r   r   r   r   )r   r   r   r   Zvlan_filterr   r   r   r   rdevZ	supportedr   r   r   r   r   _render_vlan_interfaces!  sF    

   z Renderer._render_vlan_interfacesc           	         sn  g g  |   D ]}|d D ]0}d|kr6|d  d|kr |d  qd|krfdd|d d D 7   fdd|d d	 D 7  q| jrfd
d| jD 7 | jrЈ  fdd| jD 7  ttt gsd S td}|rtj	
|rtt|}D ]}|| q D ]}|| q0td}t|}||sj|d | }|S )Nr   r   r   dnsc                    s   g | ]}| kr|qS r   r   )r   r   found_nameserversr   r   r   X  s   z(Renderer._render_dns.<locals>.<listcomp>nameserversc                    s   g | ]}| kr|qS r   r   r   r#   found_dns_searchr   r   r   ]  s   r#   c                    s   g | ]}| kr|qS r   r   )r   
nameserverr   r   r   r   h  s   c                    s   g | ]}| kr|qS r   r   r   r   r   r   r   n  s   r   ;r   )r   r   r   dns_searchdomainsanyr   r   Z
ResolvConfosr   isfiler   Zload_text_fileZadd_nameserverZadd_search_domainr   rE   r$   )	r   existing_dns_pathr   r   contentr   ZsearchdomainheaderZcontent_strr   )r   r   r   _render_dnsH  sV    




zRenderer._render_dnsc                 C   s   d}t d}|  D ]V}|d D ]}d|ks6d|kr"d} q@q"|sd|kr|d d sd|d d	 rd} qnq| js~| js~|r|d
dd t|dkrd S dt dd|	 dg}|S )NFr   r   r   r   Tr   r   r#   mainr   r   r   )
r   ZNetworkManagerConfr   r   r   Zset_section_keypairr   r   r   r?   )r   r   Z	iface_dnsr   r   r   outr   r   r   _render_networkmanager_conf  s8    


z$Renderer._render_networkmanager_conf)r   c                 C   s  dd | j |  D }td}||D ]P}|d }|| }|dkrPd|_| D ]\}	}
|	|krX||	 ||
< qX|dkrd|kr|drd|d< nd|d< |d	rd
}|dkrd}|d	||< |dkr|dg rdd|d |d< |dg D ]F}|| }|g}||j	 |D ] }|}|dkr:d}||d< q$q|dg }|j
}| |||j| | |||| q,d S )Nc                 S   s    i | ]\}}| d r||qS )ry   )r$   )r   Zold_kZnew_kr   r   r   
<dictcomp>  s   
 z6Renderer._render_bridge_interfaces.<locals>.<dictcomp>ry   ra   r   r   ZonZoffr   r   Z	LLADDRESSZbridge_portsz%sr   ZBRIDGE_PORTSr)   r   r   )r   itemsr   r   r   r   r4   r   r   r   r   r   r   r   )r   r   r   r   Zbridge_key_mapZbridge_filterr   r   r   r   r   r0   Zbridged_iface_nameZbridged_cfgZbridged_cfgsZ
bridge_cfgZbridge_valuer   r   r   r   r   _render_bridge_interfaces  sd    





   z"Renderer._render_bridge_interfacesc           
      C   sh   t d}||D ]N}|d }|| }d|_|dg }|j}	| |||j| | ||	|| qd S )Nrz   ra   r   )	r   r   r   r   r4   r   r   r   r   )
r   r   r   r   Z	ib_filterr   r   r   r   r   r   r   r   _render_ib_interfaces  s&    
   zRenderer._render_ib_interfacesc                 C   s\  |s
| j }i }| D ]f}|d dkr(q|dp8|d }t|d ||}|dkrf|d |d | ||| |||< q| ||| | ||| | ||| | 	||| | 
||| i }	| D ]\}
}|s|jr| |	|j< |jD ]}|r| |	|j< q|jrt|jj|jjgdd	gD ]$\}}||	kr0|j||	|< q0q|	S )
z3Given state, return /etc/sysconfig files + contentsr   Zloopbackr   ra   r   r~   r   rg   rh   )r   r   r4   ru   r7   r   r   r   r   r   r   r   r   rH   r   r   ziprb   rc   )r   rX   r   r   r   r   r   r   r   contentsr   Zcpathrq   r   r   r   _render_sysconfig  sJ    	  




zRenderer._render_sysconfig)r   r   returnc                 C   sT  |s
| j }d}t|| j}| j||| j|d D ]\}}t||| q4| j	rt|| j	}| j
||d}	|	rt||	| | jrt|| j}
| ||}|rt|
|| | jr| |}t|| j}tj|||dd t||d}|drPttj| t dg}|jr8|d	 |d
 t|d|d | d S )Ni  )r   )r   T)r   modeZpreserve_moder   r   zNETWORKING=yeszNETWORKING_IPV6=yeszIPV6_AUTOCONF=nor   )r   r   target_pathr   r  r   r   r   Z
write_filer   r   r   r   r   Z_render_persistent_netr4   r%   Z
ensure_dirr   r   dirnamer   Zuse_ipv6r   r   )r.   r   r   targetZ	file_moderX   r   datar   Zresolv_contentr   Znm_conf_contentZnetrules_contentr   Zsysconfig_pathZnetcfgr   r   r   render_network_state1  sf          



  zRenderer.render_network_state)N)N)N)N)NN)rJ   rK   rL   rM   r   r   r   r   r   dict__annotations__r/   classmethodr   r   r   r   r   r   r   staticmethodr   r   r   r   r   r  r   r
  r   r   r   r   r   4  s   
		


 M
G


>
&B%>
 0  r   c                    s    fdddD S )ziReturn list of supported names for vlan devices per RHEL doc
    11.5. Naming Scheme for VLAN Interfaces.c                    s   g | ]}|j  td qS )r   Zvid)formatint)r   vr  r   r   r   i  s   z)_supported_vlan_names.<locals>.<listcomp>)z{rdev}{vid:04}z{rdev}{vid}z{rdev}.{vid:04}z{rdev}.{vid}r   r  r   r  r   r   f  s    r   c                 C   s0   t  d tkrdS t| r dS t| r,dS dS )NZvariantFT)r   Zsystem_infoKNOWN_DISTROSavailable_sysconfigavailable_nm_ifcfg_rhr  r   r   r   	availablet  s    r  c                 C   s   t  t| dS )Nz;usr/lib*/NetworkManager/*/libnm-settings-plugin-ifcfg-rh.so)globr   r  r  r   r   r   r  ~  s    r  c                 C   s`   ddg}ddg}|D ]}t j||| ds dS qddg}|D ]}tjt | |r< d	S q<dS )
NZifupZifdownz/sbinz	/usr/sbin)r#   r  Fz/etc/sysconfig/network-scripts/network-functionszetc/sysconfig/configT)r   Zwhichr   r   r   r  )r  Zexpectedr#   pZexpected_pathsr   r   r   r    s    r  )r   )N)N)N)&r]   r  r=   Zloggingr   r"   typingr   r   Z	cloudinitr   r   Zcloudinit.distros.parsersr   r   Zcloudinit.netr   r	   r
   r   r   Zcloudinit.net.network_stater   Z	getLoggerrJ   r   r  r   r    r'   r(   rN   ru   r   r   r  r  r  r   r   r   r   <module>   sV   

6nJ      8


