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 os, os.path, shutil, glob, re, datetime, sys
import dateutil.parser, dateutil.relativedelta, dateutil.tz import dateutil.parser, dateutil.relativedelta, dateutil.tz
import rtyaml import rtyaml
from exclusiveprocess import Lock from exclusiveprocess import Lock, CannotAcquireLock
from utils import load_environment, shell, wait_for_service, fix_boto from utils import load_environment, shell, wait_for_service, fix_boto
@ -20,7 +20,7 @@ rsync_ssh_options = [
] ]
def backup_status(env): def backup_status(env):
# If backups are dissbled, return no status. # If backups are disabled, return no status.
config = get_backup_config(env) config = get_backup_config(env)
if config["target"] == "off": if config["target"] == "off":
return { } return { }
@ -210,13 +210,21 @@ def get_target_type(config):
protocol = config["target"].split(":")[0] protocol = config["target"].split(":")[0]
return protocol return protocol
def perform_backup(full_backup): def perform_backup(full_backup, user_initiated=False):
env = load_environment() env = load_environment()
# Create an global exclusive lock so that the backup script # Create an global exclusive lock so that the backup script
# cannot be run more than one. # 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) config = get_backup_config(env)
backup_root = os.path.join(env["STORAGE_ROOT"], 'backup') backup_root = os.path.join(env["STORAGE_ROOT"], 'backup')
backup_cache_dir = os.path.join(backup_root, 'cache') 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 # 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 # bit (maximum of 10 seconds each) to give each a chance to finish restarting
# before the status checks might catch them down. See #381. # before the status checks might catch them down. See #381.
wait_for_service(25, True, env, 10) if user_initiated:
wait_for_service(993, True, env, 10) # 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(): def run_duplicity_verification():
env = load_environment() env = load_environment()

View File

@ -509,6 +509,19 @@ def backup_set_custom():
request.form.get('min_age', '') 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"]) @app.route('/system/privacy', methods=["GET"])
@authorized_personnel_only @authorized_personnel_only
def privacy_status_get(): def privacy_status_get():

View File

@ -140,6 +140,10 @@
<tbody> <tbody>
</tbody> </tbody>
</table> </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> <script>
function toggle_form() { function toggle_form() {
@ -303,4 +307,29 @@ function init_inputs(target_type) {
set_host($('#backup-target-s3-host-select').val()); 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> </script>