diff --git a/cou/apps/base.py b/cou/apps/base.py index 05a4ff53..29232bc5 100644 --- a/cou/apps/base.py +++ b/cou/apps/base.py @@ -147,7 +147,7 @@ def __repr__(self) -> str: def apt_source_codename(self) -> OpenStackRelease: """Identify the OpenStack release set on "openstack-origin" or "source" config. - :raises ApplicationError: When origin setting is not valid. + :raises ApplicationError: When origin setting or series are not valid. :return: OpenStackRelease object. :rtype: OpenStackRelease """ @@ -160,6 +160,8 @@ def apt_source_codename(self) -> OpenStackRelease: if self.os_origin == "distro": # find the OpenStack release based on ubuntu series + if self.series not in DISTRO_TO_OPENSTACK_MAPPING: + raise ApplicationError(f"Series '{self.series}' is not supported by COU.") return OpenStackRelease(DISTRO_TO_OPENSTACK_MAPPING[self.series]) # probably because user set a ppa or a url @@ -205,9 +207,16 @@ def channel_codename(self) -> OpenStackRelease: def current_os_release(self) -> OpenStackRelease: """Current OpenStack Release of the application. + Applications that are colocated in a same machine will upgrade all the packages in the + machine during an upgrade. This means that when upgrading a application X, the application + Y colocated with it also upgrades its packages. To ensure to change the 'source' or + 'openstack-origin' and run all the upgrade steps necessary, it's necessary to include the + OpenStack release set in the application configuration. :return: OpenStackRelease object :rtype: OpenStackRelease """ + if self.os_origin: + return min(list(self.os_release_units.keys()) + [self.apt_source_codename]) return min(self.os_release_units.keys()) @property diff --git a/cou/steps/plan.py b/cou/steps/plan.py index dabd622f..f3284797 100644 --- a/cou/steps/plan.py +++ b/cou/steps/plan.py @@ -400,7 +400,7 @@ def _get_post_upgrade_steps(analysis_result: Analysis, args: CLIargs) -> list[Po """ steps = [] if args.upgrade_group in {DATA_PLANE, None}: - steps.extend(_get_ceph_mon_post_upgrade_steps(analysis_result.apps_data_plane)) + steps.extend(_get_ceph_mon_post_upgrade_steps(analysis_result.apps_control_plane)) return steps @@ -415,7 +415,11 @@ def _get_ceph_mon_post_upgrade_steps(apps: list[OpenStackApplication]) -> list[P """ ceph_mons_apps = [app for app in apps if isinstance(app, CephMon)] - steps = [] + steps: list[PostUpgradeStep] = [] + if not ceph_mons_apps: + logger.warning("There is no ceph-mon application. Is this a valid OpenStack cloud?") + return steps + for app in ceph_mons_apps: unit = list(app.units.values())[0] # getting the first unit, since we don't care which one steps.append( diff --git a/tests/mocked_plans/sample_plans/018346c5-f95c-46df-a34e-9a78bdec0018.yaml b/tests/mocked_plans/sample_plans/018346c5-f95c-46df-a34e-9a78bdec0018.yaml index e634e0cd..9d884d1b 100644 --- a/tests/mocked_plans/sample_plans/018346c5-f95c-46df-a34e-9a78bdec0018.yaml +++ b/tests/mocked_plans/sample_plans/018346c5-f95c-46df-a34e-9a78bdec0018.yaml @@ -497,6 +497,7 @@ plan: | Upgrade 'cinder-lvm-slow' to the new channel: 'victoria/stable' Upgrade plan for 'cinder-volume-mysql-router' to 'victoria' Refresh 'cinder-volume-mysql-router' to the latest revision of '8.0/stable' + Ensure that the 'require-osd-release' option in 'ceph-mon' matches the 'ceph-osd' version applications: diff --git a/tests/mocked_plans/sample_plans/9eb9af6a-b919-4cf9-8f2f-9df16a1556be.yaml b/tests/mocked_plans/sample_plans/9eb9af6a-b919-4cf9-8f2f-9df16a1556be.yaml index 53d4b3a0..5a004291 100644 --- a/tests/mocked_plans/sample_plans/9eb9af6a-b919-4cf9-8f2f-9df16a1556be.yaml +++ b/tests/mocked_plans/sample_plans/9eb9af6a-b919-4cf9-8f2f-9df16a1556be.yaml @@ -433,6 +433,7 @@ plan: | Upgrade plan for 'ovn-chassis' to 'victoria' WARNING: Changing 'ovn-chassis' channel from latest/stable to 22.03/stable. This may be a charm downgrade, which is generally not supported. Upgrade 'ovn-chassis' to the new channel: '22.03/stable' + Ensure that the 'require-osd-release' option in 'ceph-mon' matches the 'ceph-osd' version applications: rabbitmq-server: diff --git a/tests/unit/apps/test_auxiliary.py b/tests/unit/apps/test_auxiliary.py index e612c3d7..f2a5579f 100644 --- a/tests/unit/apps/test_auxiliary.py +++ b/tests/unit/apps/test_auxiliary.py @@ -72,7 +72,11 @@ def test_auxiliary_app(model): assert app.apt_source_codename == "ussuri" assert app.channel_codename == "yoga" assert app.is_subordinate is False - assert app.current_os_release == "yoga" + + # the workload version of units are considered as yoga + assert min(app.os_release_units.keys()) == "yoga" + # application is considered as ussuri because the source is pointing to it + assert app.current_os_release == "ussuri" def test_auxiliary_app_cs(model): @@ -104,7 +108,10 @@ def test_auxiliary_app_cs(model): assert app.os_origin == "distro" assert app.apt_source_codename == "ussuri" assert app.channel_codename == "ussuri" - assert app.current_os_release == "yoga" + # the workload version of units are considered as yoga + assert min(app.os_release_units.keys()) == "yoga" + # application is considered as ussuri because the source is pointing to it + assert app.current_os_release == "ussuri" def test_auxiliary_upgrade_plan_ussuri_to_victoria_change_channel(model): @@ -397,12 +404,7 @@ def test_auxiliary_raise_error_unknown_series(model): """Test auxiliary application with unknown series.""" series = "foo" channel = "3.8/stable" - exp_msg = ( - f"Channel: {channel} for charm 'rabbitmq-server' on series '{series}' is not supported by " - "COU. Please take a look at the documentation: " - "https://docs.openstack.org/charm-guide/latest/project/charm-delivery.html " - "to see if you are using the right track." - ) + exp_msg = "Series 'foo' is not supported by COU." machines = {"0": MagicMock(spec_set=Machine)} app = RabbitMQServer( name="rabbitmq-server", @@ -818,7 +820,7 @@ def test_ovn_principal(model): assert app.os_origin == "distro" assert app.apt_source_codename == "ussuri" assert app.channel_codename == "yoga" - assert app.current_os_release == "yoga" + assert app.current_os_release == "ussuri" assert app.is_subordinate is False diff --git a/tests/unit/steps/test_analyze.py b/tests/unit/steps/test_analyze.py index 0a9f8849..f383bb5c 100644 --- a/tests/unit/steps/test_analyze.py +++ b/tests/unit/steps/test_analyze.py @@ -451,7 +451,7 @@ async def test_analysis_detect_current_cloud_series_different_series(model): can_upgrade_to="ussuri/stable", charm="cinder", channel="ussuri/stable", - config={"source": {"value": "distro"}}, + config={"source": {"value": "cloud:bionic-ussuri"}}, machines=machines, model=model, origin="ch", diff --git a/tests/unit/steps/test_plan.py b/tests/unit/steps/test_plan.py index 1c5c59b3..0906ee9a 100644 --- a/tests/unit/steps/test_plan.py +++ b/tests/unit/steps/test_plan.py @@ -1063,7 +1063,7 @@ def test_get_post_upgrade_steps_ceph_mon(mock_get_ceph_mon_post_upgrade_steps, u pre_upgrade_steps = cou_plan._get_post_upgrade_steps(analysis_result, args) assert pre_upgrade_steps == mock_get_ceph_mon_post_upgrade_steps.return_value - mock_get_ceph_mon_post_upgrade_steps.assert_called_with(analysis_result.apps_data_plane) + mock_get_ceph_mon_post_upgrade_steps.assert_called_with(analysis_result.apps_control_plane) def test_get_ceph_mon_post_upgrade_steps_zero(model):