Add FloatingIP scenarios

As discussed on the neutron-performance meeting [1] floating IP operations
should be covered in the neutron gate rally job. As I set out to write
the missing tests I discovered that some of them were already written
by rally folks. For example see [2]. Keep in mind the test code has been
relocated since to the rally-openstack repository. For example see [3].
They were later added to neutron's rally job definition [4].

Here we add one more scenario to exercise the floating IP operations
left uncovered by the above changes: associate and dissociate.

[1] http://eavesdrop.openstack.org/meetings/neutron_performance/2018/neutron_performance.2018-10-22-16.02.log.html#l-143
[2] https://review.openstack.org/225223
[3] https://github.com/openstack/rally-openstack/blob/4e4bfc5/rally_openstack/scenarios/neutron/network.py
[4] https://review.openstack.org/620952

Change-Id: I32f3bad82fa0ca822e80d51220c120568a709332
Needed-By: https://review.openstack.org/624038
This commit is contained in:
Bence Romsics 2018-12-08 10:40:44 +01:00
parent 0cce343d6c
commit 3acde99264
7 changed files with 230 additions and 4 deletions

View File

@ -290,6 +290,29 @@
failure_rate:
max: 0
NeutronNetworks.associate_and_dissociate_floating_ips:
-
args:
floating_network: "public"
runner:
type: "constant"
times: {{smoke or 8}}
concurrency: {{smoke or 4}}
context:
users:
tenants: {{smoke or 2}}
users_per_tenant: {{smoke or 1}}
quotas:
neutron:
floatingip: -1
network: -1
port: -1
router: -1
subnet: -1
sla:
failure_rate:
max: 0
NeutronNetworks.create_and_list_routers:
-
args:

View File

@ -557,6 +557,61 @@ class CreateAndDeleteFloatingIps(utils.NeutronScenario):
self._delete_floating_ip(floating_ip["floatingip"])
@validation.add("required_services",
services=[consts.Service.NEUTRON])
@validation.add("required_platform", platform="openstack", users=True)
@validation.add("external_network_exists", param_name="floating_network")
@scenario.configure(
context={"cleanup@openstack": ["neutron"]},
name="NeutronNetworks.associate_and_dissociate_floating_ips",
platform="openstack")
class AssociateAndDissociateFloatingIps(utils.NeutronScenario):
def run(self, floating_network=None):
"""Associate and dissociate floating IPs.
Measure the "openstack floating ip set" and
"openstack floating ip unset" commands performance.
Because of the prerequisites for "floating ip set/unset" we also
measure the performance of the following commands:
* "openstack network create"
* "openstack subnet create"
* "openstack port create"
* "openstack router create"
* "openstack router set --external-gateway"
* "openstack router add subnet"
:param floating_network: str, external network for floating IP creation
"""
floating_ip = self._create_floatingip(
floating_network)
private_network = self._create_network(
network_create_args={})
subnet = self._create_subnet(
network=private_network,
subnet_create_args={})
port = self._create_port(
network=private_network,
port_create_args={})
router = self._create_router(
router_create_args={})
floating_network_id = self._get_network_id(floating_network)
self._add_gateway_router(
router,
{"network": {"id": floating_network_id}})
self._add_interface_router(
subnet["subnet"],
router["router"])
self._associate_floating_ip(
floatingip=floating_ip["floatingip"],
port=port["port"])
self._dissociate_floating_ip(
floatingip=floating_ip["floatingip"])
@validation.add("required_services",
services=[consts.Service.NEUTRON])
@validation.add("required_platform", platform="openstack", users=True)

View File

@ -410,16 +410,17 @@ class NeutronScenario(scenario.OpenStackScenario):
router["id"], {"subnet_id": subnet["id"]})
@atomic.action_timer("neutron.add_gateway_router")
def _add_gateway_router(self, router, ext_net, enable_snat):
def _add_gateway_router(self, router, ext_net, enable_snat=None):
"""Set the external network gateway for a router.
:param router: dict, neutron router
:param ext_net: external network for the gateway
:param enable_snat: True if enable snat
:param enable_snat: True if enable snat, None to avoid update
"""
gw_info = {"network_id": ext_net["network"]["id"]}
if self._ext_gw_mode_enabled:
gw_info["enable_snat"] = enable_snat
if enable_snat is not None:
if self._ext_gw_mode_enabled:
gw_info["enable_snat"] = enable_snat
self.clients("neutron").add_gateway_router(
router["router"]["id"], gw_info)
@ -573,6 +574,29 @@ class NeutronScenario(scenario.OpenStackScenario):
"""
return self.clients("neutron").delete_floatingip(floating_ip["id"])
@atomic.action_timer("neutron.associate_floating_ip")
def _associate_floating_ip(self, floatingip, port):
"""Associate floating IP with port.
:param floatingip: floating IP dict
:param port: port dict
:returns: updated floating IP dict
"""
return self.clients("neutron").update_floatingip(
floatingip["id"],
{"floatingip": {"port_id": port["id"]}})["floatingip"]
@atomic.action_timer("neutron.dissociate_floating_ip")
def _dissociate_floating_ip(self, floatingip):
"""Dissociate floating IP from ports.
:param floatingip: floating IP dict
:returns: updated floating IP dict
"""
return self.clients("neutron").update_floatingip(
floatingip["id"],
{"floatingip": {"port_id": None}})["floatingip"]
@atomic.action_timer("neutron.create_healthmonitor")
def _create_v1_healthmonitor(self, **healthmonitor_create_args):
"""Create LB healthmonitor.

