From f05ee9053a1efb833a52c7f3f69123dbe5e38169 Mon Sep 17 00:00:00 2001 From: Charles Short Date: Sun, 2 Dec 2018 19:36:29 +0000 Subject: [PATCH] Add pools scenarios for octavia Added the following scenarios: - Octavia.create_and_list_pools - Octavia.create_and_delete_pools - Octavia.create_and_update_pools - Octavia.create_and_show_pools Supported pool_create parameters are admin_state, lb_algorithm, protocol, description, session_persistence, loadbalancer_id. Change-Id: Ifd192e87e8dfce7f3cd34157942a097a78a32cc6 Signed-off-by: Charles Short --- CHANGELOG.rst | 5 +- rally-jobs/load-balancing.yaml | 80 +++++++++ rally_openstack/cleanup/resources.py | 24 ++- rally_openstack/scenarios/octavia/pools.py | 155 ++++++++++++++++++ rally_openstack/scenarios/octavia/utils.py | 27 +++ .../services/loadbalancer/octavia.py | 52 +++++- .../octavia-create-and-delete-pools.json | 28 ++++ .../octavia-create-and-delete-pools.yaml | 20 +++ .../octavia-create-and-list-pools.json | 28 ++++ .../octavia-create-and-list-pools.yaml | 20 +++ .../octavia-create-and-show-pools.json | 28 ++++ .../octavia-create-and-show-pools.yaml | 20 +++ .../octavia-create-and-update-pools.json | 28 ++++ .../octavia-create-and-update-pools.yaml | 20 +++ tests/unit/cleanup/test_resources.py | 2 +- .../unit/scenarios/loadbalancer/test_pools.py | 149 +++++++++++++++++ .../unit/scenarios/loadbalancer/test_utils.py | 4 +- .../services/loadbalancer/test_octavia.py | 71 ++++++-- 18 files changed, 728 insertions(+), 33 deletions(-) create mode 100644 rally_openstack/scenarios/octavia/pools.py create mode 100644 rally_openstack/scenarios/octavia/utils.py create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.json create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.yaml create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-list-pools.json create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-list-pools.yaml create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-show-pools.json create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-show-pools.yaml create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-update-pools.json create mode 100644 samples/tasks/scenarios/octavia/octavia-create-and-update-pools.yaml create mode 100644 tests/unit/scenarios/loadbalancer/test_pools.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d701ab1c..fcfeacd1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,12 +24,15 @@ Added * Added neutron trunk scenarios * Added barbican scenarios. -* Added octavia scenarios. * [scenario plugin] Octavia.create_and_list_loadbalancers * [scenario plugin] Octavia.create_and_delete_loadbalancers * [scenario plugin] Octavia.create_and_update_loadbalancers * [scenario plugin] Octavia.create_and_stats_loadbalancers * [scenario plugin] Octavia.create_and_show_loadbalancers +* [scenario plugin] Octavia.create_and_list_pools +* [scenario plugin] Octavia.create_and_delete_pools +* [scenario plugin] Octavia.create_and_update_pools +* [scenario plugin] Octavia.create_and_show_pools * Support for osprofiler config in Devstack plugin. * Added property 'floating_ip_enabled' in magnum cluster_templates context. diff --git a/rally-jobs/load-balancing.yaml b/rally-jobs/load-balancing.yaml index f7b5c356..3fbca907 100644 --- a/rally-jobs/load-balancing.yaml +++ b/rally-jobs/load-balancing.yaml @@ -110,3 +110,83 @@ sla: failure_rate: max: 0 + - + title: Octavia.create_and_list_pools + workloads: + - + scenario: + Octavia.create_and_list_pools: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + constant: + times: 2 + concurrency: 2 + contexts: + users: + tenants: 2 + roles: ["load-balancer_member"] + network: {} + sla: + failure_rate: + max: 0 + - + title: Octavia.create_and_delete_pools + workloads: + - + scenario: + Octavia.create_and_delete_pools: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + constant: + times: 2 + concurrency: 2 + contexts: + users: + tenants: 2 + roles: ["load-balancer_member"] + network: {} + sla: + failure_rate: + max: 0 + - + title: Octavia.create_and_update_pools + workloads: + - + scenario: + Octavia.create_and_update_pools: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + constant: + times: 2 + concurrency: 2 + contexts: + users: + tenants: 2 + roles: ["load-balancer_member"] + network: {} + sla: + failure_rate: + max: 0 + - + title: Octavia.create_and_show_pools + workloads: + - + scenario: + Octavia.create_and_show_pools: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + constant: + times: 2 + concurrency: 2 + contexts: + users: + tenants: 2 + roles: ["load-balancer_member"] + network: {} + sla: + failure_rate: + max: 0 diff --git a/rally_openstack/cleanup/resources.py b/rally_openstack/cleanup/resources.py index 58ed4cfe..8dcb0e68 100644 --- a/rally_openstack/cleanup/resources.py +++ b/rally_openstack/cleanup/resources.py @@ -323,10 +323,12 @@ class NeutronV2Loadbalancer(NeutronLbaasV2Mixin): return False +# OCTAVIA + @base.resource("octavia", "loadbalancer", order=next(_neutron_order), tenant_resource=True) -class OctaviaLoadbalancer(base.ResourceManager): +class OctaviaMixIn(base.ResourceManager): def _client(self): return octavia.Octavia(self.admin or self.user) @@ -353,6 +355,12 @@ class OctaviaLoadbalancer(base.ResourceManager): return self._client().load_balancer_list()["loadbalancers"] +@base.resource("octavia", "pools", order=next(_neutron_order), + tenant_resource=True) +class OctaviaPools(OctaviaMixIn): + pass + + @base.resource("neutron", "bgpvpn", order=next(_neutron_order), admin_required=True, perform_for_admin_only=True) class NeutronBgpvpn(NeutronMixin): @@ -406,8 +414,8 @@ class NeutronPort(NeutronMixin): for port in ports: if not port.get("name"): parent_name = None - if (port["device_owner"] in self.ROUTER_INTERFACE_OWNERS or - port["device_owner"] == self.ROUTER_GATEWAY_OWNER): + if (port["device_owner"] in self.ROUTER_INTERFACE_OWNERS + or port["device_owner"] == self.ROUTER_GATEWAY_OWNER): # first case is a port created while adding an interface to # the subnet # second case is a port created while adding gateway for @@ -426,8 +434,8 @@ class NeutronPort(NeutronMixin): def delete(self): device_owner = self.raw_resource["device_owner"] - if (device_owner in self.ROUTER_INTERFACE_OWNERS or - device_owner == self.ROUTER_GATEWAY_OWNER): + if (device_owner in self.ROUTER_INTERFACE_OWNERS + or device_owner == self.ROUTER_GATEWAY_OWNER): if device_owner == self.ROUTER_GATEWAY_OWNER: self._manager().remove_gateway_router( self.raw_resource["device_id"]) @@ -590,9 +598,9 @@ class GlanceImage(base.ResourceManager): return image.Image(self.admin or self.user) def list(self): - images = (self._client().list_images(owner=self.tenant_uuid) + - self._client().list_images(status="deactivated", - owner=self.tenant_uuid)) + images = (self._client().list_images(owner=self.tenant_uuid) + + self._client().list_images(status="deactivated", + owner=self.tenant_uuid)) return images def delete(self): diff --git a/rally_openstack/scenarios/octavia/pools.py b/rally_openstack/scenarios/octavia/pools.py new file mode 100644 index 00000000..2ad293aa --- /dev/null +++ b/rally_openstack/scenarios/octavia/pools.py @@ -0,0 +1,155 @@ +# Copyright 2018: 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 rally.task import validation + +from rally_openstack import consts +from rally_openstack import scenario +from rally_openstack.scenarios.octavia import utils + +"""Scenarios for Octavia Loadbalancer pools.""" + + +@validation.add("required_services", services=[consts.Service.OCTAVIA]) +@validation.add("required_platform", platform="openstack", users=True) +@validation.add("required_contexts", contexts=["network"]) +@scenario.configure(context={"cleanup@openstack": ["octavia"]}, + name="Octavia.create_and_list_pools", + platform="openstack") +class CreateAndListPools(utils.OctaviaBase): + + def run(self, protocol, lb_algorithm): + """Create a loadbalancer pool per each subnet and then pools. + + :param protocol: protocol for which the pool listens + :param lb_algorithm: loadbalancer algorithm + """ + subnets = [] + loadbalancers = [] + networks = self.context.get("tenant", {}).get("networks", []) + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet_id in subnets: + lb = self.octavia.load_balancer_create( + subnet_id=subnet_id) + loadbalancers.append(lb) + + for loadbalancer in loadbalancers: + self.octavia.wait_for_loadbalancer_prov_status(loadbalancer) + self.octavia.pool_create( + lb_id=loadbalancer["loadbalancer"]["id"], + protocol=protocol, lb_algorithm=lb_algorithm) + self.octavia.pool_list() + + +@validation.add("required_services", services=[consts.Service.OCTAVIA]) +@validation.add("required_platform", platform="openstack", users=True) +@validation.add("required_contexts", contexts=["network"]) +@scenario.configure(context={"cleanup@openstack": ["octavia"]}, + name="Octavia.create_and_delete_pools", + platform="openstack") +class CreateAndDeletePools(utils.OctaviaBase): + + def run(self, protocol, lb_algorithm): + """Create a pool per each subnet and then delete pool + + :param protocol: protocol for which the pool listens + :param lb_algorithm: loadbalancer algorithm + """ + subnets = [] + loadbalancers = [] + networks = self.context.get("tenant", {}).get("networks", []) + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet_id in subnets: + lb = self.octavia.load_balancer_create( + subnet_id=subnet_id) + loadbalancers.append(lb) + + for loadbalancer in loadbalancers: + self.octavia.wait_for_loadbalancer_prov_status(loadbalancer) + pools = self.octavia.pool_create( + lb_id=loadbalancer["loadbalancer"]["id"], + protocol=protocol, lb_algorithm=lb_algorithm) + self.octavia.pool_delete(pools["id"]) + + +@validation.add("required_services", services=[consts.Service.OCTAVIA]) +@validation.add("required_platform", platform="openstack", users=True) +@validation.add("required_contexts", contexts=["network"]) +@scenario.configure(context={"cleanup@openstack": ["octavia"]}, + name="Octavia.create_and_update_pools", + platform="openstack") +class CreateAndUpdatePools(utils.OctaviaBase): + + def run(self, protocol, lb_algorithm): + """Create a pool per each subnet and then update + + :param protocol: protocol for which the pool listens + :param lb_algorithm: loadbalancer algorithm + """ + subnets = [] + loadbalancers = [] + networks = self.context.get("tenant", {}).get("networks", []) + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet_id in subnets: + lb = self.octavia.load_balancer_create( + subnet_id=subnet_id) + loadbalancers.append(lb) + + update_pool = { + "name": self.generate_random_name() + } + + for loadbalancer in loadbalancers: + self.octavia.wait_for_loadbalancer_prov_status(loadbalancer) + pools = self.octavia.pool_create( + lb_id=loadbalancer["loadbalancer"]["id"], + protocol=protocol, lb_algorithm=lb_algorithm) + self.octavia.pool_set( + pool_id=pools["id"], pool_update_args=update_pool) + + +@validation.add("required_services", services=[consts.Service.OCTAVIA]) +@validation.add("required_platform", platform="openstack", users=True) +@validation.add("required_contexts", contexts=["network"]) +@scenario.configure(context={"cleanup@openstack": ["octavia"]}, + name="Octavia.create_and_show_pools", + platform="openstack") +class CreateAndShowPools(utils.OctaviaBase): + + def run(self, protocol, lb_algorithm): + """Create a pool per each subnet and show it + + :param protocol: protocol for which the pool listens + :param lb_algorithm: loadbalancer algorithm + """ + subnets = [] + loadbalancers = [] + networks = self.context.get("tenant", {}).get("networks", []) + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet_id in subnets: + lb = self.octavia.load_balancer_create( + subnet_id=subnet_id) + loadbalancers.append(lb) + + for loadbalancer in loadbalancers: + self.octavia.wait_for_loadbalancer_prov_status(loadbalancer) + pools = self.octavia.pool_create( + lb_id=loadbalancer["loadbalancer"]["id"], + protocol=protocol, lb_algorithm=lb_algorithm) + self.octavia.pool_show(pools["id"]) diff --git a/rally_openstack/scenarios/octavia/utils.py b/rally_openstack/scenarios/octavia/utils.py new file mode 100644 index 00000000..9db25269 --- /dev/null +++ b/rally_openstack/scenarios/octavia/utils.py @@ -0,0 +1,27 @@ +# Copyright 2018: 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 rally_openstack import scenario +from rally_openstack.services.loadbalancer import octavia + + +class OctaviaBase(scenario.OpenStackScenario): + """Base class for Octavia scenarios with basic atomic actions.""" + + def __init__(self, context=None, admin_clients=None, clients=None): + super(OctaviaBase, self).__init__(context, admin_clients, clients) + self.octavia = octavia.Octavia( + self._clients, name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions()) diff --git a/rally_openstack/services/loadbalancer/octavia.py b/rally_openstack/services/loadbalancer/octavia.py index 71aabb94..96aa80b4 100644 --- a/rally_openstack/services/loadbalancer/octavia.py +++ b/rally_openstack/services/loadbalancer/octavia.py @@ -196,16 +196,53 @@ class Octavia(service.Service): """ return self._clients.octavia().pool_list(**kwargs) + def update_pool_resource(self, pool): + try: + new_pool = self._clients.octavia().pool_show(pool["id"]) + except Exception as e: + if getattr(e, "status_code", 400) == 404: + raise exceptions.GetResourceNotFound(resource=pool) + raise exceptions.GetResourceFailure(resource=pool, err=e) + return new_pool + @atomic.action_timer("octavia.pool_create") - def pool_create(self, **kwargs): + def pool_create(self, lb_id, protocol, lb_algorithm, + description=None, admin_state_up=True, + session_persistence=None): """Create a pool - :param kwargs: - Parameters to create a listener with (expects json=) + :param lb_id: ID of the loadbalancer + :param protocol: protocol of the resource + :param lb_algorithm: loadbalancing algorithm of the pool + :param description: a human readable description of the pool + :param admin_state_up: administrative state of the resource + :param session_persistence: a json object specifiying the session + persistence of the pool :return: A dict of the created pool's settings """ - return self._clients.octavia().pool_create(**kwargs) + args = { + "name": self.generate_random_name(), + "loadbalancer_id": lb_id, + "protocol": protocol, + "lb_algorithm": lb_algorithm, + "description": description, + "admin_state_up": admin_state_up, + "session_persistence": session_persistence + } + pool = self._clients.octavia().pool_create( + json={"pool": args}) + pool = pool["pool"] + pool = utils.wait_for_status( + pool, + ready_statuses=["ACTIVE"], + status_attr="provisioning_status", + update_resource=self.update_pool_resource, + timeout=CONF.openstack.octavia_create_loadbalancer_timeout, + check_interval=( + CONF.openstack.octavia_create_loadbalancer_poll_interval) + ) + return pool @atomic.action_timer("octavia.pool_delete") def pool_delete(self, pool_id): @@ -230,17 +267,18 @@ class Octavia(service.Service): return self._clients.octavia().pool_show(pool_id) @atomic.action_timer("octavia.pool_set") - def pool_set(self, pool_id, **kwargs): + def pool_set(self, pool_id, pool_update_args): """Update a pool's settings :param pool_id: ID of the pool to update - :param kwargs: + :param pool_update_args: A dict of arguments to update a pool :return: Response Code from the API """ - return self._clients.octavia().pool_set(pool_id, **kwargs) + return self._clients.octavia().pool_set( + pool_id, json={"pool": pool_update_args}) @atomic.action_timer("octavia.member_list") def member_list(self, pool_id, **kwargs): diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.json b/samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.json new file mode 100644 index 00000000..99371c11 --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.json @@ -0,0 +1,28 @@ +{ + "Octavia.create_and_delete_pools": [ + { + "args": { + "protocol": "HTTP", + "lb_algorithm": "ROUND_ROBIN" + }, + "runner": { + "type": "constant", + "times": 5, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "roles": ["load-balancer_member"], + "network": {} + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.yaml b/samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.yaml new file mode 100644 index 00000000..7323b0a4 --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-delete-pools.yaml @@ -0,0 +1,20 @@ +--- + Octavia.create_and_delete_pools: + - + args: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + type: "constant" + times: 5 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + roles: + - load-balancer_member + network: {} + sla: + failure_rate: + max: 0 diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-list-pools.json b/samples/tasks/scenarios/octavia/octavia-create-and-list-pools.json new file mode 100644 index 00000000..eec4d1c3 --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-list-pools.json @@ -0,0 +1,28 @@ +{ + "Octavia.create_and_list_pools": [ + { + "args": { + "protocol": "HTTP", + "lb_algorithm": "ROUND_ROBIN" + }, + "runner": { + "type": "constant", + "times": 5, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "roles": ["load-balancer_member"], + "network": {} + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-list-pools.yaml b/samples/tasks/scenarios/octavia/octavia-create-and-list-pools.yaml new file mode 100644 index 00000000..31fa32b0 --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-list-pools.yaml @@ -0,0 +1,20 @@ +--- + Octavia.create_and_list_pools: + - + args: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + type: "constant" + times: 5 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + roles: + - load-balancer_member + network: {} + sla: + failure_rate: + max: 0 diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-show-pools.json b/samples/tasks/scenarios/octavia/octavia-create-and-show-pools.json new file mode 100644 index 00000000..9d270cbd --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-show-pools.json @@ -0,0 +1,28 @@ +{ + "Octavia.create_and_show_pools": [ + { + "args": { + "protocol": "HTTP", + "lb_algorithm": "ROUND_ROBIN" + }, + "runner": { + "type": "constant", + "times": 5, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "roles": ["load-balancer_member"], + "network": {} + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-show-pools.yaml b/samples/tasks/scenarios/octavia/octavia-create-and-show-pools.yaml new file mode 100644 index 00000000..898d7a83 --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-show-pools.yaml @@ -0,0 +1,20 @@ +--- + Octavia.create_and_show_pools: + - + args: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + type: "constant" + times: 5 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + roles: + - load-balancer_member + network: {} + sla: + failure_rate: + max: 0 diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-update-pools.json b/samples/tasks/scenarios/octavia/octavia-create-and-update-pools.json new file mode 100644 index 00000000..d500ca8d --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-update-pools.json @@ -0,0 +1,28 @@ +{ + "Octavia.create_and_update_pools": [ + { + "args": { + "protocol": "HTTP", + "lb_algorithm": "ROUND_ROBIN" + }, + "runner": { + "type": "constant", + "times": 5, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "roles": ["load-balancer_member"], + "network": {} + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/octavia/octavia-create-and-update-pools.yaml b/samples/tasks/scenarios/octavia/octavia-create-and-update-pools.yaml new file mode 100644 index 00000000..2b6f5307 --- /dev/null +++ b/samples/tasks/scenarios/octavia/octavia-create-and-update-pools.yaml @@ -0,0 +1,20 @@ +--- + Octavia.create_and_update_pools: + - + args: + protocol: "HTTP" + lb_algorithm: "ROUND_ROBIN" + runner: + type: "constant" + times: 5 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + roles: + - load-balancer_member + network: {} + sla: + failure_rate: + max: 0 diff --git a/tests/unit/cleanup/test_resources.py b/tests/unit/cleanup/test_resources.py index 43161d4a..42d5b15f 100644 --- a/tests/unit/cleanup/test_resources.py +++ b/tests/unit/cleanup/test_resources.py @@ -1222,7 +1222,7 @@ class BarbicanSecretsTestCase(test.TestCase): class OctaviaResourceTestCase(test.TestCase): def get_octavia(self): - octavia = resources.OctaviaLoadbalancer() + octavia = resources.OctaviaMixIn() octavia._service = "octavia" octavia._manager = mock.Mock() return octavia diff --git a/tests/unit/scenarios/loadbalancer/test_pools.py b/tests/unit/scenarios/loadbalancer/test_pools.py new file mode 100644 index 00000000..9327cc6b --- /dev/null +++ b/tests/unit/scenarios/loadbalancer/test_pools.py @@ -0,0 +1,149 @@ +# Copyright 2018: 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 mock + +from rally_openstack.scenarios.octavia import pools +from tests.unit import test + + +class PoolsTestCase(test.ScenarioTestCase): + + def setUp(self): + super(PoolsTestCase, self).setUp() + patch = mock.patch( + "rally_openstack.services.loadbalancer.octavia.Octavia") + self.addCleanup(patch.stop) + self.mock_loadbalancers = patch.start() + + def _get_context(self): + context = super(PoolsTestCase, self).get_test_context() + context.update({ + "user": { + "id": "fake_user", + "tenant_id": "fake_tenant", + "credential": mock.MagicMock() + }, + "tenant": {"id": "fake_tenant", + "networks": [{"id": "fake_net", + "subnets": ["fake_subnet"]}]}}) + return context + + def test_create_and_list_pools(self): + loadbalancer_service = self.mock_loadbalancers.return_value + scenario = pools.CreateAndListPools(self._get_context()) + scenario.run(protocol="HTTP", lb_algorithm="ROUND_ROBIN") + loadbalancer = [{ + "loadbalancer": { + "id": "loadbalancer-id" + } + }] + subnets = [] + mock_has_calls = [] + networks = self._get_context()["tenant"]["networks"] + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet in subnets: + mock_has_calls.append(mock.call(subnet_id="fake_subnet")) + loadbalancer_service.load_balancer_create.assert_has_calls( + mock_has_calls) + for lb in loadbalancer: + self.assertEqual( + 1, loadbalancer_service.wait_for_loadbalancer_prov_status + .call_count) + self.assertEqual(1, + loadbalancer_service.pool_create.call_count) + loadbalancer_service.pool_list.assert_called_once_with() + + def test_create_and_delete_pools(self): + loadbalancer_service = self.mock_loadbalancers.return_value + scenario = pools.CreateAndDeletePools(self._get_context()) + scenario.run(protocol="HTTP", lb_algorithm="ROUND_ROBIN") + loadbalancer = [{ + "loadbalancer": { + "id": "loadbalancer-id" + } + }] + subnets = [] + mock_has_calls = [] + networks = self._get_context()["tenant"]["networks"] + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet in subnets: + mock_has_calls.append(mock.call(subnet_id="fake_subnet")) + loadbalancer_service.load_balancer_create.assert_has_calls( + mock_has_calls) + for lb in loadbalancer: + self.assertEqual( + 1, loadbalancer_service.wait_for_loadbalancer_prov_status + .call_count) + self.assertEqual(1, + loadbalancer_service.pool_create.call_count) + self.assertEqual(1, + loadbalancer_service.pool_delete.call_count) + + def test_create_and_update_pools(self): + loadbalancer_service = self.mock_loadbalancers.return_value + scenario = pools.CreateAndUpdatePools(self._get_context()) + scenario.run(protocol="HTTP", lb_algorithm="ROUND_ROBIN") + loadbalancer = [{ + "loadbalancer": { + "id": "loadbalancer-id" + } + }] + subnets = [] + mock_has_calls = [] + networks = self._get_context()["tenant"]["networks"] + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet in subnets: + mock_has_calls.append(mock.call(subnet_id="fake_subnet")) + loadbalancer_service.load_balancer_create.assert_has_calls( + mock_has_calls) + for lb in loadbalancer: + self.assertEqual( + 1, loadbalancer_service.wait_for_loadbalancer_prov_status + .call_count) + self.assertEqual(1, + loadbalancer_service.pool_create.call_count) + self.assertEqual(1, + loadbalancer_service.pool_set.call_count) + + def test_create_and_show_pools(self): + loadbalancer_service = self.mock_loadbalancers.return_value + scenario = pools.CreateAndShowPools(self._get_context()) + scenario.run(protocol="HTTP", lb_algorithm="ROUND_ROBIN") + loadbalancer = [{ + "loadbalancer": { + "id": "loadbalancer-id" + } + }] + subnets = [] + mock_has_calls = [] + networks = self._get_context()["tenant"]["networks"] + for network in networks: + subnets.extend(network.get("subnets", [])) + for subnet in subnets: + mock_has_calls.append(mock.call(subnet_id="fake_subnet")) + loadbalancer_service.load_balancer_create.assert_has_calls( + mock_has_calls) + for lb in loadbalancer: + self.assertEqual( + 1, loadbalancer_service.wait_for_loadbalancer_prov_status + .call_count) + self.assertEqual(1, + loadbalancer_service.pool_create.call_count) + self.assertEqual(1, + loadbalancer_service.pool_show.call_count) diff --git a/tests/unit/scenarios/loadbalancer/test_utils.py b/tests/unit/scenarios/loadbalancer/test_utils.py index d8fa9247..ed0b7737 100644 --- a/tests/unit/scenarios/loadbalancer/test_utils.py +++ b/tests/unit/scenarios/loadbalancer/test_utils.py @@ -15,7 +15,7 @@ import mock -from rally_openstack.scenarios.octavia import loadbalancers +from rally_openstack.scenarios.octavia import utils from tests.unit import test @@ -42,6 +42,6 @@ class LoadBalancerBaseTestCase(test.ScenarioTestCase): self.mock_service = patch.start() def test_octavia_base(self): - base = loadbalancers.OctaviaBase(self.context) + base = utils.OctaviaBase(self.context) self.assertEqual(base.octavia, self.mock_service.return_value) diff --git a/tests/unit/services/loadbalancer/test_octavia.py b/tests/unit/services/loadbalancer/test_octavia.py index 1cdb4383..618129ae 100644 --- a/tests/unit/services/loadbalancer/test_octavia.py +++ b/tests/unit/services/loadbalancer/test_octavia.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import fixtures import mock from rally.common import cfg @@ -31,6 +32,9 @@ class LoadBalancerServiceTestCase(test.TestCase): self.name_generator = mock.MagicMock() self.service = octavia.Octavia(self.clients, name_generator=self.name_generator) + self.mock_wait_for_status = fixtures.MockPatch( + "rally.task.utils.wait_for_status") + self.useFixture(self.mock_wait_for_status) def _get_context(self): context = test.get_test_context() @@ -164,11 +168,47 @@ class LoadBalancerServiceTestCase(test.TestCase): self._test_atomic_action_timer(self.atomic_actions(), "octavia.pool_list") + def test_update_pool_resource(self): + fake_pool = {"id": "pool-id"} + self.service.update_pool_resource(fake_pool) + self.service._clients.octavia().pool_show \ + .assert_called_once_with("pool-id") + + def test_update_pool_resource_fail_404(self): + fake_pool = {"id": "pool-id"} + ex = Exception() + ex.status_code = 404 + self.service._clients.octavia().pool_show.side_effect = ex + self.assertRaises( + exceptions.GetResourceNotFound, + self.service.update_pool_resource, fake_pool) + + def test_update_pool_resource_fail(self): + fake_pool = {"id": "pool-id"} + ex = Exception() + self.service._clients.octavia().pool_show.side_effect = ex + self.assertRaises( + exceptions.GetResourceFailure, + self.service.update_pool_resource, fake_pool) + def test_pool_create(self): - self.service.pool_create() - self.assertEqual( - 1, self.service._clients.octavia().pool_create.call_count) - self.service._clients.octavia().pool_create.assert_called_once_with() + self.service.generate_random_name = mock.MagicMock( + return_value="pool") + self.service.pool_create( + lb_id="loadbalancer-id", + protocol="HTTP", + lb_algorithm="ROUND_ROBIN") + self.service._clients.octavia().pool_create \ + .assert_called_once_with( + json={"pool": { + "lb_algorithm": "ROUND_ROBIN", + "protocol": "HTTP", + "description": None, + "admin_state_up": True, + "session_persistence": None, + "loadbalancer_id": "loadbalancer-id", + "name": "pool"}}) + self._test_atomic_action_timer(self.atomic_actions(), "octavia.pool_create") @@ -187,9 +227,14 @@ class LoadBalancerServiceTestCase(test.TestCase): "octavia.pool_show") def test_pool_set(self): - self.service.pool_set(pool_id="fake_pool") + pool_update_args = {"name": "new-pool-name"} + self.service.pool_set( + pool_id="fake_pool", + pool_update_args=pool_update_args) self.service._clients.octavia().pool_set \ - .assert_called_once_with("fake_pool") + .assert_called_once_with( + "fake_pool", + json={"pool": {"name": "new-pool-name"}}) self._test_atomic_action_timer(self.atomic_actions(), "octavia.pool_set") @@ -338,14 +383,14 @@ class LoadBalancerServiceTestCase(test.TestCase): def test_quota_list(self): self.service.quota_list(params="fake_params") - self.service._clients.octavia().quota_list\ + self.service._clients.octavia().quota_list \ .assert_called_once_with("fake_params") self._test_atomic_action_timer(self.atomic_actions(), "octavia.quota_list") def test_quota_show(self): self.service.quota_show(project_id="fake_project") - self.service._clients.octavia().quota_show\ + self.service._clients.octavia().quota_show \ .assert_called_once_with("fake_project") self._test_atomic_action_timer(self.atomic_actions(), "octavia.quota_show") @@ -389,15 +434,14 @@ class LoadBalancerServiceTestCase(test.TestCase): def test_update_loadbalancer_resource(self): fake_lb = {"id": "fake_lb"} self.service.update_loadbalancer_resource(lb=fake_lb) - self.service._clients.octavia().load_balancer_show. \ - assert_called_once_with("fake_lb") + self.service._clients.octavia().load_balancer_show \ + .assert_called_once_with("fake_lb") def test_update_loadbalancer_resource_fail_404(self): fake_lb = {"id": "fake_lb"} ex = Exception() ex.status_code = 404 - self.service._clients.octavia().load_balancer_show.side_effect = \ - ex + self.service._clients.octavia().load_balancer_show.side_effect = ex self.assertRaises( exceptions.GetResourceNotFound, self.service.update_loadbalancer_resource, fake_lb) @@ -405,8 +449,7 @@ class LoadBalancerServiceTestCase(test.TestCase): def test_update_loadbalancer_resource_fail(self): fake_lb = {"id": "fake_lb"} ex = Exception() - self.service._clients.octavia().load_balancer_show.side_effect = \ - ex + self.service._clients.octavia().load_balancer_show.side_effect = ex self.assertRaises( exceptions.GetResourceFailure, self.service.update_loadbalancer_resource, fake_lb)