Add more filters for chassis node-list

Add support for filtering chassis nodes by associated, maintenance,
and provision state in the chassis-node-list command.

Change-Id: I47798468000d9096a0cd53052f0477478b62b473
Closes-Bug: #1416313
This commit is contained in:
Zhenguo Niu 2015-09-11 00:15:12 +08:00
parent 6d5779d07e
commit e5099a0133
4 changed files with 130 additions and 3 deletions

View File

@ -36,6 +36,7 @@ CHASSIS2 = {'id': 43,
NODE = {'id': 123,
'uuid': '66666666-7777-8888-9999-000000000000',
'chassis_id': 42,
'provision_state': 'available',
'driver': 'fake',
'driver_info': {'user': 'foo', 'password': 'bar'},
'properties': {'num_cpu': 4},
@ -118,6 +119,27 @@ fake_responses = {
{"nodes": [NODE]},
),
},
'/v1/chassis/%s/nodes?associated=True' % CHASSIS['uuid']:
{
'GET': (
{},
{"nodes": [NODE]},
)
},
'/v1/chassis/%s/nodes?maintenance=False' % CHASSIS['uuid']:
{
'GET': (
{},
{"nodes": [NODE]},
)
},
'/v1/chassis/%s/nodes?provision_state=available' % CHASSIS['uuid']:
{
'GET': (
{},
{"nodes": [NODE]},
)
},
}
fake_responses_pagination = {
@ -350,6 +372,34 @@ class ChassisManagerTest(testtools.TestCase):
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(nodes))
def test_chassis_node_list_maintenance(self):
nodes = self.mgr.list_nodes(CHASSIS['uuid'], maintenance=False)
expect = [
('GET', '/v1/chassis/%s/nodes?maintenance=False' %
CHASSIS['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(nodes))
def test_chassis_node_list_associated(self):
nodes = self.mgr.list_nodes(CHASSIS['uuid'], associated=True)
expect = [
('GET', '/v1/chassis/%s/nodes?associated=True' %
CHASSIS['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(nodes))
def test_chassis_node_list_provision_state(self):
nodes = self.mgr.list_nodes(CHASSIS['uuid'],
provision_state="available")
expect = [
('GET', '/v1/chassis/%s/nodes?provision_state=available' %
CHASSIS['uuid'], {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(1, len(nodes))
def test_chassis_node_list_detail_and_fields_fail(self):
self.assertRaises(exc.InvalidAttribute, self.mgr.list_nodes,
CHASSIS['uuid'], detail=True,

View File

@ -24,7 +24,8 @@ import ironicclient.v1.chassis_shell as c_shell
class ChassisShellTest(utils.BaseTestCase):
def _get_client_mock_args(self, chassis=None, marker=None, limit=None,
sort_dir=None, sort_key=None, detail=False,
fields=None):
fields=None, associated=None, maintenance=None,
provision_state=None):
args = mock.MagicMock(spec=True)
args.chassis = chassis
args.marker = marker
@ -33,6 +34,9 @@ class ChassisShellTest(utils.BaseTestCase):
args.sort_key = sort_key
args.detail = detail
args.fields = fields
args.associated = associated
args.maintenance = maintenance
args.provision_state = provision_state
return args
@ -259,6 +263,33 @@ class ChassisShellTest(utils.BaseTestCase):
client_mock.chassis.list_nodes.assert_called_once_with(
chassis_mock, fields=['uuid', 'power_state'], detail=False)
def test_do_chassis_node_list_associated(self):
client_mock = mock.MagicMock()
chassis_mock = mock.MagicMock(spec_set=[])
args = self._get_client_mock_args(chassis=chassis_mock,
associated=True)
c_shell.do_chassis_node_list(client_mock, args)
client_mock.chassis.list_nodes.assert_called_once_with(
chassis_mock, associated=True, detail=False)
def test_do_chassis_node_list_maintenance(self):
client_mock = mock.MagicMock()
chassis_mock = mock.MagicMock(spec_set=[])
args = self._get_client_mock_args(chassis=chassis_mock,
maintenance=True)
c_shell.do_chassis_node_list(client_mock, args)
client_mock.chassis.list_nodes.assert_called_once_with(
chassis_mock, maintenance=True, detail=False)
def test_do_chassis_node_list_provision_state(self):
client_mock = mock.MagicMock()
chassis_mock = mock.MagicMock(spec_set=[])
args = self._get_client_mock_args(chassis=chassis_mock,
provision_state='wait call-back')
c_shell.do_chassis_node_list(client_mock, args)
client_mock.chassis.list_nodes.assert_called_once_with(
chassis_mock, provision_state='wait call-back', detail=False)
def test_do_chassis_node_list_invalid_fields(self):
client_mock = mock.MagicMock()
chassis_mock = mock.MagicMock(spec_set=[])

View File

@ -89,7 +89,8 @@ class ChassisManager(base.Manager):
limit=limit)
def list_nodes(self, chassis_id, marker=None, limit=None,
sort_key=None, sort_dir=None, detail=False, fields=None):
sort_key=None, sort_dir=None, detail=False, fields=None,
associated=None, maintenance=None, provision_state=None):
"""List all the nodes for a given chassis.
:param chassis_id: The UUID of the chassis.
@ -117,6 +118,20 @@ class ChassisManager(base.Manager):
of the resource to be returned. Can not be used
when 'detail' is set.
:param associated: Optional. Either a Boolean or a string
representation of a Boolean that indicates whether
to return a list of associated (True or "True") or
unassociated (False or "False") nodes.
:param maintenance: Optional. Either a Boolean or a string
representation of a Boolean that indicates whether
to return nodes in maintenance mode (True or
"True"), or not in maintenance mode (False or
"False").
:param provision_state: Optional. String value to get only nodes in
that provision state.
:returns: A list of nodes.
"""
@ -130,6 +145,13 @@ class ChassisManager(base.Manager):
filters = utils.common_filters(marker, limit, sort_key, sort_dir,
fields)
if associated is not None:
filters.append('associated=%s' % associated)
if maintenance is not None:
filters.append('maintenance=%s' % maintenance)
if provision_state is not None:
filters.append('provision_state=%s' % provision_state)
path = "%s/nodes" % chassis_id
if detail:
path += '/detail'

View File

@ -206,8 +206,30 @@ def do_chassis_update(cc, args):
default=[],
help="One or more node fields. Only these fields will be fetched from "
"the server. Can not be used when '--detail' is specified.")
@cliutils.arg(
'--maintenance',
metavar='<boolean>',
help="List nodes in maintenance mode: 'true' or 'false'.")
@cliutils.arg(
'--associated',
metavar='<boolean>',
help="List nodes by instance association: 'true' or 'false'.")
@cliutils.arg(
'--provision-state',
metavar='<provision-state>',
help="List nodes in specified provision state.")
def do_chassis_node_list(cc, args):
"""List the nodes contained in a chassis."""
params = {}
if args.associated is not None:
params['associated'] = utils.bool_argument_value("--associated",
args.associated)
if args.maintenance is not None:
params['maintenance'] = utils.bool_argument_value("--maintenance",
args.maintenance)
if args.provision_state is not None:
params['provision_state'] = args.provision_state
if args.detail:
fields = res_fields.NODE_DETAILED_RESOURCE.fields
field_labels = res_fields.NODE_DETAILED_RESOURCE.labels
@ -221,7 +243,9 @@ def do_chassis_node_list(cc, args):
fields = res_fields.NODE_RESOURCE.fields
field_labels = res_fields.NODE_RESOURCE.labels
params = utils.common_params_for_list(args, fields, field_labels)
params.update(utils.common_params_for_list(args,
fields,
field_labels))
nodes = cc.chassis.list_nodes(args.chassis, **params)
cliutils.print_list(nodes, fields,