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
This commit is contained in:
Lin Yang 2017-08-24 12:00:29 -07:00
parent c07b1fe383
commit c09c76951e
6 changed files with 189 additions and 0 deletions

View File

@ -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)

View File

@ -13,6 +13,8 @@
# under the License. # under the License.
# #
from rsdclient.common import utils
FAKE_NODE_PYTHON_DICT = { FAKE_NODE_PYTHON_DICT = {
"description": "Node for testing", "description": "Node for testing",
@ -75,3 +77,68 @@ class FakeNode(object):
self.processor_summary = FakeProcessorSummary() self.processor_summary = FakeProcessorSummary()
self.memory_summary = FakeMemorySummary() self.memory_summary = FakeMemorySummary()
self.uuid = "fd011520-86a2-11e7-b4d4-5d323196a3e4" 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())

View File

@ -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)

View File

@ -16,6 +16,7 @@
import rsd_lib import rsd_lib
from rsdclient.v1 import node from rsdclient.v1 import node
from rsdclient.v1 import storage
class Client(object): class Client(object):
@ -24,3 +25,4 @@ class Client(object):
self.client = rsd_lib.RSDLib(base_url, username, password, self.client = rsd_lib.RSDLib(base_url, username, password,
verify=verify) verify=verify)
self.node = node.NodeManager(self.client) self.node = node.NodeManager(self.client)
self.storage = storage.StorageManager(self.client)

41
rsdclient/v1/storage.py Normal file
View File

@ -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

View File

@ -33,6 +33,8 @@ openstack.rsd.v1 =
rsd_node_show = rsdclient.osc.v1.node:ShowNode rsd_node_show = rsdclient.osc.v1.node:ShowNode
rsd_node_list = rsdclient.osc.v1.node:ListNode rsd_node_list = rsdclient.osc.v1.node:ListNode
rsd_storage_list = rsdclient.osc.v1.storage:ListStorage
[build_sphinx] [build_sphinx]
all-files = 1 all-files = 1
warning-is-error = 1 warning-is-error = 1