Do not call configure several times at startup

At startup, Glance first creates the stores and then verifies
the default store. Each of these operations will indirectly
trigger the creation of store objects which is triggering configure
and configure_add calls.
configure and configure_add can potentially contain remote calls
going through the network: we should avoid having these methods
called two times for nothing.

This patch adds a parameter in the store init method to specify
if the configuration of the store should happen. In case of verify
default store, the configuration should not happen.

Closes-Bug: #1315237

Change-Id: I329730a3351cd7b78de27a88a7f669ae32b2f100
This commit is contained in:
Arnaud Legendre 2014-05-01 21:49:07 -07:00
parent c6dd4917f2
commit c9a034c838
10 changed files with 64 additions and 20 deletions

View File

@ -239,6 +239,10 @@ class StoreAddDisabled(GlanceException):
"store is disabled.")
class StoreNotConfigured(GlanceException):
message = _("Store is not configured.")
class MaxRedirectsExceeded(GlanceException):
message = _("Maximum redirects (%(redirects)s) was exceeded.")

View File

@ -228,7 +228,7 @@ def verify_default_store():
scheme = cfg.CONF.default_store
context = glance.context.RequestContext()
try:
get_store_from_scheme(context, scheme)
get_store_from_scheme(context, scheme, configure=False)
except exception.UnknownScheme:
msg = _("Store for scheme %s not found") % scheme
raise RuntimeError(msg)
@ -244,7 +244,7 @@ def get_known_stores():
return list(REGISTERED_STORES)
def get_store_from_scheme(context, scheme, loc=None):
def get_store_from_scheme(context, scheme, loc=None, configure=True):
"""
Given a scheme, return the appropriate store object
for handling that scheme.
@ -252,7 +252,7 @@ def get_store_from_scheme(context, scheme, loc=None):
if scheme not in location.SCHEME_TO_CLS_MAP:
raise exception.UnknownScheme(scheme=scheme)
scheme_info = location.SCHEME_TO_CLS_MAP[scheme]
store = scheme_info['store_class'](context, loc)
store = scheme_info['store_class'](context, loc, configure)
return store

View File

@ -29,14 +29,27 @@ class Store(object):
CHUNKSIZE = 16 * units.Mi # 16M
def __init__(self, context=None, location=None):
@staticmethod
def _unconfigured(*args, **kwargs):
raise exception.StoreNotConfigured
def __init__(self, context=None, location=None, configure=True):
"""
Initialize the Store
"""
self.store_location_class = None
self.context = context
self.configure()
if not configure:
self.add = Store._unconfigured
self.get = Store._unconfigured
self.get_size = Store._unconfigured
self.add_disabled = Store._unconfigured
self.delete = Store._unconfigured
self.set_acls = Store._unconfigured
return
self.configure()
try:
self.configure_add()
except exception.BadStoreConfiguration as e:

View File

@ -285,11 +285,11 @@ class StoreLocation(glance.store.location.StoreLocation):
return ''.join([auth_scheme, self.auth_or_store_url])
def Store(context=None, loc=None):
def Store(context=None, loc=None, configure=True):
if (CONF.swift_store_multi_tenant and
(loc is None or loc.store_location.user is None)):
return MultiTenantStore(context, loc)
return SingleTenantStore(context, loc)
return MultiTenantStore(context, loc, configure=configure)
return SingleTenantStore(context, loc, configure=configure)
class BaseStore(glance.store.base.Store):

View File

@ -81,8 +81,6 @@ class TestCinderStore(store_tests.BaseTestCase, testtools.TestCase):
def get_store(self, **kwargs):
store = cinder.Store(context=kwargs.get('context') or self.context)
store.configure()
store.configure_add()
return store
def stash_image(self, image_id, image_data):

View File

@ -107,8 +107,6 @@ class TestRBDStore(store_tests.BaseTestCase, testtools.TestCase):
def get_store(self, **kwargs):
store = glance.store.rbd.Store(context=kwargs.get('context'))
store.configure()
store.configure_add()
return store
def stash_image(self, image_id, image_data):

View File

@ -59,8 +59,6 @@ class TestSheepdogStore(store_tests.BaseTestCase, testtools.TestCase):
def get_store(self, **kwargs):
store = sheepdog.Store(context=kwargs.get('context'))
store.configure()
store.configure_add()
return store
def stash_image(self, image_id, image_data):

View File

@ -176,8 +176,6 @@ class TestSwiftStore(store_tests.BaseTestCase, testtools.TestCase):
def get_store(self, **kwargs):
store = glance.store.swift.Store(context=kwargs.get('context'))
store.configure()
store.configure_add()
return store
def test_object_chunking(self):

View File

@ -118,10 +118,7 @@ class TestVMwareDatastoreStore(store_tests.BaseTestCase, testtools.TestCase):
super(TestVMwareDatastoreStore, self).setUp()
def get_store(self, **kwargs):
store = vm_store.Store(
context=kwargs.get('context'))
store.configure()
store.configure_add()
store = vm_store.Store(context=kwargs.get('context'))
return store
def stash_image(self, image_id, image_data):

View File

@ -26,6 +26,26 @@ class FakeUnconfigurableStoreDriver(store_base.Store):
class TestStoreBase(test_base.StoreClearingUnitTest):
class UnconfiguredStore(store_base.Store):
def add(self, image_id, image_file, image_size):
return True
def delete(self, location):
return True
def set_acls(self, location, public=False, read_tenants=None,
write_tenants=None):
return True
def get_size(self, location):
return True
def get(self, location):
return True
def add_disabled(self, *args, **kwargs):
return True
def setUp(self):
self.config(default_store='file')
super(TestStoreBase, self).setUp()
@ -36,3 +56,21 @@ class TestStoreBase(test_base.StoreClearingUnitTest):
"glance.store.filesystem.Store"])
count = store.create_stores()
self.assertEqual(9, count)
def test_create_store_not_configured(self):
store = self.UnconfiguredStore(configure=False)
self.assertRaises(exception.StoreNotConfigured, store.add)
self.assertRaises(exception.StoreNotConfigured, store.get)
self.assertRaises(exception.StoreNotConfigured, store.get_size)
self.assertRaises(exception.StoreNotConfigured, store.add_disabled)
self.assertRaises(exception.StoreNotConfigured, store.delete)
self.assertRaises(exception.StoreNotConfigured, store.set_acls)
def test_create_store_configured(self):
store = self.UnconfiguredStore(configure=True)
self.assertTrue(store.add)
self.assertTrue(store.get)
self.assertTrue(store.get_size)
self.assertTrue(store.add_disabled)
self.assertTrue(store.delete)
self.assertTrue(store.set_acls)