Coverage for watcher/notifications/action.py: 100%

126 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-17 12:22 +0000

1# -*- encoding: utf-8 -*- 

2# Copyright (c) 2017 Servionica 

3# 

4# Authors: Alexander Chadin <a.chadin@servionica.ru> 

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 

20 

21from watcher.common import context as wcontext 

22from watcher.common import exception 

23from watcher.notifications import action_plan as ap_notifications 

24from watcher.notifications import base as notificationbase 

25from watcher.notifications import exception as exception_notifications 

26from watcher import objects 

27from watcher.objects import base 

28from watcher.objects import fields as wfields 

29 

30CONF = cfg.CONF 

31 

32 

33@base.WatcherObjectRegistry.register_notification 

34class ActionPayload(notificationbase.NotificationPayloadBase): 

35 SCHEMA = { 

36 'uuid': ('action', 'uuid'), 

37 

38 'action_type': ('action', 'action_type'), 

39 'input_parameters': ('action', 'input_parameters'), 

40 'state': ('action', 'state'), 

41 'parents': ('action', 'parents'), 

42 

43 'created_at': ('action', 'created_at'), 

44 'updated_at': ('action', 'updated_at'), 

45 'deleted_at': ('action', 'deleted_at'), 

46 } 

47 

48 # Version 1.0: Initial version 

49 VERSION = '1.0' 

50 

51 fields = { 

52 'uuid': wfields.UUIDField(), 

53 'action_type': wfields.StringField(nullable=False), 

54 'input_parameters': wfields.DictField(nullable=False, default={}), 

55 'state': wfields.StringField(nullable=False), 

56 'parents': wfields.ListOfUUIDsField(nullable=False, default=[]), 

57 'action_plan_uuid': wfields.UUIDField(), 

58 'action_plan': wfields.ObjectField('TerseActionPlanPayload'), 

59 

60 'created_at': wfields.DateTimeField(nullable=True), 

61 'updated_at': wfields.DateTimeField(nullable=True), 

62 'deleted_at': wfields.DateTimeField(nullable=True), 

63 } 

64 

65 def __init__(self, action, **kwargs): 

66 super(ActionPayload, self).__init__(**kwargs) 

67 self.populate_schema(action=action) 

68 

69 

70@base.WatcherObjectRegistry.register_notification 

71class ActionStateUpdatePayload(notificationbase.NotificationPayloadBase): 

72 # Version 1.0: Initial version 

73 VERSION = '1.0' 

74 

75 fields = { 

76 'old_state': wfields.StringField(nullable=True), 

77 'state': wfields.StringField(nullable=True), 

78 } 

79 

80 

81@base.WatcherObjectRegistry.register_notification 

82class ActionCreatePayload(ActionPayload): 

83 # Version 1.0: Initial version 

84 VERSION = '1.0' 

85 fields = {} 

86 

87 def __init__(self, action, action_plan): 

88 super(ActionCreatePayload, self).__init__( 

89 action=action, 

90 action_plan=action_plan) 

91 

92 

93@base.WatcherObjectRegistry.register_notification 

94class ActionUpdatePayload(ActionPayload): 

95 # Version 1.0: Initial version 

96 VERSION = '1.0' 

97 fields = { 

98 'state_update': wfields.ObjectField('ActionStateUpdatePayload'), 

99 } 

100 

101 def __init__(self, action, state_update, action_plan): 

102 super(ActionUpdatePayload, self).__init__( 

103 action=action, 

104 state_update=state_update, 

105 action_plan=action_plan) 

106 

107 

108@base.WatcherObjectRegistry.register_notification 

109class ActionExecutionPayload(ActionPayload): 

110 # Version 1.0: Initial version 

111 VERSION = '1.0' 

112 fields = { 

113 'fault': wfields.ObjectField('ExceptionPayload', nullable=True), 

114 } 

115 

116 def __init__(self, action, action_plan, **kwargs): 

117 super(ActionExecutionPayload, self).__init__( 

118 action=action, 

119 action_plan=action_plan, 

120 **kwargs) 

121 

122 

123@base.WatcherObjectRegistry.register_notification 

124class ActionCancelPayload(ActionPayload): 

125 # Version 1.0: Initial version 

126 VERSION = '1.0' 

127 fields = { 

128 'fault': wfields.ObjectField('ExceptionPayload', nullable=True), 

129 } 

130 

131 def __init__(self, action, action_plan, **kwargs): 

132 super(ActionCancelPayload, self).__init__( 

133 action=action, 

134 action_plan=action_plan, 

135 **kwargs) 

136 

137 

138@base.WatcherObjectRegistry.register_notification 

139class ActionDeletePayload(ActionPayload): 

140 # Version 1.0: Initial version 

141 VERSION = '1.0' 

142 fields = {} 

143 

144 def __init__(self, action, action_plan): 

145 super(ActionDeletePayload, self).__init__( 

146 action=action, 

147 action_plan=action_plan) 

148 

149 

150@notificationbase.notification_sample('action-execution-error.json') 

151@notificationbase.notification_sample('action-execution-end.json') 

152@notificationbase.notification_sample('action-execution-start.json') 

153@base.WatcherObjectRegistry.register_notification 

154class ActionExecutionNotification(notificationbase.NotificationBase): 

155 # Version 1.0: Initial version 

156 VERSION = '1.0' 

157 

158 fields = { 

159 'payload': wfields.ObjectField('ActionExecutionPayload') 

160 } 

161 

162 

163@notificationbase.notification_sample('action-create.json') 

164@base.WatcherObjectRegistry.register_notification 

165class ActionCreateNotification(notificationbase.NotificationBase): 

166 # Version 1.0: Initial version 

167 VERSION = '1.0' 

168 

169 fields = { 

170 'payload': wfields.ObjectField('ActionCreatePayload') 

171 } 

172 

173 

174@notificationbase.notification_sample('action-update.json') 

175@base.WatcherObjectRegistry.register_notification 

176class ActionUpdateNotification(notificationbase.NotificationBase): 

177 # Version 1.0: Initial version 

178 VERSION = '1.0' 

179 

180 fields = { 

181 'payload': wfields.ObjectField('ActionUpdatePayload') 

182 } 

183 

184 

185@notificationbase.notification_sample('action-delete.json') 

186@base.WatcherObjectRegistry.register_notification 

187class ActionDeleteNotification(notificationbase.NotificationBase): 

188 # Version 1.0: Initial version 

189 VERSION = '1.0' 

190 

191 fields = { 

192 'payload': wfields.ObjectField('ActionDeletePayload') 

193 } 

194 

195 

196@notificationbase.notification_sample('action-cancel-error.json') 

197@notificationbase.notification_sample('action-cancel-end.json') 

198@notificationbase.notification_sample('action-cancel-start.json') 

199@base.WatcherObjectRegistry.register_notification 

200class ActionCancelNotification(notificationbase.NotificationBase): 

201 # Version 1.0: Initial version 

202 VERSION = '1.0' 

203 

204 fields = { 

205 'payload': wfields.ObjectField('ActionCancelPayload') 

206 } 

207 

208 

209def _get_action_plan_payload(action): 

210 action_plan = None 

211 strategy_uuid = None 

212 audit = None 

213 try: 

214 action_plan = action.action_plan 

215 audit = objects.Audit.get(wcontext.make_context(show_deleted=True), 

216 action_plan.audit_id) 

217 if audit.strategy_id: 

218 strategy_uuid = objects.Strategy.get( 

219 wcontext.make_context(show_deleted=True), 

220 audit.strategy_id).uuid 

221 except NotImplementedError: 

222 raise exception.EagerlyLoadedActionRequired(action=action.uuid) 

223 

224 action_plan_payload = ap_notifications.TerseActionPlanPayload( 

225 action_plan=action_plan, 

226 audit_uuid=audit.uuid, strategy_uuid=strategy_uuid) 

227 

228 return action_plan_payload 

229 

230 

231def send_create(context, action, service='infra-optim', host=None): 

232 """Emit an action.create notification.""" 

233 action_plan_payload = _get_action_plan_payload(action) 

234 

235 versioned_payload = ActionCreatePayload( 

236 action=action, 

237 action_plan=action_plan_payload, 

238 ) 

