
    th_                        d dl Z d dlmZ d dlmZmZmZmZmZm	Z	 d dl
mZmZ d dlmZmZ d dlmZ  e j$                  e      Zdeeee   f   deeee   f   fd	Zdedefd
Z G d d      Z G d dej2                        ZddZy)    N)defaultdict)AnyCallableDictListOptionalTuple)subputil)renderershould_add_gateway_onlink_flag)NetworkStatedatareturnc                 V    i }| j                         D ]  \  }}t        |      ||<    |S )z
    Normalize a dictionary of lists.
    - Assumes top-level keys map to lists.
    - Each list and any nested dicts/lists will be recursively normalized.
    )items_normalize_value)r   
normalizedkeyvalues       8/usr/lib/python3/dist-packages/cloudinit/net/networkd.py	normalizer      s6     Jjjl 2
U*51
32    c                 F   t        | t              r%i }t        |       D ]  }t        | |         ||<    |S t        | t              rJg }| D ]7  }t        |t        t        f      rt        |      }n|}|j                  |       9 	 t        |      S | S # t        $ r |cY S w xY w)z
    Recursively normalize a dictionary or list:
    - Dicts: keys sorted, values normalized
    - Lists: items normalized and sorted (if comparable)
    )
isinstancedictsortedr   listappend	TypeError)r   r   r   normalized_itemsitemnormalized_items         r   r   r      s     $
$< 	:C.tCy9JsO	:	D$	 	5D$t-"24"8"&##O4	5	$*++ K  	$##	$s   
B B B c                   $    e Zd Zd Zd Zd Zd Zy)	CfgParserc                 ,    g g g g g g i g g g g i d| _         y )N)MatchLinkNetworkDHCPv4DHCPv6AddressRouteNetDevVLANBondBridgeRoutingPolicyRule)	conf_dict)selfs    r   __init__zCfgParser.__init__:   s/    !#
r   c                 >   | j                   j                         D ]  }||k(  s	| j                   |   j                  | d|        t        t        j                  | j                   |               | j                   |<   | j                   |   j                           y )N=r3   keysr   r   r   fromkeyssort)r4   secr   valks        r   update_sectionzCfgParser.update_sectionJ   s    $$& 	)ACxq!((C5#8$(t~~a7H)I$Jq!q!&&(		)r   c                    | j                   j                         D ]  }||k(  s	|| j                   |   vrg | j                   |   |<   | j                   |   |   j                  | d|        t        t        j                  | j                   |   |               | j                   |   |<   | j                   |   |   j                           y)z
        For each route section we use rid as a key, this allows us to isolate
        this route from others on subsequent calls.
        r7   Nr8   )r4   r<   ridr   r=   r>   s         r   update_route_sectionzCfgParser.update_route_sectionQ   s    
 $$& 		.ACxdnnQ//-/DNN1%c*q!#&--Qsen=)-MM$.."3C"89*q!#& q!#&++-		.r   c                    d}t        | j                        | _        t        | j                  j                               D ]  \  }}|s	|dk(  rt        |      D ]  }|d| d| dz  } +|dv r:t        |      D ]+  }|d| dz  }t        ||         D ]
  }|| dz  } |dz  }- i|d| dz  }t        |      D ]
  }|| dz  } |dz  } |S )N r,   [z]


)r-   r2   
)r   r3   r   r   )r4   contentsr>   vens         r   get_final_confzCfgParser.get_final_confa   s   "4>>24>>//12 	!DAqI~ 2A!A3c!D 11H244 %A!A3c
*H#AaD\ - qcH,-$H	% as#J& )A1#R(H)D !	!$ r   N)__name__
__module____qualname__r5   r?   rB   rL    r   r   r%   r%   9   s    
 ). r   r%   c                       e Zd ZdZddZdefdZdefdZdefdZdefdZ	defd	Z
ded
efdZdefdZddZ	 	 ddedee   ddfdZdefdZdefdZd
efdZd
edefdZd
edefdZd
edefdZy)Rendererz
    Renders network information in /etc/systemd/network

    This Renderer is currently experimental and doesn't support all the
    use cases supported by the other renderers yet.
    Nc                 h    |si }|j                  dd      | _        |j                  dd      | _        y )Nresolve_conf_fnz/etc/systemd/resolved.confnetwork_conf_dirz/etc/systemd/network/)getrT   rU   )r4   configs     r   r5   zRenderer.__init__   s:    F%zz; 
 !'

 7!
