Cache the automatic version pin to avoid repeated lookups

The compute rpcapi module was looking up the desired automatic
version pin each time it was initialized. Turns out, we create and
destroy this object too often, which means we do a lot of those
lookups unnecessarily. That's a larger problem that will be harder
to solve, but we can be smarter about the DB impact of that.

This adds a cache of the last version we discovered and avoids doing
the lookup when possible. It makes the reset() method invalidate the
cache prior to reinitializing the object so that we will do the lookup
on SIGHUP as desired.

Closes-Bug: #1524444
Change-Id: Ia1c58efa7105d32973f6921c2144b17c30b764c2
This commit is contained in:
Dan Smith
2015-12-09 10:01:05 -08:00
parent b5890b3c36
commit 242ee4b5e7
3 changed files with 19 additions and 0 deletions

View File

@@ -720,6 +720,7 @@ class ComputeManager(manager.Manager):
def reset(self):
LOG.info(_LI('Reloading compute RPC API'))
compute_rpcapi.LAST_VERSION = None
self.compute_rpcapi = compute_rpcapi.ComputeAPI()
def _get_resource_tracker(self, nodename):

View File

@@ -47,6 +47,7 @@ rpcapi_cap_opt = cfg.StrOpt('compute',
CONF.register_opt(rpcapi_cap_opt, 'upgrade_levels')
LOG = logging.getLogger(__name__)
LAST_VERSION = None
def _compute_host(host, instance):
@@ -333,6 +334,9 @@ class ComputeAPI(object):
self.client = self.get_client(target, version_cap, serializer)
def _determine_version_cap(self, target):
global LAST_VERSION
if LAST_VERSION:
return LAST_VERSION
service_version = objects.Service.get_minimum_version(
context.get_admin_context(), 'nova-compute')
history = service_obj.SERVICE_VERSION_HISTORY
@@ -350,6 +354,7 @@ class ComputeAPI(object):
'service history for version %(version)i'),
{'version': service_version})
return target.version
LAST_VERSION = version_cap
LOG.info(_LI('Automatically selected compute RPC version %(rpc)s '
'from minimum service version %(service)i'),
{'rpc': version_cap,

View File

@@ -55,6 +55,7 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
def test_auto_pin(self, mock_get_min):
mock_get_min.return_value = 1
self.flags(compute='auto', group='upgrade_levels')
compute_rpcapi.LAST_VERSION = None
rpcapi = compute_rpcapi.ComputeAPI()
self.assertEqual('4.4', rpcapi.client.version_cap)
mock_get_min.assert_called_once_with(mock.ANY, 'nova-compute')
@@ -63,6 +64,7 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
def test_auto_pin_fails_if_too_old(self, mock_get_min):
mock_get_min.return_value = 1955
self.flags(compute='auto', group='upgrade_levels')
compute_rpcapi.LAST_VERSION = None
self.assertRaises(exception.ServiceTooOld,
compute_rpcapi.ComputeAPI)
@@ -70,10 +72,21 @@ class ComputeRpcAPITestCase(test.NoDBTestCase):
def test_auto_pin_kilo(self, mock_get_min):
mock_get_min.return_value = 0
self.flags(compute='auto', group='upgrade_levels')
compute_rpcapi.LAST_VERSION = None
rpcapi = compute_rpcapi.ComputeAPI()
self.assertEqual('4.0', rpcapi.client.version_cap)
mock_get_min.assert_called_once_with(mock.ANY, 'nova-compute')
@mock.patch('nova.objects.Service.get_minimum_version')
def test_auto_pin_caches(self, mock_get_min):
mock_get_min.return_value = 1
self.flags(compute='auto', group='upgrade_levels')
compute_rpcapi.LAST_VERSION = None
compute_rpcapi.ComputeAPI()
compute_rpcapi.ComputeAPI()
mock_get_min.assert_called_once_with(mock.ANY, 'nova-compute')
self.assertEqual('4.4', compute_rpcapi.LAST_VERSION)
def _test_compute_api(self, method, rpc_method,
expected_args=None, **kwargs):
ctxt = context.RequestContext('fake_user', 'fake_project')