239 

240 notification = ActionCreateNotification( 

241 priority=wfields.NotificationPriority.INFO, 

242 event_type=notificationbase.EventType( 

243 object='action', 

244 action=wfields.NotificationAction.CREATE), 

245 publisher=notificationbase.NotificationPublisher( 

246 host=host or CONF.host, 

247 binary=service), 

248 payload=versioned_payload) 

249 

250 notification.emit(context) 

251 

252 

253def send_update(context, action, service='infra-optim', 

254 host=None, old_state=None): 

255 """Emit an action.update notification.""" 

256 action_plan_payload = _get_action_plan_payload(action) 

257 

258 state_update = ActionStateUpdatePayload( 

259 old_state=old_state, 

260 state=action.state if old_state else None) 

261 

262 versioned_payload = ActionUpdatePayload( 

263 action=action, 

264 state_update=state_update, 

265 action_plan=action_plan_payload, 

266 ) 

267 

268 notification = ActionUpdateNotification( 

269 priority=wfields.NotificationPriority.INFO, 

270 event_type=notificationbase.EventType( 

271 object='action', 

272 action=wfields.NotificationAction.UPDATE), 

273 publisher=notificationbase.NotificationPublisher( 

274 host=host or CONF.host, 

275 binary=service), 

276 payload=versioned_payload) 

277 

278 notification.emit(context) 

279 

280 

281def send_delete(context, action, service='infra-optim', host=None): 

282 """Emit an action.delete notification.""" 

283 action_plan_payload = _get_action_plan_payload(action) 

284 

285 versioned_payload = ActionDeletePayload( 

286 action=action, 

287 action_plan=action_plan_payload, 

288 ) 

289 

290 notification = ActionDeleteNotification( 

291 priority=wfields.NotificationPriority.INFO, 

292 event_type=notificationbase.EventType( 

293 object='action', 

294 action=wfields.NotificationAction.DELETE), 

295 publisher=notificationbase.NotificationPublisher( 

296 host=host or CONF.host, 

297 binary=service), 

298 payload=versioned_payload) 

299 

300 notification.emit(context) 

301 

302 

303def send_execution_notification(context, action, notification_action, phase, 

304 priority=wfields.NotificationPriority.INFO, 

305 service='infra-optim', host=None): 

306 """Emit an action execution notification.""" 

307 action_plan_payload = _get_action_plan_payload(action) 

308 

309 fault = None 

310 if phase == wfields.NotificationPhase.ERROR: 

311 fault = exception_notifications.ExceptionPayload.from_exception() 

312 

313 versioned_payload = ActionExecutionPayload( 

314 action=action, 

315 action_plan=action_plan_payload, 

316 fault=fault, 

317 ) 

318 

319 notification = ActionExecutionNotification( 

320 priority=priority, 

321 event_type=notificationbase.EventType( 

322 object='action', 

323 action=notification_action, 

324 phase=phase), 

325 publisher=notificationbase.NotificationPublisher( 

326 host=host or CONF.host, 

327 binary=service), 

328 payload=versioned_payload) 

329 

330 notification.emit(context) 

331 

332 

333def send_cancel_notification(context, action, notification_action, phase, 

334 priority=wfields.NotificationPriority.INFO, 

335 service='infra-optim', host=None): 

336 """Emit an action cancel notification.""" 

337 action_plan_payload = _get_action_plan_payload(action) 

338 

339 fault = None 

340 if phase == wfields.NotificationPhase.ERROR: 

341 fault = exception_notifications.ExceptionPayload.from_exception() 

342 

343 versioned_payload = ActionCancelPayload( 

344 action=action, 

345 action_plan=action_plan_payload, 

346 fault=fault, 

347 ) 

348 

349 notification = ActionCancelNotification( 

350 priority=priority, 

351 event_type=notificationbase.EventType( 

352 object='action', 

353 action=notification_action, 

354 phase=phase), 

355 publisher=notificationbase.NotificationPublisher( 

356 host=host or CONF.host, 

357 binary=service), 

358 payload=versioned_payload) 

359 

360 notification.emit(context)