r   cfgc                     d}ddd}|d   dk(  rd|d<   |sy |j                         D ]&  \  }}||v s||   s|j                  ||||          ( |d	   S )
Nr'   NameDriver)namedrivertypephysical
MACAddressmac_addressr\   )r   r?   )r4   ifacerX   r<   
match_dictr>   rI   s          r   generate_match_sectionzRenderer.generate_match_section   s}    


 =J&(4J}%$$& 	5DAqEzeAh""3584	5 V}r   c                     d}|sy |j                  d      r|j                  |d|d          |d   dk7  r'|j                  d      r|j                  |d|d          d|v r|d   r|j                  |d	d
       y y y )Nr(   mtuMTUBytesr^   r_   ra   r`   optionalRequiredForOnlineno)rV   r?   )r4   rb   rX   r<   s       r   generate_link_sectionzRenderer.generate_link_section   s    99UsJe==J&599]+CsL%2FG5#4s$7> $5r   c                     d}ddddd}d}d|v rd	|d    }|j                         D ]+  \  }}||vr|d
k(  r||z  }|j                  ||||   |       - y)zy
        Parse a route and use rid as a key in order to isolate the route from
        others in the route dict.
        r-   GatewayDestinationMetricTable)gatewaynetworkmetrictablerD   prefix/rr   N)r   rB   )	r4   rA   confrX   r<   route_cfg_mapru   r>   rI   s	            r   parse_routeszRenderer.parse_routes   s    
  $	
 th()FJJL 	DDAq%I~V$$S#}Q/?C	Dr   c           	      P   d}d}d}|j                  dg       D ];  }|d   }|dv r|dk(  rd}n|dk(  rd	}n|d
k(  r|dk(  rd}n|dk(  rd	}d|v r*|d   r%|d   D ]  }| j                  d| ||       |dz   } d|v sd|d   }	d|v r|	d|d    z  }	ddddd}
|j                         D ]  \  }}|dk(  r|j                  d|
|   |	       "|dk(  rZ|j	                  dd| |
|   |       t        ||	      r.t        j                  d||	       |j	                  dd| dd	       |dz   }|dv s|j                  ||
|   dj                  |              > |j                  |d|       t        |j                  d      t              rd}|d   rd	}|j                  |d|       |S ) Nrj   r)   r   subnetsr^   >   dhcpdhcp4ipv4ipv6yesdhcp6routesr   addressru   rv   r,   rm   DNSDomains)r   rq   dns_nameservers
dns_searchrq   r-   azGGateway %s is not contained within subnet %s, adding GatewayOnLink flagGatewayOnLink>   r   r    DHCPz	accept-raIPv6AcceptRA)rV   ry   r   r?   rB   r   LOGdebugjoinr   bool)r4   rb   rX   r|   r<   rA   rJ   tiaddrsubnet_cfg_mapr>   rI   r=   s                 r   parse_subnetszRenderer.parse_subnets   s&   9b) 1	PA&	A%%4<!DV^ Dg4<!DV^ D1}88 "A %%#iC8'C	"
 A~|q=a(}--D((',"+	" GGI PDAqI~**9nQ6GNi 00#qYq0A1 :!TBII!= ! $	  44 '1SEOU "Ag??**3q0A388A;O+P91	Pf 	3-eii,d3C[!sNC8r   c                    dD ]\  }||vrt        ||         j                         }	 t        j                  |      }|rdnd}|dk(  rd}nd}|j                  |d	|       ^ y # t        $ r  |dk7  rt
        j                  d|       d}Y Hw xY w)
N)dhcp4domaindhcp6domainr   rj   routezInvalid dhcp4domain value - %sr   r*   r+   
UseDomains)strcasefoldr   translate_bool
ValueErrorr   warningr?   )r4   drX   r"   retsections         r   dhcp_domainzRenderer.dhcp_domain
  s    2 	;D1}ag,'')C))#."e
 }$""wc:	;  '>KK @#FCs   A##&BBnsc                 ~   d}|j                  d      }|s)|j                  dk(  r|j                  |j                  d}n|s|j                  dk(  ry |j                  d      r%|j	                  |ddj                  |d                |j                  d	      r&|j	                  |d
dj                  |d	                y y )Nr)   dnsr   )searchnameservers   r   r   r   r   r   )rV   versiondns_searchdomainsr   r?   r   )r4   rb   rX   r   r<   r   s         r   	parse_dnszRenderer.parse_dns  s    iirzzQ..!11C q778sIsxxH/FG77=!sE388C4F+GH "r   c                     ddddd}|dk(  r|j                  ddd	d
dd       d| d|v rJ|dd| fv r@|d| d   }|j                         D ]#  \  }}||v s|j                  d| |||          % y y y )Nzuse-dnsuse-domainszuse-hostnamezuse-ntp)UseDNSr   UseHostnameUseNTP4zsend-hostnamehostnamezroute-metriczuse-mtuz
use-routes)SendHostnameHostnameRouteMetricUseMTU	UseRoutesr|   
-overridesr   ipvDHCPv)updater   r?   )	r4   rX   devicer|   r   dhcp_config_mapsdhcp_overridesr>   rI   s	            r   parse_dhcp_overrideszRenderer.parse_dhcp_overrides-  s    ')	
 c>##$3 *#1'!- '*%/D'O=
 5
 $d7):$>?N(..0 P1&&&wi'8!^A=NOP5
/r   c                     d}t         j                  d|       | d| | }|j                  d      r|d d }t        j                  ||       t        j
                  |||       y )Nzsystemd-networkz Setting Networking Config for %sz10-cloud-init-rF   )r   r   endswithr   
write_filechownbyname)r4   linkrw   nwk_dirextnet_fn_ownernet_fns          r   create_network_filezRenderer.create_network_fileI  sa    (		4d;9N4&6== 9D%|<r   network_state	templatesr   c                 l   | j                   }|rt        j                  |      |z   }t        j                  |       | j                  |      }|j                  di       }|j                  di       }|j                  di       }|j                         D ]  \  }	}
| j                  |	|
|        |j                         D ]  \  }	}
| j                  |	|
|d        |j                         D ]  \  }	}
| j                  |	|
|d        |j                         D ]  \  }	}
| j                  |	|
|d        y )Nvlan_netdevbond_netdevbridge_netdevz.netdev)r   )	rU   r
   target_pathr   
ensure_dir_render_contentpopr   r   )r4   r   r   targetnetwork_dirrr   r   r   r   r>   rI   s              r   render_network_statezRenderer.render_network_stateT  sC    ++**62[@K$&&}5kk-4kk-4OR8MMO 	8DAq$$Q;7	8  %%' 	GDAq$$Q;I$F	G  %%' 	GDAq$$Q;I$F	G "'') 	GDAq$$Q;I$F	Gr   c                     d}d}|D ]A  }|j                         D ]'  \  }}|j                  |||j                         |       ) |dz  }C y )Nr   r2   r   )r   rB   
capitalize)r4   policyrX   rA   r   r=   r>   rI   s           r   parseRoutingPolicyzRenderer.parseRoutingPolicyq  sY    ! 	C		 F1((c1<<>1EF1HC	r   nsCfgc                 v    i }d}dD ]/  }||vr||   j                         D ]  \  }}||v s||   ||<    1 |S )Nzrouting-policy)	ethernetsbondsvlansbridges)r   )r4   r   routingPoliciesr   r   rb   settingss          r   extractRoutingPolicieszRenderer.extractRoutingPoliciesy  sc    A 	;Ge##(>#7#7#9 ;x(?-5c]OE*;	; r   c                    i }i }i }i }d|j                   v r | j                  |      }|d   }|d   }||d<   d|j                   v r | j                  |      }|d   }	|d   }|	|d<   d|j                   v r | j                  |      }
|
d   }|
d	   }||d<   | j	                  |j                         }|j                         D ]  }t               }|d
   }|j                  |g       }|D ]  }|j                  dd|        |j                  |      }|r| j                  ||       |j                  |      }|r|j                  dd|       |j                  |      }|r|d   j                  |i       j                  |      }|r|j                  dd|       |d   j                  |i       j                  |      }|r|j                  dd|       |j                  dd|       | j                  ||      }| j                  ||       | j                  ||      }| j                  |||       d}|j                         D ]  }| j                  d| ||       |dz   } |j                   dk(  r|d
   }|j                   d   j#                         D ]"  \  }}d|v s|j                  d      |k(  s |} n ||j                   d   v ru|j                   d   |   }| j%                  ||       dD ]L  }d| d|v r.d|j                  d| di       v r| d| d| d }t'        |      | j)                  ||||       N |j+                  ||j-                         i        |S )!Nr   r   	vlan_linkr   r   	bond_linkr   r   bridge_linkr\   r)   r/   r0   	path-costr1   Costport-priorityPriorityr   cr   r   r   zset-name)r   6r|   domainr   r   z has both dhcpzdomain and dhcpz*-overrides.use-domains configured. Use one)rW   render_vlansrender_bondsrender_bridgesr   iter_interfacesr%   rV   r?   r   rd   rk   r   r   iter_routesry   r   r   r   RuntimeErrorr   r   rL   ) r4   r   ret_dictr   r   r   	vlan_dictr   	bond_dictr   bridge_dictr   r   rb   rX   
iface_namevlan_link_namer   rPolicybond_link_namebridge_link_namer=   r   r|   rA   r   r\   dev_namedev_cfgr   r   	exceptions                                    r   r   zRenderer._render_content  s   		bii))"-I#M2K!+.I&1H]#bii))"-I#M2K!+.I&1H]#		!--b1K'8M%m4K(5H_%55bii@'') W	:E+CvJ&]]:r:N# 9""9fa89 &))*5G''5&]]:6N""9fnE*z:,S)2.S_ 
 &&x=  0S)2.S_ 
 &&xSA""9h8HI..uc:D&&uc2%%eS1DNN5#r*C)  !!AcU)UC8Ag	 zzQ&+Fm *,;)?)E)E)G "%Hg!W,";;z2d:#+D!	"
 299[11YY{3D9F $$VS1#- N"7)62f< -%zzD	*DbI!J $(&wi @,,39 57!8 &
 #/y"9911#vtWMN OOT3#5#5#789oW	:r r   c                    t        t              }i }|j                  j                  di       }|j	                         D ]  \  }}|j                  d      }|j                  d      }||t
        j                  d|       D||   j                  |       t               }	|	j                  dd|       |	j                  ddd       |j                  d	      }
|
r|	j                  dd
|
       |j                  d      }
|
r!|	j                  dd|
j                                |	j                  dd|       |	j                         ||<   
 ||dS )Nr   idr   z)Skipping VLAN %s - missing 'id' or 'link'r.   rZ   Kindvlanrf   rg   
macaddressr`   r/   Id)r   r   )r   r   rW   rV   r   r   r   r   r%   r?   lowerrL   )r4   r   vlan_link_infovlan_ndev_configsr   	vlan_namevlan_cfgvlan_idparentrX   r=   s              r   r   zRenderer.render_vlans  sA   $T*		gr*#(;;= 	@Ixll4(G\\&)F&.? 6")))4 +Cx;x8,,u%C""8Z=,,|,C""8\399;GvtW5+.+=+=+?i(5	@: -'
 	
