From fa691788e13df1b0666839c606446f56951c0ef0 Mon Sep 17 00:00:00 2001 From: hewh Date: Fri, 29 Aug 2025 18:03:54 +0800 Subject: [PATCH 01/16] add test . --- Makefile | 16 +- config/plugins/bmc_block_io.ini | 11 + config/tasks/bmc_block_io.mod | 7 + src/sentryPlugins/bmc_block_io/CMakeLists.txt | 19 + src/sentryPlugins/bmc_block_io/build.sh | 26 ++ .../bmc_block_io/include/cbmcblockio.h | 70 +++ .../bmc_block_io/include/common.h | 45 ++ .../bmc_block_io/include/configure.h | 25 ++ .../bmc_block_io/include/logger.h | 91 ++++ .../bmc_block_io/src/cbmcblockio.cpp | 415 ++++++++++++++++++ src/sentryPlugins/bmc_block_io/src/common.cpp | 202 +++++++++ src/sentryPlugins/bmc_block_io/src/logger.cpp | 165 +++++++ src/sentryPlugins/bmc_block_io/src/main.cpp | 126 ++++++ 13 files changed, 1216 insertions(+), 2 deletions(-) create mode 100644 config/plugins/bmc_block_io.ini create mode 100644 config/tasks/bmc_block_io.mod create mode 100644 src/sentryPlugins/bmc_block_io/CMakeLists.txt create mode 100644 src/sentryPlugins/bmc_block_io/build.sh create mode 100644 src/sentryPlugins/bmc_block_io/include/cbmcblockio.h create mode 100644 src/sentryPlugins/bmc_block_io/include/common.h create mode 100644 src/sentryPlugins/bmc_block_io/include/configure.h create mode 100644 src/sentryPlugins/bmc_block_io/include/logger.h create mode 100644 src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp create mode 100644 src/sentryPlugins/bmc_block_io/src/common.cpp create mode 100644 src/sentryPlugins/bmc_block_io/src/logger.cpp create mode 100644 src/sentryPlugins/bmc_block_io/src/main.cpp diff --git a/Makefile b/Makefile index aeb9950..4b99d8c 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ PYTHON_VERSION := $(shell $(PYBIN) --version 2>&1 | awk '{print $$2}' | cut -d ' PKGVER := syssentry-$(VERSION)-py$(PYTHON_VERSION) PKGVEREGG := syssentry-$(VERSION)-py$(PYTHON_VERSION).egg-info -all: lib ebpf hbm_online_repair sentry_msg_monitor +all: lib ebpf hbm_online_repair sentry_msg_monitor bmc_block_io lib:libxalarm log @@ -50,6 +50,9 @@ hbm_online_repair: sentry_msg_monitor: lib cd $(CURSRCDIR)/sentryPlugins/sentry_msg_monitor/ && make +bmc_block_io: + cd $(CURSRCDIR)/sentryPlugins/bmc_block_io/ && sh build.sh + install: all dirs isentry dirs: @@ -131,6 +134,11 @@ isentry: install -m 600 $(CURCONFIGDIR)/env/sentry_msg_monitor.env $(ETCDIR)/sysconfig/ install -m 600 $(CURCONFIGDIR)/tasks/sentry_msg_monitor.mod $(ETCDIR)/sysSentry/tasks/ + # bmc_block_io + install -m 550 $(CURSRCDIR)/sentryPlugins/bmc_block_io/output/bmc_block_io $(BINDIR) + install -m 600 $(CURCONFIGDIR)/plugins/bmc_block_io.ini $(ETCDIR)/sysSentry/plugins/ + install -m 600 $(CURCONFIGDIR)/tasks/bmc_block_io.mod $(ETCDIR)/sysSentry/tasks/ + # pysentry_notify install -m 550 src/libsentry/python/pySentryNotify/sentry_notify.py $(PYDIR)/xalarm @@ -161,7 +169,10 @@ hbm_clean: smm_clean: cd $(CURSRCDIR)/sentryPlugins/sentry_msg_monitor && make clean -clean: ebpf_clean hbm_clean smm_clean +bmc_clean: + cd $(CURSRCDIR)/sentryPlugins/bmc_block_io && sh build.sh clean + +clean: ebpf_clean hbm_clean smm_clean bmc_clean rm -rf $(CURLIBDIR)/build rm -rf $(CURSRCDIR)/build rm -rf $(CURSRCDIR)/libsentry/c/log/build @@ -175,6 +186,7 @@ uninstall: rm -rf $(BINDIR)/sentryCollector rm -rf $(BINDIR)/hbm_online_repair rm -rf $(BINDIR)/sentry_msg_monitor + rm -rf $(BINDIR)/bmc_block_io rm -rf $(BINDIR)/ebpf_collector rm -rf $(LIBINSTALLDIR)/libxalarm.so rm -rf $(INCLUDEDIR)/xalarm diff --git a/config/plugins/bmc_block_io.ini b/config/plugins/bmc_block_io.ini new file mode 100644 index 0000000..3b22618 --- /dev/null +++ b/config/plugins/bmc_block_io.ini @@ -0,0 +1,11 @@ +# log level, accepts debug, info, warning, error or critical +log_level=info + +# polling cycle, unit: seconds, range: [60, 3600] +patrol_second=5 + +# ipmitool login username +bmc_username=Administrator + +# ipmitool login passwd +bmc_passwd=Admin@9000 \ No newline at end of file diff --git a/config/tasks/bmc_block_io.mod b/config/tasks/bmc_block_io.mod new file mode 100644 index 0000000..9518c5f --- /dev/null +++ b/config/tasks/bmc_block_io.mod @@ -0,0 +1,7 @@ +[common] +enabled=yes +task_start=/usr/bin/bmc_block_io +task_stop=kill $pid +type=oneshot +alarm_id=1002 +alarm_clear_time=5 \ No newline at end of file diff --git a/src/sentryPlugins/bmc_block_io/CMakeLists.txt b/src/sentryPlugins/bmc_block_io/CMakeLists.txt new file mode 100644 index 0000000..818a0a8 --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required (VERSION 3.12) +project(bmc_block_io) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/output) + +include_directories( + ${CMAKE_SOURCE_DIR}/include +) + +set(SOURCE src/main.cpp + src/logger.cpp + src/common.cpp + src/cbmcblockio.cpp) + +add_executable(bmc_block_io ${SOURCE}) +target_link_libraries(bmc_block_io PRIVATE xalarm pthread json-c) diff --git a/src/sentryPlugins/bmc_block_io/build.sh b/src/sentryPlugins/bmc_block_io/build.sh new file mode 100644 index 0000000..8db398c --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/build.sh @@ -0,0 +1,26 @@ +#!/bin/sh +echo "----------build begin------------" +echo "---------------------------------" + +BUILD_DIR=build + +if [ "$1" = "clean" ]; then + if [ -d "$BUILD_DIR" ]; then + echo "----------clean begin------------" + cd "$BUILD_DIR" && make clean + echo "----------clean end--------------" + else + echo "Build directory does not exist. Nothing to clean." + fi + exit 0 +fi + +[ ! -d $BUILD_DIR ] && mkdir -p $BUILD_DIR +cd $BUILD_DIR + +cmake .. +make || exit "$?" + +echo "------- build end -----------" +echo "-----------------------------" +exit 0 \ No newline at end of file diff --git a/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h b/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h new file mode 100644 index 0000000..cb0b514 --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#ifndef _BMC_BLOCK_IO_H_ +#define _BMC_BLOCK_IO_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace BMCBlockIoPlu { + +struct ResponseHeader { + uint16_t totalEvents; + uint8_t eventCount; + bool valid; +}; + +struct IPMIEvent { + uint32_t alarmTypeCode; + uint32_t timestamp; + uint8_t severity; + uint8_t subjectType; + uint8_t deviceId; + bool valid; +}; + +class CBMCBlockIo { +public: + CBMCBlockIo(); + ~CBMCBlockIo(); + void Start(); + void Stop(); + void SetPatrolInterval(int seconds); + void SetUserName(std::string userName); + void SetPassWd(std::string passWd); + bool IsRunning(); +private: + void SentryWorker(); + void GetBMCIp(); + void ReportAlarm(const IPMIEvent& event); + void ReportResult(int resultLevel, const std::string& msg); + int QueryEvents(); + std::string BuildIPMICommand(uint16_t startIndex); + std::vector ExecuteIPMICommand(const std::string& cmd); + ResponseHeader ParseResponseHeader(const std::vector& hexBytes); + IPMIEvent ParseSingleEvent(const std::vector& hexBytes, size_t startPos); + void ProcessEvents(const std::vector& hexBytes, uint8_t eventCount); + +private: + std::atomic m_running; + std::thread m_worker; + std::mutex m_mutex; + std::condition_variable m_cv; + std::string m_userName; + std::string m_passWd; + std::string m_bmcIp; + int m_patrolSeconds; +}; +} +#endif + diff --git a/src/sentryPlugins/bmc_block_io/include/common.h b/src/sentryPlugins/bmc_block_io/include/common.h new file mode 100644 index 0000000..2bd0980 --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/include/common.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#ifndef _BMCPLU_COMMON_H_ +#define _BMCPLU_COMMON_H_ + +#include +#include +#include +#include +#include "configure.h" +#include "logger.h" + +#define BMCPLU_FAILED (-1) +#define BMCPLU_SUCCESS (0) + +struct PluConfig { + BMCBlockIoPlu::Logger::Level logLevel; + int patrolSeconds; + std::string userName; + std::string passWd; +}; + +struct ConfigItem { + bool required; + bool found; + std::function processor; +}; + +namespace BMCBlockIoPlu { + +std::string Trim(const std::string& str); +bool IsValidNumber(const std::string& str, int& num); +int ParseConfig(const std::string& path, PluConfig& config); +std::string ExtractFileName(const std::string& path); +int ExecCommand(const std::string cmd, std::vector& result); +std::string ByteToHex(uint8_t byte); +std::vector SplitString(const std::string& str, const std::string& split); +} + +#endif diff --git a/src/sentryPlugins/bmc_block_io/include/configure.h b/src/sentryPlugins/bmc_block_io/include/configure.h new file mode 100644 index 0000000..65a56ce --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/include/configure.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#ifndef _BMCPLU_CONFIGURE_H_ +#define _BMCPLU_CONFIGURE_H_ + +#include + +namespace BMCBlockIoPlu { + +const std::string BMCPLU_CONFIG_PATH = "/etc/sysSentry/plugins/bmc_block_io.ini"; +const std::string BMCPLU_LOG_PATH = "/var/log/sysSentry/bmc_block_io.log"; +const std::string BMCPLU_DEFAULT_USERNAME = "Administrator"; +const std::string BMCPLU_DEFAULT_PASSWD = "Admin@9000"; +const int BMCPLU_PATROL_MIN = 1; +const int BMCPLU_PATROL_MAX = 3600; +const int BMCPLU_PATROL_DEFAULT = 600; +const int BMCPLU_CONFIG_CHECK_CYCLE = 10; // seconds +const int BMCPLU_DEFAULT_SLEEP_CYCLE = 3; // seconds +} +#endif diff --git a/src/sentryPlugins/bmc_block_io/include/logger.h b/src/sentryPlugins/bmc_block_io/include/logger.h new file mode 100644 index 0000000..0627993 --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/include/logger.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#ifndef __BMCPLU_LOGGER_H__ +#define __BMCPLU_LOGGER_H__ + +#include +#include +#include +#include +#include +#include + +namespace BMCBlockIoPlu { + +class Logger { +public: + enum class Level { + Debug, + Info, + Warning, + Error, + Critical + }; + static Logger& GetInstance(); + Logger(const Logger&) = delete; + Logger& operator=(const Logger&) = delete; + bool Initialize(const std::string& logPath, Level level = Level::Info); + void SetLevel(Level level); + Level GetLevel() const; + void WriteLog(Level level, const char* file, int line, const std::string& message); + std::string LevelToString(Level level) const; +private: + Logger() = default; + void OpenLogFile(); + void CheckFileState(); + void ReopenLogFile(); + std::string GetTimeStamp() const; + std::string Format(Level level, const char* file, int line, const std::string& message) const; + +private: + std::ofstream m_logFile; + std::string m_logPath; + Level m_level = Level::Info; + mutable std::mutex m_writeMutex; + std::time_t m_checkTime = 0; + ino_t m_inode = 0; + dev_t m_device = 0; + off_t m_fileSize = 0; + bool m_fileOpen = false; +}; + +class LogStream { +public: + LogStream(Logger::Level level, const char* file, int line) + : m_level(level), m_file(file), m_line(line) + {} + ~LogStream() + { + Logger::GetInstance().WriteLog(m_level, m_file, m_line, m_stream.str()); + } + template + LogStream& operator<<(const T& value) + { + m_stream << value; + return *this; + } + LogStream& operator<<(std::ostream& (*manip)(std::ostream&)) // std::endl, std::flush... + { + m_stream << manip; + return *this; + } + +private: + Logger::Level m_level; + const char* m_file; + int m_line; + std::ostringstream m_stream; +}; + +#define BMC_LOG_DEBUG BMCBlockIoPlu::LogStream(BMCBlockIoPlu::Logger::Level::Debug, __FILE__, __LINE__) +#define BMC_LOG_INFO BMCBlockIoPlu::LogStream(BMCBlockIoPlu::Logger::Level::Info, __FILE__, __LINE__) +#define BMC_LOG_WARNING BMCBlockIoPlu::LogStream(BMCBlockIoPlu::Logger::Level::Warning, __FILE__, __LINE__) +#define BMC_LOG_ERROR BMCBlockIoPlu::LogStream(BMCBlockIoPlu::Logger::Level::Error, __FILE__, __LINE__) +#define BMC_LOG_CRITICAL BMCBlockIoPlu::LogStream(BMCBlockIoPlu::Logger::Level::Critical, __FILE__, __LINE__) +} +#endif \ No newline at end of file diff --git a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp new file mode 100644 index 0000000..9263a2d --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp @@ -0,0 +1,415 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#include "cbmcblockio.h" +#include +#include +#include +#include +#include +#include +extern "C" { +#include +} +#include "common.h" +#include "configure.h" +#include "logger.h" + +namespace BMCBlockIoPlu { + +const int BMC_ALARM_ID = 1002; +const int RESP_HEADER_SIZE = 7; +const int EVENT_SIZE = 15; +const uint32_t ALARM_OCCUR_CODE = 0x02000039; +const uint32_t ALARM_CLEAR_CODE = 0x0200003A; +const std::string BMC_TASK_NAME = "bmc_block_io"; +const std::string GET_BMCIP_CMD = "ipmitool lan print"; +const std::string IPMI_KEY_IP_ADDR = "IP Address"; +const std::string MSG_BMCIP_EMPTY = "ipmitool get bmc ip failed."; +const std::string MSG_BMC_QUERY_FAIL = "ipmitool query failed."; +const std::string MSG_EXIT_SUCCESS = "receive exit signal, task completed."; +const std::string JSON_KEY_MSG = "msg"; +const std::string JSON_KEY_ALARM_SOURCE = "alarm_source"; +const std::string JSON_KEY_DRIVER_NAME = "driver_name"; +const std::string JSON_KEY_IO_TYPE = "io_type"; +const std::string JSON_KEY_REASON = "reason"; +const std::string JSON_KEY_BLOCK_STACK = "block_stack"; +const std::string JSON_KEY_DETAILS = "details"; + +CBMCBlockIo::CBMCBlockIo() : + m_running(false), + m_patrolSeconds(BMCPLU_PATROL_DEFAULT), + m_userName(BMCPLU_DEFAULT_USERNAME), + m_passWd(BMCPLU_DEFAULT_PASSWD), + m_bmcIp("") +{ +} + +CBMCBlockIo::~CBMCBlockIo() +{ +} + +void CBMCBlockIo::Start() +{ + if (m_running) { + return; + } + + GetBMCIp(); + if (m_bmcIp.empty()) { + BMC_LOG_ERROR << "BMC Ip is empty."; + ReportResult(RESULT_LEVEL_FAIL, MSG_BMCIP_EMPTY); + return; + } + m_running = true; + m_worker = std::thread(&CBMCBlockIo::SentryWorker, this); + BMC_LOG_INFO << "BMC block io Start."; +} + +void CBMCBlockIo::Stop() +{ + { + std::lock_guard lock(m_mutex); + m_running = false; + } + m_cv.notify_all(); + + if (m_worker.joinable()) { + m_worker.join(); + } + BMC_LOG_INFO <<"BMC block io Stop."; +} + +void CBMCBlockIo::SetPatrolInterval(int seconds) +{ + m_patrolSeconds = seconds; +} + +void CBMCBlockIo::SetUserName(std::string userName) +{ + m_userName = userName; +} + +void CBMCBlockIo::SetPassWd(std::string passWd) +{ + m_passWd = passWd; +} + +bool CBMCBlockIo::IsRunning() +{ + return m_running; +} + +void CBMCBlockIo::SentryWorker() +{ + int ret = BMCPLU_SUCCESS; + while (m_running) { + std::unique_lock lock(m_mutex); + m_cv.wait_for(lock, std::chrono::seconds(m_patrolSeconds), [this] { + return !m_running; + }); + + if (!m_running) { + break; + } + ret = QueryEvents(); + if (ret != BMCPLU_SUCCESS) { + break; + } + } + + if (ret == BMCPLU_SUCCESS) { + ReportResult(RESULT_LEVEL_PASS, MSG_EXIT_SUCCESS); + } else { + ReportResult(RESULT_LEVEL_FAIL, MSG_BMC_QUERY_FAIL); + } + m_running = false; + BMC_LOG_INFO << "BMC block io SentryWorker exit."; + return; +} + +void CBMCBlockIo::GetBMCIp() +{ + std::vector result; + if (ExecCommand(GET_BMCIP_CMD, result)) { + return; + } + for (const auto& iter: result) { + if (iter.find(IPMI_KEY_IP_ADDR) != std::string::npos) { + size_t eq_pos = iter.find(':'); + if (eq_pos != std::string::npos) { + std::string key = Trim(iter.substr(0, eq_pos)); + std::string value = Trim(iter.substr(eq_pos + 1)); + if (key == IPMI_KEY_IP_ADDR) { + m_bmcIp = value; + return; + } + } + } + } + return; +} + +/***** ipml protocol *****/ +/* +请求 字节顺序 含义 + 1-3 厂商id 默认0xDB 0x07 0x0 + 4 子命令 默认0x40 + 5 请求类型 默认0x00 + 6-7 需要查询的事件起始编号,某些情况下查询到的事件可能有多条, + 单次响应无法全部返回,因此需要修改该值分页查询 + 8 事件严重级别 位图形式,bit0-normal,bit1-minor,bit2-major,bit3-critical,慢盘事件只支持normal + 9 主体类型 硬盘类型0x02 +响应 字节顺序 含义 + 1 completion code 调用成功时该字节不会显示在终端上 + 2-4 厂商ID,对应请求中内容 + 5-6 事件总数量 + 7 本次返回中包含的事件数量 + 8 占位字节,默认0 + 9-12 告警类型码,0x0200039为告警产生,0x0200003A为告警消除 + 13-16 事件发生的linux时间戳 + 17 事件严重级别,0-normal,1-minor,2-major,3-critical + 18 主体类型,对应请求中内容 + 19 设备序号 带外编号 + 20-23 占位字节,默认0 + N+1-N+15重复上面9-23中的内容,表示下一个事件 +厂商ID固定,其他所有多字节对象均为小端序, eg: +ipmitool -I lanplus -H x.x.x.x -U x -P x -C 17 raw 0x30 0x94 0xDB 0x07 0x00 0x40 0x00 0x00 0x00 0x01 0x02 +db 07 00 03 00 03 00 39 00 00 02 2f ab 91 68 00 02 04 00 00 00 00 +39 00 00 02 2e ab 91 68 00 02 02 00 00 00 00 39 00 00 02 2e ab 91 +68 00 02 01 00 00 00 00 + */ +int CBMCBlockIo::QueryEvents() +{ + uint16_t currentIndex = 0; + int ret = BMCPLU_FAILED; + + while (true) { + std::string cmd = BuildIPMICommand(currentIndex); + std::vector hexBytes = ExecuteIPMICommand(cmd); + if (hexBytes.empty()) { + break; + } + + ResponseHeader header = ParseResponseHeader(hexBytes); + if (!header.valid) { + break; + } + + size_t expectedSize = RESP_HEADER_SIZE + header.eventCount * EVENT_SIZE; + if (hexBytes.size() < expectedSize) { + BMC_LOG_ERROR << "Response size too small. Expected: " << expectedSize + << ", Actual: " << hexBytes.size(); + break; + } + + BMC_LOG_DEBUG << "Total events: " << header.totalEvents + << ", returned: " << static_cast(header.eventCount) + << ", current index: " << currentIndex; + if (header.eventCount == 0) { + ret = BMCPLU_SUCCESS; + break; + } + + ProcessEvents(hexBytes, header.eventCount); + currentIndex += header.eventCount; + + if (currentIndex >= header.totalEvents) { + ret = BMCPLU_SUCCESS; + break; + } + } + return ret; +} + +std::string CBMCBlockIo::BuildIPMICommand(uint16_t startIndex) +{ + uint8_t indexHigh = static_cast((startIndex >> 8) & 0xff); + uint8_t indexLow = static_cast(startIndex & 0xff); + std::ostringstream cmdStream; + cmdStream << "ipmitool -I lanplus -H " << m_bmcIp + << " -U " << m_userName + << " -P " << m_passWd + << " -C 17 raw 0x30 0x94 0xDB 0x07 0x00 0x40 0x00" + << " " << ByteToHex(indexLow) + << " " << ByteToHex(indexHigh) + << " 0x01 0x02"; + return cmdStream.str(); +} + +std::vector CBMCBlockIo::ExecuteIPMICommand(const std::string& cmd) +{ + BMC_LOG_DEBUG << "IPMI event query command: " << cmd; + + std::vector cmdOut; + if (ExecCommand(cmd, cmdOut)) { + BMC_LOG_ERROR << "IPMI command execute failed."; + return {}; + } + + std::ostringstream responseStream; + for (size_t i = 0; i < cmdOut.size(); ++i) { + std::string line = cmdOut[i]; + BMC_LOG_DEBUG << "Execute IPMI event response: " << line; + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); + line.erase(std::remove(line.begin(), line.end(), '\n'), line.end()); + if (i > 0 && !line.empty()) { + responseStream << ' '; + } + responseStream << line; + } + return SplitString(responseStream.str(), " "); +} + +ResponseHeader CBMCBlockIo::ParseResponseHeader(const std::vector& hexBytes) +{ + ResponseHeader header = {0, 0, false}; + + if (hexBytes.size() < RESP_HEADER_SIZE) { + BMC_LOG_ERROR << "Invalid response length: " << hexBytes.size(); + return header; + } + + if (hexBytes[0] != "db" || hexBytes[1] != "07" || hexBytes[2] != "00") { + BMC_LOG_ERROR << "Unexpected manufacturer ID: " + << hexBytes[0] << " " << hexBytes[1] << " " << hexBytes[2]; + return header; + } + + char* endPtr = nullptr; + unsigned long totalLow = std::strtoul(hexBytes[3].c_str(), &endPtr, 16); + if (endPtr == hexBytes[3].c_str() || *endPtr != '\0' || totalLow > 0xff) { + BMC_LOG_ERROR << "Invalid totalLow byte: " << hexBytes[3]; + return header; + } + + unsigned long totalHigh = std::strtoul(hexBytes[4].c_str(), &endPtr, 16); + if (endPtr == hexBytes[4].c_str() || *endPtr != '\0' || totalHigh > 0xff) { + BMC_LOG_ERROR << "Invalid totalHigh byte: " << hexBytes[4]; + return header; + } + + header.totalEvents = static_cast(totalLow) | (static_cast(totalHigh) << 8); + unsigned long count = std::strtoul(hexBytes[5].c_str(), &endPtr, 16); + if (endPtr == hexBytes[5].c_str() || *endPtr != '\0' || count > 0xff) { + BMC_LOG_ERROR << "Invalid event count byte: " << hexBytes[5]; + return header; + } + + header.eventCount = static_cast(count); + header.valid = true; + return header; +} + +IPMIEvent CBMCBlockIo::ParseSingleEvent(const std::vector& hexBytes, size_t startPos) +{ + IPMIEvent event = {0, 0, 0, 0, 0, false}; + char* endPtr = nullptr; + + for (int i = 0; i < 4; ++i) { + unsigned long byte = std::strtoul(hexBytes[startPos + i].c_str(), &endPtr, 16); + if (endPtr == hexBytes[startPos + i].c_str() || *endPtr != '\0' || byte > 0xff) { + BMC_LOG_ERROR << "Invalid alarm type byte at pos " << startPos + i + << ": " << hexBytes[startPos + i]; + return event; + } + event.alarmTypeCode |= (static_cast(byte) << (i * 8)); + } + + for (int i = 0; i < 4; ++i) { + unsigned long byte = std::strtoul(hexBytes[startPos + 4 + i].c_str(), &endPtr, 16); + if (endPtr == hexBytes[startPos + 4 + i].c_str() || *endPtr != '\0' || byte > 0xff) { + BMC_LOG_ERROR << "Invalid timestamp byte at pos " << startPos + 4 + i + << ": " << hexBytes[startPos + 4 + i]; + return event; + } + event.timestamp |= (static_cast(byte) << (i * 8)); + } + + unsigned long severity = std::strtoul(hexBytes[startPos + 8].c_str(), &endPtr, 16); + if (endPtr == hexBytes[startPos + 8].c_str() || *endPtr != '\0' || severity > 0xff) { + BMC_LOG_ERROR << "Invalid severity byte: " << hexBytes[startPos + 8]; + return event; + } + event.severity = static_cast(severity); + + unsigned long subjectType = std::strtoul(hexBytes[startPos + 9].c_str(), &endPtr, 16); + if (endPtr == hexBytes[startPos + 9].c_str() || *endPtr != '\0' || subjectType > 0xff) { + BMC_LOG_ERROR << "Invalid subject type byte: " << hexBytes[startPos + 9]; + return event; + } + event.subjectType = static_cast(subjectType); + + unsigned long deviceId = std::strtoul(hexBytes[startPos + 10].c_str(), &endPtr, 16); + if (endPtr == hexBytes[startPos + 10].c_str() || *endPtr != '\0' || deviceId > 0xff) { + BMC_LOG_ERROR << "Invalid device ID byte: " << hexBytes[startPos + 10]; + return event; + } + event.deviceId = static_cast(deviceId); + + event.valid = true; + return event; +} + +void CBMCBlockIo::ProcessEvents(const std::vector& hexBytes, uint8_t eventCount) +{ + for (int i = 0; i < eventCount; ++i) { + size_t startPos = RESP_HEADER_SIZE + i * EVENT_SIZE; + + IPMIEvent event = ParseSingleEvent(hexBytes, startPos); + if (!event.valid) { + continue; + } + + ReportAlarm(event); + } + return; +} + +void CBMCBlockIo::ReportAlarm(const IPMIEvent& event) +{ + uint8_t ucAlarmLevel = MINOR_ALM; + uint8_t ucAlarmType = 0; + if (event.alarmTypeCode == ALARM_OCCUR_CODE) { + ucAlarmType = ALARM_TYPE_OCCUR; + } else if (event.alarmTypeCode == ALARM_CLEAR_CODE) { + ucAlarmType = ALARM_TYPE_RECOVER; + } else { + BMC_LOG_ERROR << "Skipping unknown alarm type: 0x" + << std::hex << event.alarmTypeCode; + return; + } + json_object* jObject = json_object_new_object(); + json_object_object_add(jObject, JSON_KEY_ALARM_SOURCE.c_str(), json_object_new_string(BMC_TASK_NAME.c_str())); + json_object_object_add(jObject, JSON_KEY_DRIVER_NAME.c_str(), json_object_new_string(std::to_string(event.deviceId).c_str())); + //json_object_object_add(jObject, JSON_KEY_IO_TYPE.c_str(), json_object_new_string("null")); + //json_object_object_add(jObject, JSON_KEY_REASON.c_str(), json_object_new_string("null")); + //json_object_object_add(jObject, JSON_KEY_BLOCK_STACK.c_str(), json_object_new_string("null")); + //json_object_object_add(jObject, JSON_KEY_DETAILS.c_str(), json_object_new_string("null")); + const char *jData = json_object_to_json_string(jObject); + int ret = xalarm_Report(BMC_ALARM_ID, ucAlarmLevel, ucAlarmType, const_cast(jData)); + if (ret != RETURE_CODE_SUCCESS) { + BMC_LOG_ERROR << "Failed to xalarm_Report, ret: " << ret; + } + json_object_put(jObject); + return; +} + +void CBMCBlockIo::ReportResult(int resultLevel, const std::string& msg) +{ + RESULT_LEVEL level = static_cast(resultLevel); + json_object* jObject = json_object_new_object(); + json_object_object_add(jObject, JSON_KEY_MSG.c_str(), json_object_new_string(msg.c_str())); + const char *jData = json_object_to_json_string(jObject); + int ret = report_result(BMC_TASK_NAME.c_str(), level, const_cast(jData)); + if (ret != RETURE_CODE_SUCCESS) { + BMC_LOG_ERROR << "Failed to report_result, ret: " << ret; + } + json_object_put(jObject); + return; +} +}; diff --git a/src/sentryPlugins/bmc_block_io/src/common.cpp b/src/sentryPlugins/bmc_block_io/src/common.cpp new file mode 100644 index 0000000..d603d7a --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/src/common.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace BMCBlockIoPlu { + +std::string Trim(const std::string& str) +{ + size_t first = str.find_first_not_of(" \t\n\r\v\f"); + if (std::string::npos == first) { + return ""; + } + size_t last = str.find_last_not_of(" \t\n\r\v\f"); + return str.substr(first, (last - first + 1)); +} + +bool IsValidNumber(const std::string& str, int& num) +{ + if (str.empty()) { + return false; + } + for (const auto& iter : str) { + if (!std::isdigit(iter)) { + return false; + } + } + std::istringstream iss(str); + if (!(iss >> num)) { + return false; + } + return true; +} + +int ParseConfig(const std::string& path, PluConfig& config) +{ + std::ifstream file(path); + if (!file.is_open()) { + BMC_LOG_ERROR << "Failed to open config file: " << path; + return BMCPLU_FAILED; + } + + std::unordered_map configMap; + configMap["log_level"] = {true, false, [&](const std::string& value) { + if (value == "debug") { + config.logLevel = Logger::Level::Debug; + } else if (value == "info") { + config.logLevel = Logger::Level::Info; + } else if (value == "warning") { + config.logLevel = Logger::Level::Warning; + } else if (value == "error") { + config.logLevel = Logger::Level::Error; + } else if (value == "critical") { + config.logLevel = Logger::Level::Critical; + } else { + BMC_LOG_ERROR << "Invalid log_level value."; + return false; + } + return true; + }}; + + configMap["patrol_second"] = {true, false, [&](const std::string& value) { + int num = 0; + if (!IsValidNumber(value, num) || !(num >= BMCPLU_PATROL_MIN && num <= BMCPLU_PATROL_MAX)) { + BMC_LOG_ERROR << "Invalid patrol_second value."; + return false; + } + config.patrolSeconds = num; + return true; + }}; + + configMap["bmc_username"] = {true, false, [&](const std::string& value) { + config.userName = value; + return true; + }}; + + configMap["bmc_passwd"] = {true, false, [&](const std::string& value) { + config.passWd = value; + return true; + }}; + + std::string line; + while (std::getline(file, line)) { + line = Trim(line); + if (line.empty() || line[0] == '#') { + continue; + } + + size_t eqPos = line.find('='); + if (eqPos == std::string::npos || eqPos == 0) { + BMC_LOG_ERROR << "Config file format invalid."; + return BMCPLU_FAILED; + } + + std::string key = Trim(line.substr(0, eqPos)); + std::string value = Trim(line.substr(eqPos + 1)); + if (value.empty()) { + BMC_LOG_ERROR << "Config key: " << key << " cannot empty."; + return BMCPLU_FAILED; + } + + auto iter = configMap.find(key); + if (iter == configMap.end()) { + BMC_LOG_ERROR << "Config error, unknown key : " << key; + return BMCPLU_FAILED; + } + + if (!iter->second.processor(value)) { + return BMCPLU_FAILED; + } + iter->second.found = true; + } + + for (const auto& iter : configMap) { + if (iter.second.required && !iter.second.found) { + BMC_LOG_ERROR << "Config error, missing required key : " << iter.first; + return BMCPLU_FAILED; + } + } + return BMCPLU_SUCCESS; +} + +std::string ExtractFileName(const std::string& path) +{ + size_t lastSlashPos = path.find_last_of('/'); + if (lastSlashPos == std::string::npos) { + return path; + } else { + return path.substr(lastSlashPos + 1); + } +} + +int ExecCommand(const std::string cmd, std::vector& result) +{ + FILE* pipe = popen(cmd.c_str(), "r"); + if (!pipe) { + BMC_LOG_ERROR << "Cmd: " << cmd << ", popen failed."; + return BMCPLU_FAILED; + } + + char buffer[512]; + result.clear(); + while (fgets(buffer, sizeof(buffer), pipe)) { + result.push_back(buffer); + } + + int status = pclose(pipe); + if (status == -1) { + BMC_LOG_ERROR << "Cmd: " << cmd << ", pclose failed."; + return BMCPLU_FAILED; + } else { + int exitCode = WEXITSTATUS(status); + if (exitCode != 0) { + BMC_LOG_ERROR << "Cmd: " << cmd << ", exit failed, err code: " << exitCode; + return BMCPLU_FAILED; + } + } + return BMCPLU_SUCCESS; +} + +std::string ByteToHex(uint8_t byte) +{ + std::ostringstream oss; + const int hexLen = 2; + oss << std::hex << std::setfill('0') << std::setw(hexLen) << static_cast(byte); + return "0x" + oss.str(); +} + +std::vector SplitString(const std::string& str, const std::string& split) +{ + std::vector result; + if (split.empty()) { + result.push_back(str); + return result; + } + + size_t pos = 0; + while (true) { + size_t split_pos = str.find(split, pos); + if (split_pos != std::string::npos) { + result.push_back(str.substr(pos, split_pos - pos)); + pos = split_pos + split.size(); + } else { + result.push_back(str.substr(pos)); + break; + } + } + return result; +} +} diff --git a/src/sentryPlugins/bmc_block_io/src/logger.cpp b/src/sentryPlugins/bmc_block_io/src/logger.cpp new file mode 100644 index 0000000..f0c84b1 --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/src/logger.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#include "logger.h" +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +namespace BMCBlockIoPlu { + +Logger& Logger::GetInstance() +{ + static Logger instance; + return instance; +} + +bool Logger::Initialize(const std::string& logPath, Level level) +{ + m_logPath = logPath; + m_level = level; + OpenLogFile(); + return m_fileOpen; +} + +void Logger::SetLevel(Level level) +{ + m_level = level; +} + +Logger::Level Logger::GetLevel() const +{ + return m_level; +} + +void Logger::OpenLogFile() +{ + m_logFile.open(m_logPath, std::ios::out | std::ios::app); + if (!m_logFile.is_open()) { + std::cerr << "Failed to open log file: " << m_logPath + << ", error: " << strerror(errno) << std::endl; + m_fileOpen = false; + return; + } + + struct stat fileStat; + if (stat(m_logPath.c_str(), &fileStat) == 0) { + m_inode = fileStat.st_ino; + m_device = fileStat.st_dev; + m_fileSize = fileStat.st_size; + } + m_checkTime = std::time(nullptr); + + m_fileOpen = true; + return; +} + +void Logger::CheckFileState() +{ + const int timeInterval = 30; // second + std::time_t timeNow = std::time(nullptr); + if (timeNow - m_checkTime < timeInterval) { + return; + } + + struct stat fileStat; + if (stat(m_logPath.c_str(), &fileStat) != 0) { + if (errno == ENOENT) { // file deleted + std::lock_guard lock(m_writeMutex); + ReopenLogFile(); + } + std::cerr << "Failed to get file state: " << m_logPath + << ", error: " << strerror(errno) << std::endl; + return; + } + + bool needReopen = false; + if (fileStat.st_ino != m_inode) { + needReopen = true; + } else if (fileStat.st_dev != m_device) { + needReopen = true; + } else if (fileStat.st_size < m_fileSize) { + needReopen = true; + } + + if (needReopen) { + ReopenLogFile(); + } else { + m_fileSize = fileStat.st_size; + } + + m_checkTime = timeNow; +} + +void Logger::ReopenLogFile() +{ + if (m_logFile.is_open()) { + m_logFile.close(); + } + OpenLogFile(); + return; +} + +void Logger::WriteLog(Level level, const char* file, int line, const std::string& message) +{ + if (level < GetLevel() || message.empty()) { + return; + } + + CheckFileState(); + std::lock_guard lock(m_writeMutex); + if (m_fileOpen && m_logFile.good()) { + m_logFile << Format(level, file, line, message) << std::endl; + m_logFile.flush(); + } else { + std::cerr << Format(level, file, line, message) << std::endl; + } +} + +std::string Logger::LevelToString(Level level) const +{ + switch (level) { + case Level::Debug: return std::string("DEBUG"); + case Level::Info: return std::string("INFO"); + case Level::Warning: return std::string("WARNING"); + case Level::Error: return std::string("ERROR"); + case Level::Critical: return std::string("CRITICAL"); + default: return std::string("UNKNOWN"); + } + return std::string("UNKNOWN"); +} + +std::string Logger::GetTimeStamp() const +{ + auto now = std::chrono::system_clock::now(); + auto nowTimer = std::chrono::system_clock::to_time_t(now); + auto milliseconds = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + + struct tm nowTm; + localtime_r(&nowTimer, &nowTm); + + std::ostringstream oss; + const int millisecLen = 3; + oss << std::put_time(&nowTm, "%Y-%m-%d %H:%M:%S"); + oss << '.' << std::setfill('0') << std::setw(millisecLen) << milliseconds.count(); + + return oss.str(); +} + +std::string Logger::Format(Level level, const char* file, int line, const std::string & message) const +{ + std::ostringstream oss; + oss << GetTimeStamp() << " - " << LevelToString(level) << " - [" + << ExtractFileName(file) << ":" << line << "]" << " - " << message; + return oss.str(); +} +} diff --git a/src/sentryPlugins/bmc_block_io/src/main.cpp b/src/sentryPlugins/bmc_block_io/src/main.cpp new file mode 100644 index 0000000..8aeb3d0 --- /dev/null +++ b/src/sentryPlugins/bmc_block_io/src/main.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * bmc_block_io is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * Author: hewanhan@h-partners.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cbmcblockio.h" +#include "configure.h" +#include "logger.h" +#include "common.h" + +std::atomic g_exit(false); + +void HandleSignal(int sig) +{ + if (sig == SIGTERM || sig == SIGINT) { + g_exit = true; + BMC_LOG_INFO << "Receive signal SIGTERM or SIGINT, exit."; + } + return; +} + +void SetSignalHandler() +{ + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGTERM); // block SIGTERM + sigaddset(&sa.sa_mask, SIGINT); // block SIGINT + sa.sa_handler = HandleSignal; + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGTERM, &sa, nullptr) == -1) { + BMC_LOG_ERROR << "Failed to setup signal with SIGTERM:" << strerror(errno); + } + + if (sigaction(SIGINT, &sa, nullptr) == -1) { + BMC_LOG_ERROR << "Failed to setup signal with SIGINT:" << strerror(errno); + } +} + +int main(int argc, char* argv[]) +{ + if (!BMCBlockIoPlu::Logger::GetInstance().Initialize(BMCBlockIoPlu::BMCPLU_LOG_PATH)) { + std::cerr << "Failed to initialize logger." << std::endl; + } + SetSignalHandler(); + + BMCBlockIoPlu::CBMCBlockIo blockIo; + PluConfig config; + if (BMCBlockIoPlu::ParseConfig(BMCBlockIoPlu::BMCPLU_CONFIG_PATH, config)) { + BMC_LOG_ERROR << "Parse config failed, use default configuration."; + } else { + BMCBlockIoPlu::Logger::GetInstance().SetLevel(config.logLevel); + blockIo.SetPatrolInterval(config.patrolSeconds); + blockIo.SetUserName(config.userName); + blockIo.SetPassWd(config.passWd); + } + + std::thread configMonitor([&] { + time_t lastModTime = 0; + struct stat st; + if (stat(BMCBlockIoPlu::BMCPLU_CONFIG_PATH.c_str(), &st) == 0) { + lastModTime = st.st_mtime; + } + + while (!g_exit) { + std::this_thread::sleep_for(std::chrono::seconds(BMCBlockIoPlu::BMCPLU_CONFIG_CHECK_CYCLE)); + if (g_exit) { + break; + } + + struct stat st_; + if (stat(BMCBlockIoPlu::BMCPLU_CONFIG_PATH.c_str(), &st_) != 0) { + continue; + } + if (st_.st_mtime != lastModTime) { + lastModTime = st_.st_mtime; + PluConfig newConfig; + if (BMCBlockIoPlu::ParseConfig(BMCBlockIoPlu::BMCPLU_CONFIG_PATH, newConfig) == BMCPLU_SUCCESS) { + if (newConfig.logLevel != config.logLevel) { + config.logLevel = newConfig.logLevel; + BMC_LOG_INFO << "Log level update to " + << BMCBlockIoPlu::Logger::GetInstance().LevelToString(config.logLevel); + BMCBlockIoPlu::Logger::GetInstance().SetLevel(config.logLevel); + } + if (newConfig.patrolSeconds != config.patrolSeconds) { + config.patrolSeconds = newConfig.patrolSeconds; + BMC_LOG_INFO << "Patrol interval update to " << config.patrolSeconds; + blockIo.SetPatrolInterval(config.patrolSeconds); + } + if (newConfig.userName != config.userName) { + config.userName = newConfig.userName; + BMC_LOG_INFO << "BMC userName update to " << config.userName; + blockIo.SetUserName(config.userName); + } + if (newConfig.passWd != config.passWd) { + config.passWd = newConfig.passWd; + BMC_LOG_INFO << "BMC passWd update"; + blockIo.SetPassWd(config.passWd); + } + } + } + } + }); + blockIo.Start(); + while (!g_exit) { + std::this_thread::sleep_for(std::chrono::seconds(BMCBlockIoPlu::BMCPLU_DEFAULT_SLEEP_CYCLE)); + if (!blockIo.IsRunning()) { + g_exit = true; + break; + } + } + blockIo.Stop(); + if (configMonitor.joinable()) { + configMonitor.join(); + } + return 0; +} -- Gitee From 9e431c144e684d8583c246d26ba0703555bd7b12 Mon Sep 17 00:00:00 2001 From: hewanhan Date: Mon, 1 Sep 2025 10:12:27 +0800 Subject: [PATCH 02/16] add test . --- Makefile | 2 +- src/sentryPlugins/bmc_block_io/CMakeLists.txt | 4 ++++ src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4b99d8c..bd3bcb9 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ hbm_online_repair: sentry_msg_monitor: lib cd $(CURSRCDIR)/sentryPlugins/sentry_msg_monitor/ && make -bmc_block_io: +bmc_block_io: lib cd $(CURSRCDIR)/sentryPlugins/bmc_block_io/ && sh build.sh install: all dirs isentry diff --git a/src/sentryPlugins/bmc_block_io/CMakeLists.txt b/src/sentryPlugins/bmc_block_io/CMakeLists.txt index 818a0a8..2234dee 100644 --- a/src/sentryPlugins/bmc_block_io/CMakeLists.txt +++ b/src/sentryPlugins/bmc_block_io/CMakeLists.txt @@ -8,6 +8,10 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/output) include_directories( ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/../../libs/libxalarm +) +link_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/build/libxalarm ) set(SOURCE src/main.cpp diff --git a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp index 9263a2d..cb52364 100644 --- a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp +++ b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp @@ -13,7 +13,7 @@ #include #include extern "C" { -#include +#include "register_xalarm.h" } #include "common.h" #include "configure.h" -- Gitee From 289c3ce41a0b6b613073089451a885fa88a1f781 Mon Sep 17 00:00:00 2001 From: hewh Date: Mon, 8 Sep 2025 20:51:36 +0800 Subject: [PATCH 03/16] add test . --- src/sentryPlugins/bmc_block_io/include/common.h | 2 +- src/sentryPlugins/bmc_block_io/src/common.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentryPlugins/bmc_block_io/include/common.h b/src/sentryPlugins/bmc_block_io/include/common.h index 2bd0980..9304dee 100644 --- a/src/sentryPlugins/bmc_block_io/include/common.h +++ b/src/sentryPlugins/bmc_block_io/include/common.h @@ -37,7 +37,7 @@ std::string Trim(const std::string& str); bool IsValidNumber(const std::string& str, int& num); int ParseConfig(const std::string& path, PluConfig& config); std::string ExtractFileName(const std::string& path); -int ExecCommand(const std::string cmd, std::vector& result); +int ExecCommand(const std::string& cmd, std::vector& result); std::string ByteToHex(uint8_t byte); std::vector SplitString(const std::string& str, const std::string& split); } diff --git a/src/sentryPlugins/bmc_block_io/src/common.cpp b/src/sentryPlugins/bmc_block_io/src/common.cpp index d603d7a..f03db17 100644 --- a/src/sentryPlugins/bmc_block_io/src/common.cpp +++ b/src/sentryPlugins/bmc_block_io/src/common.cpp @@ -142,7 +142,7 @@ std::string ExtractFileName(const std::string& path) } } -int ExecCommand(const std::string cmd, std::vector& result) +int ExecCommand(const std::string& cmd, std::vector& result) { FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) { -- Gitee From da61e94d136e85653bbcebb8532ed0dd6f6eb0a7 Mon Sep 17 00:00:00 2001 From: hewh Date: Wed, 10 Sep 2025 18:13:43 +0800 Subject: [PATCH 04/16] add test . --- .../avg_block_io/avg_block_io.py | 4 ++- .../avg_block_io/extra_logger.py | 30 +++++++++++++++++++ src/sentryPlugins/avg_block_io/utils.py | 2 ++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/sentryPlugins/avg_block_io/extra_logger.py diff --git a/src/sentryPlugins/avg_block_io/avg_block_io.py b/src/sentryPlugins/avg_block_io/avg_block_io.py index 899d517..5e6b603 100644 --- a/src/sentryPlugins/avg_block_io/avg_block_io.py +++ b/src/sentryPlugins/avg_block_io/avg_block_io.py @@ -17,9 +17,10 @@ from .config import read_config_log, read_config_common, read_config_algorithm, from .stage_window import IoWindow, IoDumpWindow from .module_conn import avg_is_iocollect_valid, avg_get_io_data, report_alarm_fail, process_report_data, sig_handler, get_disk_type_by_name, check_disk_list_validation from .utils import update_avg_and_check_abnormal +from .extra_logger import init_extra_logger CONFIG_FILE = "/etc/sysSentry/plugins/avg_block_io.ini" - +AVG_EXTRA_LOG_PATH = "/var/log/sysSentry/avg_extra.log" def init_io_win(io_dic, config, common_param): """initialize windows of latency, iodump, and dict of avg_value""" @@ -152,6 +153,7 @@ def main(): log_level = read_config_log(CONFIG_FILE) log_format = "%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s" logging.basicConfig(level=log_level, format=log_format) + init_extra_logger(AVG_EXTRA_LOG_PATH, log_level, log_format) # 初始化配置读取 config = configparser.ConfigParser(comment_prefixes=('#', ';')) diff --git a/src/sentryPlugins/avg_block_io/extra_logger.py b/src/sentryPlugins/avg_block_io/extra_logger.py new file mode 100644 index 0000000..83902d1 --- /dev/null +++ b/src/sentryPlugins/avg_block_io/extra_logger.py @@ -0,0 +1,30 @@ +import logging +import os + +extra_logger = None + +def init_extra_logger(log_path, log_level, log_format): + global extra_logger + try: + if not os.path.exists(log_path): + fd = os.open(log_path, os.O_CREAT | os.O_WRONLY, 0o600) + os.close(fd) + logger_name = f"extra_logger_{log_path}" + logger = logging.getLogger(logger_name) + logger.propagate = False + logger.setLevel(log_level) + + file_handler = logging.FileHandler(log_path) + file_handler.setLevel(log_level) + + formatter = logging.Formatter(log_format) + file_handler.setFormatter(formatter) + + logger.addHandler(file_handler) + extra_logger = logger + except Exception as e: + logging.error(f"Failed to create extra logger for {log_path}: {e}") + extra_logger = logging.getLogger() # Fallback to default logger + +def extra_log_slow(msg): + extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {msg['io_type']}, type: {msg['alarm_type']}") diff --git a/src/sentryPlugins/avg_block_io/utils.py b/src/sentryPlugins/avg_block_io/utils.py index d5f8bb4..c7c9985 100644 --- a/src/sentryPlugins/avg_block_io/utils.py +++ b/src/sentryPlugins/avg_block_io/utils.py @@ -9,6 +9,7 @@ # PURPOSE. # See the Mulan PSL v2 for more details. import logging +from .logger_setup import extra_log_slow AVG_VALUE = 0 AVG_COUNT = 1 @@ -109,6 +110,7 @@ def log_slow_win(msg, reason): """record log of slow win""" logging.warning(f"[SLOW IO] disk: {msg['driver_name']}, stage: {msg['block_stack']}, " f"iotype: {msg['io_type']}, type: {msg['alarm_type']}, reason: {reason}") + extra_log_slow(msg) logging.info(f"latency: {msg['details']['latency']}") logging.info(f"iodump: {msg['details']['iodump']}") -- Gitee From 21988a8ad84717fe5f6a2fa7093c1d63aeba6e35 Mon Sep 17 00:00:00 2001 From: hewh Date: Wed, 10 Sep 2025 18:18:26 +0800 Subject: [PATCH 05/16] add test . --- src/sentryPlugins/avg_block_io/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentryPlugins/avg_block_io/utils.py b/src/sentryPlugins/avg_block_io/utils.py index c7c9985..74e5bb4 100644 --- a/src/sentryPlugins/avg_block_io/utils.py +++ b/src/sentryPlugins/avg_block_io/utils.py @@ -9,7 +9,7 @@ # PURPOSE. # See the Mulan PSL v2 for more details. import logging -from .logger_setup import extra_log_slow +from .extra_logger import extra_log_slow AVG_VALUE = 0 AVG_COUNT = 1 -- Gitee From 28cd344339757ff98ceb1527f39d464c45dc8fed Mon Sep 17 00:00:00 2001 From: hewh Date: Fri, 12 Sep 2025 09:31:08 +0800 Subject: [PATCH 06/16] add test . --- .../avg_block_io/avg_block_io.py | 3 +- .../avg_block_io/extra_logger.py | 97 ++++++++++++++++++- src/sentryPlugins/avg_block_io/utils.py | 5 +- 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/src/sentryPlugins/avg_block_io/avg_block_io.py b/src/sentryPlugins/avg_block_io/avg_block_io.py index 5e6b603..9f6af99 100644 --- a/src/sentryPlugins/avg_block_io/avg_block_io.py +++ b/src/sentryPlugins/avg_block_io/avg_block_io.py @@ -20,7 +20,8 @@ from .utils import update_avg_and_check_abnormal from .extra_logger import init_extra_logger CONFIG_FILE = "/etc/sysSentry/plugins/avg_block_io.ini" -AVG_EXTRA_LOG_PATH = "/var/log/sysSentry/avg_extra.log" +AVG_EXTRA_LOG_PATH = "/var/log/sysSentry/avg_block_io_extra.log" + def init_io_win(io_dic, config, common_param): """initialize windows of latency, iodump, and dict of avg_value""" diff --git a/src/sentryPlugins/avg_block_io/extra_logger.py b/src/sentryPlugins/avg_block_io/extra_logger.py index 83902d1..efcd5d8 100644 --- a/src/sentryPlugins/avg_block_io/extra_logger.py +++ b/src/sentryPlugins/avg_block_io/extra_logger.py @@ -1,8 +1,20 @@ +# coding: utf-8 +# Copyright (c) 2025 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. import logging import os +import re extra_logger = None + def init_extra_logger(log_path, log_level, log_format): global extra_logger try: @@ -26,5 +38,88 @@ def init_extra_logger(log_path, log_level, log_format): logging.error(f"Failed to create extra logger for {log_path}: {e}") extra_logger = logging.getLogger() # Fallback to default logger -def extra_log_slow(msg): + +def extra_latency_log(msg): extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {msg['io_type']}, type: {msg['alarm_type']}") + + # Parse the latency string from msg + latency_str = msg['details']['latency'] + pattern = r'(\w+):\s*\[([\d,]+)\]' + matches = re.findall(pattern, latency_str) + latency_data = {} + for match in matches: + key = match[0] + values = list(map(int, match[1].split(','))) + latency_data[key] = values + + # Define stage groups + groups = { + 'B->Q': ['throtl', 'wbt', 'iocost'], + 'Q->G': ['gettag', 'requeue'], + 'G->I': ['plug'], + 'I->D': ['deadline', 'bfq', 'hctx'], + 'D->C': ['rq_driver'] + } + + # Calculate statistics for each group + group_stats = {} + for group_name, stages in groups.items(): + all_values = [] + for stage in stages: + if stage in latency_data: + all_values.extend(latency_data[stage]) + if all_values: + min_val = min(all_values) + max_val = max(all_values) + avg_val = sum(all_values) / len(all_values) + else: + min_val = 0 + max_val = 0 + avg_val = 0 + # Convert to ms + min_val_ms = min_val / 1000.0 + max_val_ms = max_val / 1000.0 + avg_val_ms = avg_val / 1000.0 + group_stats[group_name] = { + 'min': min_val_ms, + 'max': max_val_ms, + 'avg': avg_val_ms + } + + # Calculate total latency (B->C) + total_avg = 0 + total_min = 0 + total_max = 0 + for group_name in groups: + total_avg += group_stats[group_name]['avg'] + total_min += group_stats[group_name]['min'] + total_max += group_stats[group_name]['max'] + group_stats['B->C'] = { + 'min': total_min, + 'max': total_max, + 'avg': total_avg + } + + # Calculate PCT for each group (except B->C) + for group_name in groups: + if total_avg > 0: + pct = (group_stats[group_name]['avg'] / total_avg) * 100 + else: + pct = 0 + group_stats[group_name]['pct'] = pct + group_stats['B->C']['pct'] = 100.0 + + # Output table + stage_order = ['B->Q', 'Q->G', 'G->I', 'I->D', 'D->C', 'B->C'] + # Format header + header = "STAGE MIN(ms) MAX(ms) AVG(ms) PCT" + extra_logger.warning(header) + for stage in stage_order: + s = group_stats[stage] + min_str = f"{s['min']:.3f}" + max_str = f"{s['max']:.3f}" + avg_str = f"{s['avg']:.3f}" + pct_str = f"{s['pct']:.2f}%" + # Format each line with aligned columns + line = f"{stage} {min_str:>7} {max_str:>7} {avg_str:>7} {pct_str:>6}" + extra_logger.warning(line) diff --git a/src/sentryPlugins/avg_block_io/utils.py b/src/sentryPlugins/avg_block_io/utils.py index 74e5bb4..0337cdb 100644 --- a/src/sentryPlugins/avg_block_io/utils.py +++ b/src/sentryPlugins/avg_block_io/utils.py @@ -9,7 +9,7 @@ # PURPOSE. # See the Mulan PSL v2 for more details. import logging -from .extra_logger import extra_log_slow +from .extra_logger import extra_latency_log AVG_VALUE = 0 AVG_COUNT = 1 @@ -110,7 +110,8 @@ def log_slow_win(msg, reason): """record log of slow win""" logging.warning(f"[SLOW IO] disk: {msg['driver_name']}, stage: {msg['block_stack']}, " f"iotype: {msg['io_type']}, type: {msg['alarm_type']}, reason: {reason}") - extra_log_slow(msg) + if "latency" in str(msg.get('alarm_type', '')): + extra_latency_log(msg) logging.info(f"latency: {msg['details']['latency']}") logging.info(f"iodump: {msg['details']['iodump']}") -- Gitee From 501a21977165a7e41b4492f3b096dded4670c6b8 Mon Sep 17 00:00:00 2001 From: hewh Date: Fri, 12 Sep 2025 11:06:35 +0800 Subject: [PATCH 07/16] add test . --- .../avg_block_io/extra_logger.py | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/sentryPlugins/avg_block_io/extra_logger.py b/src/sentryPlugins/avg_block_io/extra_logger.py index efcd5d8..7a34bab 100644 --- a/src/sentryPlugins/avg_block_io/extra_logger.py +++ b/src/sentryPlugins/avg_block_io/extra_logger.py @@ -44,12 +44,12 @@ def extra_latency_log(msg): # Parse the latency string from msg latency_str = msg['details']['latency'] - pattern = r'(\w+):\s*\[([\d,]+)\]' + pattern = r'(\w+):\s*\[([0-9.,]+)\]' matches = re.findall(pattern, latency_str) latency_data = {} for match in matches: key = match[0] - values = list(map(int, match[1].split(','))) + values = list(map(float, match[1].split(','))) latency_data[key] = values # Define stage groups @@ -111,15 +111,28 @@ def extra_latency_log(msg): # Output table stage_order = ['B->Q', 'Q->G', 'G->I', 'I->D', 'D->C', 'B->C'] - # Format header - header = "STAGE MIN(ms) MAX(ms) AVG(ms) PCT" + STAGE_WIDTH = 7 + NUM_WIDTH = 12 + PCT_WIDTH = 8 + + header = f"{'Stage':<{STAGE_WIDTH}} {'Min(ms)':>{NUM_WIDTH}} {'Max(ms)':>{NUM_WIDTH}} {'Avg(ms)':>{NUM_WIDTH}} {'PCT':>{PCT_WIDTH}}" extra_logger.warning(header) + for stage in stage_order: - s = group_stats[stage] - min_str = f"{s['min']:.3f}" - max_str = f"{s['max']:.3f}" - avg_str = f"{s['avg']:.3f}" - pct_str = f"{s['pct']:.2f}%" - # Format each line with aligned columns - line = f"{stage} {min_str:>7} {max_str:>7} {avg_str:>7} {pct_str:>6}" - extra_logger.warning(line) + try: + s = group_stats[stage] + min_str = f"{s['min']:.3f}" + max_str = f"{s['max']:.3f}" + avg_str = f"{s['avg']:.3f}" + pct_str = f"{s['pct']:.2f}%" + + line = ( + f"{stage:<{STAGE_WIDTH}} " + f"{min_str:>{NUM_WIDTH}} " + f"{max_str:>{NUM_WIDTH}} " + f"{avg_str:>{NUM_WIDTH}} " + f"{pct_str:>{PCT_WIDTH}}" + ) + extra_logger.warning(line) + except KeyError: + return -- Gitee From b2e43076aade53e5e3bb48be30bd7e7443ba835a Mon Sep 17 00:00:00 2001 From: hewh Date: Fri, 12 Sep 2025 11:37:50 +0800 Subject: [PATCH 08/16] add test . --- .../avg_block_io/extra_logger.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/sentryPlugins/avg_block_io/extra_logger.py b/src/sentryPlugins/avg_block_io/extra_logger.py index 7a34bab..c2bf63f 100644 --- a/src/sentryPlugins/avg_block_io/extra_logger.py +++ b/src/sentryPlugins/avg_block_io/extra_logger.py @@ -111,12 +111,17 @@ def extra_latency_log(msg): # Output table stage_order = ['B->Q', 'Q->G', 'G->I', 'I->D', 'D->C', 'B->C'] - STAGE_WIDTH = 7 - NUM_WIDTH = 12 - PCT_WIDTH = 8 - - header = f"{'Stage':<{STAGE_WIDTH}} {'Min(ms)':>{NUM_WIDTH}} {'Max(ms)':>{NUM_WIDTH}} {'Avg(ms)':>{NUM_WIDTH}} {'PCT':>{PCT_WIDTH}}" - extra_logger.warning(header) + stage_width = 7 + num_width = 12 + pct_width = 8 + + extra_logger.warning( + f"{'Stage':<{stage_width}} " + f"{'Min(ms)':>{num_width}} " + f"{'Max(ms)':>{num_width}} " + f"{'Avg(ms)':>{num_width}} " + f"{'PCT':>{pct_width}}" + ) for stage in stage_order: try: @@ -126,13 +131,12 @@ def extra_latency_log(msg): avg_str = f"{s['avg']:.3f}" pct_str = f"{s['pct']:.2f}%" - line = ( - f"{stage:<{STAGE_WIDTH}} " - f"{min_str:>{NUM_WIDTH}} " - f"{max_str:>{NUM_WIDTH}} " - f"{avg_str:>{NUM_WIDTH}} " - f"{pct_str:>{PCT_WIDTH}}" + extra_logger.warning( + f"{stage:<{stage_width}} " + f"{s['min']:.3f:>{num_width}} " + f"{s['max']:.3f:>{num_width}} " + f"{s['avg']:.3f:>{num_width}} " + f"{s['pct']:.2f}%:>{pct_width}" ) - extra_logger.warning(line) except KeyError: return -- Gitee From 24d486a53e737380e502e47b61227e8aa5128927 Mon Sep 17 00:00:00 2001 From: hewh Date: Mon, 15 Sep 2025 11:30:52 +0800 Subject: [PATCH 09/16] add test . --- .../pySentryCollector/collect_plugin.py | 4 +- src/sentryPlugins/ai_block_io/ai_block_io.py | 4 +- .../ai_block_io/config_parser.py | 3 + src/sentryPlugins/ai_block_io/extra_logger.py | 151 ++++++++++++++++++ .../ai_block_io/sliding_window.py | 7 +- .../avg_block_io/extra_logger.py | 22 ++- src/sentryPlugins/avg_block_io/utils.py | 5 +- .../bmc_block_io/src/cbmcblockio.cpp | 14 +- 8 files changed, 187 insertions(+), 23 deletions(-) create mode 100644 src/sentryPlugins/ai_block_io/extra_logger.py diff --git a/src/libsentry/python/pySentryCollector/collect_plugin.py b/src/libsentry/python/pySentryCollector/collect_plugin.py index 9495d8b..3395f89 100644 --- a/src/libsentry/python/pySentryCollector/collect_plugin.py +++ b/src/libsentry/python/pySentryCollector/collect_plugin.py @@ -326,9 +326,9 @@ def get_disk_type(disk): try: with open(disk_file, 'r') as file: num = int(file.read()) - if num == 1: + if num == 0: result['message'] = str(DiskType.TYPE_SATA_SSD) - elif num == 0: + elif num == 1: result['message'] = str(DiskType.TYPE_SATA_HDD) else: logging.error("disk %s is not support, num = %d", disk, num) diff --git a/src/sentryPlugins/ai_block_io/ai_block_io.py b/src/sentryPlugins/ai_block_io/ai_block_io.py index abf264d..0905c0d 100644 --- a/src/sentryPlugins/ai_block_io/ai_block_io.py +++ b/src/sentryPlugins/ai_block_io/ai_block_io.py @@ -27,6 +27,7 @@ from .data_access import ( ) from .io_data import MetricName from .alarm_report import Xalarm, Report +from .extra_logger import extra_slow_log CONFIG_FILE = "/etc/sysSentry/plugins/ai_block_io.ini" @@ -209,12 +210,13 @@ class SlowIODetection: del tmp_alarm_content["details"] logging.warning("[SLOW IO] " + str(tmp_alarm_content)) logging.warning(f'[SLOW IO] disk: {str(tmp_alarm_content.get("driver_name"))}, ' - f'stage: {str(tmp_alarm_content.get("driver_name"))}, ' + f'stage: {str(tmp_alarm_content.get("block_stack"))}, ' f'iotype: {str(tmp_alarm_content.get("io_type"))}, ' f'type: {str(tmp_alarm_content.get("alarm_type"))}, ' f'reason: {str(tmp_alarm_content.get("reason"))}') logging.warning(f"latency: " + str(alarm_content.get("details").get("latency"))) logging.warning(f"iodump: " + str(alarm_content.get("details").get("iodump"))) + extra_slow_log(alarm_content) # Step4:等待检测时间 logging.debug("step4. Wait to start next slow io event detection loop.") diff --git a/src/sentryPlugins/ai_block_io/config_parser.py b/src/sentryPlugins/ai_block_io/config_parser.py index 612fe9f..a918c8b 100644 --- a/src/sentryPlugins/ai_block_io/config_parser.py +++ b/src/sentryPlugins/ai_block_io/config_parser.py @@ -17,9 +17,11 @@ from .alarm_report import Report from .threshold import ThresholdType from .utils import get_threshold_type_enum, get_sliding_window_type_enum, get_log_level from .data_access import check_detect_frequency_is_valid +from .extra_logger import init_extra_logger LOG_FORMAT = "%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s" +AI_EXTRA_LOG_PATH = "/var/log/sysSentry/ai_block_io_extra.log" ALL_STAGE_LIST = [ "throtl", @@ -52,6 +54,7 @@ def init_log_format(log_level: str): logging.warning( "the log_level: %s you set is invalid, use default value: info.", log_level ) + init_extra_logger(AI_EXTRA_LOG_PATH, get_log_level(log_level.lower()), LOG_FORMAT) class ConfigParser: diff --git a/src/sentryPlugins/ai_block_io/extra_logger.py b/src/sentryPlugins/ai_block_io/extra_logger.py new file mode 100644 index 0000000..fdced27 --- /dev/null +++ b/src/sentryPlugins/ai_block_io/extra_logger.py @@ -0,0 +1,151 @@ +# coding: utf-8 +# Copyright (c) 2025 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. +import logging +import os +import re + +extra_logger = None + + +def init_extra_logger(log_path, log_level, log_format): + global extra_logger + try: + if not os.path.exists(log_path): + fd = os.open(log_path, os.O_CREAT | os.O_WRONLY, 0o600) + os.close(fd) + logger_name = f"extra_logger_{log_path}" + logger = logging.getLogger(logger_name) + logger.propagate = False + logger.setLevel(log_level) + + file_handler = logging.FileHandler(log_path) + file_handler.setLevel(log_level) + + formatter = logging.Formatter(log_format) + file_handler.setFormatter(formatter) + + logger.addHandler(file_handler) + extra_logger = logger + except Exception as e: + logging.error(f"Failed to create extra logger for {log_path}: {e}") + extra_logger = logging.getLogger() # Fallback to default logger + +def extra_slow_log(msg): + if "latency" in str(msg.get('alarm_type', '')): + extra_latency_log(msg) + return + if "iodump" in str(msg.get('alarm_type', '')): + return + +def extra_latency_log(msg): + io_types = [iot.strip() for iot in re.split(r',+', msg['io_type'])] + + # Define stage groups + groups = { + 'B->Q': ['throtl', 'wbt', 'iocost'], + 'Q->G': ['gettag', 'requeue'], + 'G->I': ['plug'], + 'I->D': ['deadline', 'bfq', 'hctx'], + 'D->C': ['rq_driver'] + } + + for io_type in io_types: + extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {io_type}") + + # Parse the latency string from msg + latency_str = msg['details']['latency'].get(io_type, {}) + pattern = r'(\w+):\s*\[([0-9.,]+)\]' + matches = re.findall(pattern, latency_str) + latency_data = {} + for match in matches: + key = match[0] + values = list(map(float, match[1].split(','))) + latency_data[key] = values + + # Calculate statistics for each group + group_stats = {} + for group_name, stages in groups.items(): + all_values = [] + for stage in stages: + if stage in latency_data: + all_values.extend(latency_data[stage]) + if all_values: + min_val = min(all_values) + max_val = max(all_values) + avg_val = sum(all_values) / len(all_values) + else: + min_val = 0 + max_val = 0 + avg_val = 0 + # Convert to ms + min_val_ms = min_val / 1000.0 + max_val_ms = max_val / 1000.0 + avg_val_ms = avg_val / 1000.0 + group_stats[group_name] = { + 'min': min_val_ms, + 'max': max_val_ms, + 'avg': avg_val_ms + } + + # Calculate total latency (B->C) + total_avg = 0 + total_min = 0 + total_max = 0 + for group_name in groups: + total_avg += group_stats[group_name]['avg'] + total_min += group_stats[group_name]['min'] + total_max += group_stats[group_name]['max'] + group_stats['B->C'] = { + 'min': total_min, + 'max': total_max, + 'avg': total_avg + } + + # Calculate PCT for each group (except B->C) + for group_name in groups: + if total_avg > 0: + pct = (group_stats[group_name]['avg'] / total_avg) * 100 + else: + pct = 0 + group_stats[group_name]['pct'] = pct + group_stats['B->C']['pct'] = 100.0 + + # Output table + stage_order = ['B->Q', 'Q->G', 'G->I', 'I->D', 'D->C', 'B->C'] + stage_width = 7 + num_width = 12 + pct_width = 8 + + extra_logger.warning( + f"{'Stage':<{stage_width}} " + f"{'Min(ms)':>{num_width}} " + f"{'Max(ms)':>{num_width}} " + f"{'Avg(ms)':>{num_width}} " + f"{'PCT':>{pct_width}}" + ) + + for stage in stage_order: + try: + s = group_stats[stage] + min_str = f"{s['min']:>.3f}" + max_str = f"{s['max']:>.3f}" + avg_str = f"{s['avg']:>.3f}" + pct_str = f"{s['pct']:.2f}%" + + extra_logger.warning( + f"{stage:<{stage_width}} " + f"{min_str:>{num_width}} " + f"{max_str:>{num_width}} " + f"{avg_str:>{num_width}} " + f"{pct_str:>{pct_width}}" + ) + except KeyError: + return diff --git a/src/sentryPlugins/ai_block_io/sliding_window.py b/src/sentryPlugins/ai_block_io/sliding_window.py index a13033f..b174d94 100644 --- a/src/sentryPlugins/ai_block_io/sliding_window.py +++ b/src/sentryPlugins/ai_block_io/sliding_window.py @@ -33,10 +33,13 @@ class SlidingWindow: def is_abnormal(self, data): if self._avg_lim is not None and data < self._avg_lim: return False - if self._ai_threshold is not None and data > self._ai_threshold: - return True + if self._avg_lim is not None and self._ai_threshold is not None: + threshold = max(self._avg_lim, self._ai_threshold) + if data > threshold: + return True if self._abs_threshold is not None and data > self._abs_threshold: return True + return False def push(self, data: float): if len(self._io_data_queue) == self._queue_length: diff --git a/src/sentryPlugins/avg_block_io/extra_logger.py b/src/sentryPlugins/avg_block_io/extra_logger.py index c2bf63f..d7f0183 100644 --- a/src/sentryPlugins/avg_block_io/extra_logger.py +++ b/src/sentryPlugins/avg_block_io/extra_logger.py @@ -38,9 +38,15 @@ def init_extra_logger(log_path, log_level, log_format): logging.error(f"Failed to create extra logger for {log_path}: {e}") extra_logger = logging.getLogger() # Fallback to default logger +def extra_slow_log(msg): + if "latency" in str(msg.get('alarm_type', '')): + extra_latency_log(msg) + return + if "iodump" in str(msg.get('alarm_type', '')): + return def extra_latency_log(msg): - extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {msg['io_type']}, type: {msg['alarm_type']}") + extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {msg['io_type']}") # Parse the latency string from msg latency_str = msg['details']['latency'] @@ -126,17 +132,17 @@ def extra_latency_log(msg): for stage in stage_order: try: s = group_stats[stage] - min_str = f"{s['min']:.3f}" - max_str = f"{s['max']:.3f}" - avg_str = f"{s['avg']:.3f}" + min_str = f"{s['min']:>.3f}" + max_str = f"{s['max']:>.3f}" + avg_str = f"{s['avg']:>.3f}" pct_str = f"{s['pct']:.2f}%" extra_logger.warning( f"{stage:<{stage_width}} " - f"{s['min']:.3f:>{num_width}} " - f"{s['max']:.3f:>{num_width}} " - f"{s['avg']:.3f:>{num_width}} " - f"{s['pct']:.2f}%:>{pct_width}" + f"{min_str:>{num_width}} " + f"{max_str:>{num_width}} " + f"{avg_str:>{num_width}} " + f"{pct_str:>{pct_width}}" ) except KeyError: return diff --git a/src/sentryPlugins/avg_block_io/utils.py b/src/sentryPlugins/avg_block_io/utils.py index 0337cdb..27c1f84 100644 --- a/src/sentryPlugins/avg_block_io/utils.py +++ b/src/sentryPlugins/avg_block_io/utils.py @@ -9,7 +9,7 @@ # PURPOSE. # See the Mulan PSL v2 for more details. import logging -from .extra_logger import extra_latency_log +from .extra_logger import extra_slow_log AVG_VALUE = 0 AVG_COUNT = 1 @@ -110,10 +110,9 @@ def log_slow_win(msg, reason): """record log of slow win""" logging.warning(f"[SLOW IO] disk: {msg['driver_name']}, stage: {msg['block_stack']}, " f"iotype: {msg['io_type']}, type: {msg['alarm_type']}, reason: {reason}") - if "latency" in str(msg.get('alarm_type', '')): - extra_latency_log(msg) logging.info(f"latency: {msg['details']['latency']}") logging.info(f"iodump: {msg['details']['iodump']}") + extra_slow_log(msg) def update_avg_and_check_abnormal(data, io_key, win_size, io_avg_value, io_data): diff --git a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp index cb52364..327ee78 100644 --- a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp +++ b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp @@ -200,13 +200,6 @@ int CBMCBlockIo::QueryEvents() break; } - size_t expectedSize = RESP_HEADER_SIZE + header.eventCount * EVENT_SIZE; - if (hexBytes.size() < expectedSize) { - BMC_LOG_ERROR << "Response size too small. Expected: " << expectedSize - << ", Actual: " << hexBytes.size(); - break; - } - BMC_LOG_DEBUG << "Total events: " << header.totalEvents << ", returned: " << static_cast(header.eventCount) << ", current index: " << currentIndex; @@ -215,6 +208,13 @@ int CBMCBlockIo::QueryEvents() break; } + size_t expectedSize = RESP_HEADER_SIZE + header.eventCount * EVENT_SIZE; + if (hexBytes.size() != expectedSize) { + BMC_LOG_ERROR << "Response size invalid. Expected: " << expectedSize + << ", Actual: " << hexBytes.size(); + break; + } + ProcessEvents(hexBytes, header.eventCount); currentIndex += header.eventCount; -- Gitee From eda0be6915a6daef29cca55041a7ae725ce815e7 Mon Sep 17 00:00:00 2001 From: hewh Date: Mon, 15 Sep 2025 14:46:17 +0800 Subject: [PATCH 10/16] add test . --- src/sentryPlugins/ai_block_io/extra_logger.py | 16 +++++----------- src/sentryPlugins/avg_block_io/extra_logger.py | 2 ++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/sentryPlugins/ai_block_io/extra_logger.py b/src/sentryPlugins/ai_block_io/extra_logger.py index fdced27..1684119 100644 --- a/src/sentryPlugins/ai_block_io/extra_logger.py +++ b/src/sentryPlugins/ai_block_io/extra_logger.py @@ -38,6 +38,7 @@ def init_extra_logger(log_path, log_level, log_format): logging.error(f"Failed to create extra logger for {log_path}: {e}") extra_logger = logging.getLogger() # Fallback to default logger + def extra_slow_log(msg): if "latency" in str(msg.get('alarm_type', '')): extra_latency_log(msg) @@ -45,6 +46,7 @@ def extra_slow_log(msg): if "iodump" in str(msg.get('alarm_type', '')): return + def extra_latency_log(msg): io_types = [iot.strip() for iot in re.split(r',+', msg['io_type'])] @@ -60,23 +62,15 @@ def extra_latency_log(msg): for io_type in io_types: extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {io_type}") - # Parse the latency string from msg - latency_str = msg['details']['latency'].get(io_type, {}) - pattern = r'(\w+):\s*\[([0-9.,]+)\]' - matches = re.findall(pattern, latency_str) - latency_data = {} - for match in matches: - key = match[0] - values = list(map(float, match[1].split(','))) - latency_data[key] = values + latency_data_dict = msg['details']['latency'].get(io_type, {}) # Calculate statistics for each group group_stats = {} for group_name, stages in groups.items(): all_values = [] for stage in stages: - if stage in latency_data: - all_values.extend(latency_data[stage]) + if stage in latency_data_dict: + all_values.extend(latency_data_dict[stage]) if all_values: min_val = min(all_values) max_val = max(all_values) diff --git a/src/sentryPlugins/avg_block_io/extra_logger.py b/src/sentryPlugins/avg_block_io/extra_logger.py index d7f0183..cd050f3 100644 --- a/src/sentryPlugins/avg_block_io/extra_logger.py +++ b/src/sentryPlugins/avg_block_io/extra_logger.py @@ -38,6 +38,7 @@ def init_extra_logger(log_path, log_level, log_format): logging.error(f"Failed to create extra logger for {log_path}: {e}") extra_logger = logging.getLogger() # Fallback to default logger + def extra_slow_log(msg): if "latency" in str(msg.get('alarm_type', '')): extra_latency_log(msg) @@ -45,6 +46,7 @@ def extra_slow_log(msg): if "iodump" in str(msg.get('alarm_type', '')): return + def extra_latency_log(msg): extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {msg['io_type']}") -- Gitee From f91d7fa88704c0006938be99a7ca99ee90183014 Mon Sep 17 00:00:00 2001 From: hewh Date: Mon, 15 Sep 2025 15:31:40 +0800 Subject: [PATCH 11/16] add test . --- selftest/test/test_ai_threshold_slow_io_detection.py | 6 +++--- src/sentryPlugins/ai_block_io/extra_logger.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/selftest/test/test_ai_threshold_slow_io_detection.py b/selftest/test/test_ai_threshold_slow_io_detection.py index c762c82..a89ce9a 100644 --- a/selftest/test/test_ai_threshold_slow_io_detection.py +++ b/selftest/test/test_ai_threshold_slow_io_detection.py @@ -91,7 +91,7 @@ class Test(unittest.TestCase): self.assertEqual(_get_n_sigma_threshold(data_list, 3), n_sigma_threshold) def test_not_continuous_sliding_window(self): - not_continuous = NotContinuousSlidingWindow(5, 3) + not_continuous = NotContinuousSlidingWindow(5, 3, 15, 40) boxplot_threshold = BoxplotThreshold(1.5, 10, 8) boxplot_threshold.attach_observer(not_continuous) data_list1 = [19, 20, 20, 20, 20, 20, 22, 24, 23, 20] @@ -114,7 +114,7 @@ class Test(unittest.TestCase): self.assertEqual(25.625, boxplot_threshold.get_threshold()) def test_continuous_sliding_window(self): - continuous = ContinuousSlidingWindow(5, 3) + continuous = ContinuousSlidingWindow(5, 3, 15, 40) boxplot_threshold = BoxplotThreshold(1.5, 10, 8) boxplot_threshold.attach_observer(continuous) data_list = [19, 20, 20, 20, 20, 20, 22, 24, 23, 20] @@ -131,7 +131,7 @@ class Test(unittest.TestCase): self.assertTrue(continuous.is_slow_io_event(25)[0][0]) def test_median_sliding_window(self): - median = MedianSlidingWindow(5, 3) + median = MedianSlidingWindow(5, 3, 15, 40) absolute_threshold = AbsoluteThreshold(10, 8) absolute_threshold.attach_observer(median) absolute_threshold.set_threshold(24.5) diff --git a/src/sentryPlugins/ai_block_io/extra_logger.py b/src/sentryPlugins/ai_block_io/extra_logger.py index 1684119..1148139 100644 --- a/src/sentryPlugins/ai_block_io/extra_logger.py +++ b/src/sentryPlugins/ai_block_io/extra_logger.py @@ -62,7 +62,7 @@ def extra_latency_log(msg): for io_type in io_types: extra_logger.warning(f"[SLOW IO] disk: {msg['driver_name']}, iotype: {io_type}") - latency_data_dict = msg['details']['latency'].get(io_type, {}) + latency_data_dict = msg['details']['latency'].get(io_type, {}) # Calculate statistics for each group group_stats = {} -- Gitee From bdcecdb23b3362771f54f67cc88ab263e5478c1f Mon Sep 17 00:00:00 2001 From: hewh Date: Mon, 15 Sep 2025 15:44:57 +0800 Subject: [PATCH 12/16] add test . --- selftest/test/test_ai_threshold_slow_io_detection.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selftest/test/test_ai_threshold_slow_io_detection.py b/selftest/test/test_ai_threshold_slow_io_detection.py index a89ce9a..a14d01c 100644 --- a/selftest/test/test_ai_threshold_slow_io_detection.py +++ b/selftest/test/test_ai_threshold_slow_io_detection.py @@ -91,7 +91,7 @@ class Test(unittest.TestCase): self.assertEqual(_get_n_sigma_threshold(data_list, 3), n_sigma_threshold) def test_not_continuous_sliding_window(self): - not_continuous = NotContinuousSlidingWindow(5, 3, 15, 40) + not_continuous = NotContinuousSlidingWindow(5, 3, 40, 15) boxplot_threshold = BoxplotThreshold(1.5, 10, 8) boxplot_threshold.attach_observer(not_continuous) data_list1 = [19, 20, 20, 20, 20, 20, 22, 24, 23, 20] @@ -114,7 +114,7 @@ class Test(unittest.TestCase): self.assertEqual(25.625, boxplot_threshold.get_threshold()) def test_continuous_sliding_window(self): - continuous = ContinuousSlidingWindow(5, 3, 15, 40) + continuous = ContinuousSlidingWindow(5, 3, 40, 15) boxplot_threshold = BoxplotThreshold(1.5, 10, 8) boxplot_threshold.attach_observer(continuous) data_list = [19, 20, 20, 20, 20, 20, 22, 24, 23, 20] @@ -131,7 +131,7 @@ class Test(unittest.TestCase): self.assertTrue(continuous.is_slow_io_event(25)[0][0]) def test_median_sliding_window(self): - median = MedianSlidingWindow(5, 3, 15, 40) + median = MedianSlidingWindow(5, 3, 40, 15) absolute_threshold = AbsoluteThreshold(10, 8) absolute_threshold.attach_observer(median) absolute_threshold.set_threshold(24.5) -- Gitee From 9b01061ff559b13ab531c357c94e9cf13e031103 Mon Sep 17 00:00:00 2001 From: hewh Date: Tue, 16 Sep 2025 10:48:16 +0800 Subject: [PATCH 13/16] add test . --- config/plugins/bmc_block_io.ini | 8 +----- .../bmc_block_io/include/cbmcblockio.h | 4 --- .../bmc_block_io/include/common.h | 2 -- .../bmc_block_io/include/configure.h | 6 ++-- .../bmc_block_io/src/cbmcblockio.cpp | 28 +++++-------------- src/sentryPlugins/bmc_block_io/src/common.cpp | 14 ++++++---- src/sentryPlugins/bmc_block_io/src/main.cpp | 12 -------- 7 files changed, 19 insertions(+), 55 deletions(-) diff --git a/config/plugins/bmc_block_io.ini b/config/plugins/bmc_block_io.ini index 3b22618..41a39ca 100644 --- a/config/plugins/bmc_block_io.ini +++ b/config/plugins/bmc_block_io.ini @@ -2,10 +2,4 @@ log_level=info # polling cycle, unit: seconds, range: [60, 3600] -patrol_second=5 - -# ipmitool login username -bmc_username=Administrator - -# ipmitool login passwd -bmc_passwd=Admin@9000 \ No newline at end of file +patrol_second=60 \ No newline at end of file diff --git a/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h b/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h index cb0b514..488b700 100644 --- a/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h +++ b/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h @@ -40,8 +40,6 @@ public: void Start(); void Stop(); void SetPatrolInterval(int seconds); - void SetUserName(std::string userName); - void SetPassWd(std::string passWd); bool IsRunning(); private: void SentryWorker(); @@ -60,8 +58,6 @@ private: std::thread m_worker; std::mutex m_mutex; std::condition_variable m_cv; - std::string m_userName; - std::string m_passWd; std::string m_bmcIp; int m_patrolSeconds; }; diff --git a/src/sentryPlugins/bmc_block_io/include/common.h b/src/sentryPlugins/bmc_block_io/include/common.h index 9304dee..e23f4b9 100644 --- a/src/sentryPlugins/bmc_block_io/include/common.h +++ b/src/sentryPlugins/bmc_block_io/include/common.h @@ -21,8 +21,6 @@ struct PluConfig { BMCBlockIoPlu::Logger::Level logLevel; int patrolSeconds; - std::string userName; - std::string passWd; }; struct ConfigItem { diff --git a/src/sentryPlugins/bmc_block_io/include/configure.h b/src/sentryPlugins/bmc_block_io/include/configure.h index 65a56ce..f253fb4 100644 --- a/src/sentryPlugins/bmc_block_io/include/configure.h +++ b/src/sentryPlugins/bmc_block_io/include/configure.h @@ -14,11 +14,9 @@ namespace BMCBlockIoPlu { const std::string BMCPLU_CONFIG_PATH = "/etc/sysSentry/plugins/bmc_block_io.ini"; const std::string BMCPLU_LOG_PATH = "/var/log/sysSentry/bmc_block_io.log"; -const std::string BMCPLU_DEFAULT_USERNAME = "Administrator"; -const std::string BMCPLU_DEFAULT_PASSWD = "Admin@9000"; -const int BMCPLU_PATROL_MIN = 1; +const int BMCPLU_PATROL_MIN = 60; const int BMCPLU_PATROL_MAX = 3600; -const int BMCPLU_PATROL_DEFAULT = 600; +const int BMCPLU_PATROL_DEFAULT = 300; const int BMCPLU_CONFIG_CHECK_CYCLE = 10; // seconds const int BMCPLU_DEFAULT_SLEEP_CYCLE = 3; // seconds } diff --git a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp index 327ee78..9711cbb 100644 --- a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp +++ b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp @@ -43,8 +43,6 @@ const std::string JSON_KEY_DETAILS = "details"; CBMCBlockIo::CBMCBlockIo() : m_running(false), m_patrolSeconds(BMCPLU_PATROL_DEFAULT), - m_userName(BMCPLU_DEFAULT_USERNAME), - m_passWd(BMCPLU_DEFAULT_PASSWD), m_bmcIp("") { } @@ -89,16 +87,6 @@ void CBMCBlockIo::SetPatrolInterval(int seconds) m_patrolSeconds = seconds; } -void CBMCBlockIo::SetUserName(std::string userName) -{ - m_userName = userName; -} - -void CBMCBlockIo::SetPassWd(std::string passWd) -{ - m_passWd = passWd; -} - bool CBMCBlockIo::IsRunning() { return m_running; @@ -178,7 +166,7 @@ void CBMCBlockIo::GetBMCIp() 20-23 占位字节,默认0 N+1-N+15重复上面9-23中的内容,表示下一个事件 厂商ID固定,其他所有多字节对象均为小端序, eg: -ipmitool -I lanplus -H x.x.x.x -U x -P x -C 17 raw 0x30 0x94 0xDB 0x07 0x00 0x40 0x00 0x00 0x00 0x01 0x02 +ipmitool raw 0x30 0x94 0xDB 0x07 0x00 0x40 0x00 0x00 0x00 0x01 0x02 db 07 00 03 00 03 00 39 00 00 02 2f ab 91 68 00 02 04 00 00 00 00 39 00 00 02 2e ab 91 68 00 02 02 00 00 00 00 39 00 00 02 2e ab 91 68 00 02 01 00 00 00 00 @@ -192,6 +180,7 @@ int CBMCBlockIo::QueryEvents() std::string cmd = BuildIPMICommand(currentIndex); std::vector hexBytes = ExecuteIPMICommand(cmd); if (hexBytes.empty()) { + ret = BMCPLU_SUCCESS; break; } @@ -231,10 +220,7 @@ std::string CBMCBlockIo::BuildIPMICommand(uint16_t startIndex) uint8_t indexHigh = static_cast((startIndex >> 8) & 0xff); uint8_t indexLow = static_cast(startIndex & 0xff); std::ostringstream cmdStream; - cmdStream << "ipmitool -I lanplus -H " << m_bmcIp - << " -U " << m_userName - << " -P " << m_passWd - << " -C 17 raw 0x30 0x94 0xDB 0x07 0x00 0x40 0x00" + cmdStream << "ipmitool raw 0x30 0x94 0xDB 0x07 0x00 0x40 0x00" << " " << ByteToHex(indexLow) << " " << ByteToHex(indexHigh) << " 0x01 0x02"; @@ -386,10 +372,10 @@ void CBMCBlockIo::ReportAlarm(const IPMIEvent& event) json_object* jObject = json_object_new_object(); json_object_object_add(jObject, JSON_KEY_ALARM_SOURCE.c_str(), json_object_new_string(BMC_TASK_NAME.c_str())); json_object_object_add(jObject, JSON_KEY_DRIVER_NAME.c_str(), json_object_new_string(std::to_string(event.deviceId).c_str())); - //json_object_object_add(jObject, JSON_KEY_IO_TYPE.c_str(), json_object_new_string("null")); - //json_object_object_add(jObject, JSON_KEY_REASON.c_str(), json_object_new_string("null")); - //json_object_object_add(jObject, JSON_KEY_BLOCK_STACK.c_str(), json_object_new_string("null")); - //json_object_object_add(jObject, JSON_KEY_DETAILS.c_str(), json_object_new_string("null")); + json_object_object_add(jObject, JSON_KEY_IO_TYPE.c_str(), json_object_new_string("read,write")); + json_object_object_add(jObject, JSON_KEY_REASON.c_str(), json_object_new_string("driver slow")); + json_object_object_add(jObject, JSON_KEY_BLOCK_STACK.c_str(), json_object_new_string("rq_driver")); + json_object_object_add(jObject, JSON_KEY_DETAILS.c_str(), json_object_new_string("{}}")); const char *jData = json_object_to_json_string(jObject); int ret = xalarm_Report(BMC_ALARM_ID, ucAlarmLevel, ucAlarmType, const_cast(jData)); if (ret != RETURE_CODE_SUCCESS) { diff --git a/src/sentryPlugins/bmc_block_io/src/common.cpp b/src/sentryPlugins/bmc_block_io/src/common.cpp index f03db17..6d98f83 100644 --- a/src/sentryPlugins/bmc_block_io/src/common.cpp +++ b/src/sentryPlugins/bmc_block_io/src/common.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace BMCBlockIoPlu { @@ -189,13 +190,16 @@ std::vector SplitString(const std::string& str, const std::string& size_t pos = 0; while (true) { size_t split_pos = str.find(split, pos); - if (split_pos != std::string::npos) { - result.push_back(str.substr(pos, split_pos - pos)); - pos = split_pos + split.size(); - } else { - result.push_back(str.substr(pos)); + std::string substring = str.substr(pos, split_pos - pos); + + if (!substring.empty()) { + result.push_back(substring); + } + + if (split_pos == std::string::npos) { break; } + pos = split_pos + split.size(); } return result; } diff --git a/src/sentryPlugins/bmc_block_io/src/main.cpp b/src/sentryPlugins/bmc_block_io/src/main.cpp index 8aeb3d0..29773b0 100644 --- a/src/sentryPlugins/bmc_block_io/src/main.cpp +++ b/src/sentryPlugins/bmc_block_io/src/main.cpp @@ -60,8 +60,6 @@ int main(int argc, char* argv[]) } else { BMCBlockIoPlu::Logger::GetInstance().SetLevel(config.logLevel); blockIo.SetPatrolInterval(config.patrolSeconds); - blockIo.SetUserName(config.userName); - blockIo.SetPassWd(config.passWd); } std::thread configMonitor([&] { @@ -96,16 +94,6 @@ int main(int argc, char* argv[]) BMC_LOG_INFO << "Patrol interval update to " << config.patrolSeconds; blockIo.SetPatrolInterval(config.patrolSeconds); } - if (newConfig.userName != config.userName) { - config.userName = newConfig.userName; - BMC_LOG_INFO << "BMC userName update to " << config.userName; - blockIo.SetUserName(config.userName); - } - if (newConfig.passWd != config.passWd) { - config.passWd = newConfig.passWd; - BMC_LOG_INFO << "BMC passWd update"; - blockIo.SetPassWd(config.passWd); - } } } } -- Gitee From 765e41fa3b02dec9a04cd6f21f113d0b3109dbfc Mon Sep 17 00:00:00 2001 From: hewh Date: Tue, 16 Sep 2025 11:06:40 +0800 Subject: [PATCH 14/16] add test . --- src/sentryPlugins/bmc_block_io/src/common.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/sentryPlugins/bmc_block_io/src/common.cpp b/src/sentryPlugins/bmc_block_io/src/common.cpp index 6d98f83..cd01b8a 100644 --- a/src/sentryPlugins/bmc_block_io/src/common.cpp +++ b/src/sentryPlugins/bmc_block_io/src/common.cpp @@ -82,16 +82,6 @@ int ParseConfig(const std::string& path, PluConfig& config) return true; }}; - configMap["bmc_username"] = {true, false, [&](const std::string& value) { - config.userName = value; - return true; - }}; - - configMap["bmc_passwd"] = {true, false, [&](const std::string& value) { - config.passWd = value; - return true; - }}; - std::string line; while (std::getline(file, line)) { line = Trim(line); -- Gitee From df576b7a333217a6d849e293b89d2ddc2ae8af23 Mon Sep 17 00:00:00 2001 From: hewanhan Date: Tue, 16 Sep 2025 19:51:28 +0800 Subject: [PATCH 15/16] add test . --- Makefile | 10 +++++----- src/libs/libxalarm/register_xalarm.c | 8 ++------ src/libs/pyxalarm/register_xalarm.py | 2 +- src/services/xalarm/xalarm_daemon.py | 2 +- src/services/xalarm/xalarm_server.py | 4 ++-- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index bd3bcb9..6009ca2 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ isentry: install -d -m 700 $(LOGSAVEDIR)/sysSentry install -d -m 700 $(VARLIB)/logrotate-syssentry install -d -m 700 $(PYDIR)/syssentry - install -d -m 700 $(PYDIR)/xalarm + install -d -m 755 $(PYDIR)/xalarm install -d -m 700 $(PYDIR)/sentryCollector install -d -m 700 $(PYDIR)/$(PKGVEREGG) install -d -m 700 $(ETCDIR)/sysconfig @@ -97,7 +97,7 @@ isentry: ## 安装python源代码文件到相应的目录 install -m 550 src/build/usr/lib/$(PYNAME)/site-packages/services/syssentry/* $(PYDIR)/syssentry - install -m 550 src/build/usr/lib/$(PYNAME)/site-packages/services/xalarm/* $(PYDIR)/xalarm + install -m 555 src/build/usr/lib/$(PYNAME)/site-packages/services/xalarm/* $(PYDIR)/xalarm install -m 550 src/build/usr/lib/$(PYNAME)/site-packages/services/sentryCollector/* $(PYDIR)/sentryCollector install -m 550 src/build/usr/lib/$(PYNAME)/site-packages/$(PKGVEREGG)/* $(PYDIR)/$(PKGVEREGG) @@ -146,14 +146,14 @@ isentry: install -m 550 src/libsentry/python/pySentryCollector/collect_plugin.py $(PYDIR)/sentryCollector # libxalarm - install -m 550 $(CURLIBDIR)/build/libxalarm/libxalarm.so $(LIBINSTALLDIR) + install -m 555 $(CURLIBDIR)/build/libxalarm/libxalarm.so $(LIBINSTALLDIR) # libxalarm-devel - install -d -m 700 $(INCLUDEDIR)/xalarm + install -d -m 755 $(INCLUDEDIR)/xalarm install -m 644 $(CURLIBDIR)/libxalarm/register_xalarm.h $(INCLUDEDIR)/xalarm/ # pyxalarm - install -m 550 src/libs/pyxalarm/register_xalarm.py $(PYDIR)/xalarm + install -m 555 src/libs/pyxalarm/register_xalarm.py $(PYDIR)/xalarm # log utils install -d -m 700 $(INCLUDEDIR)/libsentry diff --git a/src/libs/libxalarm/register_xalarm.c b/src/libs/libxalarm/register_xalarm.c index 1ddd0ae..4204fce 100644 --- a/src/libs/libxalarm/register_xalarm.c +++ b/src/libs/libxalarm/register_xalarm.c @@ -31,8 +31,8 @@ #define DIR_XALARM "/var/run/xalarm" #define PATH_REG_ALARM "/var/run/xalarm/alarm" #define PATH_REPORT_ALARM "/var/run/xalarm/report" -#define ALARM_DIR_PERMISSION 0750 -#define ALARM_SOCKET_PERMISSION 0600 +#define ALARM_DIR_PERMISSION 0755 +#define ALARM_SOCKET_PERMISSION 0666 #define TIME_UNIT_MILLISECONDS 1000 #define MAX_PARAS_LEN 8191 @@ -121,10 +121,6 @@ static int create_unix_socket(const char *path) printf("create_unix_socket: connect alarm_addr failed, ret: %d\n", ret); goto release_socket; } - if (chmod(path, ALARM_SOCKET_PERMISSION) < 0) { - printf("chmod %s failed: %s\n", path, strerror(errno)); - goto release_socket; - } return fd; diff --git a/src/libs/pyxalarm/register_xalarm.py b/src/libs/pyxalarm/register_xalarm.py index 7416478..91debf7 100644 --- a/src/libs/pyxalarm/register_xalarm.py +++ b/src/libs/pyxalarm/register_xalarm.py @@ -16,7 +16,7 @@ MAX_ALARM_ID = (MIN_ALARM_ID + MAX_NUM_OF_ALARM_ID - 1) DIR_XALARM = "/var/run/xalarm" PATH_REG_ALARM = "/var/run/xalarm/alarm" PATH_REPORT_ALARM = "/var/run/xalarm/report" -ALARM_DIR_PERMISSION = 0o0750 +ALARM_DIR_PERMISSION = 0o0755 ALARM_REG_SOCK_PERMISSION = 0o0700 ALARM_SOCKET_PERMISSION = 0o0700 TIME_UNIT_MILLISECONDS = 1000 diff --git a/src/services/xalarm/xalarm_daemon.py b/src/services/xalarm/xalarm_daemon.py index 3ab211c..14a41cd 100644 --- a/src/services/xalarm/xalarm_daemon.py +++ b/src/services/xalarm/xalarm_daemon.py @@ -25,7 +25,7 @@ from .xalarm_config import config_init, get_log_level from .xalarm_server import server_loop, SOCK_FILE ALARM_DIR = "/var/run/xalarm" -ALARM_DIR_PERMISSION = 0o750 +ALARM_DIR_PERMISSION = 0o755 ALARM_LOGFILE = '/var/log/sysSentry/xalarm.log' XALARMD_PID_FILE = "/var/run/xalarm/xalarmd.pid" PID_FILE_FLOCK = None diff --git a/src/services/xalarm/xalarm_server.py b/src/services/xalarm/xalarm_server.py index 3ed0a24..0ada5ca 100644 --- a/src/services/xalarm/xalarm_server.py +++ b/src/services/xalarm/xalarm_server.py @@ -35,8 +35,8 @@ ALARM_DIR = "/var/run/xalarm" USER_RECV_SOCK = "/var/run/xalarm/alarm" SOCK_FILE = "/var/run/xalarm/report" ALARM_REPORT_LEN = 8216 -ALARM_DIR_PERMISSION = 0o750 -SOCKET_FILE_PERMISSON = 0o600 +ALARM_DIR_PERMISSION = 0o755 +SOCKET_FILE_PERMISSON = 0o666 PERMISION_MASK = 0o777 PEROID_CHECK_TIME = 3 ALARM_LISTEN_QUEUE_LEN = 5 -- Gitee From 9adfaa97245020f835f8309a33cf8295e09f3575 Mon Sep 17 00:00:00 2001 From: hewh Date: Wed, 17 Sep 2025 17:36:29 +0800 Subject: [PATCH 16/16] add test . --- .../bmc_block_io/include/cbmcblockio.h | 3 ++ .../bmc_block_io/src/cbmcblockio.cpp | 32 ++++++++++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h b/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h index 488b700..a9829fe 100644 --- a/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h +++ b/src/sentryPlugins/bmc_block_io/include/cbmcblockio.h @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace BMCBlockIoPlu { @@ -59,6 +60,8 @@ private: std::mutex m_mutex; std::condition_variable m_cv; std::string m_bmcIp; + std::set m_lastDeviceIds; + std::set m_currentDeviceIds; int m_patrolSeconds; }; } diff --git a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp index 9711cbb..72cc819 100644 --- a/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp +++ b/src/sentryPlugins/bmc_block_io/src/cbmcblockio.cpp @@ -42,8 +42,7 @@ const std::string JSON_KEY_DETAILS = "details"; CBMCBlockIo::CBMCBlockIo() : m_running(false), - m_patrolSeconds(BMCPLU_PATROL_DEFAULT), - m_bmcIp("") + m_patrolSeconds(BMCPLU_PATROL_DEFAULT) { } @@ -174,26 +173,26 @@ db 07 00 03 00 03 00 39 00 00 02 2f ab 91 68 00 02 04 00 00 00 00 int CBMCBlockIo::QueryEvents() { uint16_t currentIndex = 0; - int ret = BMCPLU_FAILED; + int ret = BMCPLU_SUCCESS; + m_currentDeviceIds.clear(); while (true) { std::string cmd = BuildIPMICommand(currentIndex); std::vector hexBytes = ExecuteIPMICommand(cmd); if (hexBytes.empty()) { - ret = BMCPLU_SUCCESS; break; } ResponseHeader header = ParseResponseHeader(hexBytes); if (!header.valid) { + ret = BMCPLU_FAILED; break; } - BMC_LOG_DEBUG << "Total events: " << header.totalEvents + BMC_LOG_INFO << "Total events: " << header.totalEvents << ", returned: " << static_cast(header.eventCount) << ", current index: " << currentIndex; if (header.eventCount == 0) { - ret = BMCPLU_SUCCESS; break; } @@ -201,6 +200,7 @@ int CBMCBlockIo::QueryEvents() if (hexBytes.size() != expectedSize) { BMC_LOG_ERROR << "Response size invalid. Expected: " << expectedSize << ", Actual: " << hexBytes.size(); + ret = BMCPLU_FAILED; break; } @@ -208,10 +208,20 @@ int CBMCBlockIo::QueryEvents() currentIndex += header.eventCount; if (currentIndex >= header.totalEvents) { - ret = BMCPLU_SUCCESS; break; } } + + if (ret == BMCPLU_SUCCESS) { + for (const auto& id : m_lastDeviceIds) { + if (m_currentDeviceIds.find(id) == m_currentDeviceIds.end()) { + uint32_t timeNow = static_cast(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); + IPMIEvent clearEvent = {ALARM_CLEAR_CODE, timeNow, 0, 0x02, id, true}; + ReportAlarm(clearEvent); + } + } + m_lastDeviceIds = m_currentDeviceIds; + } return ret; } @@ -362,13 +372,19 @@ void CBMCBlockIo::ReportAlarm(const IPMIEvent& event) uint8_t ucAlarmType = 0; if (event.alarmTypeCode == ALARM_OCCUR_CODE) { ucAlarmType = ALARM_TYPE_OCCUR; + m_currentDeviceIds.insert(event.deviceId); } else if (event.alarmTypeCode == ALARM_CLEAR_CODE) { ucAlarmType = ALARM_TYPE_RECOVER; } else { - BMC_LOG_ERROR << "Skipping unknown alarm type: 0x" + BMC_LOG_DEBUG << "Skipping unknown alarm type: 0x" << std::hex << event.alarmTypeCode; return; } + + BMC_LOG_INFO << "Report alarm, type: " << static_cast(ucAlarmType); + BMC_LOG_INFO << "level: " << static_cast(ucAlarmLevel); + BMC_LOG_INFO << "deviceId: " << static_cast(event.deviceId); + BMC_LOG_INFO << "timestamp: " << event.timestamp; json_object* jObject = json_object_new_object(); json_object_object_add(jObject, JSON_KEY_ALARM_SOURCE.c_str(), json_object_new_string(BMC_TASK_NAME.c_str())); json_object_object_add(jObject, JSON_KEY_DRIVER_NAME.c_str(), json_object_new_string(std::to_string(event.deviceId).c_str())); -- Gitee