ezKit 1.7.7__py3-none-any.whl → 1.8.0__py3-none-any.whl
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.
- ezKit/__init__.py +0 -1
- ezKit/bottle.py +7 -2
- ezKit/bottle_extensions.py +14 -18
- ezKit/cipher.py +11 -10
- ezKit/database.py +109 -73
- ezKit/http.py +21 -22
- ezKit/mongo.py +24 -21
- ezKit/redis.py +19 -16
- ezKit/sendemail.py +1 -10
- ezKit/token.py +11 -12
- ezKit/utils.py +8 -6
- ezKit/xftp.py +2 -2
- {ezKit-1.7.7.dist-info → ezKit-1.8.0.dist-info}/METADATA +1 -1
- ezKit-1.8.0.dist-info/RECORD +17 -0
- ezKit/files.py +0 -348
- ezKit/plots.py +0 -155
- ezKit/qywx.py +0 -173
- ezKit/reports.py +0 -274
- ezKit/zabbix.py +0 -737
- ezKit-1.7.7.dist-info/RECORD +0 -22
- {ezKit-1.7.7.dist-info → ezKit-1.8.0.dist-info}/LICENSE +0 -0
- {ezKit-1.7.7.dist-info → ezKit-1.8.0.dist-info}/WHEEL +0 -0
- {ezKit-1.7.7.dist-info → ezKit-1.8.0.dist-info}/top_level.txt +0 -0
ezKit/qywx.py
DELETED
@@ -1,173 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import time
|
3
|
-
|
4
|
-
import requests
|
5
|
-
from loguru import logger
|
6
|
-
|
7
|
-
from . import utils
|
8
|
-
|
9
|
-
|
10
|
-
class QYWX(object):
|
11
|
-
"""企业微信"""
|
12
|
-
|
13
|
-
"""
|
14
|
-
企业微信开发者中心
|
15
|
-
|
16
|
-
https://developer.work.weixin.qq.com/
|
17
|
-
https://developer.work.weixin.qq.com/document/path/90313 (全局错误码)
|
18
|
-
|
19
|
-
参考文档:
|
20
|
-
|
21
|
-
https://www.gaoyuanqi.cn/python-yingyong-qiyewx/
|
22
|
-
https://www.jianshu.com/p/020709b130d3
|
23
|
-
"""
|
24
|
-
|
25
|
-
url_prefix = 'https://qyapi.weixin.qq.com'
|
26
|
-
work_id: str | None = None
|
27
|
-
agent_id: str | None = None
|
28
|
-
agent_secret: str | None = None
|
29
|
-
access_token: str | None = None
|
30
|
-
|
31
|
-
def __init__(self, work_id: str | None, agent_id: str | None, agent_secret: str | None):
|
32
|
-
"""Initiation"""
|
33
|
-
self.work_id = work_id
|
34
|
-
self.agent_id = agent_id
|
35
|
-
self.agent_secret = agent_secret
|
36
|
-
|
37
|
-
"""获取 Token"""
|
38
|
-
self.getaccess_token()
|
39
|
-
|
40
|
-
def getaccess_token(self) -> str | None:
|
41
|
-
try:
|
42
|
-
response = requests.get(f'{self.url_prefix}/cgi-bin/gettoken?corpid={self.work_id}&corpsecret={self.agent_secret}')
|
43
|
-
if response.status_code == 200:
|
44
|
-
result: dict = response.json()
|
45
|
-
self.access_token = result.get('access_token')
|
46
|
-
else:
|
47
|
-
self.access_token = None
|
48
|
-
return result.get('access_token')
|
49
|
-
except:
|
50
|
-
return None
|
51
|
-
|
52
|
-
def get_agent_list(self) -> dict | str | None:
|
53
|
-
try:
|
54
|
-
self.getaccess_token() if self.access_token == None else next
|
55
|
-
response = requests.get(f'{self.url_prefix}/cgi-bin/agent/list?access_token={self.access_token}')
|
56
|
-
if response.status_code == 200:
|
57
|
-
response_data: dict = response.json()
|
58
|
-
if response_data.get('errcode') == 42001:
|
59
|
-
self.getaccess_token()
|
60
|
-
time.sleep(1)
|
61
|
-
self.get_agent_list()
|
62
|
-
return response_data
|
63
|
-
return response.text
|
64
|
-
except:
|
65
|
-
return None
|
66
|
-
|
67
|
-
def get_department_list(self, id) -> dict | str | None:
|
68
|
-
try:
|
69
|
-
self.getaccess_token() if self.access_token == None else next
|
70
|
-
response = requests.get(f'{self.url_prefix}/cgi-bin/department/list?access_token={self.access_token}&id={id}')
|
71
|
-
if response.status_code == 200:
|
72
|
-
response_data: dict = response.json()
|
73
|
-
if response_data.get('errcode') == 42001:
|
74
|
-
self.getaccess_token()
|
75
|
-
time.sleep(1)
|
76
|
-
self.get_department_list(id)
|
77
|
-
return response_data
|
78
|
-
return response.text
|
79
|
-
except:
|
80
|
-
return None
|
81
|
-
|
82
|
-
def get_user_list(self, id) -> dict | str | None:
|
83
|
-
try:
|
84
|
-
self.getaccess_token() if self.access_token == None else next
|
85
|
-
response = requests.get(f'{self.url_prefix}/cgi-bin/user/list?access_token={self.access_token}&department_id={id}')
|
86
|
-
if response.status_code == 200:
|
87
|
-
response_data: dict = response.json()
|
88
|
-
if response_data.get('errcode') == 42001:
|
89
|
-
self.getaccess_token()
|
90
|
-
time.sleep(1)
|
91
|
-
self.get_user_list(id)
|
92
|
-
return response_data
|
93
|
-
return response.text
|
94
|
-
except:
|
95
|
-
return None
|
96
|
-
|
97
|
-
def get_user_id_by_mobile(self, mobile) -> dict | str | None:
|
98
|
-
try:
|
99
|
-
self.getaccess_token() if self.access_token == None else next
|
100
|
-
json_string = json.dumps({'mobile': mobile})
|
101
|
-
response = requests.post(f'{self.url_prefix}/cgi-bin/user/getuserid?access_token={self.access_token}', data=json_string)
|
102
|
-
if response.status_code == 200:
|
103
|
-
response_data: dict = response.json()
|
104
|
-
if response_data.get('errcode') == 42001:
|
105
|
-
self.getaccess_token()
|
106
|
-
time.sleep(1)
|
107
|
-
self.get_user_id_by_mobile(id)
|
108
|
-
return response_data
|
109
|
-
return response.text
|
110
|
-
except:
|
111
|
-
return None
|
112
|
-
|
113
|
-
def get_user_info(self, id) -> dict | str | None:
|
114
|
-
try:
|
115
|
-
self.getaccess_token() if self.access_token == None else next
|
116
|
-
response = requests.get(f'{self.url_prefix}/cgi-bin/user/get?access_token={self.access_token}&userid={id}')
|
117
|
-
if response.status_code == 200:
|
118
|
-
response_data: dict = response.json()
|
119
|
-
if response_data.get('errcode') == 42001:
|
120
|
-
self.getaccess_token()
|
121
|
-
time.sleep(1)
|
122
|
-
self.get_user_info(id)
|
123
|
-
return response_data
|
124
|
-
return response.text
|
125
|
-
except:
|
126
|
-
return None
|
127
|
-
|
128
|
-
def send_message_by_mobile(self, mobile: str | list, message: str, debug: bool = False) -> bool:
|
129
|
-
"""发送消息"""
|
130
|
-
"""
|
131
|
-
参考文档:
|
132
|
-
|
133
|
-
https://developer.work.weixin.qq.com/document/path/90235
|
134
|
-
"""
|
135
|
-
try:
|
136
|
-
self.getaccess_token() if self.access_token == None else next
|
137
|
-
|
138
|
-
users: list = []
|
139
|
-
|
140
|
-
match True:
|
141
|
-
case True if utils.v_true(mobile, list):
|
142
|
-
users = mobile
|
143
|
-
case True if utils.v_true(mobile, str):
|
144
|
-
users.append(mobile)
|
145
|
-
case _:
|
146
|
-
return None
|
147
|
-
|
148
|
-
for user in users:
|
149
|
-
user_object = self.get_user_id_by_mobile(user)
|
150
|
-
json_dict = {
|
151
|
-
'touser': user_object.get('userid'),
|
152
|
-
'msgtype': 'text',
|
153
|
-
'agentid': self.agent_id,
|
154
|
-
'text': {'content': message},
|
155
|
-
'safe': 0,
|
156
|
-
'enable_id_trans': 0,
|
157
|
-
'enable_duplicate_check': 0,
|
158
|
-
'duplicate_check_interval': 1800
|
159
|
-
}
|
160
|
-
json_string = json.dumps(json_dict)
|
161
|
-
response = requests.post(f'{self.url_prefix}/cgi-bin/message/send?access_token={self.access_token}', data=json_string)
|
162
|
-
if response.status_code == 200:
|
163
|
-
response_data: dict = response.json()
|
164
|
-
if response_data.get('errcode') == 42001:
|
165
|
-
self.getaccess_token()
|
166
|
-
time.sleep(1)
|
167
|
-
self.send_message_by_mobile(mobile, message)
|
168
|
-
|
169
|
-
return True
|
170
|
-
|
171
|
-
except Exception as e:
|
172
|
-
logger.exception(e) if utils.v_true(debug, bool) else next
|
173
|
-
return False
|
ezKit/reports.py
DELETED
@@ -1,274 +0,0 @@
|
|
1
|
-
from . import files, utils
|
2
|
-
|
3
|
-
'''
|
4
|
-
reports.logout()
|
5
|
-
|
6
|
-
生成报告完成以后, 退出 Zabbix
|
7
|
-
|
8
|
-
return _image
|
9
|
-
|
10
|
-
返回图片信息, 发邮件时使用
|
11
|
-
'''
|
12
|
-
|
13
|
-
class Reports(object):
|
14
|
-
|
15
|
-
# Zabbix Instance
|
16
|
-
_zabbix = None
|
17
|
-
|
18
|
-
# Files Instance
|
19
|
-
_files = None
|
20
|
-
|
21
|
-
# Image Object
|
22
|
-
_image_dir = '.'
|
23
|
-
_image_name_prefix = 'image'
|
24
|
-
|
25
|
-
def __init__(self, zabbix, markdown_file, html_file, image_dir, image_name_prefix):
|
26
|
-
''' Initiation '''
|
27
|
-
self._zabbix = zabbix
|
28
|
-
self._files = files.files(markdown_file, html_file)
|
29
|
-
self._image_dir = image_dir
|
30
|
-
self._image_name_prefix = image_name_prefix
|
31
|
-
|
32
|
-
def generic(
|
33
|
-
self,
|
34
|
-
pieces=None,
|
35
|
-
hosts=None,
|
36
|
-
time_from=None,
|
37
|
-
time_till=None,
|
38
|
-
item_keys=None,
|
39
|
-
data_type=None,
|
40
|
-
data_proc=None,
|
41
|
-
title=None,
|
42
|
-
description=None,
|
43
|
-
number_type=None,
|
44
|
-
number_unit=None,
|
45
|
-
number_handling=None,
|
46
|
-
table_header_title='Host',
|
47
|
-
table_header_data='Data',
|
48
|
-
sort_by_ip=None,
|
49
|
-
image_cid=None,
|
50
|
-
image_label=None,
|
51
|
-
image_kind=None
|
52
|
-
):
|
53
|
-
|
54
|
-
_history = []
|
55
|
-
|
56
|
-
if utils.v_true(item_keys, str):
|
57
|
-
_history = utils.retry(10, self._zabbix.get_history_by_item_key, hosts, time_from, time_till, item_keys, data_type)
|
58
|
-
|
59
|
-
if utils.v_true(item_keys, list):
|
60
|
-
for _item_key in item_keys:
|
61
|
-
_history_slice = utils.retry(10, self._zabbix.get_history_by_item_key, hosts, time_from, time_till, _item_key, data_type)
|
62
|
-
if _history_slice != None:
|
63
|
-
if callable(data_proc) == True:
|
64
|
-
_history_slice = data_proc(_history_slice)
|
65
|
-
_history += _history_slice
|
66
|
-
|
67
|
-
if _history != None:
|
68
|
-
|
69
|
-
_files_func = self._files.multiple_pieces
|
70
|
-
|
71
|
-
if pieces == 'single':
|
72
|
-
|
73
|
-
_files_func = self._files.single_piece
|
74
|
-
|
75
|
-
for _data in _history:
|
76
|
-
if len(_data['history']) > 0:
|
77
|
-
_history_last = max(_data['history'], key=lambda i: i['clock'])
|
78
|
-
_data['history'] = _history_last
|
79
|
-
|
80
|
-
_image = {
|
81
|
-
'cid': '{}'.format(image_cid),
|
82
|
-
'path': '{}/{}_{}.png'.format(self._image_dir, self._image_name_prefix, image_cid),
|
83
|
-
'label': image_label,
|
84
|
-
'kind': image_kind
|
85
|
-
}
|
86
|
-
|
87
|
-
_files_result = _files_func(
|
88
|
-
title=title,
|
89
|
-
description=description,
|
90
|
-
data=_history,
|
91
|
-
image=_image,
|
92
|
-
number_type=number_type,
|
93
|
-
number_unit=number_unit,
|
94
|
-
number_handling=number_handling,
|
95
|
-
table_header_title=table_header_title,
|
96
|
-
table_header_data=table_header_data,
|
97
|
-
sort_by_ip=sort_by_ip
|
98
|
-
)
|
99
|
-
|
100
|
-
if _files_result == True:
|
101
|
-
return _image
|
102
|
-
else:
|
103
|
-
return None
|
104
|
-
|
105
|
-
else:
|
106
|
-
|
107
|
-
return None
|
108
|
-
|
109
|
-
def system_interface(self, hosts, interfaces, time_from, time_till, direction='in'):
|
110
|
-
''' System Interface '''
|
111
|
-
|
112
|
-
_direction_name = 'Received'
|
113
|
-
_direction_alias = 'received'
|
114
|
-
_direction_info = '接收数据'
|
115
|
-
|
116
|
-
if direction == 'out':
|
117
|
-
_direction_name = 'Sent'
|
118
|
-
_direction_alias = 'sent'
|
119
|
-
_direction_info = '发送数据'
|
120
|
-
|
121
|
-
_history = utils.retry(10, self._zabbix.get_history_by_interface, hosts, interfaces, time_from, time_till, direction)
|
122
|
-
|
123
|
-
if utils.v_true(_history, list):
|
124
|
-
|
125
|
-
_image = {
|
126
|
-
'cid': 'system_interface_'.format(_direction_alias),
|
127
|
-
'path': '{}/{}_system_interface_{}.png'.format(self._image_dir, self._image_name_prefix, _direction_alias)
|
128
|
-
}
|
129
|
-
|
130
|
-
_ = self._files.multiple_pieces(
|
131
|
-
title='System Interface {}'.format(_direction_name),
|
132
|
-
description='说明: 网卡**{}**的速度'.format(_direction_info),
|
133
|
-
data=_history,
|
134
|
-
image=_image,
|
135
|
-
number_type='int',
|
136
|
-
number_unit='Kbps',
|
137
|
-
number_handling=utils.divisor_1000,
|
138
|
-
sort_by_ip=True
|
139
|
-
)
|
140
|
-
|
141
|
-
if _ == True:
|
142
|
-
return _image
|
143
|
-
else:
|
144
|
-
return None
|
145
|
-
|
146
|
-
else:
|
147
|
-
|
148
|
-
return None
|
149
|
-
|
150
|
-
def base_system(self, hosts, time_from, time_till, interfaces=None):
|
151
|
-
|
152
|
-
# Images
|
153
|
-
_images = []
|
154
|
-
|
155
|
-
# System CPU utilization
|
156
|
-
_image = self.generic(
|
157
|
-
hosts=hosts,
|
158
|
-
time_from=time_from,
|
159
|
-
time_till=time_till,
|
160
|
-
item_keys='system.cpu.util',
|
161
|
-
data_type=0,
|
162
|
-
title='System CPU utilization',
|
163
|
-
description='说明: 系统 CPU 使用率',
|
164
|
-
number_type='float',
|
165
|
-
number_unit='%',
|
166
|
-
sort_by_ip=True,
|
167
|
-
image_cid='system_cpu_utilization'
|
168
|
-
)
|
169
|
-
if _image != None:
|
170
|
-
_images.append(_image)
|
171
|
-
|
172
|
-
# System Memory utilization
|
173
|
-
_image = self.generic(
|
174
|
-
hosts=hosts,
|
175
|
-
time_from=time_from,
|
176
|
-
time_till=time_till,
|
177
|
-
item_keys='vm.memory.utilization',
|
178
|
-
data_type=0,
|
179
|
-
title='System Memory utilization',
|
180
|
-
description='说明: 系统 内存 使用率',
|
181
|
-
number_type='float',
|
182
|
-
number_unit='%',
|
183
|
-
sort_by_ip=True,
|
184
|
-
image_cid='system_memory_utilization'
|
185
|
-
)
|
186
|
-
if _image != None:
|
187
|
-
_images.append(_image)
|
188
|
-
|
189
|
-
# System root partition utilization
|
190
|
-
_image = self.generic(
|
191
|
-
pieces='single',
|
192
|
-
hosts=hosts,
|
193
|
-
time_from=time_from,
|
194
|
-
time_till=time_till,
|
195
|
-
item_keys='vfs.fs.size[/,pused]',
|
196
|
-
data_type=0,
|
197
|
-
title='System root partition utilization',
|
198
|
-
description='说明: 系统 根目录(/) 使用率',
|
199
|
-
number_type='float',
|
200
|
-
number_unit='%',
|
201
|
-
table_header_data='Used',
|
202
|
-
sort_by_ip=True,
|
203
|
-
image_cid='system_root_partition_utilization',
|
204
|
-
image_label='Used (%)',
|
205
|
-
image_kind='barh'
|
206
|
-
)
|
207
|
-
if _image != None:
|
208
|
-
_images.append(_image)
|
209
|
-
|
210
|
-
if interfaces != None:
|
211
|
-
|
212
|
-
# System Interface Received
|
213
|
-
_image = self.system_interface(hosts, interfaces, time_from, time_till, 'in')
|
214
|
-
if _image != None:
|
215
|
-
_images.append(_image)
|
216
|
-
|
217
|
-
# System Interface Sent
|
218
|
-
_image = self.system_interface(hosts, interfaces, time_from, time_till, 'out')
|
219
|
-
if _image != None:
|
220
|
-
_images.append(_image)
|
221
|
-
|
222
|
-
return _images
|
223
|
-
|
224
|
-
def base_generic(self, hosts, time_from, time_till, items=None):
|
225
|
-
|
226
|
-
# Images
|
227
|
-
_images = []
|
228
|
-
|
229
|
-
if items != None:
|
230
|
-
|
231
|
-
for _item in items:
|
232
|
-
|
233
|
-
# CPU utilization
|
234
|
-
_image = self.generic(
|
235
|
-
hosts=hosts,
|
236
|
-
time_from=time_from,
|
237
|
-
time_till=time_till,
|
238
|
-
item_keys=_item['keys'][0],
|
239
|
-
data_type=_item['types'][0],
|
240
|
-
data_proc=_item.get('data_proc'),
|
241
|
-
title='{} CPU utilization'.format(_item['name']),
|
242
|
-
description='说明: {} CPU 使用率'.format(_item['name']),
|
243
|
-
number_type='float',
|
244
|
-
number_unit='%',
|
245
|
-
table_header_title=_item.get('table_header_title', 'Host'),
|
246
|
-
table_header_data=_item.get('table_header_data', 'Data'),
|
247
|
-
sort_by_ip=True,
|
248
|
-
image_cid='{}_cpu_utilization'.format(_item['alias'])
|
249
|
-
)
|
250
|
-
if _image != None:
|
251
|
-
_images.append(_image)
|
252
|
-
|
253
|
-
# Memory used (RSS)
|
254
|
-
_image = self.generic(
|
255
|
-
hosts=hosts,
|
256
|
-
time_from=time_from,
|
257
|
-
time_till=time_till,
|
258
|
-
item_keys=_item['keys'][1],
|
259
|
-
data_type=_item['types'][1],
|
260
|
-
data_proc=_item.get('data_proc'),
|
261
|
-
title='{} Memory used (RSS)'.format(_item['name']),
|
262
|
-
description='说明: {} 内存 使用量'.format(_item['name']),
|
263
|
-
number_type='int',
|
264
|
-
number_unit='MB',
|
265
|
-
number_handling=utils.divisor_square_1024,
|
266
|
-
table_header_title=_item.get('table_header_title', 'Host'),
|
267
|
-
table_header_data=_item.get('table_header_data', 'Data'),
|
268
|
-
sort_by_ip=True,
|
269
|
-
image_cid='{}_memory_used_rss'.format(_item['alias'])
|
270
|
-
)
|
271
|
-
if _image != None:
|
272
|
-
_images.append(_image)
|
273
|
-
|
274
|
-
return _images
|