A new instance_name field to the node object

Add CLI support for ``node.instance_name``

Depends-On: https://review.opendev.org/c/openstack/ironic/+/952790
Change-Id: I8a5d88c9ea9433c986968b9c9af86a4a4bcfe566
Signed-off-by: Afonne-CID <afonnepaulc@gmail.com>
This commit is contained in:
Afonne-CID
2025-07-15 17:40:06 +01:00
parent 0056d8aa14
commit e2ffecc8ad
6 changed files with 105 additions and 9 deletions

View File

@@ -37,7 +37,7 @@ from ironicclient import exc
# http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa # http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa
# for full details. # for full details.
DEFAULT_VER = '1.9' DEFAULT_VER = '1.9'
LAST_KNOWN_API_VERSION = 96 LAST_KNOWN_API_VERSION = 104
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION) LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@@ -477,6 +477,10 @@ class CreateBaremetalNode(command.ShowOne):
'--name', '--name',
metavar='<name>', metavar='<name>',
help=_("Unique name for the node.")) help=_("Unique name for the node."))
parser.add_argument(
'--instance-name',
metavar='<instance_name>',
help=_('Name of the instance deployed on this node.'))
parser.add_argument( parser.add_argument(
'--bios-interface', '--bios-interface',
metavar='<bios_interface>', metavar='<bios_interface>',
@@ -611,8 +615,9 @@ class CreateBaremetalNode(command.ShowOne):
field_list = ['automated_clean', 'chassis_uuid', 'disable_power_off', field_list = ['automated_clean', 'chassis_uuid', 'disable_power_off',
'driver', 'driver_info', 'properties', 'extra', 'uuid', 'driver', 'driver_info', 'properties', 'extra', 'uuid',
'name', 'conductor_group', 'owner', 'description', 'name', 'instance_name', 'conductor_group', 'owner',
'lessee', 'shard', 'resource_class', 'parent_node', 'description', 'lessee', 'shard', 'resource_class',
'parent_node',
] + ['%s_interface' % iface ] + ['%s_interface' % iface
for iface in SUPPORTED_INTERFACES] for iface in SUPPORTED_INTERFACES]
fields = dict((k, v) for (k, v) in vars(parsed_args).items() fields = dict((k, v) for (k, v) in vars(parsed_args).items()
@@ -827,6 +832,10 @@ class ListBaremetalNode(command.Lister):
metavar='<description_contains>', metavar='<description_contains>',
help=_("Limit list to nodes with description contains " help=_("Limit list to nodes with description contains "
"<description_contains>")) "<description_contains>"))
parser.add_argument(
'--instance-name',
metavar='<instance_name>',
help=_("Filter the list of returned nodes by an instance name."))
sharded_group = parser.add_mutually_exclusive_group(required=False) sharded_group = parser.add_mutually_exclusive_group(required=False)
sharded_group.add_argument( sharded_group.add_argument(
'--sharded', '--sharded',
@@ -901,7 +910,8 @@ class ListBaremetalNode(command.Lister):
params[field] = getattr(parsed_args, field) params[field] = getattr(parsed_args, field)
for field in ['provision_state', 'driver', 'resource_class', for field in ['provision_state', 'driver', 'resource_class',
'chassis', 'conductor', 'owner', 'lessee', 'chassis', 'conductor', 'owner', 'lessee',
'description_contains', 'shards', 'parent_node']: 'description_contains', 'shards', 'parent_node',
'instance_name']:
if getattr(parsed_args, field): if getattr(parsed_args, field):
params[field] = getattr(parsed_args, field) params[field] = getattr(parsed_args, field)
if parsed_args.include_children: if parsed_args.include_children:
@@ -1329,6 +1339,11 @@ class SetBaremetalNode(command.Command):
metavar="<uuid>", metavar="<uuid>",
help=_("Set instance UUID of node to <uuid>"), help=_("Set instance UUID of node to <uuid>"),
) )
parser.add_argument(
"--instance-name",
metavar="<instance_name>",
help=_('Set the name of the instance deployed on this node.'),
)
parser.add_argument( parser.add_argument(
"--name", "--name",
metavar="<name>", metavar="<name>",
@@ -1574,7 +1589,7 @@ class SetBaremetalNode(command.Command):
baremetal_client.node.set_target_raid_config(node, raid_config) baremetal_client.node.set_target_raid_config(node, raid_config)
properties = [] properties = []
for field in ['instance_uuid', 'name', for field in ['instance_uuid', 'instance_name', 'name',
'chassis_uuid', 'driver', 'resource_class', 'chassis_uuid', 'driver', 'resource_class',
'conductor_group', 'protected', 'protected_reason', 'conductor_group', 'protected', 'protected_reason',
'retired', 'retired_reason', 'owner', 'lessee', 'retired', 'retired_reason', 'owner', 'lessee',
@@ -1723,6 +1738,12 @@ class UnsetBaremetalNode(command.Command):
default=False, default=False,
help=_('Unset instance UUID on this baremetal node') help=_('Unset instance UUID on this baremetal node')
) )
parser.add_argument(
'--instance-name',
action='store_true',
default=False,
help=_('Unset instance name on this baremetal node')
)
parser.add_argument( parser.add_argument(
"--name", "--name",
action='store_true', action='store_true',
@@ -1932,7 +1953,7 @@ class UnsetBaremetalNode(command.Command):
baremetal_client.node.set_target_raid_config(node, {}) baremetal_client.node.set_target_raid_config(node, {})
properties = [] properties = []
for field in ['instance_uuid', 'name', 'chassis_uuid', for field in ['instance_uuid', 'instance_name', 'name', 'chassis_uuid',
'resource_class', 'conductor_group', 'automated_clean', 'resource_class', 'conductor_group', 'automated_clean',
'bios_interface', 'boot_interface', 'console_interface', 'bios_interface', 'boot_interface', 'console_interface',
'deploy_interface', 'firmware_interface', 'deploy_interface', 'firmware_interface',

View File

@@ -205,7 +205,7 @@ class VersionNegotiationMixinTest(utils.BaseTestCase):
def test_negotiate_version_server_user_latest( def test_negotiate_version_server_user_latest(
self, mock_pvh, mock_msr, mock_save_data): self, mock_pvh, mock_msr, mock_save_data):
# have to retry with simple get # have to retry with simple get
mock_pvh.side_effect = iter([(None, None), ('1.1', '1.99')]) mock_pvh.side_effect = iter([(None, None), ('1.1', '1.104')])
mock_conn = mock.MagicMock() mock_conn = mock.MagicMock()
self.test_object.api_version_select_state = 'user' self.test_object.api_version_select_state = 'user'
self.test_object.os_ironic_api_version = 'latest' self.test_object.os_ironic_api_version = 'latest'

View File

@@ -990,6 +990,11 @@ class TestBaremetalCreate(TestBaremetal):
[('parent_node', 'nodex')], [('parent_node', 'nodex')],
{'parent_node': 'nodex'}) {'parent_node': 'nodex'})
def test_baremetal_create_with_instance_name(self):
self.check_with_options(['--instance-name', 'for-instance'],
[('instance_name', 'for-instance')],
{'instance_name': 'for-instance'})
def test_baremetal_create_with_disable_power_off(self): def test_baremetal_create_with_disable_power_off(self):
self.check_with_options(['--disable-power-off'], self.check_with_options(['--disable-power-off'],
[('disable_power_off', True)], [('disable_power_off', True)],
@@ -1167,6 +1172,7 @@ class TestBaremetalList(TestBaremetal):
'Inspection Finished At', 'Inspection Finished At',
'Inspection Started At', 'Inspection Started At',
'Instance Info', 'Instance Info',
'Instance Name',
'Instance UUID', 'Instance UUID',
'Last Error', 'Last Error',
'Lessee', 'Lessee',
@@ -1635,6 +1641,29 @@ class TestBaremetalList(TestBaremetal):
**kwargs **kwargs
) )
def test_baremetal_list_by_instance_name(self):
instance_name = 'for-instance'
arglist = [
'--instance-name', instance_name,
]
verifylist = [
('instance_name', instance_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
self.cmd.take_action(parsed_args)
kwargs = {
'marker': None,
'limit': None,
'instance_name': instance_name,
}
self.baremetal_mock.node.list.assert_called_with(
**kwargs
)
def test_baremetal_list_fields(self): def test_baremetal_list_fields(self):
arglist = [ arglist = [
'--fields', 'uuid', 'name', '--fields', 'uuid', 'name',
@@ -2991,6 +3020,26 @@ class TestBaremetalSet(TestBaremetal):
reset_interfaces=None, reset_interfaces=None,
) )
def test_baremetal_set_instance_name(self):
arglist = [
'node_uuid',
'--instance-name', 'for-instance',
]
verifylist = [
('nodes', ['node_uuid']),
('instance_name', 'for-instance')
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.baremetal_mock.node.update.assert_called_once_with(
'node_uuid',
[{'path': '/instance_name', 'value': 'for-instance', 'op': 'add'}],
reset_interfaces=None,
)
def test_baremetal_set_chassis(self): def test_baremetal_set_chassis(self):
chassis = '4f4135ea-7e58-4e3d-bcc4-b87ca16e980b' chassis = '4f4135ea-7e58-4e3d-bcc4-b87ca16e980b'
arglist = [ arglist = [
@@ -3920,6 +3969,25 @@ class TestBaremetalUnset(TestBaremetal):
[{'path': '/name', 'op': 'remove'}] [{'path': '/name', 'op': 'remove'}]
) )
def test_baremetal_unset_instance_name(self):
arglist = [
'node_uuid',
'--instance-name',
]
verifylist = [
('nodes', ['node_uuid']),
('instance_name', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.baremetal_mock.node.update.assert_called_once_with(
'node_uuid',
[{'path': '/instance_name', 'op': 'remove'}]
)
def test_baremetal_unset_resource_class(self): def test_baremetal_unset_resource_class(self):
arglist = [ arglist = [
'node_uuid', 'node_uuid',

View File

@@ -55,7 +55,8 @@ class NodeManager(base.CreateManager):
'vendor_interface', 'firmware_interface', 'vendor_interface', 'firmware_interface',
'resource_class', 'conductor_group', 'resource_class', 'conductor_group',
'automated_clean', 'network_data', 'parent_node', 'automated_clean', 'network_data', 'parent_node',
'owner', 'lessee', 'shard', 'description'] 'owner', 'lessee', 'shard', 'description',
'instance_name']
_resource_name = 'nodes' _resource_name = 'nodes'
def list(self, associated=None, maintenance=None, marker=None, def list(self, associated=None, maintenance=None, marker=None,
@@ -66,7 +67,7 @@ class NodeManager(base.CreateManager):
conductor=None, owner=None, retired=None, lessee=None, conductor=None, owner=None, retired=None, lessee=None,
shards=None, sharded=None, parent_node=None, shards=None, sharded=None, parent_node=None,
include_children=None, description_contains=None, include_children=None, description_contains=None,
global_request_id=None): global_request_id=None, instance_name=None):
"""Retrieve a list of nodes. """Retrieve a list of nodes.
:param associated: Optional. Either a Boolean or a string :param associated: Optional. Either a Boolean or a string
@@ -147,6 +148,8 @@ class NodeManager(base.CreateManager):
node list. node list.
:param description_contains: Optional. String value to get nodes :param description_contains: Optional. String value to get nodes
with description contains specified value. with description contains specified value.
:param instance_name: Optional. String value to get only nodes with
the given instance_name set.
:returns: A list of nodes. :returns: A list of nodes.
""" """
@@ -194,6 +197,8 @@ class NodeManager(base.CreateManager):
filters.append('include_children=True') filters.append('include_children=True')
if description_contains is not None: if description_contains is not None:
filters.append('description_contains=%s' % description_contains) filters.append('description_contains=%s' % description_contains)
if instance_name is not None:
filters.append('instance_name=%s' % instance_name)
path = '' path = ''
if detail: if detail:

View File

@@ -90,6 +90,7 @@ class Resource(object):
'inspection_finished_at': 'Inspection Finished At', 'inspection_finished_at': 'Inspection Finished At',
'inspection_started_at': 'Inspection Started At', 'inspection_started_at': 'Inspection Started At',
'instance_info': 'Instance Info', 'instance_info': 'Instance Info',
'instance_name': 'Instance Name',
'instance_uuid': 'Instance UUID', 'instance_uuid': 'Instance UUID',
'internal_info': 'Internal Info', 'internal_info': 'Internal Info',
'last_error': 'Last Error', 'last_error': 'Last Error',
@@ -273,6 +274,7 @@ NODE_DETAILED_RESOURCE = Resource(
'inspection_finished_at', 'inspection_finished_at',
'inspection_started_at', 'inspection_started_at',
'instance_info', 'instance_info',
'instance_name',
'instance_uuid', 'instance_uuid',
'last_error', 'last_error',
'lessee', 'lessee',