瀏覽代碼

ZFS hook support for borgmatic's --dry-run (#261).

Dan Helfman 7 月之前
父節點
當前提交
1e7f6d9f41

+ 2 - 1
borgmatic/actions/create.py

@@ -232,7 +232,8 @@ def run_create(
                 borgmatic_runtime_directory,
                 global_arguments.dry_run,
             )
-            source_directories.append(os.path.join(borgmatic_runtime_directory, 'bootstrap'))
+            if not global_arguments.dry_run:
+                source_directories.append(os.path.join(borgmatic_runtime_directory, 'bootstrap'))
 
         json_output = borgmatic.borg.create.create_archive(
             global_arguments.dry_run,

+ 2 - 1
borgmatic/hooks/mariadb.py

@@ -186,7 +186,8 @@ def dump_data_sources(
                 )
             )
 
-    source_directories.append(os.path.join(borgmatic_runtime_directory, 'mariadb_databases'))
+    if not dry_run:
+        source_directories.append(os.path.join(borgmatic_runtime_directory, 'mariadb_databases'))
 
     return [process for process in processes if process]
 

+ 2 - 1
borgmatic/hooks/mongodb.py

@@ -68,7 +68,8 @@ def dump_data_sources(
             dump.create_named_pipe_for_dump(dump_filename)
             processes.append(execute_command(command, shell=True, run_to_completion=False))
 
-    source_directories.append(os.path.join(borgmatic_runtime_directory, 'mongodb_databases'))
+    if not dry_run:
+        source_directories.append(os.path.join(borgmatic_runtime_directory, 'mongodb_databases'))
 
     return processes
 

+ 2 - 1
borgmatic/hooks/mysql.py

@@ -185,7 +185,8 @@ def dump_data_sources(
                 )
             )
 
-    source_directories.append(os.path.join(borgmatic_runtime_directory, 'mysql_databases'))
+    if not dry_run:
+        source_directories.append(os.path.join(borgmatic_runtime_directory, 'mysql_databases'))
 
     return [process for process in processes if process]
 

+ 2 - 1
borgmatic/hooks/postgresql.py

@@ -211,7 +211,8 @@ def dump_data_sources(
                     )
                 )
 
-    source_directories.append(os.path.join(borgmatic_runtime_directory, 'postgresql_databases'))
+    if not dry_run:
+        source_directories.append(os.path.join(borgmatic_runtime_directory, 'postgresql_databases'))
 
     return processes
 

+ 2 - 1
borgmatic/hooks/sqlite.py

@@ -81,7 +81,8 @@ def dump_data_sources(
         dump.create_named_pipe_for_dump(dump_filename)
         processes.append(execute_command(command, shell=True, run_to_completion=False))
 
-    source_directories.append(os.path.join(borgmatic_runtime_directory, 'sqlite_databases'))
+    if not dry_run:
+        source_directories.append(os.path.join(borgmatic_runtime_directory, 'sqlite_databases'))
 
     return processes
 

+ 53 - 52
borgmatic/hooks/zfs.py

@@ -37,15 +37,10 @@ def dump_data_sources(
     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.
-
     '''
-    # 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}')
 
-    # TODO: Dry run.
-
     # List ZFS datasets to get their mount points.
     zfs_command = hook_config.get('zfs_command', 'zfs')
     list_command = (
@@ -82,17 +77,18 @@ def dump_data_sources(
 
     for mount_point, dataset_name in requested_mount_point_to_dataset_name.items():
         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
         # 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),
         )
-        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 []
 
@@ -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,
     then don't actually remove anything.
     '''
-    # TODO: Dry run.
+    dry_run_label = ' (dry run; not actually removing anything)' if dry_run else ''
 
     # Unmount snapshots.
     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),
         '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):
         for mount_point in mount_points:
             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.
     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():
         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!
         if not full_snapshot_name.split('@')[-1].startswith(BORGMATIC_SNAPSHOT_PREFIX):
             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