Исправлен парсинг данных в коллекторе 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) {
|
func getClusterMembers() ([]string, error) {
|
||||||
data, err := os.ReadFile("/etc/pve/.members")
|
data, err := os.ReadFile("/etc/pve/.members")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
debugLog("Failed to read /etc/pve/.members: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Парсим JSON
|
debugLog("Raw .members data: %s", string(data))
|
||||||
var members []string
|
|
||||||
if err := json.Unmarshal(data, &members); err != nil {
|
// Пробуем парсить как JSON объект
|
||||||
// Если не JSON, пробуем построчно
|
var membersData map[string]interface{}
|
||||||
lines := strings.Split(string(data), "\n")
|
if err := json.Unmarshal(data, &membersData); err == nil {
|
||||||
for _, line := range lines {
|
debugLog("Parsed .members as JSON object")
|
||||||
line = strings.TrimSpace(line)
|
// Если это JSON объект, извлекаем имена нод из nodelist
|
||||||
if line != "" {
|
if nodelist, ok := membersData["nodelist"].(map[string]interface{}); ok {
|
||||||
members = append(members, line)
|
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
|
return members, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,7 +665,6 @@ func getNodeIDsFromCorosync(confPath string, members []string) (map[string]int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nodeIDs := make(map[string]int)
|
nodeIDs := make(map[string]int)
|
||||||
content := string(data)
|
|
||||||
|
|
||||||
// Пробуем парсить как JSON сначала
|
// Пробуем парсить как JSON сначала
|
||||||
var jsonData map[string]interface{}
|
var jsonData map[string]interface{}
|
||||||
@ -661,6 +683,7 @@ func getNodeIDsFromCorosync(confPath string, members []string) (map[string]int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Если не JSON, используем regex для текстового формата
|
// Если не JSON, используем regex для текстового формата
|
||||||
|
content := string(data)
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
// Ищем блок node { ... nodeid: X ... name: member }
|
// Ищем блок node { ... nodeid: X ... name: member }
|
||||||
re := regexp.MustCompile(`node\s*{[^}]*name:\s*` + member + `[^}]*nodeid:\s*([0-9]+)`)
|
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")
|
cmd := exec.CommandContext(ctx, "pvesh", "get", "/nodes", "--output-format", "json")
|
||||||
out, err := cmd.Output()
|
out, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
debugLog("Failed to get nodes list: %v", err)
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugLog("Raw pvesh nodes output: %s", string(out))
|
||||||
|
|
||||||
var nodes []map[string]interface{}
|
var nodes []map[string]interface{}
|
||||||
if err := json.Unmarshal(out, &nodes); err != nil {
|
if err := json.Unmarshal(out, &nodes); err != nil {
|
||||||
|
debugLog("Failed to parse nodes JSON: %v", err)
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugLog("Found %d nodes in pvesh output", len(nodes))
|
||||||
|
|
||||||
// Ищем нашу ноду в списке
|
// Ищем нашу ноду в списке
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if name, ok := node["node"].(string); ok && name == nodeName {
|
if name, ok := node["node"].(string); ok && name == nodeName {
|
||||||
|
debugLog("Found node %s in pvesh output", nodeName)
|
||||||
|
// Проверяем разные варианты статуса
|
||||||
if status, ok := node["status"].(string); ok {
|
if status, ok := node["status"].(string); ok {
|
||||||
|
debugLog("Node %s status (string): %s", nodeName, status)
|
||||||
return status == "online", nil
|
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)
|
return false, fmt.Errorf("node %s not found", nodeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,3 +962,10 @@ func parseNumber(s string) int {
|
|||||||
|
|
||||||
return num
|
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