heat/heat/tests/autoscaling/test_launch_config.py

204 lines
8.5 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 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': {
'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['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))