Исправлен парсинг данных в коллекторе proxcluster
- Исправлен парсинг /etc/pve/.members - теперь правильно обрабатывает JSON структуру - Улучшен парсинг corosync.conf для извлечения имен нод - Исправлено определение онлайн статуса нод (поддержка разных форматов статуса) - Добавлена отладочная информация для диагностики проблем - Исправлена проблема с неправильными именами нод в выводе Автор: Сергей Антропов, сайт: https://devops.org.ru
This commit is contained in:
parent
bb966dcea2
commit
17f5a04c9e
@ -615,22 +615,45 @@ func getCorosyncInfo(ctx context.Context) (map[string]interface{}, error) {
|
||||
func getClusterMembers() ([]string, error) {
|
||||
data, err := os.ReadFile("/etc/pve/.members")
|
||||
if err != nil {
|
||||
debugLog("Failed to read /etc/pve/.members: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Парсим JSON
|
||||
var members []string
|
||||
if err := json.Unmarshal(data, &members); err != nil {
|
||||
// Если не JSON, пробуем построчно
|
||||
lines := strings.Split(string(data), "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line != "" {
|
||||
members = append(members, line)
|
||||
debugLog("Raw .members data: %s", string(data))
|
||||
|
||||
// Пробуем парсить как JSON объект
|
||||
var membersData map[string]interface{}
|
||||
if err := json.Unmarshal(data, &membersData); err == nil {
|
||||
debugLog("Parsed .members as JSON object")
|
||||
// Если это JSON объект, извлекаем имена нод из nodelist
|
||||
if nodelist, ok := membersData["nodelist"].(map[string]interface{}); ok {
|
||||
var members []string
|
||||
for nodeName := range nodelist {
|
||||
members = append(members, nodeName)
|
||||
debugLog("Found node in nodelist: %s", nodeName)
|
||||
}
|
||||
return members, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Пробуем парсить как JSON массив
|
||||
var members []string
|
||||
if err := json.Unmarshal(data, &members); err == nil {
|
||||
debugLog("Parsed .members as JSON array with %d members", len(members))
|
||||
return members, nil
|
||||
}
|
||||
|
||||
debugLog("Failed to parse as JSON, trying line by line")
|
||||
// Если не JSON, пробуем построчно
|
||||
lines := strings.Split(string(data), "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line != "" {
|
||||
members = append(members, line)
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("Parsed %d members from lines", len(members))
|
||||
return members, nil
|
||||
}
|
||||
|
||||
@ -642,7 +665,6 @@ func getNodeIDsFromCorosync(confPath string, members []string) (map[string]int,
|
||||
}
|
||||
|
||||
nodeIDs := make(map[string]int)
|
||||
content := string(data)
|
||||
|
||||
// Пробуем парсить как JSON сначала
|
||||
var jsonData map[string]interface{}
|
||||
@ -661,6 +683,7 @@ func getNodeIDsFromCorosync(confPath string, members []string) (map[string]int,
|
||||
}
|
||||
|
||||
// Если не JSON, используем regex для текстового формата
|
||||
content := string(data)
|
||||
for _, member := range members {
|
||||
// Ищем блок node { ... nodeid: X ... name: member }
|
||||
re := regexp.MustCompile(`node\s*{[^}]*name:\s*` + member + `[^}]*nodeid:\s*([0-9]+)`)
|
||||
@ -755,23 +778,44 @@ func checkNodeOnline(ctx context.Context, nodeName string) (bool, error) {
|
||||
cmd := exec.CommandContext(ctx, "pvesh", "get", "/nodes", "--output-format", "json")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
debugLog("Failed to get nodes list: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
debugLog("Raw pvesh nodes output: %s", string(out))
|
||||
|
||||
var nodes []map[string]interface{}
|
||||
if err := json.Unmarshal(out, &nodes); err != nil {
|
||||
debugLog("Failed to parse nodes JSON: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
debugLog("Found %d nodes in pvesh output", len(nodes))
|
||||
|
||||
// Ищем нашу ноду в списке
|
||||
for _, node := range nodes {
|
||||
if name, ok := node["node"].(string); ok && name == nodeName {
|
||||
debugLog("Found node %s in pvesh output", nodeName)
|
||||
// Проверяем разные варианты статуса
|
||||
if status, ok := node["status"].(string); ok {
|
||||
debugLog("Node %s status (string): %s", nodeName, status)
|
||||
return status == "online", nil
|
||||
}
|
||||
// Проверяем числовой статус (1 = online, 0 = offline)
|
||||
if status, ok := node["status"].(float64); ok {
|
||||
debugLog("Node %s status (float64): %f", nodeName, status)
|
||||
return status == 1, nil
|
||||
}
|
||||
// Проверяем булевый статус
|
||||
if status, ok := node["status"].(bool); ok {
|
||||
debugLog("Node %s status (bool): %t", nodeName, status)
|
||||
return status, nil
|
||||
}
|
||||
debugLog("Node %s found but status field is unknown type", nodeName)
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("Node %s not found in pvesh output", nodeName)
|
||||
return false, fmt.Errorf("node %s not found", nodeName)
|
||||
}
|
||||
|
||||
@ -918,3 +962,10 @@ func parseNumber(s string) int {
|
||||
|
||||
return num
|
||||
}
|
||||
|
||||
// debugLog выводит отладочную информацию (только если установлена переменная окружения DEBUG=1)
|
||||
func debugLog(format string, args ...interface{}) {
|
||||
if os.Getenv("DEBUG") == "1" {
|
||||
fmt.Fprintf(os.Stderr, "[DEBUG] "+format+"\n", args...)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user