blob: 9c3c0bf0838b1a22f5045e13422cfd2f8469f2a3 [file] [log] [blame]
#!/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)