diff --git a/rally-jobs/rally-neutron-extensions.yaml b/rally-jobs/rally-neutron-extensions.yaml index e5b431cb..52111638 100644 --- a/rally-jobs/rally-neutron-extensions.yaml +++ b/rally-jobs/rally-neutron-extensions.yaml @@ -15,3 +15,19 @@ sla: failure_rate: max: 0 + + NeutronBGPVPN.create_and_delete_bgpvpns: + - + args: + bgpvpn_create_args: {} + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 3 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 \ No newline at end of file diff --git a/rally/plugins/openstack/scenarios/neutron/bgpvpn.py b/rally/plugins/openstack/scenarios/neutron/bgpvpn.py new file mode 100644 index 00000000..a57e8b1e --- /dev/null +++ b/rally/plugins/openstack/scenarios/neutron/bgpvpn.py @@ -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 import consts +from rally.plugins.openstack import scenario +from rally.plugins.openstack.scenarios.neutron import utils +from rally.task import validation + + +"""Scenarios for Neutron Networking-Bgpvpn.""" + + +@validation.restricted_parameters(["name"]) +@validation.required_neutron_extensions("bgpvpn") +@validation.required_services(consts.Service.NEUTRON) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"admin_cleanup": ["neutron"]}, + name="NeutronBGPVPN.create_and_delete_bgpvpns") +class CreateAndDeleteBgpvpns(utils.NeutronScenario): + + def run(self, bgpvpn_create_args=None): + """Create bgpvpn and delete the bgpvpn. + + Measure the "neutron bgpvpn-create" and bgpvpn-delete + command performance. + :param bgpvpn_create_args: dict, POST /v2.0/bgpvpn/bgpvpns request + options + """ + bgpvpn = self._create_bgpvpn(bgpvpn_create_args or {}) + self._delete_bgpvpn(bgpvpn) diff --git a/rally/plugins/openstack/scenarios/neutron/utils.py b/rally/plugins/openstack/scenarios/neutron/utils.py index cbe8bdda..5b305ef3 100755 --- a/rally/plugins/openstack/scenarios/neutron/utils.py +++ b/rally/plugins/openstack/scenarios/neutron/utils.py @@ -44,6 +44,9 @@ class NeutronScenario(scenario.OpenStackScenario): HM_MAX_RETRIES = 3 HM_DELAY = 20 HM_TIMEOUT = 10 + # BGPVPN + BGPVPNS_PATH = "/bgpvpn/bgpvpns" + BGPVPN_PATH = "/bgpvpn/bgpvpns/%s" def _get_network_id(self, network, **kwargs): """Get Neutron network ID for the network name. @@ -696,3 +699,25 @@ class NeutronScenario(scenario.OpenStackScenario): """ return self.clients("neutron").list_loadbalancers(retrieve_all, **lb_list_args) + + @atomic.action_timer("neutron.create_bgpvpn") + def _create_bgpvpn(self, bgpvpn_create_args): + """Create Bgpvpn resource (POST /bgpvpn/bgpvpn) + + param: bgpvpn_create_args: dict bgpvpn options + returns: dict, bgpvpn resource details + """ + if "name" not in bgpvpn_create_args: + bgpvpn_create_args["name"] = self.generate_random_name() + return self.admin_clients("neutron").create_ext( + self.BGPVPNS_PATH, {"bgpvpn": bgpvpn_create_args}) + + @atomic.action_timer("neutron.delete_bgpvpn") + def _delete_bgpvpn(self, bgpvpn): + """Delete Bgpvpn resource.(DELETE /bgpvpn/bgpvpns/{id}) + + param: bgpvpn: dict, bgpvpn + return: dict, bgpvpn + """ + return self.admin_clients("neutron").delete_ext( + self.BGPVPN_PATH, bgpvpn["bgpvpn"]["id"]) diff --git a/samples/tasks/scenarios/neutron/create-and-delete-bgpvpns.json b/samples/tasks/scenarios/neutron/create-and-delete-bgpvpns.json new file mode 100644 index 00000000..f0570af2 --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-delete-bgpvpns.json @@ -0,0 +1,23 @@ +{ + "NeutronBGPVPN.create_and_delete_bgpvpns": [ + { + "args":{}, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 1, + "users_per_tenant": 1 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} \ No newline at end of file diff --git a/samples/tasks/scenarios/neutron/create-and-delete-bgpvpns.yaml b/samples/tasks/scenarios/neutron/create-and-delete-bgpvpns.yaml new file mode 100644 index 00000000..174afe0f --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-delete-bgpvpns.yaml @@ -0,0 +1,15 @@ +--- + NeutronBGPVPN.create_and_delete_bgpvpns: + - + args: {} + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 1 + users_per_tenant: 1 + sla: + failure_rate: + max: 0 diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py b/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py new file mode 100644 index 00000000..f568f699 --- /dev/null +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_bgpvpn.py @@ -0,0 +1,42 @@ +# 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 ddt +import mock + +from rally.plugins.openstack.scenarios.neutron import bgpvpn +from tests.unit import test + + +@ddt.ddt +class NeutronBgpvpnTestCase(test.TestCase): + + def _get_context(self): + context = test.get_test_context() + return context + + @ddt.data( + {}, + {"bgpvpn_create_args": None}, + {"bgpvpn_create_args": {}}, + {"bgpvpn_create_args": {"name": "given-name"}}, + ) + @ddt.unpack + def test_create_and_delete_bgpvpns(self, bgpvpn_create_args=None): + scenario = bgpvpn.CreateAndDeleteBgpvpns(self._get_context()) + bgpvpn_create_data = bgpvpn_create_args or {} + scenario._create_bgpvpn = mock.Mock() + scenario._delete_bgpvpn = mock.Mock() + scenario.run(bgpvpn_create_args=bgpvpn_create_data) + scenario._create_bgpvpn.assert_called_once_with(bgpvpn_create_data) + scenario._delete_bgpvpn.assert_called_once_with( + scenario._create_bgpvpn.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 ef83b0ba..80870df6 100755 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py @@ -1017,6 +1017,37 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(self.scenario.atomic_actions(), "neutron.list_lbaasv2_loadbalancers") + @ddt.data( + {"bgpvpn_create_args": {}}, + {"bgpvpn_create_args": {"name": "given-name"}} + ) + @ddt.unpack + def test__create_bgpvpn(self, atomic_action=True, bgpvpn_create_args=None): + bgpvpn_create_args = bgpvpn_create_args or {} + bv = {"bgpvpn": {"id": "bgpvpn-id"}} + self.admin_clients("neutron").create_ext.return_value = bv + if bgpvpn_create_args.get("name") is None: + self.scenario.generate_random_name = mock.Mock( + return_value="random_name") + args = {"name": "random_name"} + args.update(bgpvpn_create_args) + expected_bv_data = {"bgpvpn": args} + resultant_bv = self.scenario._create_bgpvpn( + bgpvpn_create_args=bgpvpn_create_args) + self.assertEqual(bv, resultant_bv) + self.admin_clients("neutron").create_ext.assert_called_once_with( + self.scenario.BGPVPNS_PATH, expected_bv_data) + if atomic_action: + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.create_bgpvpn") + + def test_delete_bgpvpn(self): + bgpvpn_create_args = {} + bgpvpn = self.scenario._create_bgpvpn(bgpvpn_create_args) + self.scenario._delete_bgpvpn(bgpvpn) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.delete_bgpvpn") + class NeutronScenarioFunctionalTestCase(test.FakeClientsScenarioTestCase):