View File

@ -0,0 +1,34 @@
{
"NeutronNetworks.associate_and_dissociate_floating_ips": [
{
"args": {
"floating_network": "public"
},
"runner": {
"type": "constant",
"times": 10,
"concurrency": 5
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 3
},
"quotas": {
"neutron": {
"floatingip": -1,
"network": -1,
"port": -1,
"router": -1,
"subnet": -1
}
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -0,0 +1,23 @@
---
NeutronNetworks.associate_and_dissociate_floating_ips:
-
args:
floating_network: "public"
runner:
type: "constant"
times: 10
concurrency: 5
context:
users:
tenants: 2
users_per_tenant: 3
quotas:
neutron:
floatingip: -1
network: -1
port: -1
router: -1
subnet: -1
sla:
failure_rate:
max: 0

View File

@ -550,6 +550,33 @@ class NeutronNetworksTestCase(test.ScenarioTestCase):
scenario._delete_floating_ip.assert_called_once_with(
scenario._create_floatingip.return_value["floatingip"])
def test_associate_and_dissociate_floating_ips(self):
scenario = network.AssociateAndDissociateFloatingIps(self.context)
fip = {"floatingip": {"id": "floating-ip-id"}}
subnet = {"subnet": {}}
port = {"port": {"id": "port-id"}}
router = {"router": {}}
scenario._create_floatingip = mock.Mock(return_value=fip)
scenario._create_network = mock.Mock()
scenario._create_subnet = mock.Mock(return_value=subnet)
scenario._create_port = mock.Mock(return_value=port)
scenario._create_router = mock.Mock(return_value=router)
scenario._get_network_id = mock.Mock()
scenario._add_gateway_router = mock.Mock()
scenario._add_interface_router = mock.Mock()
scenario._associate_floating_ip = mock.Mock()
scenario._dissociate_floating_ip = mock.Mock()
scenario.run(floating_network="public")
scenario._associate_floating_ip.assert_called_once_with(
floatingip=fip["floatingip"], port=port["port"])
scenario._dissociate_floating_ip.assert_called_once_with(
floatingip=fip["floatingip"])
@mock.patch("%s.DeleteSubnets._delete_subnet" % BASE)
def test_delete_subnets(self, mock__delete_subnet):
# do not guess what user will be used

View File

@ -413,6 +413,29 @@ class NeutronScenarioTestCase(test.ScenarioTestCase):
self._test_atomic_action_timer(self.scenario.atomic_actions(),
"neutron.add_gateway_router")
def test_add_gateway_router_no_snat_update(self):
ext_net = {
"network": {
"name": "extnet-name",
"id": "extnet-id"
}
}
router = {
"router": {
"name": "router-name",
"id": "router-id"
}
}
gw_info = {"network_id": ext_net["network"]["id"]}
self.clients("neutron").list_extensions.return_value = {
"extensions": [{"alias": "ext-gw-mode"}]}
self.scenario._add_gateway_router(router, ext_net)
self.clients("neutron").add_gateway_router.assert_called_once_with(
router["router"]["id"], gw_info)
self._test_atomic_action_timer(self.scenario.atomic_actions(),
"neutron.add_gateway_router")
def test_add_gateway_router_without_ext_gw_mode_extension(self):
ext_net = {
"network": {
@ -627,6 +650,23 @@ class NeutronScenarioTestCase(test.ScenarioTestCase):
self._test_atomic_action_timer(self.scenario.atomic_actions(),
"neutron.delete_floating_ip")
def test_associate_floating_ip(self):
fip = {"id": "fip-id"}
port = {"id": "port-id"}
self.scenario._associate_floating_ip(fip, port)
self.clients("neutron").update_floatingip.assert_called_once_with(
"fip-id", {"floatingip": {"port_id": "port-id"}})
self._test_atomic_action_timer(self.scenario.atomic_actions(),
"neutron.associate_floating_ip")
def test_dissociate_floating_ip(self):
fip = {"id": "fip-id"}
self.scenario._dissociate_floating_ip(fip)
self.clients("neutron").update_floatingip.assert_called_once_with(
"fip-id", {"floatingip": {"port_id": None}})
self._test_atomic_action_timer(self.scenario.atomic_actions(),
"neutron.dissociate_floating_ip")
@ddt.data(
{},
{"router_create_args": {"admin_state_up": False}},