From afff0145f30bc70a29873569739895398e2a2d2f Mon Sep 17 00:00:00 2001 From: Bella Khizgiyaev Date: Mon, 2 Sep 2024 16:59:02 +0300 Subject: [PATCH] Change VM customization to use a YAML output file instead of XML. As part of the virt-v2v migration, we inspect the OS type and disk paths. Until now, this has been done with the XML output file. Due to the change to YAML format, this process needs to be adapted as well. Since we cannot use external libraries in the virt-v2v directory, it was implemented using bufio. Signed-off-by: Bella Khizgiyaev --- virt-v2v/cold/entrypoint.go | 36 +++++----- virt-v2v/cold/xml-reader.go | 132 +++++++++++++++--------------------- 2 files changed, 71 insertions(+), 97 deletions(-) diff --git a/virt-v2v/cold/entrypoint.go b/virt-v2v/cold/entrypoint.go index 46aaf6bba..e8cc0cdd1 100644 --- a/virt-v2v/cold/entrypoint.go +++ b/virt-v2v/cold/entrypoint.go @@ -82,18 +82,18 @@ func main() { } } -func getVmDiskPaths(domain *OvaVmconfig) []string { - var resp []string - for _, disk := range domain.Devices.Disks { - if disk.Source.File != "" { - resp = append(resp, disk.Source.File) - } - } - return resp -} - -func customizeVM(source string, xmlFilePath string) error { - domain, err := GetDomainFromXml(xmlFilePath) +// func getVmDiskPaths(vmConfig *VmConfig) []string { +// var resp []string +// for _, disk := range vmConfig.DiskPaths { +// if disk != "" { +// resp = append(resp, disk) +// } +// } +// return resp +// } + +func customizeVM(source string, yamlFilePath string) error { + vmConfig, err := GetVmConfigYaml(yamlFilePath) if err != nil { fmt.Printf("Error mapping xml to domain: %v\n", err) @@ -102,7 +102,7 @@ func customizeVM(source string, xmlFilePath string) error { } // Get operating system. - operatingSystem := domain.Metadata.LibOsInfo.V2VOS.ID + operatingSystem := vmConfig.OSInfo if operatingSystem == "" { fmt.Printf("Warning: no operating system found") @@ -112,15 +112,13 @@ func customizeVM(source string, xmlFilePath string) error { fmt.Printf("Operating System ID: %s\n", operatingSystem) } - // Get domain disks. - disks := getVmDiskPaths(domain) - if len(disks) == 0 { + if len(vmConfig.DiskPaths) == 0 { fmt.Printf("Warning: no V2V domain disks found") // No customization when no disks found. return nil } else { - fmt.Printf("V2V domain disks: %v\n", disks) + fmt.Printf("V2V domain disks: %v\n", vmConfig.DiskPaths) } // Customization for vSphere source. @@ -129,7 +127,7 @@ func customizeVM(source string, xmlFilePath string) error { if strings.Contains(operatingSystem, "win") { t := EmbedTool{filesystem: &scriptFS} - err = CustomizeWindows(disks, DIR, &t) + err = CustomizeWindows(vmConfig.DiskPaths, DIR, &t) if err != nil { fmt.Println("Error customizing disk image:", err) return err @@ -140,7 +138,7 @@ func customizeVM(source string, xmlFilePath string) error { if !strings.Contains(operatingSystem, "win") { t := EmbedTool{filesystem: &scriptFS} - err = CustomizeLinux(CustomizeDomainExec, disks, DIR, &t) + err = CustomizeLinux(CustomizeDomainExec, vmConfig.DiskPaths, DIR, &t) if err != nil { fmt.Println("Error customizing disk image:", err) return err diff --git a/virt-v2v/cold/xml-reader.go b/virt-v2v/cold/xml-reader.go index 07aadc656..4bc27cae7 100644 --- a/virt-v2v/cold/xml-reader.go +++ b/virt-v2v/cold/xml-reader.go @@ -1,97 +1,73 @@ package main import ( - "encoding/xml" + "bufio" "fmt" "os" + "strings" ) -type OvaVmconfig struct { - XMLName xml.Name `xml:"domain"` - Name string `xml:"name"` - OS OS `xml:"os"` - Metadata Metadata `xml:"metadata"` - Devices Devices `xml:"devices"` +type VmConfig struct { + OSInfo string + DiskPaths []string } -type OS struct { - Type OSType `xml:"type"` - Loader Loader `xml:"loader"` - Nvram Nvram `xml:"nvram"` -} - -type Metadata struct { - LibOsInfo LibOsInfo `xml:"libosinfo"` -} - -type Devices struct { - Disks []Disk `xml:"disk"` -} -type Disk struct { - Source Source `xml:"source"` -} -type Source struct { - File string `xml:"file,attr"` -} - -type LibOsInfo struct { - V2VOS V2VOS `xml:"os"` -} - -type V2VOS struct { - ID string `xml:"id,attr"` -} +// ReadYAMLFile reads the YAML file and extracts the HostDisk paths and osinfo label. +func GetVmConfigYaml(filePath string) (*VmConfig, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, fmt.Errorf("error opening YAML file: %w", err) + } + defer file.Close() -type OSType struct { - Arch string `xml:"arch,attr"` - Machine string `xml:"machine,attr"` - Content string `xml:",chardata"` -} + config := &VmConfig{} + scanner := bufio.NewScanner(file) + var inLabels, inVolumes bool + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) -type Loader struct { - Readonly string `xml:"readonly,attr"` - Type string `xml:"type,attr"` - Secure string `xml:"secure,attr"` - Path string `xml:",chardata"` -} + if line == "" || strings.HasPrefix(line, "#") { + continue + } -type Nvram struct { - Template string `xml:"template,attr"` -} + if strings.HasPrefix(line, "labels:") { + inLabels = true + continue + } -// ReadXMLFile reads the content of an XML []byte from the given file path. -// -// Arguments: -// - filePath (string): The path to the XML file. -// -// Returns: -// - []byte: The content of the XML file. -// - error: An error if the file cannot be read, or nil if successful. -func ReadXMLFile(filePath string) ([]byte, error) { - if filePath == "" { - return nil, fmt.Errorf("XML file path is empty") - } + if inLabels { + if strings.HasPrefix(line, "libguestfs.org/osinfo:") { + config.OSInfo = strings.TrimSpace(strings.TrimPrefix(line, "libguestfs.org/osinfo:")) + } + if !strings.HasPrefix(line, "libguestfs.org/") { + inLabels = false + } + } - xmlData, err := os.ReadFile(filePath) - if err != nil { - return nil, fmt.Errorf("error reading XML file: %w", err) + if strings.Contains(line, "volumes:") { + inVolumes = true + continue + } + if inVolumes { + if strings.Contains(line, "hostDisk:") { + scanner.Scan() + pathLine := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(pathLine, "path:") { + pathValue := strings.TrimSpace(strings.TrimPrefix(pathLine, "path:")) + if pathValue != "" { + config.DiskPaths = append(config.DiskPaths, pathValue) + } + } + } + if strings.Contains(line, "- name:") { + inVolumes = false + } + } } - return xmlData, nil -} - -func GetDomainFromXml(xmlFilePath string) (*OvaVmconfig, error) { - xmlData, err := ReadXMLFile(xmlFilePath) - if err != nil { - fmt.Printf("Error read XML: %v\n", err) - return nil, err + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error reading YAML file: %w", err) } - var xmlConf OvaVmconfig - err = xml.Unmarshal(xmlData, &xmlConf) - if err != nil { - fmt.Printf("Error unmarshalling XML: %v\n", err) - return nil, err - } - return &xmlConf, nil + return config, nil }