From 55a03b46318e4c977b7e84508c998775e9db34ba Mon Sep 17 00:00:00 2001 From: fly_1997 Date: Tue, 3 Dec 2024 09:13:09 +0800 Subject: [PATCH 1/4] add one-time command collection --- src/common/utils.cpp | 29 +++ src/common/utils.h | 3 + src/plugin/collect/system/CMakeLists.txt | 2 + .../collect/system/command/command_base.h | 2 +- .../system/command/command_collector.cpp | 5 +- src/plugin/collect/system/kernel_config.cpp | 223 ++++++++++-------- src/plugin/collect/system/kernel_config.h | 25 +- tests/CMakeLists.txt | 2 +- 8 files changed, 175 insertions(+), 116 deletions(-) diff --git a/src/common/utils.cpp b/src/common/utils.cpp index a300a6a..ddd5235 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -172,4 +173,32 @@ bool CreateDir(const std::string &path) } while (pos != std::string::npos); return true; } + +bool SetDataListTopic(DataList *dataList, const std::string &instanceName, const std::string &topicName, + const std::string ¶ms) +{ + dataList->topic.instanceName = new char[instanceName.size() + 1]; + if (dataList->topic.instanceName == nullptr) { + return false; + } + strcpy_s(dataList->topic.instanceName, instanceName.size() + 1, instanceName.data()); + dataList->topic.topicName = new char[topicName.size() + 1]; + if (dataList->topic.topicName == nullptr) { + delete[] dataList->topic.instanceName; + dataList->topic.instanceName = nullptr; + return false; + } + strcpy_s(dataList->topic.topicName, topicName.size() + 1, topicName.data()); + dataList->topic.params = new char[params.size() + 1]; + if (dataList->topic.params == nullptr) { + delete[] dataList->topic.instanceName; + delete[] dataList->topic.topicName; + dataList->topic.instanceName = nullptr; + dataList->topic.topicName = nullptr; + return false; + } + strcpy_s(dataList->topic.params, params.size() + 1, params.data()); + return true; +} + } diff --git a/src/common/utils.h b/src/common/utils.h index 48b72bd..ceadf36 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -13,6 +13,7 @@ #define COMMON_UTILS_H #include #include +#include "data_list.h" namespace oeaware { bool Download(const std::string &url, const std::string &path); @@ -29,6 +30,8 @@ std::string Concat(const std::vector& strings, const std::string &s // Separate "str" with the separator "split" std::vector SplitString(const std::string &str, const std::string &split); bool CreateDir(const std::string &path); +bool SetDataListTopic(DataList *dataList, const std::string &instanceName, const std::string &topicName, + const std::string ¶ms); } #endif // !COMMON_UTILS_H \ No newline at end of file diff --git a/src/plugin/collect/system/CMakeLists.txt b/src/plugin/collect/system/CMakeLists.txt index af4a239..b7d2666 100644 --- a/src/plugin/collect/system/CMakeLists.txt +++ b/src/plugin/collect/system/CMakeLists.txt @@ -10,5 +10,7 @@ add_library(system_collector SHARED ./command/command_collector.cpp ./command/command_base.cpp ) +target_include_directories(system_collector PRIVATE src/common) +target_link_libraries(system_collector common) set_target_properties(system_collector PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_LIBRARY_DIRECTORY}) \ No newline at end of file diff --git a/src/plugin/collect/system/command/command_base.h b/src/plugin/collect/system/command/command_base.h index ef9bd7c..8653a60 100644 --- a/src/plugin/collect/system/command/command_base.h +++ b/src/plugin/collect/system/command/command_base.h @@ -34,7 +34,7 @@ public: std::string nowType; oeaware::Topic topic; std::unordered_map> attrsFirst; - std::vector skipLine{"---swap--"}; + std::vector skipLine{"---swap--", "Average:"}; static std::vector command; static std::vector illegal; CommandBase(); diff --git a/src/plugin/collect/system/command/command_collector.cpp b/src/plugin/collect/system/command/command_collector.cpp index 640a406..1f6ac1e 100644 --- a/src/plugin/collect/system/command/command_collector.cpp +++ b/src/plugin/collect/system/command/command_collector.cpp @@ -9,8 +9,8 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. ******************************************************************************/ - #include "command_collector.h" +#include CommandCollector::CommandCollector(): oeaware::Interface() { @@ -41,8 +41,9 @@ void CommandCollector::CollectThread(const oeaware::Topic &topic, CommandBase* c while (collector->isRunning && fgets(buffer, sizeof(buffer), p.stream) != nullptr) { collector->ParseLine(std::string(buffer)); } + int waitTime = 10 * 1000; + usleep(waitTime); p.Pclose(); - collector->Close(); } diff --git a/src/plugin/collect/system/kernel_config.cpp b/src/plugin/collect/system/kernel_config.cpp index 3d25251..145251c 100644 --- a/src/plugin/collect/system/kernel_config.cpp +++ b/src/plugin/collect/system/kernel_config.cpp @@ -17,7 +17,9 @@ #include #include #include +#include "utils.h" #include "command_base.h" +#include "data_register.h" KernelConfig::KernelConfig(): oeaware::Interface() { @@ -35,6 +37,31 @@ KernelConfig::KernelConfig(): oeaware::Interface() } } +bool KernelConfig::InitCmd(std::stringstream &ss, const std::string &topicType) +{ + std::string cmd; + std::string word; + while (ss >> word) { + if (word == cmdSeparator) { + if (!CommandBase::ValidateCmd(cmd)) { + return false; + } + getCmds[topicType].emplace_back(cmd); + cmd = ""; + continue; + } + if (!cmd.empty()) { + cmd += " "; + } + cmd += word; + } + if (!CommandBase::ValidateCmd(cmd)) { + return false; + } + getCmds[topicType].emplace_back(cmd); + return true; +} + oeaware::Result KernelConfig::OpenTopic(const oeaware::Topic &topic) { if (find(topicStr.begin(), topicStr.end(), topic.topicName) == topicStr.end()) { @@ -42,9 +69,12 @@ oeaware::Result KernelConfig::OpenTopic(const oeaware::Topic &topic) } std::stringstream ss(topic.params); std::string word; - while (ss >> word) { - if (topic.topicName == "get_kernel_config") { - getTopics[topic.GetType()].insert(word); + std::string topicType = topic.GetType(); + if (topic.topicName == "get_cmd" && !InitCmd(ss, topicType)) { + return oeaware::Result(FAILED, "params invalid."); + } else if (topic.topicName == "get_kernel_config") { + while (ss >> word) { + getTopics[topicType].insert(word); } } return oeaware::Result(OK); @@ -53,87 +83,11 @@ oeaware::Result KernelConfig::OpenTopic(const oeaware::Topic &topic) void KernelConfig::CloseTopic(const oeaware::Topic &topic) { getTopics.erase(topic.GetType()); + getCmds.erase(topic.GetType()); setSystemParams.clear(); cmdRun.clear(); } -void KernelConfig::InitFileParam() -{ - for (auto &v : kernelParamPath) { - std::string path = v[1]; - std::ifstream file(path); - if (!file.is_open()) { - continue; - } - std::string key = v[0]; - std::string line; - std::string value = ""; - while (std::getline(file, line)) { - if (line.empty()) { - continue; - } - value += line; - value += '\n'; - } - kernelParams[key] = value; - file.close(); - } -} - -void KernelConfig::AddCommandParam(const std::string &cmd) -{ - FILE *pipe = popen(cmd.data(), "r"); - if (!pipe) { - return; - } - char buffer[1024]; - std::string value; - while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { - value += buffer; - } - pclose(pipe); - auto v = oeaware::SplitString(cmd, " "); - std::vector skipSpace; - for (auto &word : v) { - if (word.empty()) continue; - skipSpace.emplace_back(word); - } - if (skipSpace.size() > 1 && v[0] == "ethtool") { - kernelParams[v[0] + "@" + v[1]] = value; - return; - } - kernelParams[cmd] = value; -} - -static bool IsSymlink(const std::string &path) -{ - struct stat st; - if (lstat(path.c_str(), &st) != 0) { - perror("lstat failed"); - return false; - } - return S_ISLNK(st.st_mode); -} - -void KernelConfig::GetAllEth() -{ - const std::string path = "/sys/class/net"; - std::vector interfaces; - DIR* dir = opendir(path.c_str()); - if (dir == nullptr) { - WARN(logger, "failed to open directory: " << path << "."); - return; - } - struct dirent* entry; - while ((entry = readdir(dir)) != nullptr) { - std::string name(entry->d_name); - if (name != "." && name != ".." && IsSymlink(path + "/" + name)) { - allEths.push_back(name); - } - } - closedir(dir); -} - oeaware::Result KernelConfig::Enable(const std::string ¶m) { (void)param; @@ -156,21 +110,12 @@ oeaware::Result KernelConfig::Enable(const std::string ¶m) sysctlParams[values[0]] = values[1]; } pclose(pipe); - InitFileParam(); - GetAllEth(); - AddCommandParam("lscpu"); - AddCommandParam("ifconfig"); - for (auto ð : allEths) { - AddCommandParam("ethtool " + eth); - } - return oeaware::Result(OK); } void KernelConfig::Disable() { sysctlParams.clear(); - kernelParams.clear(); setSystemParams.clear(); getTopics.clear(); cmdRun.clear(); @@ -196,32 +141,103 @@ void KernelConfig::UpdateData(const DataList &dataList) return; } -void KernelConfig::PublishKernelConfig() +std::vector KernelConfig::getCmdGroup{"cat", "grep", "awk", "pgrep", "ls", "ethtool"}; + +static void SetKernelData(KernelData *data, const std::string &ret) { - if (getTopics.empty()) { + data->kernelData = new KernelDataNode(); + if (data->kernelData == nullptr) { + return; + } + data->len = 1; + data->kernelData->key = new char[1]; + if (data->kernelData->key == nullptr) { + delete data->kernelData; + data->kernelData = nullptr; + return; + } + data->kernelData->key[0] = 0; + data->kernelData->value = new char[ret.size() + 1]; + if (data->kernelData->value == nullptr) { + delete data->kernelData; + delete[] data->kernelData->key; + data->kernelData->key = nullptr; + data->kernelData = nullptr; return; } + strcpy_s(data->kernelData->value, ret.size() + 1, ret.data()); + data->kernelData->next = nullptr; +} + +void KernelConfig::PublishCmd() +{ + for (auto &p : getCmds) { + oeaware::Topic topic = oeaware::Topic::GetTopicFromType(p.first); + DataList dataList; + if (!oeaware::SetDataListTopic(&dataList, topic.instanceName, topic.topicName, topic.params)) { + continue; + } + KernelData *data = new KernelData(); + if (data == nullptr) { + WARN(logger, "KernelData failed to allocate memory."); + continue; + } + std::string cmd = ""; + for (auto &cmdPart : p.second) { + if (!cmd.empty()) { + cmd += " | "; + } + cmd += cmdPart; + } + PopenProcess pipe; + pipe.Popen(cmd); + char buffer[1024]; + std::string ret = ""; + while (fgets(buffer, sizeof(buffer), pipe.stream) != nullptr) { + ret += buffer; + } + if (pipe.Pclose() < 0) { + WARN(logger, "pipe close error."); + } + SetKernelData(data, ret); + dataList.len = 1; + dataList.data = new void* [1]; + if (dataList.data == nullptr) { + oeaware::Register::GetInstance().GetDataFreeFunc("kernel_config")(data); + continue; + } + dataList.data[0] = data; + Publish(dataList); + } +} + +void KernelConfig::PublishKernelParams() +{ for (auto &p : getTopics) { oeaware::Topic topic = oeaware::Topic::GetTopicFromType(p.first); DataList dataList; - dataList.topic.instanceName = new char[topic.instanceName.size() + 1]; - strcpy_s(dataList.topic.instanceName, topic.instanceName.size() + 1, topic.instanceName.data()); - dataList.topic.topicName = new char[topic.topicName.size() + 1]; - strcpy_s(dataList.topic.topicName, topic.topicName.size() + 1, topic.topicName.data()); - dataList.topic.params = new char[topic.params.size() + 1]; - strcpy_s(dataList.topic.params, topic.params.size() + 1, topic.params.data()); + if (!oeaware::SetDataListTopic(&dataList, topic.instanceName, topic.topicName, topic.params)) { + continue; + } KernelData *data = new KernelData(); + if (data == nullptr) { + WARN(logger, "KernelData failed to allocate memory."); + continue; + } KernelDataNode *tmp = nullptr; for (auto &name : p.second) { std::string value = ""; if (sysctlParams.count(name)) { value = sysctlParams[name]; - } else if (kernelParams.count(name)) { - value = kernelParams[name]; } else { + WARN(logger, "invalid params: " << name << "."); continue; } KernelDataNode *newNode = createNode(name.data(), value.data()); + if (newNode == nullptr) { + WARN(logger, "KernelDataNode failed to allocate memory."); + continue; + } if (data->kernelData == NULL) { data->kernelData = newNode; tmp = newNode; @@ -239,6 +255,15 @@ void KernelConfig::PublishKernelConfig() } } +void KernelConfig::PublishKernelConfig() +{ + if (getTopics.empty() && getCmds.empty()) { + return; + } + PublishCmd(); + PublishKernelParams(); +} + void KernelConfig::WriteSysParam(const std::string &path, const std::string &value) { std::ofstream sysFile(path); diff --git a/src/plugin/collect/system/kernel_config.h b/src/plugin/collect/system/kernel_config.h index 32049d4..4c6eb99 100644 --- a/src/plugin/collect/system/kernel_config.h +++ b/src/plugin/collect/system/kernel_config.h @@ -20,10 +20,11 @@ /* * topic: get_kernel_config, obtain the kernel parameter information. * params: kernel params name, including - * 1. sysctl -a -N - * 2. kernel_version, os_release, meminfo, zone_reclaim_mode - * 3. lscpu, ifconfig, ethtool@{name}. - * params : + * 1. sysctl -a -N + * + * topic: get_cmd, the trustlist command is supported. + * params: each command is seqarated by "@@", include "cat", "grep", "awk", "pgrep", "ls", "ethtool". + * * topic: set_kernel_config, modify kernel parameters. * DataList: * data: KernelData, [key, value]: @@ -41,29 +42,27 @@ public: void Disable() override; void Run() override; private: + void PublishCmd(); + void PublishKernelParams(); void PublishKernelConfig(); void SetKernelConfig(); + bool InitCmd(std::stringstream &ss, const std::string &topicType); void InitFileParam(); void AddCommandParam(const std::string &cmd); void WriteSysParam(const std::string &path, const std::string &value); void GetAllEth(); - std::vector topicStr = {"get_kernel_config", "set_kernel_config"}; - - const std::vector> kernelParamPath{{"kernel_version", "/proc/version"}, - {"os_release", "/etc/os-release"}, {"meminfo", "/proc/meminfo"}, - {"zone_reclaim_mode", "/proc/sys/vm/zone_reclaim_mode"}}; + std::vector topicStr = {"get_kernel_config", "get_cmd", "set_kernel_config"}; // key: topic type, value: parameters to be queried. std::unordered_map> getTopics; + std::unordered_map> getCmds; std::vector> setSystemParams; std::unordered_map sysctlParams; - // Stores system parameters, include lscpu, ifconfig, file path. - std::unordered_map kernelParams; - std::vector cmdRun; + static std::vector getCmdGroup; static std::vector cmdGroup; - std::vector allEths; + const std::string cmdSeparator = "@@"; }; #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index dec13ac..11079f2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -25,7 +25,7 @@ add_executable(pmu_count_test pmu_count_test.cpp ) -target_link_libraries(serialize_test PRIVATE curl GTest::gtest_main) +target_link_libraries(serialize_test PRIVATE common GTest::gtest_main) target_link_libraries(logger_test PRIVATE GTest::gtest_main log4cplus) target_link_libraries(safe_queue_test PRIVATE GTest::gtest_main) target_link_libraries(pmu_count_test PRIVATE GTest::gtest_main) -- 2.33.0