fix: исправлены проблемы с пустыми данными в коллекторе proxcluster

- Исправлена проблема с nodes: null - добавлен fallback для получения информации о текущей ноде
- Исправлена проблема с пустым cluster_uuid - добавлен fallback при недоступности corosync.conf
- Убран хардкод IP адреса - теперь определяется автоматически
- Улучшена обработка ошибок - коллектор не падает при отсутствии pvecm или corosync.conf
- Добавлена логика определения локальной ноды через сравнение IP адресов

Автор: Сергей Антропов, сайт: https://devops.org.ru
This commit is contained in:
Sergey Antropoff 2025-09-11 17:01:55 +03:00
parent 71a20610fa
commit 471fde8696

View File

@ -45,7 +45,8 @@ func collectProxCluster(ctx context.Context) (map[string]any, error) {
// Собираем информацию о нодах // Собираем информацию о нодах
nodesInfo, err := collectDetailedNodesInfo(ctx, clusterName, clusterUUID) nodesInfo, err := collectDetailedNodesInfo(ctx, clusterName, clusterUUID)
if err != nil { if err != nil {
return nil, err // Если не удалось собрать информацию о нодах, используем пустой массив
nodesInfo = []map[string]any{}
} }
// Создаем блок summary с точной структурой // Создаем блок summary с точной структурой
@ -108,7 +109,13 @@ func collectClusterInfo(ctx context.Context) (map[string]any, error) {
clusterName, clusterUUID, err := parseCorosyncConf(corosyncPath) clusterName, clusterUUID, err := parseCorosyncConf(corosyncPath)
if err != nil { if err != nil {
return result, fmt.Errorf("failed to parse corosync.conf: %w", err) // Если не удалось прочитать corosync.conf, пробуем получить информацию другими способами
if hostname, err := os.Hostname(); err == nil {
clusterName = hostname
} else {
clusterName = "unknown-cluster"
}
clusterUUID = ""
} }
result["name"] = clusterName result["name"] = clusterName
@ -523,14 +530,50 @@ func collectDetailedNodesInfo(ctx context.Context, clusterName, clusterUUID stri
// Объединяем данные // Объединяем данные
combinedNodes := combineNodeInfo(nodesData, statusData) combinedNodes := combineNodeInfo(nodesData, statusData)
// Если не удалось получить данные через pvecm, создаем информацию о текущей ноде
if len(combinedNodes) == 0 {
if hostname, err := os.Hostname(); err == nil {
// Получаем IP адрес текущей ноды
var nodeIP string
if data, err := os.ReadFile("/proc/net/route"); err == nil {
// Простая логика для получения IP
if out, err := exec.CommandContext(ctx, "hostname", "-I").Output(); err == nil {
ips := strings.Fields(string(out))
if len(ips) > 0 {
nodeIP = ips[0]
}
}
}
combinedNodes = []NodeInfo{
{
NodeID: 1,
Votes: 1,
Name: hostname,
IP: nodeIP,
},
}
}
}
// Обрабатываем объединенные данные // Обрабатываем объединенные данные
for _, nodeInfo := range combinedNodes { for _, nodeInfo := range combinedNodes {
nodeID := fmt.Sprintf("%08x", nodeInfo.NodeID) nodeID := fmt.Sprintf("%08x", nodeInfo.NodeID)
nodeName := nodeInfo.Name nodeName := nodeInfo.Name
nodeIP := nodeInfo.IP nodeIP := nodeInfo.IP
// Определяем, является ли нода локальной // Определяем, является ли нода локальной (сравниваем с IP текущей ноды)
isLocal := strings.Contains(nodeIP, "10.14.88.12") // IP локальной ноды isLocal := false
if out, err := exec.CommandContext(ctx, "hostname", "-I").Output(); err == nil {
currentIPs := strings.Fields(string(out))
for _, currentIP := range currentIPs {
if currentIP == nodeIP {
isLocal = true
break
}
}
}
if isLocal { if isLocal {
// Для локальной ноды получаем имя хоста // Для локальной ноды получаем имя хоста
if hostname, err := os.Hostname(); err == nil { if hostname, err := os.Hostname(); err == nil {