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
|
# Copyright (C) 2018 Red Hat, Inc. <http://www.redhat.com>
#
# This program 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
# any later version.
#
# This program 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Description: Library to handle all the common REST methods like GET, POST
& DELETE
"""
import json
import datetime
import hashlib
import jwt
import requests
from glusto.core import Glusto as g
class RestClient(object):
'''
Class contains common methods for POST, GET, DELETE and
verifies authentication
'''
def __init__(self, mnode, port='24007', user='glustercli', secret=None,
verify=False):
"""
Function to form base url and to get secret key
Args:
mnode (str): The server on which the command has to be executed
port (str) : The port which API calls use
user (str) : By default the user is glustercli
"""
self.user = user
self.mnode = mnode
self.secret = secret
self.verify = verify
self.port = port
self.base_url = ('http://{mnode}:{port}'.format(mnode=mnode,
port=port))
if self.secret is None:
_, self.secret, _ = g.run(mnode, "cat /var/lib/glusterd2/auth")
def _set_token_in_header(self, method, url, headers=None):
"""
Function to set token in header
Args:
method (str): It can be GET, POST or DELETE
url (str): The url for operation
For Example:
token = _set_token_in_header('GET', '/v1/peers')
"""
if headers is None:
headers = dict()
claims = dict()
claims['iss'] = self.user
# Issued at time
claims['iat'] = datetime.datetime.utcnow()
# Expiration time
claims['exp'] = datetime.datetime.utcnow() + datetime.timedelta(
seconds=1)
# URI tampering protection
val = b'%s&%s' % (method.encode('utf8'), url.encode('utf8'))
claims['qsh'] = hashlib.sha256(val).hexdigest()
token = jwt.encode(claims, self.secret, algorithm='HS256')
headers['Authorization'] = b'bearer ' + token
return headers
def handle_request(self, method, url, expected_status_code, data=None):
""" Function that handles all the methods(GET, POST, DELETE)
Args:
method (str): It can be GET, POST, DELETE
url (str): The url of the operation
expected_status_code (str) : The status_code expected after
the API call
data (str): The json input that needs to be passed
Returns:
tuple: Tuple containing three elements (ret, out, err).
The first element 'ret' is of type 'int' and returns the status
code of command execution.
The second element 'out' is of type 'str' and is the
stdout value
The third element 'err' is of type 'str' and is the
stderr message|value of the command execution.
Example:
handle_request('GET', "/v1/volumes", '200')
handle_request('POST', "/vi/volumes", '201', data)
"""
headers = self._set_token_in_header(method, url)
resp = requests.request(method, self.base_url + url,
data=json.dumps(data),
headers=headers, verify=self.verify)
if resp.status_code != expected_status_code:
return (1, None, json.dumps(resp.json()))
if resp.status_code == 204:
return (resp.status_code, None, None)
return (0, json.dumps(resp.json()), None)
|