import json import httplib2 from storm import exceptions import storm.config class RestClient(object): def __init__(self, config, user, key, auth_url, tenant_name=None): self.config = config if self.config.env.authentication == 'keystone_v2': self.token, self.base_url = self.keystone_v2_auth(user, key, auth_url, tenant_name) else: self.token, self.base_url = self.basic_auth(user, key, auth_url) def basic_auth(self, user, api_key, auth_url): """ Provides authentication for the target API """ params = {} params['headers'] = {'User-Agent': 'Test-Client', 'X-Auth-User': user, 'X-Auth-Key': api_key} self.http_obj = httplib2.Http() resp, body = self.http_obj.request(auth_url, 'GET', **params) try: return resp['x-auth-token'], resp['x-server-management-url'] except: raise def keystone_v2_auth(self, user, api_key, auth_url, tenant_name): """ Provides authentication via Keystone 2.0 """ creds = {'auth': { 'passwordCredentials': { 'username': user, 'password': api_key, }, 'tenantName': tenant_name } } self.http_obj = httplib2.Http() headers = {'Content-Type': 'application/json'} body = json.dumps(creds) resp, body = self.http_obj.request(auth_url, 'POST', headers=headers, body=body) if resp.status == 200: try: auth_data = json.loads(body)['access'] token = auth_data['token']['id'] endpoints = auth_data['serviceCatalog'][0]['endpoints'] mgmt_url = endpoints[0]['publicURL'] #TODO (dwalleck): This is a horrible stopgap. #Need to join strings more cleanly temp = mgmt_url.rsplit('/') service_url = temp[0] + '//' + temp[2] + '/' + temp[3] + '/' management_url = service_url + tenant_name return token, management_url except Exception, e: print "Failed to authenticate user: %s" % e raise elif resp.status == 401: raise exceptions.AuthenticationFailure(user=user, password=api_key) def post(self, url, body, headers): return self.request('POST', url, headers, body) def get(self, url): return self.request('GET', url) def delete(self, url): return self.request('DELETE', url) def put(self, url, body, headers): return self.request('PUT', url, headers, body) def request(self, method, url, headers=None, body=None): """A simple HTTP request interface.""" self.http_obj = httplib2.Http() if headers == None: headers = {} headers['X-Auth-Token'] = self.token req_url = "%s/%s" % (self.base_url, url) resp, body = self.http_obj.request(req_url, method, headers=headers, body=body) if resp.status == 400: body = json.loads(body) raise exceptions.BadRequest(body['badRequest']['message']) return resp, body