Raise exception when backup volume-backed instance

This patch will be backported to Juno and Icehouse so that
Nova can fail immediately to let user know that it's not
supported in that release.

Partial-Bug: #1313573

Change-Id: Ic84fa9e0b9c2d7b6cf49955aa4f0d44ade2b5397
This commit is contained in:
Fei Long Wang 2015-03-25 11:30:07 +13:00
parent 20c47ea3d5
commit 2b94135865
5 changed files with 57 additions and 2 deletions

View File

@ -289,6 +289,8 @@ class AdminActionsController(wsgi.Controller):
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'createBackup', id)
except exception.InvalidRequest as e:
raise exc.HTTPBadRequest(explanation=e.format_message())
resp = webob.Response(status_int=202)

View File

@ -69,6 +69,8 @@ class CreateBackupController(wsgi.Controller):
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'createBackup', id)
except exception.InvalidRequest as e:
raise webob.exc.HTTPBadRequest(explanation=e.format_message())
resp = webob.Response(status_int=202)

View File

@ -2120,8 +2120,17 @@ class API(base.Base):
:returns: A dict containing image metadata
"""
props_copy = dict(extra_properties, backup_type=backup_type)
image_meta = self._create_image(context, instance, name,
'backup', extra_properties=props_copy)
if self.is_volume_backed_instance(context, instance):
# TODO(flwang): The log level will be changed to INFO after
# string freeze (Liberty).
LOG.debug("It's not supported to backup volume backed instance.",
context=context, instance=instance)
raise exception.InvalidRequest()
else:
image_meta = self._create_image(context, instance,
name, 'backup',
extra_properties=props_copy)
# NOTE(comstud): Any changes to this method should also be made
# to the backup_instance() method in nova/cells/messaging.py

View File

@ -272,6 +272,28 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
self.controller._create_backup,
self.req, fakes.FAKE_UUID, body=body)
def test_backup_volume_backed_instance(self):
body = {
'createBackup': {
'name': 'BackupMe',
'backup_type': 'daily',
'rotation': 3
},
}
common.check_img_metadata_properties_quota(self.context, {})
instance = self._stub_instance_get()
instance.image_ref = None
self.compute_api.backup(self.context, instance, 'BackupMe', 'daily', 3,
extra_properties={}).AndRaise(exception.InvalidRequest())
self.mox.ReplayAll()
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller._create_backup,
self.req, instance['uuid'], body=body)
class CreateBackupTestsV2(CreateBackupTestsV21):
create_backup = create_backup_v2

View File

@ -1742,6 +1742,13 @@ class _ComputeAPIUnitTestMixIn(object):
self.mox.StubOutWithMock(self.compute_api.compute_rpcapi,
'backup_instance')
if not is_snapshot:
self.mox.StubOutWithMock(self.compute_api,
'is_volume_backed_instance')
self.compute_api.is_volume_backed_instance(self.context,
instance).AndReturn(False)
image_type = is_snapshot and 'snapshot' or 'backup'
expected_sys_meta = dict(fake_sys_meta)
@ -1885,6 +1892,19 @@ class _ComputeAPIUnitTestMixIn(object):
self._test_snapshot_and_backup(is_snapshot=False,
with_base_ref=True)
def test_backup_volume_backed_instance(self):
instance = self._create_instance_obj()
with mock.patch.object(self.compute_api,
'is_volume_backed_instance',
return_value=True) as mock_is_volume_backed:
self.assertRaises(exception.InvalidRequest,
self.compute_api.backup, self.context,
instance, 'fake-name', 'weekly',
3, extra_properties={})
mock_is_volume_backed.assert_called_once_with(self.context,
instance)
def _test_snapshot_volume_backed(self, quiesce_required, quiesce_fails,
vm_state=vm_states.ACTIVE):
params = dict(locked=True, vm_state=vm_state)