Merge ~bjornt/maas:bug-2056740-3.5 into maas:3.5

Proposed by Björn Tillenius
Status: Merged
Approved by: Björn Tillenius
Approved revision: 3469f13b0842b909f1099b2a97d6394372aef645
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~bjornt/maas:bug-2056740-3.5
Merge into: maas:3.5
Diff against target: 255 lines (+8/-74)
4 files modified
src/maasserver/models/node.py (+0/-11)
src/maasserver/models/tests/test_node.py (+0/-11)
src/provisioningserver/drivers/power/amt.py (+5/-23)
src/provisioningserver/drivers/power/tests/test_amt.py (+3/-29)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Björn Tillenius Approve
Review via email: mp+462333@code.launchpad.net

Commit message

Bug #2056740: Can't commission/deploy AMT machines

The maas-power script was passed "--boot-mode pxe" for AMT machines
and failed, since such a parameter wasn't defined.

All other power drivers, including the newer AMT one, sets PXE boot every
time the machine is powered on. I changed things, so that "boot-mode" is
no longer passed, and the older AMT driver also sets the machine to PXE
boot whenever it's turned on.

(cherry picked from commit 116ccedb102a78136d9e1d62d3144850e861947e)

To post a comment you must log in.
Revision history for this message
Björn Tillenius (bjornt) wrote :

Self-approve backport.

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

