From abd34b8a1ae89e1c2a7e24ec6627d200cc34d113 Mon Sep 17 00:00:00 2001 From: Douglas Viroel Date: Thu, 31 Jul 2025 17:54:40 -0300 Subject: [PATCH] Add support for microversion testing for api and scenario tests Following the tempest guide[1] for implementing microversion tests, a couple of changes were made in the plugin to better adapt it to support new test classes for different microversions. When not defined a minimum microversion, the min microversion from the service will be used. This change only affects the api and scenarios tests, since the client_functional tests have their own way to setup the api version, which can be further improved if needed. Some test classes had to set a minimum api version due to helper functions like the use of `GET /v1/data_model`. Two new configuration options were added to define the test target microversions, and should be used to help on testing stable branches in future releases. [1] https://docs.openstack.org/tempest/latest/microversion_testing.html#how-to-implement-microversion-tests Depends-On: https://review.opendev.org/c/openstack/watcher/+/956380 Change-Id: Id8fa25593b5cd47f5943b228415cd191e41e19ab Signed-off-by: Douglas Viroel --- watcher_tempest_plugin/config.py | 12 +++++ .../v1/json/api_microversion_fixture.py | 47 +++++++++++++++++++ .../services/infra_optim/v1/json/client.py | 2 +- .../tests/api/admin/base.py | 23 ++++++++- watcher_tempest_plugin/tests/scenario/base.py | 20 ++++++++ .../scenario/test_execute_basic_optim.py | 2 + .../scenario/test_execute_host_maintenance.py | 2 + .../tests/scenario/test_execute_strategies.py | 2 + .../scenario/test_execute_strategies_real.py | 2 + .../test_execute_vm_workload_consolidation.py | 2 + .../scenario/test_execute_workload_balance.py | 2 + .../test_execute_workload_balancing.py | 2 + .../scenario/test_execute_zone_migration.py | 2 + 13 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 watcher_tempest_plugin/services/infra_optim/v1/json/api_microversion_fixture.py diff --git a/watcher_tempest_plugin/config.py b/watcher_tempest_plugin/config.py index 512723b..52a45ca 100644 --- a/watcher_tempest_plugin/config.py +++ b/watcher_tempest_plugin/config.py @@ -115,4 +115,16 @@ OptimizationGroup = [ help="In real-data test cases, the period of time during which " "the load will be executed in seconds." ), + cfg.StrOpt( + "min_microversion", + default=None, + help="Lower version of the test target microversion range. " + "The format is 'X.Y', where 'X' and 'Y' are int values." + ), + cfg.StrOpt( + "max_microversion", + default=None, + help="Upper version of the test target microversion range. " + "The format is 'X.Y', where 'X' and 'Y' are int values." + ), ] diff --git a/watcher_tempest_plugin/services/infra_optim/v1/json/api_microversion_fixture.py b/watcher_tempest_plugin/services/infra_optim/v1/json/api_microversion_fixture.py new file mode 100644 index 0000000..d2666d6 --- /dev/null +++ b/watcher_tempest_plugin/services/infra_optim/v1/json/api_microversion_fixture.py @@ -0,0 +1,47 @@ +# Copyright 2025 Red Hat, Inc. All rights reserved. +# +# 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. + +import fixtures + +from watcher_tempest_plugin.services.infra_optim.v1.json import client + + +class APIMicroversionFixture(fixtures.Fixture): + """API Microversion Fixture to set service microversion. + + This class provides the fixture to set and reset the microversion + on service client. Service client has global variable to set the + microversion for that service API request. + This class can be used with useFixture: Example:: + + def setUp(self): + super(BaseInfraOptimTest, self).setUp() + self.useFixture(api_microversion_fixture.APIMicroversionFixture( + optimize_microversion=self.request_microversion)) + This class only supports the Resource Optimization service. + + :param str optimize_microversion: microvesion to be set on resource + optimization service client + """ + + def __init__(self, optimize_microversion): + self.optimize_microversion = optimize_microversion + + def _setUp(self): + super(APIMicroversionFixture, self)._setUp() + client.INFRA_OPTIM_VERSION = self.optimize_microversion + self.addCleanup(self._reset_optimize_microversion) + + def _reset_optimize_microversion(self): + client.INFRA_OPTIM_VERSION = None diff --git a/watcher_tempest_plugin/services/infra_optim/v1/json/client.py b/watcher_tempest_plugin/services/infra_optim/v1/json/client.py index 9db68de..d78a173 100644 --- a/watcher_tempest_plugin/services/infra_optim/v1/json/client.py +++ b/watcher_tempest_plugin/services/infra_optim/v1/json/client.py @@ -19,7 +19,7 @@ from oslo_utils import uuidutils from watcher_tempest_plugin.services import base -INFRA_OPTIM_VERSION = '1.4' +INFRA_OPTIM_VERSION = None class InfraOptimClientJSON(base.BaseClient): diff --git a/watcher_tempest_plugin/tests/api/admin/base.py b/watcher_tempest_plugin/tests/api/admin/base.py index 311675f..a70682b 100644 --- a/watcher_tempest_plugin/tests/api/admin/base.py +++ b/watcher_tempest_plugin/tests/api/admin/base.py @@ -18,16 +18,21 @@ import functools import time from tempest import config +from tempest.lib.common import api_version_utils from tempest.lib.common.utils import data_utils from tempest.lib.common.utils import test_utils from tempest import test from watcher_tempest_plugin import infra_optim_clients as clients +from watcher_tempest_plugin.services.infra_optim.v1.json import ( + api_microversion_fixture +) CONF = config.CONF -class BaseInfraOptimTest(test.BaseTestCase): +class BaseInfraOptimTest(api_version_utils.BaseMicroversionTest, + test.BaseTestCase): """Base class for Infrastructure Optimization API tests.""" # States where the object is waiting for some event to perform a transition @@ -48,6 +53,12 @@ class BaseInfraOptimTest(test.BaseTestCase): if not CONF.service_available.watcher: raise cls.skipException('Watcher support is required') + api_version_utils.check_skip_with_microversion( + cls.min_microversion, + cls.max_microversion, + CONF.optimize.min_microversion, + CONF.optimize.max_microversion) + @classmethod def setup_credentials(cls): super(BaseInfraOptimTest, cls).setup_credentials() @@ -59,6 +70,11 @@ class BaseInfraOptimTest(test.BaseTestCase): cls.client = cls.mgr.io_client cls.gnocchi = cls.mgr.gn_client + def setUp(self): + super(BaseInfraOptimTest, self).setUp() + self.useFixture(api_microversion_fixture.APIMicroversionFixture( + optimize_microversion=self.request_microversion)) + @classmethod def resource_setup(cls): super(BaseInfraOptimTest, cls).resource_setup() @@ -71,6 +87,11 @@ class BaseInfraOptimTest(test.BaseTestCase): # action plans to delete (including potential orphan one(s)) cls.created_action_plans_audit_uuids = set() + cls.request_microversion = ( + api_version_utils.select_request_microversion( + cls.min_microversion, + CONF.optimize.min_microversion)) + @classmethod def resource_cleanup(cls): """Ensure that all created objects get destroyed.""" diff --git a/watcher_tempest_plugin/tests/scenario/base.py b/watcher_tempest_plugin/tests/scenario/base.py index 3d09a84..fab135b 100644 --- a/watcher_tempest_plugin/tests/scenario/base.py +++ b/watcher_tempest_plugin/tests/scenario/base.py @@ -32,12 +32,16 @@ from oslo_log import log from tempest.common import waiters from tempest import config from tempest.lib.common import api_microversion_fixture +from tempest.lib.common import api_version_utils from tempest.lib.common.utils import data_utils from tempest.lib.common.utils import test_utils from tempest.lib import exceptions from tempest.scenario import manager from watcher_tempest_plugin import infra_optim_clients as clients +from watcher_tempest_plugin.services.infra_optim.v1.json import ( + api_microversion_fixture as watcher_microversion_fixture +) LOG = log.getLogger(__name__) @@ -54,6 +58,9 @@ NOVA_API_VERSION_CREATE_WITH_HOST = '2.74' class BaseInfraOptimScenarioTest(manager.ScenarioTest): """Base class for Infrastructure Optimization API tests.""" + min_microversion = None + max_microversion = manager.LATEST_MICROVERSION + # States where the object is waiting for some event to perform a transition IDLE_STATES = ('RECOMMENDED', 'FAILED', 'SUCCEEDED', 'CANCELLED') # States where the object can only be DELETED (end of its life-cycle) @@ -91,6 +98,12 @@ class BaseInfraOptimScenarioTest(manager.ScenarioTest): if not CONF.service_available.watcher: raise cls.skipException('Watcher support is required') + api_version_utils.check_skip_with_microversion( + cls.min_microversion, + cls.max_microversion, + CONF.optimize.min_microversion, + CONF.optimize.max_microversion) + @classmethod def setup_credentials(cls): cls._check_network_config() @@ -111,11 +124,18 @@ class BaseInfraOptimScenarioTest(manager.ScenarioTest): compute_microversion=self.compute_request_microversion)) self.useFixture(api_microversion_fixture.APIMicroversionFixture( placement_microversion=CONF.placement.min_microversion)) + self.useFixture(watcher_microversion_fixture.APIMicroversionFixture( + optimize_microversion=self.request_microversion)) @classmethod def resource_setup(cls): super(BaseInfraOptimScenarioTest, cls).resource_setup() + cls.request_microversion = ( + api_version_utils.select_request_microversion( + cls.min_microversion, + CONF.optimize.min_microversion)) + @classmethod def resource_cleanup(cls): """Ensure that all created objects get destroyed.""" diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_basic_optim.py b/watcher_tempest_plugin/tests/scenario/test_execute_basic_optim.py index f42403b..c469a4c 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_basic_optim.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_basic_optim.py @@ -29,6 +29,8 @@ CONF = config.CONF class TestExecuteBasicStrategy(base.BaseInfraOptimScenarioTest): """Tests for action plans""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_host_maintenance.py b/watcher_tempest_plugin/tests/scenario/test_execute_host_maintenance.py index 02f8a4a..4095293 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_host_maintenance.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_host_maintenance.py @@ -27,6 +27,8 @@ LOG = log.getLogger(__name__) class TestExecuteHostMaintenanceStrategy(base.BaseInfraOptimScenarioTest): """Tests for host_maintenance""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_strategies.py b/watcher_tempest_plugin/tests/scenario/test_execute_strategies.py index 7cfe684..4d5796f 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_strategies.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_strategies.py @@ -26,6 +26,8 @@ CONF = config.CONF class TestExecuteStrategies(base.BaseInfraOptimScenarioTest): """Tests for strategies""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_strategies_real.py b/watcher_tempest_plugin/tests/scenario/test_execute_strategies_real.py index e48a8c7..80fb3f5 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_strategies_real.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_strategies_real.py @@ -26,6 +26,8 @@ LOG = log.getLogger(__name__) class TestRealExecuteStrategies(base.BaseInfraOptimScenarioTest): """Tests with real data for strategies""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_vm_workload_consolidation.py b/watcher_tempest_plugin/tests/scenario/test_execute_vm_workload_consolidation.py index 2fe8844..853faf5 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_vm_workload_consolidation.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_vm_workload_consolidation.py @@ -29,6 +29,8 @@ CONF = config.CONF class TestExecuteVmWorkloadBalanceStrategy(base.BaseInfraOptimScenarioTest): """Tests for action plans""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_workload_balance.py b/watcher_tempest_plugin/tests/scenario/test_execute_workload_balance.py index ee1cc09..7ad6019 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_workload_balance.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_workload_balance.py @@ -27,6 +27,8 @@ LOG = log.getLogger(__name__) class TestExecuteWorkloadBalanceStrategy(base.BaseInfraOptimScenarioTest): """Tests for workload_balance""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_workload_balancing.py b/watcher_tempest_plugin/tests/scenario/test_execute_workload_balancing.py index 76cb2a0..a7fb059 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_workload_balancing.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_workload_balancing.py @@ -31,6 +31,8 @@ LOG = log.getLogger(__name__) class TestExecuteWorkloadBalancingStrategy(base.BaseInfraOptimScenarioTest): """Tests for action plans""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST diff --git a/watcher_tempest_plugin/tests/scenario/test_execute_zone_migration.py b/watcher_tempest_plugin/tests/scenario/test_execute_zone_migration.py index b295176..f27aeb9 100644 --- a/watcher_tempest_plugin/tests/scenario/test_execute_zone_migration.py +++ b/watcher_tempest_plugin/tests/scenario/test_execute_zone_migration.py @@ -24,6 +24,8 @@ LOG = log.getLogger(__name__) class TestExecuteZoneMigrationStrategy(base.BaseInfraOptimScenarioTest): """Tests for action plans""" + # Minimal version required for list data models + min_microversion = "1.3" # Minimal version required for _create_one_instance_per_host compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST