forked from rockstor/rockstor-core
/
api_wrapper.py
125 lines (110 loc) · 5.09 KB
/
api_wrapper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""
Copyright (c) 2012-2013 RockStor, Inc. <http://rockstor.com>
This file is part of RockStor.
RockStor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
RockStor is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import requests
import time
import json
import base64
from storageadmin.exceptions import RockStorAPIException
from storageadmin.models import OauthApp
from django.conf import settings
class APIWrapper(object):
def __init__(self, client_id=None, client_secret=None, url=None):
self.access_token = None
self.expiration = time.time()
self.client_id = client_id
self.client_secret = client_secret
# directly connect to gunicorn, bypassing nginx as we are on the same
# host.
self.url = 'http://127.0.0.1:443'
if (url is not None):
# for remote urls.
self.url = url
def set_token(self):
if (self.client_id is None or self.client_secret is None):
app = OauthApp.objects.get(name=settings.OAUTH_INTERNAL_APP)
self.client_id = app.application.client_id
self.client_secret = app.application.client_secret
token_request_data = {
'grant_type': 'client_credentials',
'client_id': self.client_id,
'client_secret': self.client_secret,
}
user_pass = '{0}:{1}'.format(self.client_id, self.client_secret)
auth_string = base64.b64encode(user_pass.encode('utf-8'))
auth_headers = {'HTTP_AUTHORIZATION':
'Basic ' + auth_string.decode("utf-8"), }
content = None
try:
response = requests.post('%s/o/token/' % self.url,
data=token_request_data,
headers=auth_headers, verify=False)
content = json.loads(response.content.decode("utf-8"))
self.access_token = content['access_token']
self.expiration = int(time.time()) + content['expires_in'] - 600
except Exception as e:
msg = ('Exception while setting access_token for url(%s): %s. '
'content: %s' % (self.url, e.__str__(), content))
raise Exception(msg)
def api_call(self, url, data=None, calltype='get', headers=None,
save_error=True):
if (self.access_token is None or
time.time() > self.expiration):
self.set_token()
api_auth_header = {'Authorization': 'Bearer ' + self.access_token, }
call = getattr(requests, calltype)
url = ('%s/api/%s' % (self.url, url))
try:
if (headers is not None):
headers.update(api_auth_header)
if (headers['content-type'] == 'application/json'):
r = call(url, verify=False, data=json.dumps(data),
headers=headers)
else:
r = call(url, verify=False, data=data,
headers=headers)
else:
r = call(url, verify=False, headers=api_auth_header, data=data)
except requests.exceptions.ConnectionError:
print('Error connecting to Rockstor. Is it running?')
raise
if (r.status_code == 404):
msg = ('Invalid api end point: %s' % url)
raise RockStorAPIException(detail=msg)
if (r.status_code != 200):
try:
error_d = json.loads(r.text)
if (settings.DEBUG is True and save_error is True):
cur_time = str(int(time.time()))
err_file = '/tmp/err-%s.html' % cur_time
with open(err_file, 'w') as efo:
for line in r.text.split('\n'):
efo.write('%s\n' % line)
print('Error detail is saved at %s' % err_file)
if ('detail' in error_d):
if (error_d['detail'] == 'Authentication credentials were not provided.'): # noqa E501
self.set_token()
return self.api_call(url, data=data, calltype=calltype,
headers=headers,
save_error=save_error)
raise RockStorAPIException(detail=error_d['detail'])
except ValueError as e:
raise RockStorAPIException(detail='Internal Server Error: %s'
% e.__str__())
r.raise_for_status()
try:
ret_val = r.json()
except ValueError:
ret_val = {}
return ret_val