diff --git a/rally/plugins/openstack/scenarios/neutron/loadbalancer_v1.py b/rally/plugins/openstack/scenarios/neutron/loadbalancer_v1.py index cf62dfbd..ee1bbeaf 100644 --- a/rally/plugins/openstack/scenarios/neutron/loadbalancer_v1.py +++ b/rally/plugins/openstack/scenarios/neutron/loadbalancer_v1.py @@ -34,9 +34,8 @@ class NeutronLoadbalancerV1(utils.NeutronScenario): :param pool_create_args: dict, POST /lb/pools request options """ pool_create_args = pool_create_args or {} - for net in self.context.get("tenant", {}).get("networks", []): - for subnet_id in net["subnets"]: - self._create_v1_pool(subnet_id, **pool_create_args) + networks = self.context.get("tenant", {}).get("networks", []) + self._create_v1_pools(networks, **pool_create_args) self._list_v1_pools() @validation.restricted_parameters("subnet_id", @@ -54,12 +53,9 @@ class NeutronLoadbalancerV1(utils.NeutronScenario): :param pool_create_args: dict, POST /lb/pools request options """ - pools = [] pool_create_args = pool_create_args or {} - for net in self.context.get("tenant", {}).get("networks", []): - for subnet_id in net["subnets"]: - pools.append(self._create_v1_pool(subnet_id=subnet_id, - **pool_create_args)) + networks = self.context.get("tenant", {}).get("networks", []) + pools = self._create_v1_pools(networks, **pool_create_args) for pool in pools: self._delete_v1_pool(pool["pool"]) @@ -80,12 +76,9 @@ class NeutronLoadbalancerV1(utils.NeutronScenario): :param pool_create_args: dict, POST /lb/pools request options :param pool_update_args: dict, POST /lb/pools update options """ - pools = [] pool_create_args = pool_create_args or {} pool_update_args = pool_update_args or {} - for net in self.context.get("tenant", {}).get("networks", []): - for subnet_id in net["subnets"]: - pools.append(self._create_v1_pool(subnet_id, - **pool_create_args)) + networks = self.context.get("tenant", {}).get("networks", []) + pools = self._create_v1_pools(networks, **pool_create_args) for pool in pools: self._update_v1_pool(pool, **pool_update_args) diff --git a/rally/plugins/openstack/scenarios/neutron/utils.py b/rally/plugins/openstack/scenarios/neutron/utils.py index 8b1e7799..5aec697f 100644 --- a/rally/plugins/openstack/scenarios/neutron/utils.py +++ b/rally/plugins/openstack/scenarios/neutron/utils.py @@ -292,20 +292,43 @@ class NeutronScenario(scenario.OpenStackScenario): self.clients("neutron").remove_interface_router( router["id"], {"subnet_id": subnet["id"]}) - @base.atomic_action_timer("neutron.create_pool") - def _create_v1_pool(self, subnet_id, **pool_create_args): - """Create pool(v1) + def _create_lb_pool(self, subnet_id, atomic_action=True, + **pool_create_args): + """Create LB pool(v1) - :parm subnet_id: str, neutron subnet-id - :parm pool_create_args: dict, POST /lb/pools request options - :returns: obj, neutron lb pool + :param subnet_id: str, neutron subnet-id + :param pool_create_args: dict, POST /lb/pools request options + :param atomic_action: True if this is an atomic action + :returns: dict, neutron lb pool """ - args = {"lb_method": self.LB_METHOD, "protocol": self.LB_PROTOCOL, + args = {"lb_method": self.LB_METHOD, + "protocol": self.LB_PROTOCOL, "name": self._generate_random_name("rally_pool_"), "subnet_id": subnet_id} args.update(pool_create_args) + if atomic_action: + with base.AtomicAction(self, "neutron.create_pool"): + return self.clients("neutron").create_pool({"pool": args}) return self.clients("neutron").create_pool({"pool": args}) + def _create_v1_pools(self, networks, **pool_create_args): + """Create LB pools(v1) + + :param networks: list, neutron networks + :param pool_create_args: dict, POST /lb/pools request options + :returns: list, neutron lb pools + """ + subnets = [] + pools = [] + for net in networks: + subnets.extend(net.get("subnets", [])) + with base.AtomicAction(self, "neutron.create_%s_pools" % + len(subnets)): + for subnet_id in subnets: + pools.append(self._create_lb_pool( + subnet_id, atomic_action=False, **pool_create_args)) + return pools + @base.atomic_action_timer("neutron.list_pools") def _list_v1_pools(self, **kwargs): """Return user lb pool list(v1).""" diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_loadbalancer_v1.py b/tests/unit/plugins/openstack/scenarios/neutron/test_loadbalancer_v1.py index 30c10e85..48005ed1 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_loadbalancer_v1.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_loadbalancer_v1.py @@ -42,14 +42,13 @@ class NeutronLoadbalancerv1TestCase(test.TestCase): neutron_scenario = loadbalancer_v1.NeutronLoadbalancerV1( self._get_context()) pool_data = pool_create_args or {} - neutron_scenario._create_v1_pool = mock.Mock() + networks = self._get_context()["tenant"]["networks"] + neutron_scenario._create_v1_pools = mock.Mock() neutron_scenario._list_v1_pools = mock.Mock() neutron_scenario.create_and_list_pools( pool_create_args=pool_create_args) - for net in self._get_context()["tenant"]["networks"]: - for subnet_id in net["subnets"]: - neutron_scenario._create_v1_pool.assert_called_once_with( - subnet_id, **pool_data) + neutron_scenario._create_v1_pools.assert_called_once_with( + networks, **pool_data) neutron_scenario._list_v1_pools.assert_called_once_with() @ddt.data( @@ -62,22 +61,19 @@ class NeutronLoadbalancerv1TestCase(test.TestCase): def test_create_and_delete_pools(self, pool_create_args=None): neutron_scenario = loadbalancer_v1.NeutronLoadbalancerV1( self._get_context()) - pool = { + pools = [{ "pool": { "id": "pool-id" } - } + }] pool_data = pool_create_args or {} - neutron_scenario._create_v1_pool = mock.Mock(return_value=pool) + networks = self._get_context()["tenant"]["networks"] + neutron_scenario._create_v1_pools = mock.Mock(return_value=pools) neutron_scenario._delete_v1_pool = mock.Mock() neutron_scenario.create_and_delete_pools( pool_create_args=pool_create_args) - pools = [] - for net in self._get_context()["tenant"]["networks"]: - for subnet_id in net["subnets"]: - self.assertEqual([mock.call(subnet_id=subnet_id, - **pool_data)], - neutron_scenario._create_v1_pool.mock_calls) + self.assertEqual([mock.call(networks, **pool_data)], + neutron_scenario._create_v1_pools.mock_calls) for pool in pools: self.assertEqual(1, neutron_scenario._delete_v1_pool.call_count) @@ -102,11 +98,11 @@ class NeutronLoadbalancerv1TestCase(test.TestCase): pool_update_args=None): neutron_scenario = loadbalancer_v1.NeutronLoadbalancerV1( self._get_context()) - pool = { + pools = [{ "pool": { "id": "pool-id" } - } + }] updated_pool = { "pool": { "id": "pool-id", @@ -117,19 +113,15 @@ class NeutronLoadbalancerv1TestCase(test.TestCase): pool_data = pool_create_args or {} pool_update_args = pool_update_args or {} pool_update_args.update({"name": "_updated", "admin_state_up": True}) - neutron_scenario._create_v1_pool = mock.Mock(return_value=pool) + neutron_scenario._create_v1_pools = mock.Mock(return_value=pools) neutron_scenario._update_v1_pool = mock.Mock( return_value=updated_pool) + networks = self._get_context()["tenant"]["networks"] neutron_scenario.create_and_update_pools( pool_create_args=pool_data, pool_update_args=pool_update_args) - pools = [] - for net in self._get_context()["tenant"]["networks"]: - for subnet_id in net["subnets"]: - pools.append( - neutron_scenario._create_v1_pool.assert_called_once_with( - subnet_id, **pool_data)) + self.assertEqual([mock.call(networks, **pool_data)], + neutron_scenario._create_v1_pools.mock_calls) for pool in pools: neutron_scenario._update_v1_pool.assert_called_once_with( - neutron_scenario._create_v1_pool.return_value, - **pool_update_args) + pool, **pool_update_args) diff --git a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py index 96383656..ac9105e1 100644 --- a/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/neutron/test_utils.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import ddt import mock from rally.plugins.openstack.scenarios.neutron import utils @@ -430,46 +431,6 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): {"allocation_pools": []}, "10.10.10.0/24")] * subnets_per_network) - def test_create_v1_pool_explicit(self): - neutron_scenario = utils.NeutronScenario() - lb_method = "LEAST_CONNECTIONS" - subnet = "fake-id" - pool = mock.Mock() - self.clients("neutron").create_pool.return_value = pool - # Explicit options - pool_data = {"lb_method": lb_method, "name": "explicit-name"} - args = {"lb_method": "ROUND_ROBIN", "protocol": "HTTP", - "name": "random_name", "subnet_id": subnet} - args.update(pool_data) - expected_pool_data = {"pool": args} - pool = neutron_scenario._create_v1_pool( - subnet_id=subnet, **pool_data) - self.clients("neutron").create_pool.assert_called_once_with( - expected_pool_data) - self._test_atomic_action_timer( - neutron_scenario.atomic_actions(), "neutron.create_pool") - - @mock.patch(NEUTRON_UTILS + "NeutronScenario._generate_random_name") - def test_create_v1_pool_default(self, mock__generate_random_name): - neutron_scenario = utils.NeutronScenario() - random_name = "random_name" - subnet = "fake-id" - pool = mock.Mock() - self.clients("neutron").create_pool.return_value = pool - mock__generate_random_name.return_value = random_name - # Random pool name - pool_data = {} - args = {"lb_method": "ROUND_ROBIN", "protocol": "HTTP", - "name": "random_name", "subnet_id": subnet} - args.update(pool_data) - expected_pool_data = {"pool": args} - pool = neutron_scenario._create_v1_pool( - subnet_id=subnet, **pool_data) - self.clients("neutron").create_pool.assert_called_once_with( - expected_pool_data) - self._test_atomic_action_timer( - neutron_scenario.atomic_actions(), "neutron.create_pool") - def test_delete_v1_pool(self): scenario = utils.NeutronScenario() @@ -536,3 +497,75 @@ class NeutronScenarioFunctionalTestCase(test.FakeClientsScenarioTestCase): # This checks both data (cidrs seem to be enough) and subnets number result_cidrs = sorted([s["subnet"]["cidr"] for s in subnets]) self.assertEqual(cidrs, result_cidrs) + + +@ddt.ddt +class NeutronLoadbalancerScenarioTestCase(test.ScenarioTestCase): + + def setUp(self): + super(NeutronLoadbalancerScenarioTestCase, self).setUp() + self.network = mock.Mock() + + @ddt.data( + {"networks": [{"subnets": "subnet-id"}]}, + {"pool_create_args": None, "networks": [{"subnets": ["subnet-id"]}]}, + {"pool_create_args": {}, "networks": [{"subnets": ["subnet-id"]}]}, + {"pool_create_args": {"name": "given-name"}, + "networks": [{"subnets": ["subnet-id"]}]}, + ) + @ddt.unpack + def test__create_v1_pools(self, networks, pool_create_args=None): + neutron_scenario = utils.NeutronScenario() + pool_create_args = pool_create_args or {} + pool = {"pool": {"id": "pool-id"}} + neutron_scenario._create_lb_pool = mock.Mock(return_value=pool) + resultant_pools = neutron_scenario._create_v1_pools( + networks=networks, **pool_create_args) + if networks: + subnets = [] + [subnets.extend(net["subnets"]) for net in networks] + neutron_scenario._create_lb_pool.assert_has_calls( + [mock.call(subnet, atomic_action=False, + **pool_create_args) for subnet in subnets]) + self.assertEqual(resultant_pools, [pool] * len(subnets)) + self._test_atomic_action_timer( + neutron_scenario.atomic_actions(), + "neutron.create_%s_pools" % len(subnets)) + + @ddt.data( + {"subnet_id": "foo-id"}, + {"pool_create_args": None, "subnet_id": "foo-id"}, + {"pool_create_args": {}, "subnet_id": "foo-id"}, + {"pool_create_args": {"name": "given-name"}, + "subnet_id": "foo-id"}, + {"subnet_id": "foo-id", "atomic_action": False}, + {"pool_create_args": None, "subnet_id": "foo-id", + "atomic_action": False}, + {"pool_create_args": {}, "subnet_id": "foo-id", + "atomic_action": False}, + {"pool_create_args": {"name": "given-name"}, + "subnet_id": "foo-id", "atomic_action": False}, + ) + @ddt.unpack + def test__create_lb_pool(self, subnet_id=None, atomic_action=True, + pool_create_args=None): + neutron_scenario = utils.NeutronScenario() + pool = {"pool": {"id": "pool-id"}} + pool_create_args = pool_create_args or {} + if pool_create_args.get("name") is None: + neutron_scenario._generate_random_name = mock.Mock( + return_value="random_name") + self.clients("neutron").create_pool.return_value = pool + args = {"lb_method": "ROUND_ROBIN", "protocol": "HTTP", + "name": "random_name", "subnet_id": subnet_id} + args.update(pool_create_args) + expected_pool_data = {"pool": args} + resultant_pool = neutron_scenario._create_lb_pool( + subnet_id=subnet_id, atomic_action=atomic_action, + **pool_create_args) + self.assertEqual(resultant_pool, pool) + self.clients("neutron").create_pool.assert_called_once_with( + expected_pool_data) + if atomic_action: + self._test_atomic_action_timer( + neutron_scenario.atomic_actions(), "neutron.create_pool")