Coverage for src/zenossapi/routers/__init__.py: 85%

52 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-25 05:47 +0000

1# -*- coding: utf-8 -*- 

2import logging 

3import requests 

4import json 

5from requests import ReadTimeout 

6from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type 

7from requests.exceptions import ConnectionError 

8from zenossapi.apiclient import ZenossAPIClientError, ZenossAPIClientAuthenticationError 

9 

10 

11class ZenossRouter(object): 

12 """ 

13 Base class for Zenoss router classes 

14 """ 

15 def __init__(self, url, headers, ssl_verify, endpoint, action, timeout=5, maxattempts=3): 

16 self.api_url = url 

17 self.api_headers = headers 

18 self.ssl_verify = ssl_verify 

19 self.api_endpoint = endpoint 

20 self.api_action = action 

21 self.api_timeout = timeout 

22 self.api_maxattempts = maxattempts 

23 

24 def _check_uid(self, uid): 

25 if not uid.startswith('Devices'): 

26 if uid.startswith('/'): 

27 uid = 'Devices{0}'.format(uid) 

28 else: 

29 uid = 'Devices/{0}'.format(uid) 

30 

31 return uid 

32 

33 def _make_request_data(self, method, data=None): 

34 if data is None: 

35 return dict( 

36 action=self.api_action, 

37 method=method, 

38 tid=1, 

39 ) 

40 else: 

41 return dict( 

42 action=self.api_action, 

43 method=method, 

44 data=[data], 

45 tid=1, 

46 ) 

47 @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=2, min=2, max=20), retry=retry_if_exception_type(ReadTimeout)) 

48 def _router_request(self, data, response_timeout=None): 

49 # Disable warnings from urllib3 if ssl_verify is False, otherwise 

50 # every request will print an InsecureRequestWarning 

51 if not self.ssl_verify: 

52 requests.urllib3.disable_warnings() 

53 

54 if response_timeout is None: 

55 response_timeout = self.api_timeout 

56 

57 try: 

58 response = requests.request("POST", 

59 '{0}/{1}'.format(self.api_url, self.api_endpoint), 

60 headers=self.api_headers, 

61 data=json.dumps(data).encode('utf-8'), 

62 verify=self.ssl_verify, 

63 timeout=response_timeout 

64 ) 

65 except ConnectionError as e: 

66 logging.warning('Error calling Zenoss API: %s\n Request data: %s' % (e, data)) 

67 # Atempt to display the failure reason from Zenoss 

68 try: 

69 logging.warning("Query failure reason from Zensos: %s" % response['result']['msg']) 

70 except: 

71 pass 

72 

73 if response.ok: 

74 if response.url.find('login_form') > -1: 

75 raise ZenossAPIClientAuthenticationError('API Login Failed') 

76 response_json = response.json() 

77 if 'result' in response_json: 

78 if response_json['result']: 

79 if 'success' in response_json['result']: 

80 if not response_json['result']['success']: 

81 raise ZenossAPIClientError('Request failed: {}'.format(response_json['result']['msg'])) 

82 else: 

83 raise ZenossAPIClientError('Request failed, no response data returned!') 

84 

85 return response_json['result'] 

86 

87 else: 

88 raise ZenossAPIClientError('Request failed: {0} {1}'.format(response.status_code, response.reason))