Add show composed node detail command
Add new command 'rsd node show' to allow user to get composed node details by specifying node ID. Change-Id: I26e4adbbf18519742cc215371e8f86fbb4b7d93e
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2017 99cloud, Inc.
|
# Copyright 2017 Intel, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
|||||||
43
rsdclient/common/utils.py
Normal file
43
rsdclient/common/utils.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Copyright 2017 Intel, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
def extract_attr(redfish_obj):
|
||||||
|
'''Extract all public attributes of python redfish object
|
||||||
|
|
||||||
|
:param redfish_obj: python redfish object returned by rsd_lib
|
||||||
|
:returns: python dict of that object
|
||||||
|
'''
|
||||||
|
|
||||||
|
if isinstance(redfish_obj, (int, six.string_types)):
|
||||||
|
return redfish_obj
|
||||||
|
if isinstance(redfish_obj, list):
|
||||||
|
return [extract_attr(i) for i in redfish_obj]
|
||||||
|
if isinstance(redfish_obj, dict):
|
||||||
|
return {i: extract_attr(redfish_obj[i]) for i in redfish_obj}
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
for key, value in vars(redfish_obj).items():
|
||||||
|
# Skip all private attributes
|
||||||
|
if key.startswith('_'):
|
||||||
|
continue
|
||||||
|
result[key] = extract_attr(value)
|
||||||
|
except TypeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return result
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
|
|
||||||
|
|
||||||
@@ -59,3 +61,22 @@ class DeleteNode(command.Command):
|
|||||||
for node in parsed_args.node:
|
for node in parsed_args.node:
|
||||||
rsd_client.node.delete(node)
|
rsd_client.node.delete(node)
|
||||||
print("Node {0} has been deleted.".format(node))
|
print("Node {0} has been deleted.".format(node))
|
||||||
|
|
||||||
|
|
||||||
|
class ShowNode(command.Command):
|
||||||
|
_description = "Display node details"
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShowNode, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'node',
|
||||||
|
metavar='<node>',
|
||||||
|
help='ID of the node.')
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
rsd_client = self.app.client_manager.rsd
|
||||||
|
node_detail = rsd_client.node.show(parsed_args.node)
|
||||||
|
print("{0}".format(json.dumps(node_detail, indent=2)))
|
||||||
|
|||||||
0
rsdclient/tests/common/__init__.py
Normal file
0
rsdclient/tests/common/__init__.py
Normal file
77
rsdclient/tests/common/fakes.py
Normal file
77
rsdclient/tests/common/fakes.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Copyright 2017 Intel, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
FAKE_NODE_PYTHON_DICT = {
|
||||||
|
"description": "Node for testing",
|
||||||
|
"processor_summary": {
|
||||||
|
"count": 1,
|
||||||
|
"model": "fake processor model",
|
||||||
|
"health": "OK"
|
||||||
|
},
|
||||||
|
"composed_node_state": "allocated",
|
||||||
|
"boot": {
|
||||||
|
"mode": "fake boot mode",
|
||||||
|
"enabled": "once",
|
||||||
|
"target": "pxe",
|
||||||
|
"allowed_values": ["pxe", "hdd"]
|
||||||
|
},
|
||||||
|
"uuid": "fd011520-86a2-11e7-b4d4-5d323196a3e4",
|
||||||
|
"power_state": "on",
|
||||||
|
"memory_summary": {
|
||||||
|
"size_gib": 8,
|
||||||
|
"health": "OK"
|
||||||
|
},
|
||||||
|
"identity": "1",
|
||||||
|
"name": "Test"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FakeProcessorSummary(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.count = 1
|
||||||
|
self.model = "fake processor model"
|
||||||
|
self.health = "OK"
|
||||||
|
|
||||||
|
|
||||||
|
class FakeBoot(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.mode = "fake boot mode"
|
||||||
|
self.enabled = "once"
|
||||||
|
self.target = "pxe"
|
||||||
|
self.allowed_values = ["pxe", "hdd"]
|
||||||
|
|
||||||
|
|
||||||
|
class FakeMemorySummary(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.size_gib = 8
|
||||||
|
self.health = "OK"
|
||||||
|
|
||||||
|
|
||||||
|
class FakeNode(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.name = "Test"
|
||||||
|
self.description = "Node for testing"
|
||||||
|
self.identity = "1"
|
||||||
|
self.power_state = "on"
|
||||||
|
self.composed_node_state = "allocated"
|
||||||
|
self.boot = FakeBoot()
|
||||||
|
self.processor_summary = FakeProcessorSummary()
|
||||||
|
self.memory_summary = FakeMemorySummary()
|
||||||
|
self.uuid = "fd011520-86a2-11e7-b4d4-5d323196a3e4"
|
||||||
28
rsdclient/tests/common/test_utils.py
Normal file
28
rsdclient/tests/common/test_utils.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Copyright 2017 Intel, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
from rsdclient.common import utils
|
||||||
|
from rsdclient.tests.common import fakes
|
||||||
|
|
||||||
|
|
||||||
|
class UtilsTest(testtools.TestCase):
|
||||||
|
|
||||||
|
def test_compose_node(self):
|
||||||
|
fake_node = fakes.FakeNode()
|
||||||
|
result = utils.extract_attr(fake_node)
|
||||||
|
expected = fakes.FAKE_NODE_PYTHON_DICT
|
||||||
|
self.assertEqual(result, expected)
|
||||||
@@ -16,13 +16,14 @@
|
|||||||
import mock
|
import mock
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from rsdclient.tests.common import fakes
|
||||||
from rsdclient.v1 import node
|
from rsdclient.v1 import node
|
||||||
|
|
||||||
|
|
||||||
class ClusterManagerTest(testtools.TestCase):
|
class NodeTest(testtools.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ClusterManagerTest, self).setUp()
|
super(NodeTest, self).setUp()
|
||||||
self.client = mock.Mock()
|
self.client = mock.Mock()
|
||||||
self.client._nodes_path = '/redfish/v1/Nodes'
|
self.client._nodes_path = '/redfish/v1/Nodes'
|
||||||
self.mgr = node.NodeManager(self.client)
|
self.mgr = node.NodeManager(self.client)
|
||||||
@@ -44,3 +45,9 @@ class ClusterManagerTest(testtools.TestCase):
|
|||||||
self.mgr.delete(node_id)
|
self.mgr.delete(node_id)
|
||||||
self.mgr.client.get_node.assert_called_once_with('/redfish/v1/Nodes/1')
|
self.mgr.client.get_node.assert_called_once_with('/redfish/v1/Nodes/1')
|
||||||
mock_node.delete_node.assert_called_once()
|
mock_node.delete_node.assert_called_once()
|
||||||
|
|
||||||
|
def test_show_node(self):
|
||||||
|
self.client.get_node.return_value = fakes.FakeNode()
|
||||||
|
result = self.mgr.show('1')
|
||||||
|
expected = fakes.FAKE_NODE_PYTHON_DICT
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from rsdclient.common import base
|
from rsdclient.common import base
|
||||||
|
from rsdclient.common import utils
|
||||||
|
|
||||||
|
|
||||||
class NodeManager(base.Manager):
|
class NodeManager(base.Manager):
|
||||||
@@ -35,3 +36,7 @@ class NodeManager(base.Manager):
|
|||||||
|
|
||||||
def delete(self, node_id):
|
def delete(self, node_id):
|
||||||
self.client.get_node(self._get_node_uri(node_id)).delete_node()
|
self.client.get_node(self._get_node_uri(node_id)).delete_node()
|
||||||
|
|
||||||
|
def show(self, node_id):
|
||||||
|
node = self.client.get_node(self._get_node_uri(node_id))
|
||||||
|
return utils.extract_attr(node)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ openstack.cli.extension =
|
|||||||
openstack.rsd.v1 =
|
openstack.rsd.v1 =
|
||||||
rsd_node_compose = rsdclient.osc.v1.node:ComposeNode
|
rsd_node_compose = rsdclient.osc.v1.node:ComposeNode
|
||||||
rsd_node_delete = rsdclient.osc.v1.node:DeleteNode
|
rsd_node_delete = rsdclient.osc.v1.node:DeleteNode
|
||||||
|
rsd_node_show = rsdclient.osc.v1.node:ShowNode
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
all-files = 1
|
all-files = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user