Merge ~cgrabowski/maas:fix_wrong_rack_controller_selection_for_bmc into maas:master

Proposed by Christian Grabowski
Status: Merged
Approved by: Christian Grabowski
Approved revision: 2315c4ca66d8307efd38b4a3da32686ee7373346
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:fix_wrong_rack_controller_selection_for_bmc
Merge into: maas:master
Diff against target: 242 lines (+188/-3)
3 files modified
src/maasserver/models/bmc.py (+3/-2)
src/maasserver/models/tests/test_bmc.py (+1/-1)
src/maasserver/models/tests/test_node.py (+184/-0)
Reviewer Review Type Date Requested Status
Alexsander de Souza Approve
MAAS Lander Approve
Review via email: mp+422693@code.launchpad.net

Commit message

check to see the rack controller is connected via rpc to consider it accessible to a bmc
fix test

add test asserting routable rack controllers are updated

only consider a BMC accessible if a rack controller is usable AND has a connection

test get_bmc_client_connection_info
add tests for _get_bmc_client_connection_info

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b fix_wrong_rack_controller_selection_for_bmc lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/12590/console
COMMIT: f080a982b64c9ffd4b3d2c9a357898c88e090ad5

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

UNIT TESTS
-b fix_wrong_rack_controller_selection_for_bmc lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/12591/console
COMMIT: 8f15383ae1646688a1fec3257b3f9ad8df166f8b

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

UNIT TESTS
-b fix_wrong_rack_controller_selection_for_bmc lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 2315c4ca66d8307efd38b4a3da32686ee7373346

