summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Lamar <brian.lamar@rackspace.com>2011-08-10 13:21:36 -0400
committerBrian Lamar <brian.lamar@rackspace.com>2011-08-10 13:21:36 -0400
commita46964ad11a85effa833decb81384b478a0cf75d (patch)
tree5799d53e98f972f3b7b7c82ea5fa57933c7791e9
parent44d4994eadc7413e27ebe60d7880278fc0365b6f (diff)
Allows multiple MySQL connections to be maintained using eventlet's db_pool.
-rw-r--r--nova/db/sqlalchemy/session.py92
-rw-r--r--nova/flags.py6
2 files changed, 74 insertions, 24 deletions
diff --git a/nova/db/sqlalchemy/session.py b/nova/db/sqlalchemy/session.py
index 4a9a28f43..726a801af 100644
--- a/nova/db/sqlalchemy/session.py
+++ b/nova/db/sqlalchemy/session.py
@@ -19,37 +19,81 @@
Session Handling for SQLAlchemy backend
"""
-from sqlalchemy import create_engine
-from sqlalchemy import pool
-from sqlalchemy.orm import sessionmaker
+import eventlet.patcher
+eventlet.patcher.monkey_patch()
-from nova import exception
-from nova import flags
+import eventlet.db_pool
+import sqlalchemy.orm
+import sqlalchemy.pool
+
+import nova.exception
+import nova.flags
+import nova.log
+
+
+FLAGS = nova.flags.FLAGS
+LOG = nova.log.getLogger("nova.db.sqlalchemy")
+
+
+try:
+ import MySQLdb
+except ImportError:
+ LOG.debug(_("Unable to load MySQLdb module."))
-FLAGS = flags.FLAGS
_ENGINE = None
_MAKER = None
def get_session(autocommit=True, expire_on_commit=False):
- """Helper method to grab session"""
- global _ENGINE
- global _MAKER
- if not _MAKER:
- if not _ENGINE:
- kwargs = {'pool_recycle': FLAGS.sql_idle_timeout,
- 'echo': False}
-
- if FLAGS.sql_connection.startswith('sqlite'):
- kwargs['poolclass'] = pool.NullPool
-
- _ENGINE = create_engine(FLAGS.sql_connection,
- **kwargs)
- _MAKER = (sessionmaker(bind=_ENGINE,
- autocommit=autocommit,
- expire_on_commit=expire_on_commit))
+ """Return a SQLAlchemy session."""
+ global _ENGINE, _MAKER
+
+ if _MAKER is None or _ENGINE is None:
+ _ENGINE = get_engine()
+ _MAKER = get_maker(_ENGINE, autocommit, expire_on_commit)
+
session = _MAKER()
- session.query = exception.wrap_db_error(session.query)
- session.flush = exception.wrap_db_error(session.flush)
+ session.query = nova.exception.wrap_db_error(session.query)
+ session.flush = nova.exception.wrap_db_error(session.flush)
return session
+
+
+def get_engine():
+ """Return a SQLAlchemy engine."""
+ connection_dict = sqlalchemy.engine.url.make_url(FLAGS.sql_connection)
+ engine_args = {
+ "pool_recycle": FLAGS.sql_idle_timeout,
+ "echo": False,
+ }
+
+ LOG.info(_("SQL connection: %s") % FLAGS.sql_connection)
+
+ if "sqlite" in connection_dict.drivername:
+ engine_args["poolclass"] = sqlalchemy.pool.NullPool
+
+ if "mysql" in connection_dict.drivername:
+ LOG.info(_("Using MySQL/eventlet DB connection pool."))
+ pool_args = {
+ "db": connection_dict.database,
+ "user": connection_dict.username,
+ "passwd": connection_dict.password,
+ "host": connection_dict.host,
+ "min_size": FLAGS.sql_min_pool_size,
+ "max_size": FLAGS.sql_max_pool_size,
+ "max_idle": FLAGS.sql_idle_timeout,
+ "max_age": FLAGS.sql_idle_timeout,
+ }
+ creator = eventlet.db_pool.ConnectionPool(MySQLdb, **pool_args)
+ engine_args["pool_size"] = FLAGS.sql_max_pool_size
+ engine_args["pool_timeout"] = FLAGS.sql_pool_timeout
+ engine_args["creator"] = creator.create
+
+ return sqlalchemy.create_engine(FLAGS.sql_connection, **engine_args)
+
+
+def get_maker(engine, autocommit=True, expire_on_commit=False):
+ """Return a SQLAlchemy sessionmaker using the given engine."""
+ return sqlalchemy.orm.sessionmaker(bind=engine,
+ autocommit=autocommit,
+ expire_on_commit=expire_on_commit)
diff --git a/nova/flags.py b/nova/flags.py
index eb6366ed9..fa5528c8c 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -345,6 +345,12 @@ DEFINE_string('logdir', None, 'output to a per-service log file in named '
'directory')
DEFINE_integer('logfile_mode', 0644, 'Default file mode of the logs.')
DEFINE_string('sqlite_db', 'nova.sqlite', 'file name for sqlite')
+DEFINE_integer('sql_pool_timeout', 30,
+ 'seconds to wait for connection from pool before erroring')
+DEFINE_integer('sql_min_pool_size', 10,
+ 'minimum number of SQL connections to pool')
+DEFINE_integer('sql_max_pool_size', 10,
+ 'maximum number of SQL connections to pool')
DEFINE_string('sql_connection',
'sqlite:///$state_path/$sqlite_db',
'connection string for sql database')