Coverage for watcher/applier/action_plan/default.py: 83%
61 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-17 12:22 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-17 12:22 +0000
1# -*- encoding: utf-8 -*-
2# Copyright (c) 2015 b<>com
3#
4# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15# implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19from oslo_config import cfg
20from oslo_log import log
22from watcher.applier.action_plan import base
23from watcher.applier import default
24from watcher.common import exception
25from watcher import notifications
26from watcher import objects
27from watcher.objects import fields
29CONF = cfg.CONF
30LOG = log.getLogger(__name__)
33class DefaultActionPlanHandler(base.BaseActionPlanHandler):
35 def __init__(self, context, service, action_plan_uuid):
36 super(DefaultActionPlanHandler, self).__init__()
37 self.ctx = context
38 self.service = service
39 self.action_plan_uuid = action_plan_uuid
41 def execute(self):
42 try:
43 action_plan = objects.ActionPlan.get_by_uuid(
44 self.ctx, self.action_plan_uuid, eager=True)
45 if action_plan.state == objects.action_plan.State.CANCELLED:
46 self._update_action_from_pending_to_cancelled()
47 return
48 action_plan.hostname = CONF.host
49 action_plan.state = objects.action_plan.State.ONGOING
50 action_plan.save()
51 notifications.action_plan.send_action_notification(
52 self.ctx, action_plan,
53 action=fields.NotificationAction.EXECUTION,
54 phase=fields.NotificationPhase.START)
56 applier = default.DefaultApplier(self.ctx, self.service)
57 applier.execute(self.action_plan_uuid)
59 # If any action has failed the action plan should be FAILED
60 # Define default values for successful execution
61 ap_state = objects.action_plan.State.SUCCEEDED
62 notification_kwargs = {
63 'phase': fields.NotificationPhase.END
64 }
66 failed_filter = {'action_plan_uuid': self.action_plan_uuid,
67 'state': objects.action.State.FAILED}
68 failed_actions = objects.Action.list(
69 self.ctx, filters=failed_filter, eager=True)
70 if failed_actions: 70 ↛ 71line 70 didn't jump to line 71 because the condition on line 70 was never true
71 ap_state = objects.action_plan.State.FAILED
72 notification_kwargs = {
73 'phase': fields.NotificationPhase.ERROR,
74 'priority': fields.NotificationPriority.ERROR
75 }
77 action_plan.state = ap_state
78 action_plan.save()
79 notifications.action_plan.send_action_notification(
80 self.ctx, action_plan,
81 action=fields.NotificationAction.EXECUTION,
82 **notification_kwargs)
84 except exception.ActionPlanCancelled as e:
85 LOG.exception(e)
86 action_plan.state = objects.action_plan.State.CANCELLED
87 self._update_action_from_pending_to_cancelled()
88 action_plan.save()
89 notifications.action_plan.send_cancel_notification(
90 self.ctx, action_plan,
91 action=fields.NotificationAction.CANCEL,
92 phase=fields.NotificationPhase.END)
94 except Exception as e:
95 LOG.exception(e)
96 action_plan = objects.ActionPlan.get_by_uuid(
97 self.ctx, self.action_plan_uuid, eager=True)
98 if action_plan.state == objects.action_plan.State.CANCELLING: 98 ↛ 99line 98 didn't jump to line 99 because the condition on line 98 was never true
99 action_plan.state = objects.action_plan.State.FAILED
100 action_plan.save()
101 notifications.action_plan.send_cancel_notification(
102 self.ctx, action_plan,
103 action=fields.NotificationAction.CANCEL,
104 priority=fields.NotificationPriority.ERROR,
105 phase=fields.NotificationPhase.ERROR)
106 else:
107 action_plan.state = objects.action_plan.State.FAILED
108 action_plan.save()
109 notifications.action_plan.send_action_notification(
110 self.ctx, action_plan,
111 action=fields.NotificationAction.EXECUTION,
112 priority=fields.NotificationPriority.ERROR,
113 phase=fields.NotificationPhase.ERROR)
115 def _update_action_from_pending_to_cancelled(self):
116 filters = {'action_plan_uuid': self.action_plan_uuid,
117 'state': objects.action.State.PENDING}
118 actions = objects.Action.list(self.ctx, filters=filters, eager=True)
119 if actions: 119 ↛ exitline 119 didn't return from function '_update_action_from_pending_to_cancelled' because the condition on line 119 was always true
120 for a in actions:
121 a.state = objects.action.State.CANCELLED
122 a.save()