import time
-from juju.errors import JujuAPIError
+import juju.errors
from juju.model import Model
from juju.machine import Machine
from juju.application import Application
db_dict: dict = None,
progress_timeout: float = None,
total_timeout: float = None,
- series: str = "xenial",
+ series: str = "bionic",
wait: bool = True,
) -> (Machine, bool):
"""
db_dict: dict = None,
progress_timeout: float = None,
total_timeout: float = None,
- **kwargs
+ **kwargs,
):
"""Execute action
# Add relation
try:
await model.add_relation(endpoint_1, endpoint_2)
- except JujuAPIError as e:
+ except juju.errors.JujuAPIError as e:
if "not found" in e.message:
self.log.warning("Relation not found: {}".format(e.message))
return
finally:
await self.disconnect_controller(controller)
- async def destroy_application(self, model: Model, application_name: str):
+ async def destroy_application(
+ self, model_name: str, application_name: str, total_timeout: float
+ ):
"""
Destroy application
- :param: model: Model object
+ :param: model_name: Model name
:param: application_name: Application name
+ :param: total_timeout: Timeout
"""
- self.log.debug(
- "Destroying application {} in model {}".format(
- application_name, model.info.name
+
+ controller = await self.get_controller()
+ model = None
+
+ try:
+ model = await self.get_model(controller, model_name)
+ self.log.debug(
+ "Destroying application {} in model {}".format(
+ application_name, model_name
+ )
)
- )
- application = model.applications.get(application_name)
- if application:
- await application.destroy()
- else:
- self.log.warning("Application not found: {}".format(application_name))
+ application = self._get_application(model, application_name)
+ if application:
+ await application.destroy()
+ else:
+ self.log.warning("Application not found: {}".format(application_name))
+
+ self.log.debug(
+ "Waiting for application {} to be destroyed in model {}...".format(
+ application_name, model_name
+ )
+ )
+ if total_timeout is None:
+ total_timeout = 3600
+ end = time.time() + total_timeout
+ while time.time() < end:
+ if not self._get_application(model, application_name):
+ self.log.debug(
+ "The application {} was destroyed in model {} ".format(
+ application_name, model_name
+ )
+ )
+ return
+ await asyncio.sleep(5)
+ raise Exception(
+ "Timeout waiting for application {} to be destroyed in model {}".format(
+ application_name, model_name
+ )
+ )
+ finally:
+ if model is not None:
+ await self.disconnect_model(model)
+ await self.disconnect_controller(controller)
async def _destroy_pending_machines(self, model: Model, only_manual: bool = False):
"""
machine = model.machines[machine_id]
await machine.destroy(force=True)
- # async def destroy_machine(
- # self, model: Model, machine_id: str, total_timeout: float = 3600
- # ):
- # """
- # Destroy machine
-
- # :param: model: Model object
- # :param: machine_id: Machine id
- # :param: total_timeout: Timeout in seconds
- # """
- # machines = await model.get_machines()
- # if machine_id in machines:
- # machine = machines[machine_id]
- # await machine.destroy(force=True)
- # # max timeout
- # end = time.time() + total_timeout
-
- # # wait for machine removal
- # machines = await model.get_machines()
- # while machine_id in machines and time.time() < end:
- # self.log.debug("Waiting for machine {} is destroyed".format(machine_id))
- # await asyncio.sleep(0.5)
- # machines = await model.get_machines()
- # self.log.debug("Machine destroyed: {}".format(machine_id))
- # else:
- # self.log.debug("Machine not found: {}".format(machine_id))
-
async def configure_application(
self, model_name: str, application_name: str, config: dict = None
):
controller = await self.get_controller()
try:
await controller.remove_cloud(name)
+ except juju.errors.JujuError as e:
+ if len(e.errors) == 1 and f'cloud "{name}" not found' == e.errors[0]:
+ self.log.warning(f"Cloud {name} not found, so it could not be deleted.")
+ else:
+ raise e
finally:
await self.disconnect_controller(controller)