summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume.py73
-rw-r--r--openstackclient/volume/v2/volume.py29
2 files changed, 99 insertions, 3 deletions
diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py
index f802f637..ef9c2fab 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume.py
@@ -16,6 +16,7 @@ import argparse
from unittest import mock
from unittest.mock import call
+from cinderclient import api_versions
from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -47,6 +48,9 @@ class TestVolume(volume_fakes.TestVolume):
self.snapshots_mock = self.app.client_manager.volume.volume_snapshots
self.snapshots_mock.reset_mock()
+ self.backups_mock = self.app.client_manager.volume.backups
+ self.backups_mock.reset_mock()
+
self.types_mock = self.app.client_manager.volume.volume_types
self.types_mock.reset_mock()
@@ -129,6 +133,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -174,6 +179,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=consistency_group.id,
scheduler_hints={'k': 'v'},
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -210,6 +216,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -248,6 +255,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -286,6 +294,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -323,11 +332,72 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertCountEqual(self.datalist, data)
+
+ def test_volume_create_with_backup(self):
+ backup = volume_fakes.create_one_backup()
+ self.new_volume.backup_id = backup.id
+ arglist = [
+ '--backup', self.new_volume.backup_id,
+ self.new_volume.name,
+ ]
+ verifylist = [
+ ('backup', self.new_volume.backup_id),
+ ('name', self.new_volume.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.backups_mock.get.return_value = backup
+
+ self.app.client_manager.volume.api_version = \
+ api_versions.APIVersion('3.47')
+
+ # In base command class ShowOne in cliff, abstract method take_action()
+ # returns a two-part tuple with a tuple of column names and a tuple of
+ # data to be shown.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_once_with(
+ size=backup.size,
+ snapshot_id=None,
+ name=self.new_volume.name,
+ description=None,
+ volume_type=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None,
+ consistencygroup_id=None,
+ scheduler_hints=None,
+ backup_id=backup.id,
)
self.assertEqual(self.columns, columns)
self.assertCountEqual(self.datalist, data)
+ def test_volume_create_with_backup_pre_347(self):
+ backup = volume_fakes.create_one_backup()
+ self.new_volume.backup_id = backup.id
+ arglist = [
+ '--backup', self.new_volume.backup_id,
+ self.new_volume.name,
+ ]
+ verifylist = [
+ ('backup', self.new_volume.backup_id),
+ ('name', self.new_volume.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.backups_mock.get.return_value = backup
+
+ exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+ self.assertIn("--os-volume-api-version 3.47 or greater", str(exc))
+
def test_volume_create_with_bootable_and_readonly(self):
arglist = [
'--bootable',
@@ -361,6 +431,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -403,6 +474,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(self.columns, columns)
@@ -454,6 +526,7 @@ class TestVolumeCreate(TestVolume):
source_volid=None,
consistencygroup_id=None,
scheduler_hints=None,
+ backup_id=None,
)
self.assertEqual(2, mock_error.call_count)
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index 1e1fde92..53f6e643 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -71,10 +71,10 @@ def _check_size_arg(args):
volume is not specified.
"""
- if ((args.snapshot or args.source)
+ if ((args.snapshot or args.source or args.backup)
is None and args.size is None):
- msg = _("--size is a required option if snapshot "
- "or source volume is not specified.")
+ msg = _("--size is a required option if snapshot, backup "
+ "or source volume are not specified.")
raise exceptions.CommandError(msg)
@@ -118,6 +118,12 @@ class CreateVolume(command.ShowOne):
help=_("Volume to clone (name or ID)"),
)
source_group.add_argument(
+ "--backup",
+ metavar="<backup>",
+ help=_("Restore backup to a volume (name or ID) "
+ "(supported by --os-volume-api-version 3.47 or later)"),
+ )
+ source_group.add_argument(
"--source-replicated",
metavar="<replicated-volume>",
help=argparse.SUPPRESS,
@@ -177,9 +183,16 @@ class CreateVolume(command.ShowOne):
def take_action(self, parsed_args):
_check_size_arg(parsed_args)
+
volume_client = self.app.client_manager.volume
image_client = self.app.client_manager.image
+ if parsed_args.backup and not (
+ volume_client.api_version.matches('3.47')):
+ msg = _("--os-volume-api-version 3.47 or greater is required "
+ "to create a volume from backup.")
+ raise exceptions.CommandError(msg)
+
source_volume = None
if parsed_args.source:
source_volume = utils.find_resource(
@@ -213,6 +226,15 @@ class CreateVolume(command.ShowOne):
# snapshot size.
size = max(size or 0, snapshot_obj.size)
+ backup = None
+ if parsed_args.backup:
+ backup_obj = utils.find_resource(
+ volume_client.backups,
+ parsed_args.backup)
+ backup = backup_obj.id
+ # As above
+ size = max(size or 0, backup_obj.size)
+
volume = volume_client.volumes.create(
size=size,
snapshot_id=snapshot,
@@ -225,6 +247,7 @@ class CreateVolume(command.ShowOne):
source_volid=source_volume,
consistencygroup_id=consistency_group,
scheduler_hints=parsed_args.hint,
+ backup_id=backup,
)
if parsed_args.bootable or parsed_args.non_bootable: