blob: 9c3c0bf0838b1a22f5045e13422cfd2f8469f2a3 [file] [log] [blame]
Patricia Reinoso15ce47b2022-10-26 08:58:39 +00001#!/usr/bin/python3
2
3# Copyright 2022 Canonical Ltd.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import logging
18from osm_lcm.lcm_utils import LcmBase
19from osm_common.dbbase import DbException
20
21
22class PaasLcm(LcmBase):
23 timeout_create = 30
24
25 def __init__(self, msg, lcm_tasks, config, loop):
26 """Init, Connect to database, filesystem storage, and messaging
27 Args:
28 msg: Message object to be used to write the messages to Kafka Bus
29 lcm_tasks: Task object to register the tasks
30 config: two level dictionary with configuration. Top level should contain 'database', 'storage'
31 loop: Async event loop object
32 """
33
34 self.logger = logging.getLogger("lcm.paas")
35 self.loop = loop
36 self.lcm_tasks = lcm_tasks
37
38 super().__init__(msg, self.logger)
39
40 def _get_paas_by_id(self, paas_id: str) -> dict:
41 db_paas = self.db.get_one("paas", {"_id": paas_id})
42 self.db.encrypt_decrypt_fields(
43 db_paas,
44 "decrypt",
45 ["secret"],
46 schema_version=db_paas["schema_version"],
47 salt=db_paas["_id"],
48 )
49 return db_paas
50
51 def _register_op_and_unlock(
52 self, paas_id, db_paas_update, action, op_id, operation
53 ):
54 """
55 Args:
56 paas_id (str): ID of the PaaS to update.
57 db_paas_update (dict): content to update in DB.
58 action (str): 'create', 'edit', or 'delete'.
59 op_id (str): ID of the operation to unlock.
60 operation (dict): contains 'state' and 'details'.
61 """
62 self.update_db_2("paas", paas_id, db_paas_update)
63 self.lcm_tasks.unlock_HA(
64 "paas",
65 action,
66 op_id,
67 operationState=operation["state"],
68 detailed_status=operation["details"],
69 )
70
71 def _set_status_connectivity_ok(self, db_paas_update: dict, operation: dict):
72 db_paas_update["_admin.operationalState"] = "ENABLED"
73 db_paas_update["_admin.detailed-status"] = "Connectivity: ok"
74 operation["details"] = "PaaS validated"
75 operation["state"] = "COMPLETED"
76
77 def _set_status_exception_raised(
78 self, db_paas_update: dict, operation: dict, error_msg: str
79 ):
80 db_paas_update["_admin.operationalState"] = "ERROR"
81 db_paas_update["_admin.detailed-status"] = error_msg
82 operation["state"] = "FAILED"
83 operation["details"] = error_msg
84
85 async def create(self, paas_content, order_id):
86 """HA tasks and backward compatibility:
87 If "paas_content" does not include "op_id", we a running a legacy NBI version.
88 In such a case, HA is not supported by NBI, "op_id" is None, and lock_HA() will do nothing.
89 Args:
90 paas_content (dict): Contains "op_id" and paas id ("_id")
91 order_id (str): Of the task
92 """
93 op_id = paas_content.pop("op_id", None)
94 if not self.lcm_tasks.lock_HA("paas", "create", op_id):
95 return
96
97 paas_id = paas_content["_id"]
98 self.logger.debug("Task paas_create={} {}".format(paas_id, "Enter"))
99 db_paas_update = {}
100 operation = {}
101
102 try:
103 self._get_paas_by_id(paas_id)
104 self._set_status_connectivity_ok(db_paas_update, operation)
105 msg = "Task paas_create={} Done. Result: {}".format(
106 paas_id, operation["state"]
107 )
108 self.logger.debug(msg)
109
110 except Exception as e:
111 error_msg = "Failed with exception: {}".format(e)
112 self._set_status_exception_raised(db_paas_update, operation, error_msg)
113 self.logger.error("Task paas_create={} {}".format(paas_id, error_msg))
114 finally:
115 try:
116 self._register_op_and_unlock(
117 paas_id, db_paas_update, "create", op_id, operation
118 )
119 except DbException as e:
120 msg = "Task paas_create={} Cannot update database:{}".format(paas_id, e)
121 self.logger.error(msg)
122 self.lcm_tasks.remove("paas", paas_id, order_id)
123
124 async def edit(self, paas_content, order_id):
125 """HA tasks and backward compatibility:
126 If "paas_content" does not include "op_id", we a running a legacy NBI version.
127 In such a case, HA is not supported by NBI, "op_id" is None, and lock_HA() will do nothing.
128 Args:
129 paas_content (dict): Contains "op_id" and paas id ("_id")
130 order_id (str): Of the task
131 """
132
133 op_id = paas_content.pop("op_id", None)
134 if not self.lcm_tasks.lock_HA("paas", "edit", op_id):
135 return
136
137 paas_id = paas_content["_id"]
138 self.logger.debug("Task paas_edit={} {}".format(paas_id, "Enter"))
139 db_paas_update = {}
140 operation = {}
141
142 try:
143 self._get_paas_by_id(paas_id)
144 self._set_status_connectivity_ok(db_paas_update, operation)
145 msg = "Task paas_edit={} Done. Result: {}".format(
146 paas_id, operation["state"]
147 )
148 self.logger.debug(msg)
149
150 except Exception as e:
151 error_msg = "Failed with exception: {}".format(e)
152 self._set_status_exception_raised(db_paas_update, operation, error_msg)
153 self.logger.error("Task paas_edit={} {}".format(paas_id, error_msg))
154 finally:
155 try:
156 self._register_op_and_unlock(
157 paas_id, db_paas_update, "edit", op_id, operation
158 )
159 except DbException as e:
160 msg = "Task paas_edit={} Cannot update database:{}".format(paas_id, e)
161 self.logger.error(msg)
162 self.lcm_tasks.remove("paas", paas_id, order_id)
163
164 async def delete(self, paas_content, order_id):
165 """HA tasks and backward compatibility:
166 If "paas_content" does not include "op_id", we a running a legacy NBI version.
167 In such a case, HA is not supported by NBI, "op_id" is None, and lock_HA() will do nothing.
168 Args:
169 paas_content (dict): Contains "op_id" and paas id ("_id")
170 order_id (str): Of the task
171 """
172 op_id = paas_content.pop("op_id", None)
173 if not self.lcm_tasks.lock_HA("paas", "delete", op_id):
174 return
175
176 paas_id = paas_content["_id"]
177 db_paas_update = {}
178 operation = {}
179
180 try:
181 msg = "Task paas_delete={}: Deleting paas from db".format(paas_id)
182 self.logger.debug(msg)
183 self.db.del_one("paas", {"_id": paas_id})
184 db_paas_update = None
185 operation["state"] = "COMPLETED"
186 operation["details"] = "deleted"
187 msg = "Task paas_delete={}: Done. Result: {}".format(
188 paas_id, operation["state"]
189 )
190 self.logger.debug(msg)
191 except Exception as e:
192 error_msg = "Failed with exception: {}".format(e)
193 self.logger.error("Task paas_delete={} {}".format(paas_id, error_msg))
194 self._set_status_exception_raised(db_paas_update, operation, error_msg)
195 finally:
196 try:
197 self._register_op_and_unlock(
198 paas_id, db_paas_update, "delete", op_id, operation
199 )
200 except DbException as e:
201 msg = "Task paas_delete={}: Cannot update database:{}".format(
202 paas_id, e
203 )
204 self.logger.error(msg)
205 self.lcm_tasks.remove("paas", paas_id, order_id)