sysSentry/adapt_5.10_kenel_for_syssentry.patch
jinsaihang fb523d6c78 adapt get_alarm for kenel 5.10
Signed-off-by: jinsaihang <jinsaihang@h-partners.com>
2025-01-24 16:33:17 +08:00

703 lines
26 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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为告警IDvalue为老化时间类型为数字单位为秒
+alarm_id_clear_time_dict: Dict[int, int] = {}
+
+# 告警事件列表key为告警IDvalue为告警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