r   c           
         i }i }d}|j                   j                  di       }|j                         D ]3  \  }}|j                  d      }|st        j	                  d|       1|j                  |D 	ci c]  }	|	| c}	       t               }
|
j                  dd|       |
j                  ddd       |j                  d	      }|r|
j                  dd
|       |j                  d      }|r!|
j                  dd|j                                |j                  di       }t        t        t        t        t        t        gt        f   f   f   }i ddt        fddd fddt        fddd fddt        fddd fddt        fdd t        fd!d"t        fd#d$t        fd%d&d' fd(d)t        fd*d+t        fd,d-t        fd.d/t        fd0d1t        fd2d3d4 f}|j                         D ])  \  }\  }}||v s|
j                  || |||                + d5|v r:|d5   }t        |t              r|g}|
j                  |d6d7j                  |             |
j!                         ||<   6 ||d8S c c}	w )9Nr0   r   
interfacesz'Skipping bond %s - missing 'interfaces'r.   rZ   r  bondrf   rg   r	  r`   
parametersz	ad-selectAdSelectzall-slaves-activeAllSlavesActivec                 4    t        |       j                         S N)r   r  rI   s    r   <lambda>z'Renderer.render_bonds.<locals>.<lambda>F  s    c!flln r   zarp-all-targetsARPAllTargetszarp-intervalARPIntervalSecc                     |  dS NmsrP   r  s    r   r  z'Renderer.render_bonds.<locals>.<lambda>I  s    s"X r   zarp-validateARPValidatez
down-delayDownDelaySecc                     |  dS r  rP   r  s    r   r  z'Renderer.render_bonds.<locals>.<lambda>K  s    A3b r   zfail-over-mac-policyFailOverMACPolicyzgratuitous-arpGratuitousARPz	lacp-rateLACPTransmitRatezlearn-packet-intervalLearnPacketIntervalSeczmii-monitor-intervalMIIMonitorSecc                     |  dS r  rP   r  s    r   r  z'Renderer.render_bonds.<locals>.<lambda>P  s    qcH r   z	min-linksMinLinksmodeModezpackets-per-slavePacketsPerSlavezprimary-reselect-policyPrimaryReselectPolicyztransmit-hash-policyTransmitHashPolicyzup-delay
UpDelaySecc                     |  dS r  rP   r  s    r   r  z'Renderer.render_bonds.<locals>.<lambda>V  s    s"X r   zarp-ip-targetsARPIPTargetsr   )r   r   )rW   rV   r   r   r   r   r%   r?   r  r   r   r	   r   objectr   r   rL   )r4   r   bond_link_infobond_ndev_configsr   r   	bond_namebond_cfgr  rb   rX   r=   paramsParamMapType	param_mapr   option	formattertargetss                      r   r   zRenderer.render_bonds   s   )+		gr*#(;;= =	@Ix!l3J=y !!"L5)#3"LM +Cx;x8,,u%C""8Z=,,|,C""8\399;G \\,3FU3&30G+G%H HIL'j#.'#%,&' "OS#9' !13E F'  4' ~/AB' ')<c(B' !?C"8' 0#6' (*BC)H' ':L(M' j#.'  !'" $&7%=#'$ *,CS+I%'& ')=s(C''( \+=>)'I. -6OO,= P((fi&=&&w	&+8NOP  6) !12gs+&iG""7NCHHW<MN+.+=+=+?i({=	@@ -'
 	
