From 76844433f69a7c29ed4566ad34d7e9740feaf660 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 19 Mar 2013 17:56:30 -0700 Subject: Add caching for ec2 mapping ids. Requests to map ec2 ids can be slow when there are a large number of instances. These shouldn't ever change so cache them in memory for a week. The one week timeout is simply to prevent memory from growing uncontrollably. Fixes bug 1157437 Change-Id: I3f1c68959a933a7aaa50f122c34a716264c8722d --- nova/api/ec2/ec2utils.py | 33 +++++++++++++++++++++++++++++++++ nova/tests/api/ec2/test_cinder_cloud.py | 1 + nova/tests/api/ec2/test_cloud.py | 1 + 3 files changed, 35 insertions(+) diff --git a/nova/api/ec2/ec2utils.py b/nova/api/ec2/ec2utils.py index bb0f7245a..f1a7abfbc 100644 --- a/nova/api/ec2/ec2utils.py +++ b/nova/api/ec2/ec2utils.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +import functools import re from nova import availability_zones @@ -24,10 +25,34 @@ from nova import db from nova import exception from nova.network import model as network_model from nova.openstack.common import log as logging +from nova.openstack.common import memorycache from nova.openstack.common import timeutils from nova.openstack.common import uuidutils LOG = logging.getLogger(__name__) +# NOTE(vish): cache mapping for one week +_CACHE_TIME = 7 * 24 * 60 * 60 +_CACHE = None + + +def memoize(func): + @functools.wraps(func) + def memoizer(context, reqid): + global _CACHE + if not _CACHE: + _CACHE = memorycache.get_client() + key = "%s:%s" % (func.__name__, reqid) + value = _CACHE.get(key) + if value is None: + value = func(context, reqid) + _CACHE.set(key, value, time=_CACHE_TIME) + return value + return memoizer + + +def reset_cache(): + global _CACHE + _CACHE = None def image_type(image_type): @@ -47,11 +72,13 @@ def image_type(image_type): return image_type +@memoize def id_to_glance_id(context, image_id): """Convert an internal (db) id to a glance id.""" return db.s3_image_get(context, image_id)['uuid'] +@memoize def glance_id_to_id(context, glance_id): """Convert a glance id to an internal (db) id.""" if glance_id is None: @@ -145,6 +172,7 @@ def ec2_inst_id_to_uuid(context, ec2_id): return get_instance_uuid_from_int_id(context, int_id) +@memoize def get_instance_uuid_from_int_id(context, int_id): return db.get_instance_uuid_by_ec2_id(context, int_id) @@ -211,6 +239,7 @@ def is_ec2_timestamp_expired(request, expires=None): return True +@memoize def get_int_id_from_instance_uuid(context, instance_uuid): if instance_uuid is None: return @@ -220,6 +249,7 @@ def get_int_id_from_instance_uuid(context, instance_uuid): return db.ec2_instance_create(context, instance_uuid)['id'] +@memoize def get_int_id_from_volume_uuid(context, volume_uuid): if volume_uuid is None: return @@ -229,6 +259,7 @@ def get_int_id_from_volume_uuid(context, volume_uuid): return db.ec2_volume_create(context, volume_uuid)['id'] +@memoize def get_volume_uuid_from_int_id(context, int_id): return db.get_volume_uuid_by_ec2_id(context, int_id) @@ -242,6 +273,7 @@ def ec2_snap_id_to_uuid(ec2_id): return get_snapshot_uuid_from_int_id(ctxt, int_id) +@memoize def get_int_id_from_snapshot_uuid(context, snapshot_uuid): if snapshot_uuid is None: return @@ -251,6 +283,7 @@ def get_int_id_from_snapshot_uuid(context, snapshot_uuid): return db.ec2_snapshot_create(context, snapshot_uuid)['id'] +@memoize def get_snapshot_uuid_from_int_id(context, int_id): return db.get_snapshot_uuid_by_ec2_id(context, int_id) diff --git a/nova/tests/api/ec2/test_cinder_cloud.py b/nova/tests/api/ec2/test_cinder_cloud.py index 7b66da749..93614ef82 100644 --- a/nova/tests/api/ec2/test_cinder_cloud.py +++ b/nova/tests/api/ec2/test_cinder_cloud.py @@ -88,6 +88,7 @@ def get_instances_with_cached_ips(orig_func, *args, **kwargs): class CinderCloudTestCase(test.TestCase): def setUp(self): super(CinderCloudTestCase, self).setUp() + ec2utils.reset_cache() vol_tmpdir = self.useFixture(fixtures.TempDir()).path self.flags(compute_driver='nova.virt.fake.FakeDriver', volume_api_class='nova.tests.fake_volume.API') diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py index ebf0188b9..322bbb465 100644 --- a/nova/tests/api/ec2/test_cloud.py +++ b/nova/tests/api/ec2/test_cloud.py @@ -106,6 +106,7 @@ def get_instances_with_cached_ips(orig_func, *args, **kwargs): class CloudTestCase(test.TestCase): def setUp(self): super(CloudTestCase, self).setUp() + ec2utils.reset_cache() self.flags(compute_driver='nova.virt.fake.FakeDriver', volume_api_class='nova.tests.fake_volume.API') self.useFixture(fixtures.FakeLogger('boto')) -- cgit