|
@@ -37,15 +37,10 @@ def dump_data_sources(
|
|
Return an empty sequence, since there are no ongoing dump processes.
|
|
Return an empty sequence, since there are no ongoing dump processes.
|
|
|
|
|
|
If this is a dry run or ZFS isn't enabled, then don't actually snapshot anything.
|
|
If this is a dry run or ZFS isn't enabled, then don't actually snapshot anything.
|
|
-
|
|
|
|
'''
|
|
'''
|
|
- # TODO: Check for ZFS enabled in config and skip accordingly.
|
|
|
|
-
|
|
|
|
- dry_run_label = ' (dry run; not actually dumping anything)' if dry_run else ''
|
|
|
|
|
|
+ dry_run_label = ' (dry run; not actually snapshotting anything)' if dry_run else ''
|
|
logger.info(f'{log_prefix}: Snapshotting ZFS datasets{dry_run_label}')
|
|
logger.info(f'{log_prefix}: Snapshotting ZFS datasets{dry_run_label}')
|
|
|
|
|
|
- # TODO: Dry run.
|
|
|
|
-
|
|
|
|
# List ZFS datasets to get their mount points.
|
|
# List ZFS datasets to get their mount points.
|
|
zfs_command = hook_config.get('zfs_command', 'zfs')
|
|
zfs_command = hook_config.get('zfs_command', 'zfs')
|
|
list_command = (
|
|
list_command = (
|
|
@@ -82,17 +77,18 @@ def dump_data_sources(
|
|
|
|
|
|
for mount_point, dataset_name in requested_mount_point_to_dataset_name.items():
|
|
for mount_point, dataset_name in requested_mount_point_to_dataset_name.items():
|
|
full_snapshot_name = f'{dataset_name}@{snapshot_name}'
|
|
full_snapshot_name = f'{dataset_name}@{snapshot_name}'
|
|
- logger.debug(f'{log_prefix}: Creating ZFS snapshot {full_snapshot_name}')
|
|
|
|
-
|
|
|
|
- borgmatic.execute.execute_command(
|
|
|
|
- (
|
|
|
|
- zfs_command,
|
|
|
|
- 'snapshot',
|
|
|
|
- '-r',
|
|
|
|
- full_snapshot_name,
|
|
|
|
- ),
|
|
|
|
- output_log_level=logging.DEBUG,
|
|
|
|
- )
|
|
|
|
|
|
+ logger.debug(f'{log_prefix}: Creating ZFS snapshot {full_snapshot_name}{dry_run_label}')
|
|
|
|
+
|
|
|
|
+ if not dry_run:
|
|
|
|
+ borgmatic.execute.execute_command(
|
|
|
|
+ (
|
|
|
|
+ zfs_command,
|
|
|
|
+ 'snapshot',
|
|
|
|
+ '-r',
|
|
|
|
+ full_snapshot_name,
|
|
|
|
+ ),
|
|
|
|
+ output_log_level=logging.DEBUG,
|
|
|
|
+ )
|
|
|
|
|
|
# Mount the snapshot into a particular named temporary directory so that the snapshot ends
|
|
# Mount the snapshot into a particular named temporary directory so that the snapshot ends
|
|
# up in the Borg archive at the "original" dataset mount point path.
|
|
# up in the Borg archive at the "original" dataset mount point path.
|
|
@@ -102,22 +98,24 @@ def dump_data_sources(
|
|
'.',
|
|
'.',
|
|
mount_point.lstrip(os.path.sep),
|
|
mount_point.lstrip(os.path.sep),
|
|
)
|
|
)
|
|
- logger.debug(f'{log_prefix}: Mounting ZFS snapshot {full_snapshot_name} at {snapshot_path}')
|
|
|
|
-
|
|
|
|
- os.makedirs(snapshot_path, mode=0o700, exist_ok=True)
|
|
|
|
- borgmatic.execute.execute_command(
|
|
|
|
- (
|
|
|
|
- hook_config.get('mount_command', 'mount'),
|
|
|
|
- '-t',
|
|
|
|
- 'zfs',
|
|
|
|
- f'{dataset_name}@{snapshot_name}',
|
|
|
|
- snapshot_path,
|
|
|
|
- ),
|
|
|
|
- output_log_level=logging.DEBUG,
|
|
|
|
- )
|
|
|
|
|
|
+ logger.debug(f'{log_prefix}: Mounting ZFS snapshot {full_snapshot_name} at {snapshot_path}{dry_run_label}')
|
|
|
|
|
|
- source_directories.remove(mount_point)
|
|
|
|
- source_directories.append(snapshot_path)
|
|
|
|
|
|
+ if not dry_run:
|
|
|
|
+ os.makedirs(snapshot_path, mode=0o700, exist_ok=True)
|
|
|
|
+ borgmatic.execute.execute_command(
|
|
|
|
+ (
|
|
|
|
+ hook_config.get('mount_command', 'mount'),
|
|
|
|
+ '-t',
|
|
|
|
+ 'zfs',
|
|
|
|
+ f'{dataset_name}@{snapshot_name}',
|
|
|
|
+ snapshot_path,
|
|
|
|
+ ),
|
|
|
|
+ output_log_level=logging.DEBUG,
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if not dry_run:
|
|
|
|
+ source_directories.remove(mount_point)
|
|
|
|
+ source_directories.append(snapshot_path)
|
|
|
|
|
|
return []
|
|
return []
|
|
|
|
|
|
@@ -129,7 +127,7 @@ def remove_data_source_dumps(hook_config, config, log_prefix, borgmatic_runtime_
|
|
borgmatic. Use the log prefix in any log entries. If this is a dry run or ZFS isn't enabled,
|
|
borgmatic. Use the log prefix in any log entries. If this is a dry run or ZFS isn't enabled,
|
|
then don't actually remove anything.
|
|
then don't actually remove anything.
|
|
'''
|
|
'''
|
|
- # TODO: Dry run.
|
|
|
|
|
|
+ dry_run_label = ' (dry run; not actually removing anything)' if dry_run else ''
|
|
|
|
|
|
# Unmount snapshots.
|
|
# Unmount snapshots.
|
|
zfs_command = hook_config.get('zfs_command', 'zfs')
|
|
zfs_command = hook_config.get('zfs_command', 'zfs')
|
|
@@ -162,19 +160,21 @@ def remove_data_source_dumps(hook_config, config, log_prefix, borgmatic_runtime_
|
|
os.path.normpath(borgmatic_runtime_directory),
|
|
os.path.normpath(borgmatic_runtime_directory),
|
|
'zfs_snapshots',
|
|
'zfs_snapshots',
|
|
)
|
|
)
|
|
- logger.debug(f'{log_prefix}: Looking for snapshots in {snapshots_directory}')
|
|
|
|
|
|
+ logger.debug(f'{log_prefix}: Looking for snapshots to remove in {snapshots_directory}{dry_run_label}')
|
|
|
|
|
|
if os.path.isdir(snapshots_directory):
|
|
if os.path.isdir(snapshots_directory):
|
|
for mount_point in mount_points:
|
|
for mount_point in mount_points:
|
|
snapshot_path = os.path.join(snapshots_directory, mount_point.lstrip(os.path.sep))
|
|
snapshot_path = os.path.join(snapshots_directory, mount_point.lstrip(os.path.sep))
|
|
- logger.debug(f'{log_prefix}: Unmounting ZFS snapshot at {snapshot_path}')
|
|
|
|
- borgmatic.execute.execute_command(
|
|
|
|
- (
|
|
|
|
- hook_config.get('umount_command', 'umount'),
|
|
|
|
- snapshot_path,
|
|
|
|
- ),
|
|
|
|
- output_log_level=logging.DEBUG,
|
|
|
|
- )
|
|
|
|
|
|
+ logger.debug(f'{log_prefix}: Unmounting ZFS snapshot at {snapshot_path}{dry_run_label}')
|
|
|
|
+
|
|
|
|
+ if not dry_run:
|
|
|
|
+ borgmatic.execute.execute_command(
|
|
|
|
+ (
|
|
|
|
+ hook_config.get('umount_command', 'umount'),
|
|
|
|
+ snapshot_path,
|
|
|
|
+ ),
|
|
|
|
+ output_log_level=logging.DEBUG,
|
|
|
|
+ )
|
|
|
|
|
|
# Destroy snapshots.
|
|
# Destroy snapshots.
|
|
list_snapshots_command = (
|
|
list_snapshots_command = (
|
|
@@ -192,21 +192,22 @@ def remove_data_source_dumps(hook_config, config, log_prefix, borgmatic_runtime_
|
|
|
|
|
|
for line in list_snapshots_output.splitlines():
|
|
for line in list_snapshots_output.splitlines():
|
|
full_snapshot_name = line.rstrip()
|
|
full_snapshot_name = line.rstrip()
|
|
- logger.debug(f'{log_prefix}: Destroying ZFS snapshot {full_snapshot_name}')
|
|
|
|
|
|
+ logger.debug(f'{log_prefix}: Destroying ZFS snapshot {full_snapshot_name}{dry_run_label}')
|
|
|
|
|
|
# Only destroy snapshots that borgmatic actually created!
|
|
# Only destroy snapshots that borgmatic actually created!
|
|
if not full_snapshot_name.split('@')[-1].startswith(BORGMATIC_SNAPSHOT_PREFIX):
|
|
if not full_snapshot_name.split('@')[-1].startswith(BORGMATIC_SNAPSHOT_PREFIX):
|
|
continue
|
|
continue
|
|
|
|
|
|
- borgmatic.execute.execute_command(
|
|
|
|
- (
|
|
|
|
- zfs_command,
|
|
|
|
- 'destroy',
|
|
|
|
- '-r',
|
|
|
|
- full_snapshot_name,
|
|
|
|
- ),
|
|
|
|
- output_log_level=logging.DEBUG,
|
|
|
|
- )
|
|
|
|
|
|
+ if not dry_run:
|
|
|
|
+ borgmatic.execute.execute_command(
|
|
|
|
+ (
|
|
|
|
+ zfs_command,
|
|
|
|
+ 'destroy',
|
|
|
|
+ '-r',
|
|
|
|
+ full_snapshot_name,
|
|
|
|
+ ),
|
|
|
|
+ output_log_level=logging.DEBUG,
|
|
|
|
+ )
|
|
|
|
|
|
|
|
|
|
def make_data_source_dump_patterns(hook_config, config, log_prefix, name=None): # pragma: no cover
|
|
def make_data_source_dump_patterns(hook_config, config, log_prefix, name=None): # pragma: no cover
|