1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
"""
Command for backup database.
"""
from django.core.management.base import CommandError
from ... import settings, utils
from ...db.base import get_connector
from ...storage import StorageError, get_storage
from ._base import BaseDbBackupCommand, make_option
class Command(BaseDbBackupCommand):
help = "Backup a database, encrypt and/or compress."
content_type = "db"
option_list = BaseDbBackupCommand.option_list + (
make_option(
"-c",
"--clean",
dest="clean",
action="store_true",
default=False,
help="Clean up old backup files",
),
make_option(
"-d",
"--database",
help="Database(s) to backup specified by key separated by"
" commas(default: all)",
),
make_option(
"-s",
"--servername",
help="Specify server name to include in backup filename",
),
make_option(
"-z",
"--compress",
action="store_true",
default=False,
help="Compress the backup files",
),
make_option(
"-e",
"--encrypt",
action="store_true",
default=False,
help="Encrypt the backup files",
),
make_option(
"-o", "--output-filename", default=None, help="Specify filename on storage"
),
make_option(
"-O",
"--output-path",
default=None,
help="Specify where to store on local filesystem",
),
make_option(
"-x", "--exclude-tables", default=None, help="Exclude tables from backup"
),
make_option(
"-n",
"--schema",
action="append",
default=[],
help="Specify schema(s) to backup. Can be used multiple times.",
),
)
@utils.email_uncaught_exception
def handle(self, **options):
self.verbosity = options.get("verbosity")
self.quiet = options.get("quiet")
self._set_logger_level()
self.clean = options.get("clean")
self.servername = options.get("servername")
self.compress = options.get("compress")
self.encrypt = options.get("encrypt")
self.filename = options.get("output_filename")
self.path = options.get("output_path")
self.exclude_tables = options.get("exclude_tables")
self.storage = get_storage()
self.schemas = options.get("schema")
self.database = options.get("database") or ""
for database_key in self._get_database_keys():
self.connector = get_connector(database_key)
if self.connector and self.exclude_tables:
self.connector.exclude.extend(
list(self.exclude_tables.replace(" ", "").split(","))
)
database = self.connector.settings
try:
self._save_new_backup(database)
if self.clean:
self._cleanup_old_backups(database=database_key)
except StorageError as err:
raise CommandError(err) from err
def _get_database_keys(self):
return self.database.split(",") if self.database else settings.DATABASES
def _save_new_backup(self, database):
"""
Save a new backup file.
"""
self.logger.info("Backing Up Database: %s", database["NAME"])
# Get backup, schema and name
filename = self.connector.generate_filename(self.servername)
if self.schemas:
self.connector.schemas = self.schemas
outputfile = self.connector.create_dump()
# Apply trans
if self.compress:
compressed_file, filename = utils.compress_file(outputfile, filename)
outputfile = compressed_file
if self.encrypt:
encrypted_file, filename = utils.encrypt_file(outputfile, filename)
outputfile = encrypted_file
# Set file name
filename = self.filename or filename
self.logger.debug("Backup size: %s", utils.handle_size(outputfile))
# Store backup
outputfile.seek(0)
if self.path is None:
self.write_to_storage(outputfile, filename)
else:
self.write_local_file(outputfile, self.path)
|