Remove network_api fallback for info_cache from APIs
Fixes bug 932395 OS API and EC2 would query the network API when instance['info_cache'] had no network info.. or network info was an empty list. The ideal was to fall back to querying the network IP in case the cache was busted. However, reality says this case is extremely common as it is the case when instances are freshly built and haven't had network info assigned yet. The calls to network API are expensive and goes against the whole idea of this "cache". So, this patch removes the fallback to querying the network API. In its place, it adds a periodic task to the compute manager to periodically sync the cache entry. Since I had to fix a number of tests, I consolidated some things there as well with regards to instance stubbing. Change-Id: I493f811bcba4e99ac6a5756bcab473557d5c0104
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
"""
|
||||
Tests For Compute
|
||||
"""
|
||||
from copy import copy
|
||||
import copy
|
||||
import datetime
|
||||
import sys
|
||||
import time
|
||||
@@ -1604,6 +1604,81 @@ class ComputeTestCase(BaseTestCase):
|
||||
val = self.compute._running_deleted_instances('context')
|
||||
self.assertEqual(val, [instance1])
|
||||
|
||||
def test_heal_instance_info_cache(self):
|
||||
# Update on every call for the test
|
||||
self.flags(heal_instance_info_cache_interval=-1)
|
||||
ctxt = context.get_admin_context()
|
||||
|
||||
instance_map = {}
|
||||
instances = []
|
||||
for x in xrange(5):
|
||||
uuid = 'fake-uuid-%s' % x
|
||||
instance_map[uuid] = {'uuid': uuid, 'host': FLAGS.host}
|
||||
instances.append(instance_map[uuid])
|
||||
|
||||
call_info = {'get_all_by_host': 0, 'get_by_uuid': 0,
|
||||
'get_nw_info': 0, 'expected_instance': None}
|
||||
|
||||
def fake_instance_get_all_by_host(context, host):
|
||||
call_info['get_all_by_host'] += 1
|
||||
return instances[:]
|
||||
|
||||
def fake_instance_get_by_uuid(context, instance_uuid):
|
||||
if instance_uuid not in instance_map:
|
||||
raise exception.InstanceNotFound
|
||||
call_info['get_by_uuid'] += 1
|
||||
return instance_map[instance_uuid]
|
||||
|
||||
def fake_get_instance_nw_info(context, instance):
|
||||
# Note that this exception gets caught in compute/manager
|
||||
# and is ignored. However, the below increment of
|
||||
# 'get_nw_info' won't happen, and you'll get an assert
|
||||
# failure checking it below.
|
||||
self.assertEqual(instance, call_info['expected_instance'])
|
||||
call_info['get_nw_info'] += 1
|
||||
|
||||
self.stubs.Set(db, 'instance_get_all_by_host',
|
||||
fake_instance_get_all_by_host)
|
||||
self.stubs.Set(db, 'instance_get_by_uuid',
|
||||
fake_instance_get_by_uuid)
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info',
|
||||
fake_get_instance_nw_info)
|
||||
|
||||
call_info['expected_instance'] = instances[0]
|
||||
self.compute._heal_instance_info_cache(ctxt)
|
||||
self.assertEqual(call_info['get_all_by_host'], 1)
|
||||
self.assertEqual(call_info['get_by_uuid'], 0)
|
||||
self.assertEqual(call_info['get_nw_info'], 1)
|
||||
|
||||
call_info['expected_instance'] = instances[1]
|
||||
self.compute._heal_instance_info_cache(ctxt)
|
||||
self.assertEqual(call_info['get_all_by_host'], 1)
|
||||
self.assertEqual(call_info['get_by_uuid'], 1)
|
||||
self.assertEqual(call_info['get_nw_info'], 2)
|
||||
|
||||
# Make an instance switch hosts
|
||||
instances[2]['host'] = 'not-me'
|
||||
# Make an instance disappear
|
||||
instance_map.pop(instances[3]['uuid'])
|
||||
# '2' and '3' should be skipped..
|
||||
call_info['expected_instance'] = instances[4]
|
||||
self.compute._heal_instance_info_cache(ctxt)
|
||||
self.assertEqual(call_info['get_all_by_host'], 1)
|
||||
# Incremented for '2' and '4'.. '3' caused a raise above.
|
||||
self.assertEqual(call_info['get_by_uuid'], 3)
|
||||
self.assertEqual(call_info['get_nw_info'], 3)
|
||||
# Should be no more left.
|
||||
self.assertEqual(len(self.compute._instance_uuids_to_heal), 0)
|
||||
|
||||
# This should cause a DB query now so we get first instance
|
||||
# back again
|
||||
call_info['expected_instance'] = instances[0]
|
||||
self.compute._heal_instance_info_cache(ctxt)
|
||||
self.assertEqual(call_info['get_all_by_host'], 2)
|
||||
# Stays the same, beacuse the instance came from the DB
|
||||
self.assertEqual(call_info['get_by_uuid'], 3)
|
||||
self.assertEqual(call_info['get_nw_info'], 4)
|
||||
|
||||
|
||||
class ComputeAPITestCase(BaseTestCase):
|
||||
|
||||
@@ -1638,7 +1713,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
inst_type['memory_mb'] = 1
|
||||
|
||||
def fake_show(*args):
|
||||
img = copy(self.fake_image)
|
||||
img = copy.copy(self.fake_image)
|
||||
img['min_ram'] = 2
|
||||
return img
|
||||
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
|
||||
@@ -1659,7 +1734,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
inst_type['root_gb'] = 1
|
||||
|
||||
def fake_show(*args):
|
||||
img = copy(self.fake_image)
|
||||
img = copy.copy(self.fake_image)
|
||||
img['min_disk'] = 2
|
||||
return img
|
||||
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
|
||||
@@ -1681,7 +1756,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
inst_type['memory_mb'] = 2
|
||||
|
||||
def fake_show(*args):
|
||||
img = copy(self.fake_image)
|
||||
img = copy.copy(self.fake_image)
|
||||
img['min_ram'] = 2
|
||||
img['min_disk'] = 2
|
||||
return img
|
||||
@@ -1699,7 +1774,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
inst_type['memory_mb'] = 1
|
||||
|
||||
def fake_show(*args):
|
||||
return copy(self.fake_image)
|
||||
return copy.copy(self.fake_image)
|
||||
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
|
||||
|
||||
(refs, resv_id) = self.compute_api.create(self.context,
|
||||
@@ -2143,7 +2218,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
"""
|
||||
|
||||
def fake_show(*args):
|
||||
img = copy(self.fake_image)
|
||||
img = copy.copy(self.fake_image)
|
||||
img['disk_format'] = 'vhd'
|
||||
return img
|
||||
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
|
||||
@@ -2175,7 +2250,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
"""
|
||||
|
||||
def fake_show(*args):
|
||||
img = copy(self.fake_image)
|
||||
img = copy.copy(self.fake_image)
|
||||
img['disk_format'] = 'raw'
|
||||
img['min_ram'] = 512
|
||||
img['min_disk'] = 1
|
||||
@@ -2205,7 +2280,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
"""
|
||||
|
||||
def fake_show(*args):
|
||||
img = copy(self.fake_image)
|
||||
img = copy.copy(self.fake_image)
|
||||
img['disk_format'] = 'raw'
|
||||
img['min_disk'] = 1
|
||||
return img
|
||||
|
||||
Reference in New Issue
Block a user