duplicity-team team mailing list archive
-
duplicity-team team
-
Mailing list archive
-
Message #02421
[Merge] lp:~kartoch/duplicity/hubic into lp:duplicity
Kartoch has proposed merging lp:~kartoch/duplicity/hubic into lp:duplicity.
Requested reviews:
duplicity-team (duplicity-team)
For more details, see:
https://code.launchpad.net/~kartoch/duplicity/hubic/+merge/231126
Add a new backend for the support of Hubic, a french cloud provider offering cheap space storage.
The code adds a pre-authentication step to the swift backend, requesting some web services to obtain pre-authentication URL and token.
Usage:
- url is "hubic://default"
- user / password is deliver to duplicity via export variables HUBIC_USERNAME and HUBIC_PASSWORD
At the present time there is few limitations:
- the URL MUST BE "hubic://default", thus there is no way to place backup in a sub-directory
- token are valid 8 hours. If the backup takes more time, the user needs to relaunch duplicity to continue it. This is a limitation of the swift code to relaunch an authentication step in case of "not authorized" error during transfer.
--
https://code.launchpad.net/~kartoch/duplicity/hubic/+merge/231126
Your team duplicity-team is requested to review the proposed merge of lp:~kartoch/duplicity/hubic into lp:duplicity.
=== added file 'duplicity/backends/hubicbackend.py'
--- duplicity/backends/hubicbackend.py 1970-01-01 00:00:00 +0000
+++ duplicity/backends/hubicbackend.py 2014-08-17 17:56:53 +0000
@@ -0,0 +1,97 @@
+import base64
+import json
+import os
+
+import duplicity.backend
+from duplicity.backends.swiftbackend import SwiftBackend
+from duplicity import log
+from duplicity.errors import BackendException
+
+try:
+ import requests
+except ImportError:
+ raise BackendException("This backend requires the python-requests library.")
+
+class HubicBackend(SwiftBackend):
+
+ """
+ Backend for Hubic
+ """
+
+ OVH_SESSION_HANDLER = 'https://ws.ovh.com/sessionHandler/r4/rest.dispatcher/'
+ HUBIC_WS = 'https://ws.ovh.com/hubic/r5/rest.dispatcher/'
+
+ def __init__(self, parsed_url):
+
+ if 'HUBIC_USERNAME' not in os.environ:
+ raise BackendException('HUBIC_USERNAME environment variable '
+ 'not set.')
+ login = os.environ['HUBIC_USERNAME']
+
+ if 'HUBIC_PASSWORD' not in os.environ:
+ raise BackendException('HUBIC_PASSWORD environment variable '
+ 'not set.')
+ password = os.environ['HUBIC_PASSWORD']
+
+ if 'SWIFT_PREAUTHURL' in os.environ or \
+ 'SWIFT_PREAUTHTOKEN' in os.environ or \
+ 'SWIFT_USERNAME' in os.environ or \
+ 'SWIFT_PASSWORD' in os.environ or \
+ 'SWIFT_AUTHURL' in os.environ:
+ raise BackendException('SWIFT_* environment variables '
+ 'must not be set.')
+
+ (url, token) = self._authenticate(login, password)
+
+ os.environ['SWIFT_PREAUTHURL'] = url
+ os.environ['SWIFT_PREAUTHTOKEN'] = token
+
+ super(HubicBackend, self).__init__(parsed_url)
+
+ def _authenticate(self, login, password):
+
+ # get anonymous session id
+ r = requests.get(self.OVH_SESSION_HANDLER + 'getAnonymousSession')
+ anonymous_session_id = r.json()['answer']['session']['id']
+
+ log.Debug("HUBIC: hubic anonymous session id:" + anonymous_session_id)
+
+ params = {'sessionId': anonymous_session_id,
+ 'email': login}
+ payload = {'params': json.dumps(params)}
+
+ # get hubic id
+ r = requests.get(self.HUBIC_WS + 'getHubics', params=payload)
+ hubics = r.json()
+ hubics_id = hubics['answer'][0]['id']
+ log.Debug("HUBIC: hubics id:" + hubics_id)
+
+ # get authenticated session id
+ params = {'login': hubics['answer'][0]['nic'],
+ 'password': password,
+ 'context': 'hubic'}
+ payload = {'params': json.dumps(params)}
+ r = requests.get(self.OVH_SESSION_HANDLER + 'login', params=payload)
+ self.session_id = r.json()['answer']['session']['id']
+ log.Debug("HUBIC: authenticated hubics id:" + self.session_id)
+
+ # get storage URL and authorization token
+ params = { 'sessionId': self.session_id,
+ 'hubicId': hubics_id}
+ payload = {'params': json.dumps(params)}
+
+ r = requests.get(self.HUBIC_WS + 'getHubic', params=payload)
+ storage_url = base64.b64decode(r.json()['answer']['credentials']['username'])
+ log.Debug("HUBIC: storage url:" + str(storage_url))
+ auth_token = r.json()['answer']['credentials']['secret']
+ log.Debug("HUBIC: auth token:" + auth_token)
+
+ return storage_url, auth_token
+
+ def _close(self):
+ log.Debug("HUBIC: logout")
+ params = { 'sessionId': self.session_id}
+ payload = {'params': json.dumps(params)}
+ r = requests.get(self.OVH_SESSION_HANDLER + 'logout', params=payload)
+
+duplicity.backend.register_backend("hubic", HubicBackend)
=== modified file 'duplicity/commandline.py'
--- duplicity/commandline.py 2014-06-28 14:48:21 +0000
+++ duplicity/commandline.py 2014-08-17 17:56:53 +0000
@@ -848,6 +848,7 @@
ftp://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
ftps://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
hsi://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
+ hubic://default
imap://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]::/%(module)s/%(some_dir)s
rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(relative_path)s
Follow ups