feat: реализована новая логика получения machine_uid для QEMU и LXC
- Для QEMU VM: получение UUID из конфигурации (uuid, smbios1 uuid) с fallback на machine_id - Для LXC контейнеров: получение machine-id через pct exec (запущенные) или чтение из rootfs (остановленные) - Добавлены функции getLXCMachineIDViaExec и getLXCMachineIDFromRootfs - Улучшена логика fallback для случаев когда UUID недоступен - Все machine_uid генерируются как SHA256[:16] для консистентности - Протестировано на реальных VM и контейнерах
This commit is contained in:
parent
96b841d6c8
commit
b23d724bea
@ -279,24 +279,8 @@ func processQEMUVM(vm VM, nodeName, clusterUID, nodeUID string) map[string]any {
|
|||||||
machineID = "unknown"
|
machineID = "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Для QEMU VM пытаемся получить UUID из smbios1
|
// Генерируем machine_uid
|
||||||
var machineUID string
|
machineUID := generateMachineUID("QEMU", vmidStr, config)
|
||||||
if smbiosUUID := getString(config, "smbios1"); smbiosUUID != "" {
|
|
||||||
// Извлекаем UUID из строки типа "uuid=5325693e-271b-47ed-95c2-3a2cf42f4886"
|
|
||||||
if strings.Contains(smbiosUUID, "uuid=") {
|
|
||||||
parts := strings.Split(smbiosUUID, "uuid=")
|
|
||||||
if len(parts) > 1 {
|
|
||||||
uuid := strings.TrimSpace(parts[1])
|
|
||||||
machineUID = generateMachineUID(uuid)
|
|
||||||
} else {
|
|
||||||
machineUID = generateMachineUID(machineID)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
machineUID = generateMachineUID(machineID)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
machineUID = generateMachineUID(machineID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаем структуру VM
|
// Создаем структуру VM
|
||||||
vmData := map[string]any{
|
vmData := map[string]any{
|
||||||
@ -396,7 +380,7 @@ func processLXCContainer(ct VM, nodeName, clusterUID, nodeUID string) map[string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Генерируем machine_uid
|
// Генерируем machine_uid
|
||||||
machineUID := generateMachineUID(machineID)
|
machineUID := generateMachineUID("LXC", vmidStr, config)
|
||||||
|
|
||||||
// Создаем структуру контейнера
|
// Создаем структуру контейнера
|
||||||
ctData := map[string]any{
|
ctData := map[string]any{
|
||||||
@ -573,13 +557,123 @@ func generateNodeUID(clusterUUID, nodeID string) string {
|
|||||||
return hex.EncodeToString(hash[:])[:16]
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateMachineUID создает уникальный ID машины на основе machine_id
|
// generateMachineUID генерирует уникальный ID машины для QEMU и LXC
|
||||||
func generateMachineUID(machineID string) string {
|
func generateMachineUID(vmType, vmid string, config map[string]interface{}) string {
|
||||||
if machineID == "" {
|
if vmType == "QEMU" {
|
||||||
machineID = "unknown-machine-id"
|
return generateQEMUMachineUID(vmid, config)
|
||||||
|
} else if vmType == "LXC" {
|
||||||
|
return generateLXCMachineUID(vmid, config)
|
||||||
}
|
}
|
||||||
hash := sha256.Sum256([]byte(machineID))
|
return ""
|
||||||
return hex.EncodeToString(hash[:])[:16]
|
}
|
||||||
|
|
||||||
|
// generateQEMUMachineUID генерирует machine_uid для QEMU VM
|
||||||
|
func generateQEMUMachineUID(vmid string, config map[string]interface{}) string {
|
||||||
|
// 1. Пытаемся получить uuid из конфигурации
|
||||||
|
if uuid, ok := config["uuid"].(string); ok && uuid != "" {
|
||||||
|
hash := sha256.Sum256([]byte(uuid))
|
||||||
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Пытаемся получить smbios1 uuid из конфигурации
|
||||||
|
if smbios1, ok := config["smbios1"].(string); ok && smbios1 != "" {
|
||||||
|
// Парсим smbios1 для поиска uuid
|
||||||
|
if parsed := parseKeyValueString(smbios1); parsed != nil {
|
||||||
|
if uuid, exists := parsed["uuid"]; exists {
|
||||||
|
if uuidStr, ok := uuid.(string); ok && uuidStr != "" {
|
||||||
|
hash := sha256.Sum256([]byte(uuidStr))
|
||||||
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Fallback: используем machine_id
|
||||||
|
if machineID, ok := config["machine_id"].(string); ok && machineID != "" {
|
||||||
|
hash := sha256.Sum256([]byte(machineID))
|
||||||
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateLXCMachineUID генерирует machine_uid для LXC контейнера
|
||||||
|
func generateLXCMachineUID(vmid string, config map[string]interface{}) string {
|
||||||
|
// 1. Пытаемся получить machine-id из конфигурации
|
||||||
|
if machineID, ok := config["machine_id"].(string); ok && machineID != "" {
|
||||||
|
hash := sha256.Sum256([]byte(machineID))
|
||||||
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Пытаемся получить machine-id через pct exec (если контейнер запущен)
|
||||||
|
if machineID := getLXCMachineIDViaExec(vmid); machineID != "" {
|
||||||
|
hash := sha256.Sum256([]byte(machineID))
|
||||||
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Пытаемся прочитать machine-id из rootfs (если контейнер остановлен)
|
||||||
|
if machineID := getLXCMachineIDFromRootfs(vmid); machineID != "" {
|
||||||
|
hash := sha256.Sum256([]byte(machineID))
|
||||||
|
return hex.EncodeToString(hash[:])[:16]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLXCMachineIDViaExec получает machine-id через pct exec (для запущенных контейнеров)
|
||||||
|
func getLXCMachineIDViaExec(vmid string) string {
|
||||||
|
cmd := exec.Command("pct", "exec", vmid, "--", "cat", "/etc/machine-id")
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
debugLog("Failed to get machine-id via pct exec for LXC %s: %v", vmid, err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
machineID := strings.TrimSpace(string(output))
|
||||||
|
if machineID == "" {
|
||||||
|
debugLog("Empty machine-id from pct exec for LXC %s", vmid)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
debugLog("Successfully got machine-id via pct exec for LXC %s: %s", vmid, machineID)
|
||||||
|
return machineID
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLXCMachineIDFromRootfs читает machine-id из rootfs (для остановленных контейнеров)
|
||||||
|
func getLXCMachineIDFromRootfs(vmid string) string {
|
||||||
|
// Пробуем разные возможные пути
|
||||||
|
paths := []string{
|
||||||
|
fmt.Sprintf("/var/lib/lxc/%s/rootfs/etc/machine-id", vmid),
|
||||||
|
fmt.Sprintf("/rpool/data/subvol-%s-disk-0/etc/machine-id", vmid),
|
||||||
|
fmt.Sprintf("/var/lib/lxc/%s/rootfs/var/lib/dbus/machine-id", vmid),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range paths {
|
||||||
|
if machineID := readMachineIDFromFile(path); machineID != "" {
|
||||||
|
debugLog("Successfully read machine-id from %s for LXC %s: %s", path, vmid, machineID)
|
||||||
|
return machineID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugLog("Failed to read machine-id from rootfs for LXC %s", vmid)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// readMachineIDFromFile читает machine-id из файла
|
||||||
|
func readMachineIDFromFile(path string) string {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
debugLog("Failed to read file %s: %v", path, err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
machineID := strings.TrimSpace(string(data))
|
||||||
|
if machineID == "" {
|
||||||
|
debugLog("Empty machine-id in file %s", path)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return machineID
|
||||||
}
|
}
|
||||||
|
|
||||||
// getString извлекает строку из map[string]interface{}
|
// getString извлекает строку из map[string]interface{}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user