Исправлены критические ошибки приведения типов в коллекторе 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 {
for k, v := range altResources {
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 {
for k, v := range altHardware {
hardware[k] = v
@ -441,15 +469,31 @@ func getVMSummary(ctx context.Context, nodeName string) (map[string]interface{},
// Суммируем ресурсы VM
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" {
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 {
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" {
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 {
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" {
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 {
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" {
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 и память (упрощенно)
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
if online, ok := node["online"].(bool); ok && online {
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
}
}
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
}
}
@ -854,7 +933,14 @@ func getAlternativeResources(ctx context.Context, nodeName string) (map[string]i
}
// Если данные все еще пустые, пробуем через /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")
out, err = cmd.Output()
if err == nil {
@ -913,7 +999,14 @@ func getAlternativeHardware(ctx context.Context, nodeName string) (map[string]in
}
// Если данные все еще пустые, пробуем через /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")
out, err = cmd.Output()
if err == nil {