From 8336b75c4029717b0aad09259169265fe39df2cf Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 11 Jun 2020 10:01:00 +0000 Subject: [PATCH] Add test to perform charm upgrade. Add test to perform charm upgrade and a few small tweaks to the upgrade utils. --- .../charm_tests/charm_upgrade/__init__.py | 15 ++++ .../charm_tests/charm_upgrade/tests.py | 78 +++++++++++++++++++ zaza/openstack/utilities/upgrade_utils.py | 57 +++++++++----- 3 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 zaza/openstack/charm_tests/charm_upgrade/__init__.py create mode 100644 zaza/openstack/charm_tests/charm_upgrade/tests.py diff --git a/zaza/openstack/charm_tests/charm_upgrade/__init__.py b/zaza/openstack/charm_tests/charm_upgrade/__init__.py new file mode 100644 index 0000000..fc5baa5 --- /dev/null +++ b/zaza/openstack/charm_tests/charm_upgrade/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test charm upgrade.""" diff --git a/zaza/openstack/charm_tests/charm_upgrade/tests.py b/zaza/openstack/charm_tests/charm_upgrade/tests.py new file mode 100644 index 0000000..0ffd30b --- /dev/null +++ b/zaza/openstack/charm_tests/charm_upgrade/tests.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 + +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Define class for Charm Upgrade.""" + +import logging +import unittest + +import zaza.model +from zaza.openstack.utilities import ( + cli as cli_utils, + upgrade_utils as upgrade_utils, +) +from zaza.openstack.charm_tests.nova.tests import LTSGuestCreateTest + + +class FullCloudCharmUpgradeTest(unittest.TestCase): + """Class to encapsulate Charm Upgrade Tests.""" + + @classmethod + def setUpClass(cls): + """Run setup for Charm Upgrades.""" + cli_utils.setup_logging() + cls.lts = LTSGuestCreateTest() + cls.target_charm_namespace = '~openstack-charmers-next' + + def get_upgrade_url(self, charm_url): + """Return the charm_url to upgrade to. + + :param charm_url: Current charm url. + :type charm_url: str + """ + charm_name = upgrade_utils.extract_charm_name_from_url( + charm_url) + next_charm_url = zaza.model.get_latest_charm_url( + "cs:{}/{}".format(self.target_charm_namespace, charm_name)) + return next_charm_url + + def test_200_run_charm_upgrade(self): + """Run charm upgrade.""" + self.lts.test_launch_small_instance() + applications = zaza.model.get_status().applications + groups = upgrade_utils.get_charm_upgrade_groups() + for group_name, group in groups.items(): + logging.info("About to upgrade {} ({})".format(group_name, group)) + for application, app_details in applications.items(): + if application not in group: + continue + target_url = self.get_upgrade_url(app_details['charm']) + if target_url == app_details['charm']: + logging.warn( + "Skipping upgrade of {}, already using {}".format( + application, + target_url)) + else: + logging.info("Upgrading {} to {}".format( + application, + target_url)) + zaza.model.upgrade_charm( + application, + switch=target_url) + logging.info("Waiting for charm url to update") + zaza.model.block_until_charm_url(application, target_url) + zaza.model.block_until_all_units_idle() + self.lts.test_launch_small_instance() diff --git a/zaza/openstack/utilities/upgrade_utils.py b/zaza/openstack/utilities/upgrade_utils.py index 4066d19..b134a69 100644 --- a/zaza/openstack/utilities/upgrade_utils.py +++ b/zaza/openstack/utilities/upgrade_utils.py @@ -20,7 +20,8 @@ import zaza.model SERVICE_GROUPS = collections.OrderedDict([ - ('Stateful Services', ['percona-cluster', 'rabbitmq-server', 'ceph-mon']), + ('Stateful Services', ['percona-cluster', 'rabbitmq-server', 'ceph-mon', + 'mysql-innodb-cluster']), ('Core Identity', ['keystone']), ('Control Plane', [ 'aodh', 'barbican', 'ceilometer', 'ceph-fs', @@ -92,6 +93,19 @@ def _filter_non_openstack_services(app, app_config, model_name=None): return False +def _apply_extra_filters(filters, extra_filters): + if extra_filters: + if isinstance(extra_filters, list): + filters.extend(extra_filters) + elif callable(extra_filters): + filters.append(extra_filters) + else: + raise RuntimeError( + "extra_filters should be a list of " + "callables") + return filters + + def get_upgrade_groups(model_name=None, extra_filters=None): """Place apps in the model into their upgrade groups. @@ -108,18 +122,10 @@ def get_upgrade_groups(model_name=None, extra_filters=None): _filter_openstack_upgrade_list, _filter_non_openstack_services, ] - if extra_filters: - if isinstance(extra_filters, list): - filters.extend(extra_filters) - elif callable(extra_filters): - filters.append(extra_filters) - else: - raise RuntimeError( - "extra_filters should be a list of " - "callables") + filters = _apply_extra_filters(filters, extra_filters) apps_in_model = get_upgrade_candidates( model_name=model_name, - filters=filters,) + filters=filters) return _build_service_groups(apps_in_model) @@ -136,15 +142,26 @@ def get_series_upgrade_groups(model_name=None, extra_filters=None): :rtype: collections.OrderedDict """ filters = [_filter_subordinates] - if extra_filters: - if isinstance(extra_filters, list): - filters.extend(extra_filters) - elif callable(extra_filters): - filters.append(extra_filters) - else: - raise RuntimeError( - "extra_filters should be a list of " - "callables") + filters = _apply_extra_filters(filters, extra_filters) + apps_in_model = get_upgrade_candidates( + model_name=model_name, + filters=filters) + + return _build_service_groups(apps_in_model) + + +def get_charm_upgrade_groups(model_name=None, extra_filters=None): + """Place apps in the model into their upgrade groups for a charm upgrade. + + Place apps in the model into their upgrade groups. If an app is deployed + but is not in SERVICE_GROUPS then it is placed in a sweep_up group. + + :param model_name: Name of model to query. + :type model_name: str + :returns: Dict of group lists keyed on group name. + :rtype: collections.OrderedDict + """ + filters = _apply_extra_filters([], extra_filters) apps_in_model = get_upgrade_candidates( model_name=model_name, filters=filters)