99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
import time
|
|
from abc import ABC, abstractmethod
|
|
import gzip
|
|
import subprocess
|
|
import uuid
|
|
from typing import Any
|
|
|
|
from .models import DB, DBBackup
|
|
# https://medium.com/poka-techblog/5-different-ways-to-backup-your-postgresql-database-using-python-3f06cea4f51
|
|
|
|
|
|
class BackupEngineBase(ABC):
|
|
def __init__(self, backupdb: DBBackup):
|
|
self.backup_instance = backupdb
|
|
self.db_instance = self.backup_instance.db
|
|
|
|
# self.db_instance = db_instance
|
|
# self.backup_instance = BackupDB.objects.create(
|
|
# db=self.db_instance,
|
|
# rel_path="{db_id}-{timestamp}-{rand_gen}.{db_type}.{ext}".format(
|
|
# db_id=self.db_instance.id,
|
|
# timestamp=int(time.time()),
|
|
# rand_gen=uuid.uuid4().hex[:5],
|
|
# db_type=self.db_instance.db_type,
|
|
# ext='sql.gz' if self.gzip else 'sql'
|
|
# ),
|
|
# )
|
|
self.credentials = {"database": self.db_instance.db_name, **self.db_instance.credential.credentials}
|
|
|
|
@property
|
|
@abstractmethod
|
|
def cmd_kwargs(self) -> dict[str, Any]:
|
|
...
|
|
|
|
@property
|
|
def format_cmd_kwargs(self):
|
|
return " ".join([
|
|
key if isinstance(value, bool) else f"{key} {value}"
|
|
for key, value in self.cmd_kwargs.items()
|
|
if value
|
|
])
|
|
|
|
@property
|
|
@abstractmethod
|
|
def cmd(self):
|
|
...
|
|
|
|
@property
|
|
def cmd_format(self):
|
|
return self.cmd.format(cmd_kwargs=self.format_cmd_kwargs, **self.credentials)
|
|
|
|
def popen(self):
|
|
return subprocess.Popen(self.cmd_format,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
shell=True,
|
|
universal_newlines=True)
|
|
|
|
def file_obj(self, path):
|
|
return gzip.open(path, "wb")
|
|
|
|
def run(self, task_id=None):
|
|
self.backup_instance.update_task_id(task_id)
|
|
try:
|
|
with self.file_obj(self.backup_instance.abs_path) as f:
|
|
with self.popen() as proc:
|
|
self.backup_instance.update_status("running")
|
|
for line in iter(proc.stdout.readline, ""):
|
|
f.write(line.encode())
|
|
except Exception as e:
|
|
self.backup_instance.update_status("finished")
|
|
raise e
|
|
|
|
|
|
class MySQLBackupEngine(BackupEngineBase):
|
|
@property
|
|
def cmd_kwargs(self) -> dict[str, Any]:
|
|
return {
|
|
"--no-tablespaces": True
|
|
}
|
|
|
|
@property
|
|
def cmd(self):
|
|
return "mysqldump {cmd_kwargs} -h {host} -P {port} -u {user} -p{password} {database}"
|
|
|
|
|
|
class PostgreSQLBackupEngine(BackupEngineBase):
|
|
@property
|
|
def cmd_kwargs(self) -> dict[str, Any]:
|
|
return {
|
|
"--no-owner": True,
|
|
"--no-privileges": True,
|
|
"--clean": False
|
|
}
|
|
|
|
@property
|
|
def cmd(self):
|
|
return "pg_dump {cmd_kwargs} --dbname=postgresql://{user}:{password}@{host}:{port}/{database}"
|