bug 601: wait until charms are removed. 59/7059/2
authortierno <alfonso.tiernosepulveda@telefonica.com>
Fri, 14 Dec 2018 13:16:18 +0000 (13:16 +0000)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Mon, 17 Dec 2018 10:27:05 +0000 (10:27 +0000)
Remove tasks done at registry.
Set instantiated state at beginning for avoiding race contitions with NBI deletetion

Change-Id: I922f6197a14e76974c601daa9074a7b2c92eea4d
Signed-off-by: tierno <alfonso.tiernosepulveda@telefonica.com>
osm_lcm/lcm.py
osm_lcm/lcm_utils.py
osm_lcm/netslice.py
osm_lcm/ns.py
osm_lcm/vim_sdn.py

index a6760d0..62a2054 100644 (file)
@@ -44,8 +44,8 @@ min_RO_version = [0, 6, 0]
 min_n2vc_version = "0.0.2"
 min_common_version = "0.1.11"
 # uncomment if LCM is installed as library and installed, and get them from __init__.py
-lcm_version = '0.1.28'
-lcm_version_date = '2018-11-29'
+lcm_version = '0.1.29'
+lcm_version_date = '2018-12-14'
 
 
 class Lcm:
index 687da41..01701a5 100644 (file)
@@ -17,7 +17,7 @@
 ##
 
 from collections import OrderedDict
-from osm_common.dbbase import DbException
+from osm_common.dbbase import DbException
 
 __author__ = "Alfonso Tierno"
 
@@ -84,23 +84,27 @@ class TaskRegistry:
 
     def remove(self, topic, _id, op_id, task_name=None):
         """
-        When task is ended, it should removed. It ignores missing tasks
+        When task is ended, it should be removed. It ignores missing tasks. It also removes tasks done with this _id
         :param topic: Can be "ns", "nsi", "vim_account", "sdn"
         :param _id: _id of the related item
         :param op_id: id of the operation of the related item
-        :param task_name: Task descriptive name. If note it deletes all
-        :return:
+        :param task_name: Task descriptive name. If none it deletes all tasks with same _id and op_id
+        :return: None
         """
-        if not self.task_registry[topic].get(_id) or not self.task_registry[topic][_id].get(op_id):
+        if not self.task_registry[topic].get(_id):
             return
         if not task_name:
-            # print("deleting tasks", topic, _id, op_id, self.task_registry[topic][_id][op_id])
-            del self.task_registry[topic][_id][op_id]
-        elif task_name in self.task_registry[topic][_id][op_id]:
-            # print("deleting tasks", topic, _id, op_id, task_name, self.task_registry[topic][_id][op_id][task_name])
-            del self.task_registry[topic][_id][op_id][task_name]
-            if not self.task_registry[topic][_id][op_id]:
-                del self.task_registry[topic][_id][op_id]
+            self.task_registry[topic][_id].pop(op_id, None)
+        elif self.task_registry[topic][_id].get(op_id):
+            self.task_registry[topic][_id][op_id].pop(task_name, None)
+
+        # delete done tasks
+        for op_id_ in list(self.task_registry[topic][_id]):
+            for name, task in self.task_registry[topic][_id][op_id_].items():
+                if not task.done():
+                    break
+            else:
+                del self.task_registry[topic][_id][op_id_]
         if not self.task_registry[topic][_id]:
             del self.task_registry[topic][_id]
 
@@ -116,8 +120,9 @@ class TaskRegistry:
                 continue
 
             for task_name, task in self.task_registry[topic][_id][op_id].items():
-                task_list.append(task)
-                task_name_list.append(task_name)
+                if not task.done():
+                    task_list.append(task)
+                    task_name_list.append(task_name)
             break
         return ", ".join(task_name_list), task_list
 
@@ -154,16 +159,15 @@ class LcmBase:
 
     def update_db_2(self, item, _id, _desc):
         """
-        Updates database with _desc information. Upon success _desc is cleared
+        Updates database with _desc information. If success _desc is cleared
         :param item:
         :param _id:
-        :param _desc:
-        :return:
+        :param _desc: dictionary with the content to update. Keys are dot separated keys for
+        :return: None. Exception is raised on error
         """
         if not _desc:
             return
