Syncronize with fs before action and reverse sync after action to allow high availabi...
[osm/N2VC.git] / n2vc / libjuju.py
index 8d1fdad..5a3ddbb 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.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)
+        else:
+            self.endpoints = db_endpoints
         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.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:
         """
@@ -159,7 +165,8 @@ class Libjuju:
 
         :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):
         """
@@ -485,6 +492,28 @@ class Libjuju:
 
         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,
@@ -924,15 +953,17 @@ class Libjuju:
         self.log.debug("Configuring application {}".format(application_name))
 
         if config:
+            controller = await self.get_controller()
+            model = None
             try:
-                controller = await self.get_controller()
                 model = await self.get_model(controller, model_name)
                 application = self._get_application(
                     model, application_name=application_name,
                 )
                 await application.set_config(config)
             finally:
-                await self.disconnect_model(model)
+                if model:
+                    await self.disconnect_model(model)
                 await self.disconnect_controller(controller)
 
     def _get_api_endpoints_db(self) -> [str]:
@@ -995,6 +1026,7 @@ class Libjuju:
 
         :param: interval: Time in seconds between checks
         """
+        controller = None
         while True:
             try:
                 controller = await self.get_controller()
@@ -1135,7 +1167,7 @@ class Libjuju:
             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,