From a72a66c206cd80aa4b392eb42c29e4a1cd4463f9 Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Thu, 15 Dec 2011 15:21:11 +0000 Subject: [PATCH] Switch disk_config extension to use one DB query A response through this extension can have many servers and making one query per server can slow down response time dramatically. This change switches the extension to use one DB query instead of many queries. It also avoids queries when the key is already populated, such as when the results include responses from a remote zone. This change reduces a 'nova list' of 21 servers from 14 seconds to 1 second on my (relatively slow) development system. Change-Id: I8476dbca0f87ff2a3d69bd7b8f51c296e41e3388 --- nova/api/openstack/v2/contrib/disk_config.py | 17 ++++++++++++++--- .../openstack/v2/contrib/test_disk_config.py | 18 +++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/nova/api/openstack/v2/contrib/disk_config.py b/nova/api/openstack/v2/contrib/disk_config.py index 6e26c1daad12..7ce24a3fdd48 100644 --- a/nova/api/openstack/v2/contrib/disk_config.py +++ b/nova/api/openstack/v2/contrib/disk_config.py @@ -23,6 +23,7 @@ from webob import exc from nova.api.openstack.v2 import extensions from nova.api.openstack import xmlutil from nova import compute +from nova import db from nova import log as logging from nova import utils @@ -118,10 +119,20 @@ class Disk_config(extensions.ExtensionDescriptor): singular='server', singular_template=ServerDiskConfigTemplate(), plural='servers', plural_template=ServersDiskConfigTemplate()) + # Filter out any servers that already have the key set (most likely + # from a remote zone) + servers = filter(lambda s: self.API_DISK_CONFIG not in s, servers) + + # Get DB information for servers + uuids = [server['id'] for server in servers] + db_servers = db.instance_get_all_by_filters(context, {'uuid': uuids}) + db_servers = dict([(s['uuid'], s) for s in db_servers]) + for server in servers: - db_server = self.compute_api.routing_get(context, server['id']) - value = db_server[self.INTERNAL_DISK_CONFIG] - server[self.API_DISK_CONFIG] = disk_config_to_api(value) + db_server = db_servers.get(server['id']) + if db_server: + value = db_server[self.INTERNAL_DISK_CONFIG] + server[self.API_DISK_CONFIG] = disk_config_to_api(value) return res diff --git a/nova/tests/api/openstack/v2/contrib/test_disk_config.py b/nova/tests/api/openstack/v2/contrib/test_disk_config.py index ac2391a046af..95cfd3747a9a 100644 --- a/nova/tests/api/openstack/v2/contrib/test_disk_config.py +++ b/nova/tests/api/openstack/v2/contrib/test_disk_config.py @@ -60,7 +60,6 @@ class DiskConfigTestCase(test.TestCase): if id_ == instance['id']: return instance - self.stubs.Set(nova.db.api, 'instance_get', fake_instance_get) self.stubs.Set(nova.db, 'instance_get', fake_instance_get) def fake_instance_get_by_uuid(context, uuid): @@ -75,7 +74,7 @@ class DiskConfigTestCase(test.TestCase): return FAKE_INSTANCES self.stubs.Set(nova.db, 'instance_get_all', fake_instance_get_all) - self.stubs.Set(nova.db.api, 'instance_get_all_by_filters', + self.stubs.Set(nova.db, 'instance_get_all_by_filters', fake_instance_get_all) def fake_instance_create(context, inst_, session=None): @@ -91,21 +90,26 @@ class DiskConfigTestCase(test.TestCase): inst['progress'] = 0 inst['name'] = 'instance-1' # this is a property - def fake_instance_get_for_create(context, id_, session=None): + def fake_instance_get_for_create(context, id_, *args, **kwargs): return inst self.stubs.Set(nova.db, 'instance_get', fake_instance_get_for_create) - self.stubs.Set(nova.db.api, 'instance_get', - fake_instance_get_for_create) - self.stubs.Set(nova.db.sqlalchemy.api, 'instance_get', + self.stubs.Set(nova.db, 'instance_update', fake_instance_get_for_create) + def fake_instance_get_all_for_create(context, *args, **kwargs): + return [inst] + self.stubs.Set(nova.db, 'instance_get_all', + fake_instance_get_all_for_create) + self.stubs.Set(nova.db, 'instance_get_all_by_filters', + fake_instance_get_all_for_create) + def fake_instance_add_security_group(context, instance_id, security_group_id): pass - self.stubs.Set(nova.db.sqlalchemy.api, + self.stubs.Set(nova.db, 'instance_add_security_group', fake_instance_add_security_group)