-        try:
-            self.db.set_one(item, {"_id": _id}, _desc)
-            _desc.clear()
-        except DbException as e:
-            self.logger.error("Updating {} _id={} with '{}'. Error: {}".format(item, _id, _desc, e))
+        self.db.set_one(item, {"_id": _id}, _desc)
+        _desc.clear()
+        # except DbException as e:
+        #     self.logger.error("Updating {} _id={} with '{}'. Error: {}".format(item, _id, _desc, e))
index 282757f..e4684bc 100644 (file)
@@ -143,6 +143,10 @@ class NetsliceLcm(LcmBase):
                 RO_ns_params["scenario"] = {"nets": nets}
                 RO_ns_params["datacenter"] = vim_account_2_RO(netslice_vld["vimAccountId"])
 
+            # set state to INSTANTIATED. When instantiated NBI will not delete directly
+            db_nsir_update["_admin.nsState"] = "INSTANTIATED"
+            self.update_db_2("nsis", nsir_id, db_nsir_update)
+
             # Crate ns at RO
             # if present use it unless in error status
             RO_nsir_id = db_nsir["_admin"].get("deployed", {}).get("RO", {}).get("nsir_id")
@@ -177,7 +181,6 @@ class NetsliceLcm(LcmBase):
                 step = db_nsir_update["detailed-status"] = "Creating ns at RO"
                 desc = await RO.create("ns", descriptor=RO_ns_params)
                 RO_nsir_id = db_nsir_update["_admin.deployed.RO.nsir_id"] = desc["uuid"]
-                db_nsir_update["_admin.nsState"] = "INSTANTIATED"
                 db_nsir_update["_admin.deployed.RO.nsir_status"] = "BUILD"
                 self.logger.debug(logging_text + "ns created at RO. RO_id={}".format(desc["uuid"]))
             self.update_db_2("nsis", nsir_id, db_nsir_update)
@@ -292,13 +295,15 @@ class NetsliceLcm(LcmBase):
                     db_nsilcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
                     db_nsilcmop_update["operationState"] = nsilcmop_operation_state = "FAILED"
                     db_nsilcmop_update["statusEnteredTime"] = time()
