From 89a67fdb3fb28c88aaa0abdedbff080c06f78c4e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 18 Oct 2020 15:02:44 +0200 Subject: Add a dry-run option. --- example.py | 3 ++- lbup/repository.py | 4 ++-- lbup/targets.py | 52 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/example.py b/example.py index 1643a17..62e237f 100755 --- a/example.py +++ b/example.py @@ -20,6 +20,7 @@ def list_targets(tgts): # parse the commandline parser = argparse.ArgumentParser() parser.add_argument('-l', '--list-targets', action = 'store_true') +parser.add_argument('-n', '--dry-run', action = 'store_true') parser.add_argument('targets', nargs = argparse.REMAINDER) args = parser.parse_args() @@ -41,7 +42,7 @@ else: tgts_run = tgts repo = Repo() -res = repo.backup(tgts_run) +res = repo.backup(tgts_run, dry_run = args.dry_run) for tgt, tgt_res in res.target_results.items(): if tgt_res.success: continue diff --git a/lbup/repository.py b/lbup/repository.py index a0caf75..8275910 100644 --- a/lbup/repository.py +++ b/lbup/repository.py @@ -55,7 +55,7 @@ class Repo: self.bup_dir = bup_dir self.data_dir = data_dir - def backup(self, tgts, gen_par2 = True): + def backup(self, tgts, *, gen_par2 = True, dry_run = False): """ Backup the supplied targets. @@ -72,7 +72,7 @@ class Repo: for tgt in tgts: self._logger.info('Backing up %s...' % tgt.name) try: - res = tgt.save(self.data_dir) + res = tgt.save(self.data_dir, dry_run) except Exception as e: self._logger.exception('Exception backing up %s: %s' % (tgt.name, str(e))) res = StepResult(False, str(e).encode('utf-8')) diff --git a/lbup/targets.py b/lbup/targets.py index 4ce7110..8e817b9 100644 --- a/lbup/targets.py +++ b/lbup/targets.py @@ -79,7 +79,8 @@ class Target(ABC): if len(stderr) > 0: self._logger.debug('%s stderr: %s' % (name, sanitize(stderr))) - def _do_save(self, bup_exec, path_prefix = '', index_opts = None, save_opts = None): + def _do_save(self, bup_exec, dry_run, *, + path_prefix = '', index_opts = None, save_opts = None): excludes = [path_prefix + '/' + e for e in self.excludes] dirs = [path_prefix + '/' + d for d in self.dirs] @@ -93,38 +94,45 @@ class Target(ABC): cmd.extend(['--exclude=%s' % e for e in excludes]) cmd.extend(dirs) - self._logger.debug('Executing index command: ' + str(cmd)) - res_idx = subprocess.run(cmd, capture_output = True) - self._log_command('Index', res_idx.returncode, - res_idx.stdout, res_idx.stderr) + if dry_run: + self._logger.debug('Not executing index command: ' + str(cmd)) + else: + self._logger.debug('Executing index command: ' + str(cmd)) + res_idx = subprocess.run(cmd, capture_output = True) + self._log_command('Index', res_idx.returncode, + res_idx.stdout, res_idx.stderr) # save cmd = bup_exec + ['save', '-n', self.name] + save_opts + dirs - self._logger.debug('Executing save command: ' + str(cmd)) - res_save = subprocess.run(cmd, capture_output = True) - self._log_command('Save', res_save.returncode, - res_save.stdout, res_save.stderr) + if dry_run: + self._logger.debug('Not executing save command: ' + str(cmd)) + else: + self._logger.debug('Executing save command: ' + str(cmd)) + res_save = subprocess.run(cmd, capture_output = True) + self._log_command('Save', res_save.returncode, + res_save.stdout, res_save.stderr) retcode = 0 output = b'' - if res_idx.returncode != 0: - retcode = res_idx.returncode - output += res_idx.stderr + res_idx.stdout - if res_save.returncode != 0: - retcode = res_save.returncode - output += res_save.stderr + res_save.stdout + if not dry_run: + if res_idx.returncode != 0: + retcode = res_idx.returncode + output += res_idx.stderr + res_idx.stdout + if res_save.returncode != 0: + retcode = res_save.returncode + output += res_save.stderr + res_save.stdout result = repository.StepResult(retcode == 0, output) return result @abstractmethod - def save(self, data_dir): + def save(self, data_dir, dry_run = False): pass class TargetLocal(Target): - def save(self, data_dir): - return self._do_save(['bup']) + def save(self, data_dir, dry_run = False): + return self._do_save(['bup'], dry_run) class TargetSSH(Target): _remote = None @@ -178,13 +186,13 @@ class TargetSSH(Target): raise BackupException('Invalid BUP_DIR on the remote target: %s' % str(bupdir)) return bupdir[0] - def save(self, data_dir): + def save(self, data_dir, dry_run = False): with _ssh_client.SSHConnection(self._remote) as ssh: remote_bupdir = self._resolve_remote_bupdir(ssh) bup_exec = ['bup', 'on', '%s@%s' % (self._remote.username, self._remote.host), '-d', remote_bupdir] - return self._do_save(bup_exec) + return self._do_save(bup_exec, dry_run) class TargetSSHLXCLVM(TargetSSH): """ @@ -219,7 +227,7 @@ class TargetSSHLXCLVM(TargetSSH): return "%s{LXC:%s/%s@[%s]}{LVM:%s}" % (super().__str__(), self._lxc_containername, self._lxc_username, str(self._parent_remote), self._snapshot_size) - def save(self, data_dir): + def save(self, data_dir, dry_run = False): with contextlib.ExitStack() as stack: parent = stack.enter_context(_ssh_client.SSHConnection(self._parent_remote)) container = stack.enter_context(_ssh_client.SSHConnection(self._remote)) @@ -320,7 +328,7 @@ class TargetSSHLXCLVM(TargetSSH): bup_exec = ['bup', 'on', '%s@%s' % (self._remote.username, self._remote.host), '-d', container_bupdir] try: - ret = self._do_save(bup_exec, path_prefix = container_mountpoint, + ret = self._do_save(bup_exec, dry_run, path_prefix = container_mountpoint, save_opts = save_opts, index_opts = ['--no-check-device']) finally: self._paramiko_exec_cmd(parent, -- cgit v1.2.3