Add lock deleting namespaces 99/11999/2
authorDavid Garcia <david.garcia@canonical.com>
Wed, 4 May 2022 13:33:03 +0000 (15:33 +0200)
committerDavid Garcia <david.garcia@canonical.com>
Wed, 4 May 2022 14:09:48 +0000 (16:09 +0200)
- Fix bug 2016

Change-Id: Ifd4572937376cdeec79e3dfd808174d3f14325b9
Signed-off-by: David Garcia <david.garcia@canonical.com>
n2vc/n2vc_juju_conn.py

index 4efbd1c..f077b40 100644 (file)
@@ -93,7 +93,7 @@ class N2VCJujuConnector(N2VCConnector):
         db_uri = EnvironConfig(prefixes=["OSMLCM_", "OSMMON_"]).get("database_uri")
         self._store = MotorStore(db_uri)
         self.loading_libjuju = asyncio.Lock(loop=self.loop)
-
+        self.delete_namespace_locks = {}
         self.log.info("N2VC juju connector initialized")
 
     async def get_status(
@@ -791,33 +791,55 @@ class N2VCJujuConnector(N2VCConnector):
         :param: vca_id: VCA ID
         """
         self.log.info("Deleting namespace={}".format(namespace))
-        libjuju = await self._get_libjuju(vca_id)
+        will_not_delete = False
+        if namespace not in self.delete_namespace_locks:
+            self.delete_namespace_locks[namespace] = asyncio.Lock(loop=self.loop)
 
-        # check arguments
-        if namespace is None:
-            raise N2VCBadArgumentsException(
-                message="namespace is mandatory", bad_args=["namespace"]
-            )
+        while self.delete_namespace_locks[namespace].locked():
+            will_not_delete = True
+            await asyncio.sleep(0.1)
 
-        _nsi_id, ns_id, _vnf_id, _vdu_id, _vdu_count = self._get_namespace_components(
-            namespace=namespace
-        )
-        if ns_id is not None:
-            try:
-                models = await libjuju.list_models(contains=ns_id)
-                for model in models:
-                    await libjuju.destroy_model(
-                        model_name=model, total_timeout=total_timeout
+        if will_not_delete:
+            self.log.info("Namespace {} deleted by another worker.".format(namespace))
+            return
+
+        try:
+            async with self.delete_namespace_locks[namespace]:
+                libjuju = await self._get_libjuju(vca_id)
+
+                # check arguments
+                if namespace is None:
+                    raise N2VCBadArgumentsException(
+                        message="namespace is mandatory", bad_args=["namespace"]
                     )
-            except Exception as e:
-                raise N2VCException(
-                    message="Error deleting namespace {} : {}".format(namespace, e)
-                )
-        else:
-            raise N2VCBadArgumentsException(
-                message="only ns_id is permitted to delete yet", bad_args=["namespace"]
-            )
 
+                (
+                    _nsi_id,
+                    ns_id,
+                    _vnf_id,
+                    _vdu_id,
+                    _vdu_count,
+                ) = self._get_namespace_components(namespace=namespace)
+                if ns_id is not None:
+                    try:
+                        models = await libjuju.list_models(contains=ns_id)
+                        for model in models:
+                            await libjuju.destroy_model(
+                                model_name=model, total_timeout=total_timeout
+                            )
+                    except Exception as e:
+                        raise N2VCException(
+                            message="Error deleting namespace {} : {}".format(
+                                namespace, e
+                            )
+                        )
+                else:
+                    raise N2VCBadArgumentsException(
+                        message="only ns_id is permitted to delete yet",
+                        bad_args=["namespace"],
+                    )
+        finally:
+            self.delete_namespace_locks.pop(namespace)
         self.log.info("Namespace {} deleted".format(namespace))
 
     async def delete_execution_environment(