Merge "Add "consistency group create" command"
This commit is contained in:
@@ -4,6 +4,42 @@ consistency group
|
|||||||
|
|
||||||
Block Storage v2
|
Block Storage v2
|
||||||
|
|
||||||
|
consistency group create
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Create new consistency group.
|
||||||
|
|
||||||
|
.. program:: consistency group create
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
os consistency group create
|
||||||
|
--volume-type <volume-type> | --consistency-group-source <consistency-group>
|
||||||
|
[--description <description>]
|
||||||
|
[--availability-zone <availability-zone>]
|
||||||
|
[<name>]
|
||||||
|
|
||||||
|
.. option:: --volume-type <volume-type>
|
||||||
|
|
||||||
|
Volume type of this consistency group (name or ID)
|
||||||
|
|
||||||
|
.. option:: --consistency-group-source <consistency-group>
|
||||||
|
|
||||||
|
Existing consistency group (name or ID)
|
||||||
|
|
||||||
|
.. option:: --description <description>
|
||||||
|
|
||||||
|
Description of this consistency group
|
||||||
|
|
||||||
|
.. option:: --availability-zone <availability-zone>
|
||||||
|
|
||||||
|
Availability zone for this consistency group
|
||||||
|
(not available if creating consistency group from source)
|
||||||
|
|
||||||
|
.. _consistency_group_create-name:
|
||||||
|
.. option:: <name>
|
||||||
|
|
||||||
|
Name of new consistency group (default to None)
|
||||||
|
|
||||||
consistency group list
|
consistency group list
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,138 @@ class TestConsistencyGroup(volume_fakes.TestVolume):
|
|||||||
self.app.client_manager.volume.consistencygroups)
|
self.app.client_manager.volume.consistencygroups)
|
||||||
self.consistencygroups_mock.reset_mock()
|
self.consistencygroups_mock.reset_mock()
|
||||||
|
|
||||||
|
self.types_mock = self.app.client_manager.volume.volume_types
|
||||||
|
self.types_mock.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
class TestConsistencyGroupCreate(TestConsistencyGroup):
|
||||||
|
|
||||||
|
volume_type = volume_fakes.FakeType.create_one_type()
|
||||||
|
new_consistency_group = (
|
||||||
|
volume_fakes.FakeConsistencyGroup.create_one_consistency_group())
|
||||||
|
|
||||||
|
columns = (
|
||||||
|
'availability_zone',
|
||||||
|
'created_at',
|
||||||
|
'description',
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'status',
|
||||||
|
'volume_types',
|
||||||
|
)
|
||||||
|
data = (
|
||||||
|
new_consistency_group.availability_zone,
|
||||||
|
new_consistency_group.created_at,
|
||||||
|
new_consistency_group.description,
|
||||||
|
new_consistency_group.id,
|
||||||
|
new_consistency_group.name,
|
||||||
|
new_consistency_group.status,
|
||||||
|
new_consistency_group.volume_types,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestConsistencyGroupCreate, self).setUp()
|
||||||
|
self.consistencygroups_mock.create.return_value = (
|
||||||
|
self.new_consistency_group)
|
||||||
|
self.consistencygroups_mock.create_from_src.return_value = (
|
||||||
|
self.new_consistency_group)
|
||||||
|
self.consistencygroups_mock.get.return_value = (
|
||||||
|
self.new_consistency_group)
|
||||||
|
self.types_mock.get.return_value = self.volume_type
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = consistency_group.CreateConsistencyGroup(self.app, None)
|
||||||
|
|
||||||
|
def test_consistency_group_create(self):
|
||||||
|
arglist = [
|
||||||
|
'--volume-type', self.volume_type.id,
|
||||||
|
'--description', self.new_consistency_group.description,
|
||||||
|
'--availability-zone',
|
||||||
|
self.new_consistency_group.availability_zone,
|
||||||
|
self.new_consistency_group.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('volume_type', self.volume_type.id),
|
||||||
|
('description', self.new_consistency_group.description),
|
||||||
|
('availability_zone',
|
||||||
|
self.new_consistency_group.availability_zone),
|
||||||
|
('name', self.new_consistency_group.name),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.types_mock.get.assert_called_once_with(
|
||||||
|
self.volume_type.id)
|
||||||
|
self.consistencygroups_mock.get.assert_not_called()
|
||||||
|
self.consistencygroups_mock.create.assert_called_once_with(
|
||||||
|
self.volume_type.id,
|
||||||
|
name=self.new_consistency_group.name,
|
||||||
|
description=self.new_consistency_group.description,
|
||||||
|
availability_zone=self.new_consistency_group.availability_zone,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_consistency_group_create_without_name(self):
|
||||||
|
arglist = [
|
||||||
|
'--volume-type', self.volume_type.id,
|
||||||
|
'--description', self.new_consistency_group.description,
|
||||||
|
'--availability-zone',
|
||||||
|
self.new_consistency_group.availability_zone,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('volume_type', self.volume_type.id),
|
||||||
|
('description', self.new_consistency_group.description),
|
||||||
|
('availability_zone',
|
||||||
|
self.new_consistency_group.availability_zone),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.types_mock.get.assert_called_once_with(
|
||||||
|
self.volume_type.id)
|
||||||
|
self.consistencygroups_mock.get.assert_not_called()
|
||||||
|
self.consistencygroups_mock.create.assert_called_once_with(
|
||||||
|
self.volume_type.id,
|
||||||
|
name=None,
|
||||||
|
description=self.new_consistency_group.description,
|
||||||
|
availability_zone=self.new_consistency_group.availability_zone,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_consistency_group_create_from_source(self):
|
||||||
|
arglist = [
|
||||||
|
'--consistency-group-source', self.new_consistency_group.id,
|
||||||
|
'--description', self.new_consistency_group.description,
|
||||||
|
self.new_consistency_group.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('consistency_group_source', self.new_consistency_group.id),
|
||||||
|
('description', self.new_consistency_group.description),
|
||||||
|
('name', self.new_consistency_group.name),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.types_mock.get.assert_not_called()
|
||||||
|
self.consistencygroups_mock.get.assert_called_once_with(
|
||||||
|
self.new_consistency_group.id)
|
||||||
|
self.consistencygroups_mock.create_from_src.assert_called_with(
|
||||||
|
None,
|
||||||
|
self.new_consistency_group.id,
|
||||||
|
name=self.new_consistency_group.name,
|
||||||
|
description=self.new_consistency_group.description,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
|
||||||
class TestConsistencyGroupList(TestConsistencyGroup):
|
class TestConsistencyGroupList(TestConsistencyGroup):
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,89 @@
|
|||||||
|
|
||||||
"""Volume v2 consistency group action implementations"""
|
"""Volume v2 consistency group action implementations"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
|
import six
|
||||||
|
|
||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateConsistencyGroup(command.ShowOne):
|
||||||
|
_description = _("Create new consistency group.")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CreateConsistencyGroup, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"name",
|
||||||
|
metavar="<name>",
|
||||||
|
nargs="?",
|
||||||
|
help=_("Name of new consistency group (default to None)")
|
||||||
|
)
|
||||||
|
exclusive_group = parser.add_mutually_exclusive_group(required=True)
|
||||||
|
exclusive_group.add_argument(
|
||||||
|
"--volume-type",
|
||||||
|
metavar="<volume-type>",
|
||||||
|
help=_("Volume type of this consistency group (name or ID)")
|
||||||
|
)
|
||||||
|
exclusive_group.add_argument(
|
||||||
|
"--consistency-group-source",
|
||||||
|
metavar="<consistency-group>",
|
||||||
|
help=_("Existing consistency group (name or ID)")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--description",
|
||||||
|
metavar="<description>",
|
||||||
|
help=_("Description of this consistency group")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--availability-zone",
|
||||||
|
metavar="<availability-zone>",
|
||||||
|
help=_("Availability zone for this consistency group "
|
||||||
|
"(not available if creating consistency group "
|
||||||
|
"from source)"),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
if parsed_args.volume_type:
|
||||||
|
volume_type_id = utils.find_resource(
|
||||||
|
volume_client.volume_types,
|
||||||
|
parsed_args.volume_type).id
|
||||||
|
consistency_group = volume_client.consistencygroups.create(
|
||||||
|
volume_type_id,
|
||||||
|
name=parsed_args.name,
|
||||||
|
description=parsed_args.description,
|
||||||
|
availability_zone=parsed_args.availability_zone
|
||||||
|
)
|
||||||
|
elif parsed_args.consistency_group_source:
|
||||||
|
if parsed_args.availability_zone:
|
||||||
|
msg = _("'--availability-zone' option will not work "
|
||||||
|
"if creating consistency group from source")
|
||||||
|
LOG.warning(msg)
|
||||||
|
consistency_group_id = utils.find_resource(
|
||||||
|
volume_client.consistencygroups,
|
||||||
|
parsed_args.consistency_group_source).id
|
||||||
|
consistency_group_snapshot = None
|
||||||
|
# TODO(Huanxuan Ao): Support for creating from consistency group
|
||||||
|
# snapshot after adding "consistency_group_snapshot" resource
|
||||||
|
consistency_group = (
|
||||||
|
volume_client.consistencygroups.create_from_src(
|
||||||
|
consistency_group_snapshot,
|
||||||
|
consistency_group_id,
|
||||||
|
name=parsed_args.name,
|
||||||
|
description=parsed_args.description
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return zip(*sorted(six.iteritems(consistency_group._info)))
|
||||||
|
|
||||||
|
|
||||||
class ListConsistencyGroup(command.Lister):
|
class ListConsistencyGroup(command.Lister):
|
||||||
_description = _("List consistency groups.")
|
_description = _("List consistency groups.")
|
||||||
|
|
||||||
|
|||||||
4
releasenotes/notes/bug-1613964-837196399be16b3d.yaml
Normal file
4
releasenotes/notes/bug-1613964-837196399be16b3d.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add ``consistency group create`` command in volume v2.
|
||||||
|
[Bug `1613964 <https://bugs.launchpad.net/python-openstackclient/+bug/1613964>`_]
|
||||||
@@ -508,6 +508,7 @@ openstack.volume.v2 =
|
|||||||
backup_restore = openstackclient.volume.v2.backup:RestoreBackup
|
backup_restore = openstackclient.volume.v2.backup:RestoreBackup
|
||||||
backup_show = openstackclient.volume.v2.backup:ShowBackup
|
backup_show = openstackclient.volume.v2.backup:ShowBackup
|
||||||
|
|
||||||
|
consistency_group_create = openstackclient.volume.v2.consistency_group:CreateConsistencyGroup
|
||||||
consistency_group_list = openstackclient.volume.v2.consistency_group:ListConsistencyGroup
|
consistency_group_list = openstackclient.volume.v2.consistency_group:ListConsistencyGroup
|
||||||
|
|
||||||
snapshot_create = openstackclient.volume.v2.snapshot:CreateSnapshot
|
snapshot_create = openstackclient.volume.v2.snapshot:CreateSnapshot
|
||||||
|
|||||||
Reference in New Issue
Block a user