diff --git a/unit_tests/test_zaza_model.py b/unit_tests/test_zaza_model.py index b911888..fe567b9 100644 --- a/unit_tests/test_zaza_model.py +++ b/unit_tests/test_zaza_model.py @@ -974,6 +974,38 @@ disk_formats = ami,ari,aki,vhd,vmdk,raw,qcow2,vdi,iso,root-tar with self.assertRaises(asyncio.futures.TimeoutError): model.wait_for_agent_status(timeout=0.1) + def test_prepare_series_upgrade(self): + self.patch_object(model, 'subprocess') + self.patch_object(model, 'get_juju_model', + return_value=self.model_name) + _machine_num = "1" + _to_series = "bionic" + model.prepare_series_upgrade(_machine_num, to_series=_to_series) + self.subprocess.check_call.assert_called_once_with( + ["juju", "upgrade-series", "-m", self.model_name, + "prepare", _machine_num, _to_series, "--agree"]) + + def test_complete_series_upgrade(self): + self.patch_object(model, 'get_juju_model', + return_value=self.model_name) + self.patch_object(model, 'subprocess') + _machine_num = "1" + model.complete_series_upgrade(_machine_num) + self.subprocess.check_call.assert_called_once_with( + ["juju", "upgrade-series", "-m", self.model_name, + "complete", _machine_num]) + + def test_set_series(self): + self.patch_object(model, 'get_juju_model', + return_value=self.model_name) + self.patch_object(model, 'subprocess') + _application = "application" + _to_series = "bionic" + model.set_series(_application, _to_series) + self.subprocess.check_call.assert_called_once_with( + ["juju", "set-series", "-m", self.model_name, + _application, _to_series]) + class AsyncModelTests(aiounittest.AsyncTestCase): diff --git a/unit_tests/utilities/test_zaza_utilities_generic.py b/unit_tests/utilities/test_zaza_utilities_generic.py index 76481fc..f44bf74 100644 --- a/unit_tests/utilities/test_zaza_utilities_generic.py +++ b/unit_tests/utilities/test_zaza_utilities_generic.py @@ -47,6 +47,12 @@ class TestGenericUtils(ut_utils.BaseTestCase): name='subprocess' ) + # Juju Status Object and data + self.juju_status = mock.MagicMock() + self.juju_status.applications.__getitem__.return_value = FAKE_STATUS + self.patch_object(generic_utils, "model") + self.model.get_status.return_value = self.juju_status + def test_dict_to_yaml(self): _dict_data = {"key": "value"} _str_data = "key: value\n" @@ -215,9 +221,9 @@ class TestGenericUtils(ut_utils.BaseTestCase): def test_series_upgrade(self): self.patch_object(generic_utils.model, "block_until_all_units_idle") self.patch_object(generic_utils.model, "block_until_unit_wl_status") - self.patch_object(generic_utils.juju_utils, "prepare_series_upgrade") - self.patch_object(generic_utils.juju_utils, "complete_series_upgrade") - self.patch_object(generic_utils.juju_utils, "set_series") + self.patch_object(generic_utils.model, "prepare_series_upgrade") + self.patch_object(generic_utils.model, "complete_series_upgrade") + self.patch_object(generic_utils.model, "set_series") self.patch_object(generic_utils, "set_origin") self.patch_object(generic_utils, "wrap_do_release_upgrade") self.patch_object(generic_utils, "reboot") @@ -245,10 +251,8 @@ class TestGenericUtils(ut_utils.BaseTestCase): self.reboot.assert_called_once_with(_unit) def test_series_upgrade_application_pause_peers_and_subordinates(self): - self.patch_object(generic_utils.juju_utils, "get_application_status") self.patch_object(generic_utils.model, "run_action") self.patch_object(generic_utils, "series_upgrade") - self.get_application_status.return_value = FAKE_STATUS _application = "app" _from_series = "xenial" _to_series = "bionic" @@ -284,10 +288,8 @@ class TestGenericUtils(ut_utils.BaseTestCase): self.series_upgrade.assert_has_calls(_series_upgrade_calls) def test_series_upgrade_application_pause_subordinates(self): - self.patch_object(generic_utils.juju_utils, "get_application_status") self.patch_object(generic_utils.model, "run_action") self.patch_object(generic_utils, "series_upgrade") - self.get_application_status.return_value = FAKE_STATUS _application = "app" _from_series = "xenial" _to_series = "bionic" @@ -302,6 +304,7 @@ class TestGenericUtils(ut_utils.BaseTestCase): "pause", action_params={}), ] _series_upgrade_calls = [] + for machine_num in ("0", "1", "2"): _series_upgrade_calls.append( mock.call("{}/{}".format(_application, machine_num), @@ -321,10 +324,8 @@ class TestGenericUtils(ut_utils.BaseTestCase): self.series_upgrade.assert_has_calls(_series_upgrade_calls) def test_series_upgrade_application_no_pause(self): - self.patch_object(generic_utils.juju_utils, "get_application_status") self.patch_object(generic_utils.model, "run_action") self.patch_object(generic_utils, "series_upgrade") - self.get_application_status.return_value = FAKE_STATUS _application = "app" _from_series = "xenial" _to_series = "bionic" @@ -332,6 +333,7 @@ class TestGenericUtils(ut_utils.BaseTestCase): _series_upgrade_calls = [] _files = ["filename", "scriptname"] _workaround_script = "scriptname" + for machine_num in ("0", "1", "2"): _series_upgrade_calls.append( mock.call("{}/{}".format(_application, machine_num), diff --git a/unit_tests/utilities/test_zaza_utilities_juju.py b/unit_tests/utilities/test_zaza_utilities_juju.py index e5cd43b..4754b6c 100644 --- a/unit_tests/utilities/test_zaza_utilities_juju.py +++ b/unit_tests/utilities/test_zaza_utilities_juju.py @@ -22,13 +22,6 @@ class TestJujuUtils(ut_utils.BaseTestCase): def setUp(self): super(TestJujuUtils, self).setUp() - # Patch all subprocess calls - self.patch( - 'zaza.utilities.juju.subprocess', - new_callable=mock.MagicMock(), - name='subprocess' - ) - # Juju Status Object and data self.key = "instance-id" self.key_data = "machine-uuid" @@ -264,34 +257,3 @@ class TestJujuUtils(ut_utils.BaseTestCase): key='series' ) self.assertEqual(expected, actual) - - def test_prepare_series_upgrade(self): - _machine_num = "1" - _to_series = "bionic" - juju_utils.prepare_series_upgrade(_machine_num, to_series=_to_series) - self.subprocess.check_call.assert_called_once_with( - ["juju", "upgrade-series", "-m", self.model_name, - "prepare", _machine_num, _to_series, "--agree"]) - - def test_complete_series_upgrade(self): - _machine_num = "1" - juju_utils.complete_series_upgrade(_machine_num) - self.subprocess.check_call.assert_called_once_with( - ["juju", "upgrade-series", "-m", self.model_name, - "complete", _machine_num]) - - def test_set_series(self): - _application = "application" - _to_series = "bionic" - juju_utils.set_series(_application, _to_series) - self.subprocess.check_call.assert_called_once_with( - ["juju", "set-series", "-m", self.model_name, - _application, _to_series]) - - def test_update_series(self): - _machine_num = "1" - _to_series = "bionic" - juju_utils.update_series(_machine_num, _to_series) - self.subprocess.check_call.assert_called_once_with( - ["juju", "update-series", "-m", self.model_name, - _machine_num, _to_series]) diff --git a/zaza/model.py b/zaza/model.py index 9670eb3..181b214 100644 --- a/zaza/model.py +++ b/zaza/model.py @@ -1183,3 +1183,62 @@ class UnitNotFound(Exception): msg = ('Unit: {} was not found in current model'. format(unit_name)) super(UnitNotFound, self).__init__(msg) + + +# NOTE: The following are series upgrade related functions which are new +# features in juju. We can migrate to libjuju calls when the feature +# stabilizes. +def prepare_series_upgrade(machine_num, to_series="xenial"): + """Execute juju series-upgrade prepare on machine. + + NOTE: This is a new feature in juju behind a feature flag and not yet in + libjuju. + export JUJU_DEV_FEATURE_FLAGS=upgrade-series + + :param machine_num: Machine number + :type machine_num: str + :param to_series: The series to which to upgrade + :type to_series: str + :returns: None + :rtype: None + """ + juju_model = get_juju_model() + cmd = ["juju", "upgrade-series", "-m", juju_model, + "prepare", machine_num, to_series, "--agree"] + subprocess.check_call(cmd) + + +def complete_series_upgrade(machine_num): + """Execute juju series-upgrade complete on machine. + + NOTE: This is a new feature in juju behind a feature flag and not yet in + libjuju. + export JUJU_DEV_FEATURE_FLAGS=upgrade-series + + :param machine_num: Machine number + :type machine_num: str + :returns: None + :rtype: None + """ + juju_model = get_juju_model() + cmd = ["juju", "upgrade-series", "-m", juju_model, + "complete", machine_num] + subprocess.check_call(cmd) + + +def set_series(application, to_series): + """Execute juju set-series complete on application. + + NOTE: This is a new feature in juju and not yet in libjuju. + + :param application: Name of application to upgrade series + :type application: str + :param to_series: The series to which to upgrade + :type to_series: str + :returns: None + :rtype: None + """ + juju_model = get_juju_model() + cmd = ["juju", "set-series", "-m", juju_model, + application, to_series] + subprocess.check_call(cmd) diff --git a/zaza/utilities/generic.py b/zaza/utilities/generic.py index 74ddfe5..b5a549c 100644 --- a/zaza/utilities/generic.py +++ b/zaza/utilities/generic.py @@ -201,7 +201,7 @@ def series_upgrade_application(application, pause_non_leader_primary=True, :returns: None :rtype: None """ - status = juju_utils.get_application_status(application=application) + status = model.get_status().applications[application] # For some applications (percona-cluster) the leader unit must upgrade # first. For API applications the non-leader haclusters must be paused @@ -270,7 +270,7 @@ def series_upgrade(unit_name, machine_num, logging.info("Series upgrade {}".format(unit_name)) application = unit_name.split('/')[0] logging.info("Prepare series upgrade on {}".format(machine_num)) - juju_utils.prepare_series_upgrade(machine_num, to_series=to_series) + model.prepare_series_upgrade(machine_num, to_series=to_series) logging.info("Watiing for workload status 'unknown' on {}" .format(unit_name)) model.block_until_unit_wl_status(unit_name, "unknown") @@ -285,7 +285,7 @@ def series_upgrade(unit_name, machine_num, logging.info("Watiing for model idleness") model.block_until_all_units_idle() logging.info("Complete series upgrade on {}".format(machine_num)) - juju_utils.complete_series_upgrade(machine_num) + model.complete_series_upgrade(machine_num) model.block_until_all_units_idle() logging.info("Watiing for workload status 'active' on {}" .format(unit_name)) @@ -296,7 +296,7 @@ def series_upgrade(unit_name, machine_num, model.block_until_all_units_idle() # This step may be performed by juju in the future logging.info("Set series on {} to {}".format(application, to_series)) - juju_utils.set_series(application, to_series) + model.set_series(application, to_series) def set_origin(application, origin='openstack-origin', pocket='distro'): diff --git a/zaza/utilities/juju.py b/zaza/utilities/juju.py index 642a3d4..6f3c792 100644 --- a/zaza/utilities/juju.py +++ b/zaza/utilities/juju.py @@ -16,7 +16,6 @@ """Module for interacting with juju.""" import os from pathlib import Path -import subprocess import yaml from zaza import ( @@ -259,77 +258,3 @@ def leader_get(application, key=''): return yaml.load(result.get('Stdout')) else: raise model.CommandRunFailed(cmd, result) - - -def prepare_series_upgrade(machine_num, to_series="xenial"): - """Execute juju series-upgrade prepare on machine. - - NOTE: This is a new feature in juju behind a feature flag and not yet in - libjuju. - export JUJU_DEV_FEATURE_FLAGS=upgrade-series - - :param machine_num: Machine number - :type machine_num: str - :param to_series: The series to which to upgrade - :type to_series: str - :returns: None - :rtype: None - """ - juju_model = model.get_juju_model() - cmd = ["juju", "upgrade-series", "-m", juju_model, - "prepare", machine_num, to_series, "--agree"] - subprocess.check_call(cmd) - - -def complete_series_upgrade(machine_num): - """Execute juju series-upgrade complete on machine. - - NOTE: This is a new feature in juju behind a feature flag and not yet in - libjuju. - export JUJU_DEV_FEATURE_FLAGS=upgrade-series - - :param machine_num: Machine number - :type machine_num: str - :returns: None - :rtype: None - """ - juju_model = model.get_juju_model() - cmd = ["juju", "upgrade-series", "-m", juju_model, - "complete", machine_num] - subprocess.check_call(cmd) - - -def set_series(application, to_series): - """Execute juju set-series complete on application. - - NOTE: This is a new feature in juju and not yet in libjuju. - - :param application: Name of application to upgrade series - :type application: str - :param to_series: The series to which to upgrade - :type to_series: str - :returns: None - :rtype: None - """ - juju_model = model.get_juju_model() - cmd = ["juju", "set-series", "-m", juju_model, - application, to_series] - subprocess.check_call(cmd) - - -def update_series(machine_num, to_series): - """Execute juju update-series complete on machine. - - NOTE: This is a new feature in juju and not yet in libjuju. - - :param machine_num: Machine number - :type machine_num: str - :param to_series: The series to which to upgrade - :type to_series: str - :returns: None - :rtype: None - """ - juju_model = model.get_juju_model() - cmd = ["juju", "update-series", "-m", juju_model, - machine_num, to_series] - subprocess.check_call(cmd)