o
    f                     @   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 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g d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 )!    N)MappingOptional)subputil)networkmanager_confresolv_conf)IPV6_DYNAMIC_TYPESis_ipv6_addressnet_prefix_to_ipv4_maskrenderersubnet_is_ipv6)NetworkState)	almalinuxcentos
cloudlinux	eurolinuxfedoramiraclelinux	openeulerOpenCloudOSopenmandrivarhelrockysuse	TencentOS	virtuozzo#c                 C   sJ   ddg}t t|D ]}|| r| 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 |v S )N)z::z0.0.0.0prefixr   networkr&   )routedefault_netsr&   r&   r'   _is_default_route6   s   r-   c                 C   s0   t d| r| dr| dr| S d|  S | S )Nz\s"z"%s")research
startswithendswith)valuer&   r&   r'   _quote_value;   s
   r4   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.yesno)TFc                 C   s
   i | _ d S N_confselfr&   r&   r'   __init__O      
zConfigMap.__init__c                 C   s   || j |< d S r8   r9   )r<   keyr3   r&   r&   r'   __setitem__R   s   zConfigMap.__setitem__c                 C   s
   | j | S r8   r9   r<   r?   r&   r&   r'   __getitem__U   r>   zConfigMap.__getitem__c                 C   s   | j |S r8   )r:   getrA   r&   r&   r'   rC   X   s   zConfigMap.getc                 C   s
   || j v S r8   r9   rA   r&   r&   r'   __contains__[   r>   zConfigMap.__contains__c                 C   s   | j |d  d S r8   )r:   poprA   r&   r&   r'   drop^   s   zConfigMap.dropc                 C   s
   t | jS r8   )r!   r:   r;   r&   r&   r'   __len__a   r>   zConfigMap.__len__c                 C   s   dS )z6Skip the pair key, value if it matches a certain rule.Fr&   r<   r?   valr&   r&   r'   skip_key_valued   s   zConfigMap.skip_key_valuec                 C   s   t  }|t  | jr|d t| j D ],}| j| }| ||r'qt|t	r1| j
| }t|ts:t|}|d|t|f  q| S )Nr   %s=%s
)ioStringIOwriter(   r:   sortedkeysrJ   
isinstancebool	_bool_mapstrr4   getvalue)r<   bufr?   r3   r&   r&   r'   	to_stringh   s   




zConfigMap.to_stringc                 C   s   | j | d S r8   )r:   update)r<   updatesr&   r&   r'   rX   x   s   zConfigMap.updateN)__name__
__module____qualname____doc__rS   r=   r@   rB   rC   rD   rF   rG   rJ   rW   rX   r&   r&   r&   r'   r5   F   s    r5   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)
superr^   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<   
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 r8   )
r^   rd   re   rf   rg   r:   copyra   rb   rc   )r<   rr&   r&   r'   rn      s   z
Route.copyc                 C      | j | j| jd S N)basename)rf   re   rd   r;   r&   r&   r'   	path_ipv4      zRoute.path_ipv4c                 C   rp   rq   )rg   re   rd   r;   r&   r&   r'   	path_ipv6   ru   zRoute.path_ipv6c                 C   s   d|v S )N:r&   )r<   addressr&   r&   r'   is_ipv6_route   s   zRoute.is_ipv6_routeipv4c              	   C   s  |dvrt dt| t }|t  | jr|d d}t| j D ]}d|vr.q'|	dd}t| j| }t| jd|  }|dkr| 
|st| jd	|  }|d
 }|ddt| t|f  |ddt| t|f  |dd	t| t|f  d| }	|	| jv rt| jd|  }
|ddt| t|
f  q'|dkr| 
|rt| jd|  }d| | jv rdt| jd|   nd}
|d||||
| jf  q'| S )N)rz   ipv6zUnknown protocol '%s'r   ADDRESSr   GATEWAYrz   NETMASKr_   rK   METRICr{   PREFIXzmetric z%s/%s via %s %s dev %s
)
ValueErrorrT   rL   rM   rN   r(   r:   rO   rP   replacery   r4   rd   rU   )r<   protorV   reindexr?   indexaddress_valuegateway_valuenetmask_value
metric_keymetric_valueprefix_valuer&   r&   r'   rW      st   

zRoute.to_string)rz   )rZ   r[   r\   r]   r=   rn   propertyrt   rv   ry   rW   __classcell__r&   r&   rl   r'   r^   |   s    


