Merge "Add neutron lbaasv2 loadbalancer scenarios"
This commit is contained in:
commit
6f3c139073
17
rally-jobs/rally-neutron-extensions.yaml
Normal file
17
rally-jobs/rally-neutron-extensions.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
NeutronLoadbalancerV2.create_and_list_loadbalancers:
|
||||
-
|
||||
args:
|
||||
lb_create_args: {}
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 5
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
network: {}
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
21
rally/plugins/openstack/cleanup/resources.py
Normal file → Executable file
21
rally/plugins/openstack/cleanup/resources.py
Normal file → Executable file
@ -386,6 +386,27 @@ class NeutronV1Pool(NeutronLbaasV1Mixin):
|
||||
pass
|
||||
|
||||
|
||||
class NeutronLbaasV2Mixin(NeutronMixin):
|
||||
|
||||
def list(self):
|
||||
if self.supports_extension("lbaasv2"):
|
||||
return super(NeutronLbaasV2Mixin, self).list()
|
||||
return []
|
||||
|
||||
|
||||
@base.resource("neutron", "loadbalancer", order=next(_neutron_order),
|
||||
tenant_resource=True)
|
||||
class NeutronV2Loadbalancer(NeutronLbaasV2Mixin):
|
||||
|
||||
def is_deleted(self):
|
||||
try:
|
||||
self._manager().show_loadbalancer(self.id())
|
||||
except Exception as e:
|
||||
return getattr(e, "status_code", 400) == 404
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@base.resource("neutron", "port", order=next(_neutron_order),
|
||||
tenant_resource=True)
|
||||
class NeutronPort(NeutronMixin):
|
||||
|
47
rally/plugins/openstack/scenarios/neutron/loadbalancer_v2.py
Executable file
47
rally/plugins/openstack/scenarios/neutron/loadbalancer_v2.py
Executable file
@ -0,0 +1,47 @@
|
||||
# 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 import consts
|
||||
from rally.plugins.openstack import scenario
|
||||
from rally.plugins.openstack.scenarios.neutron import utils
|
||||
from rally.task import validation
|
||||
|
||||
|
||||
"""Scenarios for Neutron Loadbalancer v2."""
|
||||
|
||||
|
||||
@validation.required_neutron_extensions("lbaasv2")
|
||||
@validation.required_services(consts.Service.NEUTRON)
|
||||
@validation.required_openstack(users=True)
|
||||
@validation.required_contexts("network")
|
||||
@scenario.configure(context={"cleanup": ["neutron"]},
|
||||
name="NeutronLoadbalancerV2.create_and_list_loadbalancers")
|
||||
class CreateAndListLoadbalancers(utils.NeutronScenario):
|
||||
|
||||
def run(self, lb_create_args=None):
|
||||
"""Create a loadbalancer(v2) and then list loadbalancers(v2).
|
||||
|
||||
Measure the "neutron lbaas-loadbalancer-list" command performance.
|
||||
The scenario creates a loadbalancer for every subnet and then lists
|
||||
loadbalancers.
|
||||
|
||||
:param loadbalancer_create_args: dict, POST /lbaas/loadbalancers
|
||||
request options
|
||||
"""
|
||||
lb_create_args = lb_create_args or {}
|
||||
subnets = []
|
||||
networks = self.context.get("tenant", {}).get("networks", [])
|
||||
for network in networks:
|
||||
subnets.extend(network.get("subnets", []))
|
||||
for subnet_id in subnets:
|
||||
self._create_lbaasv2_loadbalancer(subnet_id, **lb_create_args)
|
||||
self._list_lbaasv2_loadbalancers()
|
67
rally/plugins/openstack/scenarios/neutron/utils.py
Normal file → Executable file
67
rally/plugins/openstack/scenarios/neutron/utils.py
Normal file → Executable file
@ -15,12 +15,32 @@
|
||||
|
||||
import random
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from rally.common.i18n import _
|
||||
from rally.common import logging
|
||||
from rally import exceptions
|
||||
from rally.plugins.openstack import scenario
|
||||
from rally.plugins.openstack.wrappers import network as network_wrapper
|
||||
from rally.task import atomic
|
||||
from rally.task import utils
|
||||
|
||||
NEUTRON_BENCHMARK_OPTS = [
|
||||
cfg.FloatOpt(
|
||||
"neutron_create_loadbalancer_timeout",
|
||||
default=float(500),
|
||||
help="Neutron create loadbalancer timeout"),
|
||||
cfg.FloatOpt(
|
||||
"neutron_create_loadbalancer_poll_interval",
|
||||
default=float(2),
|
||||
help="Neutron create loadbalancer poll interval")
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
benchmark_group = cfg.OptGroup(name="benchmark",
|
||||
title="benchmark options")
|
||||
CONF.register_group(benchmark_group)
|
||||
CONF.register_opts(NEUTRON_BENCHMARK_OPTS, group=benchmark_group)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -588,3 +608,50 @@ class NeutronScenario(scenario.OpenStackScenario):
|
||||
body = {"security_group": security_group_update_args}
|
||||
return self.clients("neutron").update_security_group(
|
||||
security_group["security_group"]["id"], body)
|
||||
|
||||
def update_loadbalancer_resource(self, lb):
|
||||
try:
|
||||
new_lb = self.clients("neutron").show_loadbalancer(lb["id"])
|
||||
except Exception as e:
|
||||
if getattr(e, "status_code", 400) == 404:
|
||||
raise exceptions.GetResourceNotFound(resource=lb)
|
||||
raise exceptions.GetResourceFailure(resource=lb, err=e)
|
||||
return new_lb["loadbalancer"]
|
||||
|
||||
@atomic.optional_action_timer("neutron.create_lbaasv2_loadbalancer")
|
||||
def _create_lbaasv2_loadbalancer(self, subnet_id, **lb_create_args):
|
||||
"""Create LB loadbalancer(v2)
|
||||
|
||||
:param subnet_id: str, neutron subnet-id
|
||||
:param lb_create_args: dict, POST /lbaas/loadbalancers request options
|
||||
:param atomic_action: True if this is an atomic action. added
|
||||
and handled by the
|
||||
optional_action_timer() decorator
|
||||
:returns: dict, neutron lb
|
||||
"""
|
||||
args = {"name": self.generate_random_name(),
|
||||
"vip_subnet_id": subnet_id}
|
||||
args.update(lb_create_args)
|
||||
neutronclient = self.clients("neutron")
|
||||
lb = neutronclient.create_loadbalancer({"loadbalancer": args})
|
||||
lb = lb["loadbalancer"]
|
||||
lb = utils.wait_for_status(
|
||||
lb,
|
||||
ready_statuses=["ACTIVE"],
|
||||
status_attr="provisioning_status",
|
||||
update_resource=self.update_loadbalancer_resource,
|
||||
timeout=CONF.benchmark.neutron_create_loadbalancer_timeout,
|
||||
check_interval=(
|
||||
CONF.benchmark.neutron_create_loadbalancer_poll_interval)
|
||||
)
|
||||
return lb
|
||||
|
||||
@atomic.action_timer("neutron.list_lbaasv2_loadbalancers")
|
||||
def _list_lbaasv2_loadbalancers(self, retrieve_all=True, **lb_list_args):
|
||||
"""List LB loadbalancers(v2)
|
||||
|
||||
:param lb_list_args: dict, POST /lbaas/loadbalancers request options
|
||||
:returns: dict, neutron lb loadbalancers(v2)
|
||||
"""
|
||||
return self.clients("neutron").list_loadbalancers(retrieve_all,
|
||||
**lb_list_args)
|
||||
|
@ -0,0 +1,26 @@
|
||||
{
|
||||
"NeutronLoadbalancerV2.create_and_list_loadbalancers": [
|
||||
{
|
||||
"args": {
|
||||
"lb_create_args": {}
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 5,
|
||||
"concurrency": 2
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 2,
|
||||
"users_per_tenant": 2
|
||||
},
|
||||
"network": {}
|
||||
},
|
||||
"sla": {
|
||||
"failure_rate": {
|
||||
"max": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
NeutronLoadbalancerV2.create_and_list_loadbalancers:
|
||||
-
|
||||
args:
|
||||
lb_create_args: {}
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 5
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
network: {}
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
73
tests/unit/plugins/openstack/cleanup/test_resources.py
Normal file → Executable file
73
tests/unit/plugins/openstack/cleanup/test_resources.py
Normal file → Executable file
@ -434,6 +434,79 @@ class NeutronLbaasV1MixinTestCase(test.TestCase):
|
||||
self.assertFalse(neut._manager().list_some_resources.called)
|
||||
|
||||
|
||||
class NeutronLbaasV2MixinTestCase(test.TestCase):
|
||||
|
||||
def get_neutron_lbaasv2_mixin(self, extensions=None):
|
||||
if extensions is None:
|
||||
extensions = []
|
||||
neut = resources.NeutronLbaasV2Mixin()
|
||||
neut._service = "neutron"
|
||||
neut._resource = "some_resource"
|
||||
neut._manager = mock.Mock()
|
||||
neut._manager().list_extensions.return_value = {
|
||||
"extensions": [{"alias": ext} for ext in extensions]
|
||||
}
|
||||
return neut
|
||||
|
||||
def test_list_lbaasv2_available(self):
|
||||
neut = self.get_neutron_lbaasv2_mixin(extensions=["lbaasv2"])
|
||||
neut.tenant_uuid = "user_tenant"
|
||||
|
||||
some_resources = [{"tenant_id": neut.tenant_uuid}, {"tenant_id": "a"}]
|
||||
neut._manager().list_some_resources.return_value = {
|
||||
"some_resources": some_resources
|
||||
}
|
||||
|
||||
self.assertEqual([some_resources[0]], list(neut.list()))
|
||||
neut._manager().list_some_resources.assert_called_once_with(
|
||||
tenant_id=neut.tenant_uuid)
|
||||
|
||||
def test_list_lbaasv2_unavailable(self):
|
||||
neut = self.get_neutron_lbaasv2_mixin()
|
||||
|
||||
self.assertEqual([], list(neut.list()))
|
||||
self.assertFalse(neut._manager().list_some_resources.called)
|
||||
|
||||
|
||||
class NeutronV2LoadbalancerTestCase(test.TestCase):
|
||||
|
||||
def get_neutron_lbaasv2_lb(self):
|
||||
neutron_lb = resources.NeutronV2Loadbalancer()
|
||||
neutron_lb.raw_resource = {"id": "1", "name": "s_rally"}
|
||||
neutron_lb._manager = mock.Mock()
|
||||
return neutron_lb
|
||||
|
||||
def test_is_deleted_true(self):
|
||||
from neutronclient.common import exceptions as n_exceptions
|
||||
neutron_lb = self.get_neutron_lbaasv2_lb()
|
||||
neutron_lb._manager().show_loadbalancer.side_effect = (
|
||||
n_exceptions.NotFound)
|
||||
|
||||
self.assertTrue(neutron_lb.is_deleted())
|
||||
|
||||
neutron_lb._manager().show_loadbalancer.assert_called_once_with(
|
||||
neutron_lb.id())
|
||||
|
||||
def test_is_deleted_false(self):
|
||||
from neutronclient.common import exceptions as n_exceptions
|
||||
neutron_lb = self.get_neutron_lbaasv2_lb()
|
||||
neutron_lb._manager().show_loadbalancer.return_value = (
|
||||
neutron_lb.raw_resource)
|
||||
|
||||
self.assertFalse(neutron_lb.is_deleted())
|
||||
neutron_lb._manager().show_loadbalancer.assert_called_once_with(
|
||||
neutron_lb.id())
|
||||
|
||||
neutron_lb._manager().show_loadbalancer.reset_mock()
|
||||
|
||||
neutron_lb._manager().show_loadbalancer.side_effect = (
|
||||
n_exceptions.Forbidden)
|
||||
|
||||
self.assertFalse(neutron_lb.is_deleted())
|
||||
neutron_lb._manager().show_loadbalancer.assert_called_once_with(
|
||||
neutron_lb.id())
|
||||
|
||||
|
||||
class NeutronPortTestCase(test.TestCase):
|
||||
|
||||
def test_delete(self):
|
||||
|
59
tests/unit/plugins/openstack/scenarios/neutron/test_loadbalancer_v2.py
Executable file
59
tests/unit/plugins/openstack/scenarios/neutron/test_loadbalancer_v2.py
Executable file
@ -0,0 +1,59 @@
|
||||
# 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 ddt
|
||||
import mock
|
||||
|
||||
from rally.plugins.openstack.scenarios.neutron import loadbalancer_v2
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class NeutronLoadbalancerv2TestCase(test.TestCase):
|
||||
|
||||
def _get_context(self):
|
||||
context = test.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
|
||||
|
||||
@ddt.data(
|
||||
{},
|
||||
{"lb_create_args": None},
|
||||
{"lb_create_args": {}},
|
||||
{"lb_create_args": {"name": "given-name"}},
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_create_and_list_load_balancers(self, lb_create_args=None):
|
||||
context = self._get_context()
|
||||
scenario = loadbalancer_v2.CreateAndListLoadbalancers(context)
|
||||
lb_create_args = lb_create_args or {}
|
||||
networks = context["tenant"]["networks"]
|
||||
scenario._create_lbaasv2_loadbalancer = mock.Mock()
|
||||
scenario._list_lbaasv2_loadbalancers = mock.Mock()
|
||||
scenario.run(lb_create_args=lb_create_args)
|
||||
|
||||
subnets = []
|
||||
mock_has_calls = []
|
||||
for network in networks:
|
||||
subnets.extend(network.get("subnets", []))
|
||||
for subnet in subnets:
|
||||
mock_has_calls.append(mock.call(subnet, **lb_create_args))
|
||||
scenario._create_lbaasv2_loadbalancer.assert_has_calls(mock_has_calls)
|
||||
scenario._list_lbaasv2_loadbalancers.assert_called_once_with()
|
69
tests/unit/plugins/openstack/scenarios/neutron/test_utils.py
Normal file → Executable file
69
tests/unit/plugins/openstack/scenarios/neutron/test_utils.py
Normal file → Executable file
@ -20,7 +20,6 @@ from rally import exceptions
|
||||
from rally.plugins.openstack.scenarios.neutron import utils
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
NEUTRON_UTILS = "rally.plugins.openstack.scenarios.neutron.utils."
|
||||
|
||||
|
||||
@ -880,6 +879,74 @@ class NeutronScenarioTestCase(test.ScenarioTestCase):
|
||||
self._test_atomic_action_timer(self.scenario.atomic_actions(),
|
||||
"neutron.update_healthmonitor")
|
||||
|
||||
def test_update_loadbalancer_resource(self):
|
||||
lb = {"id": "1", "provisioning_status": "READY"}
|
||||
new_lb = {"id": "1", "provisioning_status": "ACTIVE"}
|
||||
self.clients("neutron").show_loadbalancer.return_value = {
|
||||
"loadbalancer": new_lb}
|
||||
|
||||
return_lb = self.scenario.update_loadbalancer_resource(lb)
|
||||
|
||||
self.clients("neutron").show_loadbalancer.assert_called_once_with(
|
||||
lb["id"])
|
||||
self.assertEqual(new_lb, return_lb)
|
||||
|
||||
def test_update_loadbalancer_resource_not_found(self):
|
||||
from neutronclient.common import exceptions as n_exceptions
|
||||
lb = {"id": "1", "provisioning_status": "READY"}
|
||||
self.clients("neutron").show_loadbalancer.side_effect = (
|
||||
n_exceptions.NotFound)
|
||||
|
||||
self.assertRaises(exceptions.GetResourceNotFound,
|
||||
self.scenario.update_loadbalancer_resource,
|
||||
lb)
|
||||
self.clients("neutron").show_loadbalancer.assert_called_once_with(
|
||||
lb["id"])
|
||||
|
||||
def test_update_loadbalancer_resource_failure(self):
|
||||
from neutronclient.common import exceptions as n_exceptions
|
||||
lb = {"id": "1", "provisioning_status": "READY"}
|
||||
self.clients("neutron").show_loadbalancer.side_effect = (
|
||||
n_exceptions.Forbidden)
|
||||
|
||||
self.assertRaises(exceptions.GetResourceFailure,
|
||||
self.scenario.update_loadbalancer_resource,
|
||||
lb)
|
||||
self.clients("neutron").show_loadbalancer.assert_called_once_with(
|
||||
lb["id"])
|
||||
|
||||
def test__create_lbaasv2_loadbalancer(self):
|
||||
neutronclient = self.clients("neutron")
|
||||
create_args = {"name": "s_rally", "vip_subnet_id": "1",
|
||||
"fake": "fake"}
|
||||
new_lb = {"id": "1", "provisioning_status": "ACTIVE"}
|
||||
|
||||
self.scenario.generate_random_name = mock.Mock(
|
||||
return_value="s_rally")
|
||||
self.mock_wait_for_status.mock.return_value = new_lb
|
||||
|
||||
return_lb = self.scenario._create_lbaasv2_loadbalancer(
|
||||
"1", fake="fake")
|
||||
|
||||
neutronclient.create_loadbalancer.assert_called_once_with(
|
||||
{"loadbalancer": create_args})
|
||||
self.assertEqual(new_lb, return_lb)
|
||||
self._test_atomic_action_timer(self.scenario.atomic_actions(),
|
||||
"neutron.create_lbaasv2_loadbalancer")
|
||||
|
||||
def test__list_lbaasv2_loadbalancers(self):
|
||||
value = {"loadbalancer": [{"id": "1", "name": "s_rally"}]}
|
||||
self.clients("neutron").list_loadbalancers.return_value = value
|
||||
|
||||
return_value = self.scenario._list_lbaasv2_loadbalancers(
|
||||
True, fake="fake")
|
||||
|
||||
(self.clients("neutron").list_loadbalancers
|
||||
.assert_called_once_with(True, fake="fake"))
|
||||
self.assertEqual(value, return_value)
|
||||
self._test_atomic_action_timer(self.scenario.atomic_actions(),
|
||||
"neutron.list_lbaasv2_loadbalancers")
|
||||
|
||||
|
||||
class NeutronScenarioFunctionalTestCase(test.FakeClientsScenarioTestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user