
    쑛hT                         d dl Z d dl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
j*                        ZddZy)    N)AnyDictListOptional)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 d
| _         y )N)
MatchLinkNetworkDHCPv4DHCPv6AddressRouteNetDevVLANBond)	conf_dict)selfs    r   __init__zCfgParser.__init__9   s)    
r   c                 >   | j                   j                         D ]  }||k(  s	| j                   |   j                  | d|        t        t        j                  | j                   |               | j                   |<   | j                   |   j                           y )N=r.   keysr   r   r   fromkeyssort)r/   secr   valks        r   update_sectionzCfgParser.update_sectionG   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.
        r2   Nr3   )r/   r7   ridr   r8   r9   s         r   update_route_sectionzCfgParser.update_route_sectionN   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k(  r:t        |      D ]+  }|d| dz  }t        ||         D ]
  }|| dz  } |dz  }- j|d| dz  }t        |      D ]
  }|| dz  } |dz  } |S )N r)   [z]


r*   
)r   r.   r   r   )r/   contentsr9   vens         r   get_final_confzCfgParser.get_final_conf^   s   "4>>24>>//12 	!DAqI~ 2A!A3c!D 11H2g %A!A3c
*H#AaD\ - qcH,-$H	% as#J& )A1#R(H)D !	!$ r   N)__name__
__module____qualname__r0   r:   r=   rG    r   r   r"   r"   8   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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/)getrO   rP   )r/   configs     r   r0   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_addressrW   )r   r:   )r/   ifacerS   r7   
match_dictr9   rD   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MTUBytesrY   rZ   r\   r[   optionalRequiredForOnlineno)rQ   r:   )r/   r]   rS   r7   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|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)gatewaynetworkmetricr?   prefix/rl   N)r   r=   )	r/   r<   confrS   r7   route_cfg_maprn   r9   rD   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 ) Nre   r&   r   subnetsrY   >   dhcpdhcp4ipv4ipv6yesdhcp6routesr   addressrn   ro   r)   rh   DNSDomains)r~   rk   dns_nameservers
dns_searchrk   r*   azGGateway %s is not contained within subnet %s, adding GatewayOnLink flagGatewayOnLink>   r   r    DHCPz	accept-raIPv6AcceptRA)rQ   rr   r   r:   r=   r
   LOGdebugjoinr   bool)r/   r]   rS   ru   r7   r<   rE   tiaddrsubnet_cfg_mapr9   rD   r8   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dhcp6domainry   re   routezInvalid dhcp4domain value - %sr   r'   r(   
UseDomains)strcasefoldr   translate_bool
ValueErrorr   warningr:   )r/   drS   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   )rQ   versiondns_searchdomainsr   r:   r   )r/   r]   rS   r   r7   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	UseRoutesru   
-overridesry   ipvDHCPv)updater   r:   )	r/   rS   deviceru   r   dhcp_config_mapsdhcp_overridesr9   rD   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-rA   )r   r   endswithr   
write_filechownbyname)r/   linkrp   nwk_dirextnet_fn_ownernet_fns          r   create_network_filezRenderer.create_network_fileE  sa    (		4d;9N4&6== 9D%|<r   network_state	templatesr   c                    | j                   }|rt        j                  |      |z   }t        j                  |       | j                  |      }|j                  di       }|j                  di       }|j                         D ]  \  }}	| j                  ||	|        |j                         D ]  \  }}	| j                  ||	|d        |j                         D ]  \  }}	| j                  ||	|d        y )Nvlan_netdevbond_netdevz.netdev)r   )	rP   r   target_pathr   
ensure_dir_render_contentpopr   r   )
r/   r   r   targetnetwork_dirrl   r   r   r9   rD   s
             r   render_network_statezRenderer.render_network_stateP  s     ++**62[@K$&&}5kk-4kk-4MMO 	8DAq$$Q;7	8  %%' 	GDAq$$Q;I$F	G  %%' 	GDAq$$Q;I$F	Gr   c                 b   i }i }i }d|j                   v r | j                  |      }|d   }|d   }||d<   d|j                   v r | j                  |      }|d   }|d   }||d<   |j                         D ]8  }	t	               }
|	d   }|j                  |      }|r|
j                  dd	|       |	d
   s,|j                  d      r|d   j                  |      }|r||	d
<   |j                  |      }|r|
j                  dd|       |	d
   s,|j                  d      r|d   j                  |      }|r||	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 )Nvlansr   	vlan_linkbondsr   	bond_linkrW   r&   r,   r\   
