summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Dague <sdague@linux.vnet.ibm.com>2013-02-26 10:21:31 -0500
committerSean Dague <sdague@linux.vnet.ibm.com>2013-03-04 13:38:50 -0500
commit2c3d38d88bce8fb2f6ed4fa55dbbc0115196f395 (patch)
treea359c2d48624807a348e766b38b15acad2fdffd4
parentbcdbe9ba881db8b38525bfc44a182e6b210459cd (diff)
downloadnova-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.py70
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