btrbk_restore_raw.py: add dry-run mode

pull/401/head
fr3aker 2021-08-06 22:33:38 +02:00
parent 7e80e0cbba
commit 025a7709e3
1 changed files with 39 additions and 13 deletions

View File

@ -11,6 +11,9 @@ logger = logging.getLogger(__name__)
class TransformProcess: class TransformProcess:
def run(self, bfile, options, **kw): def run(self, bfile, options, **kw):
return subprocess.Popen(self.get_cmd(bfile, options), **kw)
def get_cmd(self, bfile, options):
raise NotImplementedError() raise NotImplementedError()
@classmethod @classmethod
@ -20,13 +23,14 @@ class TransformProcess:
class TransformOpensslDecrypt(TransformProcess): class TransformOpensslDecrypt(TransformProcess):
@staticmethod @staticmethod
def run(bfile, options, **kw): def get_cmd(bfile, options):
return subprocess.Popen([ return [
'openssl', 'enc', '-d', '-' + bfile.info['cipher'], '-K', 'openssl', 'enc', '-d', '-' + bfile.info['cipher'], '-K',
open(options.openssl_keyfile, 'r').read(), '-iv', bfile.info['iv']], **kw) open(options.openssl_keyfile, 'r').read(), '-iv', bfile.info['iv']
]
@classmethod @staticmethod
def add_parser_options(cls, parser): def add_parser_options(parser):
parser.add_argument('--openssl-keyfile', help="path to private encryption key file") parser.add_argument('--openssl-keyfile', help="path to private encryption key file")
@ -34,14 +38,18 @@ class TransformDecompress(TransformProcess):
def __init__(self, program): def __init__(self, program):
self.p = program self.p = program
def run(self, bfile, options, **kw): def get_cmd(self, bfile, options):
return subprocess.Popen([self.p, '-d'], **kw) return [self.p, '-d']
class TransformBtrfsReceive(TransformProcess): class TransformBtrfsReceive(TransformProcess):
@classmethod
def run(cls, bfile, options, **kw):
return subprocess.Popen(cls.get_cmd(bfile, options), **kw)
@staticmethod @staticmethod
def run(bfile, options, **kw): def get_cmd(bfile, options):
return subprocess.Popen(['btrfs', 'receive', options.restore_dir], **kw) return ['btrfs', 'receive', options.restore_dir]
TRANSFORMERS = ( TRANSFORMERS = (
@ -96,6 +104,13 @@ class BtrfsPipeline:
if msg: if msg:
logger.error(f"error running {p.args}: {msg}") logger.error(f"error running {p.args}: {msg}")
def get_cmd(self, options):
command_pipe = [['cat', self.bfile.data_file]]
for transformer in self.processors:
command_pipe.append(transformer.get_cmd(self.bfile, options))
command_pipe.append(TransformBtrfsReceive.get_cmd(self.bfile, options))
return ' | '.join(' '.join(x) for x in command_pipe)
class BackupFile: class BackupFile:
def __init__(self, path): def __init__(self, path):
@ -132,10 +147,13 @@ class BackupFile:
def restore_file(self, options): def restore_file(self, options):
assert self.info.get('TYPE') == 'raw' assert self.info.get('TYPE') == 'raw'
assert not self.info.get('INCOMPLETE') assert not self.info.get('INCOMPLETE')
logger.info(f"restoring backup {os.path.basename(self.data_file)}")
pipeline = BtrfsPipeline(self) pipeline = BtrfsPipeline(self)
for transformer in self.get_transformers(): for transformer in self.get_transformers():
pipeline.append(transformer) pipeline.append(transformer)
if options.dry_run:
print(pipeline.get_cmd(options))
else:
logger.info(f"restoring backup {os.path.basename(self.data_file)}")
pipeline.run(options) pipeline.run(options)
self.is_restored = True self.is_restored = True
@ -175,13 +193,21 @@ def main():
parser = argparse.ArgumentParser(description="restore btrbk raw backup") parser = argparse.ArgumentParser(description="restore btrbk raw backup")
parser.add_argument('backup', help="backup file to restore; for incremental" parser.add_argument('backup', help="backup file to restore; for incremental"
" backups the parent files must be in the same directory") " backups the parent files must be in the same directory")
parser.add_argument('restore_dir', help="target directory for restored subvolumes (path argument for \"btrfs receive\")") parser.add_argument('restore_dir', help="target directory for restored subvolumes"
parser.add_argument('--ignore-missing', action='store_true', help="do not fail on missing parent snapshots") " (path argument for \"btrfs receive\")")
parser.add_argument('--ignore-missing', action='store_true',
help="do not fail on missing parent snapshots")
parser.add_argument('--dry-run', '-n', action='store_true',
help="print commmands that would be exectuted")
for transformer in TRANSFORMERS: for transformer in TRANSFORMERS:
transformer.add_parser_options(parser) transformer.add_parser_options(parser)
args = parser.parse_args() args = parser.parse_args()
if args.dry_run:
logger.setLevel('ERROR')
restore_from_path(args.backup, args) restore_from_path(args.backup, args)