Merge ~bjornt/maas:move-fake-commissioning-data into maas:master

Proposed by Björn Tillenius
Status: Merged
Approved by: Björn Tillenius
Approved revision: d1c0008c387b7fdef9e541a6797f17e31124b620
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~bjornt/maas:move-fake-commissioning-data
Merge into: maas:master
Diff against target: 880 lines (+419/-414)
3 files modified
src/maasserver/rpc/tests/test_rackcontrollers.py (+1/-4)
src/maasserver/testing/commissioning.py (+413/-0)
src/metadataserver/builtin_scripts/tests/test_network.py (+5/-410)
Reviewer Review Type Date Requested Status
Alberto Donato (community) Approve
Review via email: mp+416011@code.launchpad.net

Commit message

Move FakeCommissioningData to maasserver.testing.

This makes it easier to reuse it for other tests and for sampledata.

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/rpc/tests/test_rackcontrollers.py b/src/maasserver/rpc/tests/test_rackcontrollers.py
2index 141135d..8e9c1a7 100644
3--- a/src/maasserver/rpc/tests/test_rackcontrollers.py
4+++ b/src/maasserver/rpc/tests/test_rackcontrollers.py
5@@ -25,16 +25,13 @@ from maasserver.rpc.rackcontrollers import (
6 update_last_image_sync,
7 update_state,
8 )
9+from maasserver.testing.commissioning import FakeCommissioningData, LXDAddress
10 from maasserver.testing.factory import factory
11 from maasserver.testing.testcase import MAASServerTestCase
12 from maasserver.utils.orm import reload_object
13 from maastesting.matchers import DocTestMatches, MockCalledOnceWith
14 from metadataserver.builtin_scripts import load_builtin_scripts
15 from metadataserver.builtin_scripts.network import update_node_interfaces
16-from metadataserver.builtin_scripts.tests.test_network import (
17- FakeCommissioningData,
18- LXDAddress,
19-)
20 from provisioningserver.enum import CONTROLLER_INSTALL_TYPE
21 from provisioningserver.rpc.exceptions import NoSuchScope
22
23diff --git a/src/maasserver/testing/commissioning.py b/src/maasserver/testing/commissioning.py
24new file mode 100644
25index 0000000..5969219
26--- /dev/null
27+++ b/src/maasserver/testing/commissioning.py
28@@ -0,0 +1,413 @@
29+import dataclasses
30+import random
31+from typing import List, Optional
32+
33+from maasserver.testing.factory import factory
34+from provisioningserver.utils.network import (
35+ annotate_with_default_monitored_interfaces,
36+ get_default_monitored_interfaces,
37+)
38+
39+GB = 1000 * 1000 * 1000
40+
41+
42+@dataclasses.dataclass
43+class LXDPartition:
44+ id: str
45+ read_only: bool = False
46+
47+
48+@dataclasses.dataclass
49+class LXDDisk:
50+ id: str
51+ size: int = 250 * GB
52+ partitions: List[LXDPartition] = dataclasses.field(default_factory=list)
53+ type: str = "sata"
54+ read_only: bool = False
55+ removable: bool = False
56+ rpm: int = 0
57+ numa_node: int = 0
58+
59+
60+@dataclasses.dataclass
61+class LXDVlan:
62+ lower_device: str
63+ vid: int
64+
65+
66+@dataclasses.dataclass
67+class LXDBridge:
68+ upper_devices: List[str] = dataclasses.field(default_factory=list)
69+
70+
71+@dataclasses.dataclass
72+class LXDBond:
73+ lower_devices: List[str] = dataclasses.field(default_factory=list)
74+
75+
76+@dataclasses.dataclass
77+class LXDAddress:
78+
79+ address: str
80+ netmask: str
81+ family: str = "inet"
82+ scope: str = "global"
83+
84+
85+@dataclasses.dataclass
86+class LXDNetwork:
87+ name: str
88+ hwaddr: str
89+ type: str = "broadcast"
90+ state: str = "up"
91+ addresses: List[LXDAddress] = dataclasses.field(default_factory=list)
92+ vlan: Optional[LXDVlan] = None
93+ bridge: Optional[LXDBridge] = None
94+ bond: Optional[LXDBond] = None
95+
96+
97+@dataclasses.dataclass
98+class LXDNetworkPort:
99+
100+ id: str
101+ port: int
102+ address: str = dataclasses.field(default_factory=factory.make_mac_address)
103+ protocol: str = "ethernet"
104+ supported_modes: List[str] = dataclasses.field(
105+ default_factory=lambda: ["10000baseT/Full"]
106+ )
107+ supported_ports: List[str] = dataclasses.field(
108+ default_factory=lambda: ["fiber"]
109+ )
110+ port_type: str = "fiber"
111+ transceiver_type: str = "internal"
112+ auto_negotiation: bool = True
113+ link_detected: bool = True
114+ link_speed: int = 10000
115+ link_duplex: str = "full"
116+
117+
118+@dataclasses.dataclass
119+class LXDNetworkCard:
120+
121+ pci_address: str
122+ vendor: str = "My Corporation"
123+ vendor_id: str = "1234"
124+ product: str = "My Gigabit Network Connection"
125+ product_id: str = "5678"
126+ firmware_version: str = "1.63, 0x800009fa"
127+ numa_node: int = 0
128+ driver: str = "mydriver"
129+ driver_version: str = "1.2.3"
130+ ports: Optional[List[LXDNetworkPort]] = None
131+
132+
133+class FakeCommissioningData:
134+ """Helper to generate commissioning output programtically.
135+
136+ Instead of hardcoding the commissioning data, taking care of
137+ including all the possible keys and values, this class allows you to
138+ tell which interface you want the machine to have, and you only have
139+ to specify what's important for the tests. The helper will ensure
140+ that all the other keys are there with a sane value and in the right
141+ format.
142+ """
143+
144+ def __init__(
145+ self,
146+ cores=1,
147+ memory=2048,
148+ disks=None,
149+ api_extensions=None,
150+ api_version="1.0",
151+ ):
152+ self.cores = cores
153+ self.memory = memory
154+ if api_extensions is None:
155+ api_extensions = [
156+ "resources",
157+ "resources_v2",
158+ "api_os",
159+ "resources_system",
160+ "resources_usb_pci",
161+ ]
162+ self.api_extensions = api_extensions
163+ self.api_version = api_version
164+ self.environment = {
165+ "kernel": "Linux",
166+ "kernel_architecture": "x86_64",
167+ "kernel_version": "5.4.0-67-generic",
168+ "os_name": "ubuntu",
169+ "os_version": "20.04",
170+ "server": "maas-machine-resources",
171+ "server_name": factory.make_name("host"),
172+ "server_version": "4.11",
173+ }
174+ self.address_annotations = {}
175+ self._allocated_pci_addresses = []
176+ self.networks = {}
177+ self._network_cards = []
178+ if disks is None:
179+ disks = [LXDDisk("sda")]
180+ self._disks = list(disks)
181+ self.hints = None
182+
183+ def allocate_pci_address(self):
184+ prev_address = (
185+ self._allocated_pci_addresses[-1]
186+ if self._allocated_pci_addresses
187+ else "0000:00:00.0"
188+ )
189+ bus, device, func = prev_address.split(":")
190+ next_device = int(device, 16) + 1
191+ self._allocated_pci_addresses.append(
192+ f"{bus}:{next_device:0>4x}:{func}"
193+ )
194+ return self._allocated_pci_addresses[-1]
195+
196+ def get_available_vid(self):
197+ available_vids = set(range(2, 4095))
198+ used_vids = {
199+ network.vlan.vid
200+ for network in self.networks.values()
201+ if network.vlan is not None
202+ }
203+ available_vids = list(available_vids.difference(used_vids))
204+ return random.choice(available_vids)
205+
206+ def create_network_card(self):
207+ card = LXDNetworkCard(self.allocate_pci_address())
208+ self._network_cards.append(card)
209+ return card
210+
211+ def create_physical_network(
212+ self,
213+ name=None,
214+ mac_address=None,
215+ card=None,
216+ port=None,
217+ ):
218+ if card is None:
219+ card = self.create_network_card()
220+ if card.ports is None:
221+ card.ports = []
222+ network = self.create_physical_network_without_nic(name, mac_address)
223+ if port is None:
224+ port = LXDNetworkPort(
225+ network.name, len(card.ports), address=network.hwaddr
226+ )
227+ card.ports.append(port)
228+ return network
229+
230+ def create_physical_network_without_nic(
231+ self,
232+ name=None,
233+ mac_address=None,
234+ ):
235+ if name is None:
236+ name = factory.make_string("eth")
237+ if mac_address is None:
238+ mac_address = factory.make_mac_address()
239+ network = LXDNetwork(name, mac_address)
240+ self.networks[name] = network
241+ return network
242+
243+ def create_vlan_network(
244+ self,
245+ name=None,
246+ vid=None,
247+ mac_address=None,
248+ parent=None,
249+ ):
250+ if name is None:
251+ name = factory.make_string("vlan")
252+ if parent is None:
253+ parent = self.create_physical_network()
254+ if mac_address is None:
255+ mac_address = factory.make_mac_address()
256+ if vid is None:
257+ vid = self.get_available_vid()
258+ network = LXDNetwork(
259+ name, mac_address, vlan=LXDVlan(lower_device=parent.name, vid=vid)
260+ )
261+ self.networks[name] = network
262+ return network
263+
264+ def create_bridge_network(
265+ self,
266+ name=None,
267+ mac_address=None,
268+ parents=None,
269+ ):
270+ if name is None:
271+ name = factory.make_string("bridge")
272+ if parents is None:
273+ parents = [self.create_physical_network()]
274+ if mac_address is None:
275+ mac_address = factory.make_mac_address()
276+ network = LXDNetwork(
277+ name,
278+ mac_address,
279+ bridge=LXDBridge(
280+ upper_devices=[parent.name for parent in parents]
281+ ),
282+ )
283+ self.networks[name] = network
284+ return network
285+
286+ def create_bond_network(
287+ self,
288+ name=None,
289+ mac_address=None,
290+ parents=None,
291+ ):
292+ if name is None:
293+ name = factory.make_string("bond")
294+ if parents is None:
295+ parents = [self.create_physical_network()]
296+ if mac_address is None:
297+ mac_address = factory.make_mac_address()
298+ network = LXDNetwork(
299+ name,
300+ mac_address,
301+ bond=LXDBond(lower_devices=[parent.name for parent in parents]),
302+ )
303+ self.networks[name] = network
304+ return network
305+
306+ def render(self, include_extra=False):
307+ storage_resources = {
308+ "disks": [dataclasses.asdict(disk) for disk in self._disks],
309+ "total": len(self._disks),
310+ }
311+ network_resources = {
312+ "cards": [
313+ dataclasses.asdict(card) for card in self._network_cards
314+ ],
315+ "total": len(self._network_cards),
316+ }
317+ for card in network_resources["cards"]:
318+ if card["ports"] is None:
319+ del card["ports"]
320+ networks = {
321+ name: dataclasses.asdict(network)
322+ for name, network in self.networks.items()
323+ }
324+ old_interfaces_data = self._generate_interfaces()
325+ data = {
326+ "api_extensions": self.api_extensions,
327+ "api_version": self.api_version,
328+ "environment": self.environment,
329+ "resources": {
330+ "cpu": {
331+ "architecture": self.environment["kernel_architecture"],
332+ "sockets": [
333+ {
334+ "socket": 0,
335+ "cores": [],
336+ }
337+ ],
338+ },
339+ "memory": {
340+ "hugepages_total": 0,
341+ "hugepages_used": 0,
342+ "hugepages_size": 0,
343+ "used": int(0.3 * self.memory * 1024 * 1024),
344+ "total": int(self.memory * 1024 * 1024),
345+ },
346+ "gpu": {"cards": [], "total": 0},
347+ "network": network_resources,
348+ "storage": storage_resources,
349+ },
350+ "networks": networks,
351+ }
352+ for core_index in range(self.cores):
353+ data["resources"]["cpu"]["sockets"][0]["cores"].append(
354+ {
355+ "core": core_index,
356+ "threads": [
357+ {
358+ "id": core_index,
359+ "thread": 0,
360+ "online": True,
361+ "numa_node": 0,
362+ },
363+ ],
364+ "frequency": 1500,
365+ }
366+ )
367+ if include_extra:
368+ data["network-extra"] = {
369+ "interfaces": old_interfaces_data,
370+ "monitored-interfaces": get_default_monitored_interfaces(
371+ old_interfaces_data
372+ ),
373+ "hints": self.hints,
374+ }
375+ return data
376+
377+ def _generate_interfaces(self):
378+ # XXX: It would be good if this method could basically call
379+ # get_all_interfaces_definition(), passing in information it
380+ # needs. But considering the goal is to minimize information and
381+ # instead make use of the LXD data directly, it's probably worth
382+ # holding off until there's less information to render.
383+ interfaces = {}
384+ for name, network in self.networks.items():
385+ if network.type != "broadcast":
386+ continue
387+ interface = {
388+ "mac_address": self._get_network_port_mac(
389+ name, network.hwaddr
390+ ),
391+ "links": [],
392+ "enabled": network.state == "up",
393+ "source": "machine-resources",
394+ }
395+ if network.vlan is not None:
396+ interface.update(
397+ {
398+ "type": "vlan",
399+ "parents": [network.vlan.lower_device],
400+ "vid": network.vlan.vid,
401+ }
402+ )
403+ elif network.bridge is not None:
404+ interface.update(
405+ {
406+ "type": "bridge",
407+ "parents": list(network.bridge.upper_devices),
408+ }
409+ )
410+ elif network.bond is not None:
411+ interface.update(
412+ {
413+ "type": "bond",
414+ "parents": list(network.bond.lower_devices),
415+ }
416+ )
417+ else:
418+ interface.update({"type": "physical", "parents": []})
419+ for address in network.addresses:
420+ link = {
421+ "address": f"{address.address}/{address.netmask}",
422+ "mode": "static",
423+ }
424+ address_annotation = self.address_annotations.get(
425+ address.address, {}
426+ )
427+ link.update(address_annotation)
428+ interface["links"].append(link)
429+ interfaces[name] = interface
430+ annotate_with_default_monitored_interfaces(interfaces)
431+ return interfaces
432+
433+ def _get_network_port_mac(self, port_name, default):
434+ for card in self._network_cards:
435+ if not card.ports:
436+ continue
437+ for port in card.ports:
438+ if port.id == port_name:
439+ return port.address
440+
441+ return default
442diff --git a/src/metadataserver/builtin_scripts/tests/test_network.py b/src/metadataserver/builtin_scripts/tests/test_network.py
443index a2f1a6d..5e06062 100644
444--- a/src/metadataserver/builtin_scripts/tests/test_network.py
445+++ b/src/metadataserver/builtin_scripts/tests/test_network.py
446@@ -1,7 +1,5 @@
447-import dataclasses
448 import json
449 import random
450-from typing import List, Optional
451 from unittest.mock import call
452
453 from maasserver.enum import (
454@@ -22,6 +20,11 @@ from maasserver.models.interface import (
455 from maasserver.models.staticipaddress import StaticIPAddress
456 from maasserver.models.subnet import Subnet
457 from maasserver.models.vlan import VLAN
458+from maasserver.testing.commissioning import (
459+ FakeCommissioningData,
460+ LXDAddress,
461+ LXDNetworkCard,
462+)
463 from maasserver.testing.factory import factory
464 from maasserver.testing.testcase import (
465 MAASServerTestCase,
466@@ -37,414 +40,6 @@ from metadataserver.builtin_scripts.network import (
467 from provisioningserver.refresh.node_info_scripts import (
468 COMMISSIONING_OUTPUT_NAME,
469 )
470-from provisioningserver.utils.network import (
471- annotate_with_default_monitored_interfaces,
472- get_default_monitored_interfaces,
473-)
474-
475-GB = 1000 * 1000 * 1000
476-
477-
478-@dataclasses.dataclass
479-class LXDPartition:
480- id: str
481- read_only: bool = False
482-
483-
484-@dataclasses.dataclass
485-class LXDDisk:
486- id: str
487- size: int = 250 * GB
488- partitions: List[LXDPartition] = dataclasses.field(default_factory=list)
489- type: str = "sata"
490- read_only: bool = False
491- removable: bool = False
492- rpm: int = 0
493- numa_node: int = 0
494-
495-
496-@dataclasses.dataclass
497-class LXDVlan:
498- lower_device: str
499- vid: int
500-
501-
502-@dataclasses.dataclass
503-class LXDBridge:
504- upper_devices: List[str] = dataclasses.field(default_factory=list)
505-
506-
507-@dataclasses.dataclass
508-class LXDBond:
509- lower_devices: List[str] = dataclasses.field(default_factory=list)
510-
511-
512-@dataclasses.dataclass
513-class LXDAddress:
514-
515- address: str
516- netmask: str
517- family: str = "inet"
518- scope: str = "global"
519-
520-
521-@dataclasses.dataclass
522-class LXDNetwork:
523- name: str
524- hwaddr: str
525- type: str = "broadcast"
526- state: str = "up"
527- addresses: List[LXDAddress] = dataclasses.field(default_factory=list)
528- vlan: Optional[LXDVlan] = None
529- bridge: Optional[LXDBridge] = None
530- bond: Optional[LXDBond] = None
531-
532-
533-@dataclasses.dataclass
534-class LXDNetworkPort:
535-
536- id: str
537- port: int
538- address: str = dataclasses.field(default_factory=factory.make_mac_address)
539- protocol: str = "ethernet"
540- supported_modes: List[str] = dataclasses.field(
541- default_factory=lambda: ["10000baseT/Full"]
542- )
543- supported_ports: List[str] = dataclasses.field(
544- default_factory=lambda: ["fiber"]
545- )
546- port_type: str = "fiber"
547- transceiver_type: str = "internal"
548- auto_negotiation: bool = True
549- link_detected: bool = True
550- link_speed: int = 10000
551- link_duplex: str = "full"
552-
553-
554-@dataclasses.dataclass
555-class LXDNetworkCard:
556-
557- pci_address: str
558- vendor: str = "My Corporation"
559- vendor_id: str = "1234"
560- product: str = "My Gigabit Network Connection"
561- product_id: str = "5678"
562- firmware_version: str = "1.63, 0x800009fa"
563- numa_node: int = 0
564- driver: str = "mydriver"
565- driver_version: str = "1.2.3"
566- ports: Optional[List[LXDNetworkPort]] = None
567-
568-
569-class FakeCommissioningData:
570- """Helper to generate commissioning output programtically.
571-
572- Instead of hardcoding the commissioning data, taking care of
573- including all the possible keys and values, this class allows you to
574- tell which interface you want the machine to have, and you only have
575- to specify what's important for the tests. The helper will ensure
576- that all the other keys are there with a sane value and in the right
577- format.
578- """
579-
580- def __init__(
581- self,
582- cores=1,
583- memory=2048,
584- disks=None,
585- api_extensions=None,
586- api_version="1.0",
587- ):
588- self.cores = cores
589- self.memory = memory
590- if api_extensions is None:
591- api_extensions = [
592- "resources",
593- "resources_v2",
594- "api_os",
595- "resources_system",
596- "resources_usb_pci",
597- ]
598- self.api_extensions = api_extensions
599- self.api_version = api_version
600- self.environment = {
601- "kernel": "Linux",
602- "kernel_architecture": "x86_64",
603- "kernel_version": "5.4.0-67-generic",
604- "os_name": "ubuntu",
605- "os_version": "20.04",
606- "server": "maas-machine-resources",
607- "server_name": factory.make_name("host"),
608- "server_version": "4.11",
609- }
610- self.address_annotations = {}
611- self._allocated_pci_addresses = []
612- self.networks = {}
613- self._network_cards = []
614- if disks is None:
615- disks = [LXDDisk("sda")]
616- self._disks = list(disks)
617- self.hints = None
618-
619- def allocate_pci_address(self):
620- prev_address = (
621- self._allocated_pci_addresses[-1]
622- if self._allocated_pci_addresses
623- else "0000:00:00.0"
624- )
625- bus, device, func = prev_address.split(":")
626- next_device = int(device, 16) + 1
627- self._allocated_pci_addresses.append(
628- f"{bus}:{next_device:0>4x}:{func}"
629- )
630- return self._allocated_pci_addresses[-1]
631-
632- def get_available_vid(self):
633- available_vids = set(range(2, 4095))
634- used_vids = {
635- network.vlan.vid
636- for network in self.networks.values()
637- if network.vlan is not None
638- }
639- available_vids = list(available_vids.difference(used_vids))
640- return random.choice(available_vids)
641-
642- def create_network_card(self):
643- card = LXDNetworkCard(self.allocate_pci_address())
644- self._network_cards.append(card)
645- return card
646-
647- def create_physical_network(
648- self,
649- name=None,
650- mac_address=None,
651- card=None,
652- port=None,
653- ):
654- if card is None:
655- card = self.create_network_card()
656- if card.ports is None:
657- card.ports = []
658- network = self.create_physical_network_without_nic(name, mac_address)
659- if port is None:
660- port = LXDNetworkPort(
661- network.name, len(card.ports), address=network.hwaddr
662- )
663- card.ports.append(port)
664- return network
665-
666- def create_physical_network_without_nic(
667- self,
668- name=None,
669- mac_address=None,
670- ):
671- if name is None:
672- name = factory.make_string("eth")
673- if mac_address is None:
674- mac_address = factory.make_mac_address()
675- network = LXDNetwork(name, mac_address)
676- self.networks[name] = network
677- return network
678-
679- def create_vlan_network(
680- self,
681- name=None,
682- vid=None,
683- mac_address=None,
684- parent=None,
685- ):
686- if name is None:
687- name = factory.make_string("vlan")
688- if parent is None:
689- parent = self.create_physical_network()
690- if mac_address is None:
691- mac_address = factory.make_mac_address()
692- if vid is None:
693- vid = self.get_available_vid()
694- network = LXDNetwork(
695- name, mac_address, vlan=LXDVlan(lower_device=parent.name, vid=vid)
696- )
697- self.networks[name] = network
698- return network
699-
700- def create_bridge_network(
701- self,
702- name=None,
703- mac_address=None,
704- parents=None,
705- ):
706- if name is None:
707- name = factory.make_string("bridge")
708- if parents is None:
709- parents = [self.create_physical_network()]
710- if mac_address is None:
711- mac_address = factory.make_mac_address()
712- network = LXDNetwork(
713- name,
714- mac_address,
715- bridge=LXDBridge(
716- upper_devices=[parent.name for parent in parents]
717- ),
718- )
719- self.networks[name] = network
720- return network
721-
722- def create_bond_network(
723- self,
724- name=None,
725- mac_address=None,
726- parents=None,
727- ):
728- if name is None:
729- name = factory.make_string("bond")
730- if parents is None:
731- parents = [self.create_physical_network()]
732- if mac_address is None:
733- mac_address = factory.make_mac_address()
734- network = LXDNetwork(
735- name,
736- mac_address,
737- bond=LXDBond(lower_devices=[parent.name for parent in parents]),
738- )
739- self.networks[name] = network
740- return network
741-
742- def render(self, include_extra=False):
743- storage_resources = {
744- "disks": [dataclasses.asdict(disk) for disk in self._disks],
745- "total": len(self._disks),
746- }
747- network_resources = {
748- "cards": [
749- dataclasses.asdict(card) for card in self._network_cards
750- ],
751- "total": len(self._network_cards),
752- }
753- for card in network_resources["cards"]:
754- if card["ports"] is None:
755- del card["ports"]
756- networks = {
757- name: dataclasses.asdict(network)
758- for name, network in self.networks.items()
759- }
760- old_interfaces_data = self._generate_interfaces()
761- data = {
762- "api_extensions": self.api_extensions,
763- "api_version": self.api_version,
764- "environment": self.environment,
765- "resources": {
766- "cpu": {
767- "architecture": self.environment["kernel_architecture"],
768- "sockets": [
769- {
770- "socket": 0,
771- "cores": [],
772- }
773- ],
774- },
775- "memory": {
776- "hugepages_total": 0,
777- "hugepages_used": 0,
778- "hugepages_size": 0,
779- "used": int(0.3 * self.memory * 1024 * 1024),
780- "total": int(self.memory * 1024 * 1024),
781- },
782- "gpu": {"cards": [], "total": 0},
783- "network": network_resources,
784- "storage": storage_resources,
785- },
786- "networks": networks,
787- }
788- for core_index in range(self.cores):
789- data["resources"]["cpu"]["sockets"][0]["cores"].append(
790- {
791- "core": core_index,
792- "threads": [
793- {
794- "id": core_index,
795- "thread": 0,
796- "online": True,
797- "numa_node": 0,
798- },
799- ],
800- "frequency": 1500,
801- }
802- )
803- if include_extra:
804- data["network-extra"] = {
805- "interfaces": old_interfaces_data,
806- "monitored-interfaces": get_default_monitored_interfaces(
807- old_interfaces_data
808- ),
809- "hints": self.hints,
810- }
811- return data
812-
813- def _generate_interfaces(self):
814- # XXX: It would be good if this method could basically call
815- # get_all_interfaces_definition(), passing in information it
816- # needs. But considering the goal is to minimize information and
817- # instead make use of the LXD data directly, it's probably worth
818- # holding off until there's less information to render.
819- interfaces = {}
820- for name, network in self.networks.items():
821- if network.type != "broadcast":
822- continue
823- interface = {
824- "mac_address": self._get_network_port_mac(
825- name, network.hwaddr
826- ),
827- "links": [],
828- "enabled": network.state == "up",
829- "source": "machine-resources",
830- }
831- if network.vlan is not None:
832- interface.update(
833- {
834- "type": "vlan",
835- "parents": [network.vlan.lower_device],
836- "vid": network.vlan.vid,
837- }
838- )
839- elif network.bridge is not None:
840- interface.update(
841- {
842- "type": "bridge",
843- "parents": list(network.bridge.upper_devices),
844- }
845- )
846- elif network.bond is not None:
847- interface.update(
848- {
849- "type": "bond",
850- "parents": list(network.bond.lower_devices),
851- }
852- )
853- else:
854- interface.update({"type": "physical", "parents": []})
855- for address in network.addresses:
856- link = {
857- "address": f"{address.address}/{address.netmask}",
858- "mode": "static",
859- }
860- address_annotation = self.address_annotations.get(
861- address.address, {}
862- )
863- link.update(address_annotation)
864- interface["links"].append(link)
865- interfaces[name] = interface
866- annotate_with_default_monitored_interfaces(interfaces)
867- return interfaces
868-
869- def _get_network_port_mac(self, port_name, default):
870- for card in self._network_cards:
871- if not card.ports:
872- continue
873- for port in card.ports:
874- if port.id == port_name:
875- return port.address
876-
877- return default
878
879
880 class UpdateInterfacesMixin:

Subscribers

People subscribed via source and target branches