r^   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).EthernetBondBridge
InfiniBandVlan)ethernetbondbridge
infinibandvlanr   c                    sr   t t|   g | _|| _| jd}t|||d|dd| _| jd| _|| _	|| _
|| jd< || _d S )Nroute_templatesrz   r{   )rj   rk   iface_templatesDEVICE)r`   r   r=   children	templatesrC   r^   routesiface_fn_tplkind_iface_namer:   re   )r<   
iface_nameri   r   r   	route_tplrl   r&   r'   r=      s   

zNetInterface.__init__c                 C      | j S r8   )r   r;   r&   r&   r'   rs   	     zNetInterface.namec                 C   s   || _ || jd< d S )Nr   )r   r:   )r<   r   r&   r&   r'   rs     s   c                 C   r   r8   )_kindr;   r&   r&   r'   r     r   zNetInterface.kindc                 C   s,   || j vr	t||| _| j | | jd< d S )NTYPE)iface_typesr   r   r:   )r<   r   r&   r&   r'   r     s   
c                 C   rp   rq   )r   re   rs   r;   r&   r&   r'   path  ru   zNetInterface.pathFc                 C   sH   t | j| j| j| jd}| j |_|rt| j|_|r"| j	 |_	|S )N)r   )
r   rs   re   r   r   r:   rn   listr   r   )r<   copy_childrencopy_routescr&   r&   r'   rn   #  s   zNetInterface.copyc                 C   s   |dkr
|dkr
dS dS )Nr   r   TFr&   rH   r&   r&   r'   rJ   .  s   zNetInterface.skip_key_value)r   )FF)rZ   r[   r\   r]   r   r=   r   rs   setterr   r   rn   rJ   r   r&   r&   rl   r'   r      s,    	





r   c                   @   s(  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g dZi Ze	e
d< d7ddZedd Zedd Zedd  Zed!d" Zed#d$ Zed%d& Zed'd( Zed7d)d*Zed7d+d,Zed-d. Zed/d0 Ze	d7d1d2Z		d8d3edee	 d4dfd5d6ZdS )9Rendererz7Renders network information in a /etc/sysconfig format.TFnone)ONBOOTUSERCTL	BOOTPROTOstaticauto)r   	STARTMODE)r   r   IPV6_FORCE_ACCEPT_RASTPAGEINGPRIOHWADDRMTU)	accept-ra
bridge_stpbridge_ageingbridge_bridgepriomac_addressmtu
BRIDGE_STPBRIDGE_AGEINGTIMEBRIDGE_PRIORITYLLADDR)r   r   r   r   r   ))	bond_modezmode=%s)bond_xmit_hash_policyzxmit_hash_policy=%s)bond_miimonz	miimon=%s)bond_min_linkszmin_links=%s)bond_arp_intervalzarp_interval=%s)bond_arp_ip_targetzarp_ip_target=%s)bond_arp_validatezarp_validate=%s)bond_ad_selectzad_select=%s)bond_num_grat_arpznum_grat_arp=%s)bond_downdelayzdowndelay=%s)bond_updelayz
updelay=%s)bond_lacp_ratezlacp_rate=%s)bond_fail_over_maczfail_over_mac=%s)bond_primaryz
primary=%s)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   )rC   r   r   r   r   r   r   )r<   confignm_conf_pathr&   r&   r'   r=   p  s    zRenderer.__init__c                 C   s   t | j|i }|| dD ]$}||}|d ur5|dkr'|d dvr'q| j| |}|r5|||< qd|v rJ|d rL|d dkrNd|d< d S d S d S d S )	N)r   r   r   r   type)physicalr   	wakeonlanr   zwol gETHTOOL_OPTS)rn   deepcopyiface_defaultsrC   rX   cfg_key_maps)clsiface	iface_cfgr   flavor_defaultsold_key	old_valuenew_keyr&   r&   r'   _render_iface_shared  s$   

zRenderer._render_iface_sharedc                 C   sP  |dkrd|d< d|v rd|d< | d nd|d< t|t|jdD ]R\}}d}|d	}|d
ks7|dkrr|dkrP|d dv rFd|d< nd
|d< d|d< n|dkri|dkrid|d< d|d< d|d< d|d< nd|d< d|d< n|dkr|dkr|d dv rd|d< nd
|d< d|d< nd|d< d|d< d|d< d|d< n|dkr|dkr|d dv rd|d< nd
|d< d|d< nd|d< d|d< n|dv r|d }	d|d< |dkr|	dvrd|d< n|dv r?t|r|dkrd}d|d< d|v r,t||v o|d || k}
|
rtd |j	|| |d  t|r&|dkrn|d ||< n|d ||< t|r>|dkr>d|d!< d|d< n!|d"krW|dkrPt
d#| n||v |d$< n	td%||j	f |d&d"krv|dkrrd"|d'< q#d|d$< q#d(}d(}t|t|jdD ] \}}|d	}d)|v r|dkr|d) |d*< |d+v r|dkr|r|d dkrd|d,< q|tv rq|dv rt|r|d- }d.|d/ |d0 f }|d1kr|dkr||d2< nQ||d3< nL|d-kr|dkr||d4< n=||d5< n8|dkr||d6| < n,|d5  d7| 7  < n!|d- }|d1kr!d8nt|}|d/ |d9| < t|d0 |d:| < d;|v rY|dkrYd|d<< t|d; rS|d; |d=< n|d; |d>< d?|v rl|dkrld7|d? |d@< dA|v r|dkrt|dA dBkrt
dC|j	t|dA  t|dA d dB d-D ]\}}||dDt| < qqd S )ENr   r   r   BRIDGEdhcpr   startr   r   dhcp6zipv6_dhcpv6-stateful)dhcp4r   managedDHCLIENT6_MODEr   TDHCPV6CIPV6INITFIPV6_AUTOCONFIPV6_FAILURE_FATALzipv6_dhcpv6-statelessinfoz-SDHCPV6C_OPTIONS
ipv6_slaac)r   r   r   )r   static6IPV6_MTUr   zZNetwork config: ignoring %s device-level mtu:%s because ipv4 subnet-level mtu:%s provided.r   manualz Unknown subnet type setting "%s"r   z1Unknown subnet type '%s' found for interface '%s'r   r   r|   metricr   r   r   DHCLIENT_SET_DEFAULT_ROUTEr_   z%s/%srx   r)   r   IPADDR6IPV6ADDR	IPADDR6_1IPV6ADDR_SECONDARIESz
IPADDR6_%dr   r   IPADDRr   gatewayDEFROUTEIPV6_DEFAULTGWr~   
dns_searchDOMAINdns_nameservers   z6%s has %d entries in dns_nameservers. Only 3 are used.DNS)rF   	enumerater!   r   rC   r   rR   LOGwarningrs   debugr   r   rT   r
   r	   r"   )r   r   subnetshas_default_router   r%   subnetmtu_keysubnet_typebootproto_inmtu_mismatch
ipv4_index
ipv6_index	ipv6_cidrsuffkr&   r&   r'   _render_subnets  s  





































zRenderer._render_subnetsc                 C   s>  |dkrd S t |t|jdD ]\}}|d}|dg D ]}}|dp*t|d }	t|r||tvr||dr;|jsC|drJ|jrJt	d|j
 d	|d
< |d dv rXd	|d< d|v rq|	rh|d |d< d	|_n	|d |d< d	|_d|v r{|d |d< qdD ]\}
}|
|v r| |j }||
 ||< q~| jd7  _qqd S )Nr   r   r   r   r{   r  rz   z?Duplicate declaration of default route found for interface '%s'Tr	  r   r  r  r
  r~   r   r   ))r  r~   )r   r   )r)   r   )netmaskr   )r*   r}   r_   )r  r!   r   rC   r	   r-   r   rb   rc   r   rs   ra   )r   r   	route_cfgr  r   _r  r  r+   is_ipv6r   new_namer   r&   r&   r'   _render_subnet_routese  sX   
	zRenderer._render_subnet_routesc           	      C   s   g }| j D ].\}}||ddg}|D ]}||v r2|| }t|ttfr)d|}|||   nqq|rL|dkrCd||d< d S d||d< d S d S )Nr#  -r   r   BONDING_MODULE_OPTSBONDING_OPTS)bond_tpl_optsr   rQ   tupler   r"   append)	r   r   r   r   	bond_optsbond_key	value_tpl	bond_keys
bond_valuer&   r&   r'   _render_bonding_opts  s"   
zRenderer._render_bonding_optsc           
      C   s^   t j}||D ]$}|d }|dg }|| }|j}	| |||j| | ||	|| qd S )Nrs   r  )r   filter_by_physicaliter_interfacesrC   r   r   r  r&  )
r   network_stateiface_contentsr   physical_filterr   r   iface_subnetsr   r"  r&   r&   r'   _render_physical_interfaces  s    z$Renderer._render_physical_interfacesc                    s^  t d}t d}||D ]}|d  |  }| ||| |g}||j |D ]}	d|	d< |dkr8d|	_q+|drQ|dkrJ|d|d< n|d|d	< |d
g }
|j	}| 
||
|j| | |||
| t fdd||D }t|D ].\}}|dkrd| }nd| }|||< || }|dkrd|d< d|d< q} |d< d|d< q}qd S )Nr   bond-masterrs   TBONDING_MASTERr   r   r   MACADDRr  c                    s    g | ]}|d   kr|d qS )r:  rs   r&   ).0slave_ifacer   r&   r'   
<listcomp>  s
    z4Renderer._render_bond_interfaces.<locals>.<listcomp>zBONDING_SLAVE_%szBONDING_SLAVE%sr   r   hotplugr   MASTERSLAVE)r   filter_by_typefilter_by_attrr4  r2  extendr   r   rC   r   r   r  r&  rO   r  )r   r5  r6  r   bond_filterslave_filterr   r   master_cfgs
master_cfgr8  r"  bond_slavesr   
bond_slaveslavestr	slave_cfgr&   r?  r'   _render_bond_interfaces  s`   







