/
api_wrapper.py
136 lines (122 loc) · 5.17 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
126
127
128
129
130
131
132
133
134
135
136
"""
Copyright (c) 2012-2020 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:8000"
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