Merge "Add Neutron Loadbalancer v1 create and list pool"
This commit is contained in:
commit
c52f111a98
@ -91,6 +91,28 @@
|
||||
failure_rate:
|
||||
max: 20
|
||||
|
||||
NeutronLoadbalancerV1.create_and_list_pools:
|
||||
-
|
||||
args:
|
||||
pool_create_args: {}
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 20
|
||||
concurrency: 10
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
network: {}
|
||||
quotas:
|
||||
neutron:
|
||||
network: -1
|
||||
subnet: -1
|
||||
pool: -1
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
NeutronNetworks.create_and_update_networks:
|
||||
-
|
||||
args:
|
||||
|
@ -52,6 +52,10 @@ class NeutronQuotas(object):
|
||||
"security_group_rule": {
|
||||
"type": "integer",
|
||||
"minimum": -1
|
||||
},
|
||||
"pool": {
|
||||
"type": "integer",
|
||||
"minimum": -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
38
rally/plugins/openstack/scenarios/neutron/loadbalancer_v1.py
Normal file
38
rally/plugins/openstack/scenarios/neutron/loadbalancer_v1.py
Normal file
@ -0,0 +1,38 @@
|
||||
# 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.benchmark.scenarios import base
|
||||
from rally.benchmark import validation
|
||||
from rally import consts
|
||||
from rally.plugins.openstack.scenarios.neutron import utils
|
||||
|
||||
|
||||
class NeutronLoadbalancerV1(utils.NeutronScenario):
|
||||
"""Benchmark scenarios for Neutron Loadbalancer v1."""
|
||||
|
||||
@validation.restricted_parameters("subnet_id", subdict="pool_create_args")
|
||||
@validation.required_services(consts.Service.NEUTRON)
|
||||
@validation.required_openstack(users=True)
|
||||
@validation.required_contexts("network")
|
||||
@base.scenario(context={"cleanup": ["neutron"]})
|
||||
def create_and_list_pools(self, pool_create_args=None):
|
||||
"""Create a pool(v1) and then list pools(v1).
|
||||
|
||||
Measure the "neutron lb-pool-list" command performance.
|
||||
The scenario creates a pool for every subnet and then lists pools.
|
||||
|
||||
:param pool_create_args: dict, POST /lb/pools request options
|
||||
"""
|
||||
for net in self.context.get("tenant", {}).get("networks", []):
|
||||
for subnet_id in net["subnets"]:
|
||||
self._create_v1_pool(subnet_id, **pool_create_args)
|
||||
self._list_v1_pools()
|
@ -28,6 +28,9 @@ class NeutronScenario(base.Scenario):
|
||||
RESOURCE_NAME_PREFIX = "rally_net_"
|
||||
RESOURCE_NAME_LENGTH = 16
|
||||
SUBNET_IP_VERSION = 4
|
||||
# TODO(rkiran): modify in case LBaaS-v2 requires
|
||||
LB_METHOD = "ROUND_ROBIN"
|
||||
LB_PROTOCOL = "HTTP"
|
||||
|
||||
@base.atomic_action_timer("neutron.create_network")
|
||||
def _create_network(self, network_create_args):
|
||||
@ -287,3 +290,22 @@ class NeutronScenario(base.Scenario):
|
||||
"""
|
||||
self.clients("neutron").remove_interface_router(
|
||||
router["id"], {"subnet_id": subnet["id"]})
|
||||
|
||||
@base.atomic_action_timer("neutron.create_pool")
|
||||
def _create_v1_pool(self, subnet_id, **pool_create_args):
|
||||
"""Create pool(v1)
|
||||
|
||||
:parm subnet_id: str, neutron subnet-id
|
||||
:parm pool_create_args: dict, POST /lb/pools request options
|
||||
:returns: obj, neutron lb pool
|
||||
"""
|
||||
args = {"lb_method": self.LB_METHOD, "protocol": self.LB_PROTOCOL,
|
||||
"name": self._generate_random_name("rally_pool_"),
|
||||
"subnet_id": subnet_id}
|
||||
args.update(pool_create_args)
|
||||
return self.clients("neutron").create_pool({"pool": args})
|
||||
|
||||
@base.atomic_action_timer("neutron.list_pools")
|
||||
def _list_v1_pools(self, **kwargs):
|
||||
"""Return user lb pool list(v1)."""
|
||||
return self.clients("neutron").list_pools()
|
||||
|
@ -1064,6 +1064,7 @@ class FakeNeutronClient(object):
|
||||
self.__subnets = {}
|
||||
self.__routers = {}
|
||||
self.__ports = {}
|
||||
self.__pools = {}
|
||||
self.__tenant_id = kwargs.get("tenant_id", generate_uuid())
|
||||
|
||||
self.format = "json"
|
||||
@ -1112,6 +1113,21 @@ class FakeNeutronClient(object):
|
||||
self.__networks[network_id] = network
|
||||
return {"network": network}
|
||||
|
||||
def create_pool(self, data):
|
||||
pool = setup_dict(data["pool"],
|
||||
required=["lb_method", "protocol", "subnet_id"],
|
||||
defaults={"name": generate_name("pool_"),
|
||||
"admin_state_up": True})
|
||||
if pool["subnet_id"] not in self.__subnets:
|
||||
raise neutron_exceptions.NeutronClientException
|
||||
pool_id = generate_uuid()
|
||||
|
||||
pool.update({"id": pool_id,
|
||||
"status": "PENDING_CREATE",
|
||||
"tenant_id": self.__tenant_id})
|
||||
self.__pools[pool_id] = pool
|
||||
return {"pool": pool}
|
||||
|
||||
def create_port(self, data):
|
||||
port = setup_dict(data["port"],
|
||||
required=["network_id"],
|
||||
@ -1238,6 +1254,10 @@ class FakeNeutronClient(object):
|
||||
nets = self._filter(self.__networks.values(), search_opts)
|
||||
return {"networks": nets}
|
||||
|
||||
def list_pools(self, **search_opts):
|
||||
pools = self._filter(self.__pools.values(), search_opts)
|
||||
return {"pools": pools}
|
||||
|
||||
def list_ports(self, **search_opts):
|
||||
ports = self._filter(self.__ports.values(), search_opts)
|
||||
return {"ports": ports}
|
||||
|
@ -0,0 +1,45 @@
|
||||
# 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.plugins.openstack.scenarios.neutron import loadbalancer_v1
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
class NeutronLoadbalancerv1TestCase(test.TestCase):
|
||||
|
||||
def _get_context(self):
|
||||
return {
|
||||
"user": {"id": "fake_user", "tenant_id": "fake_tenant"},
|
||||
"tenant": {"id": "fake_tenant",
|
||||
"networks": [{"id": "fake_net",
|
||||
"subnets": ["fake_subnet"]}]}}
|
||||
|
||||
def _validate_scenario(self, pool_create_args):
|
||||
neutron_scenario = loadbalancer_v1.NeutronLoadbalancerV1(
|
||||
self._get_context())
|
||||
neutron_scenario._create_v1_pool = mock.Mock()
|
||||
neutron_scenario._list_v1_pools = mock.Mock()
|
||||
neutron_scenario.create_and_list_pools(
|
||||
pool_create_args=pool_create_args)
|
||||
for net in self._get_context()["tenant"]["networks"]:
|
||||
for subnet_id in net["subnets"]:
|
||||
neutron_scenario._create_v1_pool.assert_called_once_with(
|
||||
subnet_id, **pool_create_args)
|
||||
neutron_scenario._list_v1_pools.assert_called_once_with()
|
||||
|
||||
def test_create_and_list_pools_default(self):
|
||||
self._validate_scenario(pool_create_args={})
|
||||
|
||||
def test_create_and_list_pools_explicit(self):
|
||||
self._validate_scenario(pool_create_args={"name": "given-name"})
|
@ -391,6 +391,56 @@ class NeutronScenarioTestCase(test.ClientsTestCase):
|
||||
{"allocation_pools": []},
|
||||
"10.10.10.0/24")] * subnets_per_network)
|
||||
|
||||
def test_create_v1_pool_explicit(self):
|
||||
neutron_scenario = utils.NeutronScenario()
|
||||
lb_method = "LEAST_CONNECTIONS"
|
||||
subnet = "fake-id"
|
||||
pool = mock.Mock()
|
||||
self.clients("neutron").create_pool.return_value = pool
|
||||
# Explicit options
|
||||
pool_data = {"lb_method": lb_method, "name": "explicit-name"}
|
||||
args = {"lb_method": "ROUND_ROBIN", "protocol": "HTTP",
|
||||
"name": "random_name", "subnet_id": subnet}
|
||||
args.update(pool_data)
|
||||
expected_pool_data = {"pool": args}
|
||||
pool = neutron_scenario._create_v1_pool(
|
||||
subnet_id=subnet, **pool_data)
|
||||
self.clients("neutron").create_pool.assert_called_once_with(
|
||||
expected_pool_data)
|
||||
self._test_atomic_action_timer(
|
||||
neutron_scenario.atomic_actions(), "neutron.create_pool")
|
||||
|
||||
@mock.patch(NEUTRON_UTILS + "NeutronScenario._generate_random_name")
|
||||
def test_create_v1_pool_default(self, mock_random_name):
|
||||
neutron_scenario = utils.NeutronScenario()
|
||||
random_name = "random_name"
|
||||
subnet = "fake-id"
|
||||
pool = mock.Mock()
|
||||
self.clients("neutron").create_pool.return_value = pool
|
||||
mock_random_name.return_value = random_name
|
||||
# Random pool name
|
||||
pool_data = {}
|
||||
args = {"lb_method": "ROUND_ROBIN", "protocol": "HTTP",
|
||||
"name": "random_name", "subnet_id": subnet}
|
||||
args.update(pool_data)
|
||||
expected_pool_data = {"pool": args}
|
||||
pool = neutron_scenario._create_v1_pool(
|
||||
subnet_id=subnet, **pool_data)
|
||||
self.clients("neutron").create_pool.assert_called_once_with(
|
||||
expected_pool_data)
|
||||
self._test_atomic_action_timer(
|
||||
neutron_scenario.atomic_actions(), "neutron.create_pool")
|
||||
|
||||
def test_list_v1_pools(self):
|
||||
scenario = utils.NeutronScenario()
|
||||
pools_list = []
|
||||
pools_dict = {"pools": pools_list}
|
||||
self.clients("neutron").list_pools.return_value = pools_dict
|
||||
return_pools_dict = scenario._list_v1_pools()
|
||||
self.assertEqual(pools_dict, return_pools_dict)
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"neutron.list_pools")
|
||||
|
||||
|
||||
class NeutronScenarioFunctionalTestCase(test.FakeClientsTestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user