Merge "Add neutron lbaasv2 loadbalancer scenarios"

This commit is contained in:
Jenkins 2017-01-21 17:20:58 +00:00 committed by Gerrit Code Review
commit 6f3c139073
9 changed files with 395 additions and 1 deletions

View 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
View File

@ -386,6 +386,27 @@ class NeutronV1Pool(NeutronLbaasV1Mixin):
pass 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), @base.resource("neutron", "port", order=next(_neutron_order),
tenant_resource=True) tenant_resource=True)
class NeutronPort(NeutronMixin): class NeutronPort(NeutronMixin):

View 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
View File

@ -15,12 +15,32 @@
import random import random
from oslo_config import cfg
from rally.common.i18n import _ from rally.common.i18n import _
from rally.common import logging from rally.common import logging
from rally import exceptions from rally import exceptions
from rally.plugins.openstack import scenario from rally.plugins.openstack import scenario
from rally.plugins.openstack.wrappers import network as network_wrapper from rally.plugins.openstack.wrappers import network as network_wrapper
from rally.task import atomic 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__) LOG = logging.getLogger(__name__)
@ -588,3 +608,50 @@ class NeutronScenario(scenario.OpenStackScenario):
body = {"security_group": security_group_update_args} body = {"security_group": security_group_update_args}
return self.clients("neutron").update_security_group( return self.clients("neutron").update_security_group(
security_group["security_group"]["id"], body) 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)

View File

@ -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
}
}
}
]
}

View 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

73
tests/unit/plugins/openstack/cleanup/test_resources.py Normal file → Executable file
View File

@ -434,6 +434,79 @@ class NeutronLbaasV1MixinTestCase(test.TestCase):
self.assertFalse(neut._manager().list_some_resources.called) 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): class NeutronPortTestCase(test.TestCase):
def test_delete(self): def test_delete(self):

View 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()

View File

@ -20,7 +20,6 @@ from rally import exceptions
from rally.plugins.openstack.scenarios.neutron import utils from rally.plugins.openstack.scenarios.neutron import utils
from tests.unit import test from tests.unit import test
NEUTRON_UTILS = "rally.plugins.openstack.scenarios.neutron.utils." 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(), self._test_atomic_action_timer(self.scenario.atomic_actions(),
"neutron.update_healthmonitor") "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): class NeutronScenarioFunctionalTestCase(test.FakeClientsScenarioTestCase):