Skip to content

Commit

Permalink
Merge branch 'dev/data-plane' into separate_plans
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielcocenza committed Feb 29, 2024
2 parents 11ca8c2 + 824996d commit bf35481
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 83 deletions.
61 changes: 37 additions & 24 deletions cou/apps/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
import logging
from collections import defaultdict
from dataclasses import dataclass, field
from io import StringIO
from typing import Any, Iterable, Optional

from ruamel.yaml import YAML
import yaml

from cou.exceptions import (
ApplicationError,
Expand All @@ -46,6 +45,8 @@
logger = logging.getLogger(__name__)

DEFAULT_WAITING_TIMEOUT = 5 * 60 # 5 min
ORIGIN_SETTINGS = ("openstack-origin", "source")
REQUIRED_SETTINGS = ("enable-auto-restarts", "action-managed-upgrade", *ORIGIN_SETTINGS)


@dataclass(frozen=True)
Expand Down Expand Up @@ -99,23 +100,38 @@ def __str__(self) -> str:
summary = {
self.name: {
"model_name": self.model.name,
"can_upgrade_to": self.can_upgrade_to,
"charm": self.charm,
"charm_origin": self.origin,
"os_origin": self.os_origin,
"channel": self.channel,
# Note (rgildein): sanitized the config
"config": {
key: self.config[key] for key in self.config if key in REQUIRED_SETTINGS
},
"origin": self.origin,
"series": self.series,
"subordinate_to": self.subordinate_to,
"workload_version": self.workload_version,
"units": {
unit.name: {
"name": unit.name,
"machine": unit.machine.machine_id,
"workload_version": unit.workload_version,
"os_version": str(self._get_latest_os_version(unit)),
}
for unit in self.units.values()
},
"machines": {
machine.machine_id: {
"id": machine.machine_id,
"apps": machine.apps,
"az": machine.az,
}
for machine in self.machines.values()
},
}
}
yaml = YAML()
with StringIO() as stream:
yaml.dump(summary, stream)
return stream.getvalue()

return yaml.dump(summary, sort_keys=False)

def _verify_channel(self) -> None:
"""Verify app channel from current data.
Expand Down Expand Up @@ -155,7 +171,7 @@ def origin_setting(self) -> Optional[str]:
:return: return name of charm origin setting, e.g. "source", "openstack-origin" or None
:rtype: Optional[str]
"""
for origin in ("openstack-origin", "source"):
for origin in ORIGIN_SETTINGS:
if origin in self.config:
return origin

Expand Down Expand Up @@ -410,18 +426,17 @@ def generate_upgrade_plan(
:return: Full upgrade plan if the Application is able to generate it.
:rtype: ApplicationUpgradePlan
"""
upgrade_steps = ApplicationUpgradePlan(
upgrade_plan = ApplicationUpgradePlan(
description=f"Upgrade plan for '{self.name}' to {target}",
)
all_steps = (
self.pre_upgrade_steps(target, units)
+ self.upgrade_steps(target, units, force)
+ self.post_upgrade_steps(target, units)
)
for step in all_steps:
if step:
upgrade_steps.add_step(step)
return upgrade_steps

upgrade_plan.sub_steps = [
*self.pre_upgrade_steps(target, units),
*self.upgrade_steps(target, units, force),
*self.post_upgrade_steps(target, units),
]

return upgrade_plan

def _get_upgrade_current_release_packages_step(
self, units: Optional[list[COUUnit]]
Expand Down Expand Up @@ -471,10 +486,8 @@ def _get_refresh_charm_step(self, target: OpenStackRelease) -> PreUpgradeStep:
# corner case for rabbitmq and hacluster.
if len(self.possible_current_channels) > 1:
logger.info(
(
"'%s' has more than one channel compatible with the current OpenStack "
"release: '%s'. '%s' will be used"
),
"'%s' has more than one channel compatible with the current OpenStack release: "
"'%s'. '%s' will be used",
self.name,
self.current_os_release.codename,
channel,
Expand Down Expand Up @@ -574,7 +587,7 @@ def _get_resume_unit_step(self, unit: COUUnit, dependent: bool = False) -> UnitU
:rtype: UnitUpgradeStep
"""
return UnitUpgradeStep(
description=(f"Resume the unit: '{unit.name}'."),
description=f"Resume the unit: '{unit.name}'.",
coro=self.model.run_action(
unit_name=unit.name, action_name="resume", raise_on_failure=True
),
Expand Down
5 changes: 5 additions & 0 deletions cou/steps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def description(self, description: str) -> None:
"""
if not description and self._coro:
raise ValueError("Every coroutine should have a description")

self._description = description

@property
Expand Down Expand Up @@ -244,6 +245,10 @@ def add_step(self, step: BaseStep) -> None:
if not isinstance(step, BaseStep):
raise TypeError("Cannot add an upgrade step that is not derived from BaseStep")

if not step:
logger.debug("skipping adding empty step")
return

self._sub_steps.append(step)

def cancel(self, safe: bool = True) -> None:
Expand Down
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ install_requires =
oslo.config
juju<3.0
colorama
ruamel.yaml
packaging
aioconsole
halo
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/apps/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ def test_nova_compute_upgrade_plan(model):
Upgrade software packages on unit nova-compute/1
Upgrade software packages on unit nova-compute/2
Refresh 'nova-compute' to the latest revision of 'ussuri/stable'
Change charm config of 'nova-compute' 'action-managed-upgrade' to True.
Change charm config of 'nova-compute' 'action-managed-upgrade' to True
Upgrade 'nova-compute' to the new channel: 'victoria/stable'
Change charm config of 'nova-compute' 'source' to 'cloud:focal-victoria'
Upgrade plan for units: nova-compute/0, nova-compute/1, nova-compute/2
Expand Down Expand Up @@ -933,7 +933,7 @@ def test_nova_compute_upgrade_plan(model):
can_upgrade_to="ussuri/stable",
charm="nova-compute",
channel="ussuri/stable",
config={"source": {"value": "distro"}},
config={"source": {"value": "distro"}, "action-managed-upgrade": {"value": False}},
machines=machines,
model=model,
origin="ch",
Expand All @@ -957,7 +957,7 @@ def test_nova_compute_upgrade_plan_single_unit(model):
Upgrade software packages of 'nova-compute' from the current APT repositories
Upgrade software packages on unit nova-compute/0
Refresh 'nova-compute' to the latest revision of 'ussuri/stable'
Change charm config of 'nova-compute' 'action-managed-upgrade' to True.
Change charm config of 'nova-compute' 'action-managed-upgrade' to True
Upgrade 'nova-compute' to the new channel: 'victoria/stable'
Change charm config of 'nova-compute' 'source' to 'cloud:focal-victoria'
Upgrade plan for units: nova-compute/0
Expand Down Expand Up @@ -986,7 +986,7 @@ def test_nova_compute_upgrade_plan_single_unit(model):
can_upgrade_to="ussuri/stable",
charm="nova-compute",
channel="ussuri/stable",
config={"source": {"value": "distro"}},
config={"source": {"value": "distro"}, "action-managed-upgrade": {"value": False}},
machines=machines,
model=model,
origin="ch",
Expand Down
24 changes: 20 additions & 4 deletions tests/unit/steps/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,14 @@ def test_step_bool():
sub_step = BaseStep(description="a.a")
assert bool(sub_step) is False

plan.sub_steps = [sub_step]
plan.add_step(sub_step)
assert bool(plan) is False

# coroutine in the plan sub_steps tree
sub_sub_step = BaseStep(description="a.a.a", coro=mock_coro("a.a.a"))
sub_step.sub_steps = [sub_sub_step]
sub_step.add_step(sub_sub_step)
plan.add_step(sub_step)

assert bool(sub_sub_step) is True
assert bool(sub_step) is True
assert bool(plan) is True
Expand Down Expand Up @@ -225,6 +227,16 @@ def test_step_add_step():
exp_sub_steps = 3
plan = BaseStep(description="plan")
for i in range(exp_sub_steps):
plan.add_step(BaseStep(description=f"sub-step-{i}", coro=mock_coro()))

assert len(plan.sub_steps) == exp_sub_steps


def test_step_add_step_skipping_empty():
"""Test BaseStep skipping to add empty sub steps."""
exp_sub_steps = 0
plan = BaseStep(description="plan")
for i in range(3):
plan.add_step(BaseStep(description=f"sub-step-{i}"))

assert len(plan.sub_steps) == exp_sub_steps
Expand All @@ -242,9 +254,13 @@ def test_step_add_step_failed():
def test_step_cancel_safe():
"""Test step safe cancel."""
plan = BaseStep(description="plan")
plan.sub_steps = sub_steps = [BaseStep(description=f"sub-{i}") for i in range(10)]
plan.sub_steps = sub_steps = [
BaseStep(description=f"sub-{i}", coro=mock_coro()) for i in range(10)
]
# add sub-sub-steps to one sub-step
sub_steps[0].sub_steps = [BaseStep(description=f"sub-0.{i}") for i in range(3)]
sub_steps[0].sub_steps = [
BaseStep(description=f"sub-0.{i}", coro=mock_coro()) for i in range(3)
]

plan.cancel()

Expand Down
Loading

0 comments on commit bf35481

Please sign in to comment.