Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing Machine for OpenStackApplication #298

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions cou/apps/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
UpgradeStep,
)
from cou.utils.app_utils import upgrade_packages
from cou.utils.juju_utils import COUModel
from cou.utils.juju_utils import COUModel, Machine
from cou.utils.openstack import (
DISTRO_TO_OPENSTACK_MAPPING,
OpenStackCodenameLookup,
Expand All @@ -59,8 +59,8 @@ class ApplicationUnit:

name: str
os_version: OpenStackRelease
machine: Machine
workload_version: str = ""
machine: str = ""


@dataclass
Expand All @@ -77,6 +77,8 @@ class OpenStackApplication:
:type model: COUModel
:param charm: Name of the charm.
:type charm: str
:param machines: dictionary with Machine
:type machines: dict[str, Machine]
:param units: Units representation of an application.
:type units: list[ApplicationUnit]
:raises ApplicationError: When there are no compatible OpenStack release for the
Expand All @@ -95,6 +97,7 @@ class OpenStackApplication:
config: dict
model: COUModel
charm: str
machines: dict[str, Machine]
units: list[ApplicationUnit] = field(default_factory=lambda: [])
packages_to_hold: Optional[list] = field(default=None, init=False)
wait_timeout: int = field(default=STANDARD_IDLE_TIMEOUT, init=False)
Expand Down Expand Up @@ -177,7 +180,7 @@ def _populate_units(self) -> None:
name=name,
workload_version=unit.workload_version,
os_version=compatible_os_version,
machine=unit.machine,
machine=self.machines[unit.machine],
)
)

Expand Down Expand Up @@ -390,16 +393,8 @@ def channel_codename(self) -> OpenStackRelease:
:return: OpenStackRelease object
:rtype: OpenStackRelease
"""
try:
# get the OpenStack release from the channel track of the application.
os_track_release_channel = OpenStackRelease(self._get_track_from_channel(self.channel))
except ValueError:
logger.debug(
"The current channel of '%s' does not exist or is unexpectedly formatted",
self.name,
)
os_track_release_channel = self.current_os_release
return os_track_release_channel
gabrielcocenza marked this conversation as resolved.
Show resolved Hide resolved
# get the OpenStack release from the channel track of the application.
return OpenStackRelease(self._get_track_from_channel(self.channel))

@property
def can_upgrade_current_channel(self) -> bool:
Expand Down
14 changes: 12 additions & 2 deletions cou/apps/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from juju.client._definitions import ApplicationStatus

from cou.apps.base import OpenStackApplication
from cou.utils.juju_utils import COUModel
from cou.utils.juju_utils import COUModel, Machine
from cou.utils.openstack import is_charm_supported

logger = logging.getLogger(__name__)
Expand All @@ -41,13 +41,16 @@ def create(
config: dict,
model: COUModel,
charm: str,
machines: dict[str, Machine],
) -> Optional[OpenStackApplication]:
"""Create the OpenStackApplication or registered subclasses.

Applications Subclasses registered with the "register_application"
decorator can be instantiated and used with their customized methods.
:param name: Name of the application
:type name: str
:param machines: Machines in the model
:type machines: dict[str, Machine]
:param status: Status of the application
:type status: ApplicationStatus
:param config: Configuration of the application
Expand All @@ -62,7 +65,14 @@ def create(
# pylint: disable=too-many-arguments
if is_charm_supported(charm):
app_class = cls.charms.get(charm, OpenStackApplication)
return app_class(name=name, status=status, config=config, model=model, charm=charm)
return app_class(
name=name,
status=status,
config=config,
model=model,
charm=charm,
machines=machines,
)
logger.debug(
"'%s' is not a supported OpenStack related application and will be ignored.",
name,
Expand Down
5 changes: 5 additions & 0 deletions cou/steps/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,18 @@ async def _populate(cls, model: juju_utils.COUModel) -> list[OpenStackApplicatio
:rtype: List[OpenStackApplication]
"""
juju_status = await model.get_status()
juju_machines = await model.get_machines()
apps = {
AppFactory.create(
name=app,
status=app_status,
config=await model.get_application_config(app),
model=model,
charm=await model.get_charm_name(app),
machines={
unit_status.machine: juju_machines[unit_status.machine]
for unit_status in app_status.units.values()
},
)
for app, app_status in juju_status.applications.items()
if app_status
Expand Down
31 changes: 31 additions & 0 deletions cou/utils/juju_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import asyncio
import logging
import os
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Callable, Optional

Expand Down Expand Up @@ -129,6 +130,15 @@ async def wrapper(*args: Any, **kwargs: Any) -> Any: # pylint: disable=W9011
return _wrapper


@dataclass(frozen=True)
class Machine:
"""Representation of a juju machine."""

machine_id: str
apps: tuple[str]
az: Optional[str] = None # simple deployments may not have azs


class COUModel:
"""COU model object.

Expand Down Expand Up @@ -499,3 +509,24 @@ async def _wait_for_active_idle() -> None:
apps = await self._get_supported_apps()

await _wait_for_active_idle()

async def get_machines(self) -> dict[str, Machine]:
"""Get all the machines in the model.

:return: Dictionary of the machines found in the model. E.g: {'0': Machine0}
:rtype: dict[str, Machine]
"""
model = await self._get_model()

return {
machine.id: Machine(
machine_id=machine.id,
apps=tuple(
unit.application
for unit in self._model.units.values()
if unit.machine.id == machine.id
),
az=machine.hardware_characteristics.get("availability-zone"),
)
for machine in model.machines.values()
}
Loading
Loading