From 60c25a50becb437c577d9d9f287f4512bd8a762f Mon Sep 17 00:00:00 2001 From: liusheng Date: Thu, 10 Aug 2017 12:07:56 +0800 Subject: [PATCH] Add commands for aggregate node actions Partially Implements: bp node-aggregate Change-Id: I733f5158997cd0764048471b5cae5c97fe40c4dc --- moganclient/osc/v1/aggregate.py | 78 +++++++++++++++++++ moganclient/tests/unit/fakes.py | 2 + .../tests/unit/osc/v1/test_aggregate.py | 69 ++++++++++++++++ moganclient/v1/aggregate.py | 21 +++++ moganclient/v1/client.py | 1 + setup.cfg | 3 + 6 files changed, 174 insertions(+) diff --git a/moganclient/osc/v1/aggregate.py b/moganclient/osc/v1/aggregate.py index d315de9..0efa26d 100644 --- a/moganclient/osc/v1/aggregate.py +++ b/moganclient/osc/v1/aggregate.py @@ -226,3 +226,81 @@ class UnsetAggregate(command.Command): "path": "/metadata/%s" % key}) if updates: bc_client.aggregate.update(aggregate, updates) + + +class AggregateAddNode(command.Command): + """Add a node for a specified node aggregate""" + + def get_parser(self, prog_name): + parser = super(AggregateAddNode, self).get_parser(prog_name) + parser.add_argument( + "aggregate", + metavar="", + help=_("Aggregate to add nodes (name or UUID)") + ) + parser.add_argument( + "node", + metavar="", + help=_("Name of baremetal node") + ) + return parser + + def take_action(self, parsed_args): + bc_client = self.app.client_manager.baremetal_compute + aggregate = utils.find_resource( + bc_client.aggregate, + parsed_args.aggregate, + ) + bc_client.aggregate_node.add_node(aggregate.uuid, + parsed_args.node) + + +class AggregateListNode(command.Lister): + """List all baremetal nodes names of a specified node aggregate""" + + def get_parser(self, prog_name): + parser = super(AggregateListNode, self).get_parser(prog_name) + parser.add_argument( + "aggregate", + metavar="", + help=_("Aggregate to list its nodes (name or UUID)") + ) + return parser + + def take_action(self, parsed_args): + bc_client = self.app.client_manager.baremetal_compute + aggregate = utils.find_resource( + bc_client.aggregate, + parsed_args.aggregate, + ) + data = bc_client.aggregate_node.list_node(aggregate.uuid) + + return (('Node',), + tuple((d,) for d in data)) + + +class AggregateRemoveNode(command.Command): + """Remove a node for a specified node aggregate""" + + def get_parser(self, prog_name): + parser = super(AggregateRemoveNode, self).get_parser(prog_name) + parser.add_argument( + "aggregate", + metavar="", + help=_("Aggregate to delete its node (name or UUID)") + ) + parser.add_argument( + "node", + metavar="", + help=_("Name of baremetal node") + ) + return parser + + def take_action(self, parsed_args): + bc_client = self.app.client_manager.baremetal_compute + aggregate = utils.find_resource( + bc_client.aggregate, + parsed_args.aggregate, + ) + bc_client.aggregate_node.remove_node(aggregate.uuid, + parsed_args.node) diff --git a/moganclient/tests/unit/fakes.py b/moganclient/tests/unit/fakes.py index 0f8ee7f..4dbdd32 100644 --- a/moganclient/tests/unit/fakes.py +++ b/moganclient/tests/unit/fakes.py @@ -72,6 +72,8 @@ class FakeBaremetalComputeV1Client(object): self.aggregate = aggregate.AggregateManager(self.fake_http_client) self.server_group = server_group.ServerGroupManager( self.fake_http_client) + self.aggregate_node = aggregate.AggregateNodeManager( + self.fake_http_client) class FakeHTTPClient(object): diff --git a/moganclient/tests/unit/osc/v1/test_aggregate.py b/moganclient/tests/unit/osc/v1/test_aggregate.py index 945f4f8..1058e39 100644 --- a/moganclient/tests/unit/osc/v1/test_aggregate.py +++ b/moganclient/tests/unit/osc/v1/test_aggregate.py @@ -222,3 +222,72 @@ class TestAggregateUnset(TestAggregateBase): ] mock_update.assert_called_once_with(expected_url, data=expected_args) + + +@mock.patch.object(utils, 'find_resource') +@mock.patch.object(aggregate_mgr.AggregateNodeManager, '_list') +class TestAggregateListNode(TestAggregateBase): + def setUp(self): + super(TestAggregateListNode, self).setUp() + self.cmd = aggregate.AggregateListNode(self.app, None) + self.fake_nodes = ("node-1", "node-1", "node-1") + + def test_agg_node_list(self, mock_list, mock_find): + mock_find.return_value = self.fake_agg + arglist = [ + self.fake_agg.uuid, + ] + verifylist = [ + ('aggregate', self.fake_agg.uuid), + ] + mock_list.return_value = [self.fake_nodes] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + url = '/aggregates/%s/nodes' % self.fake_agg.uuid + mock_list.assert_called_once_with(url, response_key='nodes') + self.assertEqual(('Node',), columns) + self.assertEqual(((("node-1", "node-1", "node-1"),),), data) + + +@mock.patch.object(utils, 'find_resource') +@mock.patch.object(aggregate_mgr.AggregateNodeManager, '_create') +class TestAggregateAddNode(TestAggregateBase): + def setUp(self): + super(TestAggregateAddNode, self).setUp() + self.cmd = aggregate.AggregateAddNode(self.app, None) + + def test_agg_node_add(self, mock_create, mock_find): + mock_find.return_value = self.fake_agg + arglist = [ + self.fake_agg.uuid, 'node-1', + ] + verifylist = [ + ('aggregate', self.fake_agg.uuid), + ('node', 'node-1'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + url = '/aggregates/%s/nodes' % self.fake_agg.uuid + mock_create.assert_called_once_with(url, data={'node': 'node-1'}) + + +@mock.patch.object(utils, 'find_resource') +@mock.patch.object(aggregate_mgr.AggregateNodeManager, '_delete') +class TestAggregateRemoveNode(TestAggregateBase): + def setUp(self): + super(TestAggregateRemoveNode, self).setUp() + self.cmd = aggregate.AggregateRemoveNode(self.app, None) + + def test_agg_node_remove(self, mock_delete, mock_find): + mock_find.return_value = self.fake_agg + arglist = [ + self.fake_agg.uuid, 'node-1', + ] + verifylist = [ + ('aggregate', self.fake_agg.uuid), + ('node', 'node-1'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + url = '/aggregates/%s/nodes/node-1' % self.fake_agg.uuid + mock_delete.assert_called_once_with(url) diff --git a/moganclient/v1/aggregate.py b/moganclient/v1/aggregate.py index db90d68..f00b591 100644 --- a/moganclient/v1/aggregate.py +++ b/moganclient/v1/aggregate.py @@ -45,3 +45,24 @@ class AggregateManager(base.ManagerWithFind): def update(self, aggregate, updates): url = '/aggregates/%s' % base.getid(aggregate) return self._update(url, data=updates) + + +class AggregateNode(base.Resource): + pass + + +class AggregateNodeManager(base.Manager): + resource_class = AggregateNode + + def add_node(self, aggregate_uuid, node): + url = '/aggregates/%s/nodes' % aggregate_uuid + data = {'node': node} + return self._create(url, data=data) + + def list_node(self, aggregate_uuid): + url = '/aggregates/%s/nodes' % aggregate_uuid + return self._list(url, response_key='nodes') + + def remove_node(self, aggregate_uuid, node): + url = '/aggregates/%s/nodes/%s' % (aggregate_uuid, node) + return self._delete(url) diff --git a/moganclient/v1/client.py b/moganclient/v1/client.py index 3081770..25b13c1 100644 --- a/moganclient/v1/client.py +++ b/moganclient/v1/client.py @@ -39,3 +39,4 @@ class Client(object): self.node = node.NodeManager(self.http_client) self.aggregate = aggregate.AggregateManager(self.http_client) self.server_group = server_group.ServerGroupManager(self.http_client) + self.aggregate_node = aggregate.AggregateNodeManager(self.http_client) diff --git a/setup.cfg b/setup.cfg index 5f9e9c5..5dfafce 100644 --- a/setup.cfg +++ b/setup.cfg @@ -67,6 +67,9 @@ openstack.baremetal_compute.v1 = baremetalcompute_server_group_show = moganclient.osc.v1.server_group:ShowServerGroup baremetalcompute_server_group_list = moganclient.osc.v1.server_group:ListServerGroup baremetalcompute_server_group_delete = moganclient.osc.v1.server_group:DeleteServerGroup + baremetalcompute_aggregate_add_node = moganclient.osc.v1.aggregate:AggregateAddNode + baremetalcompute_aggregate_list_node = moganclient.osc.v1.aggregate:AggregateListNode + baremetalcompute_aggregate_remove_node = moganclient.osc.v1.aggregate:AggregateRemoveNode [build_sphinx] source-dir = doc/source