Merge "Return HTTP 400 for invalid server-group uuid"
This commit is contained in:
commit
4c42235e14
|
@ -84,6 +84,7 @@ CREATE_EXCEPTIONS = {
|
||||||
exception.InstanceExists: exc.HTTPConflict,
|
exception.InstanceExists: exc.HTTPConflict,
|
||||||
exception.NoUniqueMatch: exc.HTTPConflict,
|
exception.NoUniqueMatch: exc.HTTPConflict,
|
||||||
exception.Invalid: exc.HTTPBadRequest,
|
exception.Invalid: exc.HTTPBadRequest,
|
||||||
|
exception.InstanceGroupNotFound: exc.HTTPBadRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_EXCEPTIONS_MSGS = {
|
CREATE_EXCEPTIONS_MSGS = {
|
||||||
|
|
|
@ -19,9 +19,8 @@ _hints = {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'group': {
|
'group': {
|
||||||
# NOTE: The value of 'group' is stored to value which is
|
'type': 'string',
|
||||||
# defined as varchar(255) in instance_system_metadata table.
|
'format': 'uuid'
|
||||||
'type': 'string', 'maxLength': 255,
|
|
||||||
},
|
},
|
||||||
'different_host': {
|
'different_host': {
|
||||||
# NOTE: The value of 'different_host' is the set of server
|
# NOTE: The value of 'different_host' is the set of server
|
||||||
|
|
|
@ -689,7 +689,8 @@ class ServersController(wsgi.Controller):
|
||||||
exception.ImageNUMATopologyCPUOutOfRange,
|
exception.ImageNUMATopologyCPUOutOfRange,
|
||||||
exception.ImageNUMATopologyCPUDuplicates,
|
exception.ImageNUMATopologyCPUDuplicates,
|
||||||
exception.ImageNUMATopologyCPUsUnassigned,
|
exception.ImageNUMATopologyCPUsUnassigned,
|
||||||
exception.ImageNUMATopologyMemoryOutOfRange) as error:
|
exception.ImageNUMATopologyMemoryOutOfRange,
|
||||||
|
exception.InstanceGroupNotFound) as error:
|
||||||
raise exc.HTTPBadRequest(explanation=error.format_message())
|
raise exc.HTTPBadRequest(explanation=error.format_message())
|
||||||
except (exception.PortInUse,
|
except (exception.PortInUse,
|
||||||
exception.InstanceExists,
|
exception.InstanceExists,
|
||||||
|
|
|
@ -1031,6 +1031,8 @@ class API(base.Base):
|
||||||
if not group_hint:
|
if not group_hint:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# TODO(gibi): We need to remove the following validation code when
|
||||||
|
# removing legacy v2 code.
|
||||||
if not uuidutils.is_uuid_like(group_hint):
|
if not uuidutils.is_uuid_like(group_hint):
|
||||||
msg = _('Server group scheduler hint must be a UUID.')
|
msg = _('Server group scheduler hint must be a UUID.')
|
||||||
raise exception.InvalidInput(reason=msg)
|
raise exception.InvalidInput(reason=msg)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ from nova.api.openstack.compute import servers as servers_v21
|
||||||
from nova.api.openstack import extensions
|
from nova.api.openstack import extensions
|
||||||
import nova.compute.api
|
import nova.compute.api
|
||||||
from nova.compute import flavors
|
from nova.compute import flavors
|
||||||
|
from nova import exception
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.tests.unit.api.openstack import fakes
|
from nova.tests.unit.api.openstack import fakes
|
||||||
from nova.tests.unit import fake_instance
|
from nova.tests.unit import fake_instance
|
||||||
|
@ -97,7 +99,11 @@ class SchedulerHintsTestCaseV21(test.TestCase):
|
||||||
self.assertEqual(202, res.status_int)
|
self.assertEqual(202, res.status_int)
|
||||||
|
|
||||||
def test_create_server_with_group_hint(self):
|
def test_create_server_with_group_hint(self):
|
||||||
self._test_create_server_with_hint({'group': 'foo'})
|
self._test_create_server_with_hint({'group': UUID})
|
||||||
|
|
||||||
|
def test_create_server_with_non_uuid_group_hint(self):
|
||||||
|
self._create_server_with_scheduler_hints_bad_request(
|
||||||
|
{'group': 'non-uuid'})
|
||||||
|
|
||||||
def test_create_server_with_different_host_hint(self):
|
def test_create_server_with_different_host_hint(self):
|
||||||
self._test_create_server_with_hint(
|
self._test_create_server_with_hint(
|
||||||
|
@ -160,6 +166,13 @@ class SchedulerHintsTestCaseV2(SchedulerHintsTestCaseV21):
|
||||||
# We skip this test for v2.0.
|
# We skip this test for v2.0.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@mock.patch(
|
||||||
|
'nova.api.openstack.compute.legacy_v2.servers.Controller.create')
|
||||||
|
def test_create_server_with_non_uuid_group_hint(self, mock_create):
|
||||||
|
mock_create.side_effect = exception.InvalidInput(reason='')
|
||||||
|
self._create_server_with_scheduler_hints_bad_request(
|
||||||
|
{'group': 'non-uuid'})
|
||||||
|
|
||||||
|
|
||||||
class ServersControllerCreateTestV21(test.TestCase):
|
class ServersControllerCreateTestV21(test.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -3116,6 +3116,24 @@ class ServersControllerCreateTest(test.TestCase):
|
||||||
test_group = objects.InstanceGroup.get_by_uuid(ctxt, test_group.uuid)
|
test_group = objects.InstanceGroup.get_by_uuid(ctxt, test_group.uuid)
|
||||||
self.assertIn(server['id'], test_group.members)
|
self.assertIn(server['id'], test_group.members)
|
||||||
|
|
||||||
|
def test_create_instance_with_group_hint_group_not_found(self):
|
||||||
|
def fake_instance_destroy(context, uuid, constraint):
|
||||||
|
return fakes.stub_instance(1)
|
||||||
|
|
||||||
|
self.stub_out('nova.db.instance_destroy', fake_instance_destroy)
|
||||||
|
self.body['os:scheduler_hints'] = {
|
||||||
|
'group': '5b674f73-c8cf-40ef-9965-3b6fe4b304b1'}
|
||||||
|
self.req.body = jsonutils.dump_as_bytes(self.body)
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
|
self.controller.create, self.req, body=self.body)
|
||||||
|
|
||||||
|
def test_create_instance_with_group_hint_wrong_uuid_format(self):
|
||||||
|
self.body['os:scheduler_hints'] = {
|
||||||
|
'group': 'non-uuid'}
|
||||||
|
self.req.body = jsonutils.dump_as_bytes(self.body)
|
||||||
|
self.assertRaises(exception.ValidationError,
|
||||||
|
self.controller.create, self.req, body=self.body)
|
||||||
|
|
||||||
def test_create_instance_with_neutronv2_port_in_use(self):
|
def test_create_instance_with_neutronv2_port_in_use(self):
|
||||||
network = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
|
network = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
|
||||||
port = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
port = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
||||||
|
|
|
@ -7832,9 +7832,27 @@ class ComputeAPITestCase(BaseTestCase):
|
||||||
self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show)
|
self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show)
|
||||||
|
|
||||||
inst_type = flavors.get_default_flavor()
|
inst_type = flavors.get_default_flavor()
|
||||||
self.assertRaises(exception.InvalidInput, self.compute_api.create,
|
self.assertRaises(
|
||||||
self.context, inst_type, self.fake_image['id'],
|
exception.InvalidInput,
|
||||||
scheduler_hints={'group': 'groupname'})
|
self.compute_api.create,
|
||||||
|
self.context,
|
||||||
|
inst_type,
|
||||||
|
self.fake_image['id'],
|
||||||
|
scheduler_hints={'group': 'non-uuid'})
|
||||||
|
|
||||||
|
def test_instance_create_with_group_uuid_fails_group_not_exist(self):
|
||||||
|
self.stub_out('nova.tests.unit.image.fake._FakeImageService.show',
|
||||||
|
self.fake_show)
|
||||||
|
|
||||||
|
inst_type = flavors.get_default_flavor()
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InstanceGroupNotFound,
|
||||||
|
self.compute_api.create,
|
||||||
|
self.context,
|
||||||
|
inst_type,
|
||||||
|
self.fake_image['id'],
|
||||||
|
scheduler_hints={'group':
|
||||||
|
'5b674f73-c8cf-40ef-9965-3b6fe4b304b1'})
|
||||||
|
|
||||||
def test_destroy_instance_disassociates_security_groups(self):
|
def test_destroy_instance_disassociates_security_groups(self):
|
||||||
# Make sure destroying disassociates security groups.
|
# Make sure destroying disassociates security groups.
|
||||||
|
|
Loading…
Reference in New Issue