970ac9fac1
Fixes StackWatchService to use Stack and WatchRule objects in places of db api. Implements blueprint versioned-objects Change-Id: I4f364ef90e4ca58065e974cd9d400d785d465daa
114 lines
4.3 KiB
Python
114 lines
4.3 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.
|
|
|
|
from oslo_log import log as logging
|
|
from oslo_utils import timeutils
|
|
|
|
from heat.common import context
|
|
from heat.common.i18n import _LE
|
|
from heat.common.i18n import _LW
|
|
from heat.engine import stack
|
|
from heat.engine import watchrule
|
|
from heat.objects import stack as stack_object
|
|
from heat.objects import watch_rule as watch_rule_object
|
|
from heat.rpc import api as rpc_api
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class StackWatch(object):
|
|
def __init__(self, thread_group_mgr):
|
|
self.thread_group_mgr = thread_group_mgr
|
|
|
|
def start_watch_task(self, stack_id, cnxt):
|
|
|
|
def stack_has_a_watchrule(sid):
|
|
wrs = watch_rule_object.WatchRule.get_all_by_stack(cnxt, sid)
|
|
|
|
now = timeutils.utcnow()
|
|
start_watch_thread = False
|
|
for wr in wrs:
|
|
# reset the last_evaluated so we don't fire off alarms when
|
|
# the engine has not been running.
|
|
watch_rule_object.WatchRule.update_by_id(
|
|
cnxt, wr.id,
|
|
{'last_evaluated': now})
|
|
|
|
if wr.state != rpc_api.WATCH_STATE_CEILOMETER_CONTROLLED:
|
|
start_watch_thread = True
|
|
|
|
children = stack_object.Stack.get_all_by_owner_id(cnxt, sid)
|
|
for child in children:
|
|
if stack_has_a_watchrule(child.id):
|
|
start_watch_thread = True
|
|
|
|
return start_watch_thread
|
|
|
|
if stack_has_a_watchrule(stack_id):
|
|
self.thread_group_mgr.add_timer(
|
|
stack_id,
|
|
self.periodic_watcher_task,
|
|
sid=stack_id)
|
|
|
|
def check_stack_watches(self, sid):
|
|
# Retrieve the stored credentials & create context
|
|
# Require tenant_safe=False to the stack_get to defeat tenant
|
|
# scoping otherwise we fail to retrieve the stack
|
|
LOG.debug("Periodic watcher task for stack %s" % sid)
|
|
admin_context = context.get_admin_context()
|
|
db_stack = stack_object.Stack.get_by_id(admin_context,
|
|
sid,
|
|
tenant_safe=False,
|
|
eager_load=True)
|
|
if not db_stack:
|
|
LOG.error(_LE("Unable to retrieve stack %s for periodic task"),
|
|
sid)
|
|
return
|
|
stk = stack.Stack.load(admin_context, stack=db_stack,
|
|
use_stored_context=True)
|
|
|
|
# recurse into any nested stacks.
|
|
children = stack_object.Stack.get_all_by_owner_id(admin_context, sid)
|
|
for child in children:
|
|
self.check_stack_watches(child.id)
|
|
|
|
# Get all watchrules for this stack and evaluate them
|
|
try:
|
|
wrs = watch_rule_object.WatchRule.get_all_by_stack(admin_context,
|
|
sid)
|
|
except Exception as ex:
|
|
LOG.warn(_LW('periodic_task db error watch rule removed? %(ex)s'),
|
|
ex)
|
|
return
|
|
|
|
def run_alarm_action(stk, actions, details):
|
|
for action in actions:
|
|
action(details=details)
|
|
for res in stk.itervalues():
|
|
res.metadata_update()
|
|
|
|
for wr in wrs:
|
|
rule = watchrule.WatchRule.load(stk.context, watch=wr)
|
|
actions = rule.evaluate()
|
|
if actions:
|
|
self.thread_group_mgr.start(sid, run_alarm_action, stk,
|
|
actions, rule.get_details())
|
|
|
|
def periodic_watcher_task(self, sid):
|
|
"""
|
|
Periodic task, created for each stack, triggers watch-rule
|
|
evaluation for all rules defined for the stack
|
|
sid = stack ID
|
|
"""
|
|
self.check_stack_watches(sid)
|