diff --git a/rally-jobs/rally-neutron.yaml b/rally-jobs/rally-neutron.yaml index 5243af98..95184c4b 100644 --- a/rally-jobs/rally-neutron.yaml +++ b/rally-jobs/rally-neutron.yaml @@ -42,6 +42,31 @@ failure_rate: max: 20 + NeutronNetworks.set_and_clear_router_gateway: + - + args: + network_create_args: + router:external: True + router_create_args: {} + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + network: {} + users: + tenants: 2 + users_per_tenant: 2 + quotas: + neutron: + network: -1 + router: -1 + roles: + - "admin" + sla: + failure_rate: + max: 0 + NeutronNetworks.create_and_show_network: - args: @@ -726,4 +751,4 @@ users: tenants: 3 users_per_tenant: 2 - network: {} \ No newline at end of file + network: {} diff --git a/rally/plugins/openstack/scenarios/neutron/network.py b/rally/plugins/openstack/scenarios/neutron/network.py index afa98d49..94363ff8 100644 --- a/rally/plugins/openstack/scenarios/neutron/network.py +++ b/rally/plugins/openstack/scenarios/neutron/network.py @@ -304,6 +304,33 @@ class CreateAndDeleteRouters(utils.NeutronScenario): self._delete_router(router) +@validation.required_services(consts.Service.NEUTRON) +@validation.required_openstack(users=True) +@scenario.configure(context={"cleanup": ["neutron"]}, + name="NeutronNetworks.set_and_clear_router_gateway") +class SetAndClearRouterGateway(utils.NeutronScenario): + + def run(self, enable_snat=True, network_create_args=None, + router_create_args=None): + """Set and Remove the external network gateway from a router. + + create an external network and a router, set external network + gateway for the router, remove the external network gateway from + the router. + + :param enable_snat: True if enable snat + :param network_create_args: dict, POST /v2.0/networks request + options + :param router_create_args: dict, POST /v2.0/routers request options + """ + network_create_args = network_create_args or {} + router_create_args = router_create_args or {} + ext_net = self._create_network(network_create_args) + router = self._create_router(router_create_args) + self._add_gateway_router(router, ext_net, enable_snat) + self._remove_gateway_router(router) + + @validation.number("ports_per_network", minval=1, integer_only=True) @validation.required_services(consts.Service.NEUTRON) @validation.add("required_platform", platform="openstack", users=True) diff --git a/rally/plugins/openstack/scenarios/neutron/utils.py b/rally/plugins/openstack/scenarios/neutron/utils.py index c3f1d8df..56db4da9 100755 --- a/rally/plugins/openstack/scenarios/neutron/utils.py +++ b/rally/plugins/openstack/scenarios/neutron/utils.py @@ -403,6 +403,28 @@ class NeutronScenario(scenario.OpenStackScenario): self.clients("neutron").remove_interface_router( router["id"], {"subnet_id": subnet["id"]}) + @atomic.action_timer("neutron.add_gateway_router") + def _add_gateway_router(self, router, ext_net, enable_snat): + """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 + """ + gw_info = {"network_id": ext_net["network"]["id"], + "enable_snat": enable_snat} + self.clients("neutron").add_gateway_router( + router["router"]["id"], gw_info) + + @atomic.action_timer("neutron.remove_gateway_router") + def _remove_gateway_router(self, router): + """Removes an external network gateway from the specified router. + + :param router: dict, neutron router + """ + self.clients("neutron").remove_gateway_router( + router["router"]["id"]) + @atomic.optional_action_timer("neutron.create_pool") def _create_lb_pool(self, subnet_id, **pool_create_args): """Create LB pool(v1) diff --git a/samples/tasks/scenarios/neutron/set-and-clear-router-gateway.json b/samples/tasks/scenarios/neutron/set-and-clear-router-gateway.json new file mode 100644 index 00000000..5a0cbfb9 --- /dev/null +++ b/samples/tasks/scenarios/neutron/set-and-clear-router-gateway.json @@ -0,0 +1,36 @@ +{ + "NeutronNetworks.set_and_clear_router_gateway": [ + { + "args": { + "network_create_args": { + "router:external": true + }, + "router_create_args": {} + }, + "runner": { + "type": "constant", + "times": 4, + "concurrency": 2 + }, + "context": { + "network": {}, + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "quotas": { + "neutron": { + "network": -1, + "router": -1 + } + }, + "roles": ["admin"] + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/neutron/set-and-clear-router-gateway.yaml b/samples/tasks/scenarios/neutron/set-and-clear-router-gateway.yaml new file mode 100644 index 00000000..27af6873 --- /dev/null +++ b/samples/tasks/scenarios/neutron/set-and-clear-router-gateway.yaml @@ -0,0 +1,25 @@ +--- + NeutronNetworks.set_and_clear_router_gateway: + - + args: + network_create_args: + router:external: True + router_create_args: {} + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + network: {} + users: + tenants: 2 + users_per_tenant: 2 + quotas: + neutron: + network: -1 + router: -1 + roles: + - "admin" + 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 bc13bd55..ebf8ef3a 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_network.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_network.py @@ -183,6 +183,27 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): scenario._show_subnet.assert_called_with(subnet, atomic_action=False) + def test_set_and_clear_router_gateway(self): + network_create_args = {"router:external": True} + router_create_args = {"admin_state_up": True} + enable_snat = True + ext_net = mock.MagicMock() + router = mock.MagicMock() + scenario = network.SetAndClearRouterGateway(self.context) + scenario._create_network = mock.Mock(return_value=ext_net) + scenario._create_router = mock.Mock(return_value=router) + scenario._add_gateway_router = mock.Mock() + scenario._remove_gateway_router = mock.Mock() + + scenario.run(enable_snat, network_create_args, router_create_args) + + scenario._create_network.assert_called_once_with( + network_create_args) + scenario._create_router.assert_called_once_with(router_create_args) + scenario._add_gateway_router.assert_called_once_with(router, ext_net, + enable_snat) + scenario._remove_gateway_router.assert_called_once_with(router) + def test_create_and_update_subnets(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py index 4e3fd740..a7e4c831 100755 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py @@ -350,6 +350,41 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(self.scenario.atomic_actions(), "neutron.remove_interface_router") + def test_add_gateway_router(self): + ext_net = { + "network": { + "name": "extnet-name", + "id": "extnet-id" + } + } + router = { + "router": { + "name": "router-name", + "id": "router-id" + } + } + enable_snat = "fake_snat" + gw_info = {"network_id": ext_net["network"]["id"], + "enable_snat": enable_snat} + self.scenario._add_gateway_router(router, ext_net, enable_snat) + 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_remove_gateway_router(self): + router = { + "router": { + "name": "router-name", + "id": "router-id" + } + } + self.scenario._remove_gateway_router(router) + self.clients("neutron").remove_gateway_router.assert_called_once_with( + router["router"]["id"]) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.remove_gateway_router") + def test_SUBNET_IP_VERSION(self): """Curent NeutronScenario implementation supports only IPv4.""" self.assertEqual(utils.NeutronScenario.SUBNET_IP_VERSION, 4)