duplicity-talk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Duplicity-talk] Tahoe backend for duplicity


From: Francois Deppierraz
Subject: [Duplicity-talk] Tahoe backend for duplicity
Date: Mon, 24 Nov 2008 12:15:23 +0100
User-agent: Thunderbird 2.0.0.17 (X11/20080925)

Hi Folks,

Following on the "BackupDB proposal" [1] thread on tahoe-dev
mailing-list, here is a quick and dirty patch adding tahoe [2] support
to the duplicity backup tool [3].

This feature brings a fully distributed and fault-tolerant backend store
to duplicity. Usage of GPG encryption is not necessary with this backend
because everything is already encrypted by tahoe.

The patch is quite small (<100 lines) and makes heavy use of tahoe CLI.
 It has the advantage of being largely independent from tahoe codebase.

== Quickstart ==

1. Install duplicity version 0.5.03 with attached patch applied

  tar xzfv duplicity-0.5.03.tar.gz
  cd duplicity-0.5.03
  patch -p1 < ../duplicity-0.5.03-tahoe_support.patch
  python setup.py install

2. Install tahoe version 1.2.0 (or greater)
2. Setup a tahoe CLI client, see [2]
3. Create a new directory for your backup

  tahoe add-alias mybackup $(tahoe mkdir)

4. Backup your files

  duplicity --no-encryption /home/me tahoe:///mybackup/

5. Restore your files

  duplicity --no-encryption tahoe:///mybackup/ /tmp/recovery

== Open questions ==

I don't really know if performances of such a backend interacting
directly with the web-API could be much better ?

What is the correct way to get such feature integrated upstream in
duplicity ?

Feedback is wholeheartedly welcome !

Fran├žois

P.S. This message is cross-posted on tahoe-dev and duplicity-talk.

[1] http://allmydata.org/pipermail/tahoe-dev/2008-September/000814.html
[2] http://allmydata.org/
[3] http://duplicity.nongnu.org/
diff --git a/src/backends/__init__.py b/src/backends/__init__.py
index 81d798a..22787c1 100644
--- a/src/backends/__init__.py
+++ b/src/backends/__init__.py
@@ -16,4 +16,5 @@ import duplicity.backends.localbackend
 import duplicity.backends.rsyncbackend
 import duplicity.backends.sshbackend
 import duplicity.backends.webdavbackend
+import duplicity.backends.tahoebackend
 
diff --git a/src/backends/tahoebackend.py b/src/backends/tahoebackend.py
new file mode 100644
index 0000000..35e075c
--- /dev/null
+++ b/src/backends/tahoebackend.py
@@ -0,0 +1,89 @@
+# Copyright 2008 Francois Deppierraz
+#
+# This file is part of duplicity.
+#
+# Duplicity is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at your
+# option) any later version.
+#
+# Duplicity is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with duplicity; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+import time
+
+import duplicity.backend
+import duplicity.globals as globals
+import duplicity.log as log
+from duplicity.errors import *
+#from duplicity.util import exception_traceback
+
+from commands import getstatusoutput,getoutput,getstatus
+
+class TAHOEBackend(duplicity.backend.Backend):
+    """
+    """
+
+    def __init__(self, parsed_url):
+        duplicity.backend.Backend.__init__(self, parsed_url)
+
+        url = parsed_url[2].strip('///').split('/')
+
+        self.alias = url[0]
+
+        if len(url) > 2:
+            self.directory = "/".join(url[1:])
+        elif len(url) == 2:
+            self.directory = url[1]
+        else:
+            self.directory = ""
+        
+        log.Log("%s -> %s:%s" % (url, self.alias, self.directory), 9)
+
+    def get_remote_path(self, filename=None):
+        if filename == None:
+            if self.directory != "":
+                return "%s:%s" % (self.alias, self.directory)
+            else:
+                return "%s:" % self.alias
+            
+        if self.directory != "":
+            return "%s:%s/%s" % (self.alias, self.directory, filename)
+        else:
+            return "%s:%s" % (self.alias, filename)
+
+    def run(self, *args):
+        cmd = " ".join(args)
+        log.Log("EXECUTE: %s" % cmd, 9)
+        (status, output) = getstatusoutput(cmd)
+
+        if status != 0:
+            raise BackendException("Error running %s" % cmd)
+        else:
+            return output
+
+    def put(self, source_path, remote_filename=None):
+        self.run("tahoe", "cp", source_path.name, 
self.get_remote_path(remote_filename))
+
+    def get(self, remote_filename, local_path):
+        self.run("tahoe", "cp", self.get_remote_path(remote_filename), 
local_path.name)
+        local_path.setdata()
+
+    def list(self):
+        log.Log("TAHOE: List", 9)
+
+        return self.run("tahoe", "ls", self.get_remote_path()).split('\n')
+
+    def delete(self, filename_list):
+        log.Log("TAHOE: delete(%s)" % filename_list, 9)
+        for filename in filename_list:
+            self.run("tahoe", "rm", self.get_remote_path(filename))
+
+duplicity.backend.register_backend("tahoe", TAHOEBackend)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]