From 4f476e6ee3ef06578dfd8cfeeb2cbab5264a1e6e Mon Sep 17 00:00:00 2001 From: anbu Date: Fri, 14 Nov 2014 03:54:30 +0000 Subject: [PATCH] Optimization fix in {resource}_count plugin_db APIs When there are no filters or just tenant-id filter for {resource}_count, it is better to get the count of the resources directly from the vnc library instead of calculating the len() return values of {resource}_list call. Fixes bug: #1391801 Change-Id: I5d80a5e1df5f752b41cb1adcc7e8e989fcf83548 --- .../vnc_openstack/neutron_plugin_db.py | 49 +++++++++++++ .../vnc_openstack/tests/test_vnc_plugin_db.py | 73 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/config/vnc_openstack/vnc_openstack/tests/test_vnc_plugin_db.py diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index 14bab332b01..008f3a10f8a 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -2710,7 +2710,35 @@ def _collect_without_prune(net_ids): return ret_list #end network_list + def _resource_count_optimized(self, resource, filters=None): + if filters and ('tenant_id' not in filters or len(filters.keys()) > 1): + return None + + project_ids = filters.get('tenant_id') if filters else None + if not isinstance(project_ids, list): + project_ids = [project_ids] + + json_resource = resource.replace("_", "-") + if resource == "floating_ips": + count = lambda pid: self._vnc_lib. \ + floating_ips_list(back_ref_id=pid, + count=True)[json_resource]['count'] + else: + method = getattr(self._vnc_lib, resource + "_list") + count = lambda pid: method(parent_id=pid, + count=True)[json_resource]['count'] + + ret = [count(pid) for pid in project_ids] if project_ids \ + else [count(None)] + return sum(ret) + + # end _resource_count_optimized + def network_count(self, filters=None): + count = self._resource_count_optimized("virtual_networks", filters) + if count is not None: + return count + nets_info = self.network_list(filters=filters) return len(nets_info) #end network_count @@ -3069,6 +3097,10 @@ def ipam_list(self, context=None, filters=None): #end ipam_list def ipam_count(self, filters=None): + count = self._resource_count_optimized("network_ipams", filters) + if count is not None: + return count + ipam_info = self.ipam_list(filters=filters) return len(ipam_info) #end ipam_count @@ -3143,6 +3175,10 @@ def policy_list(self, context=None, filters=None): #end policy_list def policy_count(self, filters=None): + count = self._resource_count_optimized("network_policys", filters) + if count is not None: + return count + policy_info = self.policy_list(filters=filters) return len(policy_info) #end policy_count @@ -3471,6 +3507,10 @@ def router_list(self, context=None, filters=None): #end router_list def router_count(self, filters=None): + count = self._resource_count_optimized("logical_routers", filters) + if count is not None: + return count + rtrs_info = self.router_list(filters=filters) return len(rtrs_info) #end router_count @@ -3694,6 +3734,10 @@ def floatingip_list(self, context, filters=None): #end floatingip_list def floatingip_count(self, context, filters=None): + count = self._resource_count_optimized("floating_ips", filters) + if count is not None: + return count + floatingip_info = self.floatingip_list(context, filters) return len(floatingip_info) #end floatingip_count @@ -3992,6 +4036,11 @@ def port_list(self, context=None, filters=None): #end port_list def port_count(self, filters=None): + count = self._resource_count_optimized("virtual_machine_interfaces", + filters) + if count is not None: + return count + if (filters.get('device_owner') == 'network:dhcp' or 'network:dhcp' in filters.get('device_owner', [])): return 0 diff --git a/src/config/vnc_openstack/vnc_openstack/tests/test_vnc_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/tests/test_vnc_plugin_db.py new file mode 100644 index 00000000000..796056dcf2d --- /dev/null +++ b/src/config/vnc_openstack/vnc_openstack/tests/test_vnc_plugin_db.py @@ -0,0 +1,73 @@ +import unittest +from flexmock import flexmock + +from vnc_openstack import neutron_plugin_db as db + +class MockDbInterface(db.DBInterface): + def __init__(self): + pass + +class TestDbInterface(unittest.TestCase): + _tenant_ids = ['tenant_id_1', + 'tenant_id_2'] + + def _list_resource(self, resource, ret_count=0): + def _list_others(parent_id, count): + self.assertEqual(count, True) + self.assertTrue(parent_id in self._tenant_ids) + self.assertTrue(resource in ['virtual_networks', + 'virtual_machine_interfaces', + 'logical_routers', + 'network_policys', + 'network_ipams', + 'route_tables']) + r = resource.replace("_", "-") + return {r: {'count': ret_count}} + + def _list_fip(back_ref_id, count): + self.assertEqual(count, True) + self.assertTrue(back_ref_id in self._tenant_ids) + + r = resource.replace("_", "-") + return {r: {'count': ret_count}} + + if resource == "floating_ips": + return _list_fip + + return _list_others + + def _test_for(self, resource): + dbi = MockDbInterface() + + kwargs={"operational": True, + resource + "_list": self._list_resource(resource, 1), + } + dbi._vnc_lib = flexmock(**kwargs) + + ret = dbi._resource_count_optimized(resource, + filters={'tenant_id': self._tenant_ids[0]}) + self.assertEqual(ret, 1) + + ret = dbi._resource_count_optimized(resource, + filters={'tenant_id': self._tenant_ids}) + self.assertEqual(ret, 2) + + def test_resource_count_optimized(self): + dbi = MockDbInterface() + + ret = dbi._resource_count_optimized('virtual-networks', + filters={'f': 'some-filter'}) + self.assertEqual(ret, None) + + ret = dbi._resource_count_optimized('virtual-networks', + filters={'tenant_id': 'some-id', + 'f': 'some_filter'}) + self.assertEqual(ret, None) + + self._test_for("virtual_networks") + self._test_for("virtual_machine_interfaces") + self._test_for("floating_ips") + self._test_for("logical_routers") + self._test_for("network_policys") + self._test_for("network_ipams") + self._test_for("route_tables")