Add manual backup option

This commit is contained in:
David Duque 2020-07-10 15:48:37 +01:00
parent 199c2c50ba
commit af9ef186b3
No known key found for this signature in database
GPG key ID: 2F327738A3C0AE3A
3 changed files with 61 additions and 7 deletions

View file

@ -10,7 +10,7 @@
import os, os.path, shutil, glob, re, datetime, sys
import dateutil.parser, dateutil.relativedelta, dateutil.tz
import rtyaml
from exclusiveprocess import Lock
from exclusiveprocess import Lock, CannotAcquireLock
from utils import load_environment, shell, wait_for_service, fix_boto
@ -20,7 +20,7 @@ rsync_ssh_options = [
]
def backup_status(env):
# If backups are dissbled, return no status.
# If backups are disabled, return no status.
config = get_backup_config(env)
if config["target"] == "off":
return { }
@ -210,13 +210,21 @@ def get_target_type(config):
protocol = config["target"].split(":")[0]
return protocol
def perform_backup(full_backup):
def perform_backup(full_backup, user_initiated=False):
env = load_environment()
# Create an global exclusive lock so that the backup script
# cannot be run more than one.
Lock(die=True).forever()
lock = Lock(die=(not user_initiated))
if user_initiated:
# God forgive me for what I'm about to do
try:
lock._acquire()
except CannotAcquireLock:
return "Another backup is already being done!"
else:
lock.forever()
config = get_backup_config(env)
backup_root = os.path.join(env["STORAGE_ROOT"], 'backup')
backup_cache_dir = os.path.join(backup_root, 'cache')
@ -329,8 +337,12 @@ def perform_backup(full_backup):
# backup. Since it checks that dovecot and postfix are running, block for a
# bit (maximum of 10 seconds each) to give each a chance to finish restarting
# before the status checks might catch them down. See #381.
wait_for_service(25, True, env, 10)
wait_for_service(993, True, env, 10)
if user_initiated:
# God forgive me for what I'm about to do
lock._release() # We don't need to restart the services
else:
wait_for_service(25, True, env, 10)
wait_for_service(993, True, env, 10)
def run_duplicity_verification():
env = load_environment()

View file

@ -509,6 +509,19 @@ def backup_set_custom():
request.form.get('min_age', '')
))
@app.route('/system/backup/new', methods=["POST"])
@authorized_personnel_only
def backup_new():
from backup import perform_backup, get_backup_config
# If backups are disabled, don't perform the backup
config = get_backup_config(env)
if config["target"] == "off":
return "Backups are disabled in this machine. Nothing was done."
msg = perform_backup(request.form.get('full', False) == 'true', True)
return "OK" if msg is None else msg
@app.route('/system/privacy', methods=["GET"])
@authorized_personnel_only
def privacy_status_get():

View file

@ -140,6 +140,10 @@
<tbody>
</tbody>
</table>
<button id="create-full-backup-button" class="btn btn-primary" onclick="do_backup(true)">Create Full Backup Now</button>
<button id="create-incremental-backup-button" class="btn btn-primary" onclick="do_backup(false)">Create Incremental Backup Now</button>
<script>
function toggle_form() {
@ -303,4 +307,29 @@ function init_inputs(target_type) {
set_host($('#backup-target-s3-host-select').val());
}
}
function do_backup(is_full) {
let disclaimer = "The backup process will pause some services (such as PHP, Postfix and Dovecot). Depending on the size of the data this can take a while."
if (!is_full) {
disclaimer += "\nDepending on the amount of incremental backups done after the last full backup, the box may decide to do a full backup instead."
}
show_modal_confirm("Warning!", disclaimer, "Start Backup", () => {
api(
"/system/backup/new",
"POST",
{
full: is_full
},
function(r) {
// use .text() --- it's a text response, not html
show_modal_error("Backup configuration", $("<p/>").text(r), function() { if (r == "OK") show_system_backup(); }); // refresh after modal on success
},
function(r) {
// use .text() --- it's a text response, not html
show_modal_error("Backup configuration", $("<p/>").text(r));
});
return false;
})
}
</script>