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

NOTE: This conflict is because there is a new parameter
named 'id' for method:
common.raise_http_conflict_for_instance_invalid_state.

Conflicts:
        nova/api/openstack/compute/contrib/admin_actions.py
        nova/api/openstack/compute/plugins/v3/create_backup.py

Change-Id: Ic84fa9e0b9c2d7b6cf49955aa4f0d44ade2b5397
(cherry picked from commit 2b94135865)
tags/2014.2.4
Fei Long Wang 4 years ago
parent
commit
b0d8d69dbe
6 changed files with 78 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. +21
    -0
      nova/tests/api/openstack/compute/contrib/test_admin_actions.py
  5. +22
    -0
      nova/tests/api/openstack/compute/plugins/v3/test_create_backup.py
  6. +20
    -0
      nova/tests/compute/test_compute_api.py

+ 2
- 0
nova/api/openstack/compute/contrib/admin_actions.py View File

@@ -299,6 +299,8 @@ class AdminActionsController(wsgi.Controller):
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'createBackup')
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

@@ -70,6 +70,8 @@ class CreateBackupController(wsgi.Controller):
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'createBackup')
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

@@ -2048,8 +2048,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

+ 21
- 0
nova/tests/api/openstack/compute/contrib/test_admin_actions.py View File

@@ -633,6 +633,27 @@ class CreateBackupTestsV2(CommonMixin, test.NoDBTestCase):
res = self._make_request(self._make_url('fake'), body=body)
self.assertEqual(400, res.status_int)

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()

res = self._make_request(self._make_url(instance['uuid']), body)
self.assertEqual(400, res.status_int)


class ResetStateTestsV21(test.NoDBTestCase):
admin_act = admin_actions_v21

+ 22
- 0
nova/tests/api/openstack/compute/plugins/v3/test_create_backup.py View File

@@ -15,6 +15,7 @@

from nova.api.openstack import common
from nova.api.openstack.compute.plugins.v3 import create_backup
from nova import exception
from nova.openstack.common import uuidutils
from nova import test
from nova.tests.api.openstack.compute.plugins.v3 import \
@@ -259,3 +260,24 @@ class CreateBackupTests(admin_only_action_common.CommonMixin,
}
res = self._make_request(self._make_url(), body)
self.assertEqual(400, res.status_int)

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()

res = self._make_request(self._make_url(instance['uuid']), body)
self.assertEqual(400, res.status_int)

+ 20
- 0
nova/tests/compute/test_compute_api.py View File

@@ -1526,6 +1526,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)
@@ -1665,6 +1672,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):
params = dict(locked=True)
instance = self._create_instance_obj(params=params)

Loading…
Cancel
Save