From 278a95faff68f638059b3136ddd4eadd0a1b96ee Mon Sep 17 00:00:00 2001 From: dixiaoli Date: Sat, 20 Feb 2016 12:47:26 +0800 Subject: [PATCH] Add OpenstackClient plugin for cluster node show This change implements the "openstack cluster node show" command Based on the existing senlin command: senlin node-show Change-Id: I356b8c2aea1f68c41ffecd2c58131819fbade3a2 Blueprint: senlin-support-python-openstackclient --- senlinclient/osc/v1/node.py | 53 +++++++++++++++++++++ senlinclient/tests/unit/osc/v1/test_node.py | 53 +++++++++++++++++++++ setup.cfg | 1 + 3 files changed, 107 insertions(+) diff --git a/senlinclient/osc/v1/node.py b/senlinclient/osc/v1/node.py index a7072bf7..8c1f73b7 100644 --- a/senlinclient/osc/v1/node.py +++ b/senlinclient/osc/v1/node.py @@ -13,8 +13,12 @@ """Clustering v1 node action implementations""" import logging +import six from cliff import lister +from cliff import show +from openstack import exceptions as sdk_exc +from openstackclient.common import exceptions as exc from openstackclient.common import utils from senlinclient.common.i18n import _ @@ -109,3 +113,52 @@ class ListNode(lister.Lister): (utils.get_item_properties(n, columns, formatters=formatters) for n in nodes) ) + + +class ShowNode(show.ShowOne): + """Show detailed info about the specified node.""" + + log = logging.getLogger(__name__ + ".ShowNode") + + def get_parser(self, prog_name): + parser = super(ShowNode, self).get_parser(prog_name) + parser.add_argument( + '--details', + default=False, + action="store_true", + help=_('Include physical object details') + ) + parser.add_argument( + 'node', + metavar='', + help=_('Name or ID of the node to show the details for') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + senlin_client = self.app.client_manager.clustering + return _show_node(senlin_client, parsed_args.node, parsed_args.details) + + +def _show_node(senlin_client, node_id, show_details=False): + """Show detailed info about the specified node.""" + + args = {'show_details': True} if show_details else None + try: + node = senlin_client.get_node(node_id, args=args) + except sdk_exc.ResourceNotFound: + raise exc.CommandError(_('Node not found: %s') % node_id) + + formatters = { + 'metadata': senlin_utils.json_formatter, + 'data': senlin_utils.json_formatter, + } + if show_details and node: + formatters['details'] = senlin_utils.nested_dict_formatter( + list(node['details'].keys()), ['property', 'value']) + + columns = list(six.iterkeys(node)) + return columns, utils.get_dict_properties(node.to_dict(), columns, + formatters=formatters) diff --git a/senlinclient/tests/unit/osc/v1/test_node.py b/senlinclient/tests/unit/osc/v1/test_node.py index 4174c008..84a0056c 100644 --- a/senlinclient/tests/unit/osc/v1/test_node.py +++ b/senlinclient/tests/unit/osc/v1/test_node.py @@ -15,6 +15,7 @@ import mock from openstack.cluster.v1 import node as sdk_node from openstack import exceptions as sdk_exc +from openstackclient.common import exceptions as exc from senlinclient.osc.v1 import node as osc_node from senlinclient.tests.unit.osc.v1 import fakes @@ -140,3 +141,55 @@ class TestNodeList(TestNode): columns, data = self.cmd.take_action(parsed_args) self.mock_client.nodes.assert_called_with(**kwargs) self.assertEqual(self.columns, columns) + + +class TestNodeShow(TestNode): + get_response = {"node": { + "cluster_id": None, + "created_at": "2015-02-10T12:03:16", + "data": {}, + "details": { + "OS-DCF:diskConfig": "MANUAL"}, + "domain": None, + "id": "d5779bb0-f0a0-49c9-88cc-6f078adb5a0b", + "index": -1, + "init_at": "2015-02-10T12:03:13", + "metadata": {}, + "name": "my_node", + "physical_id": "f41537fa-22ab-4bea-94c0-c874e19d0c80", + "profile_id": "edc63d0a-2ca4-48fa-9854-27926da76a4a", + "profile_name": "mystack", + "project": "6e18cc2bdbeb48a5b3cad2dc499f6804", + "role": None, + "status": "ACTIVE", + "status_reason": "Creation succeeded", + "updated_at": "2015-03-04T04:58:27", + "user": "5e5bf8027826429c96af157f68dc9072" + }} + + def setUp(self): + super(TestNodeShow, self).setUp() + self.cmd = osc_node.ShowNode(self.app, None) + self.mock_client.get_node = mock.Mock( + return_value=sdk_node.Node(None, self.get_response)) + + def test_node_show(self): + arglist = ['my_node'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.get_node.assert_called_with('my_node', args=None) + + def test_node_show_with_details(self): + arglist = ['my_node', '--details'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.get_node.assert_called_with( + 'my_node', args={'show_details': True}) + + def test_node_show_not_found(self): + arglist = ['my_node'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.mock_client.get_node.side_effect = sdk_exc.ResourceNotFound() + error = self.assertRaises(exc.CommandError, self.cmd.take_action, + parsed_args) + self.assertEqual('Node not found: my_node', str(error)) diff --git a/setup.cfg b/setup.cfg index 2cc9289d..f4d7ae4d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,6 +31,7 @@ openstack.cli.extension = openstack.clustering.v1 = cluster_node_list = senlinclient.osc.v1.node:ListNode + cluster_node_show = senlinclient.osc.v1.node:ShowNode cluster_profile_create = senlinclient.osc.v1.profile:CreateProfile cluster_profile_delete = senlinclient.osc.v1.profile:DeleteProfile cluster_profile_list = senlinclient.osc.v1.profile:ListProfile