summaryrefslogtreecommitdiffstats
path: root/glustolibs-gluster-gd2/glustolibs/gluster/rest.py
blob: f687ea3dff90cba7342b685dd5ef76783e8be522 (plain)
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)