Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | |
| 3 | """Migrations to update the path where logfiles are stored.""" |
| 4 | # pylint: disable=invalid-name |
| 5 | |
| 6 | import logging |
| 7 | import os |
| 8 | import shutil |
| 9 | |
| 10 | from django.db import migrations |
| 11 | from django.conf import settings |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 12 | from django.core.files.storage import default_storage |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 13 | |
| 14 | from crashreports.models import LogFile, crashreport_file_name |
| 15 | |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 16 | LOGGER = logging.getLogger(__name__) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 17 | |
| 18 | |
| 19 | def migrate_logfiles(apps, schema_editor): |
| 20 | """Migrate the logfiles and update the logfile paths in the database.""" |
| 21 | # pylint: disable=unused-argument |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 22 | crashreport_uploads_dir = "crashreport_uploads" |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 23 | |
| 24 | if not LogFile.objects.filter( |
| 25 | logfile__startswith=crashreport_uploads_dir |
| 26 | ).exists(): |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 27 | LOGGER.info( |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 28 | "No old logfile path found. Assuming this is a new installation " |
| 29 | "and the migration does not need to be applied." |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 30 | ) |
| 31 | return |
| 32 | |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 33 | crashreport_uploads_legacy_dir = crashreport_uploads_dir + "_legacy" |
| 34 | assert not os.path.isdir(crashreport_uploads_legacy_dir), ( |
| 35 | "Existing crashreport_uploads_legacy directory found. Remove this" |
| 36 | "directory in order to run this migration." |
| 37 | ) |
| 38 | |
| 39 | if os.path.isdir(crashreport_uploads_dir): |
| 40 | shutil.move(crashreport_uploads_dir, crashreport_uploads_legacy_dir) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 41 | |
| 42 | for logfile in LogFile.objects.all(): |
| 43 | migrate_logfile_instance( |
| 44 | logfile, crashreport_uploads_dir, crashreport_uploads_legacy_dir |
| 45 | ) |
| 46 | |
| 47 | |
| 48 | def migrate_logfile_instance( |
| 49 | logfile, crashreport_uploads_dir, crashreport_uploads_legacy_dir |
| 50 | ): |
| 51 | """Migrate a single logfile instance.""" |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 52 | old_logfile_relative_path = logfile.logfile.name.replace( |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 53 | crashreport_uploads_dir, crashreport_uploads_legacy_dir, 1 |
| 54 | ) |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 55 | old_logfile_absolute_path = os.path.join( |
| 56 | settings.BASE_DIR, old_logfile_relative_path |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 57 | ) |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 58 | new_logfile_path = crashreport_file_name( |
| 59 | logfile, os.path.basename(old_logfile_relative_path) |
| 60 | ) |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 61 | LOGGER.info("Migrating %s", old_logfile_absolute_path) |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 62 | if os.path.isfile(old_logfile_absolute_path): |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 63 | update_logfile_path(logfile, new_logfile_path) |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 64 | move_logfile_file(old_logfile_absolute_path, new_logfile_path) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 65 | else: |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 66 | LOGGER.warning("Logfile does not exist: %s", old_logfile_absolute_path) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 67 | |
| 68 | |
| 69 | def move_logfile_file(old_logfile_path, new_logfile_path): |
| 70 | """Move a logfile to a new path and delete empty directories.""" |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 71 | new_logfile_absolute_path = default_storage.path(new_logfile_path) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 72 | |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 73 | LOGGER.debug("Creating directories for %s", new_logfile_absolute_path) |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 74 | os.makedirs(os.path.dirname(new_logfile_absolute_path), exist_ok=True) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 75 | |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 76 | LOGGER.debug("Moving %s to %s", old_logfile_path, new_logfile_absolute_path) |
Franz-Xaver Geiger | 38a66bc | 2018-10-09 14:52:26 +0200 | [diff] [blame] | 77 | shutil.move(old_logfile_path, new_logfile_absolute_path) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 78 | |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 79 | LOGGER.debug("Deleting empty directories from %s", old_logfile_path) |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 80 | os.removedirs(os.path.dirname(old_logfile_path)) |
| 81 | |
| 82 | |
| 83 | def update_logfile_path(logfile, new_logfile_path): |
| 84 | """Update the path of a logfile database instance.""" |
Mitja Nikolaus | 88cc94e | 2018-11-23 13:47:22 +0100 | [diff] [blame] | 85 | LOGGER.debug( |
Mitja Nikolaus | 6820ad0 | 2018-10-05 09:58:18 +0200 | [diff] [blame] | 86 | "Changing logfile path in database from %s to %s", |
| 87 | logfile.logfile, |
| 88 | new_logfile_path, |
| 89 | ) |
| 90 | |
| 91 | logfile.logfile = new_logfile_path |
| 92 | logfile.save() |
| 93 | |
| 94 | |
| 95 | class Migration(migrations.Migration): |
| 96 | """Run the migration script.""" |
| 97 | |
| 98 | dependencies = [ |
| 99 | ("crashreports", "0003_crashreport_and_heartbeat_with_radio_version") |
| 100 | ] |
| 101 | |
| 102 | operations = [migrations.RunPython(migrate_logfiles)] |