From 0b401de17f1e2814f46184e5df0ec49d140902c8 Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Mon, 19 Apr 2021 17:03:05 -0400 Subject: [PATCH 1/3] Get OpenStack codename from /etc/openstack-release In newer versions of Ubuntu and the Cloud Archive (currently Hirsute, Wallaby, and above), there is an openstack-release package that, if installed, specifies the current OpenStack release in /etc/openstack-release. Also adds wallaby definitions to non-version definitions in os_versions.py. Fixes #560 --- .../test_zaza_utilities_openstack.py | 36 ++++++++++++- zaza/openstack/utilities/openstack.py | 50 +++++++++++++++++-- zaza/openstack/utilities/os_versions.py | 4 +- 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/unit_tests/utilities/test_zaza_utilities_openstack.py b/unit_tests/utilities/test_zaza_utilities_openstack.py index c42fc9d..b7f2eeb 100644 --- a/unit_tests/utilities/test_zaza_utilities_openstack.py +++ b/unit_tests/utilities/test_zaza_utilities_openstack.py @@ -884,7 +884,24 @@ class TestOpenStackUtils(ut_utils.BaseTestCase): result = openstack_utils.get_current_os_release_pair() self.assertEqual(expected, result) - def test_get_openstack_release(self): + def test_get_current_os_versions(self): + self.patch_object(openstack_utils, "get_openstack_release") + self.patch_object(openstack_utils.generic_utils, "get_pkg_version") + + # Pre-Wallaby scenario where openstack-release package isn't installed + self.get_openstack_release.return_value = None + self.get_pkg_version.return_value = '18.0.0' + expected = {'keystone': 'victoria'} + result = openstack_utils.get_current_os_versions('keystone') + self.assertEqual(expected, result) + + # Wallaby+ scenario where openstack-release package is installed + self.get_openstack_release.return_value = 'wallaby' + expected = {'keystone': 'wallaby'} + result = openstack_utils.get_current_os_versions('keystone') + self.assertEqual(expected, result) + + def test_get_os_release(self): self.patch( 'zaza.openstack.utilities.openstack.get_current_os_release_pair', new_callable=mock.MagicMock(), @@ -936,6 +953,23 @@ class TestOpenStackUtils(ut_utils.BaseTestCase): self.get_application_config_option.return_value = None self.assertEqual(openstack_utils.get_keystone_api_version(), 3) + def test_get_openstack_release(self): + self.patch_object(openstack_utils.model, "get_units") + self.patch_object(openstack_utils.juju_utils, "remote_run") + + # Test pre-Wallaby behavior where openstack-release pkg isn't installed + self.get_units.return_value = [] + self.remote_run.return_value = "OPENSTACK_CODENAME=wallaby " + + # Test Wallaby+ behavior where openstack-release package is installed + unit1 = mock.MagicMock() + unit1.entity_id = 1 + self.get_units.return_value = [unit1] + self.remote_run.return_value = "OPENSTACK_CODENAME=wallaby " + + result = openstack_utils.get_openstack_release("application", "model") + self.assertEqual(result, "wallaby") + def test_get_project_id(self): # No domain self.patch_object(openstack_utils, "get_keystone_api_version") diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 230a3f6..75ab9d7 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1753,9 +1753,44 @@ def get_os_code_info(package, pkg_version): return OPENSTACK_CODENAMES[vers] +def get_openstack_release(application, model_name=None): + """Return the openstack release codename based on /etc/openstack-release. + + This will only return a codename if the openstack-release package is + installed on the unit. + + :param application: Application name + :type application: string + :param model_name: Name of model to query. + :type model_name: str + :returns: OpenStack release codename for application + :rtype: string + """ + versions = [] + units = model.get_units(application, model_name=model_name) + for unit in units: + cmd = 'cat /etc/openstack-release | grep OPENSTACK_CODENAME' + out = juju_utils.remote_run(unit.entity_id, cmd, model_name=model_name) + codename = out.split('=')[1].strip() + versions.append(codename) + if len(set(versions)) == 0: + return None + elif len(set(versions)) > 1: + raise Exception('Unexpected mix of OpenStack releases for {}: {}', + application, versions) + return versions[0] + + def get_current_os_versions(deployed_applications, model_name=None): """Determine OpenStack codename of deployed applications. + Initially, see if the openstack-release pkg is available and use it + instead. + + If it isn't then it falls back to the existing method of checking the + version of the package passed and then resolving the version from that + using lookup tables. + :param deployed_applications: List of deployed applications :type deployed_applications: list :param model_name: Name of model to query. @@ -1769,11 +1804,16 @@ def get_current_os_versions(deployed_applications, model_name=None): continue logging.info("looking at application: {}".format(application)) - version = generic_utils.get_pkg_version(application['name'], - application['type']['pkg'], - model_name=model_name) - versions[application['name']] = ( - get_os_code_info(application['type']['pkg'], version)) + codename = get_openstack_release(application['name'], + model_name=model_name) + if codename: + versions[application['name']] = codename + else: + version = generic_utils.get_pkg_version(application['name'], + application['type']['pkg'], + model_name=model_name) + versions[application['name']] = ( + get_os_code_info(application['type']['pkg'], version)) return versions diff --git a/zaza/openstack/utilities/os_versions.py b/zaza/openstack/utilities/os_versions.py index 420253c..fdb6f0f 100644 --- a/zaza/openstack/utilities/os_versions.py +++ b/zaza/openstack/utilities/os_versions.py @@ -36,6 +36,7 @@ UBUNTU_OPENSTACK_RELEASE = OrderedDict([ ('eoan', 'train'), ('focal', 'ussuri'), ('groovy', 'victoria'), + ('hirsute', 'wallaby'), ]) @@ -69,7 +70,8 @@ OPENSTACK_RELEASES_PAIRS = [ 'bionic_queens', 'bionic_rocky', 'cosmic_rocky', 'bionic_stein', 'disco_stein', 'bionic_train', 'eoan_train', 'bionic_ussuri', 'focal_ussuri', - 'focal_victoria', 'groovy_victoria'] + 'focal_victoria', 'groovy_victoria', + 'focal_wallaby', 'hirsute_wallaby'] SWIFT_CODENAMES = OrderedDict([ ('diablo', From 9a48757d5e214c4c0c4e14e8528a1f895a54901c Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Tue, 20 Apr 2021 12:24:23 -0400 Subject: [PATCH 2/3] Fix version fallback path when /etc/openstack-release doesn't exist --- zaza/openstack/utilities/openstack.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 75ab9d7..846cca4 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1770,9 +1770,14 @@ def get_openstack_release(application, model_name=None): units = model.get_units(application, model_name=model_name) for unit in units: cmd = 'cat /etc/openstack-release | grep OPENSTACK_CODENAME' - out = juju_utils.remote_run(unit.entity_id, cmd, model_name=model_name) - codename = out.split('=')[1].strip() - versions.append(codename) + try: + out = juju_utils.remote_run(unit.entity_id, cmd, + model_name=model_name) + except model.CommandRunFailed: + logging.info('Fall back to version check for OpenStack codename') + else: + codename = out.split('=')[1].strip() + versions.append(codename) if len(set(versions)) == 0: return None elif len(set(versions)) > 1: From d70ff79b1e5e6bfc7fcffac98ef1e80f92da4c28 Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Tue, 20 Apr 2021 13:05:18 -0400 Subject: [PATCH 3/3] Change log to debug to create less noise --- zaza/openstack/utilities/openstack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 846cca4..79e1c54 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -1774,7 +1774,7 @@ def get_openstack_release(application, model_name=None): out = juju_utils.remote_run(unit.entity_id, cmd, model_name=model_name) except model.CommandRunFailed: - logging.info('Fall back to version check for OpenStack codename') + logging.debug('Fall back to version check for OpenStack codename') else: codename = out.split('=')[1].strip() versions.append(codename)