Исправлены критические ошибки приведения типов в коллекторе proxcluster

- Исправлена ошибка 'interface conversion: interface {} is int, not float64'
- Добавлено безопасное приведение типов для всех операций с interface{}
- Исправлены проблемы в функциях getAlternativeResources, getAlternativeHardware, getVMSummary, calculateClusterResources
- Добавлена поддержка как int, так и float64 типов из JSON
- Улучшена стабильность работы коллектора

Автор: Сергей Антропов, сайт: https://devops.org.ru
This commit is contained in:
Sergey Antropoff 2025-09-11 19:00:15 +03:00
parent 17f5a04c9e
commit c3a81d963f

View File

@ -342,7 +342,21 @@ func getNodeDetails(ctx context.Context, nodeName string) (map[string]interface{
} }
// Если данные о ресурсах пустые, пробуем альтернативные методы // Если данные о ресурсах пустые, пробуем альтернативные методы
if resources["cpu_usage_percent"].(float64) == 0 && resources["memory_used_mb"].(int) == 0 { cpuUsage := 0.0
if val, ok := resources["cpu_usage_percent"].(float64); ok {
cpuUsage = val
} else if val, ok := resources["cpu_usage_percent"].(int); ok {
cpuUsage = float64(val)
}
memoryUsed := 0
if val, ok := resources["memory_used_mb"].(int); ok {
memoryUsed = val
} else if val, ok := resources["memory_used_mb"].(float64); ok {
memoryUsed = int(val)
}
if cpuUsage == 0 && memoryUsed == 0 {
if altResources, err := getAlternativeResources(ctx, nodeName); err == nil { if altResources, err := getAlternativeResources(ctx, nodeName); err == nil {
for k, v := range altResources { for k, v := range altResources {
resources[k] = v resources[k] = v
@ -371,7 +385,21 @@ func getNodeDetails(ctx context.Context, nodeName string) (map[string]interface{
} }
// Если данные о железе пустые, пробуем альтернативные методы // Если данные о железе пустые, пробуем альтернативные методы
if hardware["cpu_cores"].(int) == 0 && hardware["memory_total_mb"].(int) == 0 { cpuCores := 0
if val, ok := hardware["cpu_cores"].(int); ok {
cpuCores = val
} else if val, ok := hardware["cpu_cores"].(float64); ok {
cpuCores = int(val)
}
memoryTotal := 0
if val, ok := hardware["memory_total_mb"].(int); ok {
memoryTotal = val
} else if val, ok := hardware["memory_total_mb"].(float64); ok {
memoryTotal = int(val)
}
if cpuCores == 0 && memoryTotal == 0 {
if altHardware, err := getAlternativeHardware(ctx, nodeName); err == nil { if altHardware, err := getAlternativeHardware(ctx, nodeName); err == nil {
for k, v := range altHardware { for k, v := range altHardware {
hardware[k] = v hardware[k] = v
@ -441,15 +469,31 @@ func getVMSummary(ctx context.Context, nodeName string) (map[string]interface{},
// Суммируем ресурсы VM // Суммируем ресурсы VM
if cpus, ok := vm["cpus"].(float64); ok { if cpus, ok := vm["cpus"].(float64); ok {
result["total_cpu_cores"] = result["total_cpu_cores"].(int) + int(cpus) totalCores := 0
if val, ok := result["total_cpu_cores"].(int); ok {
totalCores = val
}
result["total_cpu_cores"] = totalCores + int(cpus)
if status, ok := vm["status"].(string); ok && status == "running" { if status, ok := vm["status"].(string); ok && status == "running" {
result["used_cpu_cores"] = result["used_cpu_cores"].(int) + int(cpus) usedCores := 0
if val, ok := result["used_cpu_cores"].(int); ok {
usedCores = val
}
result["used_cpu_cores"] = usedCores + int(cpus)
} }
} }
if mem, ok := vm["maxmem"].(float64); ok { if mem, ok := vm["maxmem"].(float64); ok {
result["total_memory_mb"] = result["total_memory_mb"].(int) + int(mem/1024/1024) totalMem := 0
if val, ok := result["total_memory_mb"].(int); ok {
totalMem = val
}
result["total_memory_mb"] = totalMem + int(mem/1024/1024)
if status, ok := vm["status"].(string); ok && status == "running" { if status, ok := vm["status"].(string); ok && status == "running" {
result["used_memory_mb"] = result["used_memory_mb"].(int) + int(mem/1024/1024) usedMem := 0
if val, ok := result["used_memory_mb"].(int); ok {
usedMem = val
}
result["used_memory_mb"] = usedMem + int(mem/1024/1024)
} }
} }
} }
@ -474,15 +518,31 @@ func getVMSummary(ctx context.Context, nodeName string) (map[string]interface{},
// Суммируем ресурсы контейнеров // Суммируем ресурсы контейнеров
if cpus, ok := container["cpus"].(float64); ok { if cpus, ok := container["cpus"].(float64); ok {
result["total_cpu_cores"] = result["total_cpu_cores"].(int) + int(cpus) totalCores := 0
if val, ok := result["total_cpu_cores"].(int); ok {
totalCores = val
}
result["total_cpu_cores"] = totalCores + int(cpus)
if status, ok := container["status"].(string); ok && status == "running" { if status, ok := container["status"].(string); ok && status == "running" {
result["used_cpu_cores"] = result["used_cpu_cores"].(int) + int(cpus) usedCores := 0
if val, ok := result["used_cpu_cores"].(int); ok {
usedCores = val
}
result["used_cpu_cores"] = usedCores + int(cpus)
} }
} }
if mem, ok := container["maxmem"].(float64); ok { if mem, ok := container["maxmem"].(float64); ok {
result["total_memory_mb"] = result["total_memory_mb"].(int) + int(mem/1024/1024) totalMem := 0
if val, ok := result["total_memory_mb"].(int); ok {
totalMem = val
}
result["total_memory_mb"] = totalMem + int(mem/1024/1024)
if status, ok := container["status"].(string); ok && status == "running" { if status, ok := container["status"].(string); ok && status == "running" {
result["used_memory_mb"] = result["used_memory_mb"].(int) + int(mem/1024/1024) usedMem := 0
if val, ok := result["used_memory_mb"].(int); ok {
usedMem = val
}
result["used_memory_mb"] = usedMem + int(mem/1024/1024)
} }
} }
} }
@ -522,19 +582,38 @@ func calculateClusterResources(nodes []map[string]interface{}) map[string]interf
// Агрегируем CPU и память (упрощенно) // Агрегируем CPU и память (упрощенно)
if hardware, ok := node["hardware"].(map[string]interface{}); ok { if hardware, ok := node["hardware"].(map[string]interface{}); ok {
if cores, ok := hardware["cpu_cores"].(int); ok { cores := 0
if val, ok := hardware["cpu_cores"].(int); ok {
cores = val
} else if val, ok := hardware["cpu_cores"].(float64); ok {
cores = int(val)
}
if cores > 0 {
totalCores += cores totalCores += cores
if online, ok := node["online"].(bool); ok && online { if online, ok := node["online"].(bool); ok && online {
onlineCores += cores onlineCores += cores
} }
} }
if memory, ok := hardware["memory_total_mb"].(int); ok {
memory := 0
if val, ok := hardware["memory_total_mb"].(int); ok {
memory = val
} else if val, ok := hardware["memory_total_mb"].(float64); ok {
memory = int(val)
}
if memory > 0 {
totalMemory += memory totalMemory += memory
} }
} }
if resources, ok := node["resources"].(map[string]interface{}); ok { if resources, ok := node["resources"].(map[string]interface{}); ok {
if used, ok := resources["memory_used_mb"].(int); ok { used := 0
if val, ok := resources["memory_used_mb"].(int); ok {
used = val
} else if val, ok := resources["memory_used_mb"].(float64); ok {
used = int(val)
}
if used > 0 {
usedMemory += used usedMemory += used
} }
} }
@ -854,7 +933,14 @@ func getAlternativeResources(ctx context.Context, nodeName string) (map[string]i
} }
// Если данные все еще пустые, пробуем через /nodes/{node}/capabilities // Если данные все еще пустые, пробуем через /nodes/{node}/capabilities
if result["cpu_usage_percent"].(float64) == 0 { cpuUsage := 0.0
if val, ok := result["cpu_usage_percent"].(float64); ok {
cpuUsage = val
} else if val, ok := result["cpu_usage_percent"].(int); ok {
cpuUsage = float64(val)
}
if cpuUsage == 0 {
cmd = exec.CommandContext(ctx, "pvesh", "get", "/nodes/"+nodeName+"/capabilities", "--output-format", "json") cmd = exec.CommandContext(ctx, "pvesh", "get", "/nodes/"+nodeName+"/capabilities", "--output-format", "json")
out, err = cmd.Output() out, err = cmd.Output()
if err == nil { if err == nil {
@ -913,7 +999,14 @@ func getAlternativeHardware(ctx context.Context, nodeName string) (map[string]in
} }
// Если данные все еще пустые, пробуем через /nodes/{node}/hardware // Если данные все еще пустые, пробуем через /nodes/{node}/hardware
if result["cpu_cores"].(int) == 0 { cpuCores := 0
if val, ok := result["cpu_cores"].(int); ok {
cpuCores = val
} else if val, ok := result["cpu_cores"].(float64); ok {
cpuCores = int(val)
}
if cpuCores == 0 {
cmd = exec.CommandContext(ctx, "pvesh", "get", "/nodes/"+nodeName+"/hardware", "--output-format", "json") cmd = exec.CommandContext(ctx, "pvesh", "get", "/nodes/"+nodeName+"/hardware", "--output-format", "json")
out, err = cmd.Output() out, err = cmd.Output()
if err == nil { if err == nil {