-            if db_nsir:
-                db_nsir_update["_admin.nsiState"] = "INSTANTIATED"
-                db_nsir_update["_admin.nsilcmop"] = None
-                self.update_db_2("nsis", nsir_id, db_nsir_update)
-            if db_nsilcmop:
-
-                self.update_db_2("nsilcmops", nsilcmop_id, db_nsilcmop_update)
+            try:
+                if db_nsir:
+                    db_nsir_update["_admin.nsiState"] = "INSTANTIATED"
+                    db_nsir_update["_admin.nsilcmop"] = None
+                    self.update_db_2("nsis", nsir_id, db_nsir_update)
+                if db_nsilcmop:
+                    self.update_db_2("nsilcmops", nsilcmop_id, db_nsilcmop_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             if nsilcmop_operation_state:
                 try:
                     await self.msg.aiowrite("nsi", "instantiated", {"nsir_id": nsir_id, "nsilcmop_id": nsilcmop_id,
@@ -483,12 +488,15 @@ class NetsliceLcm(LcmBase):
                     db_nsilcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
                     db_nsilcmop_update["operationState"] = nsilcmop_operation_state = "FAILED"
                     db_nsilcmop_update["statusEnteredTime"] = time()
-            if db_nsir:
-                db_nsir_update["_admin.nsilcmop"] = None
-                db_nsir_update["_admin.nsiState"] = "TERMINATED"
-                self.update_db_2("nsis", nsir_id, db_nsir_update)
-            if db_nsilcmop:
-                self.update_db_2("nsilcmops", nsilcmop_id, db_nsilcmop_update)
+            try:
+                if db_nsir:
+                    db_nsir_update["_admin.nsilcmop"] = None
+                    db_nsir_update["_admin.nsiState"] = "TERMINATED"
+                    self.update_db_2("nsis", nsir_id, db_nsir_update)
+                if db_nsilcmop:
+                    self.update_db_2("nsilcmops", nsilcmop_id, db_nsilcmop_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
 
             if nsilcmop_operation_state:
                 try:
index 173ad88..2f806f4 100644 (file)
@@ -69,6 +69,7 @@ def populate_dict(target_dict, key_list, value):
 class NsLcm(LcmBase):
     timeout_vca_on_error = 5 * 60   # Time for charm from first time at blocked,error status to mark as failed
     total_deploy_timeout = 2 * 3600   # global timeout for deployment
+    timeout_charm_delete = 10 * 60
 
     def __init__(self, db, msg, fs, lcm_tasks, ro_config, vca_config, loop):
         """
@@ -626,6 +627,10 @@ class NsLcm(LcmBase):
 
             RO = ROclient.ROClient(self.loop, **self.ro_config)
 
+            # set state to INSTANTIATED. When instantiated NBI will not delete directly
+            db_nsr_update["_admin.nsState"] = "INSTANTIATED"
+            self.update_db_2("nsrs", nsr_id, db_nsr_update)
+
             # get vnfds, instantiate at RO
             for vnfd_id, vnfd in db_vnfds.items():
                 vnfd_ref = vnfd["id"]
@@ -645,7 +650,6 @@ class NsLcm(LcmBase):
                     vnfd_RO = self.vnfd2RO(vnfd, vnfd_id_RO)
                     desc = await RO.create("vnfd", descriptor=vnfd_RO)
                     db_nsr_update["_admin.deployed.RO.vnfd_id.{}".format(vnfd_id)] = desc["uuid"]
-                    db_nsr_update["_admin.nsState"] = "INSTANTIATED"
                     self.logger.debug(logging_text + "vnfd={} created at RO. RO_id={}".format(
                         vnfd_ref, desc["uuid"]))
                 self.update_db_2("nsrs", nsr_id, db_nsr_update)
@@ -1010,11 +1014,14 @@ class NsLcm(LcmBase):
                     db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
                     db_nslcmop_update["operationState"] = nslcmop_operation_state = "FAILED"
                     db_nslcmop_update["statusEnteredTime"] = time()
-            if db_nsr:
-                db_nsr_update["_admin.nslcmop"] = None
-                self.update_db_2("nsrs", nsr_id, db_nsr_update)
-            if db_nslcmop_update:
-                self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
+            try:
+                if db_nsr:
+                    db_nsr_update["_admin.nslcmop"] = None
+                    self.update_db_2("nsrs", nsr_id, db_nsr_update)
+                if db_nslcmop_update:
+                    self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             if nslcmop_operation_state:
                 try:
                     await self.msg.aiowrite("ns", "instantiated", {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id,
@@ -1025,6 +1032,34 @@ class NsLcm(LcmBase):
             self.logger.debug(logging_text + "Exit")
             self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
 
+    async def _destroy_charm(self, model, application):
+        """
+        Order N2VC destroy a charm
+        :param model:
+        :param application:
+        :return: True if charm does not exist. False if it exist
+        """
+        if not await self.n2vc.HasApplication(model, application):
+            return True  # Already removed
+        await self.n2vc.RemoveCharms(model, application)
+        return False
+
+    async def _wait_charm_destroyed(self, model, application, timeout):
+        """
+        Wait until charm does not exist
+        :param model:
+        :param application:
+        :param timeout:
+        :return: True if not exist, False if timeout
+        """
+        while True:
+            if not await self.n2vc.HasApplication(model, application):
+                return True
+            if timeout < 0:
+                return False
+            await asyncio.sleep(10)
+            timeout -= 10
+
     async def terminate(self, nsr_id, nslcmop_id):
         logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
         self.logger.debug(logging_text + "Enter")
@@ -1032,9 +1067,7 @@ class NsLcm(LcmBase):
         db_nslcmop = None
         exc = None
         failed_detail = []   # annotates all failed error messages
-        vca_task_list = []
-        vca_task_dict = {}
-        vca_application_name2index = {}
+        vca_time_destroy = None   # time of where destroy charm order
         db_nsr_update = {"_admin.nslcmop": nslcmop_id}
         db_nslcmop_update = {}
         nslcmop_operation_state = None
@@ -1047,8 +1080,6 @@ class NsLcm(LcmBase):
             nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed"))
             if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
                 return
-            # TODO ALF remove
-            # db_vim = self.db.get_one("vim_accounts", {"_id":  db_nsr["datacenter"]})
             # #TODO check if VIM is creating and wait
             # RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
 
@@ -1068,24 +1099,12 @@ class NsLcm(LcmBase):
                         self.update_db_2("nsrs", nsr_id, db_nsr_update)
 
                     for vca_index, vca_deployed in enumerate(nsr_deployed["VCA"]):
-                        if vca_deployed:  # TODO it would be desirable having a and deploy_info.get("deployed"):
-                            task = asyncio.ensure_future(
-                                self.n2vc.RemoveCharms(
-                                    vca_deployed['model'],
-                                    vca_deployed["application"],
-                                    # self.n2vc_callback,
-                                    # db_nsr,
-                                    # db_nslcmop,
-                                )
-                            )
-                            vca_application_name2index[vca_deployed["application"]] = vca_index
-                            vca_task_list.append(task)
-                            vca_task_dict[vca_deployed["application"]] = task
-                            # task.add_done_callback(functools.partial(self.n2vc_callback, vca_deployed['model'],
-                            #                                          vca_deployed['application'], None, db_nsr,
-                            #                                          db_nslcmop, vnf_index))
-                            self.lcm_tasks.register("ns", nsr_id, nslcmop_id,
-                                                    "delete_charm:" + vca_deployed["application"], task)
+                        if vca_deployed:
+                            if await self._destroy_charm(vca_deployed['model'], vca_deployed["application"]):
+                                vca_deployed.clear()
+                                db_nsr["_admin.deployed.VCA.{}".format(vca_index)] = None
+                            else:
+                                vca_time_destroy = time()
                 except Exception as e:
                     self.logger.debug(logging_text + "Failed while deleting charms: {}".format(e))
 
@@ -1111,7 +1130,8 @@ class NsLcm(LcmBase):
                     db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
                 if RO_delete_action:
                     # wait until NS is deleted from VIM
-                    step = detailed_status = "Waiting ns deleted from VIM. RO_id={}".format(RO_nsr_id)
+                    step = detailed_status = "Waiting ns deleted from VIM. RO_id={} RO_delete_action={}".\
+                        format(RO_nsr_id, RO_delete_action)
                     detailed_status_old = None
                     self.logger.debug(logging_text + step)
 
@@ -1125,6 +1145,8 @@ class NsLcm(LcmBase):
                         elif ns_status == "BUILD":
                             detailed_status = step + "; {}".format(ns_status_info)
                         elif ns_status == "ACTIVE":
+                            db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
+                            db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
                             break
                         else:
                             assert False, "ROclient.check_action_status returns unknown {}".format(ns_status)
@@ -1142,6 +1164,7 @@ class NsLcm(LcmBase):
                 if e.http_code == 404:  # not found
                     db_nsr_update["_admin.deployed.RO.nsr_id"] = None
                     db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
+                    db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
                     self.logger.debug(logging_text + "RO_ns_id={} already deleted".format(RO_nsr_id))
                 elif e.http_code == 409:   # conflict
                     failed_detail.append("RO_ns_id={} delete conflict: {}".format(RO_nsr_id, e))
@@ -1195,28 +1218,23 @@ class NsLcm(LcmBase):
                             failed_detail.append("RO_vnfd_id={} delete error: {}".format(RO_vnfd_id, e))
                             self.logger.error(logging_text + failed_detail[-1])
 
-            if vca_task_list:
-                db_nsr_update["detailed-status"] = db_nslcmop_update["detailed-status"] =\
+            # wait until charm deleted
+            if vca_time_destroy:
+                db_nsr_update["detailed-status"] = db_nslcmop_update["detailed-status"] = step = \
                     "Waiting for deletion of configuration charms"
                 self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
                 self.update_db_2("nsrs", nsr_id, db_nsr_update)
-                await asyncio.wait(vca_task_list, timeout=300)
-            for application_name, task in vca_task_dict.items():
-                if task.cancelled():
-                    failed_detail.append("VCA[application_name={}] Deletion has been cancelled"
-                                         .format(application_name))
-                elif task.done():
-                    exc = task.exception()
-                    if exc:
-                        failed_detail.append("VCA[application_name={}] Deletion exception: {}"
-                                             .format(application_name, exc))
+                for vca_index, vca_deployed in enumerate(nsr_deployed["VCA"]):
+                    if not vca_deployed:
+                        continue
+                    step = "Waiting for deletion of charm application_name={}".format(vca_deployed["application"])
+                    timeout = self.timeout_charm_delete - int(time() - vca_time_destroy)
+                    if not await self._wait_charm_destroyed(vca_deployed['model'], vca_deployed["application"],
+                                                            timeout):
+                        failed_detail.append("VCA[application_name={}] Deletion timeout".format(
+                            vca_deployed["application"]))
                     else:
-                        vca_index = vca_application_name2index[application_name]
-                        db_nsr_update["_admin.deployed.VCA.{}".format(vca_index)] = None
-                else:  # timeout
-                    # TODO Should it be cancelled?!!
-                    task.cancel()
-                    failed_detail.append("VCA[application_name={}] Deletion timeout".format(application_name))
+                        db_nsr["_admin.deployed.VCA.{}".format(vca_index)] = None
 
             if failed_detail:
                 self.logger.error(logging_text + " ;".join(failed_detail))
@@ -1227,8 +1245,10 @@ class NsLcm(LcmBase):
                 db_nslcmop_update["statusEnteredTime"] = time()
             elif db_nslcmop["operationParams"].get("autoremove"):
                 self.db.del_one("nsrs", {"_id": nsr_id})
+                db_nsr = None
                 db_nsr_update.clear()
                 self.db.del_list("nslcmops", {"nsInstanceId": nsr_id})
+                db_nslcmop = None
                 nslcmop_operation_state = "COMPLETED"
                 db_nslcmop_update.clear()
                 self.db.del_list("vnfrs", {"nsr-id-ref": nsr_id})
@@ -1257,11 +1277,14 @@ class NsLcm(LcmBase):
                 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
                 db_nslcmop_update["operationState"] = nslcmop_operation_state = "FAILED"
                 db_nslcmop_update["statusEnteredTime"] = time()
-            if db_nslcmop_update:
-                self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
-            if db_nsr:
-                db_nsr_update["_admin.nslcmop"] = None
-                self.update_db_2("nsrs", nsr_id, db_nsr_update)
+            try:
+                if db_nslcmop and db_nslcmop_update:
+                    self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
+                if db_nsr:
+                    db_nsr_update["_admin.nslcmop"] = None
+                    self.update_db_2("nsrs", nsr_id, db_nsr_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             if nslcmop_operation_state:
                 try:
                     await self.msg.aiowrite("ns", "terminated", {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id,
@@ -1395,11 +1418,14 @@ class NsLcm(LcmBase):
                 db_nslcmop_update["detailed-status"] = "FAILED {}: {}".format(step, exc)
                 db_nslcmop_update["operationState"] = nslcmop_operation_state = "FAILED"
                 db_nslcmop_update["statusEnteredTime"] = time()
-            if db_nslcmop_update:
-                self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
-            if db_nsr:
-                db_nsr_update["_admin.nslcmop"] = None
-                self.update_db_2("nsrs", nsr_id, db_nsr_update)
+            try:
+                if db_nslcmop_update:
+                    self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
+                if db_nsr:
+                    db_nsr_update["_admin.nslcmop"] = None
+                    self.update_db_2("nsrs", nsr_id, db_nsr_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.logger.debug(logging_text + "Exit")
             if nslcmop_operation_state:
                 try:
@@ -1737,11 +1763,14 @@ class NsLcm(LcmBase):
                             db_nsr_update["operational-status"] = "failed"
                         db_nsr_update["detailed-status"] = "FAILED scaling nslcmop={} {}: {}".format(nslcmop_id, step,
                                                                                                      exc)
-            if db_nslcmop_update:
-                self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
-            if db_nsr:
-                db_nsr_update["_admin.nslcmop"] = None
-                self.update_db_2("nsrs", nsr_id, db_nsr_update)
+            try:
+                if db_nslcmop and db_nslcmop_update:
+                    self.update_db_2("nslcmops", nslcmop_id, db_nslcmop_update)
+                if db_nsr:
+                    db_nsr_update["_admin.nslcmop"] = None
+                    self.update_db_2("nsrs", nsr_id, db_nsr_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             if nslcmop_operation_state:
                 try:
                     await self.msg.aiowrite("ns", "scaled", {"nsr_id": nsr_id, "nslcmop_id": nslcmop_id,
index 07aa4a9..0f4c431 100644 (file)
@@ -56,7 +56,6 @@ class VimLcm(LcmBase):
         try:
             step = "Getting vim-id='{}' from db".format(vim_id)
             db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
-            db_vim_update["_admin.deployed.RO"] = None
             if vim_content.get("config") and vim_content["config"].get("sdn-controller"):
                 step = "Getting sdn-controller-id='{}' from db".format(vim_content["config"]["sdn-controller"])
                 db_sdn = self.db.get_one("sdns", {"_id": vim_content["config"]["sdn-controller"]})
@@ -67,6 +66,7 @@ class VimLcm(LcmBase):
                         vim_content["config"]["sdn-controller"]))
 
             step = "Creating vim at RO"
+            db_vim_update["_admin.deployed.RO"] = None
             db_vim_update["_admin.detailed-status"] = step
             self.update_db_2("vim_accounts", vim_id, db_vim_update)
             RO = ROclient.ROClient(self.loop, **self.ro_config)
@@ -129,8 +129,12 @@ class VimLcm(LcmBase):
             if exc and db_vim:
                 db_vim_update["_admin.operationalState"] = "ERROR"
                 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_vim_update:
-                self.update_db_2("vim_accounts", vim_id, db_vim_update)
+            try:
+                if db_vim_update:
+                    self.update_db_2("vim_accounts", vim_id, db_vim_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
+
             self.lcm_tasks.remove("vim_account", vim_id, order_id)
 
     async def edit(self, vim_content, order_id):
@@ -243,8 +247,12 @@ class VimLcm(LcmBase):
             if exc and db_vim:
                 db_vim_update["_admin.operationalState"] = "ERROR"
                 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_vim_update:
-                self.update_db_2("vim_accounts", vim_id, db_vim_update)
+            try:
+                if db_vim_update:
+                    self.update_db_2("vim_accounts", vim_id, db_vim_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
+
             self.lcm_tasks.remove("vim_account", vim_id, order_id)
 
     async def delete(self, vim_id, order_id):
@@ -280,6 +288,7 @@ class VimLcm(LcmBase):
                 # nothing to delete
                 self.logger.error(logging_text + "Nohing to remove at RO")
             self.db.del_one("vim_accounts", {"_id": vim_id})
+            db_vim = None
             self.logger.debug(logging_text + "Exit Ok")
             return
 
@@ -294,8 +303,11 @@ class VimLcm(LcmBase):
             if exc and db_vim:
                 db_vim_update["_admin.operationalState"] = "ERROR"
                 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_vim_update:
-                self.update_db_2("vim_accounts", vim_id, db_vim_update)
+            try:
+                if db_vim and db_vim_update:
+                    self.update_db_2("vim_accounts", vim_id, db_vim_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("vim_account", vim_id, order_id)
 
 
@@ -387,8 +399,11 @@ class WimLcm(LcmBase):
             if exc and db_wim:
                 db_wim_update["_admin.operationalState"] = "ERROR"
                 db_wim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_wim_update:
-                self.update_db_2("wim_accounts", wim_id, db_wim_update)
+            try:
+                if db_wim_update:
+                    self.update_db_2("wim_accounts", wim_id, db_wim_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("wim_account", wim_id, order_id)
 
     async def edit(self, wim_content, order_id):
@@ -476,8 +491,11 @@ class WimLcm(LcmBase):
             if exc and db_wim:
                 db_wim_update["_admin.operationalState"] = "ERROR"
                 db_wim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_wim_update:
-                self.update_db_2("wim_accounts", wim_id, db_wim_update)
+            try:
+                if db_wim_update:
+                    self.update_db_2("wim_accounts", wim_id, db_wim_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("wim_account", wim_id, order_id)
 
     async def delete(self, wim_id, order_id):
@@ -513,6 +531,7 @@ class WimLcm(LcmBase):
                 # nothing to delete
                 self.logger.error(logging_text + "Nohing to remove at RO")
             self.db.del_one("wim_accounts", {"_id": wim_id})
+            db_wim = None
             self.logger.debug(logging_text + "Exit Ok")
             return
 
@@ -527,8 +546,11 @@ class WimLcm(LcmBase):
             if exc and db_wim:
                 db_wim_update["_admin.operationalState"] = "ERROR"
                 db_wim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_wim_update:
-                self.update_db_2("wim_accounts", wim_id, db_wim_update)
+            try:
+                if db_wim and db_wim_update:
+                    self.update_db_2("wim_accounts", wim_id, db_wim_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("wim_account", wim_id, order_id)
 
 
@@ -562,6 +584,9 @@ class SdnLcm(LcmBase):
             db_sdn_update["_admin.deployed.RO"] = None
 
             step = "Creating sdn at RO"
+            db_sdn_update["_admin.detailed-status"] = step
+            self.update_db_2("sdns", sdn_id, db_sdn_update)
+
             RO = ROclient.ROClient(self.loop, **self.ro_config)
             sdn_RO = deepcopy(sdn_content)
             sdn_RO.pop("_id", None)
@@ -589,8 +614,11 @@ class SdnLcm(LcmBase):
             if exc and db_sdn:
                 db_sdn_update["_admin.operationalState"] = "ERROR"
                 db_sdn_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_sdn_update:
-                self.update_db_2("sdns", sdn_id, db_sdn_update)
+            try:
+                if db_sdn and db_sdn_update:
+                    self.update_db_2("sdns", sdn_id, db_sdn_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("sdn", sdn_id, order_id)
 
     async def edit(self, sdn_content, order_id):
@@ -633,8 +661,11 @@ class SdnLcm(LcmBase):
             if exc and db_sdn:
                 db_sdn["_admin.operationalState"] = "ERROR"
                 db_sdn["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_sdn_update:
-                self.update_db_2("sdns", sdn_id, db_sdn_update)
+            try:
+                if db_sdn_update:
+                    self.update_db_2("sdns", sdn_id, db_sdn_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("sdn", sdn_id, order_id)
 
     async def delete(self, sdn_id, order_id):
@@ -661,6 +692,7 @@ class SdnLcm(LcmBase):
                 # nothing to delete
                 self.logger.error(logging_text + "Skipping. There is not RO information at database")
             self.db.del_one("sdns", {"_id": sdn_id})
+            db_sdn = None
             self.logger.debug("sdn_delete task sdn_id={} Exit Ok".format(sdn_id))
             return
 
@@ -674,6 +706,9 @@ class SdnLcm(LcmBase):
             if exc and db_sdn:
                 db_sdn["_admin.operationalState"] = "ERROR"
                 db_sdn["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
-            if db_sdn_update:
-                self.update_db_2("sdns", sdn_id, db_sdn_update)
+            try:
+                if db_sdn and db_sdn_update:
+                    self.update_db_2("sdns", sdn_id, db_sdn_update)
+            except DbException as e:
+                self.logger.error(logging_text + "Cannot update database: {}".format(e))
             self.lcm_tasks.remove("sdn", sdn_id, order_id)