storage: always use get_connection_from_config()

There's no way to connect to a backend only using an URL, because of
parameters such as mongodb_replicaset, etc. So we just remove
get_connection(url) function and always relies on
get_connection_from_config(conf).

Change-Id: I39fabbc78325709150dc7f4edb474c7bd9501205
This commit is contained in:
Julien Danjou 2015-07-24 15:48:21 +02:00
parent 3a05f31288
commit f2708b4ad2
6 changed files with 76 additions and 71 deletions

View File

@ -91,23 +91,20 @@ def get_connection_from_config(conf):
# Convert retry_interval secs to msecs for retry decorator
@retrying.retry(wait_fixed=conf.database.retry_interval * 1000,
stop_max_attempt_number=retries if retries >= 0 else None)
def _inner():
return get_connection(conf.database.connection)
def _get_connection():
"""Return an open connection to the database."""
url = conf.database.connection
connection_scheme = urlparse.urlparse(url).scheme
# SQLAlchemy connections specify may specify a 'dialect' or
# 'dialect+driver'. Handle the case where driver is specified.
engine_name = connection_scheme.split('+')[0]
# NOTE: translation not applied bug #1446983
LOG.debug('looking for %(name)r driver in %(namespace)r',
{'name': engine_name, 'namespace': _NAMESPACE})
mgr = driver.DriverManager(_NAMESPACE, engine_name)
return mgr.driver(conf, url)
return _inner()
def get_connection(url):
"""Return an open connection to the database."""
connection_scheme = urlparse.urlparse(url).scheme
# SqlAlchemy connections specify may specify a 'dialect' or
# 'dialect+driver'. Handle the case where driver is specified.
engine_name = connection_scheme.split('+')[0]
# NOTE: translation not applied bug #1446983
LOG.debug('looking for %(name)r driver in %(namespace)r',
{'name': engine_name, 'namespace': _NAMESPACE})
mgr = driver.DriverManager(_NAMESPACE, engine_name)
return mgr.driver(cfg.CONF, url)
return _get_connection()
class SampleFilter(object):

View File

@ -39,8 +39,8 @@ except ImportError:
class MongoDbManager(fixtures.Fixture):
def __init__(self, url):
self._url = url
def __init__(self, conf):
self.conf = conf
def setUp(self):
super(MongoDbManager, self).setUp()
@ -48,67 +48,63 @@ class MongoDbManager(fixtures.Fixture):
warnings.filterwarnings(
action='ignore',
message='.*you must provide a username and password.*')
self.conf.set_override("connection",
'%(url)s_%(db)s' % {
'url': self.conf.database.connection,
'db': uuid.uuid4().hex,
}, "database")
try:
self.alarm_connection = storage.get_connection(
self.url)
self.alarm_connection = storage.get_connection_from_config(
self.conf)
except storage.StorageBadVersion as e:
raise testcase.TestSkipped(six.text_type(e))
@property
def url(self):
return '%(url)s_%(db)s' % {
'url': self._url,
'db': uuid.uuid4().hex
}
class SQLManager(fixtures.Fixture):
def __init__(self, conf):
self.conf = conf
db_name = 'aodh_%s' % uuid.uuid4().hex
self._engine = sqlalchemy.create_engine(conf.database.connection)
self._conn = self._engine.connect()
self._create_db(self._conn, db_name)
self.url = conf.database.connection.replace(
self.url_dbname_placeholder, db_name)
self.conf.set_override("connection", self.url, "database")
self._conn.close()
self._engine.dispose()
def setUp(self):
super(SQLManager, self).setUp()
self.alarm_connection = storage.get_connection(
self.url)
@property
def url(self):
return self._url.replace('template1', self._db_name)
self.alarm_connection = storage.get_connection_from_config(self.conf)
class PgSQLManager(SQLManager):
def __init__(self, url):
self._url = url
self._db_name = 'aodh_%s' % uuid.uuid4().hex
self._engine = sqlalchemy.create_engine(self._url)
self._conn = self._engine.connect()
self._conn.connection.set_isolation_level(0)
self._conn.execute(
'CREATE DATABASE %s WITH TEMPLATE template0;' % self._db_name)
self._conn.connection.set_isolation_level(1)
self._conn.close()
self._engine.dispose()
url_dbname_placeholder = 'template1'
@staticmethod
def _create_db(conn, db_name):
conn.connection.set_isolation_level(0)
conn.execute('CREATE DATABASE %s WITH TEMPLATE template0;' % db_name)
conn.connection.set_isolation_level(1)
class MySQLManager(SQLManager):
def __init__(self, url):
self._url = url
self._db_name = 'aodh_%s' % uuid.uuid4().hex
self._engine = sqlalchemy.create_engine(
self._url.replace('template1', ''))
self._conn = self._engine.connect()
self._conn.execute('CREATE DATABASE %s;' % self._db_name)
self._conn.close()
self._engine.dispose()
url_dbname_placeholder = 'test'
@staticmethod
def _create_db(conn, db_name):
conn.execute('CREATE DATABASE %s;' % db_name)
class HBaseManager(fixtures.Fixture):
def __init__(self, url):
self._url = url
def __init__(self, conf):
self.conf = conf
def setUp(self):
super(HBaseManager, self).setUp()
self.alarm_connection = storage.get_connection(
self.url)
self.alarm_connection = storage.get_connection_from_config(self.conf)
# Unique prefix for each test to keep data is distinguished because
# all test data is stored in one table
data_prefix = str(uuid.uuid4().hex)
@ -139,13 +135,12 @@ class HBaseManager(fixtures.Fixture):
class SQLiteManager(fixtures.Fixture):
def __init__(self, url):
self.url = url
def __init__(self, conf):
self.conf = conf
def setUp(self):
super(SQLiteManager, self).setUp()
self.alarm_connection = storage.get_connection(
self.url)
self.alarm_connection = storage.get_connection_from_config(self.conf)
class TestBase(testscenarios.testcase.WithScenarios, test_base.BaseTestCase):
@ -179,9 +174,10 @@ class TestBase(testscenarios.testcase.WithScenarios, test_base.BaseTestCase):
import aodh.service # noqa
self.CONF = self.useFixture(fixture_config.Config()).conf
self.CONF([], project='aodh', validate_default_values=True)
self.CONF.set_override('connection', self.db_url, group="database")
try:
self.db_manager = self._get_driver_manager(engine)(self.db_url)
self.db_manager = self._get_driver_manager(engine)(self.CONF)
except ValueError as exc:
self.skipTest("missing driver manager: %s" % exc)
self.useFixture(self.db_manager)
@ -189,15 +185,16 @@ class TestBase(testscenarios.testcase.WithScenarios, test_base.BaseTestCase):
self.alarm_conn = self.db_manager.alarm_connection
self.alarm_conn.upgrade()
self.useFixture(mockpatch.Patch('aodh.storage.get_connection',
side_effect=self._get_connection))
self.useFixture(mockpatch.Patch(
'aodh.storage.get_connection_from_config',
side_effect=self._get_connection))
def tearDown(self):
self.alarm_conn.clear()
self.alarm_conn = None
super(TestBase, self).tearDown()
def _get_connection(self, url):
def _get_connection(self, conf):
return self.alarm_conn
def _get_driver_manager(self, engine):

