mirror of
				https://github.com/mail-in-a-box/mailinabox.git
				synced 2025-11-03 19:30:54 +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,12 +210,20 @@ 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')
 | 
				
			||||||
@ -329,6 +337,10 @@ 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.
 | 
				
			||||||
 | 
						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(25, True, env, 10)
 | 
				
			||||||
		wait_for_service(993, True, env, 10)
 | 
							wait_for_service(993, True, env, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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