diff --git a/doc/source/dev/manual_install.rst b/doc/source/dev/manual_install.rst index 16fea5d0be..ea228ae7ab 100644 --- a/doc/source/dev/manual_install.rst +++ b/doc/source/dev/manual_install.rst @@ -71,7 +71,7 @@ List of packages to be installed: .. code-block:: bash $ sudo apt-get install build-essential libxslt1-dev qemu-utils mysql-client \ - git python-dev python-pexpect python-mysqldb libmysqlclient-dev + git python-dev python-pexpect python-pymysql libmysqlclient-dev Python settings --------------- @@ -254,7 +254,7 @@ Create the Trove database schema: - Connect to the storage backend (MySQL, PostgreSQL) - Create a database called `trove` (this database will be used for storing Trove ORM) - - Compose connection string. Example: mysql://:@:/ + - Compose connection string. Example: mysql+pymysql://:@:/ Initialize the database ======================= diff --git a/etc/trove/trove-conductor.conf.sample b/etc/trove/trove-conductor.conf.sample index 9399a5a1a4..964303ea84 100644 --- a/etc/trove/trove-conductor.conf.sample +++ b/etc/trove/trove-conductor.conf.sample @@ -27,7 +27,7 @@ control_exchange = trove #trace_sqlalchemy = True [database] -connection = mysql://root:e1a2c042c828d3566d0a@localhost/trove +connection = mysql+pymysql://root:e1a2c042c828d3566d0a@localhost/trove [oslo_messaging_rabbit] # The RabbitMQ broker address where a single node is used. (string value) diff --git a/etc/trove/trove-taskmanager.conf.sample b/etc/trove/trove-taskmanager.conf.sample index 57af2831b0..873ad40623 100644 --- a/etc/trove/trove-taskmanager.conf.sample +++ b/etc/trove/trove-taskmanager.conf.sample @@ -163,8 +163,8 @@ pydev_debug = disabled # SQLAlchemy connection string for the reference implementation # registry server. Any valid SQLAlchemy connection string is fine. # See: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/connections.html#sqlalchemy.create_engine -connection = mysql://root:e1a2c042c828d3566d0a@localhost/trove -# connection = mysql://root:root@localhost/trove +connection = mysql+pymysql://root:e1a2c042c828d3566d0a@localhost/trove +# connection = mysql+pymysql://root:root@localhost/trove # Period in seconds after which SQLAlchemy should reestablish its connection # to the database. diff --git a/etc/trove/trove.conf.sample b/etc/trove/trove.conf.sample index af81c8202d..6e4098bffb 100644 --- a/etc/trove/trove.conf.sample +++ b/etc/trove/trove.conf.sample @@ -146,7 +146,7 @@ api_paste_config = api-paste.ini # registry server. Any valid SQLAlchemy connection string is fine. # See: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/connections.html#sqlalchemy.create_engine # connection = sqlite:///trove_test.sqlite -connection = mysql://root:e1a2c042c828d3566d0a@localhost/trove +connection = mysql+pymysql://root:e1a2c042c828d3566d0a@localhost/trove #connection = postgresql://trove:trove@localhost/trove # Period in seconds after which SQLAlchemy should reestablish its connection diff --git a/etc/trove/trove.conf.test b/etc/trove/trove.conf.test index 72b0456931..e22b4c0b12 100644 --- a/etc/trove/trove.conf.test +++ b/etc/trove/trove.conf.test @@ -147,7 +147,7 @@ device_path = /dev/vdb # registry server. Any valid SQLAlchemy connection string is fine. # See: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/connections.html#sqlalchemy.create_engine connection = sqlite:///trove_test.sqlite -#connection = mysql://root:e1a2c042c828d3566d0a@localhost/trove +#connection = mysql+pymysql://root:e1a2c042c828d3566d0a@localhost/trove #connection = postgresql://trove:trove@localhost/trove # Period in seconds after which SQLAlchemy should reestablish its connection diff --git a/install-guide/source/common_configure.txt b/install-guide/source/common_configure.txt index d2c001d919..eef5b28848 100644 --- a/install-guide/source/common_configure.txt +++ b/install-guide/source/common_configure.txt @@ -15,7 +15,7 @@ notifier_queue_hostname = controller ... [database] - connection = mysql://trove:TROVE_DBPASS@controller/trove + connection = mysql+pymysql://trove:TROVE_DBPASS@controller/trove * Configure the Database service to use the ``RabbitMQ`` message broker by setting the following options in each file: @@ -98,7 +98,7 @@ # su -s /bin/sh -c "trove-manage db_sync" trove ... 2016-04-06 22:00:17.771 10706 INFO trove.db.sqlalchemy.migration [-] - Upgrading mysql://trove:dbaasdb@controller/trove to version latest + Upgrading mysql+pymysql://trove:dbaasdb@controller/trove to version latest .. note:: diff --git a/requirements.txt b/requirements.txt index 2d0da28af4..3a122f34f9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,7 +35,7 @@ oslo.serialization>=1.10.0 # Apache-2.0 oslo.service>=1.10.0 # Apache-2.0 oslo.utils>=3.11.0 # Apache-2.0 oslo.concurrency>=3.8.0 # Apache-2.0 -MySQL-python;python_version=='2.7' # GPL with FOSS exception +PyMySQL>=0.6.2 # MIT License Babel>=2.3.4 # BSD six>=1.9.0 # MIT stevedore>=1.10.0 # Apache-2.0 diff --git a/trove/db/sqlalchemy/migrate_repo/versions/026_datastore_versions_unique_fix.py b/trove/db/sqlalchemy/migrate_repo/versions/026_datastore_versions_unique_fix.py index daa9ea8896..364b358456 100644 --- a/trove/db/sqlalchemy/migrate_repo/versions/026_datastore_versions_unique_fix.py +++ b/trove/db/sqlalchemy/migrate_repo/versions/026_datastore_versions_unique_fix.py @@ -14,6 +14,7 @@ from migrate.changeset import UniqueConstraint from oslo_log import log as logging +from sqlalchemy.exc import InternalError from sqlalchemy.exc import OperationalError from sqlalchemy.schema import MetaData @@ -38,7 +39,7 @@ def upgrade(migrate_engine): if uc: try: uc.drop() - except OperationalError as e: + except (OperationalError, InternalError) as e: logger.info(e) diff --git a/trove/guestagent/datastore/experimental/pxc/service.py b/trove/guestagent/datastore/experimental/pxc/service.py index 8c541c5277..3d55e94827 100644 --- a/trove/guestagent/datastore/experimental/pxc/service.py +++ b/trove/guestagent/datastore/experimental/pxc/service.py @@ -56,8 +56,8 @@ class PXCApp(galera_service.GaleraApp): LOG.info(_("Generating admin password.")) admin_password = utils.generate_random_password() mysql_service.clear_expired_password() - engine = sqlalchemy.create_engine("mysql://root:@localhost:3306", - echo=True) + uri = "mysql+pymysql://root:@localhost:3306" + engine = sqlalchemy.create_engine(uri, echo=True) with self.local_sql_client(engine) as client: self._remove_anonymous_user(client) self._create_admin_user(client, admin_password) diff --git a/trove/guestagent/datastore/galera_common/service.py b/trove/guestagent/datastore/galera_common/service.py index e286609372..ba0039cc2d 100644 --- a/trove/guestagent/datastore/galera_common/service.py +++ b/trove/guestagent/datastore/galera_common/service.py @@ -37,8 +37,8 @@ class GaleraApp(service.BaseMySqlApp): keep_alive_connection_cls) def _test_mysql(self): - engine = sqlalchemy.create_engine("mysql://root:@localhost:3306", - echo=True) + uri = "mysql+pymysql://root:@localhost:3306" + engine = sqlalchemy.create_engine(uri, echo=True) try: with self.local_sql_client(engine) as client: out = client.execute(text("select 1;")) diff --git a/trove/guestagent/datastore/mysql_common/service.py b/trove/guestagent/datastore/mysql_common/service.py index fa12ee0a58..8f30f38673 100644 --- a/trove/guestagent/datastore/mysql_common/service.py +++ b/trove/guestagent/datastore/mysql_common/service.py @@ -606,8 +606,9 @@ class BaseMySqlApp(object): return ENGINE pwd = self.get_auth_password() - ENGINE = sqlalchemy.create_engine("mysql://%s:%s@localhost:3306" % - (ADMIN_USER_NAME, pwd.strip()), + uri = ("mysql+pymysql://%s:%s@localhost:3306" + % (ADMIN_USER_NAME, pwd.strip())) + ENGINE = sqlalchemy.create_engine(uri, pool_recycle=7200, echo=CONF.sql_query_logging, listeners=[ @@ -682,8 +683,8 @@ class BaseMySqlApp(object): LOG.info(_("Generating admin password.")) admin_password = utils.generate_random_password() clear_expired_password() - engine = sqlalchemy.create_engine("mysql://root:@localhost:3306", - echo=True) + uri = "mysql+pymysql://root:@localhost:3306" + engine = sqlalchemy.create_engine(uri, echo=True) with self.local_sql_client(engine) as client: self._remove_anonymous_user(client) self._create_admin_user(client, admin_password) @@ -1037,7 +1038,7 @@ class BaseMySqlRootAccess(object): cu = sql_query.CreateUser(user.name, host=user.host) t = text(str(cu)) client.execute(t, **cu.keyArgs) - except exc.OperationalError as err: + except (exc.OperationalError, exc.InternalError) as err: # Ignore, user is already created, just reset the password # TODO(rnirmal): More fine grained error checking later on LOG.debug(err) diff --git a/trove/tests/db/migrations.py b/trove/tests/db/migrations.py index fe10a8be1e..dcca35f9f5 100644 --- a/trove/tests/db/migrations.py +++ b/trove/tests/db/migrations.py @@ -150,7 +150,7 @@ class TestTroveMigrations(object): @test def test_mysql_migration(self): - db_backend = "mysql+mysqldb" + db_backend = "mysql+pymysql" # Gracefully skip this test if the developer do not have # MySQL running. MySQL should always be available on # the infrastructure diff --git a/trove/tests/unittests/guestagent/test_dbmodels.py b/trove/tests/unittests/guestagent/test_dbmodels.py index 1fc76699a8..b9bea43d03 100644 --- a/trove/tests/unittests/guestagent/test_dbmodels.py +++ b/trove/tests/unittests/guestagent/test_dbmodels.py @@ -40,7 +40,7 @@ class MySQLDatabaseTest(trove_testtools.TestCase): self.assertEqual(test_name, self.mysqlDb.name) def test_is_valid_positive(self): - self.assertTrue(self.mysqlDb._is_valid('mysqldb')) + self.assertTrue(self.mysqlDb._is_valid('pymysql')) def test_is_valid_negative(self): self.assertFalse(self.mysqlDb._is_valid('mysql')) diff --git a/trove/tests/util/__init__.py b/trove/tests/util/__init__.py index 934f1f090a..f452933658 100644 --- a/trove/tests/util/__init__.py +++ b/trove/tests/util/__init__.py @@ -295,6 +295,6 @@ class LocalSqlClient(object): @staticmethod def init_engine(user, password, host): - return create_engine("mysql://%s:%s@%s:3306" % + return create_engine("mysql+pymysql://%s:%s@%s:3306" % (user, password, host), pool_recycle=1800, echo=True) diff --git a/trove/tests/util/mysql.py b/trove/tests/util/mysql.py index 95bc9b65e8..218e3910a0 100644 --- a/trove/tests/util/mysql.py +++ b/trove/tests/util/mysql.py @@ -115,7 +115,7 @@ class SqlAlchemyConnection(object): @staticmethod def _init_engine(user, password, host): return session.EngineFacade( - "mysql://%s:%s@%s:3306" % (user, password, host), + "mysql+pymysql://%s:%s@%s:3306" % (user, password, host), pool_recycle=1800, echo=True ).get_engine()