205 lines
8.6 KiB
Python
205 lines
8.6 KiB
Python
#
|
|
# 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.
|
|
|
|
import mock
|
|
import six
|
|
|
|
from heat.common import exception
|
|
from heat.common import short_id
|
|
from heat.common import template_format
|
|
from heat.engine.clients.os import nova
|
|
from heat.engine import node_data
|
|
from heat.engine import scheduler
|
|
from heat.tests.autoscaling import inline_templates
|
|
from heat.tests import common
|
|
from heat.tests import utils
|
|
|
|
|
|
class LaunchConfigurationTest(common.HeatTestCase):
|
|
def validate_launch_config(self, stack, lc_name='LaunchConfig'):
|
|
# create the launch configuration resource
|
|
conf = stack[lc_name]
|
|
self.assertIsNone(conf.validate())
|
|
scheduler.TaskRunner(conf.create)()
|
|
self.assertEqual((conf.CREATE, conf.COMPLETE), conf.state)
|
|
# check bdm in configuration
|
|
self.assertIsNotNone(conf.properties['BlockDeviceMappings'])
|
|
|
|
def test_launch_config_get_ref_by_id(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params)
|
|
rsrc = stack['LaunchConfig']
|
|
self.stub_ImageConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
self.stub_SnapshotConstraint_validate()
|
|
|
|
self.assertIsNone(rsrc.validate())
|
|
scheduler.TaskRunner(rsrc.create)()
|
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
|
|
|
# use physical_resource_name when rsrc.id is not None
|
|
self.assertIsNotNone(rsrc.uuid)
|
|
expected = '%s-%s-%s' % (rsrc.stack.name,
|
|
rsrc.name,
|
|
short_id.get_id(rsrc.uuid))
|
|
self.assertEqual(expected, rsrc.FnGetRefId())
|
|
|
|
# otherwise use parent method
|
|
rsrc.id = None
|
|
self.assertIsNone(rsrc.resource_id)
|
|
self.assertEqual('LaunchConfig', rsrc.FnGetRefId())
|
|
|
|
def test_launch_config_refid_convergence_cache_data(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
cache_data = {'LaunchConfig': node_data.NodeData.from_dict({
|
|
'uuid': mock.ANY,
|
|
'id': mock.ANY,
|
|
'action': 'CREATE',
|
|
'status': 'COMPLETE',
|
|
'reference_id': 'convg_xyz'
|
|
})}
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params,
|
|
cache_data=cache_data)
|
|
rsrc = stack.defn['LaunchConfig']
|
|
self.assertEqual('convg_xyz', rsrc.FnGetRefId())
|
|
|
|
def test_launch_config_create_with_instanceid(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
lcp['InstanceId'] = '5678'
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params)
|
|
rsrc = stack['LaunchConfig']
|
|
# ImageId, InstanceType and BlockDeviceMappings keep the lc's values
|
|
# KeyName and SecurityGroups are derived from the instance
|
|
lc_props = {
|
|
'ImageId': 'foo',
|
|
'InstanceType': 'bar',
|
|
'BlockDeviceMappings': lcp['BlockDeviceMappings'],
|
|
'KeyName': 'hth_keypair',
|
|
'SecurityGroups': ['hth_test']
|
|
}
|
|
rsrc.rebuild_lc_properties = mock.Mock(return_value=lc_props)
|
|
self.stub_ImageConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
self.stub_SnapshotConstraint_validate()
|
|
self.stub_ServerConstraint_validate()
|
|
|
|
self.assertIsNone(rsrc.validate())
|
|
scheduler.TaskRunner(rsrc.create)()
|
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
|
|
|
def test_lc_validate_without_InstanceId_and_ImageId(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
lcp.pop('ImageId')
|
|
stack = utils.parse_stack(t, inline_templates.as_params)
|
|
rsrc = stack['LaunchConfig']
|
|
self.stub_SnapshotConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
|
|
e = self.assertRaises(exception.StackValidationFailed,
|
|
rsrc.validate)
|
|
ex_msg = ('If without InstanceId, '
|
|
'ImageId and InstanceType are required.')
|
|
self.assertIn(ex_msg, six.text_type(e))
|
|
|
|
def test_lc_validate_without_InstanceId_and_InstanceType(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
lcp.pop('InstanceType')
|
|
stack = utils.parse_stack(t, inline_templates.as_params)
|
|
rsrc = stack['LaunchConfig']
|
|
self.stub_SnapshotConstraint_validate()
|
|
self.stub_ImageConstraint_validate()
|
|
|
|
e = self.assertRaises(exception.StackValidationFailed,
|
|
rsrc.validate)
|
|
ex_msg = ('If without InstanceId, '
|
|
'ImageId and InstanceType are required.')
|
|
self.assertIn(ex_msg, six.text_type(e))
|
|
|
|
def test_launch_config_create_with_instanceid_not_found(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
lcp['InstanceId'] = '5678'
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params)
|
|
rsrc = stack['LaunchConfig']
|
|
self.stub_SnapshotConstraint_validate()
|
|
self.stub_ImageConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
|
|
self.patchobject(nova.NovaClientPlugin, 'get_server',
|
|
side_effect=exception.EntityNotFound(
|
|
entity='Server', name='5678'))
|
|
msg = ("Property error: "
|
|
"Resources.LaunchConfig.Properties.InstanceId: "
|
|
"Error validating value '5678': The Server (5678) "
|
|
"could not be found.")
|
|
|
|
exc = self.assertRaises(exception.StackValidationFailed,
|
|
rsrc.validate)
|
|
self.assertIn(msg, six.text_type(exc))
|
|
|
|
def test_validate_BlockDeviceMappings_without_Ebs_property(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
bdm = [{'DeviceName': 'vdb'}]
|
|
lcp['BlockDeviceMappings'] = bdm
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params)
|
|
|
|
self.stub_ImageConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
|
|
e = self.assertRaises(exception.StackValidationFailed,
|
|
self.validate_launch_config, stack)
|
|
|
|
self.assertIn("Ebs is missing, this is required",
|
|
six.text_type(e))
|
|
|
|
def test_validate_BlockDeviceMappings_without_SnapshotId_property(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
bdm = [{'DeviceName': 'vdb',
|
|
'Ebs': {'VolumeSize': '1'}}]
|
|
lcp['BlockDeviceMappings'] = bdm
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params)
|
|
|
|
self.stub_ImageConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
|
|
e = self.assertRaises(exception.StackValidationFailed,
|
|
self.validate_launch_config, stack)
|
|
|
|
self.assertIn("SnapshotId is missing, this is required",
|
|
six.text_type(e))
|
|
|
|
def test_validate_BlockDeviceMappings_without_DeviceName_property(self):
|
|
t = template_format.parse(inline_templates.as_template)
|
|
lcp = t['Resources']['LaunchConfig']['Properties']
|
|
bdm = [{'Ebs': {'SnapshotId': '1234',
|
|
'VolumeSize': '1'}}]
|
|
lcp['BlockDeviceMappings'] = bdm
|
|
stack = utils.parse_stack(t, params=inline_templates.as_params)
|
|
self.stub_ImageConstraint_validate()
|
|
self.stub_FlavorConstraint_validate()
|
|
self.stub_SnapshotConstraint_validate()
|
|
|
|
e = self.assertRaises(exception.StackValidationFailed,
|
|
self.validate_launch_config, stack)
|
|
|
|
excepted_error = (
|
|
'Property error: '
|
|
'Resources.LaunchConfig.Properties.BlockDeviceMappings[0]: '
|
|
'Property DeviceName not assigned')
|
|
self.assertIn(excepted_error, six.text_type(e))
|