summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCenne <cennedee+opendev@protonmail.com>2021-08-09 19:32:53 +0200
committerCenne <cennedee+opendev@protonmail.com>2021-08-13 18:24:58 +0200
commit00808631c1ffa3a9ec2cecafd5ea9f7447f440a8 (patch)
tree035d6232e171c2940a80f6fa5e8e4c87f0a09251
parenta5a3d4e4426ce8700f193aae77688cd63ac26b05 (diff)
downloadpython-ironicclient-00808631c1ffa3a9ec2cecafd5ea9f7447f440a8.tar.gz
Add support for changing 'boot_mode' and 'secure_boot' states
Story: 2008567 Task: 41709 depends-on: https://review.opendev.org/c/openstack/ironic/+/800084 Change-Id: I2937ea924ccc4ca6e9ab5599aa02e3c078c166b3
-rw-r--r--ironicclient/common/http.py2
-rwxr-xr-xironicclient/osc/v1/baremetal_node.py76
-rw-r--r--ironicclient/tests/unit/osc/v1/test_baremetal_node.py63
-rw-r--r--ironicclient/tests/unit/v1/test_node.py61
-rw-r--r--ironicclient/v1/node.py58
-rw-r--r--releasenotes/notes/add-node-boot-mode-set-9746b45aa3f80fe8.yaml5
-rw-r--r--setup.cfg3
7 files changed, 267 insertions, 1 deletions
diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py
index 2c71386..f2a1aef 100644
--- a/ironicclient/common/http.py
+++ b/ironicclient/common/http.py
@@ -37,7 +37,7 @@ from ironicclient import exc
# http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa
# for full details.
DEFAULT_VER = '1.9'
-LAST_KNOWN_API_VERSION = 75
+LAST_KNOWN_API_VERSION = 76
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
LOG = logging.getLogger(__name__)
diff --git a/ironicclient/osc/v1/baremetal_node.py b/ironicclient/osc/v1/baremetal_node.py
index 45b3b30..2229ac0 100755
--- a/ironicclient/osc/v1/baremetal_node.py
+++ b/ironicclient/osc/v1/baremetal_node.py
@@ -242,6 +242,38 @@ class BootdeviceShowBaremetalNode(command.ShowOne):
return zip(*sorted(info.items()))
+class BootmodeSetBaremetalNode(command.Command):
+ """Set boot mode for baremetal node"""
+
+ log = logging.getLogger(__name__ + ".BootmodeSetBaremetalNode")
+
+ def get_parser(self, prog_name):
+ parser = super(BootmodeSetBaremetalNode, self).get_parser(prog_name)
+
+ parser.add_argument(
+ 'node',
+ metavar='<node>',
+ help=_("Name or UUID of the node.")
+ )
+ parser.add_argument(
+ 'boot_mode',
+ choices=['uefi', 'bios'],
+ metavar='<boot_mode>',
+ help=_('The boot mode to set for node (uefi/bios)')
+ )
+
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug("take_action(%s)", parsed_args)
+
+ baremetal_client = self.app.client_manager.baremetal
+
+ baremetal_client.node.set_boot_mode(
+ parsed_args.node,
+ parsed_args.boot_mode)
+
+
class CleanBaremetalNode(ProvisionStateWithWait):
"""Set provision state of baremetal node to 'clean'"""
@@ -1086,6 +1118,50 @@ class RescueBaremetalNode(ProvisionStateWithWait):
return parser
+class SecurebootOnBaremetalNode(command.Command):
+ """Turn secure boot on"""
+
+ log = logging.getLogger(__name__ + ".SecurebootOnBaremetalNode")
+
+ def get_parser(self, prog_name):
+ parser = super(SecurebootOnBaremetalNode, self).get_parser(prog_name)
+
+ parser.add_argument(
+ 'node',
+ metavar='<node>',
+ help=_("Name or UUID of the node")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug("take_action(%s)", parsed_args)
+
+ baremetal_client = self.app.client_manager.baremetal
+ baremetal_client.node.set_secure_boot(parsed_args.node, 'on')
+
+
+class SecurebootOffBaremetalNode(command.Command):
+ """Turn secure boot off"""
+
+ log = logging.getLogger(__name__ + ".SecurebootOffBaremetalNode")
+
+ def get_parser(self, prog_name):
+ parser = super(SecurebootOffBaremetalNode, self).get_parser(prog_name)
+
+ parser.add_argument(
+ 'node',
+ metavar='<node>',
+ help=_("Name or UUID of the node")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug("take_action(%s)", parsed_args)
+
+ baremetal_client = self.app.client_manager.baremetal
+ baremetal_client.node.set_secure_boot(parsed_args.node, 'off')
+
+
class SetBaremetalNode(command.Command):
"""Set baremetal properties"""
diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py
index 7b17e47..1ec53be 100644
--- a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py
+++ b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py
@@ -440,6 +440,69 @@ class TestConsoleShow(TestBaremetal):
'node_uuid')
+class TestSecurebootOff(TestBaremetal):
+ def setUp(self):
+ super(TestSecurebootOff, self).setUp()
+
+ # Get the command object to test
+ self.cmd = baremetal_node.SecurebootOffBaremetalNode(self.app, None)
+
+ def test_secure_boot_off(self):
+ arglist = ['node_uuid']
+ verifylist = [('node', 'node_uuid')]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.baremetal_mock.node.set_secure_boot.assert_called_once_with(
+ 'node_uuid', 'off')
+
+
+class TestSecurebootOn(TestBaremetal):
+ def setUp(self):
+ super(TestSecurebootOn, self).setUp()
+
+ # Get the command object to test
+ self.cmd = baremetal_node.SecurebootOnBaremetalNode(self.app, None)
+
+ def test_console_enable(self):
+ arglist = ['node_uuid']
+ verifylist = [('node', 'node_uuid')]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.baremetal_mock.node.set_secure_boot.assert_called_once_with(
+ 'node_uuid', 'on')
+
+
+class TestBootmodeSet(TestBaremetal):
+ def setUp(self):
+ super(TestBootmodeSet, self).setUp()
+
+ # Get the command object to test
+ self.cmd = baremetal_node.BootmodeSetBaremetalNode(self.app, None)
+
+ def test_baremetal_boot_mode_bios(self):
+ arglist = ['node_uuid',
+ 'bios']
+ verifylist = [
+ ('node', 'node_uuid'),
+ ('boot_mode', 'bios'),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.baremetal_mock.node.set_boot_mode.assert_called_once_with(
+ 'node_uuid',
+ 'bios'
+ )
+
+
class TestBaremetalCreate(TestBaremetal):
def setUp(self):
super(TestBaremetalCreate, self).setUp()
diff --git a/ironicclient/tests/unit/v1/test_node.py b/ironicclient/tests/unit/v1/test_node.py
index 648fce3..85352e9 100644
--- a/ironicclient/tests/unit/v1/test_node.py
+++ b/ironicclient/tests/unit/v1/test_node.py
@@ -412,6 +412,13 @@ fake_responses = {
None,
),
},
+ '/v1/nodes/%s/states/boot_mode' % NODE1['uuid']:
+ {
+ 'PUT': (
+ {},
+ None,
+ ),
+ },
'/v1/nodes/%s/states/power' % NODE1['uuid']:
{
'PUT': (
@@ -419,6 +426,13 @@ fake_responses = {
POWER_STATE,
),
},
+ '/v1/nodes/%s/states/secure_boot' % NODE1['uuid']:
+ {
+ 'PUT': (
+ {},
+ None,
+ ),
+ },
'/v1/nodes/%s/validate' % NODE1['uuid']:
{
'GET': (
@@ -1452,6 +1466,53 @@ class NodeManagerTest(testtools.TestCase):
self.mgr.set_power_state,
NODE1['uuid'], 'off', soft=False, timeout='a')
+ def test_node_set_boot_mode_bios(self):
+ target_state = 'bios'
+ self.mgr.set_boot_mode(NODE1['uuid'], target_state)
+ body = {'target': target_state}
+ expect = [
+ ('PUT', '/v1/nodes/%s/states/boot_mode' % NODE1['uuid'], {}, body),
+ ]
+ self.assertEqual(expect, self.api.calls)
+
+ def test_node_set_boot_mode_invalid(self):
+ self.assertRaises(ValueError, self.mgr.set_boot_mode,
+ NODE1['uuid'], 'ancient-bios')
+
+ def test_node_set_secure_boot_bool(self):
+ secure_boot = self.mgr.set_secure_boot(NODE1['uuid'], True)
+ body = {'target': True}
+ expect = [
+ ('PUT', '/v1/nodes/%s/states/secure_boot' % NODE1['uuid'],
+ {}, body),
+ ]
+ self.assertEqual(expect, self.api.calls)
+ self.assertIsNone(secure_boot)
+
+ def test_node_set_secure_boot_on(self):
+ secure_boot = self.mgr.set_secure_boot(NODE1['uuid'], 'on')
+ body = {'target': True}
+ expect = [
+ ('PUT', '/v1/nodes/%s/states/secure_boot' % NODE1['uuid'],
+ {}, body),
+ ]
+ self.assertEqual(expect, self.api.calls)
+ self.assertIsNone(secure_boot)
+
+ def test_node_set_secure_boot_off(self):
+ secure_boot = self.mgr.set_secure_boot(NODE1['uuid'], 'off')
+ body = {'target': False}
+ expect = [
+ ('PUT', '/v1/nodes/%s/states/secure_boot' % NODE1['uuid'],
+ {}, body),
+ ]
+ self.assertEqual(expect, self.api.calls)
+ self.assertIsNone(secure_boot)
+
+ def test_node_set_secure_boot_bad(self):
+ self.assertRaises(exc.InvalidAttribute, self.mgr.set_secure_boot,
+ NODE1['uuid'], 'band')
+
def test_set_target_raid_config(self):
self.mgr.set_target_raid_config(
NODE1['uuid'], {'fake': 'config'})
diff --git a/ironicclient/v1/node.py b/ironicclient/v1/node.py
index 88879f0..df00867 100644
--- a/ironicclient/v1/node.py
+++ b/ironicclient/v1/node.py
@@ -590,6 +590,64 @@ class NodeManager(base.CreateManager):
os_ironic_api_version=os_ironic_api_version,
global_request_id=global_request_id)
+ def set_boot_mode(self, node_id, state,
+ os_ironic_api_version=None, global_request_id=None):
+ """Sets boot mode for a node.
+
+ :param node_id: Node identifier
+ :param state: One of target boot modes, 'uefi' or 'bios'
+ :param os_ironic_api_version: String version (e.g. "1.76") to use for
+ the request. If not specified, the client's default is used.
+ :param global_request_id: String containing global request ID header
+ value (in form "req-<UUID>") to use for the request.
+
+ :raises: ValueError if boot mode is not one of 'uefi' / 'bios'
+ :returns: The status of the request
+ """
+ if state not in ('uefi', 'bios'):
+ raise ValueError(
+ _("Valid boot modes are 'uefi' or 'bios'"))
+
+ path = "%s/states/boot_mode" % node_id
+ target = state
+ body = {'target': target}
+
+ return self.update(path, body, http_method='PUT',
+ os_ironic_api_version=os_ironic_api_version,
+ global_request_id=global_request_id)
+
+ def set_secure_boot(self, node_id, state,
+ os_ironic_api_version=None, global_request_id=None):
+ """Set the secure boot state for the node.
+
+ :param node_id: The UUID of the node.
+ :param state: the secure boot state; either a Boolean or a string
+ representation of a Boolean (eg, 'true', 'on', 'false',
+ 'off'). True to turn secure boot on; False
+ to turn secure boot off.
+ :param os_ironic_api_version: String version (e.g. "1.76") to use for
+ the request. If not specified, the client's default is used.
+ :param global_request_id: String containing global request ID header
+ value (in form "req-<UUID>") to use for the request.
+
+ :raises: InvalidAttribute if state is an invalid string (that doesn't
+ represent a Boolean).
+ """
+ if isinstance(state, bool):
+ target = state
+ else:
+ try:
+ target = strutils.bool_from_string(state, strict=True)
+ except ValueError as e:
+ raise exc.InvalidAttribute(_("Argument 'state': %(err)s") %
+ {'err': e})
+ path = "%s/states/secure_boot" % node_id
+ body = {'target': target}
+
+ return self.update(path, body, http_method='PUT',
+ os_ironic_api_version=os_ironic_api_version,
+ global_request_id=global_request_id)
+
def set_target_raid_config(
self, node_ident, target_raid_config,
os_ironic_api_version=None, global_request_id=None):
diff --git a/releasenotes/notes/add-node-boot-mode-set-9746b45aa3f80fe8.yaml b/releasenotes/notes/add-node-boot-mode-set-9746b45aa3f80fe8.yaml
new file mode 100644
index 0000000..0abe738
--- /dev/null
+++ b/releasenotes/notes/add-node-boot-mode-set-9746b45aa3f80fe8.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Adds support for changing node states ``boot_mode`` and ``secure_boot``
+ in sync with functionality introduced in API 1.76.
diff --git a/setup.cfg b/setup.cfg
index b430146..d8de9bb 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -63,6 +63,7 @@ openstack.baremetal.v1 =
baremetal_node_bios_setting_show = ironicclient.osc.v1.baremetal_node:BIOSSettingShowBaremetalNode
baremetal_node_boot_device_set = ironicclient.osc.v1.baremetal_node:BootdeviceSetBaremetalNode
baremetal_node_boot_device_show = ironicclient.osc.v1.baremetal_node:BootdeviceShowBaremetalNode
+ baremetal_node_boot_mode_set = ironicclient.osc.v1.baremetal_node:BootmodeSetBaremetalNode
baremetal_node_clean = ironicclient.osc.v1.baremetal_node:CleanBaremetalNode
baremetal_node_console_disable = ironicclient.osc.v1.baremetal_node:ConsoleDisableBaremetalNode
baremetal_node_console_enable = ironicclient.osc.v1.baremetal_node:ConsoleEnableBaremetalNode
@@ -84,6 +85,8 @@ openstack.baremetal.v1 =
baremetal_node_rebuild = ironicclient.osc.v1.baremetal_node:RebuildBaremetalNode
baremetal_node_remove_trait = ironicclient.osc.v1.baremetal_node:RemoveTraitBaremetalNode
baremetal_node_rescue = ironicclient.osc.v1.baremetal_node:RescueBaremetalNode
+ baremetal_node_secure_boot_on = ironicclient.osc.v1.baremetal_node:SecurebootOnBaremetalNode
+ baremetal_node_secure_boot_off = ironicclient.osc.v1.baremetal_node:SecurebootOffBaremetalNode
baremetal_node_set = ironicclient.osc.v1.baremetal_node:SetBaremetalNode
baremetal_node_show = ironicclient.osc.v1.baremetal_node:ShowBaremetalNode
baremetal_node_trait_list = ironicclient.osc.v1.baremetal_node:ListTraitsBaremetalNode