diff --git a/rally-jobs/rally-neutron.yaml b/rally-jobs/rally-neutron.yaml index 430bc81f..1de3bbec 100644 --- a/rally-jobs/rally-neutron.yaml +++ b/rally-jobs/rally-neutron.yaml @@ -230,6 +230,29 @@ failure_rate: max: 0 + NeutronNetworks.create_and_show_ports: + - + args: + network_create_args: {} + port_create_args: {} + ports_per_network: 2 + runner: + type: "constant" + times: {{smoke or 5}} + concurrency: {{smoke or 2}} + context: + network: {} + users: + tenants: {{smoke or 2}} + users_per_tenant: {{smoke or 2}} + quotas: + neutron: + network: -1 + port: -1 + sla: + failure_rate: + max: 0 + NeutronNetworks.create_and_update_networks: - args: diff --git a/rally/plugins/openstack/scenarios/neutron/network.py b/rally/plugins/openstack/scenarios/neutron/network.py index 48f942d1..49126308 100644 --- a/rally/plugins/openstack/scenarios/neutron/network.py +++ b/rally/plugins/openstack/scenarios/neutron/network.py @@ -16,6 +16,7 @@ from rally import consts from rally.plugins.openstack import scenario from rally.plugins.openstack.scenarios.neutron import utils +from rally.task import atomic from rally.task import validation @@ -320,6 +321,42 @@ class CreateAndUpdatePorts(utils.NeutronScenario): self._update_port(port, port_update_args) +@validation.number("ports_per_network", minval=1, integer_only=True) +@validation.required_services(consts.Service.NEUTRON) +@validation.required_openstack(users=True) +@scenario.configure(context={"cleanup": ["neutron"]}, + name="NeutronNetworks.create_and_show_ports") +class CreateAndShowPorts(utils.NeutronScenario): + + def run(self, network_create_args=None, + port_create_args=None, ports_per_network=1): + """Create a given number of ports and show created ports in trun. + + Measure the "neutron port-create" and "neutron port-show" commands + performance. + + :param network_create_args: dict, POST /v2.0/networks request + options. + :param port_create_args: dict, POST /v2.0/ports request options + :param ports_per_network: int, number of ports for one network + """ + network_create_args = network_create_args or {} + port_create_args = port_create_args or {} + + network = self._get_or_create_network(network_create_args) + with atomic.ActionTimer(self, "neutron.create_and_show_%i_ports" % + ports_per_network): + for i in range(ports_per_network): + port = self._create_port(network, port_create_args) + msg = "Port isn't created" + self.assertTrue(port, err_msg=msg) + + port_info = self._show_port(port) + msg = "Created port and Showed port isn't equal" + self.assertEqual(port["port"]["id"], port_info["port"]["id"], + err_msg=msg) + + @validation.required_parameters("ports_per_network") @validation.required_services(consts.Service.NEUTRON) @scenario.configure(context={"cleanup": ["neutron"]}, diff --git a/rally/plugins/openstack/scenarios/neutron/utils.py b/rally/plugins/openstack/scenarios/neutron/utils.py index a3200311..a65f5185 100755 --- a/rally/plugins/openstack/scenarios/neutron/utils.py +++ b/rally/plugins/openstack/scenarios/neutron/utils.py @@ -253,6 +253,16 @@ class NeutronScenario(scenario.OpenStackScenario): """Return user ports list.""" return self.clients("neutron").list_ports()["ports"] + @atomic.action_timer("neutron.show_port") + def _show_port(self, port, **params): + """Return user port details. + + :param port: dict, neutron port + :param params: neutron port show options + :returns: neutron port dict + """ + return self.clients("neutron").show_port(port["port"]["id"], **params) + @atomic.action_timer("neutron.update_port") def _update_port(self, port, port_update_args): """Update the neutron port. diff --git a/samples/tasks/scenarios/neutron/create-and-show-ports.json b/samples/tasks/scenarios/neutron/create-and-show-ports.json new file mode 100644 index 00000000..8fec44d2 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-show-ports.json @@ -0,0 +1,34 @@ +{ + "NeutronNetworks.create_and_show_ports": [ + { + "args": { + "network_create_args": {}, + "port_create_args": {}, + "ports_per_network": 2 + }, + "runner": { + "type": "constant", + "times": 5, + "concurrency": 2 + }, + "context": { + "network": {}, + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "quotas": { + "neutron": { + "network": -1, + "port": -1 + } + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/neutron/create-and-show-ports.yaml b/samples/tasks/scenarios/neutron/create-and-show-ports.yaml new file mode 100644 index 00000000..13fb0308 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-show-ports.yaml @@ -0,0 +1,23 @@ +--- + NeutronNetworks.create_and_show_ports: + - + args: + network_create_args: {} + port_create_args: {} + ports_per_network: 2 + runner: + type: "constant" + times: 5 + concurrency: 2 + context: + network: {} + users: + tenants: 2 + users_per_tenant: 2 + quotas: + neutron: + network: -1 + port: -1 + sla: + failure_rate: + max: 0 diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_network.py b/tests/unit/plugins/openstack/scenarios/neutron/test_network.py index 08fe7b27..2d7e42a5 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_network.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_network.py @@ -16,6 +16,7 @@ import ddt import mock +from rally import exceptions as rally_exceptions from rally.plugins.openstack.scenarios.neutron import network from tests.unit import test @@ -352,6 +353,69 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): scenario._update_port.assert_has_calls( [mock.call(p, port_update_args) for p in ports]) + def test_create_and_show_ports_positive(self): + port_create_args = {"allocation_pools": []} + ports_per_network = 1 + network_create_args = {"router:external": True} + net = mock.MagicMock() + + scenario = network.CreateAndShowPorts(self.context) + scenario._get_or_create_network = mock.MagicMock(return_value=net) + scenario._create_port = mock.MagicMock() + scenario._show_port = mock.MagicMock() + port = {"port": {"id": 1, "name": "f"}} + port_info = {"port": {"id": 1, "name": "f", "status": "ACTIVE"}} + scenario._show_port.return_value = port_info + + # Positive case: + scenario._create_port.return_value = port + scenario.run(network_create_args=network_create_args, + port_create_args=port_create_args, + ports_per_network=ports_per_network) + scenario._get_or_create_network.assert_called_once_with( + network_create_args) + scenario._create_port.assert_called_with(net, port_create_args) + scenario._show_port.assert_called_with(port) + + def test_create_and_show_ports_negative(self): + port_create_args = {"allocation_pools": []} + ports_per_network = 1 + network_create_args = {"router:external": True} + net = mock.MagicMock() + + scenario = network.CreateAndShowPorts(self.context) + scenario._get_or_create_network = mock.MagicMock(return_value=net) + scenario._create_port = mock.MagicMock() + scenario._show_port = mock.MagicMock() + + # Negative case1: port isn't created + scenario._create_port.return_value = None + self.assertRaises(rally_exceptions.RallyAssertionError, + scenario.run, + network_create_args, + port_create_args, + ports_per_network) + scenario._get_or_create_network.assert_called_once_with( + network_create_args) + scenario._create_port.assert_called_once_with(net, port_create_args) + + # Negative case2: port isn't show + port = {"port": {"id": 1, "name": "f1"}} + port_info = {"port": {"id": 2, "name": "f2", "status": "ACTIVE"}} + scenario._show_port.return_value = port_info + scenario._create_port.return_value = port + + self.assertRaises(rally_exceptions.RallyAssertionError, + scenario.run, + network_create_args, + port_create_args, + ports_per_network) + + scenario._get_or_create_network.assert_called_with( + network_create_args) + scenario._create_port.assert_called_with(net, port_create_args) + scenario._show_port.assert_called_with(port) + def test_create_and_delete_ports(self): port_create_args = {"allocation_pools": []} ports_per_network = 10 diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py index 1b54e8aa..a9fea7c7 100755 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py @@ -379,6 +379,21 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(self.scenario.atomic_actions(), "neutron.list_ports") + def test_show_port(self): + expect_port = { + "port": { + "id": "port-id", + "name": "port-name", + "admin_state_up": True + } + } + self.clients("neutron").show_port.return_value = expect_port + self.assertEqual(expect_port, self.scenario._show_port(expect_port)) + self.clients("neutron").show_port.assert_called_once_with( + expect_port["port"]["id"]) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.show_port") + def test_update_port(self): expected_port = { "port": {