summaryrefslogtreecommitdiff
path: root/src/s3ql/backends/swiftks.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/s3ql/backends/swiftks.py')
-rw-r--r--src/s3ql/backends/swiftks.py72
1 files changed, 65 insertions, 7 deletions
diff --git a/src/s3ql/backends/swiftks.py b/src/s3ql/backends/swiftks.py
index e3dc79d..c43dd1d 100644
--- a/src/s3ql/backends/swiftks.py
+++ b/src/s3ql/backends/swiftks.py
@@ -76,18 +76,60 @@ class Backend(swift.Backend):
tenant = None
user = self.login
- auth_body = { 'auth':
+ domain = self.options.get('domain', None)
+ if domain:
+ if not tenant:
+ raise ValueError("Tenant is required when Keystone v3 is used")
+
+ # In simple cases where there's only one domain, the project domain
+ # will be the same as the authentication domain, but this option
+ # allows for them to be different
+ project_domain = self.options.get('project-domain', domain)
+
+ auth_body = {
+ 'auth': {
+ 'identity': {
+ 'methods': ['password'],
+ 'password': {
+ 'user': {
+ 'name': user,
+ 'domain': {
+ 'id': domain
+ },
+ 'password': self.password
+ }
+ }
+ },
+ 'scope': {
+ 'project': {
+ 'id': tenant,
+ 'domain': {
+ 'id': project_domain
+ }
+ }
+ }
+ }
+ }
+
+ auth_url_path = '/v3/auth/tokens'
+
+ else:
+ # If a domain is not specified, assume v2
+ auth_body = { 'auth':
{ 'passwordCredentials':
{ 'username': user,
'password': self.password } }}
- if tenant:
- auth_body['auth']['tenantName'] = tenant
+
+ auth_url_path = '/v2.0/tokens'
+
+ if tenant:
+ auth_body['auth']['tenantName'] = tenant
with HTTPConnection(self.hostname, port=self.port, proxy=self.proxy,
ssl_context=ssl_context) as conn:
conn.timeout = int(self.options.get('tcp-timeout', 20))
- conn.send_request('POST', '/v2.0/tokens', headers=headers,
+ conn.send_request('POST', auth_url_path, headers=headers,
body=json.dumps(auth_body).encode('utf-8'))
resp = conn.read_response()
@@ -98,10 +140,16 @@ class Backend(swift.Backend):
raise HTTPError(resp.status, resp.reason, resp.headers)
cat = json.loads(conn.read().decode('utf-8'))
- self.auth_token = cat['access']['token']['id']
+
+ if self.options.get('domain', None):
+ self.auth_token = resp.headers['X-Subject-Token']
+ service_catalog = cat['token']['catalog']
+ else:
+ self.auth_token = cat['access']['token']['id']
+ service_catalog = cat['access']['serviceCatalog']
avail_regions = []
- for service in cat['access']['serviceCatalog']:
+ for service in service_catalog:
if service['type'] != 'object-store':
continue
@@ -110,7 +158,17 @@ class Backend(swift.Backend):
avail_regions.append(endpoint['region'])
continue
- o = urlsplit(endpoint['publicURL'])
+ if 'publicURL' in endpoint:
+ # The publicURL nomenclature is found in v2 catalogs
+ o = urlsplit(endpoint['publicURL'])
+ else:
+ # Whereas v3 catalogs do 'interface' == 'public' and
+ # 'url' for the URL itself
+ if endpoint['interface'] != 'public':
+ continue
+
+ o = urlsplit(endpoint['url'])
+
self.auth_prefix = urllib.parse.unquote(o.path)
if o.scheme == 'https':
ssl_context = self.ssl_context