RIC-642 related changes: REST subscription, rnib enhancements, symptomdata, rest...
[ric-plt/xapp-frame-py.git] / ricxappframe / subsclient / rest.py
1 # coding: utf-8
2
3 """
4     RIC subscription
5
6     This is the initial REST API for RIC subscription  # noqa: E501
7
8     OpenAPI spec version: 0.0.4
9     
10     Generated by: https://github.com/swagger-api/swagger-codegen.git
11 """
12
13
14 from __future__ import absolute_import
15
16 import io
17 import json
18 import logging
19 import re
20 import ssl
21
22 import certifi
23 # python 2 and python 3 compatibility library
24 import six
25 from six.moves.urllib.parse import urlencode
26
27 try:
28     import urllib3
29 except ImportError:
30     raise ImportError('Swagger python client requires urllib3.')
31
32
33 logger = logging.getLogger(__name__)
34
35
36 class RESTResponse(io.IOBase):
37
38     def __init__(self, resp):
39         self.urllib3_response = resp
40         self.status = resp.status
41         self.reason = resp.reason
42         self.data = resp.data
43
44     def getheaders(self):
45         """Returns a dictionary of the response headers."""
46         return self.urllib3_response.getheaders()
47
48     def getheader(self, name, default=None):
49         """Returns a given response header."""
50         return self.urllib3_response.getheader(name, default)
51
52
53 class RESTClientObject(object):
54
55     def __init__(self, configuration, pools_size=4, maxsize=None):
56         # urllib3.PoolManager will pass all kw parameters to connectionpool
57         # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75  # noqa: E501
58         # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680  # noqa: E501
59         # maxsize is the number of requests to host that are allowed in parallel  # noqa: E501
60         # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html  # noqa: E501
61
62         # cert_reqs
63         if configuration.verify_ssl:
64             cert_reqs = ssl.CERT_REQUIRED
65         else:
66             cert_reqs = ssl.CERT_NONE
67
68         # ca_certs
69         if configuration.ssl_ca_cert:
70             ca_certs = configuration.ssl_ca_cert
71         else:
72             # if not set certificate file, use Mozilla's root certificates.
73             ca_certs = certifi.where()
74
75         addition_pool_args = {}
76         if configuration.assert_hostname is not None:
77             addition_pool_args['assert_hostname'] = configuration.assert_hostname  # noqa: E501
78
79         if maxsize is None:
80             if configuration.connection_pool_maxsize is not None:
81                 maxsize = configuration.connection_pool_maxsize
82             else:
83                 maxsize = 4
84
85         # https pool manager
86         if configuration.proxy:
87             self.pool_manager = urllib3.ProxyManager(
88                 num_pools=pools_size,
89                 maxsize=maxsize,
90                 cert_reqs=cert_reqs,
91                 ca_certs=ca_certs,
92                 cert_file=configuration.cert_file,
93                 key_file=configuration.key_file,
94                 proxy_url=configuration.proxy,
95                 **addition_pool_args
96             )
97         else:
98             self.pool_manager = urllib3.PoolManager(
99                 num_pools=pools_size,
100                 maxsize=maxsize,
101                 cert_reqs=cert_reqs,
102                 ca_certs=ca_certs,
103                 cert_file=configuration.cert_file,
104                 key_file=configuration.key_file,
105                 **addition_pool_args
106             )
107
108     def request(self, method, url, query_params=None, headers=None,
109                 body=None, post_params=None, _preload_content=True,
110                 _request_timeout=None):
111         """Perform requests.
112
113         :param method: http request method
114         :param url: http request url
115         :param query_params: query parameters in the url
116         :param headers: http request headers
117         :param body: request json body, for `application/json`
118         :param post_params: request post parameters,
119                             `application/x-www-form-urlencoded`
120                             and `multipart/form-data`
121         :param _preload_content: if False, the urllib3.HTTPResponse object will
122                                  be returned without reading/decoding response
123                                  data. Default is True.
124         :param _request_timeout: timeout setting for this request. If one
125                                  number provided, it will be total request
126                                  timeout. It can also be a pair (tuple) of
127                                  (connection, read) timeouts.
128         """
129         method = method.upper()
130         assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
131                           'PATCH', 'OPTIONS']
132
133         if post_params and body:
134             raise ValueError(
135                 "body parameter cannot be used with post_params parameter."
136             )
137
138         post_params = post_params or {}
139         headers = headers or {}
140
141         timeout = None
142         if _request_timeout:
143             if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
144                 timeout = urllib3.Timeout(total=_request_timeout)
145             elif (isinstance(_request_timeout, tuple) and
146                   len(_request_timeout) == 2):
147                 timeout = urllib3.Timeout(
148                     connect=_request_timeout[0], read=_request_timeout[1])
149
150         if 'Content-Type' not in headers:
151             headers['Content-Type'] = 'application/json'
152
153         try:
154             # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
155             if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
156                 if query_params:
157                     url += '?' + urlencode(query_params)
158                 if re.search('json', headers['Content-Type'], re.IGNORECASE):
159                     request_body = '{}'
160                     if body is not None:
161                         request_body = json.dumps(body)
162                     r = self.pool_manager.request(
163                         method, url,
164                         body=request_body,
165                         preload_content=_preload_content,
166                         timeout=timeout,
167                         headers=headers)
168                 elif headers['Content-Type'] == 'application/x-www-form-urlencoded':  # noqa: E501
169                     r = self.pool_manager.request(
170                         method, url,
171                         fields=post_params,
172                         encode_multipart=False,
173                         preload_content=_preload_content,
174                         timeout=timeout,
175                         headers=headers)
176                 elif headers['Content-Type'] == 'multipart/form-data':
177                     # must del headers['Content-Type'], or the correct
178                     # Content-Type which generated by urllib3 will be
179                     # overwritten.
180                     del headers['Content-Type']
181                     r = self.pool_manager.request(
182                         method, url,
183                         fields=post_params,
184                         encode_multipart=True,
185                         preload_content=_preload_content,
186                         timeout=timeout,
187                         headers=headers)
188                 # Pass a `string` parameter directly in the body to support
189                 # other content types than Json when `body` argument is
190                 # provided in serialized form
191                 elif isinstance(body, str):
192                     request_body = body
193                     r = self.pool_manager.request(
194                         method, url,
195                         body=request_body,
196                         preload_content=_preload_content,
197                         timeout=timeout,
198                         headers=headers)
199                 else:
200                     # Cannot generate the request from given parameters
201                     msg = """Cannot prepare a request message for provided
202                              arguments. Please check that your arguments match
203                              declared content type."""
204                     raise ApiException(status=0, reason=msg)
205             # For `GET`, `HEAD`
206             else:
207                 r = self.pool_manager.request(method, url,
208                                               fields=query_params,
209                                               preload_content=_preload_content,
210                                               timeout=timeout,
211                                               headers=headers)
212         except urllib3.exceptions.SSLError as e:
213             msg = "{0}\n{1}".format(type(e).__name__, str(e))
214             raise ApiException(status=0, reason=msg)
215
216         if _preload_content:
217             r = RESTResponse(r)
218
219             # In the python 3, the response.data is bytes.
220             # we need to decode it to string.
221             if six.PY3:
222                 r.data = r.data.decode('utf8')
223
224             # log response body
225             logger.debug("response body: %s", r.data)
226
227         if not 200 <= r.status <= 299:
228             raise ApiException(http_resp=r)
229
230         return r
231
232     def GET(self, url, headers=None, query_params=None, _preload_content=True,
233             _request_timeout=None):
234         return self.request("GET", url,
235                             headers=headers,
236                             _preload_content=_preload_content,
237                             _request_timeout=_request_timeout,
238                             query_params=query_params)
239
240     def HEAD(self, url, headers=None, query_params=None, _preload_content=True,
241              _request_timeout=None):
242         return self.request("HEAD", url,
243                             headers=headers,
244                             _preload_content=_preload_content,
245                             _request_timeout=_request_timeout,
246                             query_params=query_params)
247
248     def OPTIONS(self, url, headers=None, query_params=None, post_params=None,
249                 body=None, _preload_content=True, _request_timeout=None):
250         return self.request("OPTIONS", url,
251                             headers=headers,
252                             query_params=query_params,
253                             post_params=post_params,
254                             _preload_content=_preload_content,
255                             _request_timeout=_request_timeout,
256                             body=body)
257
258     def DELETE(self, url, headers=None, query_params=None, body=None,
259                _preload_content=True, _request_timeout=None):
260         return self.request("DELETE", url,
261                             headers=headers,
262                             query_params=query_params,
263                             _preload_content=_preload_content,
264                             _request_timeout=_request_timeout,
265                             body=body)
266
267     def POST(self, url, headers=None, query_params=None, post_params=None,
268              body=None, _preload_content=True, _request_timeout=None):
269         return self.request("POST", url,
270                             headers=headers,
271                             query_params=query_params,
272                             post_params=post_params,
273                             _preload_content=_preload_content,
274                             _request_timeout=_request_timeout,
275                             body=body)
276
277     def PUT(self, url, headers=None, query_params=None, post_params=None,
278             body=None, _preload_content=True, _request_timeout=None):
279         return self.request("PUT", url,
280                             headers=headers,
281                             query_params=query_params,
282                             post_params=post_params,
283                             _preload_content=_preload_content,
284                             _request_timeout=_request_timeout,
285                             body=body)
286
287     def PATCH(self, url, headers=None, query_params=None, post_params=None,
288               body=None, _preload_content=True, _request_timeout=None):
289         return self.request("PATCH", url,
290                             headers=headers,
291                             query_params=query_params,
292                             post_params=post_params,
293                             _preload_content=_preload_content,
294                             _request_timeout=_request_timeout,
295                             body=body)
296
297
298 class ApiException(Exception):
299
300     def __init__(self, status=None, reason=None, http_resp=None):
301         if http_resp:
302             self.status = http_resp.status
303             self.reason = http_resp.reason
304             self.body = http_resp.data
305             self.headers = http_resp.getheaders()
306         else:
307             self.status = status
308             self.reason = reason
309             self.body = None
310             self.headers = None
311
312     def __str__(self):
313         """Custom error messages for exception"""
314         error_message = "({0})\n"\
315                         "Reason: {1}\n".format(self.status, self.reason)
316         if self.headers:
317             error_message += "HTTP response headers: {0}\n".format(
318                 self.headers)
319
320         if self.body:
321             error_message += "HTTP response body: {0}\n".format(self.body)
322
323         return error_message