Browse Source

support source_type sshfs

Fabian Peter Hammerle 7 years ago
parent
commit
54f4783bb9
1 changed files with 68 additions and 38 deletions
  1. 68 38
      scripts/duplitab

+ 68 - 38
scripts/duplitab

@@ -53,60 +53,90 @@ def backup(config, no_print_config, no_print_statistics, tab_dry):
             if 'encrypt_key' in backup:
                 backup_command += ['--encrypt-key', backup['encrypt_key']]
 
-        # selectors
+        # determine source
         try:
-            selectors = backup['selectors']
+            source_type = backup['source_type']
         except KeyError:
-            selectors = []
-        for selector in selectors:
-            if selector['option'] in ['include', 'exclude']:
-                backup_command += ['--{}'.format(selector['option']), selector['shell_pattern']]
+            source_type = 'local'
+        source_mount_path = None
+        try:
+            if source_type == 'local':
+                local_source_path = backup['source_path']
+            elif source_type == 'sshfs':
+                source_mount_path = tempfile.mkdtemp(prefix = 'duplitab-source-sshfs-')
+                sshfs_mount(
+                    url = 'sftp://{}/{}'.format(backup['source_host'], backup['source_path']),
+                    path = source_mount_path,
+                    )
+                local_source_path = source_mount_path
+                backup_command.append('--allow-source-mismatch')
             else:
-                raise Exception("unsupported selector option '{}'".format(selector['option']))
+                raise Exception("unsupported source type '{}'".format(source_type))
 
-        # statistics
-        if no_print_statistics:
-            backup_command.append('--no-print-statistics')
+            # selectors
+            try:
+                selectors = backup['selectors']
+            except KeyError:
+                selectors = []
+            for selector in selectors:
+                if selector['option'] in ['include', 'exclude']:
+                    shell_pattern = selector['shell_pattern']
+                    if shell_pattern.startswith(backup['source_path']):
+                        shell_pattern = shell_pattern.replace(
+                                backup['source_path'],
+                                local_source_path,
+                                1,
+                                )
+                    backup_command += ['--{}'.format(selector['option']), shell_pattern]
+                else:
+                    raise Exception("unsupported selector option '{}'".format(selector['option']))
 
-        # source
-        try:
-            source_type = backup['source_type']
-        except KeyError:
-            source_type = 'local'
-        if source_type == 'local':
-            backup_command += [backup['source_path']]
-        else:
-            raise Exception("unsupported source type '{}'".format(source_type))
+            # statistics
+            if no_print_statistics:
+                backup_command.append('--no-print-statistics')
 
-        # target
-        try:
+            # source path
+            backup_command.append(local_source_path)
+
+            # target
             target_mount_path = None
-            if 'target_via_sshfs' in backup and backup['target_via_sshfs']:
-                target_mount_path = tempfile.mkdtemp(prefix = 'duplitab-target-sshfs-')
-                backup_command += ['file://' + target_mount_path]
-                sshfs_mount(backup['target_url'], target_mount_path)
-                # set backup name to make archive dir persistent
-                # (default name: hash of target url)
-                backup_command += ['--name', hashlib.sha1(backup['target_url'].encode('utf-8')).hexdigest()]
-            else:
-                backup_command += [backup['target_url']]
             try:
-                if tab_dry:
-                    print('* {}'.format(command_join(backup_command)))
+                if 'target_via_sshfs' in backup and backup['target_via_sshfs']:
+                    target_mount_path = tempfile.mkdtemp(prefix = 'duplitab-target-sshfs-')
+                    backup_command += ['file://' + target_mount_path]
+                    sshfs_mount(backup['target_url'], target_mount_path)
+                    # set backup name to make archive dir persistent
+                    # (default name: hash of target url)
+                    backup_command += ['--name', hashlib.sha1(backup['target_url'].encode('utf-8')).hexdigest()]
                 else:
-                    print('+ {}'.format(command_join(backup_command)))
-                    subprocess.check_call(backup_command)
+                    backup_command += [backup['target_url']]
+                try:
+                    if tab_dry:
+                        print('* {}'.format(command_join(backup_command)))
+                    else:
+                        print('+ {}'.format(command_join(backup_command)))
+                        subprocess.check_call(backup_command)
+                finally:
+                    if target_mount_path:
+                        try:
+                            sshfs_unmount(target_mount_path)
+                        except subprocess.CalledProcessError:
+                            time.sleep(1)
+                            sshfs_unmount(target_mount_path)
+
             finally:
                 if target_mount_path:
+                    os.rmdir(target_mount_path)
+                if source_mount_path:
                     try:
-                        sshfs_unmount(target_mount_path)
+                        sshfs_unmount(source_mount_path)
                     except subprocess.CalledProcessError:
                         time.sleep(1)
-                        sshfs_unmount(target_mount_path)
+                        sshfs_unmount(source_mount_path)
 
         finally:
-            if target_mount_path:
-                os.rmdir(target_mount_path)
+            if source_mount_path:
+                os.rmdir(source_mount_path)
 
 def run(command, config_path, no_print_config, no_print_statistics, tab_dry):