o #Ms   3
I/
c                 |   i i i d}i }|j                   j                  di       }|j                         D ]  \  }}|j                  dg       }|st        j	                  d|       2|D ]  }|||<   	 t               }	|	j                  dd|       |	j                  ddd       |j                  d	      }
|
r|	j                  dd
|
       |j                  d      }
|
r!|	j                  dd|
j                                |j                  di       }ddddddd}|j                         D ]B  \  }}|j                  |      }
|
st        |
t              r|
rdnd}
|	j                  d||
       D |j                  d      }
|
r|
|d   |<   |j                  d      }
|
r|
|d   |<   |	j                         ||<    ||dS )N)r	  r   r   r   r  z)Skipping bridge %s - missing 'interfaces'r.   rZ   r  bridgerf   rg   r	  r`   r  AgeingTimeSecForwardDelaySecHelloTimeSec	MaxAgeSecr   STP)zageing-timezforward-delayz
hello-timezmax-ageprioritystpr   rj   r1   r   r   )r   r   )rW   rV   r   r   r   r%   r?   r  r   r   rL   )r4   r   bridge_link_infobridge_ndev_configsr   bridge_name
bridge_cfgr  rb   rX   r=   r8  r:  r   sysd_keys                  r   r   zRenderer.render_bridgesj  s   ,
 !))--	2.'.}} 2	D#K#b9J?  $ 6*5 '6 +Cx=x:..'C""8Z=...C""8\399;G  ^^L"5F.!2,&&I "+!2 @Xjjo!#t,'*e&&x3?@ **[)C=@ -k:**_-CAD 1+>/2/A/A/C,e2	Dj 1+
 	
r   r  )z.network)NN)rM   rN   rO   __doc__r5   r%   rd   rk   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rP   r   r   rR   rR   {   s   
 &?	 ?D9 D2?	 ?D;) ;$II I< I"P	 P8	= %)	G#G D>G
 
G:i 
D 
s, sj$
| $
 $
LH
| H
 H
TA
 A
$ A
r   rR   c                 T    ddg}ddg}|D ]  }t        j                  ||      r y y)Nip	systemctlz	/usr/sbinz/bin)r   FT)r
   which)r   expectedr   ps       r   	availablerS    s;    k"H6"F zz!F+ r   r  )loggingcollectionsr   typingr   r   r   r   r   r	   	cloudinitr
   r   cloudinit.netr   r   cloudinit.net.network_stater   	getLoggerrM   r   r   r   r   r%   rR   rS  rP   r   r   <module>r[     s     # = =   B 4g!	Dd3i( 	T#tCy.-A 	3 3 6? ?Dp
x   p
fr   