From c09c76951eeed1acad7cc2db8d67508f7916f5bd Mon Sep 17 00:00:00 2001 From: Lin Yang Date: Thu, 24 Aug 2017 12:00:29 -0700 Subject: [PATCH] Add list storage services command Add new command 'rsd storage list' to allow user to list all storage services brief info like below shows. $ openstack rsd storage list +----------+-----------------+-----------------------------+ | Identity | Name | Description | +----------+-----------------+-----------------------------+ | 1 | Storage Service | Storage Service for Testing | +----------+-----------------+-----------------------------+ Change-Id: Id54e630881de4c79f731ca93e6bf7a3c18fe6589 --- rsdclient/osc/v1/storage.py | 26 ++++++++++++ rsdclient/tests/common/fakes.py | 67 ++++++++++++++++++++++++++++++ rsdclient/tests/v1/test_storage.py | 51 +++++++++++++++++++++++ rsdclient/v1/client.py | 2 + rsdclient/v1/storage.py | 41 ++++++++++++++++++ setup.cfg | 2 + 6 files changed, 189 insertions(+) create mode 100644 rsdclient/osc/v1/storage.py create mode 100644 rsdclient/tests/v1/test_storage.py create mode 100644 rsdclient/v1/storage.py diff --git a/rsdclient/osc/v1/storage.py b/rsdclient/osc/v1/storage.py new file mode 100644 index 0000000..4a9bca7 --- /dev/null +++ b/rsdclient/osc/v1/storage.py @@ -0,0 +1,26 @@ +# 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. +# + +from rsdclient.common import command + + +class ListStorage(command.Command): + _description = "List all storage services" + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + rsd_client = self.app.client_manager.rsd + storage_service_list = rsd_client.storage.list() + print(storage_service_list) diff --git a/rsdclient/tests/common/fakes.py b/rsdclient/tests/common/fakes.py index 1dfe128..e91775e 100644 --- a/rsdclient/tests/common/fakes.py +++ b/rsdclient/tests/common/fakes.py @@ -13,6 +13,8 @@ # under the License. # +from rsdclient.common import utils + FAKE_NODE_PYTHON_DICT = { "description": "Node for testing", @@ -75,3 +77,68 @@ class FakeNode(object): self.processor_summary = FakeProcessorSummary() self.memory_summary = FakeMemorySummary() self.uuid = "fd011520-86a2-11e7-b4d4-5d323196a3e4" + + +class FakeRemoteTarget(object): + + def __init__(self): + self.addresses = [{ + 'iSCSI': { + 'TargetIQN': 'base_logical_volume_target', + 'TargetLUN': [{ + 'LUN': 1, + 'LogicalDrive': { + '@odata.id': '/redfish/v1/Services/1/LogicalDrives/2' + } + }], + 'TargetPortalIP': '10.2.0.4', + 'TargetPortalPort': 3260 + } + }] + self.identity = '1' + self.initiator = [{'iSCSI': {'InitiatorIQN': 'ALL'}}] + self.redfish_version = '1.0.0' + self.target_type = 'iSCSITargets' + + +class FakePhysicalDrive(object): + + def __init__(self): + self.capacity_gib = 931 + self.drive_type = 'HDD' + self.identity = '1' + self.interface = 'SATA' + self.manufacturer = 'fake manufacture' + self.model = 'ST1000NM0033-9ZM' + self.redfish_version = '1.0.0' + self.rpm = 7200 + self.serial_number = 'Z1W23Q3V' + + +class FakeLogicalDrive(object): + + def __init__(self): + self.bootable = True + self.capacity_gib = 5589 + self.drive_type = 'LVM' + self.identity = '2' + self.image = 'fake image' + self.mode = 'LVG' + self.protected = False + self.redfish_version = '1.0.0' + self.snapshot = False + + +class FakeStorageSerice(object): + + def __init__(self): + self.description = 'Storage Service for Testing' + self.identity = '1' + self.name = 'Storage Service' + self.redfish_version = '1.0.0' + self.remote_targets = [FakeRemoteTarget()] + self.physical_drives = [FakePhysicalDrive()] + self.logical_drives = [FakeLogicalDrive()] + + +FAKE_STORAGE_PYTHON_DICT = utils.extract_attr(FakeStorageSerice()) diff --git a/rsdclient/tests/v1/test_storage.py b/rsdclient/tests/v1/test_storage.py new file mode 100644 index 0000000..4040500 --- /dev/null +++ b/rsdclient/tests/v1/test_storage.py @@ -0,0 +1,51 @@ +# 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 mock +import testtools + +from rsdclient.tests.common import fakes +from rsdclient.v1 import storage + + +class NodeTest(testtools.TestCase): + + def setUp(self): + super(NodeTest, self).setUp() + self.client = mock.Mock() + self.client._storage_service_path = '/redfish/v1/Services' + self.mgr = storage.StorageManager(self.client) + + def test_list_storage(self): + mock_storage_collection = mock.Mock() + mock_storage_collection.members_identities = \ + ('/redfish/v1/Services/1',) + self.mgr.client.get_storage_service_collection.return_value = \ + mock_storage_collection + self.mgr.client.get_storage_service.return_value = \ + fakes.FakeStorageSerice() + + expected = ( + '+----------+-----------------+-----------------------------+\n' + '| Identity | Name | Description |\n' + '+----------+-----------------+-----------------------------+\n' + '| 1 | Storage Service | Storage Service for Testing |\n' + '+----------+-----------------+-----------------------------+') + + result = self.mgr.list() + self.mgr.client.get_storage_service_collection.assert_called_once() + self.mgr.client.get_storage_service.assert_called_once_with( + '/redfish/v1/Services/1') + self.assertEqual(str(result), expected) diff --git a/rsdclient/v1/client.py b/rsdclient/v1/client.py index 09ec413..915d907 100644 --- a/rsdclient/v1/client.py +++ b/rsdclient/v1/client.py @@ -16,6 +16,7 @@ import rsd_lib from rsdclient.v1 import node +from rsdclient.v1 import storage class Client(object): @@ -24,3 +25,4 @@ class Client(object): self.client = rsd_lib.RSDLib(base_url, username, password, verify=verify) self.node = node.NodeManager(self.client) + self.storage = storage.StorageManager(self.client) diff --git a/rsdclient/v1/storage.py b/rsdclient/v1/storage.py new file mode 100644 index 0000000..1076a15 --- /dev/null +++ b/rsdclient/v1/storage.py @@ -0,0 +1,41 @@ +# 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 os + +from rsdclient.common import base +from rsdclient.common import utils + + +class StorageManager(base.Manager): + _resource_name = 'storages' + + def __init__(self, *args, **kwargs): + super(StorageManager, self).__init__(*args, **kwargs) + self.storage_service_path = self.client._storage_service_path + + def _get_storage_service_uri(self, storage_service_id): + return os.path.join(self.storage_service_path, storage_service_id) + + def list(self): + storage_service_collection = \ + self.client.get_storage_service_collection() + storages = [utils.extract_attr(self.client. + get_storage_service(storage_uri)) + for storage_uri in storage_service_collection. + members_identities] + storage_info_table = utils.print_dict( + storages, ["Identity", "Name", "Description"]) + return storage_info_table diff --git a/setup.cfg b/setup.cfg index 3fc73d5..acd24a0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,6 +33,8 @@ openstack.rsd.v1 = rsd_node_show = rsdclient.osc.v1.node:ShowNode rsd_node_list = rsdclient.osc.v1.node:ListNode + rsd_storage_list = rsdclient.osc.v1.storage:ListStorage + [build_sphinx] all-files = 1 warning-is-error = 1