2020import re
2121import shlex
2222import textwrap
23- from typing import Any , Dict , Optional
23+ from typing import Any , Dict , List , Optional , overload
2424
2525from cloudinit import atomic_helper , net , sources , subp , util
2626
4242
4343
4444class DataSourceOpenNebula (sources .DataSource ):
45+
4546 dsname = "OpenNebula"
4647
4748 def __init__ (self , sys_cfg , distro , paths ):
@@ -94,11 +95,9 @@ def _get_data(self):
9495 LOG .debug ("found datasource in %s" , cdev )
9596 break
9697
97- if not seed :
98+ if not seed or results is None :
9899 return False
99100
100- assert results is not None
101-
102101 # merge fetched metadata with datasource defaults
103102 md = results ["metadata" ]
104103 md = util .mergemanydict ([md , defaults ])
@@ -119,7 +118,10 @@ def _get_data(self):
119118
120119 def _get_subplatform (self ):
121120 """Return the subplatform metadata source details."""
122- assert self .seed is not None
121+ if self .seed is None :
122+ raise RuntimeError (
123+ "_get_subplatform called before datasource was read"
124+ )
123125 if self .seed_dir in self .seed :
124126 subplatform_type = "seed-dir"
125127 else :
@@ -151,33 +153,40 @@ class BrokenContextDiskDir(Exception):
151153
152154
153155class OpenNebulaNetwork :
154- def __init__ (self , context , distro , system_nics_by_mac = None ):
156+ def __init__ (
157+ self ,
158+ context : Dict [str , str ],
159+ distro : Any ,
160+ system_nics_by_mac : Optional [Dict [str , str ]] = None ,
161+ ) -> None :
155162 self .context = context
156163 if system_nics_by_mac is None :
157164 system_nics_by_mac = get_physical_nics_by_mac (distro )
158- self .ifaces = collections .OrderedDict (
159- [
160- k
161- for k in sorted (
162- system_nics_by_mac .items (),
163- key = lambda k : net .natural_sort_key (k [1 ]),
164- )
165- ]
165+ self .ifaces : collections .OrderedDict [str , str ] = (
166+ collections .OrderedDict (
167+ [
168+ k
169+ for k in sorted (
170+ system_nics_by_mac .items (),
171+ key = lambda k : net .natural_sort_key (k [1 ]),
172+ )
173+ ]
174+ )
166175 )
167176
168177 # OpenNebula 4.14+ provide macaddr for ETHX in variable ETH_MAC.
169178 # context_devname provides {mac.lower():ETHX, mac2.lower():ETHX}
170- self .context_devname = {}
179+ self .context_devname : Dict [ str , str ] = {}
171180 for k , v in context .items ():
172181 m = re .match (r"^(.+)_MAC$" , k )
173182 if m :
174183 self .context_devname [v .lower ()] = m .group (1 )
175184
176- def mac2ip (self , mac ) :
185+ def mac2ip (self , mac : str ) -> str :
177186 return "." .join ([str (int (c , 16 )) for c in mac .split (":" )[2 :]])
178187
179- def get_nameservers (self , dev ) :
180- nameservers = {}
188+ def get_nameservers (self , dev : str ) -> Dict [ str , List [ str ]] :
189+ nameservers : Dict [ str , List [ str ]] = {}
181190 dns = self .get_field (dev , "dns" , "" ).split ()
182191 dns .extend (self .context .get ("DNS" , "" ).split ())
183192 if dns :
@@ -187,14 +196,14 @@ def get_nameservers(self, dev):
187196 nameservers ["search" ] = search_domain
188197 return nameservers
189198
190- def get_mtu (self , dev ) :
199+ def get_mtu (self , dev : str ) -> Optional [ str ] :
191200 return self .get_field (dev , "mtu" )
192201
193- def get_ip (self , dev , mac ) :
202+ def get_ip (self , dev : str , mac : str ) -> str :
194203 return self .get_field (dev , "ip" , self .mac2ip (mac ))
195204
196- def get_ip6 (self , dev ) :
197- addresses6 = []
205+ def get_ip6 (self , dev : str ) -> List [ str ] :
206+ addresses6 : List [ str ] = []
198207 ip6 = self .get_field (dev , "ip6" )
199208 if ip6 :
200209 addresses6 .append (ip6 )
@@ -203,24 +212,35 @@ def get_ip6(self, dev):
203212 addresses6 .append (ip6_ula )
204213 return addresses6
205214
206- def get_ip6_prefix (self , dev ) :
215+ def get_ip6_prefix (self , dev : str ) -> str :
207216 return self .get_field (dev , "ip6_prefix_length" , "64" )
208217
209- def get_gateway (self , dev ) :
218+ def get_gateway (self , dev : str ) -> Optional [ str ] :
210219 return self .get_field (dev , "gateway" )
211220
212- def get_gateway6 (self , dev ) :
221+ def get_gateway6 (self , dev : str ) -> Optional [ str ] :
213222 # OpenNebula 6.1.80 introduced new context parameter ETHx_IP6_GATEWAY
214223 # to replace old ETHx_GATEWAY6. Old ETHx_GATEWAY6 will be removed in
215224 # OpenNebula 6.4.0 (https://github.com/OpenNebula/one/issues/5536).
216- return self .get_field (
217- dev , "ip6_gateway" , self .get_field (dev , "gateway6" )
218- )
225+ ip6_gateway = self .get_field (dev , "ip6_gateway" )
226+ if ip6_gateway is not None :
227+ return ip6_gateway
228+ return self .get_field (dev , "gateway6" )
219229
220- def get_mask (self , dev ) :
230+ def get_mask (self , dev : str ) -> str :
221231 return self .get_field (dev , "mask" , "255.255.255.0" )
222232
223- def get_field (self , dev , name , default = None ):
233+ @overload
234+ def get_field (self , dev : str , name : str ) -> Optional [str ]: ...
235+ @overload
236+ def get_field (
237+ self , dev : str , name : str , default : None
238+ ) -> Optional [str ]: ...
239+ @overload
240+ def get_field (self , dev : str , name : str , default : str ) -> str : ...
241+ def get_field (
242+ self , dev : str , name : str , default : Optional [str ] = None
243+ ) -> Optional [str ]:
224244 """return the field name in context for device dev.
225245
226246 context stores <dev>_<NAME> (example: eth0_DOMAIN).
@@ -324,7 +344,9 @@ def varprinter():
324344 )
325345
326346
327- def parse_shell_config (content , asuser = None ):
347+ def parse_shell_config (
348+ content : str , asuser : Optional [str ] = None
349+ ) -> Dict [str , str ]:
328350 """run content and return environment variables which changed
329351
330352 WARNING: the special variable _start_ is used to delimit content
@@ -398,10 +420,14 @@ def parse_shell_config(content, asuser=None):
398420def read_context_disk_dir (
399421 source_dir : str , distro : Any , asuser : Optional [str ] = None
400422) -> Dict [str , Any ]:
401- """
402- read_context_disk_dir(source_dir):
403- read source_dir and return a tuple with metadata dict and user-data
404- string populated. If not a valid dir, raise a NonContextDiskDir
423+ """Read ``source_dir`` and return a dictionary containing context data.
424+
425+ The returned dictionary always includes ``"metadata"`` and
426+ ``"userdata"`` keys, and may also include ``"network-interfaces"``
427+ when network configuration can be generated from the context.
428+
429+ If ``source_dir`` is not a valid context directory, raise
430+ ``NonContextDiskDir``.
405431 """
406432 found : Dict [str , str ] = {}
407433 for af in CONTEXT_DISK_FILES :
@@ -493,7 +519,7 @@ def read_context_disk_dir(
493519 return results
494520
495521
496- def get_physical_nics_by_mac (distro ) :
522+ def get_physical_nics_by_mac (distro : Any ) -> Dict [ str , str ] :
497523 devs = net .get_interfaces_by_mac ()
498524 return dict (
499525 [(m , n ) for m , n in devs .items () if distro .networking .is_physical (n )]
0 commit comments