blob: 04a3bb36b887f72c7c6fe905d8bf412c0d6dffd8 [file] [log] [blame]
# -*- coding: utf-8 -*-
"""Migrations to update the path where logfiles are stored."""
# pylint: disable=invalid-name
import logging
import os
import shutil
from django.db import migrations
from django.conf import settings
from django.core.files.storage import default_storage
from crashreports.models import LogFile, crashreport_file_name
LOGGER = logging.getLogger(__name__)
def migrate_logfiles(apps, schema_editor):
"""Migrate the logfiles and update the logfile paths in the database."""
# pylint: disable=unused-argument
crashreport_uploads_dir = "crashreport_uploads"
if not LogFile.objects.filter(
logfile__startswith=crashreport_uploads_dir
).exists():
LOGGER.info(
"No old logfile path found. Assuming this is a new installation "
"and the migration does not need to be applied."
)
return
crashreport_uploads_legacy_dir = crashreport_uploads_dir + "_legacy"
assert not os.path.isdir(crashreport_uploads_legacy_dir), (
"Existing crashreport_uploads_legacy directory found. Remove this"
"directory in order to run this migration."
)
if os.path.isdir(crashreport_uploads_dir):
shutil.move(crashreport_uploads_dir, crashreport_uploads_legacy_dir)
for logfile in LogFile.objects.all():
migrate_logfile_instance(
logfile, crashreport_uploads_dir, crashreport_uploads_legacy_dir
)
def migrate_logfile_instance(
logfile, crashreport_uploads_dir, crashreport_uploads_legacy_dir
):
"""Migrate a single logfile instance."""
old_logfile_relative_path = logfile.logfile.name.replace(
crashreport_uploads_dir, crashreport_uploads_legacy_dir, 1
)
old_logfile_absolute_path = os.path.join(
settings.BASE_DIR, old_logfile_relative_path
)
new_logfile_path = crashreport_file_name(
logfile, os.path.basename(old_logfile_relative_path)
)
LOGGER.info("Migrating %s", old_logfile_absolute_path)
if os.path.isfile(old_logfile_absolute_path):
update_logfile_path(logfile, new_logfile_path)
move_logfile_file(old_logfile_absolute_path, new_logfile_path)
else:
LOGGER.warning("Logfile does not exist: %s", old_logfile_absolute_path)
def move_logfile_file(old_logfile_path, new_logfile_path):
"""Move a logfile to a new path and delete empty directories."""
new_logfile_absolute_path = default_storage.path(new_logfile_path)
LOGGER.debug("Creating directories for %s", new_logfile_absolute_path)
os.makedirs(os.path.dirname(new_logfile_absolute_path), exist_ok=True)
LOGGER.debug("Moving %s to %s", old_logfile_path, new_logfile_absolute_path)
shutil.move(old_logfile_path, new_logfile_absolute_path)
LOGGER.debug("Deleting empty directories from %s", old_logfile_path)
os.removedirs(os.path.dirname(old_logfile_path))
def update_logfile_path(logfile, new_logfile_path):
"""Update the path of a logfile database instance."""
LOGGER.debug(
"Changing logfile path in database from %s to %s",
logfile.logfile,
new_logfile_path,
)
logfile.logfile = new_logfile_path
logfile.save()
class Migration(migrations.Migration):
"""Run the migration script."""
dependencies = [
("crashreports", "0003_crashreport_and_heartbeat_with_radio_version")
]
operations = [migrations.RunPython(migrate_logfiles)]