← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~ghoz/duplicity/swift-prefix into lp:duplicity

 

Ghozlane TOUMI has proposed merging lp:~ghoz/duplicity/swift-prefix into lp:duplicity.

Requested reviews:
  duplicity-team (duplicity-team)

For more details, see:
https://code.launchpad.net/~ghoz/duplicity/swift-prefix/+merge/295017

per request from the ML :

Right now duplicity's swift backend only accept a container as target (swift://container)
trying to use a prefix / pseudo folder (swift://container/backup/path ) results in a JSON exception.

This patch adds the abiliy to use path in the swift backend, in order to have multiple backups to the same container neatly organized.

It borrows some code from the S3 backend, and is quite unobtrusive 
-- 
Your team duplicity-team is requested to review the proposed merge of lp:~ghoz/duplicity/swift-prefix into lp:duplicity.
=== modified file 'bin/duplicity.1'
--- bin/duplicity.1	2016-03-05 11:18:43 +0000
+++ bin/duplicity.1	2016-05-18 08:19:06 +0000
@@ -1175,7 +1175,7 @@
 .BR "Swift" " (Openstack)"
 .PP
 .RS
-swift://container_name
+swift://container_name[/prefix]
 .PP
 See also
 .B "A NOTE ON SWIFT (OPENSTACK OBJECT STORAGE) ACCESS"

=== modified file 'duplicity/backends/swiftbackend.py'
--- duplicity/backends/swiftbackend.py	2015-11-25 08:58:18 +0000
+++ duplicity/backends/swiftbackend.py	2016-05-18 08:19:06 +0000
@@ -90,7 +90,16 @@
 
         conn_kwargs['os_options'] = os_options
 
-        self.container = parsed_url.path.lstrip('/')
+        # This folds the null prefix and all null parts, which means that:
+        #  //MyContainer/ and //MyContainer are equivalent.
+        #  //MyContainer//My/Prefix/ and //MyContainer/My/Prefix are equivalent.
+        url_parts = [x for x in parsed_url.path.split('/') if x != '']
+
+        self.container = url_parts.pop(0)
+        if url_parts:
+            self.prefix = '%s/' % '/'.join(url_parts)
+        else:
+            self.prefix= ''
 
         container_metadata = None
         try:
@@ -118,24 +127,25 @@
                 return log.ErrorCode.backend_not_found
 
     def _put(self, source_path, remote_filename):
-        self.conn.put_object(self.container, remote_filename,
+        self.conn.put_object(self.container, self.prefix + remote_filename,
                              file(source_path.name))
 
     def _get(self, remote_filename, local_path):
-        headers, body = self.conn.get_object(self.container, remote_filename)
+        headers, body = self.conn.get_object(self.container, self.prefix + remote_filename)
         with open(local_path.name, 'wb') as f:
             for chunk in body:
                 f.write(chunk)
 
     def _list(self):
-        headers, objs = self.conn.get_container(self.container, full_listing=True)
-        return [o['name'] for o in objs]
+        headers, objs = self.conn.get_container(self.container, full_listing=True, path=self.prefix)
+        # removes prefix from return values. should check for the prefix ?
+        return [o['name'][len(self.prefix):] for o in objs]
 
     def _delete(self, filename):
-        self.conn.delete_object(self.container, filename)
+        self.conn.delete_object(self.container, self.prefix + filename)
 
     def _query(self, filename):
-        sobject = self.conn.head_object(self.container, filename)
+        sobject = self.conn.head_object(self.container, self.prefix + filename)
         return {'size': int(sobject['content-length'])}
 
 duplicity.backend.register_backend("swift", SwiftBackend)


Follow ups