Merge "Only check service availability during validation"
This commit is contained in:
commit
9b6b65b3d1
@ -171,12 +171,6 @@ class Resource(status.ResourceStatus):
|
||||
|
||||
assert issubclass(ResourceClass, Resource)
|
||||
|
||||
if not stack.service_check_defer:
|
||||
ResourceClass._validate_service_availability(
|
||||
stack.context,
|
||||
definition.resource_type
|
||||
)
|
||||
|
||||
return super(Resource, cls).__new__(ResourceClass)
|
||||
|
||||
@classmethod
|
||||
@ -1748,7 +1742,6 @@ class Resource(status.ResourceStatus):
|
||||
in an overridden validate() such as accessing properties
|
||||
may not work.
|
||||
"""
|
||||
if self.stack.service_check_defer:
|
||||
self._validate_service_availability(
|
||||
self.stack.context,
|
||||
self.t.resource_type
|
||||
|
@ -1230,7 +1230,6 @@ class EngineService(service.ServiceBase):
|
||||
msg = _("No Template provided.")
|
||||
return webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
service_check_defer = False
|
||||
if ignorable_errors:
|
||||
invalid_codes = (set(ignorable_errors) -
|
||||
set(exception.ERROR_CODE_MAP.keys()))
|
||||
@ -1239,8 +1238,6 @@ class EngineService(service.ServiceBase):
|
||||
list(invalid_codes))
|
||||
return webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
service_check_defer = True
|
||||
|
||||
tmpl = templatem.Template(template, files=files)
|
||||
env_util.merge_environments(environment_files, files, params,
|
||||
tmpl.all_param_schemata(files))
|
||||
@ -1252,8 +1249,7 @@ class EngineService(service.ServiceBase):
|
||||
|
||||
stack_name = 'dummy'
|
||||
stack = parser.Stack(cnxt, stack_name, tmpl,
|
||||
strict_validate=False,
|
||||
service_check_defer=service_check_defer)
|
||||
strict_validate=False)
|
||||
try:
|
||||
stack.validate(ignorable_errors=ignorable_errors,
|
||||
validate_res_tmpl_only=True)
|
||||
@ -2386,7 +2382,6 @@ class EngineService(service.ServiceBase):
|
||||
try:
|
||||
for st in stacks:
|
||||
if not st.convergence:
|
||||
st.service_check_defer = True
|
||||
st.migrate_to_convergence()
|
||||
sess.commit()
|
||||
except Exception:
|
||||
@ -2465,8 +2460,7 @@ class EngineService(service.ServiceBase):
|
||||
lock.release()
|
||||
continue
|
||||
|
||||
stk = parser.Stack.load(cnxt, stack=s,
|
||||
service_check_defer=True)
|
||||
stk = parser.Stack.load(cnxt, stack=s)
|
||||
LOG.info('Engine %(engine)s went down when stack '
|
||||
'%(stack_id)s was in action %(action)s',
|
||||
{'engine': engine_id, 'action': stk.action,
|
||||
|
@ -121,7 +121,7 @@ class Stack(collections.Mapping):
|
||||
nested_depth=0, strict_validate=True, convergence=False,
|
||||
current_traversal=None, tags=None, prev_raw_template_id=None,
|
||||
current_deps=None, cache_data=None,
|
||||
service_check_defer=False, deleted_time=None):
|
||||
deleted_time=None):
|
||||
|
||||
"""Initialise the Stack.
|
||||
|
||||
@ -188,12 +188,6 @@ class Stack(collections.Mapping):
|
||||
# for not-yet-created resources (which return None)
|
||||
self.strict_validate = strict_validate
|
||||
|
||||
# service_check_defer can be used to defer the validation of service
|
||||
# availability for a given resource, which helps to create the resource
|
||||
# dependency tree completely when respective service is not available,
|
||||
# especially during template_validate
|
||||
self.service_check_defer = service_check_defer
|
||||
|
||||
self.in_convergence_check = cache_data is not None
|
||||
|
||||
if use_stored_context:
|
||||
@ -520,7 +514,7 @@ class Stack(collections.Mapping):
|
||||
@classmethod
|
||||
def load(cls, context, stack_id=None, stack=None, show_deleted=True,
|
||||
use_stored_context=False, force_reload=False, cache_data=None,
|
||||
service_check_defer=False, load_template=True):
|
||||
load_template=True):
|
||||
"""Retrieve a Stack from the database."""
|
||||
if stack is None:
|
||||
stack = stack_object.Stack.get_by_id(
|
||||
@ -537,7 +531,6 @@ class Stack(collections.Mapping):
|
||||
return cls._from_db(context, stack,
|
||||
use_stored_context=use_stored_context,
|
||||
cache_data=cache_data,
|
||||
service_check_defer=service_check_defer,
|
||||
load_template=load_template)
|
||||
|
||||
@classmethod
|
||||
@ -572,7 +565,7 @@ class Stack(collections.Mapping):
|
||||
@classmethod
|
||||
def _from_db(cls, context, stack,
|
||||
use_stored_context=False, cache_data=None,
|
||||
service_check_defer=False, load_template=True):
|
||||
load_template=True):
|
||||
if load_template:
|
||||
template = tmpl.Template.load(
|
||||
context, stack.raw_template_id, stack.raw_template)
|
||||
@ -596,8 +589,7 @@ class Stack(collections.Mapping):
|
||||
prev_raw_template_id=stack.prev_raw_template_id,
|
||||
current_deps=stack.current_deps, cache_data=cache_data,
|
||||
nested_depth=stack.nested_depth,
|
||||
deleted_time=stack.deleted_at,
|
||||
service_check_defer=service_check_defer)
|
||||
deleted_time=stack.deleted_at)
|
||||
|
||||
def get_kwargs_for_cloning(self, keep_status=False, only_db=False):
|
||||
"""Get common kwargs for calling Stack() for cloning.
|
||||
|
@ -301,11 +301,15 @@ class ResourceWithAttributeType(GenericResource):
|
||||
class ResourceWithDefaultClientName(resource.Resource):
|
||||
default_client_name = 'sample'
|
||||
|
||||
properties_schema = {}
|
||||
|
||||
|
||||
class ResourceWithDefaultClientNameExt(resource.Resource):
|
||||
default_client_name = 'sample'
|
||||
required_service_extension = 'foo'
|
||||
|
||||
properties_schema = {}
|
||||
|
||||
|
||||
class ResourceWithFnGetAttType(GenericResource):
|
||||
def get_attribute(self, name):
|
||||
|
@ -147,6 +147,9 @@ class L7PolicyTest(common.HeatTestCase):
|
||||
self.assertTrue(self.l7policy.check_create_complete(props))
|
||||
|
||||
def test_create_missing_properties(self):
|
||||
self.patchobject(l7policy.L7Policy, 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
for prop in ('action', 'listener'):
|
||||
tmpl = yaml.load(inline_templates.L7POLICY_TEMPLATE)
|
||||
del tmpl['resources']['l7policy']['properties'][prop]
|
||||
|
@ -96,6 +96,9 @@ class L7RuleTest(common.HeatTestCase):
|
||||
self.assertTrue(self.l7rule.check_create_complete(props))
|
||||
|
||||
def test_create_missing_properties(self):
|
||||
self.patchobject(l7rule.L7Rule, 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
for prop in ('l7policy', 'type', 'compare_type', 'value'):
|
||||
tmpl = yaml.load(inline_templates.L7RULE_TEMPLATE)
|
||||
del tmpl['resources']['l7rule']['properties'][prop]
|
||||
|
@ -50,6 +50,9 @@ class ListenerTest(common.HeatTestCase):
|
||||
return_value=self.neutron_client)
|
||||
|
||||
def test_validate_terminated_https(self):
|
||||
self.patchobject(listener.Listener, 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
tmpl = yaml.load(inline_templates.LISTENER_TEMPLATE)
|
||||
props = tmpl['resources']['listener']['properties']
|
||||
props['protocol'] = 'TERMINATED_HTTPS'
|
||||
|
@ -113,6 +113,9 @@ class PoolTest(common.HeatTestCase):
|
||||
self.assertTrue(self.pool.check_create_complete(props))
|
||||
|
||||
def test_create_missing_properties(self):
|
||||
self.patchobject(pool.Pool, 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
for prop in ('lb_algorithm', 'listener', 'protocol'):
|
||||
tmpl = yaml.load(inline_templates.POOL_TEMPLATE)
|
||||
del tmpl['resources']['pool']['properties']['loadbalancer']
|
||||
|
@ -67,6 +67,10 @@ class RBACPolicyTest(common.HeatTestCase):
|
||||
msg = ("Invalid action %(action)s for object type %(type)s." %
|
||||
{'action': invalid_action,
|
||||
'type': obj_type})
|
||||
|
||||
self.patchobject(type(self.rbac), 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
self.assertRaisesRegex(exception.StackValidationFailed, msg,
|
||||
self.rbac.validate)
|
||||
|
||||
@ -86,11 +90,19 @@ class RBACPolicyTest(common.HeatTestCase):
|
||||
tpl['resources']['rbac']['properties']['object_type'] = 'networks'
|
||||
self._create_stack(tmpl=yaml.safe_dump(tpl))
|
||||
msg = "Invalid object_type: networks. "
|
||||
|
||||
self.patchobject(type(self.rbac), 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
self.assertRaisesRegex(exception.StackValidationFailed, msg,
|
||||
self.rbac.validate)
|
||||
|
||||
def test_validate_object_id_reference(self):
|
||||
self._create_stack(tmpl=inline_templates.RBAC_REFERENCE_TEMPLATE)
|
||||
|
||||
self.patchobject(type(self.rbac), 'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
# won't check the object_id, so validate() is success
|
||||
self.rbac.validate()
|
||||
|
||||
|
@ -63,6 +63,10 @@ class SecurityGroupRuleTest(common.HeatTestCase):
|
||||
expected)
|
||||
|
||||
def test_validate_conflict_props(self):
|
||||
self.patchobject(security_group_rule.SecurityGroupRule,
|
||||
'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
tmpl = inline_templates.SECURITY_GROUP_RULE_TEMPLATE
|
||||
tmpl += ' remote_ip_prefix: "123"'
|
||||
self._create_stack(tmpl=tmpl)
|
||||
@ -71,6 +75,10 @@ class SecurityGroupRuleTest(common.HeatTestCase):
|
||||
self.sg_rule.validate)
|
||||
|
||||
def test_validate_max_port_less_than_min_port(self):
|
||||
self.patchobject(security_group_rule.SecurityGroupRule,
|
||||
'is_service_available',
|
||||
return_value=(True, None))
|
||||
|
||||
tmpl = inline_templates.SECURITY_GROUP_RULE_TEMPLATE
|
||||
tmpl += ' port_range_max: 50'
|
||||
self._create_stack(tmpl=tmpl)
|
||||
|
@ -1337,8 +1337,7 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.call(self.ctx, 'bar'),
|
||||
])
|
||||
mock_stack_load.assert_called_once_with(self.ctx,
|
||||
stack=db_stack,
|
||||
service_check_defer=True)
|
||||
stack=db_stack)
|
||||
self.assertTrue(lock2.release.called)
|
||||
reason = ('Engine went down during stack %s' % fake_stack.action)
|
||||
mock_thread.start_with_acquired_lock.assert_called_once_with(
|
||||
|
@ -225,14 +225,12 @@ class WaitConditionMetadataUpdateTest(common.HeatTestCase):
|
||||
@mock.patch.object(glance.GlanceClientPlugin, 'find_image_by_name_or_id')
|
||||
@mock.patch.object(instance.Instance, 'handle_create')
|
||||
@mock.patch.object(instance.Instance, 'check_create_complete')
|
||||
@mock.patch.object(instance.Instance, 'is_service_available')
|
||||
@mock.patch.object(scheduler.TaskRunner, '_sleep')
|
||||
@mock.patch.object(WaitConditionHandle, 'identifier')
|
||||
def test_wait_metadata(self, mock_identifier, mock_sleep, mock_available,
|
||||
def test_wait_metadata(self, mock_identifier, mock_sleep,
|
||||
mock_check, mock_handle, *args):
|
||||
"""Tests a wait condition metadata update after a signal call."""
|
||||
|
||||
mock_available.return_value = (True, None)
|
||||
# Setup Stack
|
||||
temp = template_format.parse(TEST_TEMPLATE_WAIT_CONDITION)
|
||||
template = tmpl.Template(temp)
|
||||
@ -298,7 +296,6 @@ class WaitConditionMetadataUpdateTest(common.HeatTestCase):
|
||||
jsonutils.loads(inst.metadata_get(refresh=True)['test']))
|
||||
|
||||
# Verify outgoing calls
|
||||
self.assertGreater(mock_available.call_count, 0)
|
||||
self.assertEqual(2, mock_handle.call_count)
|
||||
self.assertEqual(2, mock_check.call_count)
|
||||
|
||||
|
@ -3909,15 +3909,15 @@ class ResourceAvailabilityTest(common.HeatTestCase):
|
||||
resource_type='UnavailableResourceType')
|
||||
|
||||
mock_stack = mock.MagicMock()
|
||||
mock_stack.service_check_defer = False
|
||||
mock_stack.in_convergence_check = False
|
||||
mock_stack.db_resource_get.return_value = None
|
||||
rsrc = generic_rsrc.ResourceWithDefaultClientName('test_res',
|
||||
definition,
|
||||
mock_stack)
|
||||
|
||||
ex = self.assertRaises(
|
||||
exception.ResourceTypeUnavailable,
|
||||
generic_rsrc.ResourceWithDefaultClientName.__new__,
|
||||
cls=generic_rsrc.ResourceWithDefaultClientName,
|
||||
name='test_stack',
|
||||
definition=definition,
|
||||
stack=mock_stack)
|
||||
rsrc.validate_template)
|
||||
|
||||
msg = ('HEAT-E99001 Service sample is not available for resource '
|
||||
'type UnavailableResourceType, reason: '
|
||||
@ -3945,15 +3945,15 @@ class ResourceAvailabilityTest(common.HeatTestCase):
|
||||
resource_type='UnavailableResourceType')
|
||||
|
||||
mock_stack = mock.MagicMock()
|
||||
mock_stack.service_check_defer = False
|
||||
mock_stack.in_convergence_check = False
|
||||
mock_stack.db_resource_get.return_value = None
|
||||
rsrc = generic_rsrc.ResourceWithDefaultClientName('test_res',
|
||||
definition,
|
||||
mock_stack)
|
||||
|
||||
ex = self.assertRaises(
|
||||
exception.ResourceTypeUnavailable,
|
||||
generic_rsrc.ResourceWithDefaultClientName.__new__,
|
||||
cls=generic_rsrc.ResourceWithDefaultClientName,
|
||||
name='test_stack',
|
||||
definition=definition,
|
||||
stack=mock_stack)
|
||||
rsrc.validate_template)
|
||||
|
||||
msg = ('HEAT-E99001 Service sample is not available for resource '
|
||||
'type UnavailableResourceType, reason: '
|
||||
|
@ -454,8 +454,7 @@ class StackTest(common.HeatTestCase):
|
||||
prev_raw_template_id=None,
|
||||
current_deps=None, cache_data=None,
|
||||
nested_depth=0,
|
||||
deleted_time=None,
|
||||
service_check_defer=False)
|
||||
deleted_time=None)
|
||||
|
||||
self.m.ReplayAll()
|
||||
stack.Stack.load(self.ctx, stack_id=self.stack.id)
|
||||
|
Loading…
Reference in New Issue
Block a user