Merge ~mpontillo/maas:update-vlans-based-on-discovered-machine-interfaces into maas:master

Proposed by Mike Pontillo
Status: Merged
Approved by: Mike Pontillo
Approved revision: f957d5f40bbd22b1ab13054eb3eb8ecb471508bd
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~mpontillo/maas:update-vlans-based-on-discovered-machine-interfaces
Merge into: maas:master
Diff against target: 136 lines (+86/-2)
3 files modified
src/maasserver/models/bmc.py (+35/-0)
src/maasserver/models/signals/interfaces.py (+7/-2)
src/maasserver/models/tests/test_bmc.py (+44/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Newell Jensen (community) Approve
Review via email: mp+353043@code.launchpad.net

Commit message

Use information from DiscoveredMachineInterface objects to update dynamically composed machine interfaces.

To post a comment you must log in.
Revision history for this message
Newell Jensen (newell-jensen) wrote :

Question inline.

review: Needs Information
Revision history for this message
Mike Pontillo (mpontillo) wrote :

See reply below.

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b update-vlans-based-on-discovered-machine-interfaces lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 25fcb7dc6582d3c42c5ed7683324bc68560c0f4a

review: Approve
Revision history for this message
Newell Jensen (newell-jensen) wrote :

Looks good. Thanks for the update!

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

LANDING
-b update-vlans-based-on-discovered-machine-interfaces lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/3648/consoleText

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b update-vlans-based-on-discovered-machine-interfaces lp:~mpontillo/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: f957d5f40bbd22b1ab13054eb3eb8ecb471508bd

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/models/bmc.py b/src/maasserver/models/bmc.py
2index 13340f1..be93b79 100644
3--- a/src/maasserver/models/bmc.py
4+++ b/src/maasserver/models/bmc.py
5@@ -821,21 +821,56 @@ class Pod(BMC):
6 ]
7 # Create the discovered interface and set the default networking
8 # configuration.
9+ created_interfaces = []
10 for idx, discovered_nic in enumerate(discovered_machine.interfaces):
11 interface = self._create_interface(
12 discovered_nic, machine, name=interface_names[idx])
13+ created_interfaces.append(interface)
14 if discovered_nic.boot:
15 machine.boot_interface = interface
16 machine.save(update_fields=['boot_interface'])
17 if skip_commissioning:
18 machine.set_initial_networking_configuration()
19
20+ # We need a second pass here to configure interfaces that the above
21+ # function call would otherwise change.
22+ if self.host is not None:
23+ self._update_vlans_based_on_pod_host(
24+ created_interfaces, discovered_machine)
25+
26 # New machines get commission started immediately unless skipped.
27 if not skip_commissioning:
28 machine.start_commissioning(commissioning_user)
29
30 return machine
31
32+ def _update_vlans_based_on_pod_host(
33+ self, created_interfaces, discovered_machine):
34+ """Matches up newly-created interfaces with interfaces on the pod.host,
35+ given a list of interfaces that were created for the machine, and
36+ the DiscoveredMachine object.
37+ """
38+ # Circular imports.
39+ from maasserver.models import Interface
40+ interfaces = {
41+ interface.name: interface
42+ for interface in Interface.objects.all_interfaces_parents_first(
43+ self.host)
44+ }
45+ for idx, discovered_nic in enumerate(discovered_machine.interfaces):
46+ if discovered_nic.attach_type in ('bridge', 'macvlan'):
47+ host_attach_interface = interfaces.get(
48+ discovered_nic.attach_name, None)
49+ if host_attach_interface is not None:
50+ # If we get to this point, we found the interface the
51+ # the VM has been attached to. Update the VLAN (but
52+ # only if necessary).
53+ host_vlan = host_attach_interface.vlan
54+ if host_vlan != created_interfaces[idx].vlan:
55+ created_interfaces[idx].vlan = host_vlan
56+ created_interfaces[idx].save()
57+ continue
58+
59 def _sync_machine(self, discovered_machine, existing_machine):
60 """Sync's the information from `discovered_machine` to update
61 `existing_machine`."""
62diff --git a/src/maasserver/models/signals/interfaces.py b/src/maasserver/models/signals/interfaces.py
63index 6e9fb33..fa20c33 100644
64--- a/src/maasserver/models/signals/interfaces.py
65+++ b/src/maasserver/models/signals/interfaces.py
66@@ -264,8 +264,13 @@ def interface_vlan_update(instance, old_values, **kwargs):
67 # links except the DISCOVERED ones.
68 instance.ip_addresses.exclude(
69 alloc_type=IPADDRESS_TYPE.DISCOVERED).delete()
70- log.msg("%s: deleted IP addresses due to VLAN update (%s -> %s)." % (
71- instance.get_log_string(), old_vlan_id, new_vlan_id))
72+ if old_vlan_id is not None:
73+ # Don't bother logging if the VLAN was previously NULL, since there
74+ # shouldn't be any IP addresses on the interface, anyway. (But keep
75+ # the above database cleanup, just in case of the unexpected.)
76+ log.msg(
77+ "%s: deleted IP addresses due to VLAN update (%s -> %s)." % (
78+ instance.get_log_string(), old_vlan_id, new_vlan_id))
79
80
81 for klass in INTERFACE_CLASSES:
82diff --git a/src/maasserver/models/tests/test_bmc.py b/src/maasserver/models/tests/test_bmc.py
83index 9861119..e54a351 100644
84--- a/src/maasserver/models/tests/test_bmc.py
85+++ b/src/maasserver/models/tests/test_bmc.py
86@@ -999,6 +999,50 @@ class TestPod(MAASServerTestCase):
87 list(machine.interface_set.order_by('id').values_list(
88 'name', flat=True)))
89
90+ def test_create_machine_sets_interface_vlans_using_attach_names(self):
91+ discovered_machine = self.make_discovered_machine()
92+ self.patch(Machine, "set_default_storage_layout")
93+ self.patch(Machine, "set_initial_networking_configuration")
94+ self.patch(Machine, "start_commissioning")
95+ fabric = factory.make_Fabric()
96+ controller = factory.make_RackController()
97+ vlan = factory.make_VLAN(
98+ fabric=fabric, dhcp_on=True, primary_rack=controller)
99+ subnet = factory.make_Subnet()
100+ vlan2 = factory.make_VLAN(
101+ fabric=fabric, dhcp_on=False, primary_rack=controller)
102+ vlan3 = factory.make_VLAN(
103+ fabric=fabric, dhcp_on=False, primary_rack=controller)
104+ eth0 = factory.make_Interface(node=controller, vlan=vlan)
105+ eth1 = factory.make_Interface(node=controller, vlan=vlan2)
106+ eth2 = factory.make_Interface(node=controller, vlan=vlan3)
107+ br0 = factory.make_Interface(
108+ iftype=INTERFACE_TYPE.BRIDGE, node=controller, vlan=vlan,
109+ parents=[eth0])
110+ ip = factory.make_StaticIPAddress(subnet=subnet, interface=br0)
111+ discovered_machine.interfaces[0].attach_type = 'bridge'
112+ discovered_machine.interfaces[0].attach_name = br0.name
113+ discovered_machine.interfaces[1].attach_type = 'macvlan'
114+ discovered_machine.interfaces[1].attach_name = eth1.name
115+ discovered_machine.interfaces[2].attach_type = 'macvlan'
116+ discovered_machine.interfaces[2].attach_name = eth2.name
117+ pod = factory.make_Pod(
118+ host=controller, ip_address=ip)
119+ machine = pod.create_machine(
120+ discovered_machine, factory.make_User(),
121+ interfaces=LabeledConstraintMap(
122+ 'eth0:vlan=id:%d;eth1:vlan=id:%d;eth2:vlan=id:%d' % (
123+ vlan.id, vlan2.id, vlan3.id),
124+ )
125+ )
126+ interfaces = {
127+ interface.name: interface
128+ for interface in machine.interface_set.all()
129+ }
130+ self.assertThat(interfaces['eth0'].vlan, Equals(vlan))
131+ self.assertThat(interfaces['eth1'].vlan, Equals(vlan2))
132+ self.assertThat(interfaces['eth2'].vlan, Equals(vlan3))
133+
134 def test_create_machine_uses_default_ifnames_if_discovered_mismatch(self):
135 """This makes sure that if the discovered machine comes back with
136 a different number of interfaces than the constraint string, the

Subscribers

People subscribed via source and target branches