macaddressr-   r   cr}   r   	ethernetszset-name)r   6ru   domainr   r   z has both dhcpzdomain and dhcpz*-overrides.use-domains configured. Use one)rR   render_vlansrender_bondsiter_interfacesr"   rQ   r:   r_   rf   r   r   iter_routesrr   r   r   r   RuntimeErrorr   r   rG   )r/   r   ret_dictr   r   	vlan_dictr   	bond_dictr   r]   rS   
iface_namevlan_link_namemacbond_link_namer   ru   r<   r   rW   dev_namedev_cfgr   r   	exceptions                            r   r   zRenderer._render_contenti  s+   		bii))"-I#M2K!+.I&1H]#bii))"-I#M2K!+.I&1H]#'') M	:E+CvJ&]]:6N""9fnE 'IMM,,G-11*=+.E-(&]]:6N""9fnE 'IMM,,G-11*=+.E-(..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9[M	:^ r   c                    i }i }i |d<   |j                   j                  di       }|j                         D ]  \  }}|j                  d      }|j                  d      }||t        j	                  d|       D|||<   t               }	|	j                  dd|       |	j                  ddd	       |j                  d
      }
|
r|	j                  dd|
       |j                  d      }
|
r+|
j                         }
|	j                  dd|
       |
|d   |<   |	j                  dd|       |	j                         ||<    ||d}|S )Nr   r   idr   z)Skipping VLAN %s - missing 'id' or 'link'r+   rU   Kindvlanra   rb   r[   r,   Id)r   r   )	rR   rQ   r   r   r   r"   r:   lowerrG   )r/   r   vlan_link_infovlan_ndev_configsr   	vlan_namevlan_cfgvlan_idparentrS   r8   r   s               r   r   zRenderer.render_vlans  sU   )+')|$		gr*#(;;= 	@Ixll4(G\\&)F&.? %.N6" +Cx;x8,,u%C""8Z=,,|,Ciik""8\3?:=|,Y7vtW5+.+=+=+?i(9	@> -'
 r   c           	         i }i }d}i |d<   |j                   j                  di       }|j                         D ]  \  }}|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                         }|
j                  dd|       ||d   |<   |j                  di       }d|v r|
j                  |d|d          d|v r|
j                  |d|d    d       d|v r|
j                  |d|d    d       d|v r|
j                  |d|d    d       d|v r|
j                  |d|d    d       d|v r<|d   }t        |t              r|g}dj                  |      }|
j                  |d|       d|v r|
j                  |d|d          d|v r|
j                  |d|d          d |v r|
j                  |d!|d           d"|v r|
j                  |d#|d"          d$|v r|
j                  |d%|d$          d&|v r|
j                  |d'|d&          d(|v r|
j                  |d)t        |d(                d*|v r-|
j                  |d+t        |d*         j                                |
j                         ||<    ||d,}|S c c}	w )-Nr-   r   r   
interfacesz'Skipping bond %s - missing 'interfaces'r+   rU   r   bondra   rb   r[   
parametersmodeModezmii-monitor-intervalMIIMonitorSecmsupdelay
UpDelaySec	downdelayDownDelaySeczarp-intervalARPIntervalSeczarp-ip-targetr   ARPIPTargetszarp-validateARPValidatezarp-all-targetsARPAllTargetszprimary-reselectPrimaryReselectPolicyz	lacp-rateLACPTransmitRateztransmit-hash-policyTransmitHashPolicyz	ad-selectAdSelectz	min-linksMinLinkszall-slaves-activeAllSlavesActive)r   r   )rR   rQ   r   r   r   r   r"   r:   r   r   r   r   rG   )r/   r   bond_link_infobond_ndev_configsr   r   	bond_namebond_cfgr   r]   rS   r8   paramstargetsip_listr   s                   r   r   zRenderer.render_bonds  s   )+')|$		gr*#(;;= h	@Ix!l3J=y !!"L5)#3"LM +Cx;x8,,u%C""8Z=,,|,Ciik""8\3?:=|,Y7 \\,3F""7FF6NC%/""#456b9 F"""\fY.?-@+C f$""^{0C/DB-G '""-&2H1I/L &( 1gs+&iG((7+""7NGD'""]F>,B !F*""_f5F.G "V+""+-. f$""/1D &/""(12 f$""7J{8KLf$""ZVK-@)A #f,""%234::< ,/+=+=+?i(Qh	@V -'
 M #Ms   8
L

N)z.network)NN)rH   rI   rJ   __doc__r0   r"   r_   rf   rr   r   r   r   r   r   r   r   r   r   r   r   r   rK   r   r   rM   rM   x   s    
 &?	 ?D9 D0?	 ?D;) ;$II I< I"P	 P8	= %)	G#G D>G
 
G2`, `D(| ( (Tv| v vr   rM   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   	availabler  n  s;    k"H6"F zz!F+ r   r  )loggingtypingr   r   r   r   	cloudinitr   r   cloudinit.netr	   r
   cloudinit.net.network_stater   	getLoggerrH   r   r   r   r   r"   rM   r  rK   r   r   <module>r$     s     , ,   B 4g!	Dd3i( 	T#tCy.-A 	3 3 6= =@sx   slr   