From 8c4e0be50cb001cdbeef25e49657c38a37afa43c Mon Sep 17 00:00:00 2001 From: Jianing YANG Date: Thu, 25 Jul 2013 20:47:31 +0800 Subject: [PATCH] Returns text error when instance validation fails Since heat now is able to return parsable errors by middleware, we don't need to return jsonfied error strings here. Fixes Bug 1204582 Change-Id: Id3d68b9996ad67df0e25c6db5754f73bfa1e8830 --- heat/common/exception.py | 8 +++ heat/engine/resources/instance.py | 18 ++----- heat/tests/test_validate.py | 84 +++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/heat/common/exception.py b/heat/common/exception.py index eb236a5a38..9d61ef4545 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -278,3 +278,11 @@ class ResourceFailure(OpenstackException): class NotSupported(OpenstackException): message = _("%(feature)s is not supported.") + + +class ResourcePropertyConflict(OpenstackException): + message = _('Cannot define the following properties at the same time: %s.') + + def __init__(self, *args): + self.message = self.message % ", ".join(args) + super(ResourcePropertyConflict, self).__init__() diff --git a/heat/engine/resources/instance.py b/heat/engine/resources/instance.py index b8a2c980bd..4eab8b7eb4 100644 --- a/heat/engine/resources/instance.py +++ b/heat/engine/resources/instance.py @@ -505,26 +505,18 @@ class Instance(resource.Resource): if key_name: keypairs = self.nova().keypairs.list() if not any(k.name == key_name for k in keypairs): - return {'Error': - 'Provided KeyName is not registered with nova'} + raise exception.UserKeyPairMissing(key_name=key_name) # check validity of security groups vs. network interfaces security_groups = self._get_security_groups() if security_groups and self.properties.get('NetworkInterfaces'): - return {'Error': - 'Cannot define both SecurityGroups/SecurityGroupIds and ' - 'NetworkInterfaces properties.'} + raise exception.ResourcePropertyConflict( + 'SecurityGroups/SecurityGroupIds', + 'NetworkInterfaces') # make sure the image exists. image_identifier = self.properties['ImageId'] - try: - self._get_image_id(image_identifier) - except exception.ImageNotFound: - return {'Error': 'Image %s was not found in glance' % - image_identifier} - except exception.NoUniqueImageFound: - return {'Error': 'Multiple images were found with name %s' % - image_identifier} + self._get_image_id(image_identifier) return diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py index c815d043d6..69fb7561a4 100644 --- a/heat/tests/test_validate.py +++ b/heat/tests/test_validate.py @@ -397,6 +397,34 @@ test_unregistered_key = ''' } ''' +test_template_image = ''' +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "test.", + "Parameters" : { + + "KeyName" : { +''' + \ + '"Description" : "Name of an existing EC2' + \ + 'KeyPair to enable SSH access to the instances",' + \ + ''' + "Type" : "String" + } + }, + + "Resources" : { + "Instance": { + "Type": "AWS::EC2::Instance", + "Properties": { + "ImageId": "image_name", + "InstanceType": "m1.large", + "KeyName": { "Ref" : "KeyName" } + } + } + } + } + ''' + test_template_invalid_secgroups = ''' { "AWSTemplateFormatVersion" : "2010-09-09", @@ -700,7 +728,55 @@ class validateTest(HeatTestCase): self.m.ReplayAll() resource = stack.resources['Instance'] - self.assertNotEqual(resource.validate(), None) + self.assertRaises(exception.UserKeyPairMissing, resource.validate) + + def test_unregistered_image(self): + t = template_format.parse(test_template_image) + template = parser.Template(t) + + stack = parser.Stack(self.ctx, 'test_stack', template, + environment.Environment({'KeyName': 'test'})) + + self.m.StubOutWithMock(instances.Instance, 'nova') + instances.Instance.nova().AndReturn(self.fc) + instances.Instance.nova().AndReturn(self.fc) + self.m.ReplayAll() + + resource = stack.resources['Instance'] + self.assertRaises(exception.ImageNotFound, resource.validate) + + self.m.VerifyAll() + + def test_duplicated_image(self): + t = template_format.parse(test_template_image) + template = parser.Template(t) + + stack = parser.Stack(self.ctx, 'test_stack', template, + environment.Environment({'KeyName': 'test'})) + + class image_type(object): + + def __init__(self, id, name): + self.id = id + self.name = name + + image_list = [image_type(id='768b5464-3df5-4abf-be33-63b60f8b99d0', + name='image_name'), + image_type(id='a57384f5-690f-48e1-bf46-c4291e6c887e', + name='image_name')] + + self.m.StubOutWithMock(self.fc.images, 'list') + self.fc.images.list().AndReturn(image_list) + + self.m.StubOutWithMock(instances.Instance, 'nova') + instances.Instance.nova().AndReturn(self.fc) + instances.Instance.nova().AndReturn(self.fc) + self.m.ReplayAll() + + resource = stack.resources['Instance'] + self.assertRaises(exception.NoUniqueImageFound, resource.validate) + + self.m.VerifyAll() def test_invalid_security_groups_with_nics(self): t = template_format.parse(test_template_invalid_secgroups) @@ -713,7 +789,8 @@ class validateTest(HeatTestCase): self.m.ReplayAll() resource = stack.resources['Instance'] - self.assertNotEqual(resource.validate(), None) + self.assertRaises(exception.ResourcePropertyConflict, + resource.validate) def test_invalid_security_group_ids_with_nics(self): t = template_format.parse(test_template_invalid_secgroupids) @@ -726,7 +803,8 @@ class validateTest(HeatTestCase): self.m.ReplayAll() resource = stack.resources['Instance'] - self.assertNotEqual(resource.validate(), None) + self.assertRaises(exception.ResourcePropertyConflict, + resource.validate) def test_client_exception_from_nova_client(self): t = template_format.parse(test_template_nova_client_exception)