Add block storage manageable list commands
This patch adds the ``block storage volume manageable list`` and ``block storage snapshot manageable list`` commands that allow operators to list the volumes and snapshots on a particular host or cluster for management under OpenStack. Change-Id: I328dada5a0dc4e9e44c0d51db5cf3f224e27f88f
This commit is contained in:
parent
2be3596779
commit
73b4ce88eb
11
doc/source/cli/command-objects/block-storage-manage.rst
Normal file
11
doc/source/cli/command-objects/block-storage-manage.rst
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
====================
|
||||||
|
Block Storage Manage
|
||||||
|
====================
|
||||||
|
|
||||||
|
Block Storage v3
|
||||||
|
|
||||||
|
.. autoprogram-cliff:: openstack.volume.v3
|
||||||
|
:command: block storage volume manageable list
|
||||||
|
|
||||||
|
.. autoprogram-cliff:: openstack.volume.v3
|
||||||
|
:command: block storage snapshot manageable list
|
@ -71,7 +71,7 @@ image-metadata-show,volume show,Shows volume image metadata.
|
|||||||
list,volume list,Lists all volumes.
|
list,volume list,Lists all volumes.
|
||||||
list-filters,block storage resource filter list,List enabled filters. (Supported by API versions 3.33 - 3.latest)
|
list-filters,block storage resource filter list,List enabled filters. (Supported by API versions 3.33 - 3.latest)
|
||||||
manage,volume create --remote-source k=v,Manage an existing volume.
|
manage,volume create --remote-source k=v,Manage an existing volume.
|
||||||
manageable-list,,Lists all manageable volumes. (Supported by API versions 3.8 - 3.latest)
|
manageable-list,block storage volume manageable list,Lists all manageable volumes. (Supported by API versions 3.8 - 3.latest)
|
||||||
message-delete,volume message delete,Removes one or more messages. (Supported by API versions 3.3 - 3.latest)
|
message-delete,volume message delete,Removes one or more messages. (Supported by API versions 3.3 - 3.latest)
|
||||||
message-list,volume message list,Lists all messages. (Supported by API versions 3.3 - 3.latest)
|
message-list,volume message list,Lists all messages. (Supported by API versions 3.3 - 3.latest)
|
||||||
message-show,volume message show,Shows message details. (Supported by API versions 3.3 - 3.latest)
|
message-show,volume message show,Shows message details. (Supported by API versions 3.3 - 3.latest)
|
||||||
@ -112,7 +112,7 @@ snapshot-create,snapshot create,Creates a snapshot.
|
|||||||
snapshot-delete,snapshot delete,Remove one or more snapshots.
|
snapshot-delete,snapshot delete,Remove one or more snapshots.
|
||||||
snapshot-list,snapshot list,Lists all snapshots.
|
snapshot-list,snapshot list,Lists all snapshots.
|
||||||
snapshot-manage,volume snapshot create --remote-source <key=value>,Manage an existing snapshot.
|
snapshot-manage,volume snapshot create --remote-source <key=value>,Manage an existing snapshot.
|
||||||
snapshot-manageable-list,,Lists all manageable snapshots. (Supported by API versions 3.8 - 3.latest)
|
snapshot-manageable-list,block storage snapshot manageable list,Lists all manageable snapshots. (Supported by API versions 3.8 - 3.latest)
|
||||||
snapshot-metadata,snapshot set --property k=v / snapshot unset --property k,Sets or deletes snapshot metadata.
|
snapshot-metadata,snapshot set --property k=v / snapshot unset --property k,Sets or deletes snapshot metadata.
|
||||||
snapshot-metadata-show,snapshot show,Shows snapshot metadata.
|
snapshot-metadata-show,snapshot show,Shows snapshot metadata.
|
||||||
snapshot-metadata-update-all,snapshot set --property k=v,Updates snapshot metadata.
|
snapshot-metadata-update-all,snapshot set --property k=v,Updates snapshot metadata.
|
||||||
|
|
@ -487,3 +487,41 @@ def create_cleanup_records():
|
|||||||
None, obj, loaded=True) for obj in unavailable_records]
|
None, obj, loaded=True) for obj in unavailable_records]
|
||||||
|
|
||||||
return cleaning, unavailable
|
return cleaning, unavailable
|
||||||
|
|
||||||
|
|
||||||
|
def create_one_manage_record(attrs=None, snapshot=False):
|
||||||
|
manage_dict = {
|
||||||
|
'reference': {'source-name': 'fake-volume'},
|
||||||
|
'size': '1',
|
||||||
|
'safe_to_manage': False,
|
||||||
|
'reason_not_safe': 'already managed',
|
||||||
|
'cinder_id': 'fake-volume',
|
||||||
|
'extra_info': None,
|
||||||
|
}
|
||||||
|
if snapshot:
|
||||||
|
manage_dict['source_reference'] = {'source-name': 'fake-source'}
|
||||||
|
|
||||||
|
# Overwrite default attributes if there are some attributes set
|
||||||
|
attrs = attrs or {}
|
||||||
|
|
||||||
|
manage_dict.update(attrs)
|
||||||
|
manage_record = fakes.FakeResource(None, manage_dict, loaded=True)
|
||||||
|
return manage_record
|
||||||
|
|
||||||
|
|
||||||
|
def create_volume_manage_list_records(count=2):
|
||||||
|
volume_manage_list = []
|
||||||
|
for i in range(count):
|
||||||
|
volume_manage_list.append(
|
||||||
|
create_one_manage_record({'size': str(i + 1)}))
|
||||||
|
|
||||||
|
return volume_manage_list
|
||||||
|
|
||||||
|
|
||||||
|
def create_snapshot_manage_list_records(count=2):
|
||||||
|
snapshot_manage_list = []
|
||||||
|
for i in range(count):
|
||||||
|
snapshot_manage_list.append(
|
||||||
|
create_one_manage_record({'size': str(i + 1)}, snapshot=True))
|
||||||
|
|
||||||
|
return snapshot_manage_list
|
||||||
|
@ -0,0 +1,411 @@
|
|||||||
|
# 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 cinderclient import api_versions
|
||||||
|
from osc_lib import exceptions
|
||||||
|
|
||||||
|
from openstackclient.tests.unit import utils as tests_utils
|
||||||
|
from openstackclient.tests.unit.volume.v2 import fakes as v2_volume_fakes
|
||||||
|
from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
|
||||||
|
from openstackclient.volume.v3 import block_storage_manage
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlockStorageManage(v2_volume_fakes.TestVolume):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.volumes_mock = self.app.client_manager.volume.volumes
|
||||||
|
self.volumes_mock.reset_mock()
|
||||||
|
self.snapshots_mock = self.app.client_manager.volume.volume_snapshots
|
||||||
|
self.snapshots_mock.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlockStorageVolumeManage(TestBlockStorageManage):
|
||||||
|
|
||||||
|
volume_manage_list = volume_fakes.create_volume_manage_list_records()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.volumes_mock.list_manageable.return_value = (
|
||||||
|
self.volume_manage_list)
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = block_storage_manage.BlockStorageManageVolumes(
|
||||||
|
self.app, None)
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_list(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.8')
|
||||||
|
host = 'fake_host'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
expected_columns = [
|
||||||
|
'reference',
|
||||||
|
'size',
|
||||||
|
'safe_to_manage',
|
||||||
|
'reason_not_safe',
|
||||||
|
'cinder_id',
|
||||||
|
'extra_info',
|
||||||
|
]
|
||||||
|
|
||||||
|
# confirming if all expected columns are present in the result.
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
|
||||||
|
datalist = []
|
||||||
|
for volume_record in self.volume_manage_list:
|
||||||
|
manage_details = (
|
||||||
|
volume_record.reference,
|
||||||
|
volume_record.size,
|
||||||
|
volume_record.safe_to_manage,
|
||||||
|
volume_record.reason_not_safe,
|
||||||
|
volume_record.cinder_id,
|
||||||
|
volume_record.extra_info,
|
||||||
|
)
|
||||||
|
datalist.append(manage_details)
|
||||||
|
datalist = tuple(datalist)
|
||||||
|
|
||||||
|
# confirming if all expected values are present in the result.
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
# checking if proper call was made to get volume manageable list
|
||||||
|
self.volumes_mock.list_manageable.assert_called_with(
|
||||||
|
host=parsed_args.host,
|
||||||
|
detailed=parsed_args.detailed,
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
offset=parsed_args.offset,
|
||||||
|
sort=parsed_args.sort,
|
||||||
|
cluster=parsed_args.cluster,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_pre_38(self):
|
||||||
|
host = 'fake_host'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
self.assertIn(
|
||||||
|
'--os-volume-api-version 3.8 or greater is required', str(exc))
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_pre_317(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.16')
|
||||||
|
cluster = 'fake_cluster'
|
||||||
|
arglist = [
|
||||||
|
'--cluster', cluster,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('cluster', cluster),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
self.assertIn(
|
||||||
|
'--os-volume-api-version 3.17 or greater is required', str(exc))
|
||||||
|
self.assertIn('--cluster', str(exc))
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_host_and_cluster(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.17')
|
||||||
|
host = 'fake_host'
|
||||||
|
cluster = 'fake_cluster'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
'--cluster', cluster,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
('cluster', cluster),
|
||||||
|
]
|
||||||
|
exc = self.assertRaises(tests_utils.ParserException,
|
||||||
|
self.check_parser, self.cmd,
|
||||||
|
arglist, verifylist)
|
||||||
|
self.assertIn(
|
||||||
|
'argument --cluster: not allowed with argument <host>', str(exc))
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_list_all_args(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.8')
|
||||||
|
host = 'fake_host'
|
||||||
|
detailed = True
|
||||||
|
marker = 'fake_marker'
|
||||||
|
limit = '5'
|
||||||
|
offset = '3'
|
||||||
|
sort = 'size:asc'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
'--detailed', str(detailed),
|
||||||
|
'--marker', marker,
|
||||||
|
'--limit', limit,
|
||||||
|
'--offset', offset,
|
||||||
|
'--sort', sort,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
('detailed', str(detailed)),
|
||||||
|
('marker', marker),
|
||||||
|
('limit', limit),
|
||||||
|
('offset', offset),
|
||||||
|
('sort', sort),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
expected_columns = [
|
||||||
|
'reference',
|
||||||
|
'size',
|
||||||
|
'safe_to_manage',
|
||||||
|
'reason_not_safe',
|
||||||
|
'cinder_id',
|
||||||
|
'extra_info',
|
||||||
|
]
|
||||||
|
|
||||||
|
# confirming if all expected columns are present in the result.
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
|
||||||
|
datalist = []
|
||||||
|
for volume_record in self.volume_manage_list:
|
||||||
|
manage_details = (
|
||||||
|
volume_record.reference,
|
||||||
|
volume_record.size,
|
||||||
|
volume_record.safe_to_manage,
|
||||||
|
volume_record.reason_not_safe,
|
||||||
|
volume_record.cinder_id,
|
||||||
|
volume_record.extra_info,
|
||||||
|
)
|
||||||
|
datalist.append(manage_details)
|
||||||
|
datalist = tuple(datalist)
|
||||||
|
|
||||||
|
# confirming if all expected values are present in the result.
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
# checking if proper call was made to get volume manageable list
|
||||||
|
self.volumes_mock.list_manageable.assert_called_with(
|
||||||
|
host=host,
|
||||||
|
detailed=detailed,
|
||||||
|
marker=marker,
|
||||||
|
limit=limit,
|
||||||
|
offset=offset,
|
||||||
|
sort=sort,
|
||||||
|
cluster=parsed_args.cluster,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlockStorageSnapshotManage(TestBlockStorageManage):
|
||||||
|
|
||||||
|
snapshot_manage_list = volume_fakes.create_snapshot_manage_list_records()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.snapshots_mock.list_manageable.return_value = (
|
||||||
|
self.snapshot_manage_list)
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = block_storage_manage.BlockStorageManageSnapshots(
|
||||||
|
self.app, None)
|
||||||
|
|
||||||
|
def test_block_storage_snapshot_manage_list(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.8')
|
||||||
|
host = 'fake_host'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
expected_columns = [
|
||||||
|
'reference',
|
||||||
|
'size',
|
||||||
|
'safe_to_manage',
|
||||||
|
'source_reference',
|
||||||
|
'reason_not_safe',
|
||||||
|
'cinder_id',
|
||||||
|
'extra_info',
|
||||||
|
]
|
||||||
|
|
||||||
|
# confirming if all expected columns are present in the result.
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
|
||||||
|
datalist = []
|
||||||
|
for snapshot_record in self.snapshot_manage_list:
|
||||||
|
manage_details = (
|
||||||
|
snapshot_record.reference,
|
||||||
|
snapshot_record.size,
|
||||||
|
snapshot_record.safe_to_manage,
|
||||||
|
snapshot_record.source_reference,
|
||||||
|
snapshot_record.reason_not_safe,
|
||||||
|
snapshot_record.cinder_id,
|
||||||
|
snapshot_record.extra_info,
|
||||||
|
)
|
||||||
|
datalist.append(manage_details)
|
||||||
|
datalist = tuple(datalist)
|
||||||
|
|
||||||
|
# confirming if all expected values are present in the result.
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
# checking if proper call was made to get snapshot manageable list
|
||||||
|
self.snapshots_mock.list_manageable.assert_called_with(
|
||||||
|
host=parsed_args.host,
|
||||||
|
detailed=parsed_args.detailed,
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
offset=parsed_args.offset,
|
||||||
|
sort=parsed_args.sort,
|
||||||
|
cluster=parsed_args.cluster,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_pre_38(self):
|
||||||
|
host = 'fake_host'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
self.assertIn(
|
||||||
|
'--os-volume-api-version 3.8 or greater is required', str(exc))
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_pre_317(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.16')
|
||||||
|
cluster = 'fake_cluster'
|
||||||
|
arglist = [
|
||||||
|
'--cluster', cluster,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('cluster', cluster),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
self.assertIn(
|
||||||
|
'--os-volume-api-version 3.17 or greater is required', str(exc))
|
||||||
|
self.assertIn('--cluster', str(exc))
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_host_and_cluster(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.17')
|
||||||
|
host = 'fake_host'
|
||||||
|
cluster = 'fake_cluster'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
'--cluster', cluster,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
('cluster', cluster),
|
||||||
|
]
|
||||||
|
exc = self.assertRaises(tests_utils.ParserException,
|
||||||
|
self.check_parser, self.cmd,
|
||||||
|
arglist, verifylist)
|
||||||
|
self.assertIn(
|
||||||
|
'argument --cluster: not allowed with argument <host>', str(exc))
|
||||||
|
|
||||||
|
def test_block_storage_volume_manage_list_all_args(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.8')
|
||||||
|
host = 'fake_host'
|
||||||
|
detailed = True
|
||||||
|
marker = 'fake_marker'
|
||||||
|
limit = '5'
|
||||||
|
offset = '3'
|
||||||
|
sort = 'size:asc'
|
||||||
|
arglist = [
|
||||||
|
host,
|
||||||
|
'--detailed', str(detailed),
|
||||||
|
'--marker', marker,
|
||||||
|
'--limit', limit,
|
||||||
|
'--offset', offset,
|
||||||
|
'--sort', sort,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('host', host),
|
||||||
|
('detailed', str(detailed)),
|
||||||
|
('marker', marker),
|
||||||
|
('limit', limit),
|
||||||
|
('offset', offset),
|
||||||
|
('sort', sort),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
expected_columns = [
|
||||||
|
'reference',
|
||||||
|
'size',
|
||||||
|
'safe_to_manage',
|
||||||
|
'source_reference',
|
||||||
|
'reason_not_safe',
|
||||||
|
'cinder_id',
|
||||||
|
'extra_info',
|
||||||
|
]
|
||||||
|
|
||||||
|
# confirming if all expected columns are present in the result.
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
|
||||||
|
datalist = []
|
||||||
|
for snapshot_record in self.snapshot_manage_list:
|
||||||
|
manage_details = (
|
||||||
|
snapshot_record.reference,
|
||||||
|
snapshot_record.size,
|
||||||
|
snapshot_record.safe_to_manage,
|
||||||
|
snapshot_record.source_reference,
|
||||||
|
snapshot_record.reason_not_safe,
|
||||||
|
snapshot_record.cinder_id,
|
||||||
|
snapshot_record.extra_info,
|
||||||
|
)
|
||||||
|
datalist.append(manage_details)
|
||||||
|
datalist = tuple(datalist)
|
||||||
|
|
||||||
|
# confirming if all expected values are present in the result.
|
||||||
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
# checking if proper call was made to get snapshot manageable list
|
||||||
|
self.snapshots_mock.list_manageable.assert_called_with(
|
||||||
|
host=host,
|
||||||
|
detailed=detailed,
|
||||||
|
marker=marker,
|
||||||
|
limit=limit,
|
||||||
|
offset=offset,
|
||||||
|
sort=sort,
|
||||||
|
cluster=parsed_args.cluster,
|
||||||
|
)
|
258
openstackclient/volume/v3/block_storage_manage.py
Normal file
258
openstackclient/volume/v3/block_storage_manage.py
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Block Storage Volume/Snapshot Management implementations"""
|
||||||
|
|
||||||
|
from cinderclient import api_versions
|
||||||
|
from osc_lib.command import command
|
||||||
|
from osc_lib import exceptions
|
||||||
|
from osc_lib import utils
|
||||||
|
from oslo_utils import strutils
|
||||||
|
|
||||||
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
SORT_MANAGEABLE_KEY_VALUES = ('size', 'reference')
|
||||||
|
|
||||||
|
|
||||||
|
class BlockStorageManageVolumes(command.Lister):
|
||||||
|
"""List manageable volumes.
|
||||||
|
|
||||||
|
Supported by --os-volume-api-version 3.8 or greater.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
host_group = parser.add_mutually_exclusive_group()
|
||||||
|
host_group.add_argument(
|
||||||
|
"host",
|
||||||
|
metavar="<host>",
|
||||||
|
nargs='?',
|
||||||
|
help=_('Cinder host on which to list manageable volumes. '
|
||||||
|
'Takes the form: host@backend-name#pool')
|
||||||
|
)
|
||||||
|
host_group.add_argument(
|
||||||
|
"--cluster",
|
||||||
|
metavar="<cluster>",
|
||||||
|
help=_('Cinder cluster on which to list manageable volumes. '
|
||||||
|
'Takes the form: cluster@backend-name#pool. '
|
||||||
|
'(supported by --os-volume-api-version 3.17 or later)')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--detailed',
|
||||||
|
metavar='<detailed>',
|
||||||
|
default=True,
|
||||||
|
help=_('Returns detailed information (Default=True).')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--marker',
|
||||||
|
metavar='<marker>',
|
||||||
|
default=None,
|
||||||
|
help=_('Begin returning volumes that appear later in the volume '
|
||||||
|
'list than that represented by this reference. This '
|
||||||
|
'reference should be json like. Default=None.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
metavar='<limit>',
|
||||||
|
default=None,
|
||||||
|
help=_('Maximum number of volumes to return. Default=None.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--offset',
|
||||||
|
metavar='<offset>',
|
||||||
|
default=None,
|
||||||
|
help=_('Number of volumes to skip after marker. Default=None.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--sort',
|
||||||
|
metavar='<key>[:<direction>]',
|
||||||
|
default=None,
|
||||||
|
help=(_('Comma-separated list of sort keys and directions in the '
|
||||||
|
'form of <key>[:<asc|desc>]. '
|
||||||
|
'Valid keys: %s. '
|
||||||
|
'Default=None.') % ', '.join(SORT_MANAGEABLE_KEY_VALUES))
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
|
if parsed_args.host is None and parsed_args.cluster is None:
|
||||||
|
msg = _(
|
||||||
|
"Either <host> or '--cluster <cluster>' needs to be provided "
|
||||||
|
"to run the 'block storage volume manageable list' command"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
if volume_client.api_version < api_versions.APIVersion('3.8'):
|
||||||
|
msg = _(
|
||||||
|
"--os-volume-api-version 3.8 or greater is required to "
|
||||||
|
"support the 'block storage volume manageable list' command"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
if parsed_args.cluster:
|
||||||
|
if volume_client.api_version < api_versions.APIVersion('3.17'):
|
||||||
|
msg = _(
|
||||||
|
"--os-volume-api-version 3.17 or greater is required to "
|
||||||
|
"support the '--cluster' option"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
detailed = strutils.bool_from_string(parsed_args.detailed)
|
||||||
|
cluster = getattr(parsed_args, 'cluster', None)
|
||||||
|
|
||||||
|
columns = [
|
||||||
|
'reference',
|
||||||
|
'size',
|
||||||
|
'safe_to_manage',
|
||||||
|
]
|
||||||
|
if detailed:
|
||||||
|
columns.extend([
|
||||||
|
'reason_not_safe',
|
||||||
|
'cinder_id',
|
||||||
|
'extra_info',
|
||||||
|
])
|
||||||
|
|
||||||
|
data = volume_client.volumes.list_manageable(
|
||||||
|
host=parsed_args.host,
|
||||||
|
detailed=detailed,
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
offset=parsed_args.offset,
|
||||||
|
sort=parsed_args.sort,
|
||||||
|
cluster=cluster)
|
||||||
|
|
||||||
|
return (columns,
|
||||||
|
(utils.get_item_properties(
|
||||||
|
s, columns,
|
||||||
|
) for s in data))
|
||||||
|
|
||||||
|
|
||||||
|
class BlockStorageManageSnapshots(command.Lister):
|
||||||
|
"""List manageable snapshots.
|
||||||
|
|
||||||
|
Supported by --os-volume-api-version 3.8 or greater.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
host_group = parser.add_mutually_exclusive_group()
|
||||||
|
host_group.add_argument(
|
||||||
|
"host",
|
||||||
|
metavar="<host>",
|
||||||
|
nargs='?',
|
||||||
|
help=_('Cinder host on which to list manageable snapshots. '
|
||||||
|
'Takes the form: host@backend-name#pool')
|
||||||
|
)
|
||||||
|
host_group.add_argument(
|
||||||
|
"--cluster",
|
||||||
|
metavar="<cluster>",
|
||||||
|
help=_('Cinder cluster on which to list manageable snapshots. '
|
||||||
|
'Takes the form: cluster@backend-name#pool. '
|
||||||
|
'(supported by --os-volume-api-version 3.17 or later)')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--detailed',
|
||||||
|
metavar='<detailed>',
|
||||||
|
default=True,
|
||||||
|
help=_('Returns detailed information (Default=True).')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--marker',
|
||||||
|
metavar='<marker>',
|
||||||
|
default=None,
|
||||||
|
help=_('Begin returning snapshots that appear later in the '
|
||||||
|
'snapshot list than that represented by this reference. '
|
||||||
|
'This reference should be json like. Default=None.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
metavar='<limit>',
|
||||||
|
default=None,
|
||||||
|
help=_('Maximum number of snapshots to return. Default=None.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--offset',
|
||||||
|
metavar='<offset>',
|
||||||
|
default=None,
|
||||||
|
help=_('Number of snapshots to skip after marker. Default=None.')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--sort',
|
||||||
|
metavar='<key>[:<direction>]',
|
||||||
|
default=None,
|
||||||
|
help=(_('Comma-separated list of sort keys and directions in the '
|
||||||
|
'form of <key>[:<asc|desc>]. '
|
||||||
|
'Valid keys: %s. '
|
||||||
|
'Default=None.') % ', '.join(SORT_MANAGEABLE_KEY_VALUES))
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
|
if parsed_args.host is None and parsed_args.cluster is None:
|
||||||
|
msg = _(
|
||||||
|
"Either <host> or '--cluster <cluster>' needs to be provided "
|
||||||
|
"to run the 'block storage volume snapshot manageable list' "
|
||||||
|
"command"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
if volume_client.api_version < api_versions.APIVersion('3.8'):
|
||||||
|
msg = _(
|
||||||
|
"--os-volume-api-version 3.8 or greater is required to "
|
||||||
|
"support the 'block storage volume snapshot manageable list' "
|
||||||
|
"command"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
if parsed_args.cluster:
|
||||||
|
if volume_client.api_version < api_versions.APIVersion('3.17'):
|
||||||
|
msg = _(
|
||||||
|
"--os-volume-api-version 3.17 or greater is required to "
|
||||||
|
"support the '--cluster' option"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
detailed = strutils.bool_from_string(parsed_args.detailed)
|
||||||
|
cluster = getattr(parsed_args, 'cluster', None)
|
||||||
|
|
||||||
|
columns = [
|
||||||
|
'reference',
|
||||||
|
'size',
|
||||||
|
'safe_to_manage',
|
||||||
|
'source_reference',
|
||||||
|
]
|
||||||
|
if detailed:
|
||||||
|
columns.extend([
|
||||||
|
'reason_not_safe',
|
||||||
|
'cinder_id',
|
||||||
|
'extra_info',
|
||||||
|
])
|
||||||
|
|
||||||
|
data = volume_client.volume_snapshots.list_manageable(
|
||||||
|
host=parsed_args.host,
|
||||||
|
detailed=detailed,
|
||||||
|
marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit,
|
||||||
|
offset=parsed_args.offset,
|
||||||
|
sort=parsed_args.sort,
|
||||||
|
cluster=cluster)
|
||||||
|
|
||||||
|
return (columns,
|
||||||
|
(utils.get_item_properties(
|
||||||
|
s, columns,
|
||||||
|
) for s in data))
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added ``block storage volume manageable list`` and
|
||||||
|
``block storage snapshot manageable list`` commands that
|
||||||
|
allow operators to list the volumes and snapshots on a
|
||||||
|
particular host or cluster for management under OpenStack.
|
@ -825,3 +825,5 @@ openstack.volume.v3 =
|
|||||||
block_storage_log_level_list = openstackclient.volume.v3.block_storage_log_level:BlockStorageLogLevelList
|
block_storage_log_level_list = openstackclient.volume.v3.block_storage_log_level:BlockStorageLogLevelList
|
||||||
block_storage_log_level_set = openstackclient.volume.v3.block_storage_log_level:BlockStorageLogLevelSet
|
block_storage_log_level_set = openstackclient.volume.v3.block_storage_log_level:BlockStorageLogLevelSet
|
||||||
block_storage_cleanup = openstackclient.volume.v3.block_storage_cleanup:BlockStorageCleanup
|
block_storage_cleanup = openstackclient.volume.v3.block_storage_cleanup:BlockStorageCleanup
|
||||||
|
block_storage_volume_manageable_list = openstackclient.volume.v3.block_storage_manage:BlockStorageManageVolumes
|
||||||
|
block_storage_snapshot_manageable_list = openstackclient.volume.v3.block_storage_manage:BlockStorageManageSnapshots
|
||||||
|
Loading…
x
Reference in New Issue
Block a user