summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Pavlovic <boris@pavlovic.me>2013-05-08 16:25:46 +0400
committerBoris Pavlovic <boris@pavlovic.me>2013-05-08 17:16:46 +0400
commitac9cc15164f0afcac4b3320bcd58d36c00f3232c (patch)
tree9d2ae38fc73fc2231270a601bc89ee18803b3708
parent2e35d7177830e16abd3e919510437f48c6691d51 (diff)
downloadnova-ac9cc15164f0afcac4b3320bcd58d36c00f3232c.tar.gz
nova-ac9cc15164f0afcac4b3320bcd58d36c00f3232c.tar.xz
nova-ac9cc15164f0afcac4b3320bcd58d36c00f3232c.zip
Optimize db.instance_floating_address_get_all method
Optimize db.instance_floating_address_get_all Was: Get FixedIps with corresponding instance_uuid For each FixedIp get associated FloatIp (N request) Now: Get only list of FixedIps ids Get all corresponding FloatingIp with one query (select in) Get only addresses from FloatingIps (because we are using only it) Add temporary test for db.instance_floating_address_get_all to ensure that it works as expected. Change-Id: Id3c515de0ca35707bbfe46b991c2d7cf591e431b
-rw-r--r--nova/db/sqlalchemy/api.py21
-rw-r--r--nova/network/api.py2
-rw-r--r--nova/tests/test_db_api.py28
3 files changed, 44 insertions, 7 deletions
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index d5f4c8e6f..bb5978f82 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -1911,14 +1911,23 @@ def instance_get_floating_address(context, instance_id):
@require_context
def instance_floating_address_get_all(context, instance_uuid):
- fixed_ips = fixed_ip_get_by_instance(context, instance_uuid)
+ if not uuidutils.is_uuid_like(instance_uuid):
+ raise exception.InvalidUUID(uuid=instance_uuid)
+
+ fixed_ip_ids = model_query(context, models.FixedIp.id,
+ base_model=models.FixedIp).\
+ filter_by(instance_uuid=instance_uuid).\
+ all()
+ if not fixed_ip_ids:
+ raise exception.FixedIpNotFoundForInstance(instance_uuid=instance_uuid)
- floating_ips = []
- for fixed_ip in fixed_ips:
- _floating_ips = floating_ip_get_by_fixed_ip_id(context, fixed_ip['id'])
- floating_ips += _floating_ips
+ fixed_ip_ids = [fixed_ip_id.id for fixed_ip_id in fixed_ip_ids]
- return floating_ips
+ floating_ips = model_query(context, models.FloatingIp.address,
+ base_model=models.FloatingIp).\
+ filter(models.FloatingIp.fixed_ip_id.in_(fixed_ip_ids)).\
+ all()
+ return [floating_ip.address for floating_ip in floating_ips]
@require_admin_context
diff --git a/nova/network/api.py b/nova/network/api.py
index b8baf9810..26ca7584a 100644
--- a/nova/network/api.py
+++ b/nova/network/api.py
@@ -486,7 +486,7 @@ class API(base.Base):
def _get_floating_ip_addresses(self, context, instance):
floating_ips = self.db.instance_floating_address_get_all(context,
instance['uuid'])
- return [floating_ip['address'] for floating_ip in floating_ips]
+ return floating_ips
@wrap_check_policy
def migrate_instance_start(self, context, instance, migration):
diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py
index cfed3ab3b..626cad630 100644
--- a/nova/tests/test_db_api.py
+++ b/nova/tests/test_db_api.py
@@ -1023,6 +1023,34 @@ class DbApiTestCase(DbTestCase):
self.assertEqual(db.network_in_use_on_host(ctxt, 1, 'foo'), True)
self.assertEqual(db.network_in_use_on_host(ctxt, 1, 'bar'), False)
+ def test_instance_floating_address_get_all(self):
+ ctxt = context.get_admin_context()
+
+ instance1 = db.instance_create(ctxt, {'host': 'h1', 'hostname': 'n1'})
+ instance2 = db.instance_create(ctxt, {'host': 'h2', 'hostname': 'n2'})
+
+ fixed_addresses = ['1.1.1.1', '1.1.1.2', '1.1.1.3']
+ float_addresses = ['2.1.1.1', '2.1.1.2', '2.1.1.3']
+ instance_uuids = [instance1['uuid'], instance1['uuid'],
+ instance2['uuid']]
+
+ for fixed_addr, float_addr, instance_uuid in zip(fixed_addresses,
+ float_addresses,
+ instance_uuids):
+ db.fixed_ip_create(ctxt, {'address': fixed_addr,
+ 'instance_uuid': instance_uuid})
+ fixed_id = db.fixed_ip_get_by_address(ctxt, fixed_addr)['id']
+ db.floating_ip_create(ctxt,
+ {'address': float_addr,
+ 'fixed_ip_id': fixed_id})
+
+ real_float_addresses = \
+ db.instance_floating_address_get_all(ctxt, instance_uuids[0])
+ self.assertEqual(set(float_addresses[:2]), set(real_float_addresses))
+ real_float_addresses = \
+ db.instance_floating_address_get_all(ctxt, instance_uuids[2])
+ self.assertEqual(set([float_addresses[2]]), set(real_float_addresses))
+
def test_get_vol_mapping_non_admin(self):
ref = db.ec2_volume_create(self.context, 'fake-uuid')
ec2_id = db.get_ec2_volume_id_by_uuid(self.context, 'fake-uuid')