View File

@ -26,13 +26,22 @@ import six
class EngineTest(base.BaseTestCase):
def setUp(self):
super(EngineTest, self).setUp()
self.CONF = self.useFixture(fixture_config.Config()).conf
def test_get_connection(self):
engine = storage.get_connection('log://localhost')
self.CONF.set_override('connection', 'log://localhost',
group='database')
engine = storage.get_connection_from_config(self.CONF)
self.assertIsInstance(engine, impl_log.Connection)
def test_get_connection_no_such_engine(self):
self.CONF.set_override('connection', 'no-such-engine://localhost',
group='database')
self.CONF.set_override('max_retries', 0, 'database')
try:
storage.get_connection('no-such-engine://localhost')
storage.get_connection_from_config(self.CONF)
except RuntimeError as err:
self.assertIn('no-such-engine', six.text_type(err))

View File

@ -30,11 +30,12 @@ from aodh.tests import db as tests_db
class MongoDBConnection(tests_db.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_connection_pooling(self):
test_conn = impl_mongodb.Connection(self.CONF, self.db_manager.url)
test_conn = impl_mongodb.Connection(self.CONF,
self.CONF.database.connection)
self.assertEqual(self.alarm_conn.conn, test_conn.conn)
def test_replica_set(self):
url = self.db_manager._url + '?replicaSet=foobar'
url = self.CONF.database.connection + '?replicaSet=foobar'
conn = impl_mongodb.Connection(self.CONF, url)
self.assertTrue(conn.conn)

View File

@ -22,7 +22,7 @@ mkfifo ${MYSQL_DATA}/out
mysqld --datadir=${MYSQL_DATA} --pid-file=${MYSQL_DATA}/mysql.pid --socket=${MYSQL_DATA}/mysql.socket --skip-networking --skip-grant-tables &> ${MYSQL_DATA}/out &
# Wait for MySQL to start listening to connections
wait_for_line "mysqld: ready for connections." ${MYSQL_DATA}/out
export AODH_TEST_MYSQL_URL="mysql+pymysql://root@localhost/template1?unix_socket=${MYSQL_DATA}/mysql.socket&charset=utf8"
export AODH_TEST_MYSQL_URL="mysql+pymysql://root@localhost/test?unix_socket=${MYSQL_DATA}/mysql.socket&charset=utf8"
# Yield execution to venv command
$*

View File

@ -24,7 +24,8 @@ def main(argv):
url = ("%s?table_prefix=%s" %
(os.getenv("AODH_TEST_HBASE_URL"),
os.getenv("AODH_TEST_HBASE_TABLE_PREFIX", "test")))
alarm_conn = storage.get_connection(url)
cfg.CONF.set_override("connection", url, group="database")
alarm_conn = storage.get_connection_from_conf(cfg.CONF)
for arg in argv:
if arg == "--upgrade":
alarm_conn.upgrade()