z Renderer._render_bond_interfacesc              	   C   s   t d}||D ]d}|d }|| }|dkr/|d}|r#||d< |d |d |d< n%d|d	< d|_|d
 }	t|	|d }
||
vrPtd||	d	|
 |	|d< |dg }|j
}| |||j| | |||| q
d S )Nr   rs   r   vlan_idVLAN_ID.ETHERDEVICETVLANzvlan-raw-devicezIName '%s' for vlan '%s' is not officially supportedby RHEL. Supported: %sr   PHYSDEVr  )r   rD  r4  rC   rfindr   _supported_vlan_namesr  r   r"   r   r   r  r&  )r   r5  r6  r   vlan_filterr   r   r   rP  rdev	supportedr8  r"  r&   r&   r'   _render_vlan_interfaces  sB   

z Renderer._render_vlan_interfacesc           	         sd  g g  |   D ]A}|d D ]}d|v r|d  d|v r& |d  qd|v rIfdd|d d D 7   fdd|d d	 D 7  q| jrYfd
d| jD 7 | jrh  fdd| jD 7  ttt gstd S td}|rtj	
|rtt|}D ]}|| q D ]}|| qtd}t|}||s|d | }|S )Nr  r  r  dnsc                       g | ]}| vr|qS r&   r&   )r=  r\  found_nameserversr&   r'   r@  I  
    z(Renderer._render_dns.<locals>.<listcomp>nameserversc                    r]  r&   r&   r=  r0   found_dns_searchr&   r'   r@  N  r`  r0   c                    r]  r&   r&   )r=  
