diff --git a/rally-jobs/rally-neutron-extensions.yaml b/rally-jobs/rally-neutron-extensions.yaml index 63a4435a..5651f5cf 100644 --- a/rally-jobs/rally-neutron-extensions.yaml +++ b/rally-jobs/rally-neutron-extensions.yaml @@ -56,4 +56,32 @@ users_per_tenant: 2 sla: failure_rate: - max: 0 \ No newline at end of file + max: 0 + + NeutronBGPVPN.create_bgpvpn_assoc_disassoc_networks: + - + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 3 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + + NeutronBGPVPN.create_bgpvpn_assoc_disassoc_routers: + - + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 3 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 diff --git a/rally/plugins/openstack/scenarios/neutron/bgpvpn.py b/rally/plugins/openstack/scenarios/neutron/bgpvpn.py index bcaf3be7..b7a5a757 100644 --- a/rally/plugins/openstack/scenarios/neutron/bgpvpn.py +++ b/rally/plugins/openstack/scenarios/neutron/bgpvpn.py @@ -18,6 +18,8 @@ from rally.task import validation """Scenarios for Neutron Networking-Bgpvpn.""" +@validation.add("enum", param_name="bgpvpn_type", values=["l2", "l3"], + missed=True) @validation.add("required_neutron_extensions", extensions=["bgpvpn"]) @validation.add("required_platform", platform="openstack", admin=True) @validation.add("required_services", @@ -27,7 +29,7 @@ from rally.task import validation class CreateAndDeleteBgpvpns(utils.NeutronScenario): def run(self, route_targets=None, import_targets=None, - export_targets=None, route_distinguishers=None, type="l3"): + export_targets=None, route_distinguishers=None, bgpvpn_type="l3"): """Create bgpvpn and delete the bgpvpn. Measure the "neutron bgpvpn-create" and neutron bgpvpn-delete @@ -39,17 +41,19 @@ class CreateAndDeleteBgpvpns(utils.NeutronScenario): :param export_targets: Additional Route Targets that will be used for export. :param route_distinguishers: List of route distinguisher strings - :param type: type of VPN and the technology behind it. + :param bgpvpn_type: type of VPN and the technology behind it. Acceptable formats: l2 and l3 """ bgpvpn = self._create_bgpvpn(route_targets=route_targets, import_targets=import_targets, export_targets=export_targets, route_distinguishers=route_distinguishers, - type=type) + type=bgpvpn_type) self._delete_bgpvpn(bgpvpn) +@validation.add("enum", param_name="bgpvpn_type", values=["l2", "l3"], + missed=True) @validation.add("required_neutron_extensions", extensions=["bgpvpn"]) @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", admin=True) @@ -58,7 +62,7 @@ class CreateAndDeleteBgpvpns(utils.NeutronScenario): class CreateAndListBgpvpns(utils.NeutronScenario): def run(self, route_targets=None, import_targets=None, - export_targets=None, route_distinguishers=None, type="l3"): + export_targets=None, route_distinguishers=None, bgpvpn_type="l3"): """Create a bgpvpn and then list all bgpvpns Measure the "neutron bgpvpn-list" command performance. @@ -69,18 +73,20 @@ class CreateAndListBgpvpns(utils.NeutronScenario): :param export_targets: Additional Route Targets that will be used for export. :param route_distinguishers: List of route distinguisher strings - :param type: type of VPN and the technology behind it. + :param bgpvpn_type: type of VPN and the technology behind it. Acceptable formats: l2 and l3 """ bgpvpn = self._create_bgpvpn(route_targets=route_targets, import_targets=import_targets, export_targets=export_targets, route_distinguishers=route_distinguishers, - type=type) + type=bgpvpn_type) bgpvpns = self._list_bgpvpns() self.assertIn(bgpvpn["bgpvpn"]["id"], [b["id"] for b in bgpvpns]) +@validation.add("enum", param_name="bgpvpn_type", values=["l2", "l3"], + missed=True) @validation.add("required_neutron_extensions", extensions=["bgpvpn"]) @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", admin=True) @@ -131,3 +137,89 @@ class CreateAndUpdateBgpvpns(utils.NeutronScenario): "route_distinguishers": updated_route_distinguishers, } self._update_bgpvpn(bgpvpn, **update_bgpvpn_args) + + +@validation.add("enum", param_name="bgpvpn_type", values=["l2", "l3"], + missed=True) +@validation.add("required_neutron_extensions", extensions=["bgpvpn"]) +@validation.add("required_services", services=[consts.Service.NEUTRON]) +@validation.add("required_platform", platform="openstack", + admin=True, users=True) +@scenario.configure(context={"admin_cleanup": ["neutron"]}, + name="NeutronBGPVPN.create_bgpvpn_assoc_disassoc_networks") +class CreateAndAssociateDissassociateNetworks(utils.NeutronScenario): + + def run(self, route_targets=None, import_targets=None, + export_targets=None, route_distinguishers=None, bgpvpn_type="l3"): + """Associate a network and disassociate it from a BGP VPN. + + Measure the "neutron bgpvpn-create", "neutron bgpvpn-net-assoc-create" + and "neutron bgpvpn-net-assoc-delete" command performance. + + :param route_targets: Route Targets that will be both imported and + used for export + :param import_targets: Additional Route Targets that will be imported + :param export_targets: Additional Route Targets that will be used + for export. + :param route_distinguishers: List of route distinguisher strings + :param bgpvpn_type: type of VPN and the technology behind it. + Acceptable formats: l2 and l3 + """ + + networks = self._list_networks( + tenant_id=self.context["user"]["tenant_id"]) + if not networks: + network = self._create_network({}) + else: + network = {"network": networks[0]} + bgpvpn = self._create_bgpvpn(route_targets=route_targets, + import_targets=import_targets, + export_targets=export_targets, + route_distinguishers=route_distinguishers, + type=bgpvpn_type, + tenant_id=network["network"]["tenant_id"]) + net_asso = self._create_bgpvpn_network_assoc(bgpvpn, network) + self._delete_bgpvpn_network_assoc(bgpvpn, net_asso) + + +@validation.add("enum", param_name="bgpvpn_type", values=["l2", "l3"], + missed=True) +@validation.add("required_neutron_extensions", extensions=["bgpvpn"]) +@validation.add("required_services", services=[consts.Service.NEUTRON]) +@validation.add("required_platform", platform="openstack", + admin=True, users=True) +@scenario.configure(context={"admin_cleanup": ["neutron"]}, + name="NeutronBGPVPN.create_bgpvpn_assoc_disassoc_routers") +class CreateAndAssociateDissassociateRouters(utils.NeutronScenario): + + def run(self, route_targets=None, import_targets=None, + export_targets=None, route_distinguishers=None, bgpvpn_type="l3"): + """Associate a router and disassociate it from a BGP VPN. + + Measure the "neutron bgpvpn-create", + "neutron bgpvpn-router-assoc-create" and + "neutron bgpvpn-router-assoc-delete" command performance. + + :param route_targets: Route Targets that will be both imported and + used for export + :param import_targets: Additional Route Targets that will be imported + :param export_targets: Additional Route Targets that will be used + for export. + :param route_distinguishers: List of route distinguisher strings + :param bgpvpn_type: type of VPN and the technology behind it. + Acceptable formats: l2 and l3 + """ + + routers = self._list_routers() + if not routers: + router = self._create_router({}) + else: + router = {"router": routers[0]} + bgpvpn = self._create_bgpvpn(route_targets=route_targets, + import_targets=import_targets, + export_targets=export_targets, + route_distinguishers=route_distinguishers, + type=bgpvpn_type, + tenant_id=router["router"]["tenant_id"]) + router_asso = self._create_bgpvpn_router_assoc(bgpvpn, router) + self._delete_bgpvpn_router_assoc(bgpvpn, router_asso) diff --git a/rally/plugins/openstack/scenarios/neutron/utils.py b/rally/plugins/openstack/scenarios/neutron/utils.py index 799177ee..a3d8d260 100755 --- a/rally/plugins/openstack/scenarios/neutron/utils.py +++ b/rally/plugins/openstack/scenarios/neutron/utils.py @@ -752,3 +752,49 @@ class NeutronScenario(scenario.OpenStackScenario): kwargs["name"] = self.generate_random_name() return self.admin_clients("neutron").update_bgpvpn( bgpvpn["bgpvpn"]["id"], {"bgpvpn": kwargs}) + + @atomic.action_timer("neutron.create_bgpvpn_network_assoc") + def _create_bgpvpn_network_assoc(self, bgpvpn, network): + """Creates a new BGP VPN network association. + + :param bgpvpn: dict, bgpvpn + :param network: dict, network + :return dict: network_association + """ + netassoc = {"network_id": network["network"]["id"]} + return self.clients("neutron").create_bgpvpn_network_assoc( + bgpvpn["bgpvpn"]["id"], {"network_association": netassoc}) + + @atomic.action_timer("neutron.delete_bgpvpn_network_assoc") + def _delete_bgpvpn_network_assoc(self, bgpvpn, net_assoc): + """Delete the specified BGP VPN network association + + :param bgpvpn: dict, bgpvpn + :param net_assoc: dict, network + :return dict: network_association + """ + return self.clients("neutron").delete_bgpvpn_network_assoc( + bgpvpn["bgpvpn"]["id"], net_assoc["network_association"]["id"]) + + @atomic.action_timer("neutron.create_bgpvpn_router_assoc") + def _create_bgpvpn_router_assoc(self, bgpvpn, router): + """Creates a new BGP VPN router association. + + :param bgpvpn: dict, bgpvpn + :param router: dict, router + :return dict: network_association + """ + router_assoc = {"router_id": router["router"]["id"]} + return self.clients("neutron").create_bgpvpn_router_assoc( + bgpvpn["bgpvpn"]["id"], {"router_association": router_assoc}) + + @atomic.action_timer("neutron.delete_bgpvpn_router_assoc") + def _delete_bgpvpn_router_assoc(self, bgpvpn, router_assoc): + """Delete the specified BGP VPN router association + + :param bgpvpn: dict, bgpvpn + :param router_assoc: dict, router + :return dict: router_association + """ + return self.clients("neutron").delete_bgpvpn_router_assoc( + bgpvpn["bgpvpn"]["id"], router_assoc["router_association"]["id"]) diff --git a/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-networks-bgpvpns.json b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-networks-bgpvpns.json new file mode 100644 index 00000000..0b0a6171 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-networks-bgpvpns.json @@ -0,0 +1,28 @@ +{ + "NeutronBGPVPN.create_bgpvpn_assoc_disassoc_networks": [ + { + "args":{}, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 1, + "users_per_tenant": 1 + }, + "quotas": { + "neutron": { + "network": -1 + } + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} \ No newline at end of file diff --git a/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-networks-bgpvpns.yaml b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-networks-bgpvpns.yaml new file mode 100644 index 00000000..2c9ea005 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-networks-bgpvpns.yaml @@ -0,0 +1,18 @@ +--- + NeutronBGPVPN.create_bgpvpn_assoc_disassoc_networks: + - + args: {} + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 1 + users_per_tenant: 1 + quotas: + neutron: + network: -1 + sla: + failure_rate: + max: 0 \ No newline at end of file diff --git a/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-routers-bgpvpns.json b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-routers-bgpvpns.json new file mode 100644 index 00000000..74ef90b6 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-routers-bgpvpns.json @@ -0,0 +1,28 @@ +{ + "NeutronBGPVPN.create_bgpvpn_assoc_disassoc_routers": [ + { + "args":{}, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 1, + "users_per_tenant": 1 + }, + "quotas": { + "neutron": { + "router": -1 + } + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} \ No newline at end of file diff --git a/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-routers-bgpvpns.yaml b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-routers-bgpvpns.yaml new file mode 100644 index 00000000..5d5c61f1 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-assoc-disassoc-routers-bgpvpns.yaml @@ -0,0 +1,18 @@ +--- + NeutronBGPVPN.create_bgpvpn_assoc_disassoc_routers: + - + args: {} + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 1 + users_per_tenant: 1 + quotas: + neutron: + router: -1 + sla: + failure_rate: + max: 0 \ No newline at end of file diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py b/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py index 594d892f..525820a9 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py @@ -106,3 +106,74 @@ class NeutronBgpvpnTestCase(test.TestCase): type="l3", **create_data) scenario._update_bgpvpn.assert_called_once_with( scenario._create_bgpvpn.return_value, **update_data) + + @ddt.data( + {"list_networks": []}, + {"list_networks": [{"tenant_id": "tenant_id", "id": "network_id"}]}, + ) + @ddt.unpack + def test_create_and_associate_disassociate_networks(self, + list_networks=None): + scenario = bgpvpn.CreateAndAssociateDissassociateNetworks( + self._get_context()) + create_data = self._get_bgpvpn_create_data() + create_data["tenant_id"] = "tenant_id" + network = {"network": {"tenant_id": "tenant_id", + "id": "network_id"}} + scenario.context = {"user": {"tenant_id": "tenant_id"}} + scenario._list_networks = mock.Mock(return_value=list_networks) + if not list_networks: + scenario._create_network = mock.Mock(return_value=network) + scenario._create_bgpvpn = mock.Mock() + scenario._create_bgpvpn_network_assoc = mock.Mock() + scenario._delete_bgpvpn_network_assoc = mock.Mock() + scenario.run() + scenario._create_bgpvpn.assert_called_once_with( + type="l3", **create_data) + if list_networks: + given_network = {"network": {"tenant_id": "tenant_id", + "id": "network_id"}} + else: + scenario._create_network.assert_called_once_with({}) + given_network = scenario._create_network.return_value + + scenario._create_bgpvpn_network_assoc.assert_called_once_with( + scenario._create_bgpvpn.return_value, given_network) + scenario._delete_bgpvpn_network_assoc.assert_called_once_with( + scenario._create_bgpvpn.return_value, + scenario._create_bgpvpn_network_assoc.return_value) + + @ddt.data( + {"list_routers": []}, + {"list_routers": [{"tenant_id": "tenant_id", "id": "router_id"}]}, + ) + @ddt.unpack + def test_create_and_associate_disassociate_routers(self, + list_routers=None): + scenario = bgpvpn.CreateAndAssociateDissassociateRouters( + self._get_context()) + create_data = self._get_bgpvpn_create_data() + create_data["tenant_id"] = "tenant_id" + router = {"router": {"tenant_id": "tenant_id", + "id": "router_id"}} + scenario._list_routers = mock.Mock(return_value=list_routers) + if not list_routers: + scenario._create_router = mock.Mock(return_value=router) + scenario._create_bgpvpn = mock.Mock() + scenario._create_bgpvpn_router_assoc = mock.Mock() + scenario._delete_bgpvpn_router_assoc = mock.Mock() + scenario.run() + scenario._create_bgpvpn.assert_called_once_with( + type="l3", **create_data) + if list_routers: + given_router = {"router": {"tenant_id": "tenant_id", + "id": "router_id"}} + else: + scenario._create_router.assert_called_once_with({}) + given_router = scenario._create_router.return_value + + scenario._create_bgpvpn_router_assoc.assert_called_once_with( + scenario._create_bgpvpn.return_value, given_router) + scenario._delete_bgpvpn_router_assoc.assert_called_once_with( + scenario._create_bgpvpn.return_value, + scenario._create_bgpvpn_router_assoc.return_value) diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py index 595c1f71..70434968 100755 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py @@ -1086,6 +1086,45 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(self.scenario.atomic_actions(), "neutron.update_bgpvpn") + def test__create_bgpvpn_network_assoc(self): + network_id = "network_id" + bgpvpn_id = "bgpvpn_id" + value = {"network_association": { + "network_id": network_id, + "id": bgpvpn_id}} + self.clients( + "neutron").create_bgpvpn_network_assoc.return_value = value + network = {"network": {"id": network_id}} + bgpvpn = {"bgpvpn": {"id": bgpvpn_id}} + return_value = self.scenario._create_bgpvpn_network_assoc(bgpvpn, + network) + netassoc = {"network_id": network["network"]["id"]} + self.clients( + "neutron").create_bgpvpn_network_assoc.assert_called_once_with( + bgpvpn_id, {"network_association": netassoc}) + self.assertEqual(return_value, value) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.create_bgpvpn_network_assoc") + + def test__create_router_network_assoc(self): + router_id = "router_id" + bgpvpn_id = "bgpvpn_id" + value = {"router_association": { + "router_id": router_id, + "id": "asso_id"}} + self.clients("neutron").create_bgpvpn_router_assoc.return_value = value + router = {"router": {"id": router_id}} + bgpvpn = {"bgpvpn": {"id": bgpvpn_id}} + return_value = self.scenario._create_bgpvpn_router_assoc(bgpvpn, + router) + router_assoc = {"router_id": router["router"]["id"]} + self.clients( + "neutron").create_bgpvpn_router_assoc.assert_called_once_with( + bgpvpn_id, {"router_association": router_assoc}) + self.assertEqual(return_value, value) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.create_bgpvpn_router_assoc") + class NeutronScenarioFunctionalTestCase(test.FakeClientsScenarioTestCase):