120 lines
3.2 KiB
Python
120 lines
3.2 KiB
Python
import datetime
|
|
import os
|
|
|
|
import frappe
|
|
from frappe import _
|
|
from frappe.utils import cint, get_site_path, get_url
|
|
from frappe.utils.data import convert_utc_to_system_timezone
|
|
|
|
|
|
def get_context(context):
|
|
def get_time(path):
|
|
dt = os.path.getmtime(path)
|
|
return convert_utc_to_system_timezone(datetime.datetime.utcfromtimestamp(dt)).strftime(
|
|
"%a %b %d %H:%M %Y"
|
|
)
|
|
|
|
def get_encrytion_status(path):
|
|
if "-enc" in path:
|
|
return True
|
|
|
|
def get_size(path):
|
|
size = os.path.getsize(path)
|
|
if size > 1048576:
|
|
return f"{float(size) / 1048576:.1f}M"
|
|
else:
|
|
return f"{float(size) / 1024:.1f}K"
|
|
|
|
path = get_site_path("private", "backups")
|
|
files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))]
|
|
backup_limit = get_scheduled_backup_limit()
|
|
|
|
if len(files) > backup_limit:
|
|
cleanup_old_backups(path, files, backup_limit)
|
|
|
|
files = [
|
|
(
|
|
"/backups/" + _file,
|
|
get_time(os.path.join(path, _file)),
|
|
get_encrytion_status(os.path.join(path, _file)),
|
|
get_size(os.path.join(path, _file)),
|
|
)
|
|
for _file in files
|
|
if _file.endswith("sql.gz")
|
|
]
|
|
files.sort(key=lambda x: x[1], reverse=True)
|
|
|
|
return {"files": files[:backup_limit]}
|
|
|
|
|
|
def get_scheduled_backup_limit():
|
|
backup_limit = frappe.db.get_singles_value("System Settings", "backup_limit")
|
|
return cint(backup_limit)
|
|
|
|
|
|
def cleanup_old_backups(site_path, files, limit):
|
|
backup_paths = []
|
|
for f in files:
|
|
if f.endswith("sql.gz"):
|
|
_path = os.path.abspath(os.path.join(site_path, f))
|
|
backup_paths.append(_path)
|
|
|
|
backup_paths = sorted(backup_paths, key=os.path.getctime)
|
|
files_to_delete = len(backup_paths) - limit
|
|
|
|
for idx in range(0, files_to_delete):
|
|
f = os.path.basename(backup_paths[idx])
|
|
files.remove(f)
|
|
|
|
os.remove(backup_paths[idx])
|
|
|
|
|
|
def delete_downloadable_backups():
|
|
path = get_site_path("private", "backups")
|
|
files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))]
|
|
backup_limit = get_scheduled_backup_limit()
|
|
|
|
if len(files) > backup_limit:
|
|
cleanup_old_backups(path, files, backup_limit)
|
|
|
|
|
|
@frappe.whitelist()
|
|
def schedule_files_backup(user_email):
|
|
from frappe.utils.background_jobs import enqueue, get_jobs
|
|
|
|
frappe.only_for("System Manager")
|
|
|
|
queued_jobs = get_jobs(site=frappe.local.site, queue="long")
|
|
method = "frappe.desk.page.backups.backups.backup_files_and_notify_user"
|
|
|
|
if method not in queued_jobs[frappe.local.site]:
|
|
enqueue(
|
|
"frappe.desk.page.backups.backups.backup_files_and_notify_user",
|
|
queue="long",
|
|
user_email=user_email,
|
|
)
|
|
frappe.msgprint(_("Queued for backup. You will receive an email with the download link"))
|
|
else:
|
|
frappe.msgprint(_("Backup job is already queued. You will receive an email with the download link"))
|
|
|
|
|
|
def backup_files_and_notify_user(user_email=None):
|
|
from frappe.utils.backups import backup
|
|
|
|
backup_files = backup(with_files=True)
|
|
get_downloadable_links(backup_files)
|
|
|
|
subject = _("File backup is ready")
|
|
frappe.sendmail(
|
|
recipients=[user_email],
|
|
subject=subject,
|
|
template="file_backup_notification",
|
|
args=backup_files,
|
|
header=[subject, "green"],
|
|
)
|
|
|
|
|
|
def get_downloadable_links(backup_files):
|
|
for key in ["backup_path_files", "backup_path_private_files"]:
|
|
path = backup_files[key]
|
|
backup_files[key] = get_url("/".join(path.split("/")[-2:]))
|