nameserverr^  r&   r'   r@  Y  r`  c                    r]  r&   r&   rb  rc  r&   r'   r@  _  r`  r   ;r   )r4  rF  r  dns_searchdomainsanyr!   r   
ResolvConfosr   isfiler   load_text_fileadd_nameserveradd_search_domainr(   rT   r1   )	r5  existing_dns_pathr   r  contentre  searchdomainheadercontent_strr&   )rd  r_  r'   _render_dns9  sZ   




zRenderer._render_dnsc                 C   sP   t d}| jr|ddd t|dkrd S dt dd| dg}|S )Nr   mainr\  r   r   r   )r   NetworkManagerConfr  set_section_keypairr!   r"   r(   rN   )r5  r   rp  outr&   r&   r'   _render_networkmanager_conf|  s   

z$Renderer._render_networkmanager_confc                 C   s|  dd | j |  D }td}||D ]}|d }|| }|dkr'd|_| D ]\}	}
|	|v r9||	 ||
< q+|dkrPd|v rP|drLd|d< nd|d< |d	rdd
}|dkr]d}|d	||< |dkrz|dg rzdd|d |d< |dg D ] }|| }|g}||j	 |D ]}|}|dkrd}||d< qq|dg }|j
}| |||j| | |||| qd S )Nc                 S   s    i | ]\}}| d r||qS )r   )r1   )r=  old_knew_kr&   r&   r'   
<dictcomp>  s    z6Renderer._render_bridge_interfaces.<locals>.<dictcomp>r   rs   r   r   onoffr   r<  	LLADDRESSbridge_portsz%sr   BRIDGE_PORTSr6   r   r  )r   itemsr   rD  r4  r   rC   r"   rF  r   r   r   r  r&  )r   r5  r6  r   bridge_key_mapbridge_filterr   r   r   r   r   r?   bridged_iface_namebridged_cfgbridged_cfgs
bridge_cfgbridge_valuer8  r"  r&   r&   r'   _render_bridge_interfaces  sd   





z"Renderer._render_bridge_interfacesc           
      C   sh   t d}||D ]'}|d }|| }d|_|dg }|j}	| |||j| | ||	|| q
d S )Nr   rs   r  )	r   rD  r4  r   rC   r   r   r  r&  )
r   r5  r6  r   	ib_filterr   r   r   r8  r"  r&   r&   r'   _render_ib_interfaces  s"   
zRenderer._render_ib_interfacesc                 C   sH  |s| j }i }| D ],}|d dkrq|d }t|||}|dkr,|d |d | ||| |||< q| ||| | ||| | ||| | ||| | 	||| i }	|
 D ]@\}}|sj|jr| |	|j< |jD ]}|r| |	|j< qt|jrt|jj|jjgddgD ]\}
}|
|	vr|j||	|
< qqa|	S )	z3Given state, return /etc/sysconfig files + contentsr   loopbackrs   r   r   r   rz   r{   )r   r4  r   rF   r   r9  rO  r[  r  r  r  r   rW   r   r   ziprt   rv   )r   ri   r5  r   r   r6  r   r   r   contentscpathr   r&   r&   r'   _render_sysconfig  sF   




zRenderer._render_sysconfigr5  returnc                 C   sT  |s| j }d}t|| j}| j||| j|d D ]\}}t||| q| j	r@t|| j	}| j
||d}	|	r@t||	| | jrYt|| j}
| ||}|rYt|
|| | jrq| |}t|| j}tj|||dd t||d}|drttj| t dg}|jr|d	 |d
 t|d|d | d S d S )Ni  )r   )ro  T)rp  modepreserve_moder   r*   zNETWORKING=yeszNETWORKING_IPV6=yeszIPV6_AUTOCONF=nor   )r   r   target_pathr   r  r   r  r   
write_filer   rt  r   ry  r   _render_persistent_netrC   r2   
ensure_dirrj  r   dirnamer(   use_ipv6r,  r"   )r<   r5  r   target	file_moderi   r   datar   resolv_contentr   nm_conf_contentnetrules_contentr   sysconfig_pathnetcfgr&   r&   r'   render_network_state  s\   






zRenderer.render_network_stater8   )NN)rZ   r[   r\   r]   r   r   r+  r*  r   dict__annotations__r=   classmethodr   r   r&  r2  r9  rO  r[  staticmethodrt  ry  r  r  r  r   r   r  r&   r&   r&   r'   r   4  s|   
 		


 H
=


>
&B
<
*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 )rY  vid)formatint)r=  vr  r&   r'   r@  @  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'   rW  =  s   rW  c                 C   s0   t  d tvr
dS t| rdS t| rdS dS )NvariantFT)r   system_infoKNOWN_DISTROSavailable_sysconfigavailable_nm_ifcfg_rhr  r&   r&   r'   	availableK  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  U  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 )
Nifupifdownz/sbinz	/usr/sbin)r0   r  Fz/etc/sysconfig/network-scripts/network-functionszetc/sysconfig/configT)r   whichrj  r   rk  r  )r  expectedr0   pexpected_pathsr&   r&   r'   r  `  s   r  )r   r8   )&rn   r  rL   loggingrj  r/   typingr   r   	cloudinitr   r   cloudinit.distros.parsersr   r   cloudinit.netr   r	   r
   r   r   cloudinit.net.network_stater   	getLoggerrZ   r  r  r(   r-   r4   r5   r^   r   r   rW  r  r  r  r&   r&   r&   r'   <module>   s<   

6nJ      


