Fix cell0 naming when QS params on the connection

We had a problem when the nova connection string included parameters on the
query string like charset encoding.
Note that the connection string necessarly needs to be RFC1738 compliant as
per Sqlalchemy rules, so it's totally safe to just unquote what the SQLA
helper method gives us as a result.

Also removed a tested connection string since it wasn't RFC1738 compatible.

Change-Id: I45fe9b92e8d93a0099d33bb0070e9d4e540595ac
Closes-Bug: #1696001
(cherry picked from commit 9a33092fa9)
This commit is contained in:
Sylvain Bauza 2017-06-06 23:28:59 +02:00
parent 47774935ac
commit 6041572a4c
2 changed files with 12 additions and 14 deletions

View File

@ -1152,19 +1152,16 @@ class CellV2Commands(object):
# based on the database connection url.
# The cell0 database will use the same database scheme and
# netloc as the main database, with a related path.
# NOTE(sbauza): The URL has to be RFC1738 compliant in order to
# be usable by sqlalchemy.
connection = CONF.database.connection
# sqlalchemy has a nice utility for parsing database connection
# URLs so we use that here to get the db name so we don't have to
# worry about parsing and splitting a URL which could have special
# characters in the password, which makes parsing a nightmare.
url = sqla_url.make_url(connection)
cell0_db_name = url.database + '_cell0'
# We need to handle multiple occurrences of the substring, e.g. if
# the username and db name are both 'nova' we need to only replace
# the last one, which is the database name in the URL, not the
# username.
connection = connection.rstrip(url.database)
return connection + cell0_db_name
url.database = url.database + '_cell0'
return urlparse.unquote(str(url))
dbc = database_connection or cell0_default_connection()
ctxt = context.RequestContext()

View File

@ -1140,16 +1140,17 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
self.assertEqual('fake://netloc/nova_cell0',
cell_mapping.database_connection)
@ddt.data('mysql+pymysql://nova:abcd0123:AB@controller/nova',
'mysql+pymysql://nova:abcd0123?AB@controller/nova',
'mysql+pymysql://nova:abcd0123@AB@controller/nova',
'mysql+pymysql://nova:abcd0123/AB@controller/nova',
'mysql+pymysql://test:abcd0123%AB@controller/nova')
@ddt.data('mysql+pymysql://nova:abcd0123:AB@controller/%s',
'mysql+pymysql://nova:abcd0123?AB@controller/%s',
'mysql+pymysql://nova:abcd0123@AB@controller/%s',
'mysql+pymysql://nova:abcd0123/AB@controller/%s',
'mysql+pymysql://test:abcd0123/AB@controller/%s?charset=utf8')
def test_map_cell0_default_database_special_characters(self,
decoded_connection):
connection):
"""Tests that a URL with special characters, like in the credentials,
is handled properly.
"""
decoded_connection = connection % 'nova'
self.flags(connection=decoded_connection, group='database')
ctxt = context.RequestContext()
self.commands.map_cell0()
@ -1158,7 +1159,7 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
self.assertEqual('cell0', cell_mapping.name)
self.assertEqual('none:///', cell_mapping.transport_url)
self.assertEqual(
decoded_connection + '_cell0',
connection % 'nova_cell0',
cell_mapping.database_connection)
# Delete the cell mapping for the next iteration.
cell_mapping.destroy()