pytbox 0.1.8__tar.gz → 0.2.0__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.

Potentially problematic release.


This version of pytbox might be problematic. Click here for more details.

Files changed (85) hide show
  1. {pytbox-0.1.8/src/pytbox.egg-info → pytbox-0.2.0}/PKG-INFO +1 -1
  2. {pytbox-0.1.8 → pytbox-0.2.0}/pyproject.toml +1 -1
  3. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/alert/alert_handler.py +27 -7
  4. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/base.py +4 -5
  5. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/database/mongo.py +1 -1
  6. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/database/victoriametrics.py +36 -2
  7. pytbox-0.2.0/src/pytbox/excel.py +64 -0
  8. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/mail/client.py +4 -0
  9. {pytbox-0.1.8 → pytbox-0.2.0/src/pytbox.egg-info}/PKG-INFO +1 -1
  10. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_victoriametrics.py +7 -1
  11. pytbox-0.1.8/src/pytbox/excel.py +0 -0
  12. {pytbox-0.1.8 → pytbox-0.2.0}/MANIFEST.in +0 -0
  13. {pytbox-0.1.8 → pytbox-0.2.0}/README.md +0 -0
  14. {pytbox-0.1.8 → pytbox-0.2.0}/setup.cfg +0 -0
  15. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/alert/ping.py +0 -0
  16. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/alicloud/sls.py +0 -0
  17. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/build_config.py +0 -0
  18. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/instances.toml +0 -0
  19. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/__init__.py +0 -0
  20. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.cpu/cpu.toml.j2 +0 -0
  21. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.disk/disk.toml.j2 +0 -0
  22. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.diskio/diskio.toml.j2 +0 -0
  23. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.dns_query/dns_query.toml.j2 +0 -0
  24. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.http_response/http_response.toml.j2 +0 -0
  25. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.mem/mem.toml.j2 +0 -0
  26. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.net/net.toml.j2 +0 -0
  27. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.net_response/net_response.toml.j2 +0 -0
  28. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.ping/ping.toml.j2 +0 -0
  29. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.prometheus/prometheus.toml.j2 +0 -0
  30. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/cisco_interface.toml.j2 +0 -0
  31. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/cisco_system.toml.j2 +0 -0
  32. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/h3c_interface.toml.j2 +0 -0
  33. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/h3c_system.toml.j2 +0 -0
  34. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/huawei_interface.toml.j2 +0 -0
  35. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/huawei_system.toml.j2 +0 -0
  36. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/ruijie_interface.toml.j2 +0 -0
  37. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.snmp/ruijie_system.toml.j2 +0 -0
  38. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/categraf/jinja2/input.vsphere/vsphere.toml.j2 +0 -0
  39. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/__init__.py +0 -0
  40. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/categraf/__init__.py +0 -0
  41. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/categraf/commands.py +0 -0
  42. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/commands/vm.py +0 -0
  43. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/common/__init__.py +0 -0
  44. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/common/options.py +0 -0
  45. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/common/utils.py +0 -0
  46. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/formatters/__init__.py +0 -0
  47. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/formatters/output.py +0 -0
  48. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli/main.py +0 -0
  49. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/cli.py +0 -0
  50. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/common/__init__.py +0 -0
  51. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/dida365.py +0 -0
  52. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/feishu/client.py +0 -0
  53. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/feishu/endpoints.py +0 -0
  54. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/feishu/errors.py +0 -0
  55. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/feishu/helpers.py +0 -0
  56. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/feishu/typing.py +0 -0
  57. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/log/logger.py +0 -0
  58. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/log/victorialog.py +0 -0
  59. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/mail/alimail.py +0 -0
  60. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/mail/mail_detail.py +0 -0
  61. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/network/meraki.py +0 -0
  62. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/onepassword_connect.py +0 -0
  63. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/onepassword_sa.py +0 -0
  64. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/pyjira.py +0 -0
  65. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/cronjob.py +0 -0
  66. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/env.py +0 -0
  67. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/load_config.py +0 -0
  68. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/load_vm_devfile.py +0 -0
  69. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/response.py +0 -0
  70. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/richutils.py +0 -0
  71. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/utils/timeutils.py +0 -0
  72. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/vmware.py +0 -0
  73. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox/win/ad.py +0 -0
  74. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox.egg-info/SOURCES.txt +0 -0
  75. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox.egg-info/dependency_links.txt +0 -0
  76. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox.egg-info/entry_points.txt +0 -0
  77. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox.egg-info/requires.txt +0 -0
  78. {pytbox-0.1.8 → pytbox-0.2.0}/src/pytbox.egg-info/top_level.txt +0 -0
  79. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_base.py +0 -0
  80. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_feishu.py +0 -0
  81. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_load_jsonfile.py +0 -0
  82. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_logger.py +0 -0
  83. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_onepassword_connect.py +0 -0
  84. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_onepassword_sa.py +0 -0
  85. {pytbox-0.1.8 → pytbox-0.2.0}/tests/test_vmware.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytbox
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)
5
5
  Author-email: mingming hou <houm01@foxmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pytbox"
7
- version = "0.1.8"
7
+ version = "0.2.0"
8
8
  description = "A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)"
9
9
  authors = [{ name = "mingming hou", email = "houm01@foxmail.com" }]
10
10
  license = "MIT"
@@ -7,6 +7,7 @@ from ..database.mongo import Mongo
7
7
  from ..feishu.client import Client as FeishuClient
8
8
  from ..dida365 import Dida365
9
9
  from ..utils.timeutils import TimeUtils
10
+ from ..mail.client import MailClient
10
11
 
11
12
 
12
13
  class AlertHandler:
@@ -15,12 +16,17 @@ class AlertHandler:
15
16
  config: dict=None,
16
17
  mongo_client: Mongo=None,
17
18
  feishu_client: FeishuClient=None,
18
- dida_client: Dida365=None
19
+ dida_client: Dida365=None,
20
+ mail_client: MailClient=None,
21
+ env: Literal['dev', 'prod']='prod'
19
22
  ):
23
+
20
24
  self.config = config
21
25
  self.mongo = mongo_client
22
26
  self.feishu = feishu_client
23
27
  self.dida = dida_client
28
+ self.mail = mail_client
29
+ self.env = env
24
30
 
25
31
  def send_alert(self,
26
32
  event_id: str=None,
@@ -34,7 +40,7 @@ class AlertHandler:
34
40
  suggestion: str='',
35
41
  troubleshot: str='暂无',
36
42
  mongo_id: str=None
37
- ):
43
+ ):
38
44
 
39
45
  if not event_id:
40
46
  event_id = str(uuid.uuid4())
@@ -62,11 +68,11 @@ class AlertHandler:
62
68
  update = {"$set": { "resolved_time": event_time}}
63
69
  self.mongo.collection.update_one(filter_doc, update)
64
70
  alarm_time = self.mongo.collection.find_one(filter_doc, {'event_time': 1})['event_time']
65
-
71
+
66
72
  content = [
67
73
  f'**事件名称**: {event_name}',
68
74
  f'**告警时间**: {TimeUtils.convert_timeobj_to_str(timeobj=event_time, timezone_offset=0) if event_type == "trigger" else TimeUtils.convert_timeobj_to_str(timeobj=alarm_time, timezone_offset=8)}',
69
- f'**事件内容**: {event_content}',
75
+ f'**事件内容**: {event_content + " 已恢复" if event_type == "resolved" else event_content}',
70
76
  f'**告警实例**: {entity_name}',
71
77
  f'**建议**: {suggestion}',
72
78
  f'**故障排查**: {troubleshot}',
@@ -78,17 +84,31 @@ class AlertHandler:
78
84
 
79
85
  if self.config['feishu']['enable_alert']:
80
86
  self.feishu.extensions.send_message_notify(
87
+ receive_id=self.config['feishu']['receive_id'],
81
88
  color='red' if event_type == "trigger" else 'green',
82
- title=event_content,
89
+ title=event_content + " 已恢复" if event_type == "resolved" else event_content,
83
90
  priority=priority,
84
- sub_title="",
91
+ sub_title='测试告警, 无需处理' if self.env == 'dev' else '',
85
92
  content='\n'.join(content)
86
93
  )
87
94
 
95
+ if self.config['mail']['enable_mail']:
96
+ if event_type == "trigger":
97
+ self.mail.send_mail(
98
+ receiver=[self.config['mail']['mail_address']],
99
+ subject=f"{self.config['mail']['subject_trigger']}, {event_content}",
100
+ contents=f"event_content:{event_content}, alarm_time: {str(event_time)}, event_id: {event_id}, alarm_name: {event_name}, entity_name: {entity_name}, priority: {priority}, automate_ts: {troubleshot}, suggestion: {suggestion}"
101
+ )
102
+ else:
103
+ self.mail.send_mail(
104
+ receiver=[self.config['mail']['mail_address']],
105
+ subject=f"{self.config['mail']['subject_resolved']}, {event_content}",
106
+ contents=f"event_content:{event_content}, alarm_time: {str(TimeUtils.get_now_time_mongo())}, event_id: {event_id}, alarm_name: {event_name}, entity_name: {entity_name}, priority: {priority}, automate_ts: {troubleshot}, suggestion: {suggestion}"
107
+ )
108
+
88
109
  if self.config['dida']['enable_alert']:
89
110
  if event_type == "trigger":
90
111
  res = self.dida.task_create(
91
-
92
112
  project_id=self.config['dida']['alert_project_id'],
93
113
  title=event_content,
94
114
  content='\n'.join(content),
@@ -8,7 +8,6 @@ from pytbox.feishu.client import Client as FeishuClient
8
8
  from pytbox.dida365 import Dida365
9
9
  from pytbox.alert.alert_handler import AlertHandler
10
10
  from pytbox.log.logger import AppLogger
11
- from pytbox.win.ad import ADClient
12
11
  from pytbox.network.meraki import Meraki
13
12
  from pytbox.utils.env import get_env_by_os_environment
14
13
  from pytbox.vmware import VMwareClient
@@ -44,6 +43,7 @@ dida = Dida365(
44
43
  access_token=config['dida']['access_token']
45
44
  )
46
45
 
46
+
47
47
  alert_handler = AlertHandler(config=config, mongo_client=get_mongo('alert_test'), feishu_client=feishu, dida_client=dida)
48
48
 
49
49
  def get_logger(app):
@@ -99,9 +99,9 @@ pyjira = PyJira(
99
99
  token=config['jira']['token']
100
100
  )
101
101
 
102
- mail_163 = MailClient(mail_address=config['mail']['163']['mail_address'], password=config['mail']['163']['password'])
103
- mail_qq = MailClient(mail_address=config['mail']['qq']['mail_address'], password=config['mail']['qq']['password'])
104
- ali_mail = AliMail(mail_address=config['mail']['aliyun']['mail_address'], client_id=config['mail']['aliyun']['client_id'], client_secret=config['mail']['aliyun']['client_secret'])
102
+ # mail_163 = MailClient(mail_address=config['mail']['163']['mail_address'], password=config['mail']['163']['password'])
103
+ # mail_qq = MailClient(mail_address=config['mail']['qq']['mail_address'], password=config['mail']['qq']['password'])
104
+ # ali_mail = AliMail(mail_address=config['mail']['aliyun']['mail_address'], client_id=config['mail']['aliyun']['client_id'], client_secret=config['mail']['aliyun']['client_secret'])
105
105
 
106
106
  sls = AliCloudSls(
107
107
  access_key_id=config['alicloud']['account1']['access_key_id'],
@@ -110,6 +110,5 @@ sls = AliCloudSls(
110
110
  logstore=config['alicloud']['account1']['logstore']
111
111
  )
112
112
 
113
-
114
113
  def get_cronjob_counter(app_type='', app='', comment=None, schedule_interval=None, schedule_cron=None):
115
114
  return cronjob_counter(vm=vm, log=get_logger('cronjob_counter'), app_type=app_type, app=app, comment=comment, schedule_interval=schedule_interval, schedule_cron=schedule_cron)
@@ -80,7 +80,7 @@ class Mongo:
80
80
  alarm_list = []
81
81
  for result in results:
82
82
  duration_minute = '持续 ' + str(int((result['resolved_time'] - result['event_time']).total_seconds() / 60)) + ' 分钟'
83
- alarm_list.append('触发告警: ' + TimeUtils.convert_timeobj_to_str(timeobj=result['event_time']) + ' ' + duration_minute)
83
+ alarm_list.append('触发时间: ' + TimeUtils.convert_timeobj_to_str(timeobj=result['event_time']) + ' ' + duration_minute)
84
84
 
85
85
  alarm_str = '\n'.join(alarm_list)
86
86
 
@@ -230,7 +230,38 @@ class VictoriaMetrics:
230
230
  rate = r.data[0]['value'][1]
231
231
  return int(float(rate))
232
232
 
233
- def check_snmp_port_status(self, sysname: str=None, if_name: str=None, last_minute: int=5) -> ReturnResponse:
233
+ def check_interface_avg_rate(self,
234
+ direction: Literal['in', 'out'],
235
+ sysname: str,
236
+ ifname:str,
237
+ last_hours: Optional[int] = 24,
238
+ last_minutes: Optional[int] = 5,
239
+ ) -> ReturnResponse:
240
+ '''
241
+ _summary_
242
+
243
+ Args:
244
+ direction (Literal[&#39;in&#39;, &#39;out&#39;]): _description_
245
+ sysname (str): _description_
246
+ ifname (str): _description_
247
+ last_hours (Optional[int], optional): _description_. Defaults to 24.
248
+ last_minutes (Optional[int], optional): _description_. Defaults to 5.
249
+
250
+ Returns:
251
+ ReturnResponse: _description_
252
+ '''
253
+ if direction == 'in':
254
+ query = f'avg_over_time(rate(snmp_interface_ifHCInOctets{{sysName="{sysname}", ifName="{ifname}"}}[{last_minutes}m]) * 8 [{last_hours}h:]) / 1e6'
255
+ else:
256
+ query = f'avg_over_time(rate(snmp_interface_ifHCOutOctets{{sysName="{sysname}", ifName="{ifname}"}}[{last_minutes}m]) * 8 [{last_hours}h:]) / 1e6'
257
+ r = self.query(query)
258
+ try:
259
+ rate = r.data[0]['value'][1]
260
+ return ReturnResponse(code=0, msg=f"查询 {sysname} {ifname} 最近 {last_hours} 小时平均速率为 {round(float(rate), 2)} Mbit/s", data=round(float(rate), 2))
261
+ except KeyError:
262
+ return ReturnResponse(code=1, msg=f"查询 {sysname} {ifname} 最近 {last_hours} 小时平均速率为 0 Mbit/s")
263
+
264
+ def check_snmp_port_status(self, sysname: str=None, if_name: str=None, last_minute: int=5, dev_file: str=None) -> ReturnResponse:
234
265
  '''
235
266
  查询端口状态
236
267
  status code 可参考 SNMP 文件 https://mibbrowser.online/mibdb_search.php?mib=IF-MIB
@@ -245,7 +276,10 @@ class VictoriaMetrics:
245
276
  code: 0, msg: , data: up,down
246
277
  '''
247
278
  q = f"""avg_over_time(snmp_interface_ifOperStatus{{sysName="{sysname}", ifName="{if_name}"}}[{last_minute}m])"""
248
- r = self.query(query=q)
279
+ if self.env == 'dev':
280
+ r = load_dev_file(dev_file)
281
+ else:
282
+ r = self.query(query=q)
249
283
  if r.code == 0:
250
284
  status_code = int(r.data[0]['value'][1])
251
285
  if status_code == 1:
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from openpyxl.styles import Alignment
4
+ from openpyxl.styles import PatternFill
5
+ from openpyxl.styles.differential import DifferentialStyle
6
+ from openpyxl.styles import Font
7
+
8
+
9
+ class ExcelFormat:
10
+ def __init__(self, ws):
11
+ self.ws = ws
12
+
13
+ def set_column(self):
14
+ for column in self.ws.columns:
15
+ max_length = 0
16
+ column = [cell for cell in column]
17
+ for cell in column:
18
+ try:
19
+ if len(str(cell.value)) > max_length:
20
+ max_length = len(cell.value)
21
+ except:
22
+ pass
23
+ adjusted_width = (max_length + 10)
24
+ self.ws.column_dimensions[column[0].column_letter].width = adjusted_width
25
+
26
+ def set_rows_center(self):
27
+ # 将所有单元格的文字居中
28
+ for row in self.ws.iter_rows():
29
+
30
+ for cell in row:
31
+ cell.alignment = Alignment(horizontal='center', vertical='center')
32
+ for row in self.ws.iter_rows():
33
+ self.ws.row_dimensions[row[0].row].height = 24
34
+
35
+ def set_freeze_first_row(self):
36
+ """设置首行锁定/冻结首行"""
37
+ # 冻结首行,从第二行开始滚动
38
+ self.ws.freeze_panes = 'A2'
39
+
40
+ def set_freeze_first_column(self):
41
+ """设置首列锁定/冻结首列"""
42
+ # 冻结首列,从第二列开始滚动
43
+ self.ws.freeze_panes = 'B1'
44
+
45
+ def set_first_row_bold_color(self, font_color='FF0000FF'):
46
+ """设置首行字体加粗并改变颜色
47
+
48
+ Args:
49
+ font_color (str): 字体颜色的十六进制代码,默认为蓝色(FF0000FF)
50
+ 格式:AARRGGBB 或 RRGGBB
51
+ 例如:'FF0000FF'(蓝色), 'FFFF0000'(红色), 'FF008000'(绿色)
52
+ """
53
+ # 遍历首行的所有单元格
54
+ for cell in self.ws[1]:
55
+ if cell.value is not None: # 只对有内容的单元格设置样式
56
+ # 设置字体为粗体并改变颜色
57
+ cell.font = Font(bold=True, color=font_color)
58
+
59
+ def set_freeze_first_row_and_column(self):
60
+ """同时冻结首行和首列"""
61
+ # 冻结首行首列,从第二行第二列开始滚动
62
+ self.ws.freeze_panes = 'B2'
63
+
64
+
@@ -27,6 +27,10 @@ class MailClient:
27
27
  elif 'foxmail.com' in mail_address:
28
28
  self.smtp_address = 'smtp.qq.com'
29
29
  self.imap_address = 'imap.qq.com'
30
+
31
+ elif 'mail' in mail_address and 'cn' in mail_address:
32
+ self.smtp_address = "smtpdm.aliyun.com"
33
+ self.imap_address = ""
30
34
 
31
35
  else:
32
36
  raise ValueError(f'不支持的邮箱地址: {mail_address}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytbox
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)
5
5
  Author-email: mingming hou <houm01@foxmail.com>
6
6
  License-Expression: MIT
@@ -21,8 +21,14 @@ def test_check_snmp_port_status():
21
21
  r = vm.check_snmp_port_status(sysname="shylf-prod-coresw-ce6820-182", if_name="10GE1/0/47", last_minute=10)
22
22
  print(r)
23
23
 
24
+
25
+ r = vm.check_interface_avg_rate(direction='in', sysname='whcq-prod-coresw-s6720-254', ifname='XGigabitEthernet0/0/47', last_hours=24, last_minutes=5)
26
+ print(r)
27
+
24
28
  if __name__ == "__main__":
25
29
  # test_get_labels()
26
30
  # test_query()
27
31
  # test_check_ping_result()
28
- test_check_snmp_port_status()
32
+ # test_check_snmp_port_status()
33
+ # test_check_interface_avg_rate()
34
+ pass
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes