diff --git a/octavia_tempest_plugin/common/decorators.py b/octavia_tempest_plugin/common/decorators.py new file mode 100644 index 00000000..b484497b --- /dev/null +++ b/octavia_tempest_plugin/common/decorators.py @@ -0,0 +1,54 @@ +# Copyright 2020 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. +from functools import wraps + +import testtools + +from oslo_utils import excutils +from tempest import config +from tempest.lib import exceptions + +CONF = config.CONF + + +def skip_if_not_implemented(f): + """A decorator to raise a skip exception for not implemented features. + + This decorator raises a skipException if the method raises a + NotImplemented exception. If "skip_if_not_implemented=False" + argument was passed to the method, the NotImplemented exception will + be raised. + + @param skip_if_not_implemented: If True (default), raise skipException. + """ + @wraps(f) + def wrapper(*func_args, **func_kwargs): + + skip = func_kwargs.pop('skip_if_not_implemented', True) + if CONF.loadbalancer_feature_enabled.not_implemented_is_error: + skip = False + try: + return f(*func_args, **func_kwargs) + except exceptions.NotImplemented as e: + with excutils.save_and_reraise_exception(): + if not skip: + raise + message = ("The configured provider driver '{driver}' " + "does not support a feature required for this " + "test.".format( + driver=CONF.load_balancer.provider)) + if hasattr(e, 'resp_body'): + message = e.resp_body.get('faultstring', message) + raise testtools.TestCase.skipException(message) + return wrapper diff --git a/octavia_tempest_plugin/config.py b/octavia_tempest_plugin/config.py index fc04c336..8dd04035 100644 --- a/octavia_tempest_plugin/config.py +++ b/octavia_tempest_plugin/config.py @@ -209,6 +209,12 @@ OctaviaGroup = [ lb_feature_enabled_group = cfg.OptGroup(name='loadbalancer-feature-enabled', title='Enabled/Disabled LB features') LBFeatureEnabledGroup = [ + cfg.BoolOpt('not_implemented_is_error', + default=True, + help="When True, not-implemented responses from the API are " + "considered an error and test failure. This should be " + "used when a driver should support all of the Octavia " + "API features, such as the reference driver."), cfg.BoolOpt('health_monitor_enabled', default=True, help="Whether Health Monitor is available with provider " diff --git a/octavia_tempest_plugin/services/load_balancer/v2/amphora_client.py b/octavia_tempest_plugin/services/load_balancer/v2/amphora_client.py index 4094515b..aed93b4b 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/amphora_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/amphora_client.py @@ -16,6 +16,7 @@ from oslo_serialization import jsonutils from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client CONF = config.CONF @@ -28,6 +29,7 @@ class AmphoraClient(base_client.BaseLBaaSClient): stats_root_tag = 'amphora_stats' base_uri = '/v2.0/octavia/{object}' + @skip_if_not_implemented def show_amphora(self, amphora_id, query_params=None, return_object_only=True): """Get amphora details. @@ -69,6 +71,7 @@ class AmphoraClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_amphorae(self, query_params=None, return_object_only=True): """Get a list of amphora objects. @@ -107,6 +110,7 @@ class AmphoraClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def get_amphora_stats(self, amphora_id, query_params=None, return_object_only=True): """Get amphora statistics. @@ -158,6 +162,7 @@ class AmphoraClient(base_client.BaseLBaaSClient): else: return jsonutils.loads(body.decode('utf-8')) + @skip_if_not_implemented def update_amphora_config(self, amphora_id): """Update the amphora agent configuration. @@ -193,6 +198,7 @@ class AmphoraClient(base_client.BaseLBaaSClient): response, body = self.put(uri, '') self.expected_success(202, response.status) + @skip_if_not_implemented def amphora_failover(self, amphora_id): """Failover an amphora. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_capabilities_client.py b/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_capabilities_client.py index 92696a77..679af744 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_capabilities_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_capabilities_client.py @@ -14,6 +14,7 @@ # under the License. # +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client from octavia_tempest_plugin.services.load_balancer.v2 import provider_client @@ -36,6 +37,7 @@ class AvailabilityZoneCapabilitiesClient(base_client.BaseLBaaSClient): object=self.list_root_tag ) + @skip_if_not_implemented def list_availability_zone_capabilities(self, provider, query_params=None, return_object_only=True): """Get a list of provider availability zone capability objects. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_client.py b/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_client.py index c729f21a..ab87a854 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_client.py @@ -16,6 +16,7 @@ from oslo_log import log as logging from tempest.lib import exceptions +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client LOG = logging.getLogger(__name__) @@ -33,6 +34,7 @@ class AvailabilityZoneClient(base_client.BaseLBaaSClient): super(AvailabilityZoneClient, self).__init__(*args, **kwargs) self.uri = self.base_uri.format(object=self.resource_path) + @skip_if_not_implemented def create_availability_zone(self, name, availability_zone_profile_id, description=Unset, enabled=Unset, return_object_only=True): @@ -75,6 +77,7 @@ class AvailabilityZoneClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_availability_zone(self, availability_zone_name, query_params=None, return_object_only=True): """Get the availability zone details. @@ -116,6 +119,7 @@ class AvailabilityZoneClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_availability_zones(self, query_params=None, return_object_only=True): """Get a list of availability zone objects. @@ -155,6 +159,7 @@ class AvailabilityZoneClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_availability_zone(self, availability_zone_name, description=Unset, enabled=Unset, return_object_only=True): @@ -195,6 +200,7 @@ class AvailabilityZoneClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('availability_zone_name') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_availability_zone(self, availability_zone_name, ignore_errors=False): """Delete an availability zone. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_profile_client.py b/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_profile_client.py index 1aaab902..071b15f1 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_profile_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/availability_zone_profile_client.py @@ -16,6 +16,7 @@ from oslo_log import log as logging from tempest.lib import exceptions +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client LOG = logging.getLogger(__name__) @@ -33,6 +34,7 @@ class AvailabilityZoneProfileClient(base_client.BaseLBaaSClient): super(AvailabilityZoneProfileClient, self).__init__(*args, **kwargs) self.uri = self.base_uri.format(object=self.resource_path) + @skip_if_not_implemented def create_availability_zone_profile(self, name, provider_name, availability_zone_data, return_object_only=True): @@ -73,6 +75,7 @@ class AvailabilityZoneProfileClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_availability_zone_profile(self, availability_zone_profile_id, query_params=None, return_object_only=True): @@ -116,6 +119,7 @@ class AvailabilityZoneProfileClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_availability_zone_profiles(self, query_params=None, return_object_only=True): """Get a list of availability zone profile objects. @@ -155,6 +159,7 @@ class AvailabilityZoneProfileClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_availability_zone_profile( self, availability_zone_profile_id, name=Unset, provider_name=Unset, availability_zone_data=Unset, @@ -199,6 +204,7 @@ class AvailabilityZoneProfileClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('availability_zone_profile_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_availability_zone_profile(self, availability_zone_profile_id, ignore_errors=False): """Delete an availability zone profile. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/flavor_capabilities_client.py b/octavia_tempest_plugin/services/load_balancer/v2/flavor_capabilities_client.py index 4c23042f..eb07faf9 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/flavor_capabilities_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/flavor_capabilities_client.py @@ -13,6 +13,7 @@ # under the License. # +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client from octavia_tempest_plugin.services.load_balancer.v2 import provider_client @@ -34,6 +35,7 @@ class FlavorCapabilitiesClient(base_client.BaseLBaaSClient): object=self.list_root_tag ) + @skip_if_not_implemented def list_flavor_capabilities(self, provider, query_params=None, return_object_only=True): """Get a list of provider flavor capability objects. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/flavor_client.py b/octavia_tempest_plugin/services/load_balancer/v2/flavor_client.py index 085da9e0..8a87a33b 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/flavor_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/flavor_client.py @@ -16,6 +16,7 @@ from oslo_log import log as logging from tempest.lib import exceptions +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client LOG = logging.getLogger(__name__) @@ -27,6 +28,7 @@ class FlavorClient(base_client.BaseLBaaSClient): root_tag = 'flavor' list_root_tag = 'flavors' + @skip_if_not_implemented def create_flavor(self, name, flavor_profile_id, description=Unset, enabled=Unset, return_object_only=True): """Create a flavor. @@ -67,6 +69,7 @@ class FlavorClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_flavor(self, flavor_id, query_params=None, return_object_only=True): """Get the flavor details. @@ -108,6 +111,7 @@ class FlavorClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_flavors(self, query_params=None, return_object_only=True): """Get a list of flavor objects. @@ -146,6 +150,7 @@ class FlavorClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_flavor(self, flavor_id, name=Unset, description=Unset, enabled=Unset, return_object_only=True): """Update a flavor. @@ -186,6 +191,7 @@ class FlavorClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('flavor_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_flavor(self, flavor_id, ignore_errors=False): """Delete a flavor. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/flavor_profile_client.py b/octavia_tempest_plugin/services/load_balancer/v2/flavor_profile_client.py index 811cff8d..bc0f2fb5 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/flavor_profile_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/flavor_profile_client.py @@ -16,6 +16,7 @@ from oslo_log import log as logging from tempest.lib import exceptions +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client LOG = logging.getLogger(__name__) @@ -27,6 +28,7 @@ class FlavorProfileClient(base_client.BaseLBaaSClient): root_tag = 'flavorprofile' list_root_tag = 'flavorprofiles' + @skip_if_not_implemented def create_flavor_profile(self, name, provider_name, flavor_data, return_object_only=True): """Create a flavor profile. @@ -65,6 +67,7 @@ class FlavorProfileClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_flavor_profile(self, flavorprofile_id, query_params=None, return_object_only=True): """Get the flavor profile details. @@ -106,6 +109,7 @@ class FlavorProfileClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_flavor_profiles(self, query_params=None, return_object_only=True): """Get a list of flavor profile objects. @@ -144,6 +148,7 @@ class FlavorProfileClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_flavor_profile( self, flavorprofile_id, name=Unset, provider_name=Unset, flavor_data=Unset, return_object_only=True): @@ -185,6 +190,7 @@ class FlavorProfileClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('flavorprofile_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_flavor_profile(self, flavorprofile_id, ignore_errors=False): """Delete a flavor profile. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/healthmonitor_client.py b/octavia_tempest_plugin/services/load_balancer/v2/healthmonitor_client.py index a7d2e6b4..4ce362ed 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/healthmonitor_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/healthmonitor_client.py @@ -14,6 +14,7 @@ from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client CONF = config.CONF @@ -26,6 +27,7 @@ class HealthMonitorClient(base_client.BaseLBaaSClient): list_root_tag = 'healthmonitors' resource_name = 'healthmonitor' + @skip_if_not_implemented def create_healthmonitor(self, pool_id, type, delay, timeout, max_retries, max_retries_down=Unset, name=Unset, tags=Unset, http_method=Unset, url_path=Unset, @@ -87,6 +89,7 @@ class HealthMonitorClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_healthmonitor(self, healthmonitor_id, query_params=None, return_object_only=True): """Get healthmonitor details. @@ -128,6 +131,7 @@ class HealthMonitorClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_healthmonitors(self, query_params=None, return_object_only=True): """Get a list of healthmonitor objects. @@ -166,6 +170,7 @@ class HealthMonitorClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_healthmonitor(self, healthmonitor_id, delay=Unset, timeout=Unset, max_retries=Unset, max_retries_down=Unset, name=Unset, tags=Unset, @@ -228,6 +233,7 @@ class HealthMonitorClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('healthmonitor_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_healthmonitor(self, healthmonitor_id, ignore_errors=False): """Delete a healthmonitor. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/l7policy_client.py b/octavia_tempest_plugin/services/load_balancer/v2/l7policy_client.py index 1feb72fc..36eef40e 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/l7policy_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/l7policy_client.py @@ -14,6 +14,7 @@ from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client CONF = config.CONF @@ -26,6 +27,7 @@ class L7PolicyClient(base_client.BaseLBaaSClient): list_root_tag = 'l7policies' resource_name = 'l7policy' + @skip_if_not_implemented def create_l7policy(self, listener_id, action, name=Unset, description=Unset, tags=Unset, admin_state_up=Unset, position=Unset, redirect_pool_id=Unset, @@ -78,6 +80,7 @@ class L7PolicyClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_l7policy(self, l7policy_id, query_params=None, return_object_only=True): """Get l7policy details. @@ -119,6 +122,7 @@ class L7PolicyClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_l7policies(self, query_params=None, return_object_only=True): """Get a list of l7policy objects. @@ -157,6 +161,7 @@ class L7PolicyClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_l7policy(self, l7policy_id, action=Unset, name=Unset, description=Unset, tags=Unset, admin_state_up=Unset, position=Unset, redirect_pool_id=Unset, @@ -210,6 +215,7 @@ class L7PolicyClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('l7policy_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_l7policy(self, l7policy_id, ignore_errors=False): """Delete a l7policy. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/l7rule_client.py b/octavia_tempest_plugin/services/load_balancer/v2/l7rule_client.py index be5434d1..da40af2a 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/l7rule_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/l7rule_client.py @@ -14,6 +14,7 @@ from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client from octavia_tempest_plugin.services.load_balancer.v2 import l7policy_client @@ -38,6 +39,7 @@ class L7RuleClient(base_client.BaseLBaaSClient): object=self.list_root_tag ) + @skip_if_not_implemented def create_l7rule(self, l7policy_id, type, value, compare_type, tags=Unset, admin_state_up=Unset, key=Unset, invert=Unset, return_object_only=True): @@ -87,6 +89,7 @@ class L7RuleClient(base_client.BaseLBaaSClient): kwargs['parent_id'] = kwargs.pop('l7policy_id') return self._create_object(**kwargs) + @skip_if_not_implemented def show_l7rule(self, l7rule_id, l7policy_id, query_params=None, return_object_only=True): """Get l7rule details. @@ -130,6 +133,7 @@ class L7RuleClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_l7rules(self, l7policy_id, query_params=None, return_object_only=True): """Get a list of l7rule objects. @@ -171,6 +175,7 @@ class L7RuleClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_l7rule(self, l7rule_id, l7policy_id, type=Unset, value=Unset, compare_type=Unset, tags=Unset, admin_state_up=Unset, key=Unset, invert=Unset, return_object_only=True): @@ -222,6 +227,7 @@ class L7RuleClient(base_client.BaseLBaaSClient): kwargs['parent_id'] = kwargs.pop('l7policy_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_l7rule(self, l7rule_id, l7policy_id, ignore_errors=False): """Delete a l7rule. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/listener_client.py b/octavia_tempest_plugin/services/load_balancer/v2/listener_client.py index eb7690a8..c059a840 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/listener_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/listener_client.py @@ -17,6 +17,7 @@ from oslo_serialization import jsonutils from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client CONF = config.CONF @@ -28,6 +29,7 @@ class ListenerClient(base_client.BaseLBaaSClient): root_tag = 'listener' list_root_tag = 'listeners' + @skip_if_not_implemented def create_listener(self, protocol, protocol_port, loadbalancer_id, name=Unset, description=Unset, tags=Unset, admin_state_up=Unset, connection_limit=Unset, @@ -120,6 +122,7 @@ class ListenerClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_listener(self, listener_id, query_params=None, return_object_only=True): """Get listener details. @@ -161,6 +164,7 @@ class ListenerClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_listeners(self, query_params=None, return_object_only=True): """Get a list of listener objects. @@ -199,6 +203,7 @@ class ListenerClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_listener(self, listener_id, name=Unset, description=Unset, tags=Unset, admin_state_up=Unset, connection_limit=Unset, timeout_client_data=Unset, @@ -289,6 +294,7 @@ class ListenerClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('listener_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_listener(self, listener_id, ignore_errors=False): """Delete a listener. @@ -325,6 +331,7 @@ class ListenerClient(base_client.BaseLBaaSClient): return self._delete_obj(obj_id=listener_id, ignore_errors=ignore_errors) + @skip_if_not_implemented def get_listener_stats(self, listener_id, query_params=None, return_object_only=True): """Get listener statistics. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/loadbalancer_client.py b/octavia_tempest_plugin/services/load_balancer/v2/loadbalancer_client.py index 0fafbf26..9499d893 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/loadbalancer_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/loadbalancer_client.py @@ -17,6 +17,7 @@ from oslo_serialization import jsonutils from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client CONF = config.CONF @@ -34,6 +35,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): self.timeout = CONF.load_balancer.lb_build_timeout self.build_interval = CONF.load_balancer.lb_build_interval + @skip_if_not_implemented def create_loadbalancer(self, name=Unset, description=Unset, admin_state_up=Unset, flavor_id=Unset, listeners=Unset, project_id=Unset, provider=Unset, @@ -92,6 +94,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_loadbalancer(self, lb_id, query_params=None, return_object_only=True): """Get loadbalancer details. @@ -133,6 +136,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_loadbalancers(self, query_params=None, return_object_only=True): """Get a list of loadbalancer objects. @@ -171,6 +175,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_loadbalancer(self, lb_id, name=Unset, description=Unset, tags=Unset, admin_state_up=Unset, vip_qos_policy_id=Unset, @@ -220,6 +225,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('lb_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_loadbalancer(self, lb_id, cascade=False, ignore_errors=False): """Delete a loadbalancer. @@ -259,6 +265,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): ignore_errors=ignore_errors, cascade=cascade) + @skip_if_not_implemented def failover_loadbalancer(self, lb_id): """Failover a loadbalancer. @@ -295,6 +302,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): self.expected_success(202, response.status) return + @skip_if_not_implemented def get_loadbalancer_stats(self, lb_id, query_params=None, return_object_only=True): """Get loadbalancer statistics. @@ -345,6 +353,7 @@ class LoadbalancerClient(base_client.BaseLBaaSClient): else: return jsonutils.loads(body.decode('utf-8')) + @skip_if_not_implemented def get_loadbalancer_status(self, lb_id, query_params=None, return_object_only=True): """Get a loadbalancer status tree. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/member_client.py b/octavia_tempest_plugin/services/load_balancer/v2/member_client.py index 0f0d6393..c0d83daa 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/member_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/member_client.py @@ -16,6 +16,7 @@ from oslo_log import log as logging from oslo_serialization import jsonutils from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client from octavia_tempest_plugin.services.load_balancer.v2 import pool_client @@ -39,6 +40,7 @@ class MemberClient(base_client.BaseLBaaSClient): object=self.list_root_tag ) + @skip_if_not_implemented def create_member(self, pool_id, address, protocol_port, name=Unset, tags=Unset, admin_state_up=Unset, weight=Unset, @@ -98,6 +100,7 @@ class MemberClient(base_client.BaseLBaaSClient): kwargs['parent_id'] = kwargs.pop('pool_id') return self._create_object(**kwargs) + @skip_if_not_implemented def show_member(self, member_id, pool_id, query_params=None, return_object_only=True): """Get member details. @@ -141,6 +144,7 @@ class MemberClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_members(self, pool_id, query_params=None, return_object_only=True): """Get a list of member objects. @@ -182,6 +186,7 @@ class MemberClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_member(self, member_id, pool_id, name=Unset, tags=Unset, admin_state_up=Unset, weight=Unset, backup=Unset, monitor_address=Unset, monitor_port=Unset, @@ -238,6 +243,7 @@ class MemberClient(base_client.BaseLBaaSClient): kwargs['parent_id'] = kwargs.pop('pool_id') return self._update_object(**kwargs) + @skip_if_not_implemented def update_members(self, pool_id, members_list): """Batch update all members on a pool. @@ -277,6 +283,7 @@ class MemberClient(base_client.BaseLBaaSClient): self.expected_success(202, response.status) return + @skip_if_not_implemented def delete_member(self, member_id, pool_id, ignore_errors=False): """Delete a member. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/pool_client.py b/octavia_tempest_plugin/services/load_balancer/v2/pool_client.py index 58db1af2..98f4bfa7 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/pool_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/pool_client.py @@ -14,6 +14,7 @@ from tempest import config +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client CONF = config.CONF @@ -26,6 +27,7 @@ class PoolClient(base_client.BaseLBaaSClient): list_root_tag = 'pools' resource_name = 'pool' + @skip_if_not_implemented def create_pool(self, protocol, lb_algorithm, loadbalancer_id=Unset, listener_id=Unset, name=Unset, description=Unset, tags=Unset, @@ -79,6 +81,7 @@ class PoolClient(base_client.BaseLBaaSClient): if arg != 'self' and value is not Unset} return self._create_object(**kwargs) + @skip_if_not_implemented def show_pool(self, pool_id, query_params=None, return_object_only=True): """Get pool details. @@ -119,6 +122,7 @@ class PoolClient(base_client.BaseLBaaSClient): query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def list_pools(self, query_params=None, return_object_only=True): """Get a list of pool objects. @@ -157,6 +161,7 @@ class PoolClient(base_client.BaseLBaaSClient): return self._list_objects(query_params=query_params, return_object_only=return_object_only) + @skip_if_not_implemented def update_pool(self, pool_id, lb_algorithm=Unset, name=Unset, description=Unset, tags=Unset, admin_state_up=Unset, session_persistence=Unset, return_object_only=True): @@ -207,6 +212,7 @@ class PoolClient(base_client.BaseLBaaSClient): kwargs['obj_id'] = kwargs.pop('pool_id') return self._update_object(**kwargs) + @skip_if_not_implemented def delete_pool(self, pool_id, ignore_errors=False): """Delete a pool. diff --git a/octavia_tempest_plugin/services/load_balancer/v2/provider_client.py b/octavia_tempest_plugin/services/load_balancer/v2/provider_client.py index cbef1df1..319826e2 100644 --- a/octavia_tempest_plugin/services/load_balancer/v2/provider_client.py +++ b/octavia_tempest_plugin/services/load_balancer/v2/provider_client.py @@ -13,6 +13,7 @@ # under the License. # +from octavia_tempest_plugin.common.decorators import skip_if_not_implemented from octavia_tempest_plugin.services.load_balancer.v2 import base_client Unset = base_client.Unset @@ -22,6 +23,7 @@ class ProviderClient(base_client.BaseLBaaSClient): list_root_tag = 'providers' + @skip_if_not_implemented def list_providers(self, query_params=None, return_object_only=True): """Get a list of provider objects. diff --git a/requirements.txt b/requirements.txt index b30b4501..e5b93b87 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,4 +16,5 @@ requests>=2.14.2 # Apache-2.0 six>=1.10.0 # MIT tempest>=17.1.0 # Apache-2.0 tenacity>=4.4.0 # Apache-2.0 +testtools>=2.2.0 # MIT keystoneauth1>=3.3.0 # Apache-2.0