Skip to content

Commit

Permalink
Change VM customization to use a YAML output file instead of XML.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
bkhizgiy committed Sep 2, 2024
1 parent 5405091 commit afff014
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 97 deletions.
36 changes: 17 additions & 19 deletions virt-v2v/cold/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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")

Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down
132 changes: 54 additions & 78 deletions virt-v2v/cold/xml-reader.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit afff014

Please sign in to comment.