Browse Source

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
tags/2015.1.0rc1
Fei Long Wang 4 years ago
parent
commit
2b94135865
5 changed files with 57 additions and 2 deletions
  1. +2
    -0
      nova/api/openstack/compute/contrib/admin_actions.py
  2. +2
    -0
      nova/api/openstack/compute/plugins/v3/create_backup.py
  3. +11
    -2
      nova/compute/api.py
  4. +22
    -0
      nova/tests/unit/api/openstack/compute/contrib/test_create_backup.py
  5. +20
    -0
      nova/tests/unit/compute/test_compute_api.py

+ 2
- 0
nova/api/openstack/compute/contrib/admin_actions.py 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)


+ 2
- 0
nova/api/openstack/compute/plugins/v3/create_backup.py 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)


+ 11
- 2
nova/compute/api.py 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

+ 22
- 0
nova/tests/unit/api/openstack/compute/contrib/test_create_backup.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

+ 20
- 0
nova/tests/unit/compute/test_compute_api.py 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)

Loading…
Cancel
Save