Merge lp:~kartoch/duplicity/hubic into lp:~duplicity-team/duplicity/0.7-series

Proposed by Kartoch
Status: Rejected
Rejected by: Kenneth Loafman
Proposed branch: lp:~kartoch/duplicity/hubic
Merge into: lp:~duplicity-team/duplicity/0.7-series
Diff against target: 120 lines (+105/-0)
2 files modified
duplicity/backends/hubicbackend.py (+104/-0)
duplicity/commandline.py (+1/-0)
To merge this branch: bzr merge lp:~kartoch/duplicity/hubic
Reviewer Review Type Date Requested Status
duplicity-team Pending
Review via email: mp+231126@code.launchpad.net

Description of the change

Hubic support

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.

To post a comment you must log in.
lp:~kartoch/duplicity/hubic updated
998. By Kartoch

Add try/catch to handle error during hubic authentication

Revision history for this message
Kartoch (kartoch) wrote :

It seems Hubic will change auth service soon for OAuth and will drop web services soon, so my patches will be probably useless...

Revision history for this message
Kenneth Loafman (kenneth-loafman) wrote :

Does this mean that the merge request can be 'rejected' (that seems to be the only option LP gives us)?

Revision history for this message
edso (ed.so) wrote :

this also misses the necessary documentation in the man page (sections requirements, url format etc..).

..ede

Revision history for this message
Kartoch (kartoch) wrote :

yeah reject it: web service is deprecated and will be remove at any time.

Unmerged revisions

998. By Kartoch

Add try/catch to handle error during hubic authentication

997. By Kartoch

Refactoring code to inherite from swiftbackend

996. By Kartoch

Preliminary support for HUBIC storage

- add a new backend dedicated to hubic
- copy/paste from swift backend to test it (refactroing later)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'duplicity/backends/hubicbackend.py'
2--- duplicity/backends/hubicbackend.py 1970-01-01 00:00:00 +0000
3+++ duplicity/backends/hubicbackend.py 2014-08-18 06:26:27 +0000
4@@ -0,0 +1,104 @@
5+import base64
6+import json
7+import os
8+
9+import duplicity.backend
10+from duplicity.backends.swiftbackend import SwiftBackend
11+from duplicity import log
12+from duplicity import util
13+from duplicity.errors import BackendException
14+
15+try:
16+ import requests
17+except ImportError:
18+ raise BackendException("This backend requires the python-requests library.")
19+
20+
21+class HubicBackend(SwiftBackend):
22+
23+ """
24+ Backend for Hubic
25+ """
26+
27+ OVH_SESSION_HANDLER = 'https://ws.ovh.com/sessionHandler/r4/rest.dispatcher/'
28+ HUBIC_WS = 'https://ws.ovh.com/hubic/r5/rest.dispatcher/'
29+
30+ def __init__(self, parsed_url):
31+
32+ if 'HUBIC_USERNAME' not in os.environ:
33+ raise BackendException('HUBIC_USERNAME environment variable '
34+ 'not set.')
35+ login = os.environ['HUBIC_USERNAME']
36+
37+ if 'HUBIC_PASSWORD' not in os.environ:
38+ raise BackendException('HUBIC_PASSWORD environment variable '
39+ 'not set.')
40+ password = os.environ['HUBIC_PASSWORD']
41+
42+ if 'SWIFT_PREAUTHURL' in os.environ or \
43+ 'SWIFT_PREAUTHTOKEN' in os.environ or \
44+ 'SWIFT_USERNAME' in os.environ or \
45+ 'SWIFT_PASSWORD' in os.environ or \
46+ 'SWIFT_AUTHURL' in os.environ:
47+ raise BackendException('SWIFT_* environment variables '
48+ 'must not be set.')
49+
50+ (url, token) = self._authenticate(login, password)
51+
52+ os.environ['SWIFT_PREAUTHURL'] = url
53+ os.environ['SWIFT_PREAUTHTOKEN'] = token
54+
55+ super(HubicBackend, self).__init__(parsed_url)
56+
57+ def _authenticate(self, login, password):
58+
59+ try:
60+ # get anonymous session id
61+ r = requests.get(self.OVH_SESSION_HANDLER + 'getAnonymousSession')
62+ anonymous_session_id = r.json()['answer']['session']['id']
63+
64+ log.Debug("HUBIC: hubic anonymous session id:" + anonymous_session_id)
65+
66+ params = {'sessionId': anonymous_session_id,
67+ 'email': login}
68+ payload = {'params': json.dumps(params)}
69+
70+ # get hubic id
71+ r = requests.get(self.HUBIC_WS + 'getHubics', params=payload)
72+ hubics = r.json()
73+ hubics_id = hubics['answer'][0]['id']
74+ log.Debug("HUBIC: hubics id:" + hubics_id)
75+
76+ # get authenticated session id
77+ params = {'login': hubics['answer'][0]['nic'],
78+ 'password': password,
79+ 'context': 'hubic'}
80+ payload = {'params': json.dumps(params)}
81+ r = requests.get(self.OVH_SESSION_HANDLER + 'login', params=payload)
82+ self.session_id = r.json()['answer']['session']['id']
83+ log.Debug("HUBIC: authenticated hubics id:" + self.session_id)
84+
85+ # get storage URL and authorization token
86+ params = {'sessionId': self.session_id,
87+ 'hubicId': hubics_id}
88+ payload = {'params': json.dumps(params)}
89+
90+ r = requests.get(self.HUBIC_WS + 'getHubic', params=payload)
91+ storage_url = base64.b64decode(r.json()['answer']['credentials']['username'])
92+ log.Debug("HUBIC: storage url:" + str(storage_url))
93+ auth_token = r.json()['answer']['credentials']['secret']
94+ log.Debug("HUBIC: auth token:" + auth_token)
95+ except Exception as e:
96+ log.FatalError("Authentication to hubic failed: %s %s"
97+ % (e.__class__.__name__, util.uexc(e)),
98+ log.ErrorCode.backend_error)
99+
100+ return storage_url, auth_token
101+
102+ def _close(self):
103+ log.Debug("HUBIC: logout")
104+ params = {'sessionId': self.session_id}
105+ payload = {'params': json.dumps(params)}
106+ requests.get(self.OVH_SESSION_HANDLER + 'logout', params=payload)
107+
108+duplicity.backend.register_backend("hubic", HubicBackend)
109
110=== modified file 'duplicity/commandline.py'
111--- duplicity/commandline.py 2014-06-28 14:48:21 +0000
112+++ duplicity/commandline.py 2014-08-18 06:26:27 +0000
113@@ -848,6 +848,7 @@
114 ftp://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
115 ftps://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
116 hsi://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
117+ hubic://default
118 imap://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(some_dir)s
119 rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]::/%(module)s/%(some_dir)s
120 rsync://%(user)s[:%(password)s]@%(other_host)s[:%(port)s]/%(relative_path)s

Subscribers

People subscribed via source and target branches