adapt get_alarm for kenel 5.10
Signed-off-by: jinsaihang <jinsaihang@h-partners.com>
This commit is contained in:
parent
1d61a493ab
commit
fb523d6c78
702
adapt_5.10_kenel_for_syssentry.patch
Normal file
702
adapt_5.10_kenel_for_syssentry.patch
Normal file
@ -0,0 +1,702 @@
|
|||||||
|
From 13bf2a16a1f61cf68cde88d5928f7ceae5396a28 Mon Sep 17 00:00:00 2001
|
||||||
|
From: jinsaihang <jinsaihang@h-partners.com>
|
||||||
|
Date: Fri, 24 Jan 2025 16:24:43 +0800
|
||||||
|
Subject: [PATCH] adapt file
|
||||||
|
|
||||||
|
---
|
||||||
|
config/xalarm.conf | 3 +
|
||||||
|
src/python/syssentry/alarm.py | 209 ++++++++++++++++++++++++++
|
||||||
|
src/python/syssentry/callbacks.py | 17 +++
|
||||||
|
src/python/syssentry/global_values.py | 4 +
|
||||||
|
src/python/syssentry/load_mods.py | 16 ++
|
||||||
|
src/python/syssentry/sentryctl | 25 ++-
|
||||||
|
src/python/syssentry/syssentry.py | 14 +-
|
||||||
|
src/python/syssentry/task_map.py | 5 +-
|
||||||
|
src/python/xalarm/register_xalarm.py | 4 +-
|
||||||
|
src/python/xalarm/xalarm_api.py | 6 +-
|
||||||
|
src/python/xalarm/xalarm_config.py | 33 +++-
|
||||||
|
src/python/xalarm/xalarm_daemon.py | 7 +-
|
||||||
|
src/python/xalarm/xalarm_transfer.py | 8 +-
|
||||||
|
13 files changed, 332 insertions(+), 19 deletions(-)
|
||||||
|
create mode 100644 src/python/syssentry/alarm.py
|
||||||
|
|
||||||
|
diff --git a/config/xalarm.conf b/config/xalarm.conf
|
||||||
|
index 14c6d39..323d2dd 100644
|
||||||
|
--- a/config/xalarm.conf
|
||||||
|
+++ b/config/xalarm.conf
|
||||||
|
@@ -1,2 +1,5 @@
|
||||||
|
[filter]
|
||||||
|
id_mask = 1001-1128
|
||||||
|
+
|
||||||
|
+[log]
|
||||||
|
+level=info
|
||||||
|
diff --git a/src/python/syssentry/alarm.py b/src/python/syssentry/alarm.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e5cc313
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/python/syssentry/alarm.py
|
||||||
|
@@ -0,0 +1,209 @@
|
||||||
|
+# coding: utf-8
|
||||||
|
+# Copyright (c) 2024 Huawei Technologies Co., Ltd.
|
||||||
|
+# sysSentry is licensed under the Mulan PSL v2.
|
||||||
|
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
+# You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
+# http://license.coscl.org.cn/MulanPSL2
|
||||||
|
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||||||
|
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||||||
|
+# PURPOSE.
|
||||||
|
+# See the Mulan PSL v2 for more details.
|
||||||
|
+
|
||||||
|
+"""
|
||||||
|
+use for report alarm
|
||||||
|
+"""
|
||||||
|
+import threading
|
||||||
|
+from typing import Dict, List
|
||||||
|
+from datetime import datetime
|
||||||
|
+import time
|
||||||
|
+import logging
|
||||||
|
+import json
|
||||||
|
+import sys
|
||||||
|
+
|
||||||
|
+from xalarm.register_xalarm import xalarm_register,xalarm_getid,xalarm_getlevel,xalarm_gettype,xalarm_gettime,xalarm_getdesc
|
||||||
|
+from xalarm.xalarm_api import Xalarm
|
||||||
|
+
|
||||||
|
+from .global_values import InspectTask
|
||||||
|
+from .task_map import TasksMap
|
||||||
|
+
|
||||||
|
+# 告警ID映射字典,key为插件名,value为告警ID(类型为数字)
|
||||||
|
+task_alarm_id_dict: Dict[str, int] = {}
|
||||||
|
+
|
||||||
|
+# 告警老化时间字典,key为告警ID,value为老化时间(类型为数字,单位为秒)
|
||||||
|
+alarm_id_clear_time_dict: Dict[int, int] = {}
|
||||||
|
+
|
||||||
|
+# 告警事件列表,key为告警ID,value为告警ID对应的告警事件列表(类型为list)
|
||||||
|
+alarm_list_dict: Dict[int, List[Xalarm]] = {}
|
||||||
|
+# 告警事件列表锁
|
||||||
|
+alarm_list_lock = threading.Lock()
|
||||||
|
+
|
||||||
|
+id_filter = []
|
||||||
|
+id_base = 1001
|
||||||
|
+clientId = -1
|
||||||
|
+
|
||||||
|
+MILLISECONDS_UNIT_SECONDS = 1000
|
||||||
|
+MAX_NUM_OF_ALARM_ID = 128
|
||||||
|
+MIN_ALARM_ID = 1001
|
||||||
|
+MAX_ALARM_ID = (MIN_ALARM_ID + MAX_NUM_OF_ALARM_ID - 1)
|
||||||
|
+
|
||||||
|
+def update_alarm_list(alarm_info: Xalarm):
|
||||||
|
+ alarm_id = xalarm_getid(alarm_info)
|
||||||
|
+ if alarm_id < MIN_ALARM_ID or alarm_id > MAX_ALARM_ID:
|
||||||
|
+ logging.warning(f"Invalid alarm_id {alarm_id}")
|
||||||
|
+ return
|
||||||
|
+ timestamp = xalarm_gettime(alarm_info)
|
||||||
|
+ if not timestamp:
|
||||||
|
+ logging.error("Retrieve timestamp failed")
|
||||||
|
+ return
|
||||||
|
+ alarm_list_lock.acquire()
|
||||||
|
+ try:
|
||||||
|
+ # new alarm is inserted into list head
|
||||||
|
+ if alarm_id not in alarm_list_dict:
|
||||||
|
+ logging.warning(f"update_alarm_list: alarm_id {alarm_id} not found in alarm_list_dict")
|
||||||
|
+ return
|
||||||
|
+ alarm_list = alarm_list_dict[alarm_id]
|
||||||
|
+
|
||||||
|
+ alarm_list.insert(0, alarm_info)
|
||||||
|
+ # clear alarm_info older than clear time threshold
|
||||||
|
+ clear_index = -1
|
||||||
|
+ clear_time = alarm_id_clear_time_dict[alarm_id]
|
||||||
|
+ for i in range(len(alarm_list)):
|
||||||
|
+ if (timestamp - xalarm_gettime(alarm_list[i])) / MILLISECONDS_UNIT_SECONDS > clear_time:
|
||||||
|
+ clear_index = i
|
||||||
|
+ break
|
||||||
|
+ if clear_index >= 0:
|
||||||
|
+ alarm_list_dict[alarm_id] = alarm_list[:clear_index]
|
||||||
|
+ finally:
|
||||||
|
+ alarm_list_lock.release()
|
||||||
|
+
|
||||||
|
+def validate_alarm_id(alarm_id):
|
||||||
|
+ if alarm_id is None:
|
||||||
|
+ return False
|
||||||
|
+ try:
|
||||||
|
+ alarm_id = int(alarm_id)
|
||||||
|
+ if MIN_ALARM_ID <= alarm_id <= MAX_ALARM_ID:
|
||||||
|
+ return True
|
||||||
|
+ else:
|
||||||
|
+ return False
|
||||||
|
+ except ValueError:
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+def validate_alarm_clear_time(alarm_clear_time):
|
||||||
|
+ try:
|
||||||
|
+ alarm_clear_time = int(alarm_clear_time)
|
||||||
|
+ if alarm_clear_time > 0 and alarm_clear_time <= sys.maxsize:
|
||||||
|
+ return True
|
||||||
|
+ else:
|
||||||
|
+ return False
|
||||||
|
+ except ValueError:
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+def alarm_register():
|
||||||
|
+ logging.debug(f"alarm_register: enter")
|
||||||
|
+ # 初始化告警ID映射字典、告警老化时间字典
|
||||||
|
+ for task_type in TasksMap.tasks_dict:
|
||||||
|
+ for task_name in TasksMap.tasks_dict[task_type]:
|
||||||
|
+ task = TasksMap.tasks_dict[task_type][task_name]
|
||||||
|
+ if not validate_alarm_id(task.alarm_id):
|
||||||
|
+ logging.warning(f"Invalid alarm_id {task.alarm_id}: ignore {task_name} alarm")
|
||||||
|
+ continue
|
||||||
|
+ if not validate_alarm_clear_time(task.alarm_clear_time):
|
||||||
|
+ logging.warning(f"Invalid alarm_clear_time {task.alarm_clear_time}: ignore {task_name} alarm")
|
||||||
|
+ continue
|
||||||
|
+ task.alarm_id = int(task.alarm_id)
|
||||||
|
+ task.alarm_clear_time = int(task.alarm_clear_time)
|
||||||
|
+ alarm_id = task.alarm_id
|
||||||
|
+ alarm_clear_time = task.alarm_clear_time
|
||||||
|
+
|
||||||
|
+ alarm_list_dict[alarm_id] = []
|
||||||
|
+ task_alarm_id_dict[task_name] = alarm_id
|
||||||
|
+ if alarm_id not in alarm_id_clear_time_dict:
|
||||||
|
+ alarm_id_clear_time_dict[alarm_id] = alarm_clear_time
|
||||||
|
+ else:
|
||||||
|
+ alarm_id_clear_time_dict[alarm_id] = max(alarm_clear_time, alarm_id_clear_time_dict[alarm_id])
|
||||||
|
+ logging.info(f"alarm_register: {task_name} is registered")
|
||||||
|
+ # 注册告警回调
|
||||||
|
+ id_filter = [True] * 128
|
||||||
|
+ clientId = xalarm_register(update_alarm_list, id_filter)
|
||||||
|
+ if clientId < 0:
|
||||||
|
+ logging.info(f'register xalarm: failed')
|
||||||
|
+ return clientId
|
||||||
|
+ logging.info('register xalarm: success')
|
||||||
|
+ return clientId
|
||||||
|
+
|
||||||
|
+def get_alarm_result(task_name: str, time_range: int, detailed: bool) -> List[Dict]:
|
||||||
|
+ alarm_list_lock.acquire()
|
||||||
|
+ try:
|
||||||
|
+ if task_name not in task_alarm_id_dict:
|
||||||
|
+ logging.debug("task_name does not exist")
|
||||||
|
+ return []
|
||||||
|
+ alarm_id = task_alarm_id_dict[task_name]
|
||||||
|
+ clear_time = alarm_id_clear_time_dict[alarm_id]
|
||||||
|
+ if alarm_id not in alarm_list_dict:
|
||||||
|
+ logging.debug("alarm_id does not exist")
|
||||||
|
+ return []
|
||||||
|
+ alarm_list = alarm_list_dict[alarm_id]
|
||||||
|
+ logging.debug(f"get_alarm_result: alarm_list of {alarm_id} has {len(alarm_list)} elements")
|
||||||
|
+ # clear alarm_info older than clear time threshold
|
||||||
|
+ stop_index = -1
|
||||||
|
+ timestamp = datetime.now().timestamp()
|
||||||
|
+ for i in range(len(alarm_list)):
|
||||||
|
+ logging.debug(f"timestamp, alarm_list[{i}].timestamp: {timestamp}, {xalarm_gettime(alarm_list[i])}")
|
||||||
|
+ if timestamp - (xalarm_gettime(alarm_list[i])) / MILLISECONDS_UNIT_SECONDS > time_range:
|
||||||
|
+ stop_index = i
|
||||||
|
+ break
|
||||||
|
+ if timestamp - (xalarm_gettime(alarm_list[i])) / MILLISECONDS_UNIT_SECONDS > clear_time:
|
||||||
|
+ stop_index = i
|
||||||
|
+ break
|
||||||
|
+ if stop_index >= 0:
|
||||||
|
+ alarm_list = alarm_list[:stop_index]
|
||||||
|
+ logging.debug(f"get_alarm_result: final alarm_list of {alarm_id} has {len(alarm_list)} elements")
|
||||||
|
+
|
||||||
|
+ def xalarm_to_dict(alarm_info: Xalarm) -> dict:
|
||||||
|
+ timestamp = alarm_info.timetamp.tv_sec + alarm_info.timetamp.tv_usec / 1000000
|
||||||
|
+ dt_object = datetime.fromtimestamp(int(timestamp))
|
||||||
|
+ return {
|
||||||
|
+ 'alarm_id': xalarm_getid(alarm_info),
|
||||||
|
+ 'alarm_type': xalarm_gettype(alarm_info),
|
||||||
|
+ 'alarm_level': xalarm_getlevel(alarm_info),
|
||||||
|
+ 'timestamp': dt_object.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
+ 'msg1': xalarm_getdesc(alarm_info)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ alarm_list = [xalarm_to_dict(alarm) for alarm in alarm_list]
|
||||||
|
+
|
||||||
|
+ # keep detail
|
||||||
|
+ for alarm in alarm_list:
|
||||||
|
+ alarm_info = alarm['msg1']
|
||||||
|
+ alarm_info = json.loads(alarm_info)
|
||||||
|
+ if not detailed:
|
||||||
|
+ if 'details' in alarm_info:
|
||||||
|
+ alarm_info.pop('details', None)
|
||||||
|
+ alarm.pop('msg1', None)
|
||||||
|
+
|
||||||
|
+ # dump each {key,value} of details in one line
|
||||||
|
+ if 'details' in alarm_info and isinstance(alarm_info['details'], dict):
|
||||||
|
+ for key in alarm_info['details']:
|
||||||
|
+ alarm_info['details'][key] = str(alarm_info['details'][key])
|
||||||
|
+
|
||||||
|
+ alarm['alarm_info'] = alarm_info
|
||||||
|
+ alarm_list = [alarm for alarm in alarm_list if 'alarm_source' in alarm['alarm_info'] and alarm['alarm_info']['alarm_source'] == task_name]
|
||||||
|
+
|
||||||
|
+ alarm_level_mapping = {
|
||||||
|
+ 1: 'MINOR_ALM',
|
||||||
|
+ 2: 'MAJOR_ALM',
|
||||||
|
+ 3: 'CRITICAL_ALM'
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ alarm_type_mapping = {
|
||||||
|
+ 1: 'ALARM_TYPE_OCCUR',
|
||||||
|
+ 2: 'ALARM_TYPE_RECOVER'
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for alarm in alarm_list:
|
||||||
|
+ alarm['alarm_level'] = alarm_level_mapping.get(alarm['alarm_level'], 'UNKNOWN_LEVEL')
|
||||||
|
+ alarm['alarm_type'] = alarm_type_mapping.get(alarm['alarm_type'], 'UNKNOWN_TYPE')
|
||||||
|
+ return alarm_list
|
||||||
|
+
|
||||||
|
+ finally:
|
||||||
|
+ alarm_list_lock.release()
|
||||||
|
diff --git a/src/python/syssentry/callbacks.py b/src/python/syssentry/callbacks.py
|
||||||
|
index d0d0719..d2dff24 100644
|
||||||
|
--- a/src/python/syssentry/callbacks.py
|
||||||
|
+++ b/src/python/syssentry/callbacks.py
|
||||||
|
@@ -18,6 +18,7 @@ import logging
|
||||||
|
|
||||||
|
from .task_map import TasksMap, ONESHOT_TYPE, PERIOD_TYPE
|
||||||
|
from .mod_status import EXITED_STATUS, RUNNING_STATUS, WAITING_STATUS, set_runtime_status
|
||||||
|
+from .alarm import get_alarm_result
|
||||||
|
|
||||||
|
|
||||||
|
def task_get_status(mod_name):
|
||||||
|
@@ -41,6 +42,22 @@ def task_get_result(mod_name):
|
||||||
|
|
||||||
|
return "success", task.get_result()
|
||||||
|
|
||||||
|
+def task_get_alarm(data):
|
||||||
|
+ """get alarm by mod name"""
|
||||||
|
+ task_name = data['task_name']
|
||||||
|
+ time_range = data['time_range']
|
||||||
|
+ try:
|
||||||
|
+ detailed = data['detailed']
|
||||||
|
+ except KeyError:
|
||||||
|
+ logging.debug("Key 'detailed' does not exist in the dictionary")
|
||||||
|
+ detailed = None
|
||||||
|
+ task = TasksMap.get_task_by_name(task_name)
|
||||||
|
+ if not task:
|
||||||
|
+ return "failed", f"cannot find task by name {task_name}"
|
||||||
|
+ if not task.load_enabled:
|
||||||
|
+ return "failed", f"mod {task_name} is not enabled"
|
||||||
|
+
|
||||||
|
+ return "success", get_alarm_result(task_name, time_range, detailed)
|
||||||
|
|
||||||
|
def task_stop(mod_name):
|
||||||
|
"""stop by mod name"""
|
||||||
|
diff --git a/src/python/syssentry/global_values.py b/src/python/syssentry/global_values.py
|
||||||
|
index 483d544..b123b2d 100644
|
||||||
|
--- a/src/python/syssentry/global_values.py
|
||||||
|
+++ b/src/python/syssentry/global_values.py
|
||||||
|
@@ -27,6 +27,7 @@ CTL_SOCKET_PATH = "/var/run/sysSentry/control.sock"
|
||||||
|
SYSSENTRY_CONF_PATH = "/etc/sysSentry"
|
||||||
|
INSPECT_CONF_PATH = "/etc/sysSentry/inspect.conf"
|
||||||
|
TASK_LOG_DIR = "/var/log/sysSentry"
|
||||||
|
+DEFAULT_ALARM_CLEAR_TIME = 15
|
||||||
|
|
||||||
|
SENTRY_RUN_DIR_PERM = 0o750
|
||||||
|
|
||||||
|
@@ -76,6 +77,9 @@ class InspectTask:
|
||||||
|
self.env_file = ""
|
||||||
|
# start mode
|
||||||
|
self.conflict = "up"
|
||||||
|
+ # alarm id
|
||||||
|
+ self.alarm_id = -1
|
||||||
|
+ self.alarm_clear_time = DEFAULT_ALARM_CLEAR_TIME
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""
|
||||||
|
diff --git a/src/python/syssentry/load_mods.py b/src/python/syssentry/load_mods.py
|
||||||
|
index 5be5540..ac15380 100644
|
||||||
|
--- a/src/python/syssentry/load_mods.py
|
||||||
|
+++ b/src/python/syssentry/load_mods.py
|
||||||
|
@@ -24,6 +24,7 @@ from .task_map import TasksMap, ONESHOT_TYPE, PERIOD_TYPE
|
||||||
|
from .cron_process import PeriodTask
|
||||||
|
from .mod_status import set_task_status
|
||||||
|
|
||||||
|
+from xalarm.register_xalarm import MIN_ALARM_ID, MAX_ALARM_ID
|
||||||
|
ONESHOT_CONF = 'oneshot'
|
||||||
|
PERIOD_CONF = 'period'
|
||||||
|
|
||||||
|
@@ -41,6 +42,8 @@ CONF_TASK_RESTART = 'task_restart'
|
||||||
|
CONF_ONSTART = 'onstart'
|
||||||
|
CONF_ENV_FILE = 'env_file'
|
||||||
|
CONF_CONFLICT = 'conflict'
|
||||||
|
+CONF_ALARM_ID = 'alarm_id'
|
||||||
|
+CONF_ALARM_CLEAR_TIME = 'alarm_clear_time'
|
||||||
|
|
||||||
|
MOD_FILE_SUFFIX = '.mod'
|
||||||
|
MOD_SUFFIX_LEN = 4
|
||||||
|
@@ -194,6 +197,18 @@ def parse_mod_conf(mod_name, mod_conf):
|
||||||
|
task.heartbeat_interval = heartbeat_interval
|
||||||
|
task.load_enabled = is_enabled
|
||||||
|
|
||||||
|
+ try:
|
||||||
|
+ task.alarm_id = mod_conf.get(CONF_TASK, CONF_ALARM_ID)
|
||||||
|
+ except configparser.NoOptionError:
|
||||||
|
+ task.alarm_id = None
|
||||||
|
+ logging.warning(f"{mod_name} alarm_id not set, alarm_id is None")
|
||||||
|
+
|
||||||
|
+ if task.alarm_id is not None:
|
||||||
|
+ try:
|
||||||
|
+ task.alarm_clear_time = mod_conf.get(CONF_TASK, CONF_ALARM_CLEAR_TIME)
|
||||||
|
+ except configparser.NoOptionError:
|
||||||
|
+ logging.warning(f"{mod_name} not set alarm_clear_time, use 15s as default")
|
||||||
|
+
|
||||||
|
if CONF_ONSTART in mod_conf.options(CONF_TASK):
|
||||||
|
is_onstart = (mod_conf.get(CONF_TASK, CONF_ONSTART) == 'yes')
|
||||||
|
if task_type == PERIOD_CONF:
|
||||||
|
@@ -328,3 +343,4 @@ def reload_single_mod(mod_name):
|
||||||
|
res, ret = reload_mod_by_name(mod_name)
|
||||||
|
|
||||||
|
return res, ret
|
||||||
|
+
|
||||||
|
diff --git a/src/python/syssentry/sentryctl b/src/python/syssentry/sentryctl
|
||||||
|
index e94491f..c2e3cef 100644
|
||||||
|
--- a/src/python/syssentry/sentryctl
|
||||||
|
+++ b/src/python/syssentry/sentryctl
|
||||||
|
@@ -25,6 +25,8 @@ MAX_PARAM_LENGTH = 256
|
||||||
|
|
||||||
|
RESULT_MSG_DATA_LEN = 4
|
||||||
|
CTL_MSG_LEN_LEN = 3
|
||||||
|
+ALARM_MSG_DATA_LEN = 6
|
||||||
|
+DEFAULT_ALARM_TIME_RANGE = 10
|
||||||
|
|
||||||
|
def status_output_format(res_data):
|
||||||
|
"""format output"""
|
||||||
|
@@ -57,6 +59,8 @@ def res_output_handle(res_struct, req_type):
|
||||||
|
status_output_format(res_struct['data'])
|
||||||
|
elif req_type == 'get_result':
|
||||||
|
result_output_format(res_struct['data'])
|
||||||
|
+ elif req_type == 'get_alarm':
|
||||||
|
+ result_output_format(res_struct['data'])
|
||||||
|
elif res_struct['ret'] == "failed":
|
||||||
|
print(res_struct['data'])
|
||||||
|
|
||||||
|
@@ -75,6 +79,7 @@ def client_send_and_recv(request_data, data_str_len):
|
||||||
|
print("sentryctl: client creat socket error")
|
||||||
|
return None
|
||||||
|
|
||||||
|
+ # connect to syssentry
|
||||||
|
try:
|
||||||
|
client_socket.connect(CTL_SOCKET_PATH)
|
||||||
|
except OSError:
|
||||||
|
@@ -82,6 +87,7 @@ def client_send_and_recv(request_data, data_str_len):
|
||||||
|
print("sentryctl: client connect error")
|
||||||
|
return None
|
||||||
|
|
||||||
|
+ # msg: CTL{len}{data}
|
||||||
|
req_data_len = len(request_data)
|
||||||
|
request_msg = "CTL" + str(req_data_len).zfill(3) + request_data
|
||||||
|
|
||||||
|
@@ -94,8 +100,8 @@ def client_send_and_recv(request_data, data_str_len):
|
||||||
|
print("sentryctl: client communicate error")
|
||||||
|
return None
|
||||||
|
|
||||||
|
+ # res: RES{len}{data}
|
||||||
|
res_magic = res_data[:3]
|
||||||
|
-
|
||||||
|
if res_magic != "RES":
|
||||||
|
print("res msg format error")
|
||||||
|
return None
|
||||||
|
@@ -128,6 +134,10 @@ if __name__ == '__main__':
|
||||||
|
parser_status.add_argument('task_name')
|
||||||
|
parser_get_result = subparsers.add_parser('get_result', help='get task result')
|
||||||
|
parser_get_result.add_argument('task_name')
|
||||||
|
+ parser_get_alarm = subparsers.add_parser('get_alarm', help='get task alarm')
|
||||||
|
+ parser_get_alarm.add_argument('task_name')
|
||||||
|
+ parser_get_alarm.add_argument('-s', '--time_range', type=int, default=DEFAULT_ALARM_TIME_RANGE, help='Specified time range')
|
||||||
|
+ parser_get_alarm.add_argument('-d', '--detailed', action='store_true', help='Print Detailed Information')
|
||||||
|
parser_list = subparsers.add_parser('list', help='show all loaded task mod')
|
||||||
|
|
||||||
|
client_args = parser.parse_args()
|
||||||
|
@@ -142,6 +152,17 @@ if __name__ == '__main__':
|
||||||
|
req_msg_struct = {"type": "get_status", "data": client_args.task_name}
|
||||||
|
elif client_args.cmd_type == 'get_result':
|
||||||
|
req_msg_struct = {"type": "get_result", "data": client_args.task_name}
|
||||||
|
+ elif client_args.cmd_type == 'get_alarm':
|
||||||
|
+ if not isinstance(client_args.time_range, int) or client_args.time_range <= 0:
|
||||||
|
+ print(f"time_range is not a positive integer: {client_args.time_range}")
|
||||||
|
+ req_msg_struct = {
|
||||||
|
+ "type": "get_alarm",
|
||||||
|
+ "data": {
|
||||||
|
+ 'task_name': client_args.task_name,
|
||||||
|
+ 'time_range': client_args.time_range,
|
||||||
|
+ 'detailed': client_args.detailed,
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
elif client_args.cmd_type == 'reload':
|
||||||
|
req_msg_struct = {"type": "reload", "data": client_args.task_name}
|
||||||
|
else:
|
||||||
|
@@ -155,6 +176,8 @@ if __name__ == '__main__':
|
||||||
|
request_message = json.dumps(req_msg_struct)
|
||||||
|
if client_args.cmd_type == 'get_result':
|
||||||
|
result_message = client_send_and_recv(request_message, RESULT_MSG_DATA_LEN)
|
||||||
|
+ elif client_args.cmd_type == 'get_alarm':
|
||||||
|
+ result_message = client_send_and_recv(request_message, ALARM_MSG_DATA_LEN)
|
||||||
|
else:
|
||||||
|
result_message = client_send_and_recv(request_message, CTL_MSG_LEN_LEN)
|
||||||
|
if not result_message:
|
||||||
|
diff --git a/src/python/syssentry/syssentry.py b/src/python/syssentry/syssentry.py
|
||||||
|
index 0956e1e..c87256d 100644
|
||||||
|
--- a/src/python/syssentry/syssentry.py
|
||||||
|
+++ b/src/python/syssentry/syssentry.py
|
||||||
|
@@ -28,7 +28,7 @@ from .sentry_config import SentryConfig, get_log_level
|
||||||
|
from .task_map import TasksMap
|
||||||
|
from .global_values import SENTRY_RUN_DIR, CTL_SOCKET_PATH, SENTRY_RUN_DIR_PERM
|
||||||
|
from .cron_process import period_tasks_handle
|
||||||
|
-from .callbacks import mod_list_show, task_start, task_get_status, task_stop, task_get_result
|
||||||
|
+from .callbacks import mod_list_show, task_start, task_get_status, task_stop, task_get_result, task_get_alarm
|
||||||
|
from .mod_status import get_task_by_pid, set_runtime_status
|
||||||
|
from .load_mods import load_tasks, reload_single_mod
|
||||||
|
from .heartbeat import (heartbeat_timeout_chk, heartbeat_fd_create,
|
||||||
|
@@ -36,7 +36,11 @@ from .heartbeat import (heartbeat_timeout_chk, heartbeat_fd_create,
|
||||||
|
from .result import RESULT_MSG_HEAD_LEN, RESULT_MSG_MAGIC_LEN, RESULT_MAGIC
|
||||||
|
from .result import RESULT_LEVEL_ERR_MSG_DICT, ResultLevel
|
||||||
|
from .utils import get_current_time_string
|
||||||
|
+from .alarm import alarm_register
|
||||||
|
|
||||||
|
+from xalarm.register_xalarm import xalarm_unregister
|
||||||
|
+
|
||||||
|
+clientId = -1
|
||||||
|
|
||||||
|
CPU_EXIST = True
|
||||||
|
try:
|
||||||
|
@@ -58,6 +62,7 @@ CTL_MSG_MAGIC_LEN = 3
|
||||||
|
CTL_MSG_LEN_LEN = 3
|
||||||
|
CTL_MAGIC = "CTL"
|
||||||
|
RES_MAGIC = "RES"
|
||||||
|
+ALARM_MSG_DATA_LEN = 6
|
||||||
|
|
||||||
|
CTL_LISTEN_QUEUE_LEN = 5
|
||||||
|
SERVER_EPOLL_TIMEOUT = 0.3
|
||||||
|
@@ -68,6 +73,7 @@ type_func = {
|
||||||
|
'stop': task_stop,
|
||||||
|
'get_status': task_get_status,
|
||||||
|
'get_result': task_get_result,
|
||||||
|
+ 'get_alarm': task_get_alarm,
|
||||||
|
'reload': reload_single_mod
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -260,6 +266,8 @@ def server_recv(server_socket: socket.socket):
|
||||||
|
res_head = RES_MAGIC
|
||||||
|
if cmd_type == "get_result":
|
||||||
|
res_data_len = str(len(res_data)).zfill(RESULT_MSG_HEAD_LEN - RESULT_MSG_MAGIC_LEN)
|
||||||
|
+ elif cmd_type == "get_alarm":
|
||||||
|
+ res_data_len = str(len(res_data)).zfill(ALARM_MSG_DATA_LEN)
|
||||||
|
else:
|
||||||
|
res_data_len = str(len(res_data)).zfill(CTL_MSG_MAGIC_LEN)
|
||||||
|
res_head += res_data_len
|
||||||
|
@@ -643,9 +651,13 @@ def main():
|
||||||
|
_ = SentryConfig.init_param()
|
||||||
|
TasksMap.init_task_map()
|
||||||
|
load_tasks()
|
||||||
|
+ clientId = alarm_register()
|
||||||
|
main_loop()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logging.error('%s', traceback.format_exc())
|
||||||
|
finally:
|
||||||
|
+ if clientId != -1:
|
||||||
|
+ xalarm_unregister(clientId)
|
||||||
|
release_pidfile()
|
||||||
|
+
|
||||||
|
diff --git a/src/python/syssentry/task_map.py b/src/python/syssentry/task_map.py
|
||||||
|
index 70aa19d..27e97ff 100644
|
||||||
|
--- a/src/python/syssentry/task_map.py
|
||||||
|
+++ b/src/python/syssentry/task_map.py
|
||||||
|
@@ -13,16 +13,16 @@
|
||||||
|
tasks map class and initialize function.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
+from typing import Dict
|
||||||
|
|
||||||
|
ONESHOT_TYPE = "ONESHOT"
|
||||||
|
PERIOD_TYPE = "PERIOD"
|
||||||
|
|
||||||
|
TASKS_MAP = None
|
||||||
|
|
||||||
|
-
|
||||||
|
class TasksMap:
|
||||||
|
"""task map class"""
|
||||||
|
- tasks_dict = {}
|
||||||
|
+ tasks_dict: Dict[str, Dict] = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def init_task_map(cls):
|
||||||
|
@@ -65,3 +65,4 @@ class TasksMap:
|
||||||
|
logging.debug("getting task by name: %s", res)
|
||||||
|
break
|
||||||
|
return res
|
||||||
|
+
|
||||||
|
diff --git a/src/python/xalarm/register_xalarm.py b/src/python/xalarm/register_xalarm.py
|
||||||
|
index 4f51e66..2a6dabf 100644
|
||||||
|
--- a/src/python/xalarm/register_xalarm.py
|
||||||
|
+++ b/src/python/xalarm/register_xalarm.py
|
||||||
|
@@ -115,6 +115,7 @@ class AlarmRegister:
|
||||||
|
def stop_thread(self) -> None:
|
||||||
|
self.thread_should_stop = True
|
||||||
|
self.thread.join()
|
||||||
|
+ self.socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
def xalarm_register(callback: callable, id_filter: list) -> int:
|
||||||
|
@@ -147,7 +148,7 @@ def xalarm_unregister(clientId: int) -> None:
|
||||||
|
ALARM_REGISTER_INFO = None
|
||||||
|
|
||||||
|
|
||||||
|
-def xalarm_upgrade(clientId: int, id_filter: list) -> bool:
|
||||||
|
+def xalarm_upgrade(id_filter: list, clientId: int) -> bool:
|
||||||
|
global ALARM_REGISTER_INFO
|
||||||
|
if clientId < 0:
|
||||||
|
sys.stderr.write("xalarm_upgrade: invalid client\n")
|
||||||
|
@@ -193,4 +194,3 @@ def xalarm_getdesc(alarm_info: Xalarm) -> str:
|
||||||
|
except UnicodeError:
|
||||||
|
desc_str = None
|
||||||
|
return desc_str
|
||||||
|
-
|
||||||
|
diff --git a/src/python/xalarm/xalarm_api.py b/src/python/xalarm/xalarm_api.py
|
||||||
|
index c365019..863bd02 100644
|
||||||
|
--- a/src/python/xalarm/xalarm_api.py
|
||||||
|
+++ b/src/python/xalarm/xalarm_api.py
|
||||||
|
@@ -98,15 +98,15 @@ class Xalarm:
|
||||||
|
def msg1(self, msg):
|
||||||
|
"""msg1 setter
|
||||||
|
"""
|
||||||
|
- if len(msg) > 512:
|
||||||
|
- raise ValueError("msg1 length must below 512")
|
||||||
|
+ if len(msg) > MAX_MSG_LEN:
|
||||||
|
+ raise ValueError(f"msg1 length must below {MAX_MSG_LEN}")
|
||||||
|
self._msg1 = msg
|
||||||
|
|
||||||
|
|
||||||
|
def alarm_bin2stu(bin_data):
|
||||||
|
"""alarm binary to struct
|
||||||
|
"""
|
||||||
|
- struct_data = struct.unpack("@HBBll512s", bin_data)
|
||||||
|
+ struct_data = struct.unpack(f"@HBBll{MAX_MSG_LEN}s", bin_data)
|
||||||
|
|
||||||
|
alarm_info = Xalarm(1001, 2, 1, 0, 0, "")
|
||||||
|
alarm_info.alarm_id = struct_data[0]
|
||||||
|
diff --git a/src/python/xalarm/xalarm_config.py b/src/python/xalarm/xalarm_config.py
|
||||||
|
index 8e56d10..754a816 100644
|
||||||
|
--- a/src/python/xalarm/xalarm_config.py
|
||||||
|
+++ b/src/python/xalarm/xalarm_config.py
|
||||||
|
@@ -15,9 +15,10 @@ Create: 2023-11-02
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
+import os
|
||||||
|
import dataclasses
|
||||||
|
import logging
|
||||||
|
-from configparser import ConfigParser
|
||||||
|
+import configparser
|
||||||
|
|
||||||
|
|
||||||
|
MAIN_CONFIG_PATH = '/etc/sysSentry/xalarm.conf'
|
||||||
|
@@ -27,6 +28,34 @@ MIN_ID_NUMBER = 1001
|
||||||
|
MAX_ID_NUMBER = 1128
|
||||||
|
MAX_ID_MASK_CAPACITY = 128
|
||||||
|
|
||||||
|
+# log
|
||||||
|
+CONF_LOG = 'log'
|
||||||
|
+CONF_LOG_LEVEL = 'level'
|
||||||
|
+LogLevel = {
|
||||||
|
+ "debug": logging.DEBUG,
|
||||||
|
+ "info": logging.INFO,
|
||||||
|
+ "warning": logging.WARNING,
|
||||||
|
+ "error": logging.ERROR,
|
||||||
|
+ "critical": logging.CRITICAL
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def get_log_level(filename=MAIN_CONFIG_PATH):
|
||||||
|
+ if not os.path.exists(filename):
|
||||||
|
+ return logging.INFO
|
||||||
|
+
|
||||||
|
+ try:
|
||||||
|
+ config = configparser.ConfigParser()
|
||||||
|
+ config.read(filename)
|
||||||
|
+ if not config.has_option(CONF_LOG, CONF_LOG_LEVEL):
|
||||||
|
+ return logging.INFO
|
||||||
|
+ log_level = config.get(CONF_LOG, CONF_LOG_LEVEL)
|
||||||
|
+ if log_level.lower() in LogLevel:
|
||||||
|
+ return LogLevel.get(log_level.lower())
|
||||||
|
+ return logging.INFO
|
||||||
|
+ except configparser.Error:
|
||||||
|
+ return logging.INFO
|
||||||
|
+
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class AlarmConfig:
|
||||||
|
@@ -106,7 +135,7 @@ def config_init():
|
||||||
|
"""
|
||||||
|
alarm_config = AlarmConfig()
|
||||||
|
|
||||||
|
- cfg = ConfigParser()
|
||||||
|
+ cfg = configparser.ConfigParser()
|
||||||
|
cfg.read(MAIN_CONFIG_PATH)
|
||||||
|
|
||||||
|
id_mask = parse_id_mask(cfg)
|
||||||
|
diff --git a/src/python/xalarm/xalarm_daemon.py b/src/python/xalarm/xalarm_daemon.py
|
||||||
|
index 00e8886..3ab211c 100644
|
||||||
|
--- a/src/python/xalarm/xalarm_daemon.py
|
||||||
|
+++ b/src/python/xalarm/xalarm_daemon.py
|
||||||
|
@@ -21,7 +21,7 @@ import signal
|
||||||
|
import fcntl
|
||||||
|
import socket
|
||||||
|
|
||||||
|
-from .xalarm_config import config_init
|
||||||
|
+from .xalarm_config import config_init, get_log_level
|
||||||
|
from .xalarm_server import server_loop, SOCK_FILE
|
||||||
|
|
||||||
|
ALARM_DIR = "/var/run/xalarm"
|
||||||
|
@@ -120,9 +120,10 @@ def alarm_process_create():
|
||||||
|
os.mkdir(ALARM_DIR)
|
||||||
|
os.chmod(ALARM_DIR, ALARM_DIR_PERMISSION)
|
||||||
|
|
||||||
|
+ log_level = get_log_level()
|
||||||
|
+ log_format = "%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s"
|
||||||
|
|
||||||
|
- logging.basicConfig(filename=ALARM_LOGFILE, level=logging.INFO,
|
||||||
|
- format='%(asctime)s|%(levelname)s| %(message)s')
|
||||||
|
+ logging.basicConfig(filename=ALARM_LOGFILE, level=log_level, format=log_format)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
|
||||||
|
diff --git a/src/python/xalarm/xalarm_transfer.py b/src/python/xalarm/xalarm_transfer.py
|
||||||
|
index 010d2ee..d135095 100644
|
||||||
|
--- a/src/python/xalarm/xalarm_transfer.py
|
||||||
|
+++ b/src/python/xalarm/xalarm_transfer.py
|
||||||
|
@@ -62,7 +62,6 @@ def cleanup_closed_connections(server_sock, epoll, fd_to_socket):
|
||||||
|
to_remove.append(fileno)
|
||||||
|
|
||||||
|
for fileno in to_remove:
|
||||||
|
- epoll.unregister(fileno)
|
||||||
|
fd_to_socket[fileno].close()
|
||||||
|
del fd_to_socket[fileno]
|
||||||
|
logging.info(f"cleaned up connection {fileno} for client lost connection.")
|
||||||
|
@@ -97,13 +96,12 @@ def wait_for_connection(server_sock, epoll, fd_to_socket, thread_should_stop):
|
||||||
|
logging.info(f"connection reach max num of {MAX_CONNECTION_NUM}, closed current connection!")
|
||||||
|
connection.close()
|
||||||
|
continue
|
||||||
|
- epoll.register(connection.fileno(), select.EPOLLOUT)
|
||||||
|
fd_to_socket[connection.fileno()] = connection
|
||||||
|
except socket.error as e:
|
||||||
|
- logging.debug("socket error, reason is %s", e)
|
||||||
|
+ logging.debug(f"socket error, reason is {e}")
|
||||||
|
break
|
||||||
|
except (KeyError, OSError, ValueError) as e:
|
||||||
|
- logging.debug("wait for connection failed %s", e)
|
||||||
|
+ logging.debug(f"wait for connection failed {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def transmit_alarm(server_sock, epoll, fd_to_socket, bin_data):
|
||||||
|
@@ -122,7 +120,7 @@ def transmit_alarm(server_sock, epoll, fd_to_socket, bin_data):
|
||||||
|
except (BrokenPipeError, ConnectionResetError):
|
||||||
|
to_remove.append(fileno)
|
||||||
|
for fileno in to_remove:
|
||||||
|
- epoll.unregister(fileno)
|
||||||
|
fd_to_socket[fileno].close()
|
||||||
|
del fd_to_socket[fileno]
|
||||||
|
logging.info(f"cleaned up connection {fileno} for client lost connection.")
|
||||||
|
+
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
@ -4,7 +4,7 @@
|
|||||||
Summary: System Inspection Framework
|
Summary: System Inspection Framework
|
||||||
Name: sysSentry
|
Name: sysSentry
|
||||||
Version: 1.0.2
|
Version: 1.0.2
|
||||||
Release: 27
|
Release: 28
|
||||||
License: Mulan PSL v2
|
License: Mulan PSL v2
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
Source0: https://gitee.com/openeuler/sysSentry/releases/download/v%{version}/%{name}-%{version}.tar.gz
|
Source0: https://gitee.com/openeuler/sysSentry/releases/download/v%{version}/%{name}-%{version}.tar.gz
|
||||||
@ -37,6 +37,7 @@ Patch24: change-status-of-period-task-and-sort-mod-file.patch
|
|||||||
Patch25: set-logrotate.patch
|
Patch25: set-logrotate.patch
|
||||||
Patch26: hbm_online_repair-add-unload-driver.patch
|
Patch26: hbm_online_repair-add-unload-driver.patch
|
||||||
Patch27: add-pyxalarm-and-pySentryNotify-add-multi-users-supp.patch
|
Patch27: add-pyxalarm-and-pySentryNotify-add-multi-users-supp.patch
|
||||||
|
Patch28: adapt_5.10_kenel_for_syssentry.patch
|
||||||
|
|
||||||
BuildRequires: cmake gcc-c++
|
BuildRequires: cmake gcc-c++
|
||||||
BuildRequires: python3 python3-setuptools
|
BuildRequires: python3 python3-setuptools
|
||||||
@ -238,6 +239,12 @@ rm -rf %{buildroot}
|
|||||||
%attr(0550,root,root) %{python3_sitelib}/syssentry/bmc_alarm.py
|
%attr(0550,root,root) %{python3_sitelib}/syssentry/bmc_alarm.py
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Jan 24 2025 jinsaihang <jinsaihang@h-partners.com> - 1.0.2-28
|
||||||
|
- Type:bugfix
|
||||||
|
- CVE:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:adapt get_alarm for kenel 5.10
|
||||||
|
|
||||||
* Wed Jan 22 2025 shixuantong <shixuantong@huawei.com> - 1.0.2-27
|
* Wed Jan 22 2025 shixuantong <shixuantong@huawei.com> - 1.0.2-27
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- CVE:NA
|
- CVE:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user