From fc304394f5501c6e326a67f768fbaf072c7a436b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 3 Aug 2018 18:50:15 -0400 Subject: [PATCH] Add convertdb command. Signed-off-by: Roberto Rosario --- HISTORY.rst | 7 +- .../common/management/commands/convertdb.py | 86 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 mayan/apps/common/management/commands/convertdb.py diff --git a/HISTORY.rst b/HISTORY.rst index 2972f4b45d..c9567eaeb6 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,4 +1,9 @@ -3.0.1 (208-07-08) +3.1 (2018-XX-XX) +================ +- Improve database vendor migration support +- Add convertdb management command. + +3.0.1 (2018-07-08) ================= - Pin javascript libraries to specific versions to avoid using potentianlly broken updates automatically. GitLab issue #486. diff --git a/mayan/apps/common/management/commands/convertdb.py b/mayan/apps/common/management/commands/convertdb.py new file mode 100644 index 0000000000..b2d4f19f6f --- /dev/null +++ b/mayan/apps/common/management/commands/convertdb.py @@ -0,0 +1,86 @@ +from __future__ import unicode_literals + +import errno +import os + +from pathlib import Path + +from django.conf import settings +from django.core import management +from django.core.management.base import CommandError +from django.utils.encoding import force_text +from django.utils.translation import ugettext_lazy as _ + +from common.utils import fs_cleanup +from documents.models import DocumentType + +CONVERTDB_FOLDER = 'convertdb' +CONVERTDB_OUTPUT_FILENAME = 'migrate.json' + + +class Command(management.BaseCommand): + help = 'Convert from a database backend to another one.' + + def add_arguments(self, parser): + parser.add_argument( + '--from', action='store', default='default', dest='from', + help=_( + 'The database from which data will be exported. If omitted ' + 'the database named "default" will be used.' + ), + ) + parser.add_argument( + '--to', action='store', default='default', dest='to', + help=_( + 'The database to which data will be imported. If omitted ' + 'the database named "default" will be used.' + ), + ) + parser.add_argument( + '--force', action='store_true', dest='force', + help=_( + 'Force the conversion of the database even if the receving ' + 'database is not empty.' + ), + ) + + def handle(self, *args, **options): + # Create the media/convertdb folder + convertdb_folder_path = force_text( + Path( + settings.MEDIA_ROOT, CONVERTDB_FOLDER + ) + ) + + try: + os.makedirs(convertdb_folder_path) + except OSError as exception: + if exception.errno == errno.EEXIST: + pass + + convertdb_file_path = force_text( + Path( + convertdb_folder_path, CONVERTDB_OUTPUT_FILENAME + ) + ) + + management.call_command( + 'dumpdata', all=True, database=options['from'], + natural_primary=True, natural_foreign=True, + output=convertdb_file_path, interactive=False, + indent=4, + ) + + if DocumentType.objects.using('default').count() and not options['force']: + fs_cleanup(convertdb_file_path) + raise CommandError( + 'There is existing data in the database that will be ' + 'used for the import. If you proceed with the conversion ' + 'you might lose data. Please check you settings.' + ) + + management.call_command( + 'loaddata', convertdb_file_path, database=options['to'], + interactive=False + ) + fs_cleanup(convertdb_file_path)