def entity_ready(entity: ModelEntity) -> bool:
+ """
+ Check if the entity is ready
+
+ :param: entity: Model entity. It can be a machine, action, or application.
+
+ :returns: boolean saying if the entity is ready or not
+ """
entity_type = entity.entity_type
if entity_type == "machine":
return entity.agent_status in ["started"]
return entity.status in ["completed", "failed", "cancelled"]
elif entity_type == "application":
# Workaround for bug: https://github.com/juju/python-libjuju/issues/441
- return status(entity) in ["active", "blocked"]
+ return entity.status in ["active", "blocked"]
else:
raise EntityInvalidException("Unknown entity type: {}".format(entity_type))
+def application_ready(application: Application) -> bool:
+ """
+ Check if an application has a leader
+
+ :param: application: Application entity.
+
+ :returns: boolean saying if the application has a unit that is a leader.
+ """
+ ready_status_list = ["active", "blocked"]
+ application_ready = application.status in ready_status_list
+ units_ready = all(
+ unit.workload_status in ready_status_list for unit in application.units
+ )
+ return application_ready and units_ready
+
+
class JujuModelWatcher:
@staticmethod
async def wait_for_model(model: Model, timeout: float = 3600):
timeout = 3600.0
# Coroutine to wait until the entity reaches the final state
- wait_for_entity = asyncio.ensure_future(
- asyncio.wait_for(
- model.block_until(
- lambda: all(
- entity_ready(entity) for entity in model.applications.values()
- )
- ),
- timeout=timeout,
+ async def wait_until_model_ready():
+ wait_for_entity = asyncio.ensure_future(
+ asyncio.wait_for(
+ model.block_until(
+ lambda: all(
+ application_ready(application)
+ for application in model.applications.values()
+ ),
+ ),
+ timeout=timeout,
+ )
)
- )
- tasks = [wait_for_entity]
- try:
- await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
- finally:
- # Cancel tasks
- for task in tasks:
- task.cancel()
+ tasks = [wait_for_entity]
+ try:
+ await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
+ finally:
+ # Cancel tasks
+ for task in tasks:
+ task.cancel()
+
+ await wait_until_model_ready()
+ # Check model is still ready after 10 seconds
+
+ await asyncio.sleep(10)
+ await wait_until_model_ready()
@staticmethod
async def wait_for(
# Coroutine to wait until the entity reaches the final state
wait_for_entity = asyncio.ensure_future(
asyncio.wait_for(
- model.block_until(lambda: entity_ready(entity)), timeout=total_timeout,
+ model.block_until(lambda: entity_ready(entity)),
+ timeout=total_timeout,
)
)