blob: bcdc758bf3dcf7accc4f954eff83fae2ce4c0322 [file] [log] [blame]
Daryl Walleck1465d612011-11-02 02:22:15 -05001import json
Jay Pipes7f757632011-12-02 15:53:32 -05002
3import httplib2
4
Daryl Wallecked8bef32011-12-05 23:02:08 -06005from tempest import exceptions
Daryl Walleck1465d612011-11-02 02:22:15 -05006
7
8class RestClient(object):
9
Jay Pipes7f757632011-12-02 15:53:32 -050010 def __init__(self, config, user, key, auth_url, tenant_name=None):
11 self.config = config
Daryl Walleck1465d612011-11-02 02:22:15 -050012 if self.config.env.authentication == 'keystone_v2':
13 self.token, self.base_url = self.keystone_v2_auth(user,
14 key,
15 auth_url,
16 tenant_name)
17 else:
18 self.token, self.base_url = self.basic_auth(user,
19 key,
20 auth_url)
21
22 def basic_auth(self, user, api_key, auth_url):
23 """
24 Provides authentication for the target API
25 """
26
27 params = {}
28 params['headers'] = {'User-Agent': 'Test-Client', 'X-Auth-User': user,
29 'X-Auth-Key': api_key}
30
31 self.http_obj = httplib2.Http()
32 resp, body = self.http_obj.request(auth_url, 'GET', **params)
33 try:
34 return resp['x-auth-token'], resp['x-server-management-url']
35 except:
36 raise
37
38 def keystone_v2_auth(self, user, api_key, auth_url, tenant_name):
39 """
40 Provides authentication via Keystone 2.0
41 """
42
43 creds = {'auth': {
44 'passwordCredentials': {
45 'username': user,
46 'password': api_key,
47 },
48 'tenantName': tenant_name
49 }
50 }
51
52 self.http_obj = httplib2.Http()
53 headers = {'Content-Type': 'application/json'}
54 body = json.dumps(creds)
55 resp, body = self.http_obj.request(auth_url, 'POST',
56 headers=headers, body=body)
57
Jay Pipes7f757632011-12-02 15:53:32 -050058 if resp.status == 200:
59 try:
60 auth_data = json.loads(body)['access']
61 token = auth_data['token']['id']
62 endpoints = auth_data['serviceCatalog'][0]['endpoints']
63 mgmt_url = endpoints[0]['publicURL']
Daryl Walleck1465d612011-11-02 02:22:15 -050064
Jay Pipes7f757632011-12-02 15:53:32 -050065 #TODO (dwalleck): This is a horrible stopgap.
66 #Need to join strings more cleanly
67 temp = mgmt_url.rsplit('/')
68 service_url = temp[0] + '//' + temp[2] + '/' + temp[3] + '/'
69 management_url = service_url + tenant_name
70 return token, management_url
71 except Exception, e:
72 print "Failed to authenticate user: %s" % e
73 raise
74 elif resp.status == 401:
75 raise exceptions.AuthenticationFailure(user=user, password=api_key)
Daryl Walleck1465d612011-11-02 02:22:15 -050076
77 def post(self, url, body, headers):
78 return self.request('POST', url, headers, body)
79
80 def get(self, url):
81 return self.request('GET', url)
82
83 def delete(self, url):
84 return self.request('DELETE', url)
85
86 def put(self, url, body, headers):
87 return self.request('PUT', url, headers, body)
88
89 def request(self, method, url, headers=None, body=None):
Daryl Wallecke5b83d42011-11-10 14:39:02 -060090 """A simple HTTP request interface."""
Daryl Walleck1465d612011-11-02 02:22:15 -050091
92 self.http_obj = httplib2.Http()
93 if headers == None:
94 headers = {}
95 headers['X-Auth-Token'] = self.token
96
97 req_url = "%s/%s" % (self.base_url, url)
98 resp, body = self.http_obj.request(req_url, method,
99 headers=headers, body=body)
Daryl Walleckadea1fa2011-11-15 18:36:39 -0600100 if resp.status == 400:
101 body = json.loads(body)
102 raise exceptions.BadRequest(body['badRequest']['message'])
103
Daryl Wallecked8bef32011-12-05 23:02:08 -0600104 if resp.status == 413:
105 body = json.loads(body)
106 raise exceptions.OverLimit(body['overLimit']['message'])
Brian Lamar12d9b292011-12-08 12:41:21 -0500107
Daryl Wallecked8bef32011-12-05 23:02:08 -0600108 if resp.status in (500, 501):
109 body = json.loads(body)
110 raise exceptions.ComputeFault(body['computeFault']['message'])
111
Daryl Walleck1465d612011-11-02 02:22:15 -0500112 return resp, body