mirror of https://github.com/digint/btrbk
btrbk_restore_raw.py: add dry-run mode
parent
7e80e0cbba
commit
025a7709e3
|
@ -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,11 +147,14 @@ 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)
|
||||||
pipeline.run(options)
|
if options.dry_run:
|
||||||
|
print(pipeline.get_cmd(options))
|
||||||
|
else:
|
||||||
|
logger.info(f"restoring backup {os.path.basename(self.data_file)}")
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue