diff --git a/rally-jobs/rally-neutron.yaml b/rally-jobs/rally-neutron.yaml index ea35ded5..60309ce8 100644 --- a/rally-jobs/rally-neutron.yaml +++ b/rally-jobs/rally-neutron.yaml @@ -211,6 +211,26 @@ failure_rate: max: 20 + NeutronSecurityGroup.create_and_list_security_group_rules: + - + args: + security_group_args: {} + security_group_rule_args: {} + runner: + type: "constant" + times: {{smoke or 20 }} + concurrency: {{smoke or 10}} + context: + users: + tenants: {{smoke or 3}} + users_per_tenant: {{smoke or 2}} + quotas: + neutron: + security_group: -1 + sla: + failure_rate: + max: 20 + NeutronNetworks.create_and_list_floating_ips: - args: diff --git a/rally/plugins/openstack/scenarios/neutron/security_groups.py b/rally/plugins/openstack/scenarios/neutron/security_groups.py index 29dbd2cb..a51d5840 100644 --- a/rally/plugins/openstack/scenarios/neutron/security_groups.py +++ b/rally/plugins/openstack/scenarios/neutron/security_groups.py @@ -116,3 +116,40 @@ class CreateAndUpdateSecurityGroups(utils.NeutronScenario): **security_group_create_args) self._update_security_group(security_group, **security_group_update_args) + + +@validation.required_services(consts.Service.NEUTRON) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"cleanup": ["neutron"]}, + name=("NeutronSecurityGroup" + ".create_and_list_security_group_rules")) +class CreateAndListSecurityGroupRules(utils.NeutronScenario): + + def run(self, security_group_args=None, + security_group_rule_args=None): + """Create and list Neutron security-group-rules. + + Measure the "neutron security-group-rule-create" and "neutron + security-group-rule-list" command performance. + + :param security_group_args: dict, POST /v2.0/security-groups + request options + :param security_group_rule_args: dict, + POST /v2.0/security-group-rules request options + """ + security_group_args = security_group_args or {} + security_group_rule_args = security_group_rule_args or {} + + security_group = self._create_security_group(**security_group_args) + msg = "security_group isn't created" + self.assertTrue(security_group, err_msg=msg) + + security_group_rule = self._create_security_group_rule( + security_group["security_group"]["id"], **security_group_rule_args) + msg = "security_group_rule isn't created" + self.assertTrue(security_group_rule, err_msg=msg) + + security_group_rules = self._list_security_group_rules() + self.assertIn(security_group_rule["security_group_rule"]["id"], + [sgr["id"] for sgr + in security_group_rules["security_group_rules"]]) diff --git a/rally/plugins/openstack/scenarios/neutron/utils.py b/rally/plugins/openstack/scenarios/neutron/utils.py index a4a1c29f..e9d8ccd0 100644 --- a/rally/plugins/openstack/scenarios/neutron/utils.py +++ b/rally/plugins/openstack/scenarios/neutron/utils.py @@ -784,3 +784,29 @@ class NeutronScenario(scenario.OpenStackScenario): """ return self.clients("neutron").delete_bgpvpn_router_assoc( bgpvpn["bgpvpn"]["id"], router_assoc["router_association"]["id"]) + + @atomic.action_timer("neutron.create_security_group_rule") + def _create_security_group_rule(self, security_group_id, + **security_group_rule_args): + """Create Neutron security-group-rule. + + param: security_group_id: id of neutron security_group + param: security_group_rule_args: dict, POST + /v2.0/security-group-rules request options + return: dict, neutron security-group-rule + """ + security_group_rule_args["security_group_id"] = security_group_id + if "direction" not in security_group_rule_args: + security_group_rule_args["direction"] = "ingress" + + return self.clients("neutron").create_security_group_rule( + {"security_group_rule": security_group_rule_args}) + + @atomic.action_timer("neutron.list_security_group_rules") + def _list_security_group_rules(self, **kwargs): + """List all security group rules. + + :param kwargs: Optional additional arguments for roles list + :return: list of security group rules + """ + return self.clients("neutron").list_security_group_rules(**kwargs) diff --git a/samples/tasks/scenarios/neutron/create-and-list-security-group-rules.json b/samples/tasks/scenarios/neutron/create-and-list-security-group-rules.json new file mode 100644 index 00000000..a7b0a7cd --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-list-security-group-rules.json @@ -0,0 +1,31 @@ +{ + "NeutronSecurityGroup.create_and_list_security_group_rules": [ + { + "args": { + "security_group_args": {}, + "security_group_rule_args":{} + }, + "runner": { + "type": "constant", + "times": 20, + "concurrency": 10 + }, + "context": { + "users": { + "tenants": 3, + "users_per_tenant": 3 + }, + "quotas": { + "neutron": { + "security_group": -1 + } + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/neutron/create-and-list-security-group-rules.yaml b/samples/tasks/scenarios/neutron/create-and-list-security-group-rules.yaml new file mode 100644 index 00000000..f39e46ae --- /dev/null +++ b/samples/tasks/scenarios/neutron/create-and-list-security-group-rules.yaml @@ -0,0 +1,20 @@ +--- + NeutronSecurityGroup.create_and_list_security_group_rules: + - + args: + security_group_args: {} + security_group_rule_args: {} + runner: + type: "constant" + times: 20 + concurrency: 10 + context: + users: + tenants: 3 + users_per_tenant: 3 + quotas: + neutron: + security_group: -1 + sla: + failure_rate: + max: 0 diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_security_groups.py b/tests/unit/plugins/openstack/scenarios/neutron/test_security_groups.py index 2f56e3e7..9e7a6012 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_security_groups.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_security_groups.py @@ -122,3 +122,106 @@ class NeutronSecurityGroup(test.TestCase): scenario._update_security_group.assert_called_once_with( scenario._create_security_group.return_value, **security_group_update_data) + + @ddt.data( + {}, + {"security_group_args": {}}, + {"security_group_args": {"description": "fake-description"}}, + {"security_group_rule_args": {}}, + {"security_group_rule_args": {"description": "fake-rule-descr"}}, + ) + @ddt.unpack + def test_create_and_list_security_group_rules( + self, security_group_args=None, + security_group_rule_args=None): + scenario = security_groups.CreateAndListSecurityGroupRules() + + security_group_data = security_group_args or {} + security_group_rule_data = security_group_rule_args or {} + + security_group = mock.MagicMock() + security_group_rule = {"security_group_rule": {"id": 1, "name": "f1"}} + scenario._create_security_group = mock.MagicMock() + scenario._create_security_group_rule = mock.MagicMock() + scenario._list_security_group_rules = mock.MagicMock() + + # Positive case + scenario._create_security_group.return_value = security_group + scenario._create_security_group_rule.return_value = security_group_rule + scenario._list_security_group_rules.return_value = { + "security_group_rules": [{"id": 1, "name": "f1"}, + {"id": 2, "name": "f2"}, + {"id": 3, "name": "f3"}]} + scenario.run(security_group_args=security_group_data, + security_group_rule_args=security_group_rule_data) + + scenario._create_security_group.assert_called_once_with( + **security_group_data) + scenario._create_security_group_rule.assert_called_once_with( + security_group["security_group"]["id"], + **security_group_rule_data) + scenario._list_security_group_rules.assert_called_once_with() + + @ddt.data( + {}, + {"security_group_args": {}}, + {"security_group_args": {"description": "fake-description"}}, + {"security_group_rule_args": {}}, + {"security_group_rule_args": {"description": "fake-rule-descr"}}, + ) + @ddt.unpack + def test_create_and_list_security_group_rules_with_fails( + self, security_group_args=None, + security_group_rule_args=None): + scenario = security_groups.CreateAndListSecurityGroupRules() + + security_group_data = security_group_args or {} + security_group_rule_data = security_group_rule_args or {} + + security_group = mock.MagicMock() + security_group_rule = {"security_group_rule": {"id": 1, "name": "f1"}} + scenario._create_security_group = mock.MagicMock() + scenario._create_security_group_rule = mock.MagicMock() + scenario._list_security_group_rules = mock.MagicMock() + scenario._create_security_group_rule.return_value = security_group_rule + scenario._list_security_group_rules.return_value = { + "security_group_rules": [{"id": 1, "name": "f1"}, + {"id": 2, "name": "f2"}, + {"id": 3, "name": "f3"}]} + + # Negative case1: security_group isn't created + scenario._create_security_group.return_value = None + self.assertRaises(rally_exceptions.RallyAssertionError, + scenario.run, + security_group_data, + security_group_rule_data) + scenario._create_security_group.assert_called_with( + **security_group_data) + + # Negative case2: security_group_rule isn't created + scenario._create_security_group.return_value = security_group + scenario._create_security_group_rule.return_value = None + self.assertRaises(rally_exceptions.RallyAssertionError, + scenario.run, + security_group_data, + security_group_rule_data) + scenario._create_security_group.assert_called_with( + **security_group_data) + scenario._create_security_group_rule.assert_called_with( + security_group["security_group"]["id"], + **security_group_rule_data) + + # Negative case3: security_group_rule isn't listed + scenario._create_security_group.return_value = security_group + scenario._create_security_group_rule.return_value = mock.MagicMock() + self.assertRaises(rally_exceptions.RallyAssertionError, + scenario.run, + security_group_data, + security_group_rule_data) + + scenario._create_security_group.assert_called_with( + **security_group_data) + scenario._create_security_group_rule.assert_called_with( + security_group["security_group"]["id"], + **security_group_rule_data) + scenario._list_security_group_rules.assert_called_with() diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py index decdd0df..94dd6423 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py @@ -788,6 +788,48 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(self.scenario.atomic_actions(), "neutron.update_security_group") + def test_create_security_group_rule(self): + security_group_rule_args = {"description": "Fake Rule"} + expected_security_group_rule = { + "security_group_rule": { + "id": "fake-id", + "security_group_id": "security-group-id", + "direction": "ingress", + "description": "Fake Rule" + } + } + client = self.clients("neutron") + client.create_security_group_rule = mock.Mock( + return_value=expected_security_group_rule) + + security_group_rule_data = { + "security_group_rule": + {"security_group_id": "security-group-id", + "direction": "ingress", + "description": "Fake Rule"} + } + result_security_group_rule = self.scenario._create_security_group_rule( + "security-group-id", **security_group_rule_args) + self.assertEqual(expected_security_group_rule, + result_security_group_rule) + client.create_security_group_rule.assert_called_once_with( + security_group_rule_data) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.create_security_group_rule") + + def test_list_security_group_rules(self): + security_group_rules_list = [{"id": "security-group-rule-id"}] + security_group_rules_dict = { + "security_group_rules": security_group_rules_list} + + self.clients("neutron").list_security_group_rules = mock.Mock( + return_value=security_group_rules_dict) + self.assertEqual( + self.scenario._list_security_group_rules(), + self.clients("neutron").list_security_group_rules.return_value) + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "neutron.list_security_group_rules") + @ddt.data( {"networks": [{"subnets": "subnet-id"}]}, {"pool_create_args": None, "networks": [{"subnets": ["subnet-id"]}]},