sysSentry/adapt_5.10_kenel_for_syssentry.patch

703 lines
26 KiB
Diff
Raw Permalink Normal View History

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