Coverage for manila/share/drivers/quobyte/jsonrpc.py: 92%

58 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright (c) 2015 Quobyte Inc. 

2# All Rights Reserved. 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); you may 

5# not use this file except in compliance with the License. You may obtain 

6# a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

13# License for the specific language governing permissions and limitations 

14# under the License. 

15 

16"""Quobyte driver helper. 

17 

18Control Quobyte over its JSON RPC API. 

19""" 

20 

21import requests 

22from requests import auth 

23from requests import codes 

24from urllib import parse as urlparse 

25 

26from oslo_log import log 

27from oslo_serialization import jsonutils 

28 

29from manila import exception 

30from manila import utils 

31 

32LOG = log.getLogger(__name__) 

33 

34ERROR_ENOENT = 2 

35ERROR_ENTITY_NOT_FOUND = -24 

36ERROR_GARBAGE_ARGS = -3 

37 

38 

39class JsonRpc(object): 

40 

41 def __init__(self, url, user_credentials, ca_file=None, key_file=None, 

42 cert_file=None): 

43 parsedurl = urlparse.urlparse(url) 

44 self._url = parsedurl.geturl() 

45 self._netloc = parsedurl.netloc 

46 self._ca_file = ca_file 

47 self._url_scheme = parsedurl.scheme 

48 if self._url_scheme == 'https': 

49 if not self._ca_file: 

50 self._ca_file = False 

51 LOG.warning( 

52 "Will not verify the server certificate of the API service" 

53 " because the CA certificate is not available.") 

54 self._id = 0 

55 self._credentials = auth.HTTPBasicAuth( 

56 user_credentials[0], user_credentials[1]) 

57 self._key_file = key_file 

58 self._cert_file = cert_file 

59 

60 @utils.synchronized('quobyte-request') 

61 def call(self, method_name, user_parameters, expected_errors=None): 

62 if expected_errors is None: 

63 expected_errors = [] 

64 # prepare request 

65 self._id += 1 

66 parameters = {'retry': 'INFINITELY'} # Backend specific setting 

67 if user_parameters: 67 ↛ 69line 67 didn't jump to line 69 because the condition on line 67 was always true

68 parameters.update(user_parameters) 

69 post_data = { 

70 'jsonrpc': '2.0', 

71 'method': method_name, 

72 'params': parameters, 

73 'id': str(self._id), 

74 } 

75 LOG.debug("Request payload to be send is: %s", 

76 jsonutils.dumps(post_data)) 

77 

78 # send request 

79 if self._url_scheme == 'https': 

80 if self._cert_file: 

81 result = requests.post(url=self._url, 

82 json=post_data, 

83 auth=self._credentials, 

84 verify=self._ca_file, 

85 cert=(self._cert_file, self._key_file), 

86 timeout=60) 

87 else: 

88 result = requests.post(url=self._url, 

89 json=post_data, 

90 auth=self._credentials, 

91 verify=self._ca_file, 

92 timeout=60) 

93 else: 

94 result = requests.post(url=self._url, 

95 json=post_data, 

96 auth=self._credentials, 

97 timeout=60) 

98 

99 # eval request response 

100 if result.status_code == codes['OK']: 100 ↛ 107line 100 didn't jump to line 107 because the condition on line 100 was always true

101 LOG.debug("Retrieved data from Quobyte backend: %s", result.text) 

102 response = result.json() 

103 return self._checked_for_application_error(response, 

104 expected_errors) 

105 

106 # If things did not work out provide error info 

107 LOG.debug("Backend request resulted in error: %s", result.text) 

108 result.raise_for_status() 

109 

110 def _checked_for_application_error(self, result, expected_errors=None): 

111 if expected_errors is None: 

112 expected_errors = [] 

113 if 'error' in result and result['error']: 

114 if 'message' in result['error'] and 'code' in result['error']: 114 ↛ 123line 114 didn't jump to line 123 because the condition on line 114 was always true

115 if result["error"]["code"] in expected_errors: 

116 # hit an expected error, return empty result 

117 return None 

118 else: 

119 raise exception.QBRpcException( 

120 result=result["error"]["message"], 

121 qbcode=result["error"]["code"]) 

122 else: 

123 raise exception.QBException(str(result["error"])) 

124 return result["result"]