* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
* ubs-engine is licensed under 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.
*/
#include "ubse_node_controller.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <src/framework/serde/ubse_serial_util.h>
#include <chrono>
#include <queue>
#include <regex>
#include <set>
#include "ubse_conf_module.h"
#include "ubse_context.h"
#include "ubse_election_module.h"
#include "ubse_net_util.h"
#include "ubse_node.h"
#include "ubse_node_com_urma_collector.h"
#include "ubse_node_controller_agent.h"
#include "ubse_node_controller_collector.h"
#include "ubse_node_controller_util.h"
#include "ubse_serial_util.h"
#include "ubse_smbios.h"
#include "ubse_str_util.h"
#include "adapter_plugins/mti/ubse_mti_def.h"
#include "adapter_plugins/mti/ubse_mti_interface.h"
#include "securec.h"
namespace ubse::nodeController {
using namespace ubse::context;
using namespace ubse::election;
using namespace ubse::serial;
using namespace ubse::config;
using namespace ubse::adapter_plugins::mti;
using namespace ubse::adapter_plugins::smbios;
using namespace ubse::log;
using namespace ubse::common::def;
using namespace ubse::utils;
UBSE_DEFINE_THIS_MODULE("ubse");
const uint32_t LOCAL_HANDLER_RETRY_DURATION = 2;
const uint32_t IPV4_LENGTH = 4;
const uint32_t IPV6_LENGTH = 16;
const size_t MAX_HOSTNAME_LENGTH = 63;
constexpr size_t MAX_IP_ADDR_NUM = 1024;
constexpr uint32_t FAULT_STATE_PROTECT_SECONDS = 60;
* 从 LCNE 模块获取全量静态节点列表,用于选主模块查询全量节点列表,做选主操作
* @return
*/
std::vector<UbseNodeInfo> UbseNodeController::GetStaticNodeInfo()
{
std::vector<UbseNodeInfo> nodeInfos{};
std::vector<UbseMtiNodeInfo> ubseNodeInfos{};
auto ret = UbseMtiInterface::GetInstance().GetClusterNodeInfoList(ubseNodeInfos);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "get all node infos from lcne failed, " << FormatRetCode(ret);
return {};
}
for (const auto& node : ubseNodeInfos) {
UbseNodeInfo ubseNodeInfo{node.nodeId};
auto cpyRet = strcpy_s(ubseNodeInfo.bondingEid, sizeof(ubseNodeInfo.bondingEid), node.eid.c_str());
if (cpyRet != EOK) {
UBSE_LOG_ERROR << "nodeId=" << node.nodeId << " copy eid failed," << FormatRetCode(ret);
continue;
}
nodeInfos.push_back(ubseNodeInfo);
}
return nodeInfos;
}
* 获取全量节点列表,agent节点向主节点请求
* @return
*/
std::unordered_map<std::string, UbseNodeInfo> UbseNodeController::GetAllNodes()
{
auto module = UbseContext::GetInstance().GetModule<UbseElectionModule>();
if (module == nullptr) {
UBSE_LOG_ERROR << "election module not load";
return {};
}
if (module->IsLeader()) {
std::shared_lock<std::shared_mutex> lock(rwMutex);
return nodeInfos;
}
Node masterNode{};
auto ret = module->UbseGetMasterNode(masterNode);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "get master node failed, " << FormatRetCode(ret);
return {};
}
std::vector<UbseNodeInfo> infos{};
ret = GetAllNodeInfoFromRemote(masterNode.id, infos);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "get all node from master=" << masterNode.id << " failed, " << FormatRetCode(ret);
return {};
}
std::unordered_map<std::string, UbseNodeInfo> maps{};
for (const auto& info : infos) {
maps[info.nodeId] = info;
}
return maps;
}
UbseNodeInfo UbseNodeController::GetCurNode()
{
if (currentNodeId.empty() || nodeInfos.find(currentNodeId) == nodeInfos.end()) {
UbseNodeInfo info{};
GetCurNodeInfo(info);
currentNodeId = info.nodeId;
return info;
}
return GetNodeById(currentNodeId);
}
UbseNodeInfo UbseNodeController::GetNodeById(const std::string& nodeId)
{
std::shared_lock<std::shared_mutex> lock(rwMutex);
auto iter = nodeInfos.find(nodeId);
if (iter == nodeInfos.end()) {
UBSE_LOG_ERROR << "nodeId=" << nodeId << " not found";
return UbseNodeInfo{};
}
return iter->second;
}
UbseNodeInfo UbseNodeController::GetNodeBySlotId(uint32_t slotId)
{
std::shared_lock<std::shared_mutex> lock(rwMutex);
for (auto& iter : nodeInfos) {
if (iter.second.slotId != slotId) {
continue;
}
return iter.second;
}
UBSE_LOG_ERROR << "slotId=" << slotId << " not found";
return {};
}
uint32_t UbseNodeController::GetLocalEidBySocket(const uint32_t& socketId, uint32_t& eid)
{
auto node = GetNodeById(currentNodeId);
for (const auto& [_, cpuInfo] : node.cpuInfos) {
if (cpuInfo.socketId == socketId) {
UBSE_LOG_INFO << "nodeId=" << currentNodeId << ", socketId=" << socketId << " , eid=" << cpuInfo.eid;
return ConvertStrToUint32(cpuInfo.eid, eid, NO_16);
}
}
UBSE_LOG_ERROR << "nodeId=" << currentNodeId << ", socketId=" << socketId << " not found";
return UBSE_ERROR;
}
uint32_t UbseNodeController::GetEid(const std::string& nodeId, const uint32_t& socketId, uint32_t& eid)
{
if (currentNodeId == nodeId) {
return GetLocalEidBySocket(socketId, eid);
}
auto nodes = GetAllNodes();
auto iter = nodes.find(nodeId);
if (iter == nodes.end()) {
UBSE_LOG_ERROR << "nodeId=" << nodeId << " not found";
return UBSE_ERROR;
}
auto node = iter->second;
for (const auto& [_, cpuInfo] : node.cpuInfos) {
if (cpuInfo.socketId == socketId) {
UBSE_LOG_INFO << "nodeId=" << nodeId << ", socketId=" << socketId << " , eid=" << cpuInfo.eid;
return ConvertStrToUint32(cpuInfo.eid, eid, NO_16);
}
}
UBSE_LOG_ERROR << "nodeId=" << nodeId << ", socketId=" << socketId << " not found";
return UBSE_ERROR;
}
UbseResult CheckHostNameCharacters(std::string hostName)
{
for (size_t i = 0; i < hostName.size(); i++) {
if (!isdigit(hostName[i]) && !islower(hostName[i]) && !isupper(hostName[i]) && hostName[i] != '-') {
UBSE_LOG_WARN << "The hostname=" << hostName << "has illegal characters.";
return UBSE_ERROR;
}
}
return UBSE_OK;
}
UbseResult CheckHostName(std::string hostName)
{
if (hostName.size() > MAX_HOSTNAME_LENGTH) {
UBSE_LOG_WARN << "The length of the hostname=" << hostName << " exceeds 63 characters.";
return UBSE_ERROR;
}
if (hostName.empty()) {
UBSE_LOG_WARN << "The hostname=" << hostName << " is empty.";
return UBSE_ERROR;
}
if (CheckHostNameCharacters(hostName) != UBSE_OK) {
return UBSE_ERROR;
}
if (hostName[0] == '-' || hostName[hostName.size() - 1] == '-') {
UBSE_LOG_WARN << "The hostname=" << hostName << " contains '-' at the beginning or end.";
return UBSE_ERROR;
}
if (isdigit(hostName[0])) {
UBSE_LOG_WARN << "The hostname=" << hostName << " starts with a number.";
return UBSE_ERROR;
}
return UBSE_OK;
}
UbseResult CheckGroupList(std::vector<std::vector<std::string>>& groupListVec, UbseMemGroupNodeList& groupList)
{
std::unordered_set<std::string> globalSeen;
std::unordered_map<std::string, UbseNodeInfo> nodesMap = UbseNodeController::GetInstance().GetAllNodes();
std::unordered_map<std::string, UbseNodeInfo> hostnameMap{};
for (auto& kv : nodesMap) {
hostnameMap[kv.second.hostName] = kv.second;
}
size_t totalCount =
std::accumulate(groupListVec.begin(), groupListVec.end(), size_t(0),
[](size_t sum, const std::vector<std::string>& group) { return sum + group.size(); });
if (totalCount != nodesMap.size()) {
UBSE_LOG_ERROR << "the number of group list hosts does not match lcne static node number.";
return UBSE_ERROR_CONF_INVALID;
}
for (auto& group : groupListVec) {
std::vector<UbseNodeInfo> groupNodeInfo;
for (auto& hostname : group) {
if (globalSeen.count(hostname)) {
continue;
}
if (CheckHostName(hostname) != UBSE_OK) {
continue;
}
auto it = hostnameMap.find(hostname);
if (it == hostnameMap.end()) {
UBSE_LOG_WARN << "hostname:" << hostname << " is invalid";
continue;
}
groupNodeInfo.push_back(it->second);
globalSeen.insert(hostname);
}
groupList.push_back(groupNodeInfo);
}
return UBSE_OK;
}
uint32_t UbseNodeController::GetMemGroupNodeList(UbseMemGroupNodeList& groupList)
{
auto confModule = UbseContext::GetInstance().GetModule<UbseConfModule>();
if (confModule == nullptr) {
UBSE_LOG_ERROR << "conf module not init";
return UBSE_ERROR_MODULE_LOAD_FAILED;
}
std::string grouListConf;
auto ret = confModule->GetConf<std::string>("ubse.memory", "group", grouListConf);
if (ret != UBSE_OK) {
UBSE_LOG_WARN << "cannot access the group conf. Use the default set." << FormatRetCode(ret);
return UBSE_OK;
}
std::vector<std::string> groupListConfVec;
std::vector<std::vector<std::string>> groupListVec;
Split(grouListConf, ";", groupListConfVec);
for (auto& groupConf : groupListConfVec) {
std::vector<std::string> groups;
Split(groupConf, ",", groups);
groupListVec.push_back(groups);
}
ret = CheckGroupList(groupListVec, groupList);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "the group conf is invalid" << FormatRetCode(ret);
return ret;
}
return UBSE_OK;
}
UbseResult CheckProviderList(std::vector<std::string>& providerListConfVec, UbseMemProviderNodeList& providerList)
{
std::unordered_set<std::string> globalSeen;
std::unordered_map<std::string, UbseNodeInfo> nodesMap = UbseNodeController::GetInstance().GetAllNodes();
std::unordered_map<std::string, UbseNodeInfo> hostnameMap{};
for (auto& kv : nodesMap) {
hostnameMap[kv.second.hostName] = kv.second;
}
if (providerListConfVec.size() >= nodesMap.size()) {
UBSE_LOG_ERROR << "the number of provider is more than lcne static node number.";
return UBSE_ERROR_CONF_INVALID;
}
for (auto& hostname : providerListConfVec) {
if (globalSeen.count(hostname)) {
continue;
}
if (CheckHostName(hostname) != UBSE_OK) {
continue;
}
auto it = hostnameMap.find(hostname);
if (it == hostnameMap.end()) {
UBSE_LOG_WARN << "hostname:" << hostname << " is invalid";
continue;
}
providerList.push_back(it->second);
globalSeen.insert(hostname);
}
return UBSE_OK;
}
uint32_t UbseNodeController::GetMemProviderNodeList(UbseMemProviderNodeList& providerList)
{
auto confModule = UbseContext::GetInstance().GetModule<UbseConfModule>();
if (confModule == nullptr) {
UBSE_LOG_ERROR << "conf module not init";
return UBSE_ERROR_MODULE_LOAD_FAILED;
}
std::string providerConf;
auto ret = confModule->GetConf<std::string>("ubse.memory", "provider", providerConf);
if (ret != UBSE_OK) {
UBSE_LOG_WARN << "cannot access the provider conf. Use the default set." << FormatRetCode(ret);
return UBSE_OK;
}
std::vector<std::string> providerListConfVec;
Split(providerConf, ",", providerListConfVec);
ret = CheckProviderList(providerListConfVec, providerList);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "the provider conf is invalid." << FormatRetCode(ret);
return ret;
}
return UBSE_OK;
}
uint32_t UbseNodeController::RegLocalStateNotifyHandler(const UbseLocalStateNotifyHandler& handler)
{
std::unique_lock<std::shared_mutex> lock(rwMutex);
UBSE_LOG_INFO << "register node local state";
localNotifyHandlers.push_back(handler);
return UBSE_OK;
}
uint32_t UbseNodeController::RegClusterStateNotifyHandler(const UbseClusterStateNotifyHandler& handler)
{
std::unique_lock<std::shared_mutex> lock(rwMutex);
clusterNotifyHandlers.push_back(handler);
return UBSE_OK;
}
void ExecLocalStateHandler(const UbseNodeInfo& nodeInfo, const std::vector<UbseLocalStateNotifyHandler>& handlers)
{
for (auto handler : handlers) {
while (true) {
if (handler == nullptr) {
break;
}
auto ret = handler(nodeInfo);
if (ret == UBSE_OK) {
break;
}
UBSE_LOG_WARN << "local node exec handler failed, when update local state to "
<< static_cast<uint32_t>(nodeInfo.localState);
sleep(LOCAL_HANDLER_RETRY_DURATION);
}
}
}
UbseResult ExecClusterStateHandler(const UbseNodeInfo& nodeInfo,
const std::vector<UbseClusterStateNotifyHandler>& handlers)
{
UbseResult ret = UBSE_OK;
auto module = UbseContext::GetInstance().GetModule<UbseElectionModule>();
if (module == nullptr) {
UBSE_LOG_ERROR << "election module not load";
return UBSE_ERROR_MODULE_LOAD_FAILED;
}
if (!module->IsLeader()) {
UBSE_LOG_WARN << "current node not master, skip exec cluster state notify";
return UBSE_OK;
}
UBSE_LOG_INFO << "ExecClusterStateHandler start, nodeId=" << nodeInfo.nodeId
<< ", clusterState=" << static_cast<uint32_t>(nodeInfo.clusterState)
<< ", handlers count=" << handlers.size();
int failedCount = 0;
for (auto handler : handlers) {
if (handler == nullptr) {
continue;
}
UbseResult handlerRet = handler(nodeInfo);
if (handlerRet != UBSE_OK) {
UBSE_LOG_ERROR << "nodeId=" << nodeInfo.nodeId << " handler failed, ret=" << FormatRetCode(handlerRet);
failedCount++;
}
ret |= handlerRet;
}
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "nodeId=" << nodeInfo.nodeId
<< " update state=" << static_cast<uint32_t>(nodeInfo.clusterState)
<< " exec handler failed, total ret=" << FormatRetCode(ret) << ", failedCount=" << failedCount
<< "/" << handlers.size();
} else {
UBSE_LOG_INFO << "nodeId=" << nodeInfo.nodeId
<< " update state=" << static_cast<uint32_t>(nodeInfo.clusterState)
<< " exec all handlers success, total=" << handlers.size();
}
return ret;
}
uint32_t UbseNodeController::UpdateNodeInfo(const std::string& nodeId, UbseNodeInfo info)
{
UbseResult ret = UBSE_OK;
rwMutex.lock();
if (nodeInfos.find(nodeId) == nodeInfos.end()) {
UBSE_LOG_INFO << "nodeId=" << nodeId << " first add, update node info, current nodeId=" << GetCurrentNodeId();
info.clusterState = UbseNodeClusterState::UBSE_NODE_INIT;
nodeInfos[nodeId] = info;
UbseSocketIdChange(nodeId);
auto notifyInfo = nodeInfos[nodeId];
rwMutex.unlock();
if (nodeId == currentNodeId) {
ExecLocalStateHandler(notifyInfo, localNotifyHandlers);
}
ret = ExecClusterStateHandler(notifyInfo, clusterNotifyHandlers);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "nodeId=" << nodeId << " first add notify cluster state failed, " << FormatRetCode(ret);
} else {
UBSE_LOG_INFO << "nodeId=" << nodeId << " first add notify cluster state success";
}
return ret;
}
auto& existing = nodeInfos[nodeId];
info.clusterState = existing.clusterState;
info.localState = existing.localState;
if (info.guid.empty() && !existing.guid.empty()) {
info.guid = existing.guid;
}
existing = std::move(info);
UbseSocketIdChange(nodeId);
rwMutex.unlock();
return UBSE_OK;
}
void LogOnSocketIdMismatch(const std::set<uint32_t>& lcneChipIdSet, const std::set<uint32_t>& osSocketIdSet)
{
if (lcneChipIdSet.size() != osSocketIdSet.size()) {
UBSE_LOG_WARN << "Mismatch in sockets. lcne reports " << lcneChipIdSet.size() << " CPUs, while OS reports "
<< osSocketIdSet.size() << " sockets.";
std::ostringstream oss;
oss << "os_socket_ids include";
std::for_each(osSocketIdSet.begin(), osSocketIdSet.end(),
[&oss](const uint32_t& osSocketId) { oss << " " << osSocketId; });
oss << ". lcne_chip_ids include";
std::for_each(lcneChipIdSet.begin(), lcneChipIdSet.end(),
[&oss](const uint32_t& lcneChipId) { oss << " " << lcneChipId; });
UBSE_LOG_WARN << oss.str();
}
}
void UbseNodeController::UbseSocketIdChange(const std::string& nodeId)
{
std::unordered_map<uint32_t, uint32_t> socketIdMap;
std::set<uint32_t> osSocketIdSet;
std::set<uint32_t> lcneChipIdSet;
for (auto& numa : nodeInfos[nodeId].numaInfos) {
osSocketIdSet.insert(numa.second.socketId);
}
for (auto& cpu : nodeInfos[nodeId].cpuInfos) {
uint32_t chipId;
ubse::utils::ConvertStrToUint32(cpu.second.chipId, chipId);
lcneChipIdSet.insert(chipId);
}
LogOnSocketIdMismatch(lcneChipIdSet, osSocketIdSet);
auto it1 = lcneChipIdSet.begin();
auto it2 = osSocketIdSet.begin();
for (size_t i = 0; i < lcneChipIdSet.size() && i < osSocketIdSet.size(); i++) {
socketIdMap[*it1] = *it2;
++it1;
++it2;
}
for (auto& cpu : nodeInfos[nodeId].cpuInfos) {
uint32_t chipId;
ubse::utils::ConvertStrToUint32(cpu.second.chipId, chipId);
auto it = socketIdMap.find(chipId);
if (it != socketIdMap.end()) {
cpu.second.socketId = it->second;
}
}
}
std::string CreateLinkIdAndPhysicalLink(const LinkInfo& linkInfo, PhysicalLink& physicalLink)
{
try {
uint32_t slotId = std::stoi(linkInfo.slotId);
uint32_t socketId = std::stoi(linkInfo.socketId);
uint32_t portId = std::stoi(linkInfo.portId);
uint32_t peerSlotId = std::stoi(linkInfo.peerSlotId);
uint32_t peerSocketId = std::stoi(linkInfo.peerSocketId);
uint32_t peerPortId = std::stoi(linkInfo.peerPortId);
if (linkInfo.slotId < linkInfo.peerSlotId) {
physicalLink = {slotId, socketId, portId, linkInfo.interfaceName,
peerSlotId, peerSocketId, peerPortId, linkInfo.peerInterfaceName};
return linkInfo.slotId + "/" + linkInfo.socketId + "/" + linkInfo.portId + "-" + linkInfo.peerSlotId + "/" +
linkInfo.peerSocketId + "/" + linkInfo.peerPortId;
} else {
physicalLink = {peerSlotId, peerSocketId, peerPortId, linkInfo.peerInterfaceName,
slotId, socketId, portId, linkInfo.interfaceName};
return linkInfo.peerSlotId + "/" + linkInfo.peerSocketId + "/" + linkInfo.peerPortId + "-" +
linkInfo.slotId + "/" + linkInfo.socketId + "/" + linkInfo.portId;
}
} catch (const std::exception& e) {
UBSE_LOG_WARN << "LCNE provides data that cannot be converted to uint32, with the specific data being: "
<< "slotId=" << linkInfo.slotId << ", socketId=" << linkInfo.socketId
<< ", portId=" << linkInfo.portId << ", peerSlotId=" << linkInfo.peerSlotId
<< ", peerSocketId=" << linkInfo.peerSocketId << ", peerPortId=" << linkInfo.peerPortId;
}
return "ERROR-LINK";
}
void UbseNodeController::UpdateConnect(PhysicalLink& physicalLink, std::string& linkId)
{
auto it = devDirConnectInfo.find(linkId);
if (it == devDirConnectInfo.end()) {
physicalLink.linkStatus = LinkStatus::conflict;
devDirConnectInfo[linkId] = physicalLink;
} else {
PhysicalLink& existing = it->second;
if (existing.interfaceName.empty() && !physicalLink.interfaceName.empty()) {
existing.interfaceName = physicalLink.interfaceName;
}
if (existing.peerInterfaceName.empty() && !physicalLink.peerInterfaceName.empty()) {
existing.peerInterfaceName = physicalLink.peerInterfaceName;
}
existing.linkStatus = LinkStatus::available;
}
}
void UbseNodeController::PrintDevDirConnectInfo()
{
std::stringstream oss;
oss << "------ DevDirConnectInfo INFO ------\n";
for (auto& connect : devDirConnectInfo) {
oss << "LinkId=" << connect.first << ", slotId=" << connect.second.slotId
<< ", chipId=" << connect.second.chipId << ", portId=" << connect.second.portId
<< ", peerSlotId=" << connect.second.peerSlotId << ", peerChipId=" << connect.second.peerChipId
<< ", peerPortId=" << connect.second.peerPortId;
if (connect.second.linkStatus == LinkStatus::conflict) {
oss << ", status=conflict";
}
oss << "\n";
}
UBSE_LOG_INFO << oss.str();
}
void UbseNodeController::UpdateDevDirConnectInfo()
{
std::unique_lock<std::shared_mutex> lock(devDirMutex);
std::unordered_map<std::string, UbseNodeInfo> localNodeInfos;
{
std::shared_lock<std::shared_mutex> lockNodeInfos(rwMutex);
localNodeInfos = nodeInfos;
}
devDirConnectInfo.clear();
for (auto& nodeInfo : localNodeInfos) {
for (auto& topoInfo : nodeInfo.second.cpuInfos) {
CreateAndUpdateInfo(topoInfo);
}
}
}
void UbseNodeController::CreateAndUpdateInfo(std::pair<const UbseCpuLocation, UbseCpuInfo> topoInfo)
{
if (UbseSmbios::GetInstance().IsClosType()) {
return;
}
std::string slotId = topoInfo.first.nodeId;
std::string chipId = topoInfo.second.chipId;
for (auto& portInfo : topoInfo.second.portInfos) {
if (portInfo.second.portStatus == PortStatus::DOWN) {
continue;
}
std::string portId = portInfo.first;
std::string interfaceName = portInfo.second.ifName;
std::string remoteSlotId = portInfo.second.remoteSlotId;
std::string remoteChipId = portInfo.second.remoteChipId;
std::string remotePortId = portInfo.second.remotePortId;
std::string peerInterfaceName = portInfo.second.remoteIfName;
if (remoteSlotId.empty() || remoteChipId.empty() || remotePortId.empty()) {
continue;
}
if (remoteSlotId == "-" || remoteChipId == "-" || remotePortId == "-") {
continue;
}
LinkInfo linkInfo{slotId, chipId, portId, interfaceName,
remoteSlotId, remoteChipId, remotePortId, peerInterfaceName};
PhysicalLink physicalLink{};
std::string linkId = CreateLinkIdAndPhysicalLink(linkInfo, physicalLink);
if (linkId == "ERROR-LINK") {
continue;
}
UpdateConnect(physicalLink, linkId);
}
}
void UbseNodeController::UpdateNodeInfoLocalState(UbseNodeLocalState state)
{
UBSE_LOG_INFO << "nodeId=" << currentNodeId << " start to update local state=" << static_cast<uint32_t>(state);
rwMutex.lock();
if (nodeInfos.find(currentNodeId) == nodeInfos.end()) {
rwMutex.unlock();
UBSE_LOG_ERROR << "nodeId=" << currentNodeId << " local node info not collect, skip update local state.";
return;
}
nodeInfos[currentNodeId].localState = state;
auto nodeInfo = nodeInfos[currentNodeId];
auto handlers = localNotifyHandlers;
rwMutex.unlock();
ExecLocalStateHandler(nodeInfo, handlers);
UBSE_LOG_INFO << "local node update local state to " << static_cast<uint32_t>(state);
}
bool CanUpdateNodeClusterState(UbseNodeClusterState curState, UbseNodeClusterState updateState)
{
switch (curState) {
case UbseNodeClusterState::UBSE_NODE_INIT:
return updateState == UbseNodeClusterState::UBSE_NODE_SMOOTHING ||
updateState == UbseNodeClusterState::UBSE_NODE_UNKNOWN ||
updateState == UbseNodeClusterState::UBSE_NODE_FAULT;
case UbseNodeClusterState::UBSE_NODE_SMOOTHING:
return updateState == UbseNodeClusterState::UBSE_NODE_WORKING ||
updateState == UbseNodeClusterState::UBSE_NODE_UNKNOWN ||
updateState == UbseNodeClusterState::UBSE_NODE_FAULT ||
updateState == UbseNodeClusterState::UBSE_NODE_PRE_BMC ||
updateState == UbseNodeClusterState::UBSE_NODE_SMOOTHING;
case UbseNodeClusterState::UBSE_NODE_WORKING:
return updateState == UbseNodeClusterState::UBSE_NODE_SMOOTHING ||
updateState == UbseNodeClusterState::UBSE_NODE_UNKNOWN ||
updateState == UbseNodeClusterState::UBSE_NODE_FAULT ||
updateState == UbseNodeClusterState::UBSE_NODE_PRE_BMC;
case UbseNodeClusterState::UBSE_NODE_UNKNOWN:
return updateState == UbseNodeClusterState::UBSE_NODE_SMOOTHING ||
updateState == UbseNodeClusterState::UBSE_NODE_FAULT ||
updateState == UbseNodeClusterState::UBSE_NODE_UNKNOWN;
case UbseNodeClusterState::UBSE_NODE_FAULT:
return updateState == UbseNodeClusterState::UBSE_NODE_SMOOTHING ||
updateState == UbseNodeClusterState::UBSE_NODE_FAULT;
case UbseNodeClusterState::UBSE_NODE_PRE_BMC:
return updateState == UbseNodeClusterState::UBSE_NODE_FAULT ||
updateState == UbseNodeClusterState::UBSE_NODE_WORKING ||
updateState == UbseNodeClusterState::UBSE_NODE_SMOOTHING;
default: {
UBSE_LOG_ERROR << "unknown current state: " << static_cast<uint32_t>(curState);
return false;
}
}
}
uint32_t GenerateFaultUbseNode(const std::string& nodeId, UbseNodeInfo& faultNodeInfo)
{
faultNodeInfo.nodeId = nodeId;
auto ret = ConvertStrToUint32(faultNodeInfo.nodeId, faultNodeInfo.slotId);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "generate fault nodeId=" << nodeId << ", convert slot id failed, " << FormatRetCode(ret);
return ret;
}
UBSE_LOG_INFO << "generate fault nodeId=" << nodeId << ", slotId=" << faultNodeInfo.slotId;
faultNodeInfo.clusterState = UbseNodeClusterState::UBSE_NODE_FAULT;
ret = CollectCpuInfo(faultNodeInfo, nodeId);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "generate fault nodeId=" << nodeId << ", cpu info failed, " << FormatRetCode(ret);
return ret;
}
std::vector<UbseMtiNodeInfo> ubseNodeInfos{};
ret = UbseMtiInterface::GetInstance().GetClusterNodeInfoList(ubseNodeInfos);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "generate fault nodeId=" << nodeId << ", get all nodes failed, " << FormatRetCode(ret);
return {};
}
for (auto& node : ubseNodeInfos) {
if (nodeId != node.nodeId) {
continue;
}
auto cpyRet = strcpy_s(faultNodeInfo.bondingEid, sizeof(faultNodeInfo.bondingEid), node.eid.c_str());
if (cpyRet != EOK) {
UBSE_LOG_ERROR << "generate fault nodeId=" << nodeId << ", copy eid failed, " << FormatRetCode(ret);
}
break;
}
return UBSE_OK;
}
uint32_t UbseNodeController::UpdateNodeInfoClusterState(const std::string& nodeId, UbseNodeClusterState state)
{
UBSE_LOG_INFO << "nodeId=" << nodeId << " start to update cluster state=" << static_cast<uint32_t>(state);
UbseResult ret = UBSE_OK;
rwMutex.lock();
if (nodeInfos.find(nodeId) == nodeInfos.end()) {
if (state != UbseNodeClusterState::UBSE_NODE_FAULT) {
rwMutex.unlock();
UBSE_LOG_ERROR << "nodeId=" << nodeId << " cluster node info not collect, skip update cluster state="
<< static_cast<uint32_t>(state);
return UBSE_ERROR_NULLPTR;
}
UbseNodeInfo faultNodeInfo{};
(void)GenerateFaultUbseNode(nodeId, faultNodeInfo);
nodeInfos[nodeId] = faultNodeInfo;
faultUpdateTimes[nodeId] = std::chrono::steady_clock::now();
rwMutex.unlock();
UBSE_LOG_WARN << "nodeId=" << nodeId << " cluster node info not collect, set default item.";
return UBSE_OK;
}
auto curState = nodeInfos[nodeId].clusterState;
if (curState == UbseNodeClusterState::UBSE_NODE_FAULT && state != UbseNodeClusterState::UBSE_NODE_FAULT) {
auto iter = faultUpdateTimes.find(nodeId);
if (iter != faultUpdateTimes.end()) {
auto elapsed =
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - iter->second)
.count();
if (elapsed < FAULT_STATE_PROTECT_SECONDS) {
rwMutex.unlock();
UBSE_LOG_WARN << "nodeId=" << nodeId << " is in fault protect period, skip update cluster state="
<< static_cast<uint32_t>(state) << ", elapsed=" << elapsed << "s";
return UBSE_OK;
}
}
}
if (!CanUpdateNodeClusterState(curState, state)) {
rwMutex.unlock();
UBSE_LOG_ERROR << "nodeId=" << nodeId
<< " can not cluster local state, current state=" << static_cast<uint32_t>(curState)
<< ", update state=" << static_cast<uint32_t>(state);
return UBSE_ERROR;
}
UBSE_LOG_INFO << "nodeId=" << nodeId << " update cluster state, current state=" << static_cast<uint32_t>(curState)
<< ", update state=" << static_cast<uint32_t>(state);
if (curState != UbseNodeClusterState::UBSE_NODE_FAULT && state == UbseNodeClusterState::UBSE_NODE_FAULT) {
faultUpdateTimes[nodeId] = std::chrono::steady_clock::now();
} else if (state != UbseNodeClusterState::UBSE_NODE_FAULT) {
faultUpdateTimes.erase(nodeId);
}
nodeInfos[nodeId].clusterState = state;
rwMutex.unlock();
rwMutex.lock_shared();
if (nodeInfos.find(nodeId) == nodeInfos.end()) {
UBSE_LOG_WARN << "nodeId=" << nodeId << " not exists.";
rwMutex.unlock_shared();
return UBSE_OK;
}
auto nodeInfoCopy = nodeInfos[nodeId];
rwMutex.unlock_shared();
ret = ExecClusterStateHandler(nodeInfoCopy, clusterNotifyHandlers);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "nodeId=" << nodeId << " update state=" << static_cast<uint32_t>(state)
<< " exec handler failed, " << FormatRetCode(ret);
}
return ret;
}
void UbseNodeController::SetCurrentNodeId(const std::string& nodeId)
{
currentNodeId = nodeId;
}
std::string UbseNodeController::GetCurrentNodeId()
{
return currentNodeId;
}
void UbseNodeController::CleanAfterMasterSwitchRole()
{
std::unique_lock<std::shared_mutex> lock(rwMutex);
for (auto it = nodeInfos.begin(); it != nodeInfos.end();) {
if (it->first != currentNodeId) {
it = nodeInfos.erase(it);
} else {
++it;
}
}
}
std::map<std::string, PhysicalLink> UbseNodeController::UbseGetDirConnectInfo()
{
auto module = UbseContext::GetInstance().GetModule<UbseElectionModule>();
if (module == nullptr) {
UBSE_LOG_ERROR << "election module not load";
return {};
}
if (module->IsLeader()) {
std::shared_lock<std::shared_mutex> lock(devDirMutex);
PrintDevDirConnectInfo();
return devDirConnectInfo;
}
Node masterNode{};
auto ret = module->UbseGetMasterNode(masterNode);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "get master node failed, " << FormatRetCode(ret);
return {};
}
std::map<std::string, PhysicalLink> devDirConnectInfoRemote;
ret = UbseGetDirConnectInfoFromRemote(masterNode.id, devDirConnectInfoRemote);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "get devDirConnectInfo form master=" << masterNode.id << " failed, " << FormatRetCode(ret);
return {};
}
return devDirConnectInfoRemote;
}
std::set<uint32_t> UbseNodeController::UbseGetAllDeployedNode()
{
std::map<std::string, PhysicalLink> connectInfo = UbseNodeController::GetInstance().UbseGetDirConnectInfo();
std::set<uint32_t> deployedNode;
for (auto& connect : connectInfo) {
deployedNode.insert(connect.second.slotId);
deployedNode.insert(connect.second.peerSlotId);
}
std::ostringstream oss;
std::for_each(deployedNode.begin(), deployedNode.end(),
[&oss](const uint32_t& slotId) { oss << std::to_string(slotId) << ","; });
UBSE_LOG_INFO << "[node_controller] UbseGetAllDeployedNode slotId are:" << oss.str();
return deployedNode;
}
UbseResult GetUbseIpAddrVecOffset(const std::vector<UbseIpAddr>& ipList, UbseSerialization& outStream)
{
outStream << (right_v<size_t>(ipList.size()));
for (size_t i = 0; i < ipList.size(); i++) {
UbseSerialization item;
auto type = ipList[i].type;
item << enum_v(type);
std::vector<uint8_t> ipv6Vec{};
std::vector<uint8_t> ipv4Vec{};
if (type == UbseIpType::UBSE_IP_V4) {
for (size_t j = 0; j < IPV4_LENGTH; j++) {
ipv4Vec.push_back(ipList[i].ipv4.addr[j]);
}
item << ipv4Vec;
} else {
for (size_t j = 0; j < IPV6_LENGTH; j++) {
ipv6Vec.push_back(ipList[i].ipv6.addr[j]);
}
item << ipv6Vec;
}
outStream << item;
if (!outStream.Check()) {
UBSE_LOG_ERROR << "Ubse serialize ip addr vec failed";
return UBSE_ERROR;
}
}
return UBSE_OK;
}
UbseResult GetUbseNumaInfoVecOffset(const std::unordered_map<UbseNumaLocation, UbseNumaInfo, UbseNumaLocation::Hash,
UbseNumaLocation::Equal>& numaInfos,
UbseSerialization& outStream)
{
outStream << (right_v<size_t>(numaInfos.size()));
for (auto numa : numaInfos) {
UbseSerialization item;
item << numa.first.nodeId << numa.first.numaId << numa.second.socketId << numa.second.bindCore
<< numa.second.size << numa.second.freeSize << numa.second.nr_hugepages_2M << numa.second.free_hugepages_2M
<< numa.second.timestamp << numa.second.nr_hugepages_1G << numa.second.free_hugepages_1G
<< numa.second.mempool_total << numa.second.mempool_used << numa.second.mempool_available_cleared
<< numa.second.mempool_available_uncleared << numa.second.nr_hugepages_512M
<< numa.second.free_hugepages_512M;
outStream << item;
if (!outStream.Check()) {
UBSE_LOG_ERROR << "Ubse serialize numa info vec failed";
return UBSE_ERROR;
}
}
return UBSE_OK;
}
UbseResult GetUbseCpuInfoOffset(
std::unordered_map<UbseCpuLocation, UbseCpuInfo, UbseCpuLocation::Hash, UbseCpuLocation::Equal> cpuInfos,
UbseSerialization& outStream)
{
outStream << (right_v<size_t>(cpuInfos.size()));
for (auto cpu : cpuInfos) {
UbseSerialization item;
item << cpu.first.nodeId << cpu.first.chipId << cpu.second.slotId << cpu.second.socketId
<< cpu.second.primaryEid << cpu.second.chipId << cpu.second.cardId << cpu.second.eid << cpu.second.guid
<< cpu.second.busNodeCna;
item << (right_v<size_t>(cpu.second.portInfos.size()));
for (auto portInfo : cpu.second.portInfos) {
UbseSerialization portItem;
portItem << portInfo.first << portInfo.second.ifName << portInfo.second.portRole
<< enum_v(portInfo.second.portStatus) << portInfo.second.portCna << portInfo.second.urmaEid
<< portInfo.second.remoteSlotId << portInfo.second.remoteChipId << portInfo.second.remoteCardId
<< portInfo.second.remoteIfName << portInfo.second.remotePortId;
item << portItem;
}
outStream << item;
if (!outStream.Check()) {
UBSE_LOG_ERROR << "Ubse serialize cpu info vec failed";
return UBSE_ERROR;
}
}
return UBSE_OK;
}
UbseResult GetUbseNodeInfoOffset(UbseNodeInfo info, UbseSerialization& outStream)
{
outStream << info.nodeId << info.slotId << info.bondingEid << info.hostName << info.comIp << info.guid
<< enum_v(info.allocator) << info.pmdMapping << info.blockSize << info.nodeMaxLendGb;
UbseSerialization ipAddrOffset;
auto ret = GetUbseIpAddrVecOffset(info.ipList, ipAddrOffset);
UbseSerialization numaInfoOffset;
ret |= GetUbseNumaInfoVecOffset(info.numaInfos, numaInfoOffset);
UbseSerialization cpuInfoOffset;
ret |= GetUbseCpuInfoOffset(info.cpuInfos, cpuInfoOffset);
outStream << ipAddrOffset << numaInfoOffset << cpuInfoOffset << enum_v(info.localState) << enum_v(info.clusterState)
<< info.eventMessage << info.isLender << enum_v(info.sysSentryState) << enum_v(info.obmmState);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "Ubse serialize node info data failed, " << FormatRetCode(ret);
return ret;
}
if (!outStream.Check()) {
UBSE_LOG_ERROR << "Ubse serialize node info check failed";
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t SerializeUbseNode(UbseNodeInfo info, uint8_t*& buffer, size_t& size)
{
UbseSerialization outStream;
auto ret = GetUbseNodeInfoOffset(info, outStream);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "Ubse serialize node info data failed";
return ret;
}
size = outStream.GetLength();
buffer = outStream.GetBuffer(true);
return UBSE_OK;
}
uint32_t SerializeUbseNodeList(std::vector<UbseNodeInfo> infos, uint8_t*& buffer, size_t& size)
{
UbseResult ret = UBSE_OK;
UbseSerialization outStream;
outStream << (right_v<size_t>(infos.size()));
for (size_t i = 0; i < infos.size(); i++) {
UbseSerialization item;
ret = GetUbseNodeInfoOffset(infos[i], item);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "Ubse serialize node info list[" << i << "] failed, " << FormatRetCode(ret);
return ret;
}
outStream << item;
if (!outStream.Check()) {
UBSE_LOG_ERROR << "Ubse serialize node info list[" << i << "] failed, " << FormatRetCode(ret);
return UBSE_ERROR;
}
}
size = outStream.GetLength();
buffer = outStream.GetBuffer(true);
return UBSE_OK;
}
uint32_t SerializeDevDirConnectInfo(std::map<std::string, PhysicalLink>& devDirConnectInfo, uint8_t*& buffer,
size_t& size)
{
UbseResult ret = UBSE_OK;
UbseSerialization outStream;
outStream << (right_v<size_t>(devDirConnectInfo.size()));
for (auto& physicalLinkInfo : devDirConnectInfo) {
std::string linkId = physicalLinkInfo.first;
PhysicalLink physicalLink = physicalLinkInfo.second;
outStream << linkId << physicalLink.slotId << physicalLink.chipId << physicalLink.portId
<< physicalLink.interfaceName << physicalLink.peerSlotId << physicalLink.peerChipId
<< physicalLink.peerPortId << physicalLink.peerInterfaceName << enum_v(physicalLink.linkStatus);
if (!outStream.Check()) {
UBSE_LOG_ERROR << "Ubse serialize devDirConnectInfo failed, " << FormatRetCode(ret);
return UBSE_ERROR;
}
}
size = outStream.GetLength();
buffer = outStream.GetBuffer(true);
return UBSE_OK;
}
template <typename IpAddrType>
UbseResult ValidateAndCopyIpData(const std::vector<uint8_t>& srcData, IpAddrType& destAddr, size_t expectedSize,
const char* ipTypeName)
{
if (srcData.size() != expectedSize) {
UBSE_LOG_ERROR << ipTypeName << " address size mismatch. Expected: " << expectedSize
<< ", Got: " << srcData.size();
return UBSE_ERROR;
}
std::copy(srcData.begin(), srcData.end(), destAddr.addr);
return UBSE_OK;
}
UbseResult SetUbseIpAddr(UbseDeSerialization& inStream, UbseIpAddr& addr)
{
std::vector<uint8_t> ipData{};
inStream >> enum_v(addr.type);
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Failed to deserialize IP type.";
return UBSE_ERROR;
}
inStream >> ipData;
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Failed to deserialize IP address data.";
return UBSE_ERROR;
}
switch (addr.type) {
case UbseIpType::UBSE_IP_V4:
return ValidateAndCopyIpData(ipData, addr.ipv4, IPV4_LENGTH, "IPv4");
case UbseIpType::UBSE_IP_V6:
return ValidateAndCopyIpData(ipData, addr.ipv6, IPV6_LENGTH, "IPv6");
default:
UBSE_LOG_ERROR << "Unsupported IP type: " << static_cast<int>(addr.type);
return UBSE_ERROR;
}
}
UbseResult ParseIpList(UbseDeSerialization& inStream, UbseNodeInfo& info)
{
size_t itemNum = 0;
inStream >> itemNum;
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize itemNum failed";
return UBSE_ERROR;
}
if (itemNum > MAX_IP_ADDR_NUM) {
UBSE_LOG_ERROR << "Ubse deserialize ip addr num exceed limit, itemNum=" << itemNum;
return UBSE_ERROR_INVAL;
}
UbseResult ret = UBSE_OK;
std::vector<UbseIpAddr> ipAddrVec{};
for (size_t i = 0; i < itemNum; i++) {
UbseDeSerialization item;
inStream >> item;
UbseIpAddr ipAddr{};
ret = SetUbseIpAddr(item, ipAddr);
if (!inStream.Check() || ret != UBSE_OK) {
UBSE_LOG_ERROR << "Ubse deserialize ubse ip addr vec failed, " << FormatRetCode(ret);
return ret;
}
ipAddrVec.push_back(ipAddr);
}
info.ipList = ipAddrVec;
return UBSE_OK;
}
uint32_t ParseNumaInfo(UbseDeSerialization& inStream, UbseNodeInfo& nodeInfo)
{
size_t itemNum = 0;
inStream >> itemNum;
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize itemNum failed";
return UBSE_ERROR;
}
for (size_t i = 0; i < itemNum; i++) {
UbseDeSerialization item;
inStream >> item;
UbseNumaLocation location{};
item >> location.nodeId >> location.numaId;
if (!item.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize numa location failed";
return UBSE_ERROR;
}
UbseNumaInfo info{};
info.location = location;
item >> info.socketId >> info.bindCore >> info.size >> info.freeSize >> info.nr_hugepages_2M >>
info.free_hugepages_2M >> info.timestamp >> info.nr_hugepages_1G >> info.free_hugepages_1G >>
info.mempool_total >> info.mempool_used >> info.mempool_available_cleared >>
info.mempool_available_uncleared >> info.nr_hugepages_512M >> info.free_hugepages_512M;
if (!item.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize numa info vec failed";
return UBSE_ERROR;
}
nodeInfo.numaInfos[location] = info;
}
return UBSE_OK;
}
uint32_t ParseCpuInfo(UbseDeSerialization& inStream, UbseNodeInfo& nodeInfo)
{
errno_t cpyRet = 0;
size_t itemNum = 0;
inStream >> itemNum;
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize itemNum failed";
return UBSE_ERROR;
}
for (size_t i = 0; i < itemNum; i++) {
UbseDeSerialization item;
inStream >> item;
UbseCpuLocation location{};
item >> location.nodeId >> location.chipId;
UbseCpuInfo info{};
item >> info.slotId;
item >> info.socketId;
std::string primaryEid;
item >> primaryEid;
cpyRet = strcpy_s(info.primaryEid, sizeof(info.primaryEid), primaryEid.c_str());
if (cpyRet != EOK) {
UBSE_LOG_ERROR << "cpy primary eid failed, ErrorCode=" << cpyRet;
return cpyRet;
}
item >> info.chipId >> info.cardId >> info.eid >> info.guid >> info.busNodeCna;
size_t portNum = 0;
item >> portNum;
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize cpu info vec failed";
return UBSE_ERROR;
}
for (size_t j = 0; j < portNum; j++) {
UbseDeSerialization port;
item >> port;
UbsePortInfo portInfo{};
port >> portInfo.portId >> portInfo.ifName >> portInfo.portRole >> enum_v(portInfo.portStatus) >>
portInfo.portCna >> portInfo.urmaEid >> portInfo.remoteSlotId >> portInfo.remoteChipId >>
portInfo.remoteCardId >> portInfo.remoteIfName >> portInfo.remotePortId;
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize portInfo failed";
return UBSE_ERROR;
}
info.portInfos[portInfo.portId] = portInfo;
}
nodeInfo.cpuInfos[location] = info;
}
return UBSE_OK;
}
uint32_t ParseNodeInfo(UbseNodeInfo& info, UbseDeSerialization& inStream)
{
inStream >> info.nodeId >> info.slotId;
std::string bondingEid;
inStream >> bondingEid;
auto cpyRet = strcpy_s(info.bondingEid, sizeof(info.bondingEid), bondingEid.c_str());
if (cpyRet != EOK) {
UBSE_LOG_ERROR << "cpy bonding eid failed, ErrorCode=" << cpyRet;
return cpyRet;
}
inStream >> info.hostName;
inStream >> info.comIp;
inStream >> info.guid;
inStream >> enum_v(info.allocator);
inStream >> info.pmdMapping;
inStream >> info.blockSize;
inStream >> info.nodeMaxLendGb;
if (!inStream.Check()) {
UBSE_LOG_WARN << "node info missing nodeMaxLendGb, likely old-version peer, nodeId=" << info.nodeId;
return UBSE_ERROR_DESERIALIZE_FAILED;
}
UbseDeSerialization ipAddrOffset;
UbseDeSerialization numaInfoOffset;
UbseDeSerialization cpuInfoOffset;
inStream >> ipAddrOffset >> numaInfoOffset >> cpuInfoOffset;
inStream >> enum_v(info.localState) >> enum_v(info.clusterState);
inStream >> info.eventMessage >> info.isLender >> enum_v(info.sysSentryState) >> enum_v(info.obmmState);
auto ret = ParseIpList(ipAddrOffset, info);
ret |= ParseNumaInfo(numaInfoOffset, info);
ret |= ParseCpuInfo(cpuInfoOffset, info);
return ret;
}
uint32_t DeSerializeUbseNode(UbseNodeInfo& info, uint8_t* buffer, size_t size)
{
UbseDeSerialization inStream(buffer, size);
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Deserialize mem node info failed";
return UBSE_ERROR;
}
return ParseNodeInfo(info, inStream);
}
uint32_t DeSerializeUbseNodeList(std::vector<UbseNodeInfo>& infos, uint8_t* buffer, size_t size)
{
UbseResult ret = UBSE_OK;
UbseDeSerialization inStream(buffer, size);
size_t num = 0;
inStream >> num;
infos.reserve(num);
if (!inStream.Check()) {
return UBSE_ERROR;
}
for (size_t i = 0; i < num; i++) {
UbseDeSerialization item;
inStream >> item;
UbseNodeInfo info{};
ret = ParseNodeInfo(info, item);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "Ubse deserialize node info list[" << i << "] failed, " << FormatRetCode(ret);
return ret;
}
infos.push_back(info);
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize node info list[" << i << "] failed, " << FormatRetCode(ret);
return UBSE_ERROR;
}
}
return UBSE_OK;
}
uint32_t DeSerializeDevDirConnectInfo(std::map<std::string, PhysicalLink>& devDirConnectInfo, uint8_t* buffer,
size_t size)
{
UbseResult ret = UBSE_OK;
UbseDeSerialization inStream(buffer, size);
size_t num = 0;
inStream >> num;
if (!inStream.Check()) {
return UBSE_ERROR;
}
for (size_t i = 0; i < num; i++) {
std::string linkId;
inStream >> linkId;
if (!inStream.Check()) {
return UBSE_ERROR;
}
auto& physicalLink = devDirConnectInfo[linkId];
inStream >> physicalLink.slotId >> physicalLink.chipId >> physicalLink.portId >> physicalLink.interfaceName >>
physicalLink.peerSlotId >> physicalLink.peerChipId >> physicalLink.peerPortId >>
physicalLink.peerInterfaceName;
inStream >> enum_v(physicalLink.linkStatus);
if (!inStream.Check()) {
UBSE_LOG_ERROR << "Ubse deserialize node info list[" << i << "] failed, " << FormatRetCode(ret);
return UBSE_ERROR;
}
}
return UBSE_OK;
}
uint32_t UbseGetNodeInfos(std::vector<NodeInfo>& nodeInfos)
{
auto nodeInfoMap = UbseNodeController::GetInstance().GetAllNodes();
if (nodeInfoMap.empty()) {
return UBSE_ERROR;
}
nodeInfos.reserve(nodeInfoMap.size());
for (const auto& [_, ubseNodeInfo] : nodeInfoMap) {
NodeInfo nodeInfo{};
nodeInfo.nodeId = ubseNodeInfo.nodeId;
nodeInfo.hostName = ubseNodeInfo.hostName;
for (const auto& ip : ubseNodeInfo.ipList) {
if (ip.type == UbseIpType::UBSE_IP_V4) {
nodeInfo.ipList.emplace_back(UbseNetUtil::Ipv4ArrToString(ip.ipv4.addr));
} else {
nodeInfo.ipList.emplace_back(UbseNetUtil::Ipv6ArrToString(ip.ipv6.addr));
}
}
nodeInfos.emplace_back(nodeInfo);
}
return UBSE_OK;
}
uint32_t UbseNodeGetNodeIdByHostname(const std::string& hostname, std::string& nodeId)
{
auto nodeInfoMap = UbseNodeController::GetInstance().GetAllNodes();
for (const auto& [_, nodeInfo] : nodeInfoMap) {
if (nodeInfo.hostName == hostname) {
nodeId = nodeInfo.nodeId;
return UBSE_OK;
}
}
return UBSE_ERROR;
}
bool parseIpString(const std::string& ipStr, UbseIpAddr& out)
{
in_addr ipv4{};
if (inet_pton(AF_INET, ipStr.c_str(), &ipv4) == 1) {
out.type = UbseIpType::UBSE_IP_V4;
auto err = memcpy_s(out.ipv4.addr, sizeof(out.ipv4.addr), &ipv4, NO_4);
if (err != EOK) {
UBSE_LOG_ERROR << "Mem copy failed, errno_t=" << err << ".";
return false;
}
return true;
}
in6_addr ipv6{};
if (inet_pton(AF_INET6, ipStr.c_str(), &ipv6) == 1) {
out.type = UbseIpType::UBSE_IP_V6;
auto err = memcpy_s(out.ipv6.addr, sizeof(out.ipv6.addr), &ipv6, NO_16);
if (err != EOK) {
UBSE_LOG_ERROR << "Mem copy failed, errno_t=" << err << ".";
return false;
}
return true;
}
return false;
}
bool isIpInList(const std::string& ipStr, const std::vector<UbseIpAddr>& ipList)
{
UbseIpAddr target{};
if (!parseIpString(ipStr, target)) {
return false;
}
for (const auto& ip : ipList) {
if (ip.type != target.type) {
continue;
}
if (ip.type == UbseIpType::UBSE_IP_V4) {
if (std::memcmp(ip.ipv4.addr, target.ipv4.addr, NO_4) == 0) {
return true;
}
} else {
if (std::memcmp(ip.ipv6.addr, target.ipv6.addr, NO_16) == 0) {
return true;
}
}
}
return false;
}
bool CheckGuid(const std::string& value, const std::pair<const std::string, UbseNodeInfo>& nodeInfo)
{
for (const auto& nodeData : nodeInfo.second.cpuInfos) {
if (value == nodeData.second.guid) {
return true;
}
}
return false;
}
uint32_t UbseGetNodeIdByAttrValue(const NodeAttr& attr, const std::string& value, uint32_t& nodeId)
{
std::unordered_map<std::string, UbseNodeInfo> nodeInfos = UbseNodeController::GetInstance().GetAllNodes();
for (const auto& nodeInfo : nodeInfos) {
if (attr == NodeAttr::Ip && isIpInList(value, nodeInfo.second.ipList)) {
nodeId = nodeInfo.second.slotId;
return UBSE_OK;
}
if (attr == NodeAttr::hostName && value == nodeInfo.second.hostName) {
nodeId = nodeInfo.second.slotId;
return UBSE_OK;
}
if (attr == NodeAttr::guid && CheckGuid(value, nodeInfo)) {
nodeId = nodeInfo.second.slotId;
return UBSE_OK;
}
}
UBSE_LOG_ERROR << "Failed to get node id. " << FormatRetCode(UBSE_ERROR);
nodeId = 0xFFFFFFFF;
return UBSE_ERROR;
}
uint32_t UbseNodeGetLinkUpNodes(std::vector<UbseRoleInfo>& roleInfos)
{
return UbseGetAllNodeInfos(roleInfos);
}
void UbseNodeController::RegisterHostBonding()
{
isHostUrmaDevOccupied = true;
}
bool UbseNodeController::IsHostBondingRegistered() const
{
return isHostUrmaDevOccupied;
}
UbseResult UbseNodeController::GetPlanningHostBondingByNodeId(const std::string& nodeId,
std::vector<UbseUrmaUvsNodeInfo>& hostUrmaInfos)
{
return UbseNodeComUrmaCollector::GetInstance().GetPlanningHostBondingByNodeId(nodeId, hostUrmaInfos);
}
}