8a9c7a11e0
ServerError is being incorrectly used to report an internal error leading to an error formatting the response, as there's no body specified to the format string. Use exception.Error instead and adjust the message to make the user-visible response clearer. Fixes bug #1214457 Change-Id: I83435686170c4f40658968a35f1faa303f50f4a4
831 lines
24 KiB
Python
831 lines
24 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from testtools import skipIf
|
|
|
|
from heat.engine import clients
|
|
from heat.engine import environment
|
|
from heat.tests.v1_1 import fakes
|
|
from heat.common import exception
|
|
from heat.common import template_format
|
|
from heat.engine import resources
|
|
from heat.engine.resources import instance as instances
|
|
from heat.engine import service
|
|
from heat.openstack.common.importutils import try_import
|
|
import heat.db.api as db_api
|
|
from heat.engine import parser
|
|
from heat.tests.common import HeatTestCase
|
|
from heat.tests import utils
|
|
|
|
test_template_volumeattach = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "test.",
|
|
"Resources" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"DeletionPolicy": "Delete",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": "test_KeyName"
|
|
}
|
|
},
|
|
"DataVolume" : {
|
|
"Type" : "AWS::EC2::Volume",
|
|
"Properties" : {
|
|
"Size" : "6",
|
|
"AvailabilityZone" : "nova"
|
|
}
|
|
},
|
|
"MountPoint" : {
|
|
"Type" : "AWS::EC2::VolumeAttachment",
|
|
"Properties" : {
|
|
"InstanceId" : { "Ref" : "WikiDatabase" },
|
|
"VolumeId" : { "Ref" : "DataVolume" },
|
|
"Device" : "/dev/%s"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_ref = '''
|
|
{
|
|
"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" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" }
|
|
}
|
|
},
|
|
"DataVolume" : {
|
|
"Type" : "AWS::EC2::Volume",
|
|
"Properties" : {
|
|
"Size" : "6",
|
|
"AvailabilityZone" : "nova"
|
|
}
|
|
},
|
|
"MountPoint" : {
|
|
"Type" : "AWS::EC2::VolumeAttachment",
|
|
"Properties" : {
|
|
"InstanceId" : { "Ref" : "%s" },
|
|
"VolumeId" : { "Ref" : "DataVolume" },
|
|
"Device" : "/dev/vdb"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
test_template_findinmap_valid = '''
|
|
{
|
|
"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" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" }
|
|
}
|
|
},
|
|
"DataVolume" : {
|
|
"Type" : "AWS::EC2::Volume",
|
|
"Properties" : {
|
|
"Size" : "6",
|
|
"AvailabilityZone" : "nova"
|
|
}
|
|
},
|
|
|
|
"MountPoint" : {
|
|
"Type" : "AWS::EC2::VolumeAttachment",
|
|
"Properties" : {
|
|
"InstanceId" : { "Ref" : "WikiDatabase" },
|
|
"VolumeId" : { "Ref" : "DataVolume" },
|
|
"Device" : "/dev/vdb"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
test_template_findinmap_invalid = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "test.",
|
|
"Parameters" : {
|
|
|
|
"KeyName" : {
|
|
''' + \
|
|
'"Description" : "Name of an existing EC2 KeyPair to enable SSH ' + \
|
|
'access to the instances",' + \
|
|
''' "Type" : "String"
|
|
}
|
|
},
|
|
|
|
"Mappings" : {
|
|
"AWSInstanceType2Arch" : {
|
|
"t1.micro" : { "Arch" : "64" },
|
|
"m1.small" : { "Arch" : "64" },
|
|
"m1.medium" : { "Arch" : "64" },
|
|
"m1.large" : { "Arch" : "64" },
|
|
"m1.xlarge" : { "Arch" : "64" },
|
|
"m2.xlarge" : { "Arch" : "64" },
|
|
"m2.2xlarge" : { "Arch" : "64" },
|
|
"m2.4xlarge" : { "Arch" : "64" },
|
|
"c1.medium" : { "Arch" : "64" },
|
|
"c1.xlarge" : { "Arch" : "64" },
|
|
"cc1.4xlarge" : { "Arch" : "64HVM" },
|
|
"cc2.8xlarge" : { "Arch" : "64HVM" },
|
|
"cg1.4xlarge" : { "Arch" : "64HVM" }
|
|
}
|
|
},
|
|
"Resources" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"Properties": {
|
|
''' + \
|
|
'"ImageId" : { "Fn::FindInMap" : [ "DistroArch2AMI", { "Ref" : ' + \
|
|
'"LinuxDistribution" },' + \
|
|
'{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : ' + \
|
|
'"InstanceType" }, "Arch" ] } ] },' + \
|
|
'''
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName"}
|
|
}
|
|
},
|
|
"DataVolume" : {
|
|
"Type" : "AWS::EC2::Volume",
|
|
"Properties" : {
|
|
"Size" : "6",
|
|
"AvailabilityZone" : "nova"
|
|
}
|
|
},
|
|
|
|
"MountPoint" : {
|
|
"Type" : "AWS::EC2::VolumeAttachment",
|
|
"Properties" : {
|
|
"InstanceId" : { "Ref" : "WikiDatabase" },
|
|
"VolumeId" : { "Ref" : "DataVolume" },
|
|
"Device" : "/dev/vdb"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_invalid_resources = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "AWS CloudFormation Sample Template for xyz.",
|
|
"Parameters" : {
|
|
"InstanceType" : {
|
|
"Description" : "Defined instance type",
|
|
"Type" : "String",
|
|
"Default" : "node.ee",
|
|
"AllowedValues" : ["node.ee", "node.apache", "node.api"],
|
|
"ConstraintDescription" : "must be a valid instance type."
|
|
}
|
|
},
|
|
"Resources" : {
|
|
"Type" : "AWS::EC2::Instance",
|
|
"Metadata" : {
|
|
},
|
|
"Properties" : {
|
|
"ImageId" : { "Ref" : "centos-6.4-20130701-0" },
|
|
"InstanceType" : { "Ref" : "InstanceType" }
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_invalid_property = '''
|
|
{
|
|
"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" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" },
|
|
"UnknownProperty": "unknown"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_unimplemented_property = '''
|
|
{
|
|
"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" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" },
|
|
"SourceDestCheck": "false"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_invalid_deletion_policy = '''
|
|
{
|
|
"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" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"DeletionPolicy": "Destroy",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_snapshot_deletion_policy = '''
|
|
{
|
|
"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" : {
|
|
"WikiDatabase": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"DeletionPolicy": "Snapshot",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_volume_snapshot = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "test.",
|
|
"Resources" : {
|
|
"DataVolume" : {
|
|
"Type" : "AWS::EC2::Volume",
|
|
"DeletionPolicy": "Snapshot",
|
|
"Properties" : {
|
|
"Size" : "6",
|
|
"AvailabilityZone" : "nova"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_unregistered_key = '''
|
|
{
|
|
"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_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",
|
|
"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" },
|
|
"SecurityGroups": [ "default" ],
|
|
"NetworkInterfaces": [ "mgmt", "data" ]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_invalid_secgroupids = '''
|
|
{
|
|
"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" },
|
|
"SecurityGroupIds": [ "default" ],
|
|
"NetworkInterfaces": [ "mgmt", "data" ]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_nova_client_exception = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "test.",
|
|
"Resources" : {
|
|
"Instance": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"DeletionPolicy": "Delete",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
test_template_unique_logical_name = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "test.",
|
|
"Parameters" : {
|
|
|
|
"KeyName" : {
|
|
''' + \
|
|
'"Description" : "Name of an existing EC2' + \
|
|
'KeyPair to enable SSH access to the instances",' + \
|
|
'''
|
|
"Type" : "String"
|
|
},
|
|
"AName" : {
|
|
''' + \
|
|
'"Description" : "Name of an existing EC2' + \
|
|
'KeyPair to enable SSH access to the instances",' + \
|
|
'''
|
|
"Type" : "String"
|
|
}
|
|
},
|
|
|
|
"Resources" : {
|
|
"AName": {
|
|
"Type": "AWS::EC2::Instance",
|
|
"Properties": {
|
|
"ImageId": "image_name",
|
|
"InstanceType": "m1.large",
|
|
"KeyName": { "Ref" : "KeyName" },
|
|
"NetworkInterfaces": [ "mgmt", "data" ]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
|
|
class validateTest(HeatTestCase):
|
|
def setUp(self):
|
|
super(validateTest, self).setUp()
|
|
resources.initialise()
|
|
self.fc = fakes.FakeClient()
|
|
resources.initialise()
|
|
utils.setup_dummy_db()
|
|
self.ctx = utils.dummy_context()
|
|
|
|
def test_validate_volumeattach_valid(self):
|
|
t = template_format.parse(test_template_volumeattach % 'vdq')
|
|
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t))
|
|
|
|
self.m.StubOutWithMock(db_api, 'resource_get_by_name_and_stack')
|
|
db_api.resource_get_by_name_and_stack(None, 'test_resource_name',
|
|
stack).AndReturn(None)
|
|
|
|
self.m.ReplayAll()
|
|
volumeattach = stack.resources['MountPoint']
|
|
self.assertTrue(volumeattach.validate() is None)
|
|
|
|
def test_validate_volumeattach_invalid(self):
|
|
t = template_format.parse(test_template_volumeattach % 'sda')
|
|
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t))
|
|
|
|
self.m.StubOutWithMock(db_api, 'resource_get_by_name_and_stack')
|
|
db_api.resource_get_by_name_and_stack(None, 'test_resource_name',
|
|
stack).AndReturn(None)
|
|
|
|
self.m.ReplayAll()
|
|
volumeattach = stack.resources['MountPoint']
|
|
self.assertRaises(exception.StackValidationFailed,
|
|
volumeattach.validate)
|
|
|
|
def test_validate_ref_valid(self):
|
|
t = template_format.parse(test_template_ref % 'WikiDatabase')
|
|
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res['Description'], 'test.')
|
|
|
|
def test_validate_hot_valid(self):
|
|
t = template_format.parse(
|
|
"""
|
|
heat_template_version: 2013-05-23
|
|
description: test.
|
|
resources:
|
|
my_instance:
|
|
type: AWS::EC2::Instance
|
|
""")
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res['Description'], 'test.')
|
|
|
|
def test_validate_ref_invalid(self):
|
|
t = template_format.parse(test_template_ref % 'WikiDatabasez')
|
|
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertNotEqual(res['Description'], 'Successfully validated')
|
|
|
|
def test_validate_findinmap_valid(self):
|
|
t = template_format.parse(test_template_findinmap_valid)
|
|
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res['Description'], 'test.')
|
|
|
|
def test_validate_findinmap_invalid(self):
|
|
t = template_format.parse(test_template_findinmap_invalid)
|
|
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertNotEqual(res['Description'], 'Successfully validated')
|
|
|
|
def test_validate_parameters(self):
|
|
t = template_format.parse(test_template_ref % 'WikiDatabase')
|
|
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res['Parameters'], {'KeyName': {
|
|
'Type': 'String',
|
|
'Description': 'Name of an existing EC2KeyPair to enable SSH '
|
|
'access to the instances'}})
|
|
|
|
def test_validate_properties(self):
|
|
t = template_format.parse(test_template_invalid_property)
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res, {'Error': 'Unknown Property UnknownProperty'})
|
|
|
|
def test_invalid_resources(self):
|
|
t = template_format.parse(test_template_invalid_resources)
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual({'Error': 'Resources must contain Resource. '
|
|
'Found a [string] instead'},
|
|
res)
|
|
|
|
def test_unimplemented_property(self):
|
|
t = template_format.parse(test_template_unimplemented_property)
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(
|
|
res,
|
|
{'Error': 'Property SourceDestCheck not implemented yet'})
|
|
|
|
def test_invalid_deletion_policy(self):
|
|
t = template_format.parse(test_template_invalid_deletion_policy)
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res, {'Error': 'Invalid DeletionPolicy Destroy'})
|
|
|
|
def test_snapshot_deletion_policy(self):
|
|
t = template_format.parse(test_template_snapshot_deletion_policy)
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(
|
|
res, {'Error': 'Snapshot DeletionPolicy not supported'})
|
|
|
|
@skipIf(try_import('cinderclient.v1.volume_backups') is None,
|
|
'unable to import volume_backups')
|
|
def test_volume_snapshot_deletion_policy(self):
|
|
t = template_format.parse(test_template_volume_snapshot)
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
engine = service.EngineService('a', 't')
|
|
res = dict(engine.validate_template(None, t))
|
|
self.assertEqual(res, {'Description': u'test.', 'Parameters': {}})
|
|
|
|
def test_unregistered_key(self):
|
|
t = template_format.parse(test_unregistered_key)
|
|
template = parser.Template(t)
|
|
params = {'KeyName': 'not_registered'}
|
|
stack = parser.Stack(self.ctx, 'test_stack', template,
|
|
environment.Environment(params))
|
|
|
|
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.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)
|
|
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)
|
|
self.m.ReplayAll()
|
|
|
|
resource = stack.resources['Instance']
|
|
self.assertRaises(exception.ResourcePropertyConflict,
|
|
resource.validate)
|
|
|
|
def test_invalid_security_group_ids_with_nics(self):
|
|
t = template_format.parse(test_template_invalid_secgroupids)
|
|
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)
|
|
self.m.ReplayAll()
|
|
|
|
resource = stack.resources['Instance']
|
|
self.assertRaises(exception.ResourcePropertyConflict,
|
|
resource.validate)
|
|
|
|
def test_client_exception_from_nova_client(self):
|
|
t = template_format.parse(test_template_nova_client_exception)
|
|
template = parser.Template(t)
|
|
stack = parser.Stack(self.ctx, 'test_stack', template)
|
|
|
|
self.m.StubOutWithMock(self.fc.images, 'list')
|
|
self.fc.images.list()\
|
|
.AndRaise(clients.novaclient.exceptions.ClientException(500))
|
|
self.m.StubOutWithMock(instances.Instance, 'nova')
|
|
instances.Instance.nova().AndReturn(self.fc)
|
|
self.m.ReplayAll()
|
|
|
|
self.assertRaises(exception.Error, stack.validate)
|
|
self.m.VerifyAll()
|
|
|
|
def test_validate_unique_logical_name(self):
|
|
t = template_format.parse(test_template_unique_logical_name)
|
|
template = parser.Template(t)
|
|
stack = parser.Stack(self.ctx, 'test_stack', template,
|
|
environment.Environment({'AName': 'test',
|
|
'KeyName': 'test'}))
|
|
|
|
self.assertRaises(exception.StackValidationFailed, stack.validate)
|