Use one wsgi app, one dbengine worker.
Return to using one wsgi application but use one database engine per worker process. Fixes Bug #1089916 Change-Id: Iea4b1b925208317c3c6ee3c9461b6723f3168405
This commit is contained in:
parent
19b8b4b73b
commit
0e9111ca59
@ -57,7 +57,7 @@ if __name__ == '__main__':
|
||||
glance.store.verify_default_store()
|
||||
|
||||
server = wsgi.Server()
|
||||
server.start(config.load_paste_app, default_port=9292)
|
||||
server.start(config.load_paste_app(), default_port=9292)
|
||||
server.wait()
|
||||
except exception.WorkerCreationFailure, e:
|
||||
fail(2, e)
|
||||
|
@ -47,7 +47,7 @@ if __name__ == '__main__':
|
||||
log.setup('glance')
|
||||
|
||||
server = wsgi.Server()
|
||||
server.start(config.load_paste_app, default_port=9191)
|
||||
server.start(config.load_paste_app(), default_port=9191)
|
||||
server.wait()
|
||||
except RuntimeError, e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
@ -33,7 +33,7 @@ class ImageDataController(object):
|
||||
def __init__(self, db_api=None, store_api=None,
|
||||
policy_enforcer=None, notifier=None):
|
||||
self.db_api = db_api or glance.db.get_api()
|
||||
self.db_api.configure_db()
|
||||
self.db_api.setup_db_env()
|
||||
self.store_api = store_api or glance.store
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or glance.notifier.Notifier()
|
||||
|
@ -24,7 +24,7 @@ import glance.db
|
||||
class Controller(object):
|
||||
def __init__(self, db=None):
|
||||
self.db_api = db or glance.db.get_api()
|
||||
self.db_api.configure_db()
|
||||
self.db_api.setup_db_env()
|
||||
|
||||
@utils.mutating
|
||||
def update(self, req, image_id, tag_value):
|
||||
|
@ -45,7 +45,7 @@ class ImagesController(object):
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None,
|
||||
store_api=None):
|
||||
self.db_api = db_api or glance.db.get_api()
|
||||
self.db_api.configure_db()
|
||||
self.db_api.setup_db_env()
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or glance.notifier.Notifier()
|
||||
self.store_api = store_api or glance.store
|
||||
|
@ -168,8 +168,7 @@ class Server(object):
|
||||
"""
|
||||
Run a WSGI server with the given application.
|
||||
|
||||
:param application: A function that can be called with no arguments
|
||||
that will return the application to run in the WSGI server
|
||||
:param application: The application to be run in the WSGI server
|
||||
:param default_port: Port to bind to if none is specified in conf
|
||||
"""
|
||||
def kill_children(*args):
|
||||
@ -188,7 +187,7 @@ class Server(object):
|
||||
signal.signal(signal.SIGHUP, signal.SIG_IGN)
|
||||
self.running = False
|
||||
|
||||
self.app_func = application
|
||||
self.application = application
|
||||
self.sock = get_socket(default_port)
|
||||
|
||||
os.umask(027) # ensure files are created with the correct privileges
|
||||
@ -197,7 +196,7 @@ class Server(object):
|
||||
if CONF.workers == 0:
|
||||
# Useful for profiling, test, debug etc.
|
||||
self.pool = self.create_pool()
|
||||
self.pool.spawn_n(self._single_run, self.app_func(), self.sock)
|
||||
self.pool.spawn_n(self._single_run, self.application, self.sock)
|
||||
return
|
||||
else:
|
||||
self.logger.info(_("Starting %d workers") % CONF.workers)
|
||||
@ -276,7 +275,7 @@ class Server(object):
|
||||
self.pool = self.create_pool()
|
||||
try:
|
||||
eventlet.wsgi.server(self.sock,
|
||||
self.app_func(),
|
||||
self.application,
|
||||
log=WritableLogger(self.logger),
|
||||
custom_pool=self.pool)
|
||||
except socket.error, err:
|
||||
|
@ -55,6 +55,10 @@ def reset():
|
||||
}
|
||||
|
||||
|
||||
def setup_db_env(*args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
def configure_db(*args, **kwargs):
|
||||
pass
|
||||
|
||||
|
@ -81,51 +81,28 @@ def ping_listener(dbapi_conn, connection_rec, connection_proxy):
|
||||
raise
|
||||
|
||||
|
||||
def setup_db_env():
|
||||
"""
|
||||
Setup configuation for database
|
||||
"""
|
||||
global sa_logger, _IDLE_TIMEOUT, _MAX_RETRIES, _RETRY_INTERVAL, _CONNECTION
|
||||
|
||||
_IDLE_TIMEOUT = CONF.sql_idle_timeout
|
||||
_MAX_RETRIES = CONF.sql_max_retries
|
||||
_RETRY_INTERVAL = CONF.sql_retry_interval
|
||||
_CONNECTION = CONF.sql_connection
|
||||
sa_logger = logging.getLogger('sqlalchemy.engine')
|
||||
if CONF.debug:
|
||||
sa_logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def configure_db():
|
||||
"""
|
||||
Establish the database, create an engine if needed, and
|
||||
register the models.
|
||||
"""
|
||||
global _ENGINE, sa_logger, _MAX_RETRIES, _RETRY_INTERVAL
|
||||
if not _ENGINE:
|
||||
sql_connection = CONF.sql_connection
|
||||
_MAX_RETRIES = CONF.sql_max_retries
|
||||
_RETRY_INTERVAL = CONF.sql_retry_interval
|
||||
connection_dict = sqlalchemy.engine.url.make_url(sql_connection)
|
||||
engine_args = {'pool_recycle': CONF.sql_idle_timeout,
|
||||
'echo': False,
|
||||
'convert_unicode': True
|
||||
}
|
||||
|
||||
try:
|
||||
_ENGINE = sqlalchemy.create_engine(sql_connection, **engine_args)
|
||||
|
||||
if 'mysql' in connection_dict.drivername:
|
||||
sqlalchemy.event.listen(_ENGINE, 'checkout', ping_listener)
|
||||
|
||||
_ENGINE.connect = wrap_db_error(_ENGINE.connect)
|
||||
_ENGINE.connect()
|
||||
except Exception, err:
|
||||
msg = _("Error configuring registry database with supplied "
|
||||
"sql_connection '%(sql_connection)s'. "
|
||||
"Got error:\n%(err)s") % locals()
|
||||
LOG.error(msg)
|
||||
raise
|
||||
|
||||
sa_logger = logging.getLogger('sqlalchemy.engine')
|
||||
if CONF.debug:
|
||||
sa_logger.setLevel(logging.DEBUG)
|
||||
|
||||
if CONF.db_auto_create:
|
||||
LOG.info(_('auto-creating glance registry DB'))
|
||||
models.register_models(_ENGINE)
|
||||
try:
|
||||
migration.version_control()
|
||||
except exception.DatabaseMigrationError:
|
||||
# only arises when the DB exists and is under version control
|
||||
pass
|
||||
else:
|
||||
LOG.info(_('not auto-creating glance registry DB'))
|
||||
setup_db_env()
|
||||
get_engine()
|
||||
|
||||
|
||||
def check_mutate_authorization(context, image_ref):
|
||||
@ -144,11 +121,73 @@ def get_session(autocommit=True, expire_on_commit=False):
|
||||
"""Helper method to grab session"""
|
||||
global _MAKER
|
||||
if not _MAKER:
|
||||
assert _ENGINE
|
||||
get_engine()
|
||||
get_maker(autocommit, expire_on_commit)
|
||||
assert(_MAKER)
|
||||
session = _MAKER()
|
||||
return session
|
||||
|
||||
|
||||
def get_engine():
|
||||
"""Return a SQLAlchemy engine."""
|
||||
"""May assign _ENGINE if not already assigned"""
|
||||
global _ENGINE, sa_logger, _CONNECTION, _IDLE_TIMEOUT, _MAX_RETRIES,\
|
||||
_RETRY_INTERVAL
|
||||
|
||||
if not _ENGINE:
|
||||
tries = _MAX_RETRIES
|
||||
retry_interval = _RETRY_INTERVAL
|
||||
|
||||
connection_dict = sqlalchemy.engine.url.make_url(_CONNECTION)
|
||||
|
||||
engine_args = {
|
||||
'pool_recycle': _IDLE_TIMEOUT,
|
||||
'echo': False,
|
||||
'convert_unicode': True}
|
||||
|
||||
try:
|
||||
_ENGINE = sqlalchemy.create_engine(_CONNECTION, **engine_args)
|
||||
|
||||
if 'mysql' in connection_dict.drivername:
|
||||
sqlalchemy.event.listen(_ENGINE, 'checkout', ping_listener)
|
||||
|
||||
_ENGINE.connect = wrap_db_error(_ENGINE.connect)
|
||||
_ENGINE.connect()
|
||||
except Exception, err:
|
||||
msg = _("Error configuring registry database with supplied "
|
||||
"sql_connection '%s'. "
|
||||
"Got error:\n%s") % (_CONNECTION, err)
|
||||
LOG.error(msg)
|
||||
raise
|
||||
|
||||
sa_logger = logging.getLogger('sqlalchemy.engine')
|
||||
if CONF.debug:
|
||||
sa_logger.setLevel(logging.DEBUG)
|
||||
|
||||
if CONF.db_auto_create:
|
||||
LOG.info(_('auto-creating glance registry DB'))
|
||||
models.register_models(_ENGINE)
|
||||
try:
|
||||
migration.version_control()
|
||||
except exception.DatabaseMigrationError:
|
||||
# only arises when the DB exists and is under version control
|
||||
pass
|
||||
else:
|
||||
LOG.info(_('not auto-creating glance registry DB'))
|
||||
|
||||
return _ENGINE
|
||||
|
||||
|
||||
def get_maker(autocommit=True, expire_on_commit=False):
|
||||
"""Return a SQLAlchemy sessionmaker."""
|
||||
"""May assign __MAKER if not already assigned"""
|
||||
global _MAKER, _ENGINE
|
||||
assert _ENGINE
|
||||
if not _MAKER:
|
||||
_MAKER = sa_orm.sessionmaker(bind=_ENGINE,
|
||||
autocommit=autocommit,
|
||||
expire_on_commit=expire_on_commit)
|
||||
return _MAKER()
|
||||
return _MAKER
|
||||
|
||||
|
||||
def is_db_connection_error(args):
|
||||
|
@ -55,7 +55,7 @@ class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.db_api = glance.db.get_api()
|
||||
self.db_api.configure_db()
|
||||
self.db_api.setup_db_env()
|
||||
|
||||
def _get_images(self, context, filters, **params):
|
||||
"""
|
||||
|
@ -35,7 +35,7 @@ class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.db_api = glance.db.get_api()
|
||||
self.db_api.configure_db()
|
||||
self.db_api.setup_db_env()
|
||||
|
||||
def index(self, req, image_id):
|
||||
"""
|
||||
|
@ -71,7 +71,7 @@ class TestClientExceptions(functional.FunctionalTest):
|
||||
server = wsgi.Server()
|
||||
self.config(bind_host='127.0.0.1')
|
||||
self.config(workers=0)
|
||||
server.start(ExceptionTestApp, self.port)
|
||||
server.start(ExceptionTestApp(), self.port)
|
||||
self.client = client.BaseClient("127.0.0.1", self.port)
|
||||
|
||||
def _do_test_exception(self, path, exc_type):
|
||||
|
@ -90,8 +90,8 @@ class TestClientRedirects(functional.FunctionalTest):
|
||||
server_two = wsgi.Server()
|
||||
self.config(bind_host='127.0.0.1')
|
||||
self.config(workers=0)
|
||||
server_one.start(RedirectTestApp("one"), self.port_one)
|
||||
server_two.start(RedirectTestApp("two"), self.port_two)
|
||||
server_one.start(RedirectTestApp("one")(), self.port_one)
|
||||
server_two.start(RedirectTestApp("two")(), self.port_two)
|
||||
self.client = client.BaseClient("127.0.0.1", self.port_one)
|
||||
|
||||
def test_get_without_redirect(self):
|
||||
|
@ -58,6 +58,8 @@ class TestRegistryDb(test_utils.BaseTestCase):
|
||||
super(TestRegistryDb, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
self.orig_engine = db_api._ENGINE
|
||||
self.orig_connection = db_api._CONNECTION
|
||||
self.orig_maker = db_api._MAKER
|
||||
|
||||
def test_bad_sql_connection(self):
|
||||
"""
|
||||
@ -70,8 +72,11 @@ class TestRegistryDb(test_utils.BaseTestCase):
|
||||
# We set this to None to trigger a reconfigure, otherwise
|
||||
# other modules may have already correctly configured the DB
|
||||
db_api._ENGINE = None
|
||||
db_api._CONNECTION = None
|
||||
db_api._MAKER = None
|
||||
db_api.setup_db_env()
|
||||
self.assertRaises((ImportError, exc.ArgumentError),
|
||||
db_api.configure_db)
|
||||
db_api.get_engine)
|
||||
exc_raised = False
|
||||
self.log_written = False
|
||||
|
||||
@ -82,6 +87,9 @@ class TestRegistryDb(test_utils.BaseTestCase):
|
||||
self.stubs.Set(db_api.LOG, 'error', fake_log_error)
|
||||
try:
|
||||
api_obj = rserver.API(routes.Mapper())
|
||||
api = test_utils.FakeAuthMiddleware(api_obj, is_admin=True)
|
||||
req = webob.Request.blank('/images/%s' % _gen_uuid())
|
||||
res = req.get_response(api)
|
||||
except exc.ArgumentError:
|
||||
exc_raised = True
|
||||
except ImportError:
|
||||
@ -94,6 +102,8 @@ class TestRegistryDb(test_utils.BaseTestCase):
|
||||
"""Clear the test environment"""
|
||||
super(TestRegistryDb, self).setUp()
|
||||
db_api._ENGINE = self.orig_engine
|
||||
db_api._CONNECTION = self.orig_connection
|
||||
db_api._MAKER = self.orig_maker
|
||||
self.stubs.UnsetAll()
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user