mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-12-25 07:47:05 +00:00
Add manual backup option
This commit is contained in:
parent
199c2c50ba
commit
af9ef186b3
@ -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()
|
||||||
|
@ -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():
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user