PyPowerStore 3.4.0.0__tar.gz → 3.4.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pypowerstore-3.4.1.1/PKG-INFO +20 -0
- pypowerstore-3.4.1.1/PyPowerStore/__init__.py +9 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/client.py +196 -130
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/configuration.py +935 -711
- pypowerstore-3.4.1.1/PyPowerStore/metrics.py +62 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/__init__.py +7 -10
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/file_dns.py +42 -33
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/file_interface.py +53 -40
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/file_nis.py +43 -35
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/nfs_server.py +45 -37
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/smb_server.py +43 -36
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/objects/snmp_server.py +38 -29
- pypowerstore-3.4.1.1/PyPowerStore/powerstore_conn.py +71 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/protection.py +470 -393
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/provisioning.py +2711 -2423
- pypowerstore-3.4.1.1/PyPowerStore/utils/__init__.py +5 -0
- pypowerstore-3.4.1.1/PyPowerStore/utils/constants.py +847 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/utils/exception.py +1 -1
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore/utils/helpers.py +94 -71
- pypowerstore-3.4.1.1/PyPowerStore.egg-info/PKG-INFO +20 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore.egg-info/SOURCES.txt +1 -0
- pypowerstore-3.4.1.1/PyPowerStore.egg-info/requires.txt +4 -0
- pypowerstore-3.4.1.1/setup.py +24 -0
- PyPowerStore-3.4.0.0/PKG-INFO +0 -14
- PyPowerStore-3.4.0.0/PyPowerStore/__init__.py +0 -8
- PyPowerStore-3.4.0.0/PyPowerStore/powerstore_conn.py +0 -60
- PyPowerStore-3.4.0.0/PyPowerStore/utils/__init__.py +0 -0
- PyPowerStore-3.4.0.0/PyPowerStore/utils/constants.py +0 -832
- PyPowerStore-3.4.0.0/PyPowerStore.egg-info/PKG-INFO +0 -14
- PyPowerStore-3.4.0.0/PyPowerStore.egg-info/requires.txt +0 -2
- PyPowerStore-3.4.0.0/setup.py +0 -25
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/LICENSE +0 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore.egg-info/dependency_links.txt +0 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/PyPowerStore.egg-info/top_level.txt +0 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/README.md +0 -0
- {PyPowerStore-3.4.0.0 → pypowerstore-3.4.1.1}/setup.cfg +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyPowerStore
|
|
3
|
+
Version: 3.4.1.1
|
|
4
|
+
Summary: Python Library for Dell PowerStore
|
|
5
|
+
Home-page: https://github.com/dell/python-powerstore
|
|
6
|
+
Author: Ansible Team at Dell
|
|
7
|
+
Author-email: ansible.team@dell.com
|
|
8
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: urllib3>=1.26.7
|
|
11
|
+
Requires-Dist: requests>=2.23.0
|
|
12
|
+
Requires-Dist: packaging>=26.0
|
|
13
|
+
Requires-Dist: setuptools>=80.10.2
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: home-page
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
Dynamic: requires-dist
|
|
20
|
+
Dynamic: summary
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright: (c) 2024, Dell Technologies
|
|
3
2
|
|
|
4
3
|
"""Client module for PowerStore"""
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
# pylint: disable=too-many-instance-attributes,too-many-arguments,too-many-positional-arguments,no-member,too-many-nested-blocks,too-many-branches,global-statement
|
|
6
|
+
|
|
7
7
|
import base64
|
|
8
|
-
import
|
|
9
|
-
import requests
|
|
8
|
+
import json
|
|
10
9
|
import time
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
from requests.exceptions import TooManyRedirects
|
|
14
|
-
|
|
15
|
-
from PyPowerStore.utils.exception import PowerStoreException
|
|
10
|
+
|
|
11
|
+
import requests
|
|
12
|
+
from requests.exceptions import SSLError, Timeout, TooManyRedirects
|
|
13
|
+
|
|
16
14
|
from PyPowerStore.utils import constants, helpers
|
|
15
|
+
from PyPowerStore.utils.exception import PowerStoreException
|
|
17
16
|
|
|
18
17
|
requests.packages.urllib3.disable_warnings()
|
|
19
18
|
|
|
20
|
-
# TODO: kept LOG as global for now will improve it to avoid overriding
|
|
21
19
|
LOG = helpers.get_logger(__name__)
|
|
22
20
|
|
|
23
21
|
# Codes
|
|
@@ -28,10 +26,10 @@ ENGVIS_LIST = ["remote_support", "node", "volume_group", "remote_system"]
|
|
|
28
26
|
class AuthenticationManager:
|
|
29
27
|
"""Manage the powerstore authentication"""
|
|
30
28
|
|
|
31
|
-
def __init__(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Initializes AuthenticationManager
|
|
29
|
+
def __init__(
|
|
30
|
+
self, username, password, verify, application_type, timeout, host=None,
|
|
31
|
+
):
|
|
32
|
+
"""Initializes AuthenticationManager
|
|
35
33
|
|
|
36
34
|
:param username: array username
|
|
37
35
|
:type username: str
|
|
@@ -58,10 +56,10 @@ class AuthenticationManager:
|
|
|
58
56
|
self.idle_timeout = 0
|
|
59
57
|
self.creation_time = None
|
|
60
58
|
self.headers = {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
"Accept": constants.APP_JSON,
|
|
60
|
+
"Accept-Language": constants.EN_US,
|
|
61
|
+
"content-type": constants.APP_JSON,
|
|
62
|
+
"Application-Type": self.application_type,
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
def set_host(self, host):
|
|
@@ -71,23 +69,32 @@ class AuthenticationManager:
|
|
|
71
69
|
def get_authorization(self):
|
|
72
70
|
"""Get the authorization header"""
|
|
73
71
|
credentials = base64.b64encode(
|
|
74
|
-
"{username}:{password}".
|
|
75
|
-
|
|
76
|
-
return {
|
|
72
|
+
f"{self.username}:{self.password}".encode(),
|
|
73
|
+
)
|
|
74
|
+
return {"authorization": "Basic " + credentials.decode()}
|
|
77
75
|
|
|
78
76
|
def set_session_timeout_and_creation_time(self, login_response):
|
|
79
77
|
"""Set the session timeout from login response object"""
|
|
80
78
|
if login_response.status_code == 200:
|
|
81
79
|
self.creation_time = time.time()
|
|
82
80
|
json_response = login_response.json()
|
|
83
|
-
login_data =
|
|
84
|
-
|
|
81
|
+
login_data = (
|
|
82
|
+
login_response.json()[0] if isinstance(json_response, list) else {}
|
|
83
|
+
)
|
|
84
|
+
self.idle_timeout = (
|
|
85
|
+
login_data["idle_timeout"]
|
|
86
|
+
if "idle_timeout" in login_data
|
|
87
|
+
else self.idle_timeout
|
|
88
|
+
)
|
|
85
89
|
|
|
86
90
|
def is_session_alive(self):
|
|
87
91
|
"""Check if the session is alive or not"""
|
|
88
|
-
if
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
if (
|
|
93
|
+
self.creation_time
|
|
94
|
+
and self.idle_timeout
|
|
95
|
+
and ((time.time() - self.creation_time) < self.idle_timeout)
|
|
96
|
+
):
|
|
97
|
+
return True
|
|
91
98
|
return False
|
|
92
99
|
|
|
93
100
|
def login(self):
|
|
@@ -96,11 +103,16 @@ class AuthenticationManager:
|
|
|
96
103
|
login_headers = dict(self.headers)
|
|
97
104
|
login_headers.update(self.get_authorization())
|
|
98
105
|
response = requests.request(
|
|
99
|
-
constants.GET,
|
|
100
|
-
|
|
106
|
+
constants.GET,
|
|
107
|
+
login_url,
|
|
108
|
+
headers=login_headers,
|
|
109
|
+
verify=self.verify,
|
|
110
|
+
timeout=self.timeout,
|
|
111
|
+
params=constants.LOGIN_SESSION_DETAILS_QUERY,
|
|
112
|
+
)
|
|
101
113
|
self.set_session_timeout_and_creation_time(response)
|
|
102
|
-
self.dell_emc_token = response.headers.get(
|
|
103
|
-
self.cookie = response.cookies.get(
|
|
114
|
+
self.dell_emc_token = response.headers.get("DELL-EMC-TOKEN")
|
|
115
|
+
self.cookie = response.cookies.get("auth_cookie")
|
|
104
116
|
|
|
105
117
|
def get_token_and_cookie(self):
|
|
106
118
|
"""Get the DELL-EMC-TOKEN and set-cookie"""
|
|
@@ -108,28 +120,42 @@ class AuthenticationManager:
|
|
|
108
120
|
if not self.dell_emc_token or not self.cookie or not self.is_session_alive():
|
|
109
121
|
self.login()
|
|
110
122
|
|
|
111
|
-
auth_tokens.update({
|
|
112
|
-
auth_tokens.update({
|
|
123
|
+
auth_tokens.update({"DELL-EMC-TOKEN": self.dell_emc_token})
|
|
124
|
+
auth_tokens.update({"Cookie": f"auth_cookie={self.cookie}"})
|
|
113
125
|
return auth_tokens
|
|
114
126
|
|
|
115
127
|
def logout_session(self):
|
|
116
|
-
"""
|
|
128
|
+
"""Logout the current session"""
|
|
117
129
|
login_url = constants.LOGOUT_URL.format(self.host)
|
|
118
130
|
logout_headers = {}
|
|
119
131
|
logout_headers.update(self.headers)
|
|
120
|
-
logout_headers.update({
|
|
121
|
-
logout_headers.update({
|
|
132
|
+
logout_headers.update({"DELL-EMC-TOKEN": self.dell_emc_token})
|
|
133
|
+
logout_headers.update({"Cookie": f"auth_cookie={self.cookie}"})
|
|
122
134
|
requests.request(
|
|
123
|
-
constants.POST,
|
|
124
|
-
|
|
135
|
+
constants.POST,
|
|
136
|
+
login_url,
|
|
137
|
+
headers=logout_headers,
|
|
138
|
+
verify=self.verify,
|
|
139
|
+
data=None,
|
|
140
|
+
timeout=self.timeout,
|
|
141
|
+
)
|
|
125
142
|
self.dell_emc_token = None
|
|
126
143
|
self.cookie = None
|
|
127
144
|
|
|
128
|
-
|
|
145
|
+
|
|
146
|
+
class Client:
|
|
129
147
|
"""Client class for PowerStore"""
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
148
|
+
|
|
149
|
+
def __init__(
|
|
150
|
+
self,
|
|
151
|
+
username,
|
|
152
|
+
password,
|
|
153
|
+
verify,
|
|
154
|
+
application_type,
|
|
155
|
+
timeout=None,
|
|
156
|
+
enable_log=False,
|
|
157
|
+
):
|
|
158
|
+
"""Initializes Client Class
|
|
133
159
|
|
|
134
160
|
:param username: array username
|
|
135
161
|
:type username: str
|
|
@@ -145,23 +171,26 @@ class Client():
|
|
|
145
171
|
:type enable_log: bool
|
|
146
172
|
:type timeout: float
|
|
147
173
|
"""
|
|
148
|
-
global LOG
|
|
149
174
|
self.username = username
|
|
150
175
|
self.password = password
|
|
151
176
|
self.verify = verify
|
|
152
177
|
self.application_type = application_type
|
|
153
178
|
"""Setting default timeout"""
|
|
154
179
|
self.timeout = timeout if timeout else constants.TIMEOUT
|
|
155
|
-
self.auth_manager = AuthenticationManager(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
180
|
+
self.auth_manager = AuthenticationManager(
|
|
181
|
+
self.username,
|
|
182
|
+
self.password,
|
|
183
|
+
self.verify,
|
|
184
|
+
self.application_type,
|
|
185
|
+
self.timeout,
|
|
186
|
+
)
|
|
187
|
+
global LOG # Reset LOG based on param
|
|
160
188
|
LOG = helpers.get_logger(__name__, enable_log=enable_log)
|
|
161
189
|
|
|
162
|
-
def fetch_response(
|
|
163
|
-
|
|
164
|
-
|
|
190
|
+
def fetch_response(
|
|
191
|
+
self, http_method, url, payload=None, querystring=None, myrange=None,
|
|
192
|
+
):
|
|
193
|
+
"""Fetch & return the response based on request parameters.
|
|
165
194
|
|
|
166
195
|
:param http_method: HTTP Method
|
|
167
196
|
:type http_method: str
|
|
@@ -176,45 +205,59 @@ class Client():
|
|
|
176
205
|
:return: Request's response.
|
|
177
206
|
:rtype: requests.models.Response object
|
|
178
207
|
"""
|
|
179
|
-
|
|
180
208
|
headers = {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
209
|
+
"Accept": "application/json",
|
|
210
|
+
"Accept-Language": "en-US",
|
|
211
|
+
"content-type": "application/json",
|
|
212
|
+
"Application-Type": self.application_type,
|
|
185
213
|
}
|
|
186
|
-
split_host = url.split(
|
|
214
|
+
split_host = url.split("/")
|
|
187
215
|
self.auth_manager.set_host(split_host[2])
|
|
188
216
|
auth_headers = self.auth_manager.get_token_and_cookie()
|
|
189
217
|
|
|
190
218
|
if split_host[5] in ENGVIS_LIST:
|
|
191
|
-
headers[
|
|
219
|
+
headers["DELL-VISIBILITY"] = "internal"
|
|
192
220
|
|
|
193
221
|
if auth_headers:
|
|
194
222
|
headers.update(auth_headers)
|
|
195
223
|
|
|
196
|
-
LOG.debug(
|
|
197
|
-
|
|
198
|
-
|
|
224
|
+
LOG.debug(
|
|
225
|
+
"Request's http_method: '%s' url: '%s' payload: '%s' querystring: '%s' myrange: '%s'"
|
|
226
|
+
, http_method, url, payload, querystring, myrange
|
|
227
|
+
)
|
|
199
228
|
if myrange:
|
|
200
229
|
headers["Range"] = myrange
|
|
201
230
|
|
|
202
231
|
if payload:
|
|
203
232
|
response = requests.request(
|
|
204
|
-
http_method,
|
|
205
|
-
|
|
233
|
+
http_method,
|
|
234
|
+
url,
|
|
235
|
+
data=json.dumps(payload),
|
|
236
|
+
headers=headers,
|
|
237
|
+
verify=self.verify,
|
|
238
|
+
timeout=self.timeout,
|
|
239
|
+
)
|
|
206
240
|
elif querystring:
|
|
207
241
|
response = requests.request(
|
|
208
|
-
http_method,
|
|
209
|
-
|
|
242
|
+
http_method,
|
|
243
|
+
url,
|
|
244
|
+
headers=headers,
|
|
245
|
+
params=querystring,
|
|
246
|
+
verify=self.verify,
|
|
247
|
+
timeout=self.timeout,
|
|
248
|
+
)
|
|
210
249
|
else:
|
|
211
250
|
response = requests.request(
|
|
212
|
-
http_method,
|
|
213
|
-
|
|
251
|
+
http_method,
|
|
252
|
+
url,
|
|
253
|
+
headers=headers,
|
|
254
|
+
verify=self.verify,
|
|
255
|
+
timeout=self.timeout,
|
|
256
|
+
)
|
|
214
257
|
return response
|
|
215
258
|
|
|
216
259
|
def is_valid_response(self, response):
|
|
217
|
-
"""
|
|
260
|
+
"""Check whether response is valid or not
|
|
218
261
|
|
|
219
262
|
:param response: Request's response.
|
|
220
263
|
:type response: requests.models.Response
|
|
@@ -225,57 +268,75 @@ class Client():
|
|
|
225
268
|
return False
|
|
226
269
|
|
|
227
270
|
def raise_http_exception(self, response):
|
|
228
|
-
"""
|
|
271
|
+
"""Raises PowerStoreException
|
|
229
272
|
|
|
230
273
|
:param response: Request's response.
|
|
231
274
|
:type response: requests.models.Response
|
|
232
275
|
"""
|
|
233
276
|
if response.status_code == 500:
|
|
234
|
-
error_msg = "PowerStore internal server error. Error "
|
|
235
|
-
|
|
277
|
+
error_msg = "PowerStore internal server error. Error details: " + str(
|
|
278
|
+
response.json(),
|
|
279
|
+
)
|
|
236
280
|
elif response.status_code == 401:
|
|
237
281
|
error_msg = "Access forbidden: Authentication required."
|
|
238
282
|
elif response.status_code == 403:
|
|
239
|
-
error_msg = "Not allowed - authorization failure. "
|
|
240
|
-
|
|
283
|
+
error_msg = "Not allowed - authorization failure. Error details: " + str(
|
|
284
|
+
response.json(),
|
|
285
|
+
)
|
|
241
286
|
elif response.status_code == 404:
|
|
242
|
-
error_msg = "Requested resource not found. "
|
|
243
|
-
|
|
287
|
+
error_msg = "Requested resource not found. Error details: " + str(
|
|
288
|
+
response.json(),
|
|
289
|
+
)
|
|
244
290
|
elif response.status_code == 405:
|
|
245
|
-
error_msg =
|
|
246
|
-
|
|
291
|
+
error_msg = (
|
|
292
|
+
"The HTTP method is not supported on that URL. "
|
|
293
|
+
"Error details: " + str(response.json())
|
|
294
|
+
)
|
|
247
295
|
elif response.status_code == 406:
|
|
248
|
-
error_msg =
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
296
|
+
error_msg = (
|
|
297
|
+
"Not acceptable - the server cannot satisfy the "
|
|
298
|
+
"Accept: header in the request. Either the format "
|
|
299
|
+
"or version requested is not supported. "
|
|
300
|
+
"Error details: " + str(response.json())
|
|
301
|
+
)
|
|
252
302
|
elif response.status_code == 415:
|
|
253
|
-
error_msg = "Invalid request Content-Type. "
|
|
254
|
-
|
|
303
|
+
error_msg = "Invalid request Content-Type. Error details: " + str(
|
|
304
|
+
response.json(),
|
|
305
|
+
)
|
|
255
306
|
elif response.status_code == 416:
|
|
256
|
-
error_msg =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
307
|
+
error_msg = (
|
|
308
|
+
"Range Not Satisfiable. The client requested a "
|
|
309
|
+
"starting offset (using the ?offset URL parameter, "
|
|
310
|
+
"or the first value in Range header) that was "
|
|
311
|
+
"larger than the number of instances in the queried "
|
|
312
|
+
"result set. Error details: " + str(response.json())
|
|
313
|
+
)
|
|
261
314
|
elif response.status_code == 422:
|
|
262
|
-
error_msg = "Request could not be completed. "
|
|
263
|
-
|
|
315
|
+
error_msg = "Request could not be completed. Error details: " + str(
|
|
316
|
+
response.json(),
|
|
317
|
+
)
|
|
264
318
|
elif response.status_code == 503:
|
|
265
|
-
error_msg =
|
|
266
|
-
|
|
319
|
+
error_msg = (
|
|
320
|
+
"The service is temporarily unavailable. "
|
|
321
|
+
"Error details: " + str(response.json())
|
|
322
|
+
)
|
|
267
323
|
else:
|
|
268
324
|
error_msg = str(response.json())
|
|
269
325
|
LOG.error(error_msg)
|
|
270
|
-
raise PowerStoreException(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
326
|
+
raise PowerStoreException(
|
|
327
|
+
PowerStoreException.HTTP_ERR,
|
|
328
|
+
"HTTP code: "
|
|
329
|
+
+ str(response.status_code)
|
|
330
|
+
+ ", "
|
|
331
|
+
+ response.reason
|
|
332
|
+
+ " ["
|
|
333
|
+
+ error_msg
|
|
334
|
+
+ "]",
|
|
335
|
+
str(response.status_code),
|
|
336
|
+
)
|
|
276
337
|
|
|
277
338
|
def get_total_size_from_content_range(self, content_range):
|
|
278
|
-
"""
|
|
339
|
+
"""Extract & return total_size from content_range
|
|
279
340
|
|
|
280
341
|
:param http_method: HTTP Method
|
|
281
342
|
:type http_method: str
|
|
@@ -286,8 +347,7 @@ class Client():
|
|
|
286
347
|
total_size = int(total_size)
|
|
287
348
|
return total_size
|
|
288
349
|
|
|
289
|
-
def request(self, http_method, url, payload=None, querystring=None,
|
|
290
|
-
all_pages=None):
|
|
350
|
+
def request(self, http_method, url, payload=None, querystring=None, all_pages=None):
|
|
291
351
|
"""Method which serves requests to PowerStore.
|
|
292
352
|
|
|
293
353
|
:param http_method: HTTP Method
|
|
@@ -304,71 +364,77 @@ class Client():
|
|
|
304
364
|
:return: Request's response.
|
|
305
365
|
:rtype: dict or list of dict
|
|
306
366
|
"""
|
|
307
|
-
|
|
308
367
|
try:
|
|
309
368
|
|
|
310
369
|
response = self.fetch_response(
|
|
311
|
-
http_method, url, payload=payload, querystring=querystring
|
|
370
|
+
http_method, url, payload=payload, querystring=querystring,
|
|
371
|
+
)
|
|
312
372
|
try:
|
|
313
373
|
if self.is_valid_response(response):
|
|
314
374
|
response_json = None
|
|
315
375
|
if response.status_code != 204:
|
|
316
|
-
if response.status_code == 201 and response.content == b
|
|
376
|
+
if response.status_code == 201 and response.content == b"":
|
|
317
377
|
pass
|
|
318
378
|
else:
|
|
319
379
|
response_json = response.json()
|
|
320
380
|
# check 'all_pages' required, response received is
|
|
321
381
|
# partial(code 206) and contains info about total size of
|
|
322
382
|
# the collection
|
|
323
|
-
content_range = response.headers.get(
|
|
324
|
-
if all_pages and response.status_code == 206 and
|
|
325
|
-
content_range:
|
|
383
|
+
content_range = response.headers.get("content-range")
|
|
384
|
+
if all_pages and response.status_code == 206 and content_range:
|
|
326
385
|
# 'content-range': '0-99/789'
|
|
327
386
|
total_size = self.get_total_size_from_content_range(
|
|
328
|
-
|
|
387
|
+
content_range,
|
|
388
|
+
)
|
|
329
389
|
myranges = [
|
|
330
|
-
"{
|
|
331
|
-
for i in range(
|
|
332
|
-
|
|
390
|
+
f"{i}-{i + constants.MAX_LIMIT}"
|
|
391
|
+
for i in range(
|
|
392
|
+
constants.OFFSET, total_size, constants.MAX_LIMIT,
|
|
393
|
+
)
|
|
394
|
+
]
|
|
333
395
|
for myrange in myranges:
|
|
334
396
|
response = self.fetch_response(
|
|
335
|
-
http_method,
|
|
336
|
-
|
|
397
|
+
http_method,
|
|
398
|
+
url,
|
|
399
|
+
payload=payload,
|
|
400
|
+
querystring=querystring,
|
|
401
|
+
myrange=myrange,
|
|
402
|
+
)
|
|
337
403
|
if self.is_valid_response(response):
|
|
338
404
|
response_json.extend(response.json())
|
|
339
405
|
else:
|
|
340
406
|
self.raise_http_exception(response)
|
|
341
407
|
|
|
342
408
|
return response_json
|
|
343
|
-
|
|
344
|
-
|
|
409
|
+
self.raise_http_exception(response)
|
|
410
|
+
return None
|
|
345
411
|
|
|
346
412
|
except ValueError as ex:
|
|
347
413
|
# its low-level or response level error caused by
|
|
348
414
|
# response.json() and not in requests.exceptions
|
|
349
|
-
error_msg =
|
|
350
|
-
"
|
|
351
|
-
|
|
415
|
+
error_msg = (
|
|
416
|
+
f"ValueError: '{ex!s}' for Method: '{http_method}' URL: '{url}'"
|
|
417
|
+
f" PayLoad: '{payload}' QueryString: '{querystring}'"
|
|
418
|
+
)
|
|
352
419
|
LOG.error(error_msg)
|
|
353
|
-
raise PowerStoreException(PowerStoreException.VALUE_ERROR,
|
|
354
|
-
error_msg)
|
|
355
|
-
except socket.error as exception:
|
|
356
|
-
LOG.error(str(exception))
|
|
357
|
-
raise PowerStoreException(PowerStoreException.SOCKET_ERR,
|
|
358
|
-
str(exception))
|
|
420
|
+
raise PowerStoreException(PowerStoreException.VALUE_ERROR, error_msg) from ex
|
|
359
421
|
except SSLError as exception:
|
|
360
422
|
LOG.error(str(exception))
|
|
361
|
-
raise PowerStoreException(PowerStoreException.SSL_ERROR,
|
|
362
|
-
str(exception))
|
|
423
|
+
raise PowerStoreException(PowerStoreException.SSL_ERROR, str(exception)) from exception
|
|
363
424
|
except ConnectionError as exception:
|
|
364
425
|
LOG.error(str(exception))
|
|
365
|
-
raise PowerStoreException(
|
|
366
|
-
|
|
426
|
+
raise PowerStoreException(
|
|
427
|
+
PowerStoreException.CONNECTION_ERROR, str(exception),
|
|
428
|
+
) from exception
|
|
367
429
|
except TooManyRedirects as exception:
|
|
368
430
|
LOG.error(str(exception))
|
|
369
431
|
raise PowerStoreException(
|
|
370
|
-
PowerStoreException.TOO_MANY_REDIRECTS_ERROR, str(exception)
|
|
432
|
+
PowerStoreException.TOO_MANY_REDIRECTS_ERROR, str(exception),
|
|
433
|
+
) from exception
|
|
371
434
|
except Timeout as exception:
|
|
372
435
|
LOG.error(str(exception))
|
|
373
|
-
raise PowerStoreException(PowerStoreException.TIMEOUT_ERROR,
|
|
374
|
-
|
|
436
|
+
raise PowerStoreException(PowerStoreException.TIMEOUT_ERROR, str(exception)
|
|
437
|
+
) from exception
|
|
438
|
+
except OSError as exception:
|
|
439
|
+
LOG.error(str(exception))
|
|
440
|
+
raise PowerStoreException(PowerStoreException.SOCKET_ERR, str(exception)) from exception
|