diff --git a/Vagrantfile b/Vagrantfile index 2d6d3a0d..9d3b3c29 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,12 +1,11 @@ + # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| - # Recreate our conditions - config.vm.box = "generic/debian10" - config.vm.provider "hyperv" do |v| - v.memory = 1024 - v.cpus = 1 + config.vm.box = "ubuntu/focal64" + config.vm.provider :virtualbox do |vb| + vb.customize ["modifyvm", :id, "--cpus", 1, "--memory", 1024] end # Network config: Since it's a mail server, the machine must be connected @@ -24,24 +23,9 @@ Vagrant.configure("2") do |config| export PUBLIC_IP=auto export PUBLIC_IPV6=auto export PRIMARY_HOSTNAME=auto - #export SKIP_NETWORK_CHECKS=1 - - if [ ! git ] - then - apt update - apt install git - fi - - if [ ! -d /mailinabox ]; - then - git clone https://github.com/ddavness/power-mailinabox.git /mailinabox - fi - + export SKIP_NETWORK_CHECKS=1 # Start the setup script. - cd /mailinabox - git checkout development - git pull - + cd /vagrant setup/start.sh SH -end +end \ No newline at end of file diff --git a/conf/nginx-top.conf b/conf/nginx-top.conf index a4d09292..85d056cf 100644 --- a/conf/nginx-top.conf +++ b/conf/nginx-top.conf @@ -7,6 +7,5 @@ ## your own --- please do not ask for help from us. upstream php-fpm { - server unix:/var/run/php/php!!___PHPVER___!!-fpm.sock; + server unix:/var/run/php/php{{phpver}}-fpm.sock; } - diff --git a/management/backup.py b/management/backup.py index 90a64588..ce53353c 100755 --- a/management/backup.py +++ b/management/backup.py @@ -10,9 +10,9 @@ 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 +from utils import load_environment, shell, wait_for_service, fix_boto, get_php_version rsync_ssh_options = [ "--ssh-options= -i /root/.ssh/id_rsa_miab", @@ -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,22 @@ 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() + php_fpm = f"php{get_php_version()}-fpm" # Create an global exclusive lock so that the backup script # cannot be run more than one. - Lock(die=True).forever() - + lock = Lock(name="mailinabox_backup_daemon", 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') @@ -247,7 +256,7 @@ def perform_backup(full_backup): if quit: sys.exit(code) - service_command("php!!___PHPVER___!!-fpm", "stop", quit=True) + service_command(php_fpm, "stop", quit=True) service_command("postfix", "stop", quit=True) service_command("dovecot", "stop", quit=True) @@ -281,7 +290,7 @@ def perform_backup(full_backup): # Start services again. service_command("dovecot", "start", quit=False) service_command("postfix", "start", quit=False) - service_command("php!!___PHPVER___!!-fpm", "start", quit=False) + service_command(php_fpm, "start", quit=False) # Remove old backups. This deletes all backup data no longer needed # from more than 3 days ago. @@ -329,8 +338,13 @@ 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 wait for the services to be up in this case + else: + wait_for_service(25, True, env, 10) + wait_for_service(993, True, env, 10) def run_duplicity_verification(): env = load_environment() diff --git a/management/daemon.py b/management/daemon.py index 26c71661..cac8a134 100755 --- a/management/daemon.py +++ b/management/daemon.py @@ -101,9 +101,12 @@ def index(): utils.fix_boto() # must call prior to importing boto import boto.s3 backup_s3_hosts = [(r.name, r.endpoint) for r in boto.s3.regions()] + lsb=utils.shell("check_output", ["/usr/bin/lsb_release", "-d"]) return render_template('index.html', hostname=env['PRIMARY_HOSTNAME'], + distname=lsb[lsb.find("\t")+1:-1], + storage_root=env['STORAGE_ROOT'], no_users_exist=no_users_exist, @@ -440,9 +443,8 @@ def system_status(): self.items[-1]["extra"].append({ "text": message, "monospace": monospace }) output = WebOutput() # Create a temporary pool of processes for the status checks - pool = multiprocessing.pool.Pool(processes=5) - run_checks(False, env, output, pool) - pool.terminate() + with multiprocessing.pool.Pool(processes=5) as pool: + run_checks(False, env, output, pool) return json_response(output.items) @app.route('/system/updates') @@ -509,6 +511,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(): diff --git a/management/status_checks.py b/management/status_checks.py index b1a5c68b..a44832fd 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -1036,12 +1036,12 @@ if __name__ == "__main__": env = load_environment() if len(sys.argv) == 1: - pool = multiprocessing.pool.Pool(processes=10) - run_checks(False, env, ConsoleOutput(), pool) + with multiprocessing.pool.Pool(processes=10) as pool: + run_checks(False, env, ConsoleOutput(), pool) elif sys.argv[1] == "--show-changes": - pool = multiprocessing.pool.Pool(processes=10) - run_and_output_changes(env, pool) + with multiprocessing.pool.Pool(processes=10) as pool: + run_and_output_changes(env, pool) elif sys.argv[1] == "--check-primary-hostname": # See if the primary hostname appears resolvable and has a signed certificate. diff --git a/management/templates/index.html b/management/templates/index.html index f4fa9a52..82e929e0 100644 --- a/management/templates/index.html +++ b/management/templates/index.html @@ -180,7 +180,7 @@
diff --git a/management/templates/system-backup.html b/management/templates/system-backup.html index 3860edb7..3e4fc202 100644 --- a/management/templates/system-backup.html +++ b/management/templates/system-backup.html @@ -12,7 +12,7 @@
-
+