Feature 9751: Centralized VCA for KNFs
[osm/N2VC.git] / n2vc / libjuju.py
index 8d1fdad..aa7afa1 100644 (file)
@@ -81,9 +81,12 @@ class Libjuju:
         self.log = log or logging.getLogger("Libjuju")
         self.db = db
         db_endpoints = self._get_api_endpoints_db()
         self.log = log or logging.getLogger("Libjuju")
         self.db = db
         db_endpoints = self._get_api_endpoints_db()
-        self.endpoints = db_endpoints or [endpoint]
-        if db_endpoints is None:
+        self.endpoints = None
+        if (db_endpoints and endpoint not in db_endpoints) or not db_endpoints:
+            self.endpoints = [endpoint]
             self._update_api_endpoints_db(self.endpoints)
             self._update_api_endpoints_db(self.endpoints)
+        else:
+            self.endpoints = db_endpoints
         self.api_proxy = api_proxy
         self.username = username
         self.password = password
         self.api_proxy = api_proxy
         self.username = username
         self.password = password
@@ -104,7 +107,10 @@ class Libjuju:
         self.models = set()
         self.log.debug("Libjuju initialized!")
 
         self.models = set()
         self.log.debug("Libjuju initialized!")
 
-        self.health_check_task = self.loop.create_task(self.health_check())
+        self.health_check_task = self._create_health_check_task()
+
+    def _create_health_check_task(self):
+        return self.loop.create_task(self.health_check())
 
     async def get_controller(self, timeout: float = 5.0) -> Controller:
         """
 
     async def get_controller(self, timeout: float = 5.0) -> Controller:
         """
@@ -159,7 +165,8 @@ class Libjuju:
 
         :param: controller: Controller that will be disconnected
         """
 
         :param: controller: Controller that will be disconnected
         """
-        await controller.disconnect()
+        if controller:
+            await controller.disconnect()
 
     async def add_model(self, model_name: str, cloud_name: str, credential_name=None):
         """
 
     async def add_model(self, model_name: str, cloud_name: str, credential_name=None):
         """
@@ -485,6 +492,28 @@ class Libjuju:
 
         return machine_id
 
 
         return machine_id
 
+    async def deploy(
+        self, uri: str, model_name: str, wait: bool = True, timeout: float = 3600
+    ):
+        """
+        Deploy bundle or charm: Similar to the juju CLI command `juju deploy`
+
+        :param: uri:            Path or Charm Store uri in which the charm or bundle can be found
+        :param: model_name:     Model name
+        :param: wait:           Indicates whether to wait or not until all applications are active
+        :param: timeout:        Time in seconds to wait until all applications are active
+        """
+        controller = await self.get_controller()
+        model = await self.get_model(controller, model_name)
+        try:
+            await model.deploy(uri)
+            if wait:
+                await JujuModelWatcher.wait_for_model(model, timeout=timeout)
+                self.log.debug("All units active in model {}".format(model_name))
+        finally:
+            await self.disconnect_model(model)
+            await self.disconnect_controller(controller)
+
     async def deploy_charm(
         self,
         application_name: str,
     async def deploy_charm(
         self,
         application_name: str,
@@ -995,6 +1024,7 @@ class Libjuju:
 
         :param: interval: Time in seconds between checks
         """
 
         :param: interval: Time in seconds between checks
         """
+        controller = None
         while True:
             try:
                 controller = await self.get_controller()
         while True:
             try:
                 controller = await self.get_controller()
@@ -1135,7 +1165,7 @@ class Libjuju:
             auth_type = "certificate"
         else:
             raise JujuInvalidK8sConfiguration("authentication method not supported")
             auth_type = "certificate"
         else:
             raise JujuInvalidK8sConfiguration("authentication method not supported")
-        return client.CloudCredential(auth_type=auth_type, attrs=attrs,)
+        return client.CloudCredential(auth_type=auth_type, attrs=attrs)
 
     async def add_cloud(
         self,
 
     async def add_cloud(
         self,