Except if tracked resource registered as countable

If a resource was registered in the quota engine before
being set as a tracked resource, it would have been registered
as a CountableResource instead of a TrackedResource.

This would cause a failure later when the resources were
being unregistered because the quota engine thought it
should have been a TrackedResource and tried to call
unregister_events on it.

This patch just prevents resources from being registered
as both types. It also callse unregister_all_resources as
part of the standard test case cleanup since the vast majority
of tests are using a plugin that may register resources.

Closes-Bug: #1612222
Change-Id: I8a40f38d7c0e5aeca257ba62115fa9b02ad5aa93
This commit is contained in:
Kevin Benton 2016-08-11 02:02:59 -07:00
parent 4a98b31b6a
commit 5d597367cf
3 changed files with 20 additions and 0 deletions

View File

@ -36,6 +36,12 @@ def get_all_resources():
return ResourceRegistry.get_instance().resources return ResourceRegistry.get_instance().resources
def unregister_all_resources():
if not ResourceRegistry._instance:
return
return ResourceRegistry.get_instance().unregister_resources()
def get_resource(resource_name): def get_resource(resource_name):
return ResourceRegistry.get_instance().get_resource(resource_name) return ResourceRegistry.get_instance().get_resource(resource_name)
@ -183,6 +189,10 @@ class ResourceRegistry(object):
if not cfg.CONF.QUOTAS.track_quota_usage: if not cfg.CONF.QUOTAS.track_quota_usage:
return return
if isinstance(self._resources.get(resource_name),
resource.CountableResource):
raise RuntimeError("Resource %s is already registered as a "
"countable resource." % resource_name)
current_model_class = self._tracked_resource_mappings.setdefault( current_model_class = self._tracked_resource_mappings.setdefault(
resource_name, model_class) resource_name, model_class)

View File

@ -46,6 +46,7 @@ from neutron.common import utils
from neutron.db import agentschedulers_db from neutron.db import agentschedulers_db
from neutron import manager from neutron import manager
from neutron import policy from neutron import policy
from neutron.quota import resource_registry
from neutron.tests import fake_notifier from neutron.tests import fake_notifier
from neutron.tests import post_mortem_debug from neutron.tests import post_mortem_debug
from neutron.tests import tools from neutron.tests import tools
@ -302,6 +303,7 @@ class BaseTestCase(DietTestCase):
policy.init() policy.init()
self.addCleanup(policy.reset) self.addCleanup(policy.reset)
self.addCleanup(resource_registry.unregister_all_resources)
self.addCleanup(rpc_consumer_reg.clear) self.addCleanup(rpc_consumer_reg.clear)
def get_new_temp_dir(self): def get_new_temp_dir(self):

View File

@ -14,6 +14,7 @@
import mock import mock
from oslo_config import cfg from oslo_config import cfg
import testtools
from neutron import context from neutron import context
from neutron.quota import resource from neutron.quota import resource
@ -64,6 +65,13 @@ class TestResourceRegistry(base.DietTestCase):
def test_register_resource_by_name_not_tracked(self): def test_register_resource_by_name_not_tracked(self):
self._test_register_resource_by_name('meh', resource.CountableResource) self._test_register_resource_by_name('meh', resource.CountableResource)
def test_tracked_resource_error_if_already_registered_as_untracked(self):
self.registry.register_resource_by_name('meh')
with testtools.ExpectedException(RuntimeError):
self.registry.set_tracked_resource('meh', test_quota.MehModel)
# ensure unregister works
self.registry.unregister_resources()
def test_register_resource_by_name_with_tracking_disabled_by_config(self): def test_register_resource_by_name_with_tracking_disabled_by_config(self):
cfg.CONF.set_override('track_quota_usage', False, cfg.CONF.set_override('track_quota_usage', False,
group='QUOTAS') group='QUOTAS')