summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander.sulfrian@fu-berlin.de>2015-09-17 16:23:53 +0200
committerAlexander Sulfrian <alexander.sulfrian@fu-berlin.de>2015-09-23 19:29:00 +0200
commiteae3cfb904c86f519d409724585eafcab99c74bd (patch)
tree5cc1f70748ac002346960b1c41dc70d2432cadec
parentc3f00276aba871f7809f202d5fff95564a9e7309 (diff)
downloadbcfg2-eae3cfb904c86f519d409724585eafcab99c74bd.tar.gz
bcfg2-eae3cfb904c86f519d409724585eafcab99c74bd.tar.bz2
bcfg2-eae3cfb904c86f519d409724585eafcab99c74bd.zip
DBSettings: Automatically upgrade migrations from south to django
On the first use with django-1.7 we manually get the south migration status and fake apply the django migration to that point. With that users can switch to django migrations at any point of time. The code simply takes the name of the last south migration and forwards the django migrations to that point. Therefor it is required to keep the names of the migrations in sync. It is required to keep the migration names of the two systems in sync.
-rw-r--r--src/lib/Bcfg2/DBSettings.py43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/DBSettings.py b/src/lib/Bcfg2/DBSettings.py
index a0ccb18a3..06988d6ef 100644
--- a/src/lib/Bcfg2/DBSettings.py
+++ b/src/lib/Bcfg2/DBSettings.py
@@ -157,6 +157,42 @@ def sync_databases(**kwargs):
**kwargs)
+def upgrade_to_django_migrations(database, logger):
+ """
+ Get the migration state from south and move django migrations to
+ the same state by fake applying the same migration.
+
+ Note: We cannot use south directly here, because this functions
+ runs on django-1.7 or higher, that is not supported by south.
+ """
+
+ last_migration = None
+ try:
+ # get latest south migration
+ cursor = django.db.connections[database].cursor()
+ cursor.cursor.execute('SELECT migration FROM south_migrationhistory')
+ applied_migrations = [name for (name,) in cursor.fetchall()]
+ last_migration = sorted(applied_migrations).pop()
+ except: # pylint: disable=W0702
+ # django.db.DatabaseError is not working here, because we are
+ # using the low level api to interact directly with the database
+ logger.debug("No south migration detected for database: %s." %
+ database)
+
+ if last_migration is not None:
+ # fake-apply matching django migrations
+ django.core.management.call_command(
+ "migrate", 'Reporting', last_migration,
+ database=database, fake=True)
+
+
+def initial_django_migration(database):
+ """ Check if we ever executed an initial django migration. """
+ from django.db.migrations import loader # pylint: disable=E0611
+ loader = loader.MigrationLoader(django.db.connections[database])
+ return len(loader.applied_migrations) == 0
+
+
def migrate_databases(**kwargs):
""" Do South migrations on all databases that we know about. """
logger = logging.getLogger()
@@ -164,6 +200,13 @@ def migrate_databases(**kwargs):
logger.debug("Migrating database %s" % (database))
if django.VERSION[0] == 1 and django.VERSION[1] >= 7:
django.setup() # pylint: disable=E1101
+ if initial_django_migration(database):
+ logger.warning(
+ "No applied django migrations found for database %s. "
+ "Trying to get the state from south migration in case "
+ "you just upgraded your django version." % database)
+ upgrade_to_django_migrations(database, logger)
+
django.core.management.call_command("migrate", database=database,
**kwargs)