Add support for parent node
- Updates the API client version to 1.83 - Adds support to get/set/update a parent_node value on a node. - Adds support to ask the API for a list of nodes which related. - Adds support to filter query list by parent_node as well. Change-Id: Iea24e96f0360c6e5ac61cb57ab0c6f5d47c57f2b
This commit is contained in:
parent
0e9a476610
commit
b57429ffdb
@ -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 = 82
|
LAST_KNOWN_API_VERSION = 83
|
||||||
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
|
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -527,18 +527,21 @@ class CreateBaremetalNode(command.ShowOne):
|
|||||||
'--shard',
|
'--shard',
|
||||||
metavar='<shard>',
|
metavar='<shard>',
|
||||||
help=_("Shard for the node."))
|
help=_("Shard for the node."))
|
||||||
|
parser.add_argument(
|
||||||
|
'--parent-node',
|
||||||
|
metavar='<parent_node>',
|
||||||
|
help=_('Parent node for the node being created.'))
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
self.log.debug("take_action(%s)", parsed_args)
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
|
||||||
baremetal_client = self.app.client_manager.baremetal
|
baremetal_client = self.app.client_manager.baremetal
|
||||||
|
|
||||||
field_list = ['automated_clean', 'chassis_uuid', 'driver',
|
field_list = ['automated_clean', 'chassis_uuid', 'driver',
|
||||||
'driver_info', 'properties', 'extra', 'uuid', 'name',
|
'driver_info', 'properties', 'extra', 'uuid', 'name',
|
||||||
'conductor_group', 'owner', 'description', 'lessee',
|
'conductor_group', 'owner', 'description', 'lessee',
|
||||||
'shard', 'resource_class'
|
'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()
|
||||||
@ -788,6 +791,18 @@ class ListBaremetalNode(command.Lister):
|
|||||||
help=_("One or more node fields. Only these fields will be "
|
help=_("One or more node fields. Only these fields will be "
|
||||||
"fetched from the server. Can not be used when '--long' "
|
"fetched from the server. Can not be used when '--long' "
|
||||||
"is specified."))
|
"is specified."))
|
||||||
|
children_group = parser.add_mutually_exclusive_group(required=False)
|
||||||
|
children_group.add_argument(
|
||||||
|
'--include-children',
|
||||||
|
action='store_true',
|
||||||
|
help=_("Include children in the node list."),
|
||||||
|
)
|
||||||
|
children_group.add_argument(
|
||||||
|
'--parent-node',
|
||||||
|
dest='parent_node',
|
||||||
|
metavar="<parent_node>",
|
||||||
|
help=_('List only nodes associated with a parent node.'),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -815,9 +830,11 @@ 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']:
|
'description_contains', 'shards', 'parent_node']:
|
||||||
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:
|
||||||
|
params['include_children'] = True
|
||||||
if parsed_args.long:
|
if parsed_args.long:
|
||||||
params['detail'] = parsed_args.long
|
params['detail'] = parsed_args.long
|
||||||
columns = res_fields.NODE_DETAILED_RESOURCE.fields
|
columns = res_fields.NODE_DETAILED_RESOURCE.fields
|
||||||
@ -1429,6 +1446,11 @@ class SetBaremetalNode(command.Command):
|
|||||||
metavar='<shard>',
|
metavar='<shard>',
|
||||||
help=_('Set the shard for the node'),
|
help=_('Set the shard for the node'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--parent-node",
|
||||||
|
metavar='<parent_node>',
|
||||||
|
help=_('Set the parent node for the node'),
|
||||||
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@ -1459,7 +1481,7 @@ class SetBaremetalNode(command.Command):
|
|||||||
'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',
|
||||||
'description', 'shard']:
|
'description', 'shard', 'parent_node']:
|
||||||
value = getattr(parsed_args, field)
|
value = getattr(parsed_args, field)
|
||||||
if value:
|
if value:
|
||||||
properties.extend(utils.args_array_to_patch(
|
properties.extend(utils.args_array_to_patch(
|
||||||
@ -1780,6 +1802,11 @@ class UnsetBaremetalNode(command.Command):
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help=_('Unset the shard field of the node'),
|
help=_('Unset the shard field of the node'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--parent-node",
|
||||||
|
action="store_true",
|
||||||
|
help=_('Unset the parent node field of the node'),
|
||||||
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@ -1805,7 +1832,7 @@ class UnsetBaremetalNode(command.Command):
|
|||||||
'storage_interface', 'vendor_interface',
|
'storage_interface', 'vendor_interface',
|
||||||
'protected', 'protected_reason', 'retired',
|
'protected', 'protected_reason', 'retired',
|
||||||
'retired_reason', 'owner', 'lessee', 'description',
|
'retired_reason', 'owner', 'lessee', 'description',
|
||||||
'shard', ]:
|
'shard', 'parent_node']:
|
||||||
if getattr(parsed_args, field):
|
if getattr(parsed_args, field):
|
||||||
properties.extend(utils.args_array_to_patch('remove', [field]))
|
properties.extend(utils.args_array_to_patch('remove', [field]))
|
||||||
|
|
||||||
@ -2300,3 +2327,31 @@ class NodeInventorySave(command.Command):
|
|||||||
json.dump(inventory, fp)
|
json.dump(inventory, fp)
|
||||||
else:
|
else:
|
||||||
json.dump(inventory, sys.stdout)
|
json.dump(inventory, sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
class NodeChildrenList(command.ShowOne):
|
||||||
|
"""Get a list of nodes assocated as children."""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".NodeChildrenList")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(NodeChildrenList, 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
|
||||||
|
|
||||||
|
labels = res_fields.CHILDREN_RESOURCE.labels
|
||||||
|
|
||||||
|
data = baremetal_client.node.list_children_of_node(
|
||||||
|
parsed_args.node)
|
||||||
|
return (labels, [[node] for node in data])
|
||||||
|
@ -149,6 +149,8 @@ PORTGROUP = {'uuid': baremetal_portgroup_uuid,
|
|||||||
|
|
||||||
VIFS = {'vifs': [{'id': 'aaa-aa'}]}
|
VIFS = {'vifs': [{'id': 'aaa-aa'}]}
|
||||||
TRAITS = ['CUSTOM_FOO', 'CUSTOM_BAR']
|
TRAITS = ['CUSTOM_FOO', 'CUSTOM_BAR']
|
||||||
|
CHILDREN = ['53da080f-6de7-4a3e-bcb6-b7889b380ad0',
|
||||||
|
'48467e9b-3cd1-45b5-a57e-169e01370169']
|
||||||
BIOS_SETTINGS = [{'name': 'bios_name_1', 'value': 'bios_value_1', 'links': []},
|
BIOS_SETTINGS = [{'name': 'bios_name_1', 'value': 'bios_value_1', 'links': []},
|
||||||
{'name': 'bios_name_2', 'value': 'bios_value_2', 'links': []}]
|
{'name': 'bios_name_2', 'value': 'bios_value_2', 'links': []}]
|
||||||
|
|
||||||
|
@ -539,7 +539,8 @@ class TestBaremetalCreate(TestBaremetal):
|
|||||||
def check_with_options(self, addl_arglist, addl_verifylist, addl_kwargs):
|
def check_with_options(self, addl_arglist, addl_verifylist, addl_kwargs):
|
||||||
arglist = copy.copy(self.arglist) + addl_arglist
|
arglist = copy.copy(self.arglist) + addl_arglist
|
||||||
verifylist = copy.copy(self.verifylist) + addl_verifylist
|
verifylist = copy.copy(self.verifylist) + addl_verifylist
|
||||||
|
print(verifylist)
|
||||||
|
print(arglist)
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
# DisplayCommandBase.take_action() returns two tuples
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
@ -736,6 +737,11 @@ class TestBaremetalCreate(TestBaremetal):
|
|||||||
[('shard', 'myshard')],
|
[('shard', 'myshard')],
|
||||||
{'shard': 'myshard'})
|
{'shard': 'myshard'})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_parent_node(self):
|
||||||
|
self.check_with_options(['--parent-node', 'nodex'],
|
||||||
|
[('parent_node', 'nodex')],
|
||||||
|
{'parent_node': 'nodex'})
|
||||||
|
|
||||||
|
|
||||||
class TestBaremetalDelete(TestBaremetal):
|
class TestBaremetalDelete(TestBaremetal):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -916,6 +922,7 @@ class TestBaremetalList(TestBaremetal):
|
|||||||
'Network Configuration',
|
'Network Configuration',
|
||||||
'Network Interface',
|
'Network Interface',
|
||||||
'Owner',
|
'Owner',
|
||||||
|
'Parent Node',
|
||||||
'Power Interface',
|
'Power Interface',
|
||||||
'Power State',
|
'Power State',
|
||||||
'Properties',
|
'Properties',
|
||||||
@ -1498,6 +1505,52 @@ class TestBaremetalList(TestBaremetal):
|
|||||||
self.assertRaises(oscutils.ParserException, self.check_parser,
|
self.assertRaises(oscutils.ParserException, self.check_parser,
|
||||||
self.cmd, arglist, verifylist)
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
def test_baremetal_list_by_parent_node(self):
|
||||||
|
parent_node = 'node1'
|
||||||
|
arglist = [
|
||||||
|
'--parent-node', parent_node,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('parent_node', parent_node),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
print(parsed_args)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
'marker': None,
|
||||||
|
'limit': None,
|
||||||
|
'parent_node': parent_node,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list.assert_called_with(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_baremetal_list_include_children(self):
|
||||||
|
arglist = [
|
||||||
|
'--include-children',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('include_children', True),
|
||||||
|
]
|
||||||
|
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,
|
||||||
|
'include_children': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list.assert_called_with(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestBaremetalMaintenanceSet(TestBaremetal):
|
class TestBaremetalMaintenanceSet(TestBaremetal):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -4448,3 +4501,27 @@ class TestNodeInventorySave(TestBaremetal):
|
|||||||
'boot': {'current_boot_mode': 'uefi'}}
|
'boot': {'current_boot_mode': 'uefi'}}
|
||||||
inventory = json.loads(buf.getvalue())
|
inventory = json.loads(buf.getvalue())
|
||||||
self.assertEqual(expected_data, inventory['inventory'])
|
self.assertEqual(expected_data, inventory['inventory'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestNodeChildrenList(TestBaremetal):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestNodeChildrenList, self).setUp()
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list_children_of_node.return_value = (
|
||||||
|
baremetal_fakes.CHILDREN)
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = baremetal_node.NodeChildrenList(self.app, None)
|
||||||
|
|
||||||
|
def test_child_node_list(self):
|
||||||
|
arglist = ['node_uuid']
|
||||||
|
verifylist = [('node', 'node_uuid')]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.list_children_of_node \
|
||||||
|
.assert_called_once_with('node_uuid')
|
||||||
|
self.assertEqual(('Child Nodes',), columns)
|
||||||
|
self.assertEqual([[node] for node in baremetal_fakes.CHILDREN], data)
|
||||||
|
@ -39,7 +39,8 @@ NODE1 = {'uuid': '66666666-7777-8888-9999-000000000000',
|
|||||||
'network_data': {},
|
'network_data': {},
|
||||||
'resource_class': 'foo',
|
'resource_class': 'foo',
|
||||||
'extra': {},
|
'extra': {},
|
||||||
'conductor_group': 'in-the-closet-to-the-left'}
|
'conductor_group': 'in-the-closet-to-the-left',
|
||||||
|
'parent_node': None}
|
||||||
NODE2 = {'uuid': '66666666-7777-8888-9999-111111111111',
|
NODE2 = {'uuid': '66666666-7777-8888-9999-111111111111',
|
||||||
'instance_uuid': '66666666-7777-8888-9999-222222222222',
|
'instance_uuid': '66666666-7777-8888-9999-222222222222',
|
||||||
'chassis_uuid': 'aaaaaaaa-1111-bbbb-2222-cccccccccccc',
|
'chassis_uuid': 'aaaaaaaa-1111-bbbb-2222-cccccccccccc',
|
||||||
@ -53,7 +54,8 @@ NODE2 = {'uuid': '66666666-7777-8888-9999-111111111111',
|
|||||||
'owner': '33333333-2222-1111-0000-111111111111',
|
'owner': '33333333-2222-1111-0000-111111111111',
|
||||||
'retired': True,
|
'retired': True,
|
||||||
'lessee': '77777777-8888-5555-2222-999999999999',
|
'lessee': '77777777-8888-5555-2222-999999999999',
|
||||||
'shard': 'myshard'}
|
'shard': 'myshard',
|
||||||
|
'parent_node': NODE1['uuid']}
|
||||||
PORT = {'uuid': '11111111-2222-3333-4444-555555555555',
|
PORT = {'uuid': '11111111-2222-3333-4444-555555555555',
|
||||||
'node_uuid': '66666666-7777-8888-9999-000000000000',
|
'node_uuid': '66666666-7777-8888-9999-000000000000',
|
||||||
'address': 'AA:AA:AA:AA:AA:AA',
|
'address': 'AA:AA:AA:AA:AA:AA',
|
||||||
@ -282,6 +284,27 @@ fake_responses = {
|
|||||||
{"nodes": [NODE2]}
|
{"nodes": [NODE2]}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
'/v1/nodes/?include_children=True':
|
||||||
|
{
|
||||||
|
'GET': (
|
||||||
|
{},
|
||||||
|
{"nodes": [NODE1, NODE2]}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
'/v1/nodes/?parent_node=%s' % NODE1['uuid']:
|
||||||
|
{
|
||||||
|
'GET': (
|
||||||
|
{},
|
||||||
|
{"nodes": [NODE2]}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
'/v1/nodes/%s/children' % NODE1['uuid']:
|
||||||
|
{
|
||||||
|
'GET': (
|
||||||
|
{},
|
||||||
|
{"children": [NODE2['uuid']]}
|
||||||
|
)
|
||||||
|
},
|
||||||
'/v1/nodes/detail?instance_uuid=%s' % NODE2['instance_uuid']:
|
'/v1/nodes/detail?instance_uuid=%s' % NODE2['instance_uuid']:
|
||||||
{
|
{
|
||||||
'GET': (
|
'GET': (
|
||||||
@ -1016,6 +1039,35 @@ class NodeManagerTest(testtools.TestCase):
|
|||||||
self.assertThat(nodes, HasLength(1))
|
self.assertThat(nodes, HasLength(1))
|
||||||
self.assertEqual(NODE2['uuid'], getattr(nodes[0], 'uuid'))
|
self.assertEqual(NODE2['uuid'], getattr(nodes[0], 'uuid'))
|
||||||
|
|
||||||
|
def test_node_list_include_chidlren(self):
|
||||||
|
nodes = self.mgr.list(include_children=True)
|
||||||
|
expect = [
|
||||||
|
('GET', '/v1/nodes/?include_children=True', {}, None),
|
||||||
|
]
|
||||||
|
self.assertEqual(expect, self.api.calls)
|
||||||
|
self.assertThat(nodes, HasLength(2))
|
||||||
|
self.assertEqual(NODE1['uuid'], getattr(nodes[0], 'uuid'))
|
||||||
|
self.assertEqual(NODE2['uuid'], getattr(nodes[1], 'uuid'))
|
||||||
|
|
||||||
|
def test_node_list_nodes_by_parent_node(self):
|
||||||
|
nodes = self.mgr.list(parent_node=NODE1['uuid'])
|
||||||
|
expect = [
|
||||||
|
('GET', '/v1/nodes/?parent_node=%s' % NODE1['uuid'],
|
||||||
|
{}, None),
|
||||||
|
]
|
||||||
|
self.assertEqual(expect, self.api.calls)
|
||||||
|
self.assertThat(nodes, HasLength(1))
|
||||||
|
self.assertEqual(NODE2['uuid'], getattr(nodes[0], 'uuid'))
|
||||||
|
|
||||||
|
def test_node_list_children_of_node(self):
|
||||||
|
children = self.mgr.list_children_of_node(NODE1['uuid'])
|
||||||
|
expect = [
|
||||||
|
('GET', '/v1/nodes/%s/children' % NODE1['uuid'], {}, None),
|
||||||
|
]
|
||||||
|
self.assertEqual(expect, self.api.calls)
|
||||||
|
self.assertEqual(1, len(children))
|
||||||
|
self.assertEqual(NODE2['uuid'], children[0])
|
||||||
|
|
||||||
def test_node_list_detail(self):
|
def test_node_list_detail(self):
|
||||||
nodes = self.mgr.list(detail=True)
|
nodes = self.mgr.list(detail=True)
|
||||||
expect = [
|
expect = [
|
||||||
|
@ -53,7 +53,8 @@ class NodeManager(base.CreateManager):
|
|||||||
'raid_interface', 'rescue_interface',
|
'raid_interface', 'rescue_interface',
|
||||||
'storage_interface', 'vendor_interface',
|
'storage_interface', 'vendor_interface',
|
||||||
'resource_class', 'conductor_group',
|
'resource_class', 'conductor_group',
|
||||||
'automated_clean', 'network_data']
|
'automated_clean', 'network_data',
|
||||||
|
'parent_node']
|
||||||
_resource_name = 'nodes'
|
_resource_name = 'nodes'
|
||||||
|
|
||||||
def list(self, associated=None, maintenance=None, marker=None,
|
def list(self, associated=None, maintenance=None, marker=None,
|
||||||
@ -62,7 +63,8 @@ class NodeManager(base.CreateManager):
|
|||||||
resource_class=None, chassis=None, fault=None,
|
resource_class=None, chassis=None, fault=None,
|
||||||
os_ironic_api_version=None, conductor_group=None,
|
os_ironic_api_version=None, conductor_group=None,
|
||||||
conductor=None, owner=None, retired=None, lessee=None,
|
conductor=None, owner=None, retired=None, lessee=None,
|
||||||
shards=None, sharded=None, global_request_id=None):
|
shards=None, sharded=None, parent_node=None,
|
||||||
|
include_children=None, global_request_id=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
|
||||||
@ -134,7 +136,13 @@ class NodeManager(base.CreateManager):
|
|||||||
:param sharded: Optional. Boolean value, when true get only nodes
|
:param sharded: Optional. Boolean value, when true get only nodes
|
||||||
with a non-null node.shard value, when false get only
|
with a non-null node.shard value, when false get only
|
||||||
nodes with a null node.shard value. None is a noop.
|
nodes with a null node.shard value. None is a noop.
|
||||||
|
with a non-null node.shard value.
|
||||||
|
:param parent_node: Optional. String value used to retreive child
|
||||||
|
nodes with the supplied parent node.
|
||||||
|
:param include_children: Optional. Boolean Value, only True is valid.
|
||||||
|
Tells the ironic API to enumerate all child
|
||||||
|
nodes which are normally hidden from the
|
||||||
|
node list.
|
||||||
:returns: A list of nodes.
|
:returns: A list of nodes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -175,6 +183,11 @@ class NodeManager(base.CreateManager):
|
|||||||
filters.append('sharded=%s' % sharded)
|
filters.append('sharded=%s' % sharded)
|
||||||
if shards is not None:
|
if shards is not None:
|
||||||
filters.append('shard=%s' % ','.join(shards))
|
filters.append('shard=%s' % ','.join(shards))
|
||||||
|
if parent_node is not None:
|
||||||
|
filters.append('parent_node=%s' % parent_node)
|
||||||
|
if include_children:
|
||||||
|
# NOTE(TheJulia): Only valid if True.
|
||||||
|
filters.append('include_children=True')
|
||||||
|
|
||||||
path = ''
|
path = ''
|
||||||
if detail:
|
if detail:
|
||||||
@ -382,6 +395,29 @@ class NodeManager(base.CreateManager):
|
|||||||
self._path(path), response_key="targets", limit=limit,
|
self._path(path), response_key="targets", limit=limit,
|
||||||
obj_class=volume_target.VolumeTarget, **header_values)
|
obj_class=volume_target.VolumeTarget, **header_values)
|
||||||
|
|
||||||
|
def list_children_of_node(
|
||||||
|
self, node_id,
|
||||||
|
os_ironic_api_version=None,
|
||||||
|
global_request_id=None):
|
||||||
|
"""Get a list of child nodes for the supplied node_id.
|
||||||
|
|
||||||
|
:param node_id: The name or UUID of a node.
|
||||||
|
|
||||||
|
:param os_ironic_api_version: String version (e.g. "1.35") 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.
|
||||||
|
|
||||||
|
:returns: A list of UUIDs representing child nodes for the supplied
|
||||||
|
node_id..
|
||||||
|
"""
|
||||||
|
path = "%s/children" % node_id
|
||||||
|
header_values = {"os_ironic_api_version": os_ironic_api_version,
|
||||||
|
"global_request_id": global_request_id}
|
||||||
|
return self._list_primitives(self._path(path), "children",
|
||||||
|
**header_values)
|
||||||
|
|
||||||
def get(self, node_id, fields=None, os_ironic_api_version=None,
|
def get(self, node_id, fields=None, os_ironic_api_version=None,
|
||||||
global_request_id=None):
|
global_request_id=None):
|
||||||
return self._get(resource_id=node_id, fields=fields,
|
return self._get(resource_id=node_id, fields=fields,
|
||||||
|
@ -152,6 +152,8 @@ class Resource(object):
|
|||||||
'id': 'ID',
|
'id': 'ID',
|
||||||
'connector_id': 'Connector ID',
|
'connector_id': 'Connector ID',
|
||||||
'is_smartnic': 'Is Smart NIC port',
|
'is_smartnic': 'Is Smart NIC port',
|
||||||
|
'parent_node': 'Parent Node',
|
||||||
|
'children': 'Child Nodes',
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, field_ids, sort_excluded=None, override_labels=None):
|
def __init__(self, field_ids, sort_excluded=None, override_labels=None):
|
||||||
@ -268,6 +270,7 @@ NODE_DETAILED_RESOURCE = Resource(
|
|||||||
'network_data',
|
'network_data',
|
||||||
'network_interface',
|
'network_interface',
|
||||||
'owner',
|
'owner',
|
||||||
|
'parent_node',
|
||||||
'power_interface',
|
'power_interface',
|
||||||
'power_state',
|
'power_state',
|
||||||
'properties',
|
'properties',
|
||||||
@ -392,6 +395,10 @@ TRAIT_RESOURCE = Resource(
|
|||||||
['traits'],
|
['traits'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CHILDREN_RESOURCE = Resource(
|
||||||
|
['children'],
|
||||||
|
)
|
||||||
|
|
||||||
BIOS_RESOURCE = Resource(
|
BIOS_RESOURCE = Resource(
|
||||||
['name', 'value'],
|
['name', 'value'],
|
||||||
override_labels={'name': 'BIOS setting name',
|
override_labels={'name': 'BIOS setting name',
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Increments the maximum API version to ``1.83`` which allows the Node field
|
||||||
|
``parent_node`` to become visible.
|
||||||
|
- |
|
||||||
|
Adds client support to allow users to get, set, and update the
|
||||||
|
``parent_node`` field on a bare metal node.
|
@ -64,6 +64,7 @@ openstack.baremetal.v1 =
|
|||||||
baremetal_node_boot_device_show = ironicclient.osc.v1.baremetal_node:BootdeviceShowBaremetalNode
|
baremetal_node_boot_device_show = ironicclient.osc.v1.baremetal_node:BootdeviceShowBaremetalNode
|
||||||
baremetal_node_boot_mode_set = ironicclient.osc.v1.baremetal_node:BootmodeSetBaremetalNode
|
baremetal_node_boot_mode_set = ironicclient.osc.v1.baremetal_node:BootmodeSetBaremetalNode
|
||||||
baremetal_node_clean = ironicclient.osc.v1.baremetal_node:CleanBaremetalNode
|
baremetal_node_clean = ironicclient.osc.v1.baremetal_node:CleanBaremetalNode
|
||||||
|
baremetal_node_children_list = ironicclient.osc.v1.baremetal_node:NodeChildrenList
|
||||||
baremetal_node_console_disable = ironicclient.osc.v1.baremetal_node:ConsoleDisableBaremetalNode
|
baremetal_node_console_disable = ironicclient.osc.v1.baremetal_node:ConsoleDisableBaremetalNode
|
||||||
baremetal_node_console_enable = ironicclient.osc.v1.baremetal_node:ConsoleEnableBaremetalNode
|
baremetal_node_console_enable = ironicclient.osc.v1.baremetal_node:ConsoleEnableBaremetalNode
|
||||||
baremetal_node_console_show = ironicclient.osc.v1.baremetal_node:ConsoleShowBaremetalNode
|
baremetal_node_console_show = ironicclient.osc.v1.baremetal_node:ConsoleShowBaremetalNode
|
||||||
|
Loading…
Reference in New Issue
Block a user