diff options
author | Sean Dague <sdague@linux.vnet.ibm.com> | 2013-02-26 10:21:31 -0500 |
---|---|---|
committer | Sean Dague <sdague@linux.vnet.ibm.com> | 2013-03-04 13:38:50 -0500 |
commit | 2c3d38d88bce8fb2f6ed4fa55dbbc0115196f395 (patch) | |
tree | a359c2d48624807a348e766b38b15acad2fdffd4 | |
parent | bcdbe9ba881db8b38525bfc44a182e6b210459cd (diff) | |
download | nova-2c3d38d88bce8fb2f6ed4fa55dbbc0115196f395.tar.gz nova-2c3d38d88bce8fb2f6ed4fa55dbbc0115196f395.tar.xz nova-2c3d38d88bce8fb2f6ed4fa55dbbc0115196f395.zip |
fix postgresql drop race
when running under testr there is a chance that we enter
reset_databases for the postgresql tests at the same time for both
general and baremetal tests. In this case the pg admin commands
could fail, as pg gets really strict about having 2 users trying
to do admin commands at the same time on a single database (in
this case the magic template1 db, that we need to use because
you can't drop the db you are currently on.)
Solve this by breaking out the postgresql reset case into a
seperate function and using @lockutils on it.
Change-Id: I31555ef5aae27f31daf7cbbae61072a8d7deb255
-rw-r--r-- | nova/tests/test_migrations.py | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py index beb03b0aa..2cea6fe0d 100644 --- a/nova/tests/test_migrations.py +++ b/nova/tests/test_migrations.py @@ -1,6 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2010-2011 OpenStack Foundation +# Copyright 2012-2013 IBM Corp. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -44,18 +45,19 @@ import collections import commands import ConfigParser import datetime -import netaddr import os -import sqlalchemy -from sqlalchemy.dialects import postgresql -from sqlalchemy.dialects import sqlite -import sqlalchemy.exc import urlparse import uuid from migrate.versioning import repository +import netaddr +import sqlalchemy +from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects import sqlite +import sqlalchemy.exc import nova.db.sqlalchemy.migrate_repo +from nova.openstack.common import lockutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils from nova import test @@ -246,12 +248,36 @@ class BaseMigrationTestCase(test.TestCase): self._reset_databases() super(BaseMigrationTestCase, self).tearDown() + def execute_cmd(self, cmd=None): + status, output = commands.getstatusoutput(cmd) + LOG.debug(output) + self.assertEqual(0, status, + "Failed to run: %s\n%s" % (cmd, output)) + + @lockutils.synchronized('pgadmin', 'nova-', external=True) + def _reset_pg(self, conn_pieces): + (user, password, database, host) = \ + get_pgsql_connection_info(conn_pieces) + os.environ['PGPASSWORD'] = password + os.environ['PGUSER'] = user + # note(boris-42): We must create and drop database, we can't + # drop database which we have connected to, so for such + # operations there is a special database template1. + sqlcmd = ("psql -w -U %(user)s -h %(host)s -c" + " '%(sql)s' -d template1") + + sql = ("drop database if exists %(database)s;") % locals() + droptable = sqlcmd % locals() + self.execute_cmd(droptable) + + sql = ("create database %(database)s;") % locals() + createtable = sqlcmd % locals() + self.execute_cmd(createtable) + + os.unsetenv('PGPASSWORD') + os.unsetenv('PGUSER') + def _reset_databases(self): - def execute_cmd(cmd=None): - status, output = commands.getstatusoutput(cmd) - LOG.debug(output) - self.assertEqual(0, status, - "Failed to run: %s\n%s" % (cmd, output)) for key, engine in self.engines.items(): conn_string = self.test_databases[key] conn_pieces = urlparse.urlparse(conn_string) @@ -274,29 +300,9 @@ class BaseMigrationTestCase(test.TestCase): "create database %(database)s;") % locals() cmd = ("mysql -u \"%(user)s\" %(password)s -h %(host)s " "-e \"%(sql)s\"") % locals() - execute_cmd(cmd) + self.execute_cmd(cmd) elif conn_string.startswith('postgresql'): - # note(krtaylor): File creation problems with tests in - # venv using .pgpass authentication, changed to - # PGPASSWORD environment variable which is no longer - # planned to be deprecated - (user, password, database, host) = \ - get_pgsql_connection_info(conn_pieces) - os.environ['PGPASSWORD'] = password - os.environ['PGUSER'] = user - # note(boris-42): We must create and drop database, we can't - # drop database which we have connected to, so for such - # operations there is a special database template1. - sqlcmd = ("psql -w -U %(user)s -h %(host)s -c" - " '%(sql)s' -d template1") - sql = ("drop database if exists %(database)s;") % locals() - droptable = sqlcmd % locals() - execute_cmd(droptable) - sql = ("create database %(database)s;") % locals() - createtable = sqlcmd % locals() - execute_cmd(createtable) - os.unsetenv('PGPASSWORD') - os.unsetenv('PGUSER') + self._reset_pg(conn_pieces) def _test_mysql_opportunistically(self): # Test that table creation on mysql only builds InnoDB tables |