BIOS Settings support

This adds support for the BIOS Setting APIs in the
openstackclient plugin. Also bump the last known
API version to 1.40 to get access to new API.

Change-Id: I1b4185e53818686c895d1fe526ba3fe5540873b3
This commit is contained in:
Zenghui Shi
2018-05-18 11:53:46 +08:00
parent 695f501fa8
commit 2fabfa4103
11 changed files with 250 additions and 38 deletions

View File

@@ -350,6 +350,12 @@ class CreateBaremetalNode(command.ShowOne):
'--name',
metavar='<name>',
help=_("Unique name for the node."))
parser.add_argument(
'--bios-interface',
metavar='<bios_interface>',
help=_('BIOS interface used by the node\'s driver. This is '
'only applicable when the specified --driver is a '
'hardware type.'))
parser.add_argument(
'--boot-interface',
metavar='<boot_interface>',
@@ -427,12 +433,13 @@ class CreateBaremetalNode(command.ShowOne):
field_list = ['chassis_uuid', 'driver', 'driver_info',
'properties', 'extra', 'uuid', 'name',
'boot_interface', 'console_interface',
'deploy_interface', 'inspect_interface',
'management_interface', 'network_interface',
'power_interface', 'raid_interface',
'rescue_interface', 'storage_interface',
'vendor_interface', 'resource_class']
'bios_interface', 'boot_interface',
'console_interface', 'deploy_interface',
'inspect_interface', 'management_interface',
'network_interface', 'power_interface',
'raid_interface', 'rescue_interface',
'storage_interface', 'vendor_interface',
'resource_class']
fields = dict((k, v) for (k, v) in vars(parsed_args).items()
if k in field_list and not (v is None))
fields = utils.args_array_to_dict(fields, 'driver_info')
@@ -993,6 +1000,11 @@ class SetBaremetalNode(command.Command):
metavar="<driver>",
help=_("Set the driver for the node"),
)
parser.add_argument(
'--bios-interface',
metavar='<bios_interface>',
help=_('Set the BIOS interface for the node'),
)
parser.add_argument(
'--boot-interface',
metavar='<boot_interface>',
@@ -1125,6 +1137,11 @@ class SetBaremetalNode(command.Command):
driver = ["driver=%s" % parsed_args.driver]
properties.extend(utils.args_array_to_patch(
'add', driver))
if parsed_args.bios_interface:
bios_interface = [
"bios_interface=%s" % parsed_args.bios_interface]
properties.extend(utils.args_array_to_patch(
'add', bios_interface))
if parsed_args.boot_interface:
boot_interface = [
"boot_interface=%s" % parsed_args.boot_interface]
@@ -1340,6 +1357,12 @@ class UnsetBaremetalNode(command.Command):
action='store_true',
help=_('Unset chassis UUID on this baremetal node'),
)
parser.add_argument(
"--bios-interface",
dest='bios_interface',
action='store_true',
help=_('Unset BIOS interface on this baremetal node'),
)
parser.add_argument(
"--boot-interface",
dest='boot_interface',
@@ -1448,6 +1471,9 @@ class UnsetBaremetalNode(command.Command):
if parsed_args.chassis_uuid:
properties.extend(utils.args_array_to_patch('remove',
['chassis_uuid']))
if parsed_args.bios_interface:
properties.extend(utils.args_array_to_patch('remove',
['bios_interface']))
if parsed_args.boot_interface:
properties.extend(utils.args_array_to_patch('remove',
['boot_interface']))
@@ -1747,3 +1773,59 @@ class RemoveTraitBaremetalNode(command.Command):
if failures:
raise exc.ClientException("\n".join(failures))
class ListBIOSSettingBaremetalNode(command.Lister):
"""List a node's BIOS settings."""
log = logging.getLogger(__name__ + ".ListBIOSSettingBaremetalNode")
def get_parser(self, prog_name):
parser = super(ListBIOSSettingBaremetalNode, 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)
labels = res_fields.BIOS_RESOURCE.labels
baremetal_client = self.app.client_manager.baremetal
settings = baremetal_client.node.list_bios_settings(parsed_args.node)
return (labels, [[s['name'], s['value']] for s in settings])
class BIOSSettingShowBaremetalNode(command.ShowOne):
"""Show a specific BIOS setting for a node."""
log = logging.getLogger(__name__ + ".BIOSSettingShowBaremetalNode")
def get_parser(self, prog_name):
parser = super(BIOSSettingShowBaremetalNode, self).get_parser(
prog_name)
parser.add_argument(
'node',
metavar='<node>',
help=_("Name or UUID of the node")
)
parser.add_argument(
'setting_name',
metavar='<setting name>',
help=_("Setting name to show")
)
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args)
baremetal_client = self.app.client_manager.baremetal
setting = baremetal_client.node.get_bios_setting(
parsed_args.node, parsed_args.setting_name)
setting.pop("links", None)
return self.dict2columns(setting)