UNIT TESTS
-b bug-2056740-3.5 lp:~bjornt/maas/+git/maas into -b 3.5 lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 3469f13b0842b909f1099b2a97d6394372aef645

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
index e34f5d4..e9a3ac2 100644
--- a/src/maasserver/models/node.py
+++ b/src/maasserver/models/node.py
@@ -3134,17 +3134,6 @@ class Node(CleanSave, TimestampedModel):
3134 if self.bmc is not None and self.bmc.power_type == "ipmi":3134 if self.bmc is not None and self.bmc.power_type == "ipmi":
3135 power_params.setdefault("power_off_mode", "")3135 power_params.setdefault("power_off_mode", "")
31363136
3137 # boot_mode is something that tells the template whether this is
3138 # a PXE boot or a local HD boot.
3139 if self.bmc is not None and self.bmc.power_type == "amt":
3140 if (
3141 self.status == NODE_STATUS.DEPLOYED
3142 or self.node_type != NODE_TYPE.MACHINE
3143 ):
3144 power_params["boot_mode"] = "local"
3145 else:
3146 power_params["boot_mode"] = "pxe"
3147
3148 return power_params3137 return power_params
31493138
3150 def get_effective_power_info(self):3139 def get_effective_power_info(self):
diff --git a/src/maasserver/models/tests/test_node.py b/src/maasserver/models/tests/test_node.py
index 6195c28..5802bf5 100644
--- a/src/maasserver/models/tests/test_node.py
+++ b/src/maasserver/models/tests/test_node.py
@@ -1579,17 +1579,6 @@ class TestNode(MAASServerTestCase):
1579 params = node.get_effective_power_parameters()1579 params = node.get_effective_power_parameters()
1580 self.assertEqual("qemu://localhost/system", params["power_address"])1580 self.assertEqual("qemu://localhost/system", params["power_address"])
15811581
1582 def test_get_effective_power_parameters_sets_local_boot_mode(self):
1583 node = factory.make_Node(status=NODE_STATUS.DEPLOYED, power_type="amt")
1584 params = node.get_effective_power_parameters()
1585 self.assertEqual("local", params["boot_mode"])
1586
1587 def test_get_effective_power_parameters_sets_pxe_boot_mode(self):
1588 status = factory.pick_enum(NODE_STATUS, but_not=[NODE_STATUS.DEPLOYED])
1589 node = factory.make_Node(status=status, power_type="amt")
1590 params = node.get_effective_power_parameters()
1591 self.assertEqual("pxe", params["boot_mode"])
1592
1593 def test_get_effective_power_info_is_False_for_unset_power_type(self):1582 def test_get_effective_power_info_is_False_for_unset_power_type(self):
1594 node = factory.make_Node(power_type=None)1583 node = factory.make_Node(power_type=None)
1595 self.assertEqual(1584 self.assertEqual(
diff --git a/src/provisioningserver/drivers/power/amt.py b/src/provisioningserver/drivers/power/amt.py
index 63ecb29..8c7279b 100644
--- a/src/provisioningserver/drivers/power/amt.py
+++ b/src/provisioningserver/drivers/power/amt.py
@@ -178,13 +178,12 @@ class AMTPowerDriver(PowerDriver):
178 cmd: str,178 cmd: str,
179 ip_address: str,179 ip_address: str,
180 power_pass: str,180 power_pass: str,
181 amttool_boot_mode=None,
182 stdin=None,181 stdin=None,
183 ) -> bytes:182 ) -> bytes:
184 """Perform a command using amttool."""183 """Perform a command using amttool."""
185 command = ("amttool", ip_address, cmd)184 command = ("amttool", ip_address, cmd)
186 if cmd in ("power-cycle", "powerup"):185 if cmd in ("power-cycle", "powerup"):
187 command += (amttool_boot_mode,)186 command += ("pxe",)
188 return self._run(command, power_pass, stdin=stdin)187 return self._run(command, power_pass, stdin=stdin)
189188
190 def _issue_wsman_command(189 def _issue_wsman_command(
@@ -304,17 +303,16 @@ class AMTPowerDriver(PowerDriver):
304 "Got unknown power state from node: %s" % state303 "Got unknown power state from node: %s" % state
305 )304 )
306305
307 def amttool_restart(self, ip_address, power_pass, amttool_boot_mode):306 def amttool_restart(self, ip_address, power_pass):
308 """Restart the node via amttool."""307 """Restart the node via amttool."""
309 self._issue_amttool_command(308 self._issue_amttool_command(
310 "power_cycle",309 "power_cycle",
311 ip_address,310 ip_address,
312 power_pass,311 power_pass,
313 amttool_boot_mode=amttool_boot_mode,
314 stdin=b"yes",312 stdin=b"yes",
315 )313 )
316314
317 def amttool_power_on(self, ip_address, power_pass, amttool_boot_mode):315 def amttool_power_on(self, ip_address, power_pass):
318 """Power on the node via amttool."""316 """Power on the node via amttool."""
319 # Try several times. Power commands often fail the first time.317 # Try several times. Power commands often fail the first time.
320 for _ in range(10):318 for _ in range(10):
@@ -323,7 +321,6 @@ class AMTPowerDriver(PowerDriver):
323 "powerup",321 "powerup",
324 ip_address,322 ip_address,
325 power_pass,323 power_pass,
326 amttool_boot_mode=amttool_boot_mode,
327 stdin=b"yes",324 stdin=b"yes",
328 )325 )
329 if self.amttool_query_state(ip_address, power_pass) == "on":326 if self.amttool_query_state(ip_address, power_pass) == "on":
@@ -413,16 +410,6 @@ class AMTPowerDriver(PowerDriver):
413 else:410 else:
414 return "amttool"411 return "amttool"
415412
416 def _get_amttool_boot_mode(self, boot_mode):
417 """Set amttool boot mode."""
418 # boot_mode tells us whether we're pxe booting or local booting.
419 # For local booting, the argument to amttool must be empty
420 # (NOT 'hd', it doesn't work!).
421 if boot_mode == "local":
422 return ""
423 else:
424 return boot_mode
425
426 def _get_wsman_command(self, *args):413 def _get_wsman_command(self, *args):
427 base_path = snap.SnapPaths.from_environ().snap or "/"414 base_path = snap.SnapPaths.from_environ().snap or "/"
428 return (415 return (
@@ -455,15 +442,10 @@ class AMTPowerDriver(PowerDriver):
455 power_pass = context.get("power_pass")442 power_pass = context.get("power_pass")
456 amt_command = self._get_amt_command(ip_address, power_pass)443 amt_command = self._get_amt_command(ip_address, power_pass)
457 if amt_command == "amttool":444 if amt_command == "amttool":
458 amttool_boot_mode = self._get_amttool_boot_mode(
459 context.get("boot_mode")
460 )
461 if self.amttool_query_state(ip_address, power_pass) == "on":445 if self.amttool_query_state(ip_address, power_pass) == "on":
462 self.amttool_restart(ip_address, power_pass, amttool_boot_mode)446 self.amttool_restart(ip_address, power_pass)
463 else:447 else:
464 self.amttool_power_on(448 self.amttool_power_on(ip_address, power_pass)
465 ip_address, power_pass, amttool_boot_mode
466 )
467 elif amt_command == "wsman":449 elif amt_command == "wsman":
468 if self.wsman_query_state(ip_address, power_pass) == "on":450 if self.wsman_query_state(ip_address, power_pass) == "on":
469 self.wsman_power_on(ip_address, power_pass, restart=True)451 self.wsman_power_on(ip_address, power_pass, restart=True)
diff --git a/src/provisioningserver/drivers/power/tests/test_amt.py b/src/provisioningserver/drivers/power/tests/test_amt.py
index db207d8..4ab4bae 100644
--- a/src/provisioningserver/drivers/power/tests/test_amt.py
+++ b/src/provisioningserver/drivers/power/tests/test_amt.py
@@ -75,7 +75,6 @@ def make_context():
75 "power_address": factory.make_name("power_address"),75 "power_address": factory.make_name("power_address"),
76 "ip_address": factory.make_ipv4_address(),76 "ip_address": factory.make_ipv4_address(),
77 "power_pass": factory.make_name("power_pass"),77 "power_pass": factory.make_name("power_pass"),
78 "boot_mode": factory.make_name("boot_mode"),
79 }78 }
8079
8180
@@ -245,10 +244,9 @@ class TestAMTPowerDriver(MAASTestCase):
245 amt_power_driver = AMTPowerDriver()244 amt_power_driver = AMTPowerDriver()
246 ip_address = factory.make_ipv4_address()245 ip_address = factory.make_ipv4_address()
247 power_pass = factory.make_name("power_pass")246 power_pass = factory.make_name("power_pass")
248 amttool_boot_mode = factory.make_name("amttool_boot_mode")
249 stdin = factory.make_name("stdin").encode("utf-8")247 stdin = factory.make_name("stdin").encode("utf-8")
250 cmd = choice(["power-cycle", "powerup"])248 cmd = choice(["power-cycle", "powerup"])
251 command = "amttool", ip_address, cmd, amttool_boot_mode249 command = "amttool", ip_address, cmd, "pxe"
252 _run_mock = self.patch(amt_power_driver, "_run")250 _run_mock = self.patch(amt_power_driver, "_run")
253 _run_mock.return_value = b"output"251 _run_mock.return_value = b"output"
254252
@@ -256,7 +254,6 @@ class TestAMTPowerDriver(MAASTestCase):
256 cmd,254 cmd,
257 ip_address,255 ip_address,
258 power_pass,256 power_pass,
259 amttool_boot_mode=amttool_boot_mode,
260 stdin=stdin,257 stdin=stdin,
261 )258 )
262259
@@ -440,20 +437,16 @@ class TestAMTPowerDriver(MAASTestCase):
440 amt_power_driver = AMTPowerDriver()437 amt_power_driver = AMTPowerDriver()
441 ip_address = factory.make_ipv4_address()438 ip_address = factory.make_ipv4_address()
442 power_pass = factory.make_name("power_pass")439 power_pass = factory.make_name("power_pass")
443 amttool_boot_mode = factory.make_name("amttool_boot_mode")
444 _issue_amttool_command_mock = self.patch(440 _issue_amttool_command_mock = self.patch(
445 amt_power_driver, "_issue_amttool_command"441 amt_power_driver, "_issue_amttool_command"
446 )442 )
447443
448 amt_power_driver.amttool_restart(444 amt_power_driver.amttool_restart(ip_address, power_pass)
449 ip_address, power_pass, amttool_boot_mode
450 )
451445
452 _issue_amttool_command_mock.assert_called_once_with(446 _issue_amttool_command_mock.assert_called_once_with(
453 "power_cycle",447 "power_cycle",
454 ip_address,448 ip_address,
455 power_pass,449 power_pass,
456 amttool_boot_mode=amttool_boot_mode,
457 stdin=b"yes",450 stdin=b"yes",
458 )451 )
459452
@@ -461,7 +454,6 @@ class TestAMTPowerDriver(MAASTestCase):
461 amt_power_driver = AMTPowerDriver()454 amt_power_driver = AMTPowerDriver()
462 ip_address = factory.make_ipv4_address()455 ip_address = factory.make_ipv4_address()
463 power_pass = factory.make_name("power_pass")456 power_pass = factory.make_name("power_pass")
464 amttool_boot_mode = factory.make_name("amttool_boot_mode")
465 _issue_amttool_command_mock = self.patch(457 _issue_amttool_command_mock = self.patch(
466 amt_power_driver, "_issue_amttool_command"458 amt_power_driver, "_issue_amttool_command"
467 )459 )
@@ -470,15 +462,12 @@ class TestAMTPowerDriver(MAASTestCase):
470 )462 )
471 amttool_query_state_mock.return_value = "on"463 amttool_query_state_mock.return_value = "on"
472464
473 amt_power_driver.amttool_power_on(465 amt_power_driver.amttool_power_on(ip_address, power_pass)
474 ip_address, power_pass, amttool_boot_mode
475 )
476466
477 _issue_amttool_command_mock.assert_called_once_with(467 _issue_amttool_command_mock.assert_called_once_with(
478 "powerup",468 "powerup",
479 ip_address,469 ip_address,
480 power_pass,470 power_pass,
481 amttool_boot_mode=amttool_boot_mode,
482 stdin=b"yes",471 stdin=b"yes",
483 )472 )
484 amttool_query_state_mock.assert_called_once_with(473 amttool_query_state_mock.assert_called_once_with(
@@ -489,7 +478,6 @@ class TestAMTPowerDriver(MAASTestCase):
489 amt_power_driver = AMTPowerDriver()478 amt_power_driver = AMTPowerDriver()
490 ip_address = factory.make_ipv4_address()479 ip_address = factory.make_ipv4_address()
491 power_pass = factory.make_name("power_pass")480 power_pass = factory.make_name("power_pass")
492 amttool_boot_mode = factory.make_name("amttool_boot_mode")
493 self.patch(amt_power_driver, "_issue_amttool_command")481 self.patch(amt_power_driver, "_issue_amttool_command")
494 amttool_query_state_mock = self.patch(482 amttool_query_state_mock = self.patch(
495 amt_power_driver, "amttool_query_state"483 amt_power_driver, "amttool_query_state"
@@ -501,7 +489,6 @@ class TestAMTPowerDriver(MAASTestCase):
501 amt_power_driver.amttool_power_on,489 amt_power_driver.amttool_power_on,
502 ip_address,490 ip_address,
503 power_pass,491 power_pass,
504 amttool_boot_mode,
505 )492 )
506493
507 def test_amttool_power_off_powers_off(self):494 def test_amttool_power_off_powers_off(self):
@@ -787,17 +774,6 @@ class TestAMTPowerDriver(MAASTestCase):
787 factory.make_name("power_pass"),774 factory.make_name("power_pass"),
788 )775 )
789776
790 def test_get_amttool_boot_mode_local_boot(self):
791 amt_power_driver = AMTPowerDriver()
792 result = amt_power_driver._get_amttool_boot_mode("local")
793 self.assertEqual(result, "")
794
795 def test_get_ammtool_boot_mode_pxe_booting(self):
796 amt_power_driver = AMTPowerDriver()
797 boot_mode = factory.make_name("boot_mode")
798 result = amt_power_driver._get_amttool_boot_mode(boot_mode)
799 self.assertEqual(result, boot_mode)
800
801 def test_get_ip_address_returns_ip_address(self):777 def test_get_ip_address_returns_ip_address(self):
802 amt_power_driver = AMTPowerDriver()778 amt_power_driver = AMTPowerDriver()
803 power_address = factory.make_name("power_address")779 power_address = factory.make_name("power_address")
@@ -841,7 +817,6 @@ class TestAMTPowerDriver(MAASTestCase):
841 amttool_restart_mock.assert_called_once_with(817 amttool_restart_mock.assert_called_once_with(
842 context["ip_address"],818 context["ip_address"],
843 context["power_pass"],819 context["power_pass"],
844 context["boot_mode"],
845 )820 )
846821
847 def test_power_on_powers_on_with_amttool_when_already_off(self):822 def test_power_on_powers_on_with_amttool_when_already_off(self):
@@ -870,7 +845,6 @@ class TestAMTPowerDriver(MAASTestCase):
870 amttool_power_on_mock.assert_called_once_with(845 amttool_power_on_mock.assert_called_once_with(
871 context["ip_address"],846 context["ip_address"],
872 context["power_pass"],847 context["power_pass"],
873 context["boot_mode"],
874 )848 )
875849
876 def test_power_on_powers_on_with_wsman_when_already_on(self):850 def test_power_on_powers_on_with_wsman_when_already_on(self):

Subscribers

People subscribed via source and target branches