dump.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import fnmatch
  2. import logging
  3. import os
  4. import shutil
  5. logger = logging.getLogger(__name__)
  6. IS_A_HOOK = False
  7. def make_data_source_dump_path(borgmatic_runtime_directory, data_source_hook_name):
  8. '''
  9. Given a borgmatic runtime directory and a data source hook name, construct a data source dump
  10. path.
  11. '''
  12. return os.path.join(borgmatic_runtime_directory, data_source_hook_name)
  13. def make_data_source_dump_filename(dump_path, name, hostname=None):
  14. '''
  15. Based on the given dump directory path, data source name, and hostname, return a filename to use
  16. for the data source dump. The hostname defaults to localhost.
  17. Raise ValueError if the data source name is invalid.
  18. '''
  19. if os.path.sep in name:
  20. raise ValueError(f'Invalid data source name {name}')
  21. return os.path.join(dump_path, hostname or 'localhost', name)
  22. def create_parent_directory_for_dump(dump_path):
  23. '''
  24. Create a directory to contain the given dump path.
  25. '''
  26. os.makedirs(os.path.dirname(dump_path), mode=0o700, exist_ok=True)
  27. def create_named_pipe_for_dump(dump_path):
  28. '''
  29. Create a named pipe at the given dump path.
  30. '''
  31. create_parent_directory_for_dump(dump_path)
  32. os.mkfifo(dump_path, mode=0o600)
  33. def remove_data_source_dumps(dump_path, data_source_type_name, log_prefix, dry_run):
  34. '''
  35. Remove all data source dumps in the given dump directory path (including the directory itself).
  36. If this is a dry run, then don't actually remove anything.
  37. '''
  38. dry_run_label = ' (dry run; not actually removing anything)' if dry_run else ''
  39. logger.debug(f'{log_prefix}: Removing {data_source_type_name} data source dumps{dry_run_label}')
  40. if dry_run:
  41. return
  42. if os.path.exists(dump_path):
  43. shutil.rmtree(dump_path)
  44. def convert_glob_patterns_to_borg_pattern(patterns):
  45. '''
  46. Convert a sequence of shell glob patterns like "/etc/*", "/tmp/*" to the corresponding Borg
  47. regular expression archive pattern as a single string like "re:etc/.*|tmp/.*".
  48. '''
  49. # Remove the "\Z" generated by fnmatch.translate() because we don't want the pattern to match
  50. # only at the end of a path, as directory format dumps require extracting files with paths
  51. # longer than the pattern. E.g., a pattern of "borgmatic/*/foo_databases/test" should also match
  52. # paths like "borgmatic/*/foo_databases/test/toc.dat"
  53. return 're:' + '|'.join(
  54. fnmatch.translate(pattern.lstrip('/')).replace('\\Z', '') for pattern in patterns
  55. )