| #!/usr/bin/python3 |
| |
| # Copyright 2022 Canonical Ltd. |
| # |
| # 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. |
| |
| import logging |
| from osm_lcm.lcm_utils import LcmBase |
| from osm_common.dbbase import DbException |
| |
| |
| class PaasLcm(LcmBase): |
| timeout_create = 30 |
| |
| def __init__(self, msg, lcm_tasks, config, loop): |
| """Init, Connect to database, filesystem storage, and messaging |
| Args: |
| msg: Message object to be used to write the messages to Kafka Bus |
| lcm_tasks: Task object to register the tasks |
| config: two level dictionary with configuration. Top level should contain 'database', 'storage' |
| loop: Async event loop object |
| """ |
| |
| self.logger = logging.getLogger("lcm.paas") |
| self.loop = loop |
| self.lcm_tasks = lcm_tasks |
| |
| super().__init__(msg, self.logger) |
| |
| def _get_paas_by_id(self, paas_id: str) -> dict: |
| db_paas = self.db.get_one("paas", {"_id": paas_id}) |
| self.db.encrypt_decrypt_fields( |
| db_paas, |
| "decrypt", |
| ["secret"], |
| schema_version=db_paas["schema_version"], |
| salt=db_paas["_id"], |
| ) |
| return db_paas |
| |
| def _register_op_and_unlock( |
| self, paas_id, db_paas_update, action, op_id, operation |
| ): |
| """ |
| Args: |
| paas_id (str): ID of the PaaS to update. |
| db_paas_update (dict): content to update in DB. |
| action (str): 'create', 'edit', or 'delete'. |
| op_id (str): ID of the operation to unlock. |
| operation (dict): contains 'state' and 'details'. |
| """ |
| self.update_db_2("paas", paas_id, db_paas_update) |
| self.lcm_tasks.unlock_HA( |
| "paas", |
| action, |
| op_id, |
| operationState=operation["state"], |
| detailed_status=operation["details"], |
| ) |
| |
| def _set_status_connectivity_ok(self, db_paas_update: dict, operation: dict): |
| db_paas_update["_admin.operationalState"] = "ENABLED" |
| db_paas_update["_admin.detailed-status"] = "Connectivity: ok" |
| operation["details"] = "PaaS validated" |
| operation["state"] = "COMPLETED" |
| |
| def _set_status_exception_raised( |
| self, db_paas_update: dict, operation: dict, error_msg: str |
| ): |
| db_paas_update["_admin.operationalState"] = "ERROR" |
| db_paas_update["_admin.detailed-status"] = error_msg |
| operation["state"] = "FAILED" |
| operation["details"] = error_msg |
| |
| async def create(self, paas_content, order_id): |
| """HA tasks and backward compatibility: |
| If "paas_content" does not include "op_id", we a running a legacy NBI version. |
| In such a case, HA is not supported by NBI, "op_id" is None, and lock_HA() will do nothing. |
| Args: |
| paas_content (dict): Contains "op_id" and paas id ("_id") |
| order_id (str): Of the task |
| """ |
| op_id = paas_content.pop("op_id", None) |
| if not self.lcm_tasks.lock_HA("paas", "create", op_id): |
| return |
| |
| paas_id = paas_content["_id"] |
| self.logger.debug("Task paas_create={} {}".format(paas_id, "Enter")) |
| db_paas_update = {} |
| operation = {} |
| |
| try: |
| self._get_paas_by_id(paas_id) |
| self._set_status_connectivity_ok(db_paas_update, operation) |
| msg = "Task paas_create={} Done. Result: {}".format( |
| paas_id, operation["state"] |
| ) |
| self.logger.debug(msg) |
| |
| except Exception as e: |
| error_msg = "Failed with exception: {}".format(e) |
| self._set_status_exception_raised(db_paas_update, operation, error_msg) |
| self.logger.error("Task paas_create={} {}".format(paas_id, error_msg)) |
| finally: |
| try: |
| self._register_op_and_unlock( |
| paas_id, db_paas_update, "create", op_id, operation |
| ) |
| except DbException as e: |
| msg = "Task paas_create={} Cannot update database:{}".format(paas_id, e) |
| self.logger.error(msg) |
| self.lcm_tasks.remove("paas", paas_id, order_id) |
| |
| async def edit(self, paas_content, order_id): |
| """HA tasks and backward compatibility: |
| If "paas_content" does not include "op_id", we a running a legacy NBI version. |
| In such a case, HA is not supported by NBI, "op_id" is None, and lock_HA() will do nothing. |
| Args: |
| paas_content (dict): Contains "op_id" and paas id ("_id") |
| order_id (str): Of the task |
| """ |
| |
| op_id = paas_content.pop("op_id", None) |
| if not self.lcm_tasks.lock_HA("paas", "edit", op_id): |
| return |
| |
| paas_id = paas_content["_id"] |
| self.logger.debug("Task paas_edit={} {}".format(paas_id, "Enter")) |
| db_paas_update = {} |
| operation = {} |
| |
| try: |
| self._get_paas_by_id(paas_id) |
| self._set_status_connectivity_ok(db_paas_update, operation) |
| msg = "Task paas_edit={} Done. Result: {}".format( |
| paas_id, operation["state"] |
| ) |
| self.logger.debug(msg) |
| |
| except Exception as e: |
| error_msg = "Failed with exception: {}".format(e) |
| self._set_status_exception_raised(db_paas_update, operation, error_msg) |
| self.logger.error("Task paas_edit={} {}".format(paas_id, error_msg)) |
| finally: |
| try: |
| self._register_op_and_unlock( |
| paas_id, db_paas_update, "edit", op_id, operation |
| ) |
| except DbException as e: |
| msg = "Task paas_edit={} Cannot update database:{}".format(paas_id, e) |
| self.logger.error(msg) |
| self.lcm_tasks.remove("paas", paas_id, order_id) |
| |
| async def delete(self, paas_content, order_id): |
| """HA tasks and backward compatibility: |
| If "paas_content" does not include "op_id", we a running a legacy NBI version. |
| In such a case, HA is not supported by NBI, "op_id" is None, and lock_HA() will do nothing. |
| Args: |
| paas_content (dict): Contains "op_id" and paas id ("_id") |
| order_id (str): Of the task |
| """ |
| op_id = paas_content.pop("op_id", None) |
| if not self.lcm_tasks.lock_HA("paas", "delete", op_id): |
| return |
| |
| paas_id = paas_content["_id"] |
| db_paas_update = {} |
| operation = {} |
| |
| try: |
| msg = "Task paas_delete={}: Deleting paas from db".format(paas_id) |
| self.logger.debug(msg) |
| self.db.del_one("paas", {"_id": paas_id}) |
| db_paas_update = None |
| operation["state"] = "COMPLETED" |
| operation["details"] = "deleted" |
| msg = "Task paas_delete={}: Done. Result: {}".format( |
| paas_id, operation["state"] |
| ) |
| self.logger.debug(msg) |
| except Exception as e: |
| error_msg = "Failed with exception: {}".format(e) |
| self.logger.error("Task paas_delete={} {}".format(paas_id, error_msg)) |
| self._set_status_exception_raised(db_paas_update, operation, error_msg) |
| finally: |
| try: |
| self._register_op_and_unlock( |
| paas_id, db_paas_update, "delete", op_id, operation |
| ) |
| except DbException as e: |
| msg = "Task paas_delete={}: Cannot update database:{}".format( |
| paas_id, e |
| ) |
| self.logger.error(msg) |
| self.lcm_tasks.remove("paas", paas_id, order_id) |