Support share revert to snapshot in Manila client
This commit adds support to Manila client for the share-revert-to-snapshot feature. Implements: blueprint manila-share-revert-to-snapshot Depends-On: Id497e13070e0003db2db951526a52de6c2182cca Change-Id: Ia9c63ac416db47baae78b02ffcab5a60892cbf5c
This commit is contained in:
parent
c91deb8498
commit
d736acc442
@ -27,7 +27,7 @@ from manilaclient import utils
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
MAX_VERSION = '2.26'
|
MAX_VERSION = '2.27'
|
||||||
MIN_VERSION = '2.0'
|
MIN_VERSION = '2.0'
|
||||||
DEPRECATED_VERSION = '1.0'
|
DEPRECATED_VERSION = '1.0'
|
||||||
_VERSIONED_METHOD_MAP = {}
|
_VERSIONED_METHOD_MAP = {}
|
||||||
|
@ -172,7 +172,8 @@ class BaseTestCase(base.ClientTestBase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def create_share_type(cls, name=None, driver_handles_share_servers=True,
|
def create_share_type(cls, name=None, driver_handles_share_servers=True,
|
||||||
snapshot_support=None,
|
snapshot_support=None,
|
||||||
create_share_from_snapshot=None, is_public=True,
|
create_share_from_snapshot=None,
|
||||||
|
revert_to_snapshot=None, is_public=True,
|
||||||
client=None, cleanup_in_class=True,
|
client=None, cleanup_in_class=True,
|
||||||
microversion=None, extra_specs=None):
|
microversion=None, extra_specs=None):
|
||||||
if client is None:
|
if client is None:
|
||||||
@ -185,6 +186,7 @@ class BaseTestCase(base.ClientTestBase):
|
|||||||
microversion=microversion,
|
microversion=microversion,
|
||||||
extra_specs=extra_specs,
|
extra_specs=extra_specs,
|
||||||
create_share_from_snapshot=create_share_from_snapshot,
|
create_share_from_snapshot=create_share_from_snapshot,
|
||||||
|
revert_to_snapshot=revert_to_snapshot
|
||||||
)
|
)
|
||||||
resource = {
|
resource = {
|
||||||
"type": "share_type",
|
"type": "share_type",
|
||||||
|
@ -164,7 +164,8 @@ class ManilaCLIClient(base.CLIClient):
|
|||||||
|
|
||||||
def create_share_type(self, name=None, driver_handles_share_servers=True,
|
def create_share_type(self, name=None, driver_handles_share_servers=True,
|
||||||
snapshot_support=None,
|
snapshot_support=None,
|
||||||
create_share_from_snapshot=None, is_public=True,
|
create_share_from_snapshot=None,
|
||||||
|
revert_to_snapshot=None, is_public=True,
|
||||||
microversion=None, extra_specs=None):
|
microversion=None, extra_specs=None):
|
||||||
"""Creates share type.
|
"""Creates share type.
|
||||||
|
|
||||||
@ -179,6 +180,8 @@ class ManilaCLIClient(base.CLIClient):
|
|||||||
:param extra_specs: -- dictionary of extra specs Default is None.
|
:param extra_specs: -- dictionary of extra specs Default is None.
|
||||||
:param create_share_from_snapshot: -- boolean or its string
|
:param create_share_from_snapshot: -- boolean or its string
|
||||||
alias. Default is None.
|
alias. Default is None.
|
||||||
|
:param revert_to_snapshot: -- boolean or its string alias. Default is
|
||||||
|
None.
|
||||||
"""
|
"""
|
||||||
if name is None:
|
if name is None:
|
||||||
name = data_utils.rand_name('manilaclient_functional_test')
|
name = data_utils.rand_name('manilaclient_functional_test')
|
||||||
@ -194,14 +197,20 @@ class ManilaCLIClient(base.CLIClient):
|
|||||||
if snapshot_support is not None:
|
if snapshot_support is not None:
|
||||||
if not isinstance(snapshot_support, six.string_types):
|
if not isinstance(snapshot_support, six.string_types):
|
||||||
snapshot_support = six.text_type(snapshot_support)
|
snapshot_support = six.text_type(snapshot_support)
|
||||||
cmd += " --snapshot-support " + snapshot_support
|
cmd += " --snapshot-support " + snapshot_support
|
||||||
|
|
||||||
if create_share_from_snapshot is not None:
|
if create_share_from_snapshot is not None:
|
||||||
if not isinstance(create_share_from_snapshot, six.string_types):
|
if not isinstance(create_share_from_snapshot, six.string_types):
|
||||||
create_share_from_snapshot = six.text_type(
|
create_share_from_snapshot = six.text_type(
|
||||||
create_share_from_snapshot)
|
create_share_from_snapshot)
|
||||||
cmd += (" --create-share-from-snapshot-support " +
|
cmd += (" --create-share-from-snapshot-support " +
|
||||||
create_share_from_snapshot)
|
create_share_from_snapshot)
|
||||||
|
|
||||||
|
if revert_to_snapshot is not None:
|
||||||
|
if not isinstance(revert_to_snapshot, six.string_types):
|
||||||
|
revert_to_snapshot = six.text_type(
|
||||||
|
revert_to_snapshot)
|
||||||
|
cmd += (" --revert-to-snapshot-support " + revert_to_snapshot)
|
||||||
|
|
||||||
if extra_specs is not None:
|
if extra_specs is not None:
|
||||||
extra_spec_str = ''
|
extra_spec_str = ''
|
||||||
|
@ -90,7 +90,7 @@ class ShareTypesReadWriteTest(base.BaseTestCase):
|
|||||||
self.skip_if_microversion_not_supported('2.0')
|
self.skip_if_microversion_not_supported('2.0')
|
||||||
self._test_create_delete_share_type(
|
self._test_create_delete_share_type(
|
||||||
'2.0', is_public, dhss, spec_snapshot_support,
|
'2.0', is_public, dhss, spec_snapshot_support,
|
||||||
None, extra_specs)
|
None, None, extra_specs)
|
||||||
|
|
||||||
@ddt.data(*unit_test_types.get_valid_type_create_data_2_24())
|
@ddt.data(*unit_test_types.get_valid_type_create_data_2_24())
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
@ -101,11 +101,25 @@ class ShareTypesReadWriteTest(base.BaseTestCase):
|
|||||||
self.skip_if_microversion_not_supported('2.24')
|
self.skip_if_microversion_not_supported('2.24')
|
||||||
self._test_create_delete_share_type(
|
self._test_create_delete_share_type(
|
||||||
'2.24', is_public, dhss, spec_snapshot_support,
|
'2.24', is_public, dhss, spec_snapshot_support,
|
||||||
spec_create_share_from_snapshot, extra_specs)
|
spec_create_share_from_snapshot, None, extra_specs)
|
||||||
|
|
||||||
|
@ddt.data(*unit_test_types.get_valid_type_create_data_2_27())
|
||||||
|
@ddt.unpack
|
||||||
|
def test_create_delete_share_type_2_27(
|
||||||
|
self, is_public, dhss, spec_snapshot_support,
|
||||||
|
spec_create_share_from_snapshot, spec_revert_to_snapshot_support,
|
||||||
|
extra_specs):
|
||||||
|
|
||||||
|
self.skip_if_microversion_not_supported('2.27')
|
||||||
|
self._test_create_delete_share_type(
|
||||||
|
'2.27', is_public, dhss, spec_snapshot_support,
|
||||||
|
spec_create_share_from_snapshot, spec_revert_to_snapshot_support,
|
||||||
|
extra_specs)
|
||||||
|
|
||||||
def _test_create_delete_share_type(self, microversion, is_public, dhss,
|
def _test_create_delete_share_type(self, microversion, is_public, dhss,
|
||||||
spec_snapshot_support,
|
spec_snapshot_support,
|
||||||
spec_create_share_from_snapshot,
|
spec_create_share_from_snapshot,
|
||||||
|
spec_revert_to_snapshot_support,
|
||||||
extra_specs):
|
extra_specs):
|
||||||
|
|
||||||
share_type_name = data_utils.rand_name('manilaclient_functional_test')
|
share_type_name = data_utils.rand_name('manilaclient_functional_test')
|
||||||
@ -119,6 +133,7 @@ class ShareTypesReadWriteTest(base.BaseTestCase):
|
|||||||
driver_handles_share_servers=dhss,
|
driver_handles_share_servers=dhss,
|
||||||
snapshot_support=spec_snapshot_support,
|
snapshot_support=spec_snapshot_support,
|
||||||
create_share_from_snapshot=spec_create_share_from_snapshot,
|
create_share_from_snapshot=spec_create_share_from_snapshot,
|
||||||
|
revert_to_snapshot=spec_revert_to_snapshot_support,
|
||||||
is_public=is_public,
|
is_public=is_public,
|
||||||
microversion=microversion,
|
microversion=microversion,
|
||||||
extra_specs=extra_specs)
|
extra_specs=extra_specs)
|
||||||
@ -163,6 +178,11 @@ class ShareTypesReadWriteTest(base.BaseTestCase):
|
|||||||
('{} : {}'.format(
|
('{} : {}'.format(
|
||||||
'create_share_from_snapshot_support',
|
'create_share_from_snapshot_support',
|
||||||
spec_create_share_from_snapshot)).strip())
|
spec_create_share_from_snapshot)).strip())
|
||||||
|
if spec_revert_to_snapshot_support is not None:
|
||||||
|
expected_extra_specs.append(
|
||||||
|
('{} : {}'.format(
|
||||||
|
'revert_to_snapshot_support',
|
||||||
|
spec_revert_to_snapshot_support)).strip())
|
||||||
|
|
||||||
# Verify optional extra specs
|
# Verify optional extra specs
|
||||||
optional_extra_specs = share_type['optional_extra_specs']
|
optional_extra_specs = share_type['optional_extra_specs']
|
||||||
|
@ -402,6 +402,9 @@ class FakeHTTPClient(fakes.FakeHTTPClient):
|
|||||||
assert body[action]['new_size'] is not None
|
assert body[action]['new_size'] is not None
|
||||||
elif action in ('unmanage', ):
|
elif action in ('unmanage', ):
|
||||||
assert body[action] is None
|
assert body[action] is None
|
||||||
|
elif action in ('revert', ):
|
||||||
|
assert body[action] is not None
|
||||||
|
assert body[action]['snapshot_id'] is not None
|
||||||
elif action in (
|
elif action in (
|
||||||
'migration_cancel', 'migration_complete',
|
'migration_cancel', 'migration_complete',
|
||||||
'migration_get_progress'):
|
'migration_get_progress'):
|
||||||
|
@ -19,6 +19,7 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from manilaclient import api_versions
|
from manilaclient import api_versions
|
||||||
|
from manilaclient.common.apiclient import exceptions as client_exceptions
|
||||||
from manilaclient import exceptions
|
from manilaclient import exceptions
|
||||||
from manilaclient import extension
|
from manilaclient import extension
|
||||||
from manilaclient.tests.unit import utils
|
from manilaclient.tests.unit import utils
|
||||||
@ -239,6 +240,35 @@ class SharesTest(utils.TestCase):
|
|||||||
manager._action.assert_called_once_with("unmanage", share)
|
manager._action.assert_called_once_with("unmanage", share)
|
||||||
self.assertEqual("fake", result)
|
self.assertEqual("fake", result)
|
||||||
|
|
||||||
|
def test_revert_to_snapshot(self):
|
||||||
|
|
||||||
|
share = 'fake_share'
|
||||||
|
snapshot = 'fake_snapshot'
|
||||||
|
version = api_versions.APIVersion("2.27")
|
||||||
|
mock_microversion = mock.Mock(api_version=version)
|
||||||
|
manager = shares.ShareManager(api=mock_microversion)
|
||||||
|
mock_action = self.mock_object(
|
||||||
|
manager, '_action', mock.Mock(return_value='fake'))
|
||||||
|
|
||||||
|
result = manager.revert_to_snapshot(share, snapshot)
|
||||||
|
|
||||||
|
self.assertEqual('fake', result)
|
||||||
|
mock_action.assert_called_once_with(
|
||||||
|
'revert', 'fake_share', info={'snapshot_id': 'fake_snapshot'})
|
||||||
|
|
||||||
|
def test_revert_to_snapshot_not_supported(self):
|
||||||
|
|
||||||
|
share = 'fake_share'
|
||||||
|
snapshot = 'fake_snapshot'
|
||||||
|
version = api_versions.APIVersion("2.26")
|
||||||
|
mock_microversion = mock.Mock(api_version=version)
|
||||||
|
manager = shares.ShareManager(api=mock_microversion)
|
||||||
|
|
||||||
|
self.assertRaises(client_exceptions.UnsupportedVersion,
|
||||||
|
manager.revert_to_snapshot,
|
||||||
|
share,
|
||||||
|
snapshot)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
("2.6", "os-force_delete"),
|
("2.6", "os-force_delete"),
|
||||||
("2.7", "force_delete"),
|
("2.7", "force_delete"),
|
||||||
|
@ -455,6 +455,7 @@ class ShellTest(test_utils.TestCase):
|
|||||||
'driver_handles_share_servers': False,
|
'driver_handles_share_servers': False,
|
||||||
'snapshot_support': True,
|
'snapshot_support': True,
|
||||||
'create_share_from_snapshot_support': True,
|
'create_share_from_snapshot_support': True,
|
||||||
|
'revert_to_snapshot_support': False,
|
||||||
},
|
},
|
||||||
'share_type_access:is_public': public
|
'share_type_access:is_public': public
|
||||||
}
|
}
|
||||||
@ -618,6 +619,19 @@ class ShellTest(test_utils.TestCase):
|
|||||||
self.assert_called('POST', '/snapshots/1234/action',
|
self.assert_called('POST', '/snapshots/1234/action',
|
||||||
body={'unmanage': None})
|
body={'unmanage': None})
|
||||||
|
|
||||||
|
def test_revert_to_snapshot(self):
|
||||||
|
|
||||||
|
fake_share_snapshot = type(
|
||||||
|
'FakeShareSnapshot', (object,), {'id': '5678', 'share_id': '1234'})
|
||||||
|
self.mock_object(
|
||||||
|
shell_v2, '_find_share_snapshot',
|
||||||
|
mock.Mock(return_value=fake_share_snapshot))
|
||||||
|
|
||||||
|
self.run_command('revert-to-snapshot 5678')
|
||||||
|
|
||||||
|
self.assert_called('POST', '/shares/1234/action',
|
||||||
|
body={'revert': {'snapshot_id': '5678'}})
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
self.run_command('delete 1234')
|
self.run_command('delete 1234')
|
||||||
self.assert_called('DELETE', '/shares/1234')
|
self.assert_called('DELETE', '/shares/1234')
|
||||||
@ -823,6 +837,7 @@ class ShellTest(test_utils.TestCase):
|
|||||||
"driver_handles_share_servers": expected_bool,
|
"driver_handles_share_servers": expected_bool,
|
||||||
"snapshot_support": True,
|
"snapshot_support": True,
|
||||||
"create_share_from_snapshot_support": True,
|
"create_share_from_snapshot_support": True,
|
||||||
|
"revert_to_snapshot_support": False,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -870,6 +885,7 @@ class ShellTest(test_utils.TestCase):
|
|||||||
"driver_handles_share_servers": False,
|
"driver_handles_share_servers": False,
|
||||||
"snapshot_support": expected_bool,
|
"snapshot_support": expected_bool,
|
||||||
"create_share_from_snapshot_support": True,
|
"create_share_from_snapshot_support": True,
|
||||||
|
"revert_to_snapshot_support": False,
|
||||||
"replication_type": replication_type,
|
"replication_type": replication_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -898,6 +914,7 @@ class ShellTest(test_utils.TestCase):
|
|||||||
"driver_handles_share_servers": False,
|
"driver_handles_share_servers": False,
|
||||||
"snapshot_support": True,
|
"snapshot_support": True,
|
||||||
"create_share_from_snapshot_support": expected_bool,
|
"create_share_from_snapshot_support": expected_bool,
|
||||||
|
"revert_to_snapshot_support": False,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -923,6 +940,41 @@ class ShellTest(test_utils.TestCase):
|
|||||||
'type-create test false --extra-specs %s=fake' % value,
|
'type-create test false --extra-specs %s=fake' % value,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ddt.unpack
|
||||||
|
@ddt.data(
|
||||||
|
*([{'expected_bool': True, 'text': v}
|
||||||
|
for v in ('true', 'True', '1', 'TRUE', 'tRuE')] +
|
||||||
|
[{'expected_bool': False, 'text': v}
|
||||||
|
for v in ('false', 'False', '0', 'FALSE', 'fAlSe')])
|
||||||
|
)
|
||||||
|
def test_type_create_with_revert_to_snapshot_support(
|
||||||
|
self, expected_bool, text):
|
||||||
|
expected = {
|
||||||
|
"share_type": {
|
||||||
|
"name": "test",
|
||||||
|
"share_type_access:is_public": True,
|
||||||
|
"extra_specs": {
|
||||||
|
"driver_handles_share_servers": False,
|
||||||
|
"snapshot_support": True,
|
||||||
|
"create_share_from_snapshot_support": True,
|
||||||
|
"revert_to_snapshot_support": expected_bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.run_command('type-create test false --snapshot-support true '
|
||||||
|
'--revert-to-snapshot-support ' + text)
|
||||||
|
|
||||||
|
self.assert_called('POST', '/types', body=expected)
|
||||||
|
|
||||||
|
@ddt.data('fake', 'FFFalse', 'trueee')
|
||||||
|
def test_type_create_invalid_revert_to_snapshot_support_value(self, value):
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.run_command,
|
||||||
|
'type-create test false --revert-to-snapshot-support ' + value,
|
||||||
|
)
|
||||||
|
|
||||||
@ddt.data('--is-public', '--is_public')
|
@ddt.data('--is-public', '--is_public')
|
||||||
def test_update(self, alias):
|
def test_update(self, alias):
|
||||||
# basic rename with positional arguments
|
# basic rename with positional arguments
|
||||||
|
@ -72,6 +72,47 @@ def get_valid_type_create_data_2_24():
|
|||||||
return snapshot_none_combos + snapshot_true_combos + snapshot_false_combos
|
return snapshot_none_combos + snapshot_true_combos + snapshot_false_combos
|
||||||
|
|
||||||
|
|
||||||
|
def get_valid_type_create_data_2_27():
|
||||||
|
|
||||||
|
public = [True, False]
|
||||||
|
dhss = [True, False]
|
||||||
|
snapshot = [None]
|
||||||
|
create_from_snapshot = [None]
|
||||||
|
revert_to_snapshot = [None]
|
||||||
|
extra_specs = [None, {'replication_type': 'writable', 'foo': 'bar'}]
|
||||||
|
|
||||||
|
snapshot_none_combos = list(itertools.product(public, dhss, snapshot,
|
||||||
|
create_from_snapshot,
|
||||||
|
revert_to_snapshot,
|
||||||
|
extra_specs))
|
||||||
|
|
||||||
|
public = [True, False]
|
||||||
|
dhss = [True, False]
|
||||||
|
snapshot = [True]
|
||||||
|
create_from_snapshot = [True, False, None]
|
||||||
|
revert_to_snapshot = [True, False, None]
|
||||||
|
extra_specs = [None, {'replication_type': 'readable', 'foo': 'bar'}]
|
||||||
|
|
||||||
|
snapshot_true_combos = list(itertools.product(public, dhss, snapshot,
|
||||||
|
create_from_snapshot,
|
||||||
|
revert_to_snapshot,
|
||||||
|
extra_specs))
|
||||||
|
|
||||||
|
public = [True, False]
|
||||||
|
dhss = [True, False]
|
||||||
|
snapshot = [False]
|
||||||
|
create_from_snapshot = [False, None]
|
||||||
|
revert_to_snapshot = [False, None]
|
||||||
|
extra_specs = [None, {'replication_type': 'dr', 'foo': 'bar'}]
|
||||||
|
|
||||||
|
snapshot_false_combos = list(itertools.product(public, dhss, snapshot,
|
||||||
|
create_from_snapshot,
|
||||||
|
revert_to_snapshot,
|
||||||
|
extra_specs))
|
||||||
|
|
||||||
|
return snapshot_none_combos + snapshot_true_combos + snapshot_false_combos
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TypesTest(utils.TestCase):
|
class TypesTest(utils.TestCase):
|
||||||
|
|
||||||
@ -146,9 +187,12 @@ class TypesTest(utils.TestCase):
|
|||||||
self.assertEqual("fake", result)
|
self.assertEqual("fake", result)
|
||||||
|
|
||||||
def _add_standard_extra_specs_to_dict(self, extra_specs,
|
def _add_standard_extra_specs_to_dict(self, extra_specs,
|
||||||
create_from_snapshot=None):
|
create_from_snapshot=None,
|
||||||
|
revert_to_snapshot=None):
|
||||||
|
|
||||||
if all(spec is None for spec in [create_from_snapshot]):
|
# Short-circuit checks to allow for extra specs to be (and remain) None
|
||||||
|
if all(spec is None for spec in [
|
||||||
|
create_from_snapshot, revert_to_snapshot]):
|
||||||
return extra_specs
|
return extra_specs
|
||||||
|
|
||||||
extra_specs = extra_specs or {}
|
extra_specs = extra_specs or {}
|
||||||
@ -156,6 +200,9 @@ class TypesTest(utils.TestCase):
|
|||||||
if create_from_snapshot is not None:
|
if create_from_snapshot is not None:
|
||||||
extra_specs['create_share_from_snapshot_support'] = (
|
extra_specs['create_share_from_snapshot_support'] = (
|
||||||
create_from_snapshot)
|
create_from_snapshot)
|
||||||
|
if revert_to_snapshot is not None:
|
||||||
|
extra_specs['revert_to_snapshot_support'] = (
|
||||||
|
revert_to_snapshot)
|
||||||
|
|
||||||
return extra_specs
|
return extra_specs
|
||||||
|
|
||||||
@ -203,6 +250,57 @@ class TypesTest(utils.TestCase):
|
|||||||
"/types", expected_body, "share_type")
|
"/types", expected_body, "share_type")
|
||||||
self.assertEqual("fake", result)
|
self.assertEqual("fake", result)
|
||||||
|
|
||||||
|
@ddt.data(*get_valid_type_create_data_2_27())
|
||||||
|
@ddt.unpack
|
||||||
|
def test_create_2_27(self, is_public, dhss, snapshot, create_from_snapshot,
|
||||||
|
revert_to_snapshot, extra_specs):
|
||||||
|
|
||||||
|
extra_specs = copy.copy(extra_specs)
|
||||||
|
extra_specs = self._add_standard_extra_specs_to_dict(
|
||||||
|
extra_specs, create_from_snapshot=create_from_snapshot,
|
||||||
|
revert_to_snapshot=revert_to_snapshot)
|
||||||
|
|
||||||
|
manager = self._get_share_types_manager("2.27")
|
||||||
|
self.mock_object(manager, '_create', mock.Mock(return_value="fake"))
|
||||||
|
|
||||||
|
result = manager.create(
|
||||||
|
'test-type-3', spec_driver_handles_share_servers=dhss,
|
||||||
|
spec_snapshot_support=snapshot,
|
||||||
|
extra_specs=extra_specs, is_public=is_public)
|
||||||
|
|
||||||
|
expected_extra_specs = dict(extra_specs or {})
|
||||||
|
expected_extra_specs["driver_handles_share_servers"] = dhss
|
||||||
|
|
||||||
|
if snapshot is None:
|
||||||
|
expected_extra_specs.pop("snapshot_support", None)
|
||||||
|
else:
|
||||||
|
expected_extra_specs["snapshot_support"] = snapshot
|
||||||
|
|
||||||
|
if create_from_snapshot is None:
|
||||||
|
expected_extra_specs.pop("create_share_from_snapshot_support",
|
||||||
|
None)
|
||||||
|
else:
|
||||||
|
expected_extra_specs["create_share_from_snapshot_support"] = (
|
||||||
|
create_from_snapshot)
|
||||||
|
|
||||||
|
if revert_to_snapshot is None:
|
||||||
|
expected_extra_specs.pop("revert_to_snapshot_support", None)
|
||||||
|
else:
|
||||||
|
expected_extra_specs["revert_to_snapshot_support"] = (
|
||||||
|
revert_to_snapshot)
|
||||||
|
|
||||||
|
expected_body = {
|
||||||
|
"share_type": {
|
||||||
|
"name": 'test-type-3',
|
||||||
|
'share_type_access:is_public': is_public,
|
||||||
|
"extra_specs": expected_extra_specs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
manager._create.assert_called_once_with(
|
||||||
|
"/types", expected_body, "share_type")
|
||||||
|
self.assertEqual("fake", result)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
(False, False, True, {'snapshot_support': True,
|
(False, False, True, {'snapshot_support': True,
|
||||||
'replication_type': 'fake_repl_type'}),
|
'replication_type': 'fake_repl_type'}),
|
||||||
|
@ -109,6 +109,10 @@ class Share(common_base.Resource):
|
|||||||
"""List instances of the specified share."""
|
"""List instances of the specified share."""
|
||||||
self.manager.list_instances(self)
|
self.manager.list_instances(self)
|
||||||
|
|
||||||
|
def revert_to_snapshot(self, snapshot):
|
||||||
|
"""Reverts a share (in place) to a snapshot."""
|
||||||
|
self.manager.revert_to_snapshot(self, snapshot)
|
||||||
|
|
||||||
|
|
||||||
class ShareManager(base.ManagerWithFind):
|
class ShareManager(base.ManagerWithFind):
|
||||||
"""Manage :class:`Share` resources."""
|
"""Manage :class:`Share` resources."""
|
||||||
@ -276,6 +280,19 @@ class ShareManager(base.ManagerWithFind):
|
|||||||
"""
|
"""
|
||||||
return self._action("unmanage", share)
|
return self._action("unmanage", share)
|
||||||
|
|
||||||
|
@api_versions.wraps("2.27")
|
||||||
|
def revert_to_snapshot(self, share, snapshot):
|
||||||
|
"""Reverts a share (in place) to a snapshot.
|
||||||
|
|
||||||
|
The snapshot must be the most recent one known to manila.
|
||||||
|
:param share: either share object or text with its ID.
|
||||||
|
:param snapshot: either snapshot object or text with its ID.
|
||||||
|
"""
|
||||||
|
|
||||||
|
snapshot_id = common_base.getid(snapshot)
|
||||||
|
info = {'snapshot_id': snapshot_id}
|
||||||
|
return self._action('revert', share, info=info)
|
||||||
|
|
||||||
def get(self, share):
|
def get(self, share):
|
||||||
"""Get a share.
|
"""Get a share.
|
||||||
|
|
||||||
|
@ -1034,6 +1034,19 @@ def do_snapshot_unmanage(cs, args):
|
|||||||
"specified snapshots.")
|
"specified snapshots.")
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.27")
|
||||||
|
@cliutils.arg(
|
||||||
|
'snapshot',
|
||||||
|
metavar='<snapshot>',
|
||||||
|
help='Name or ID of the snapshot to restore. The snapshot must be the '
|
||||||
|
'most recent one known to manila.')
|
||||||
|
def do_revert_to_snapshot(cs, args):
|
||||||
|
"""Revert a share to the specified snapshot."""
|
||||||
|
snapshot = _find_share_snapshot(cs, args.snapshot)
|
||||||
|
share = _find_share(cs, snapshot.share_id)
|
||||||
|
share.revert_to_snapshot(snapshot)
|
||||||
|
|
||||||
|
|
||||||
@cliutils.arg(
|
@cliutils.arg(
|
||||||
'share',
|
'share',
|
||||||
metavar='<share>',
|
metavar='<share>',
|
||||||
@ -3117,6 +3130,13 @@ def do_extra_specs_list(cs, args):
|
|||||||
action='single_alias',
|
action='single_alias',
|
||||||
help="Boolean extra spec used for filtering of back ends by their "
|
help="Boolean extra spec used for filtering of back ends by their "
|
||||||
"capability to create shares from snapshots.")
|
"capability to create shares from snapshots.")
|
||||||
|
@cliutils.arg(
|
||||||
|
'--revert_to_snapshot_support',
|
||||||
|
'--revert-to-snapshot-support',
|
||||||
|
metavar='<revert_to_snapshot_support>',
|
||||||
|
action='single_alias',
|
||||||
|
help="Boolean extra spec used for filtering of back ends by their "
|
||||||
|
"capability to revert shares to snapshots. (Default is False).")
|
||||||
@cliutils.arg(
|
@cliutils.arg(
|
||||||
'--extra-specs',
|
'--extra-specs',
|
||||||
'--extra_specs', # alias
|
'--extra_specs', # alias
|
||||||
@ -3157,7 +3177,11 @@ def do_type_create(cs, args):
|
|||||||
"set via positional argument.")
|
"set via positional argument.")
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
boolean_keys = ('snapshot_support', 'create_share_from_snapshot_support')
|
boolean_keys = (
|
||||||
|
'snapshot_support',
|
||||||
|
'create_share_from_snapshot_support',
|
||||||
|
'revert_to_snapshot_support',
|
||||||
|
)
|
||||||
for key in boolean_keys:
|
for key in boolean_keys:
|
||||||
value = getattr(args, key)
|
value = getattr(args, key)
|
||||||
|
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Added support for the revert-to-snapshot feature.
|
Loading…
x
Reference in New Issue
Block a user