review: Approve
Revision history for this message
Alexsander de Souza (alexsander-souza) 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/models/bmc.py b/src/maasserver/models/bmc.py
2index c697c49..5fda784 100644
3--- a/src/maasserver/models/bmc.py
4+++ b/src/maasserver/models/bmc.py
5@@ -543,7 +543,7 @@ class BMC(CleanSave, TimestampedModel):
6
7 def is_accessible(self):
8 """If the BMC is accessible by at least one rack controller."""
9- racks = self.get_usable_rack_controllers(with_connection=False)
10+ racks = self.get_usable_rack_controllers(with_connection=True)
11 return len(racks) > 0
12
13 def update_routable_racks(
14@@ -564,11 +564,12 @@ class BMC(CleanSave, TimestampedModel):
15 from maasserver.models.node import RackController
16
17 for rack_id in rack_ids:
18+ rack = None
19 try:
20 rack = RackController.objects.get(system_id=rack_id)
21 except RackController.DoesNotExist:
22 # Possible it was delete before this call, but very very rare.
23- pass
24+ continue
25 BMCRoutableRackControllerRelationship(
26 bmc=self, rack_controller=rack, routable=routable
27 ).save()
28diff --git a/src/maasserver/models/tests/test_bmc.py b/src/maasserver/models/tests/test_bmc.py
29index 5d46f76..7af9b8c 100644
30--- a/src/maasserver/models/tests/test_bmc.py
31+++ b/src/maasserver/models/tests/test_bmc.py
32@@ -559,7 +559,7 @@ class TestBMC(MAASServerTestCase):
33 bmc.is_accessible()
34 self.assertThat(
35 mock_get_usable_rack_controllers,
36- MockCalledOnceWith(with_connection=False),
37+ MockCalledOnceWith(with_connection=True),
38 )
39
40 def test_is_accessible_returns_true(self):
41diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py
42index aa968c8..33752b8 100644
43--- a/src/maasserver/models/tests/test_node.py
44+++ b/src/maasserver/models/tests/test_node.py
45@@ -6099,6 +6099,77 @@ class TestNode(MAASServerTestCase):
46 interface, list(node.current_config.interface_set.all())
47 )
48
49+ def test_get_bmc_client_connection_info_layer2(self):
50+ admin = factory.make_admin()
51+ subnet = factory.make_Subnet()
52+
53+ rack_controllers = [
54+ factory.make_RackController(owner=admin) for _ in range(2)
55+ ]
56+ for rack_controller in rack_controllers:
57+ ip = subnet.get_next_ip_for_allocation()
58+ factory.make_Interface(node=rack_controller, ip=ip)
59+
60+ clients = [Mock() for _ in rack_controllers]
61+ for i, rack_controller in enumerate(rack_controllers):
62+ clients[i].ident = rack_controller.system_id
63+
64+ mock_getAllClients = self.patch(node_module, "getAllClients")
65+ mock_getAllClients.return_value = clients
66+
67+ ip = subnet.get_next_ip_for_allocation()
68+ ip_address = factory.make_StaticIPAddress(ip=ip)
69+ bmc = factory.make_BMC(ip_address=ip_address)
70+ node = factory.make_Node(bmc=bmc)
71+ clients, _ = node._get_bmc_client_connection_info()
72+ self.assertCountEqual(
73+ [
74+ rack_controller.system_id
75+ for rack_controller in rack_controllers
76+ ],
77+ clients,
78+ )
79+
80+ def test_get_bmc_client_connection_info_routable(self):
81+ admin = factory.make_admin()
82+ subnet1 = factory.make_Subnet()
83+ subnet2 = factory.make_Subnet()
84+
85+ rack_controllers = [
86+ factory.make_RackController(owner=admin) for _ in range(2)
87+ ]
88+ for rack_controller in rack_controllers:
89+ ip = subnet1.get_next_ip_for_allocation()
90+ factory.make_Interface(node=rack_controller, ip=ip)
91+
92+ clients = [Mock() for _ in rack_controllers]
93+ for i, rack_controller in enumerate(rack_controllers):
94+ clients[i].ident = rack_controller.system_id
95+
96+ mock_getAllClients_node = self.patch(node_module, "getAllClients")
97+ mock_getAllClients_node.return_value = clients
98+ mock_getAllClients_bmc = self.patch(bmc_module, "getAllClients")
99+ mock_getAllClients_bmc.return_value = clients
100+
101+ ip = subnet2.get_next_ip_for_allocation()
102+ ip_address = factory.make_StaticIPAddress(ip=ip, subnet=subnet2)
103+ bmc = factory.make_BMC(ip_address=ip_address)
104+ node = factory.make_Node(bmc=bmc)
105+ [
106+ BMCRoutableRackControllerRelationship(
107+ bmc=bmc, rack_controller=rack_controller, routable=True
108+ ).save()
109+ for rack_controller in rack_controllers
110+ ]
111+ clients, _ = node._get_bmc_client_connection_info()
112+ self.assertCountEqual(
113+ [
114+ rack_controller.system_id
115+ for rack_controller in rack_controllers
116+ ],
117+ clients,
118+ )
119+
120
121 class TestNodePowerParameters(MAASServerTestCase):
122 def setUp(self):
123@@ -6374,6 +6445,119 @@ class TestNodePowerParameters(MAASServerTestCase):
124 self.assertFalse(node.is_sync_healthy)
125
126
127+class TestPowerControlNode(MAASTransactionServerTestCase):
128+ @wait_for_reactor
129+ @defer.inlineCallbacks
130+ def test_power_control_node_updates_routable_rack_controllers(self):
131+ bmc = yield deferToDatabase(factory.make_BMC)
132+ node = yield deferToDatabase(
133+ factory.make_Node_with_Interface_on_Subnet, bmc=bmc
134+ )
135+ rack_ip = yield deferToDatabase(factory.make_ip_address)
136+ rack_controller = yield deferToDatabase(node.get_boot_rack_controller)
137+ yield deferToDatabase(
138+ factory.make_Interface, node=rack_controller, ip=rack_ip
139+ )
140+
141+ def _create_initial_relationship():
142+ b = BMCRoutableRackControllerRelationship(
143+ bmc=bmc, rack_controller=rack_controller, routable=True
144+ )
145+ b.save()
146+
147+ yield deferToDatabase(_create_initial_relationship)
148+
149+ other_rack_controller = yield deferToDatabase(
150+ factory.make_RackController
151+ )
152+
153+ def _assert_no_routable():
154+ self.assertRaises(
155+ BMCRoutableRackControllerRelationship.DoesNotExist,
156+ BMCRoutableRackControllerRelationship.objects.get,
157+ bmc=node.bmc,
158+ rack_controller=other_rack_controller,
159+ )
160+
161+ yield deferToDatabase(_assert_no_routable)
162+
163+ client = Mock()
164+ client.ident = other_rack_controller.system_id
165+ self.patch(bmc_module, "getAllClients").return_value = [client]
166+ self.patch(node_module, "getAllClients").return_value = [client]
167+ client2 = Mock()
168+ client2.return_value = defer.succeed({"missing_packages": []})
169+ d1 = defer.succeed(client2)
170+ self.patch(bmc_module, "getClientFromIdentifiers").return_value = d1
171+ self.patch(node_module, "getClientFromIdentifiers").return_value = d1
172+ self.patch(
173+ node_module, "power_query_all"
174+ ).return_value = defer.succeed(
175+ (POWER_STATE.ON, set([other_rack_controller.system_id]), set())
176+ )
177+
178+ power_info = yield deferToDatabase(node.get_effective_power_info)
179+ yield node._power_control_node(
180+ defer.succeed(None), power_query, power_info
181+ )
182+
183+ def _assert_routable():
184+ self.assertTrue(
185+ BMCRoutableRackControllerRelationship.objects.get(
186+ bmc=node.bmc, rack_controller=other_rack_controller
187+ )
188+ )
189+
190+ yield deferToDatabase(_assert_routable)
191+
192+ @wait_for_reactor
193+ @defer.inlineCallbacks
194+ def test_power_control_node_removes_non_routable_rack_controllers(self):
195+ bmc = yield deferToDatabase(factory.make_BMC)
196+ node = yield deferToDatabase(
197+ factory.make_Node_with_Interface_on_Subnet, bmc=bmc
198+ )
199+ rack_ip = yield deferToDatabase(factory.make_ip_address)
200+ rack_controller = yield deferToDatabase(node.get_boot_rack_controller)
201+ yield deferToDatabase(
202+ factory.make_Interface, node=rack_controller, ip=rack_ip
203+ )
204+
205+ def _create_initial_relationship():
206+ b = BMCRoutableRackControllerRelationship(
207+ bmc=bmc, rack_controller=rack_controller, routable=True
208+ )
209+ b.save()
210+
211+ yield deferToDatabase(_create_initial_relationship)
212+
213+ self.patch(bmc_module, "getAllClients").return_value = []
214+ self.patch(node_module, "getAllClients").return_value = []
215+ client2 = Mock()
216+ client2.return_value = defer.succeed({"missing_packages": []})
217+ d1 = defer.succeed(client2)
218+ self.patch(bmc_module, "getClientFromIdentifiers").return_value = d1
219+ self.patch(node_module, "getClientFromIdentifiers").return_value = d1
220+ self.patch(
221+ node_module, "power_query_all"
222+ ).return_value = defer.succeed((POWER_STATE.ON, set(), set()))
223+
224+ power_info = yield deferToDatabase(node.get_effective_power_info)
225+ yield node._power_control_node(
226+ defer.succeed(None), power_query, power_info
227+ )
228+
229+ def _assert_no_routable():
230+ self.assertRaises(
231+ BMCRoutableRackControllerRelationship.DoesNotExist,
232+ BMCRoutableRackControllerRelationship.objects.get,
233+ bmc=node.bmc,
234+ rack_controller=rack_controller,
235+ )
236+
237+ yield deferToDatabase(_assert_no_routable)
238+
239+
240 class TestDecomposeMachineMixin:
241 """Mixin to help `TestDecomposeMachine` and
242 `TestDecomposeMachineTransactional`."""

Subscribers

People subscribed via source and target branches