View File

@@ -64,6 +64,7 @@ BAREMETAL_PORT = {
baremetal_driver_hosts = ['fake-host1', 'fake-host2']
baremetal_driver_name = 'fakedrivername'
baremetal_driver_type = 'classic'
baremetal_driver_default_bios_if = 'bios'
baremetal_driver_default_boot_if = 'boot'
baremetal_driver_default_console_if = 'console'
baremetal_driver_default_deploy_if = 'deploy'
@@ -75,6 +76,7 @@ baremetal_driver_default_raid_if = 'raid'
baremetal_driver_default_rescue_if = 'rescue'
baremetal_driver_default_storage_if = 'storage'
baremetal_driver_default_vendor_if = 'vendor'
baremetal_driver_enabled_bios_ifs = ['bios', 'bios2']
baremetal_driver_enabled_boot_ifs = ['boot', 'boot2']
baremetal_driver_enabled_console_ifs = ['console', 'console2']
baremetal_driver_enabled_deploy_ifs = ['deploy', 'deploy2']
@@ -91,6 +93,7 @@ BAREMETAL_DRIVER = {
'hosts': baremetal_driver_hosts,
'name': baremetal_driver_name,
'type': baremetal_driver_type,
'default_bios_interface': baremetal_driver_default_bios_if,
'default_boot_interface': baremetal_driver_default_boot_if,
'default_console_interface': baremetal_driver_default_console_if,
'default_deploy_interface': baremetal_driver_default_deploy_if,
@@ -102,6 +105,7 @@ BAREMETAL_DRIVER = {
'default_rescue_interface': baremetal_driver_default_rescue_if,
'default_storage_interface': baremetal_driver_default_storage_if,
'default_vendor_interface': baremetal_driver_default_vendor_if,
'enabled_bios_interfaces': baremetal_driver_enabled_bios_ifs,
'enabled_boot_interfaces': baremetal_driver_enabled_boot_ifs,
'enabled_console_interfaces': baremetal_driver_enabled_console_ifs,
'enabled_deploy_interfaces': baremetal_driver_enabled_deploy_ifs,
@@ -142,6 +146,8 @@ PORTGROUP = {'uuid': baremetal_portgroup_uuid,
VIFS = {'vifs': [{'id': 'aaa-aa'}]}
TRAITS = ['CUSTOM_FOO', 'CUSTOM_BAR']
BIOS_SETTINGS = [{'name': 'bios_name_1', 'value': 'bios_value_1', 'links': []},
{'name': 'bios_name_2', 'value': 'bios_value_2', 'links': []}]
baremetal_volume_connector_uuid = 'vvv-cccccc-vvvv'
baremetal_volume_connector_type = 'iqn'

View File

@@ -88,6 +88,7 @@ class TestListBaremetalDriver(TestBaremetalDriver):
"Supported driver(s)",
"Type",
"Active host(s)",
'Default BIOS Interface',
'Default Boot Interface',
'Default Console Interface',
'Default Deploy Interface',
@@ -99,6 +100,7 @@ class TestListBaremetalDriver(TestBaremetalDriver):
'Default Rescue Interface',
'Default Storage Interface',
'Default Vendor Interface',
'Enabled BIOS Interfaces',
'Enabled Boot Interfaces',
'Enabled Console Interfaces',
'Enabled Deploy Interfaces',
@@ -117,6 +119,7 @@ class TestListBaremetalDriver(TestBaremetalDriver):
baremetal_fakes.baremetal_driver_name,
baremetal_fakes.baremetal_driver_type,
', '.join(baremetal_fakes.baremetal_driver_hosts),
baremetal_fakes.baremetal_driver_default_bios_if,
baremetal_fakes.baremetal_driver_default_boot_if,
baremetal_fakes.baremetal_driver_default_console_if,
baremetal_fakes.baremetal_driver_default_deploy_if,
@@ -128,6 +131,7 @@ class TestListBaremetalDriver(TestBaremetalDriver):
baremetal_fakes.baremetal_driver_default_rescue_if,
baremetal_fakes.baremetal_driver_default_storage_if,
baremetal_fakes.baremetal_driver_default_vendor_if,
', '.join(baremetal_fakes.baremetal_driver_enabled_bios_ifs),
', '.join(baremetal_fakes.baremetal_driver_enabled_boot_ifs),
', '.join(baremetal_fakes.baremetal_driver_enabled_console_ifs),
', '.join(baremetal_fakes.baremetal_driver_enabled_deploy_ifs),
@@ -361,14 +365,16 @@ class TestShowBaremetalDriver(TestBaremetalDriver):
self.baremetal_mock.driver.get.assert_called_with(*args)
self.assertFalse(self.baremetal_mock.driver.properties.called)
collist = ('default_boot_interface', 'default_console_interface',
'default_deploy_interface', 'default_inspect_interface',
'default_management_interface', 'default_network_interface',
'default_power_interface', 'default_raid_interface',
'default_rescue_interface', 'default_storage_interface',
'default_vendor_interface',
'enabled_boot_interfaces', 'enabled_console_interfaces',
'enabled_deploy_interfaces', 'enabled_inspect_interfaces',
collist = ('default_bios_interface', 'default_boot_interface',
'default_console_interface', 'default_deploy_interface',
'default_inspect_interface',
'default_management_interface',
'default_network_interface', 'default_power_interface',
'default_raid_interface', 'default_rescue_interface',
'default_storage_interface', 'default_vendor_interface',
'enabled_bios_interfaces', 'enabled_boot_interfaces',
'enabled_console_interfaces', 'enabled_deploy_interfaces',
'enabled_inspect_interfaces',
'enabled_management_interfaces',
'enabled_network_interfaces', 'enabled_power_interfaces',
'enabled_raid_interfaces', 'enabled_rescue_interfaces',
@@ -377,6 +383,7 @@ class TestShowBaremetalDriver(TestBaremetalDriver):
self.assertEqual(collist, columns)
datalist = (
baremetal_fakes.baremetal_driver_default_bios_if,
baremetal_fakes.baremetal_driver_default_boot_if,
baremetal_fakes.baremetal_driver_default_console_if,
baremetal_fakes.baremetal_driver_default_deploy_if,
@@ -388,6 +395,7 @@ class TestShowBaremetalDriver(TestBaremetalDriver):
baremetal_fakes.baremetal_driver_default_rescue_if,
baremetal_fakes.baremetal_driver_default_storage_if,
baremetal_fakes.baremetal_driver_default_vendor_if,
', '.join(baremetal_fakes.baremetal_driver_enabled_bios_ifs),
', '.join(baremetal_fakes.baremetal_driver_enabled_boot_ifs),
', '.join(baremetal_fakes.baremetal_driver_enabled_console_ifs),
', '.join(baremetal_fakes.baremetal_driver_enabled_deploy_ifs),

View File

@@ -385,6 +385,11 @@ class TestBaremetalCreate(TestBaremetal):
[('name', 'name')],
{'name': 'name'})
def test_baremetal_create_with_bios_interface(self):
self.check_with_options(['--bios-interface', 'bios'],
[('bios_interface', 'bios')],
{'bios_interface': 'bios'})
def test_baremetal_create_with_boot_interface(self):
self.check_with_options(['--boot-interface', 'boot'],
[('boot_interface', 'boot')],
@@ -599,12 +604,12 @@ class TestBaremetalList(TestBaremetal):
'Target Provision State', 'Target RAID configuration',
'Traits', 'Updated At', 'Inspection Finished At',
'Inspection Started At', 'UUID', 'Name',
'Boot Interface', 'Console Interface',
'Deploy Interface', 'Inspect Interface',
'Management Interface', 'Network Interface',
'Power Interface', 'RAID Interface',
'Rescue Interface', 'Storage Interface',
'Vendor Interface')
'BIOS Interface', 'Boot Interface',
'Console Interface', 'Deploy Interface',
'Inspect Interface', 'Management Interface',
'Network Interface', 'Power Interface',
'RAID Interface', 'Rescue Interface',
'Storage Interface', 'Vendor Interface')
self.assertEqual(collist, columns)
datalist = ((
'',
@@ -648,6 +653,7 @@ class TestBaremetalList(TestBaremetal):
'',
'',
'',
'',
), )
self.assertEqual(datalist, tuple(data))
@@ -2041,6 +2047,9 @@ class TestBaremetalSet(TestBaremetal):
'value': 'xxxxx', 'op': 'add'}]
)
def test_baremetal_set_bios_interface(self):
self._test_baremetal_set_hardware_interface('bios')
def test_baremetal_set_boot_interface(self):
self._test_baremetal_set_hardware_interface('boot')
@@ -2662,6 +2671,9 @@ class TestBaremetalUnset(TestBaremetal):
[{'path': '/%s_interface' % interface, 'op': 'remove'}]
)
def test_baremetal_unset_bios_interface(self):
self._test_baremetal_unset_hw_interface('bios')
def test_baremetal_unset_boot_interface(self):
self._test_baremetal_unset_hw_interface('boot')
@@ -3025,3 +3037,53 @@ class TestRemoveTrait(TestBaremetal):
self.baremetal_mock.node.remove_all_traits.assert_not_called()
self.baremetal_mock.node.remove_trait.assert_not_called()
class TestListBIOSSetting(TestBaremetal):
def setUp(self):
super(TestListBIOSSetting, self).setUp()
self.baremetal_mock.node.list_bios_settings.return_value = (
baremetal_fakes.BIOS_SETTINGS)
# Get the command object to test
self.cmd = baremetal_node.ListBIOSSettingBaremetalNode(self.app, None)
def test_baremetal_list_bios_setting(self):
arglist = ['node_uuid']
verifylist = [('node', 'node_uuid')]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
data = self.cmd.take_action(parsed_args)
self.baremetal_mock.node.list_bios_settings.assert_called_once_with(
'node_uuid')
expected_data = (('BIOS setting name', 'BIOS setting value'),
[[s['name'], s['value']]
for s in baremetal_fakes.BIOS_SETTINGS])
self.assertEqual(expected_data, data)
class TestBIOSSettingShow(TestBaremetal):
def setUp(self):
super(TestBIOSSettingShow, self).setUp()
self.baremetal_mock.node.get_bios_setting.return_value = (
baremetal_fakes.BIOS_SETTINGS[0])
# Get the command object to test
self.cmd = baremetal_node.BIOSSettingShowBaremetalNode(self.app, None)
def test_baremetal_bios_setting_show(self):
arglist = ['node_uuid', 'bios_name_1']
verifylist = [('node', 'node_uuid'), ('setting_name', 'bios_name_1')]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.baremetal_mock.node.get_bios_setting.assert_called_once_with(
'node_uuid', 'bios_name_1')
expected_data = ('bios_name_1', 'bios_value_1')
self.assertEqual(expected_data, tuple(data))

View File

@@ -26,6 +26,7 @@ DRIVER1 = {
'name': 'fake',
'type': 'dynamic',
'hosts': ['fake-host1', 'fake-host2'],
'default_bios_interface': 'bios',
'default_boot_interface': 'boot',
'default_console_interface': 'console',
'default_deploy_interface': 'deploy',
@@ -35,6 +36,7 @@ DRIVER1 = {
'default_power_interface': 'power',
'default_raid_interface': 'raid',
'default_vendor_interface': 'vendor',
'enabled_bios_interfaces': ['bios', 'bios2'],
'enabled_boot_interfaces': ['boot', 'boot2'],
'enabled_console_interfaces': ['console', 'console2'],
'enabled_deploy_interfaces': ['deploy', 'deploy2'],

View File

@@ -35,18 +35,18 @@ class DriverShellTest(utils.BaseTestCase):
driver = object()
d_shell._print_driver_show(driver)
exp = ['hosts', 'name', 'type',
'default_boot_interface', 'default_console_interface',
'default_deploy_interface', 'default_inspect_interface',
'default_management_interface', 'default_network_interface',
'default_power_interface', 'default_raid_interface',
'default_rescue_interface', 'default_storage_interface',
'default_vendor_interface',
'enabled_boot_interfaces', 'enabled_console_interfaces',
'enabled_deploy_interfaces', 'enabled_inspect_interfaces',
'enabled_management_interfaces', 'enabled_network_interfaces',
'enabled_power_interfaces', 'enabled_raid_interfaces',
'enabled_rescue_interfaces', 'enabled_storage_interfaces',
'enabled_vendor_interfaces']
'default_bios_interface', 'default_boot_interface',
'default_console_interface', 'default_deploy_interface',
'default_inspect_interface', 'default_management_interface',
'default_network_interface', 'default_power_interface',
'default_raid_interface', 'default_rescue_interface',
'default_storage_interface', 'default_vendor_interface',
'enabled_bios_interfaces', 'enabled_boot_interfaces',
'enabled_console_interfaces', 'enabled_deploy_interfaces',
'enabled_inspect_interfaces', 'enabled_management_interfaces',
'enabled_network_interfaces', 'enabled_power_interfaces',
'enabled_raid_interfaces', 'enabled_rescue_interfaces',
'enabled_storage_interfaces', 'enabled_vendor_interfaces']
act = actual.keys()
self.assertEqual(sorted(exp), sorted(act))

View File

@@ -48,6 +48,7 @@ class NodeShellTest(utils.BaseTestCase):
'maintenance_reason',
'fault',
'name',
'bios_interface',
'boot_interface',
'console_interface',
'deploy_interface',

View File

@@ -47,12 +47,13 @@ class NodeManager(base.CreateManager):
resource_class = Node
_creation_attributes = ['chassis_uuid', 'driver', 'driver_info',
'extra', 'uuid', 'properties', 'name',
'boot_interface', 'console_interface',
'deploy_interface', 'inspect_interface',
'management_interface', 'network_interface',
'power_interface', 'raid_interface',
'rescue_interface', 'storage_interface',
'vendor_interface', 'resource_class']
'bios_interface', 'boot_interface',
'console_interface', 'deploy_interface',
'inspect_interface', 'management_interface',
'network_interface', 'power_interface',
'raid_interface', 'rescue_interface',
'storage_interface', 'vendor_interface',
'resource_class']
_resource_name = 'nodes'
def list(self, associated=None, maintenance=None, marker=None, limit=None,
@@ -611,6 +612,23 @@ class NodeManager(base.CreateManager):
path = "%s/traits" % node_ident
return self.delete(path)
def get_bios_setting(self, node_ident, name):
"""Get a BIOS setting from a node.
:param node_ident: node UUID or name.
:param name: BIOS setting name to get from the node.
"""
path = "%s/bios/%s" % (node_ident, name)
return self._get_as_dict(path).get(name)
def list_bios_settings(self, node_ident):
"""List all BIOS settings from a node.
:param node_ident: node UUID or name.
"""
path = "%s/bios" % node_ident
return self._list_primitives(self._path(path), 'bios')
def wait_for_provision_state(self, node_ident, expected_state,
timeout=0,
poll_interval=_DEFAULT_POLL_INTERVAL,

View File

@@ -34,11 +34,14 @@ class Resource(object):
'address': 'Address',
'async': 'Async',
'attach': 'Response is attachment',
'bios_name': 'BIOS setting name',
'bios_value': 'BIOS setting value',
'boot_index': 'Boot Index',
'chassis_uuid': 'Chassis UUID',
'clean_step': 'Clean Step',
'console_enabled': 'Console Enabled',
'created_at': 'Created At',
'default_bios_interface': 'Default BIOS Interface',
'default_boot_interface': 'Default Boot Interface',
'default_console_interface': 'Default Console Interface',
'default_deploy_interface': 'Default Deploy Interface',
@@ -54,6 +57,7 @@ class Resource(object):
'driver': 'Driver',
'driver_info': 'Driver Info',
'driver_internal_info': 'Driver Internal Info',
'enabled_bios_interfaces': 'Enabled BIOS Interfaces',
'enabled_boot_interfaces': 'Enabled Boot Interfaces',
'enabled_console_interfaces': 'Enabled Console Interfaces',
'enabled_deploy_interfaces': 'Enabled Deploy Interfaces',
@@ -99,6 +103,7 @@ class Resource(object):
'local_link_connection': 'Local Link Connection',
'pxe_enabled': 'PXE boot enabled',
'portgroup_uuid': 'Portgroup UUID',
'bios_interface': 'BIOS Interface',
'boot_interface': 'Boot Interface',
'console_interface': 'Console Interface',
'deploy_interface': 'Deploy Interface',
@@ -222,6 +227,7 @@ NODE_DETAILED_RESOURCE = Resource(
'inspection_started_at',
'uuid',
'name',
'bios_interface',
'boot_interface',
'console_interface',
'deploy_interface',
@@ -332,11 +338,16 @@ TRAIT_RESOURCE = Resource(
['traits'],
)
BIOS_RESOURCE = Resource(
['bios_name', 'bios_value'],
)
# Drivers
DRIVER_DETAILED_RESOURCE = Resource(
['name',
'type',
'hosts',
'default_bios_interface',
'default_boot_interface',
'default_console_interface',
'default_deploy_interface',
@@ -348,6 +359,7 @@ DRIVER_DETAILED_RESOURCE = Resource(
'default_rescue_interface',
'default_storage_interface',
'default_vendor_interface',
'enabled_bios_interfaces',
'enabled_boot_interfaces',
'enabled_console_interfaces',
'enabled_deploy_interfaces',

View File

@@ -0,0 +1,19 @@
---
features:
- |
Adds two new commands.
* ``openstack baremetal node bios setting list <node_ident>``
* ``openstack baremetal node bios setting show <node_ident> <setting_name>``
The first command returns a list of BIOS settings for a given node,
the second command returns a specified BIOS setting from the given node.
Also adds support of bios_interface for the commands below.
* ``openstack baremetal node create``
* ``openstack baremetal node show``
* ``openstack baremetal node set``
* ``openstack baremetal node unset``
* ``openstack baremetal driver list``
* ``openstack baremetal driver show``

View File

@@ -44,6 +44,8 @@ openstack.baremetal.v1 =
baremetal_node_abort = ironicclient.osc.v1.baremetal_node:AbortBaremetalNode
baremetal_node_add_trait = ironicclient.osc.v1.baremetal_node:AddTraitBaremetalNode
baremetal_node_adopt = ironicclient.osc.v1.baremetal_node:AdoptBaremetalNode
baremetal_node_bios_setting_list = ironicclient.osc.v1.baremetal_node:ListBIOSSettingBaremetalNode
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_clean = ironicclient.osc.v1.baremetal_node:CleanBaremetalNode