diff --git a/pkg/controller/plan/adapter/ova/ovfparser.go b/pkg/controller/plan/adapter/ova/ovfparser.go
index aab4be438..eb175da5d 100644
--- a/pkg/controller/plan/adapter/ova/ovfparser.go
+++ b/pkg/controller/plan/adapter/ova/ovfparser.go
@@ -3,35 +3,21 @@ package ova
import (
"encoding/xml"
"strings"
+
+ liberr "github.com/konveyor/forklift-controller/pkg/lib/error"
)
type OvaVmconfig struct {
- XMLName xml.Name `xml:"domain"`
- Name string `xml:"name"`
- OS OS `xml:"os"`
-}
-
-type OS struct {
- Type OSType `xml:"type"`
- Loader Loader `xml:"loader"`
- Nvram Nvram `xml:"nvram"`
-}
-
-type OSType struct {
- Arch string `xml:"arch,attr"`
- Machine string `xml:"machine,attr"`
- Content string `xml:",chardata"`
+ XMLName xml.Name `xml:"domain"`
+ Firmware Firmware `xml:"firmware"`
}
-type Loader struct {
- Readonly string `xml:"readonly,attr"`
- Type string `xml:"type,attr"`
- Secure string `xml:"secure,attr"`
- Path string `xml:",chardata"`
+type Firmware struct {
+ Bootloader Bootloader `xml:"bootloader"`
}
-type Nvram struct {
- Template string `xml:"template,attr"`
+type Bootloader struct {
+ Type string `xml:"type,attr"`
}
func readConfFromXML(xmlData string) (*OvaVmconfig, error) {
@@ -54,9 +40,9 @@ func GetFirmwareFromConfig(vmConfigXML string) (firmware string, err error) {
return
}
- path := xmlConf.OS.Loader.Path
- if strings.Contains(path, "OVMF") {
- return UEFI, nil
+ firmware = xmlConf.Firmware.Bootloader.Type
+ if firmware == "" {
+ err = liberr.New("failed to get the firmware type from virt-v2v config")
}
- return BIOS, nil
+ return
}
diff --git a/pkg/controller/plan/kubevirt.go b/pkg/controller/plan/kubevirt.go
index 30c22ae56..62dbed6a8 100644
--- a/pkg/controller/plan/kubevirt.go
+++ b/pkg/controller/plan/kubevirt.go
@@ -913,7 +913,7 @@ func (r *KubeVirt) UpdateVmByConvertedConfig(vm *plan.VMStatus, pod *core.Pod, s
return
}
- url := fmt.Sprintf("http://%s:8080/ovf", pod.Status.PodIP)
+ url := fmt.Sprintf("http://%s:8080/vm", pod.Status.PodIP)
/* Due to the virt-v2v operation, the ovf file is only available after the command's execution,
meaning it appears following the copydisks phase.
@@ -941,6 +941,8 @@ func (r *KubeVirt) UpdateVmByConvertedConfig(vm *plan.VMStatus, pod *core.Pod, s
return
}
+ r.Log.Info("setting the vm firmware to ", firmware, "vmId", vm.ID)
+
vm.Firmware = firmware
shutdownURL := fmt.Sprintf("http://%s:8080/shutdown", pod.Status.PodIP)
diff --git a/virt-v2v/cold/entrypoint.go b/virt-v2v/cold/entrypoint.go
index 8eb5b0cea..93cd5d7a9 100644
--- a/virt-v2v/cold/entrypoint.go
+++ b/virt-v2v/cold/entrypoint.go
@@ -1,6 +1,7 @@
package main
import (
+ "bufio"
"context"
"fmt"
"io"
@@ -8,7 +9,9 @@ import (
"os"
"os/exec"
"path/filepath"
+ "regexp"
"strconv"
+ "strings"
)
const (
@@ -25,6 +28,9 @@ var (
server *http.Server
)
+var UEFI_RE = regexp.MustCompile(`(?i)UEFI\s+bootloader?`)
+var firmware = "bios"
+
func main() {
virtV2vArgs := []string{"virt-v2v", "-v", "-x"}
source := os.Getenv("V2V_source")
@@ -97,7 +103,7 @@ func main() {
virtV2vArgs = append(virtV2vArgs, "--", os.Getenv("V2V_vmName"))
}
- if err := executeVirtV2v(virtV2vArgs); err != nil {
+ if err := executeVirtV2v(source, virtV2vArgs); err != nil {
fmt.Println("Error executing virt-v2v command ", err)
os.Exit(1)
}
@@ -110,7 +116,7 @@ func main() {
os.Exit(1)
}
- http.HandleFunc("/ovf", ovfHandler)
+ http.HandleFunc("/vm", vmHandler)
http.HandleFunc("/shutdown", shutdownHandler)
server = &http.Server{Addr: ":8080"}
@@ -169,16 +175,26 @@ func LinkDisks(diskKind string, num int) (err error) {
return
}
-func executeVirtV2v(args []string) (err error) {
+func executeVirtV2v(source string, args []string) (err error) {
virtV2vCmd := exec.Command(args[0], args[1:]...)
virtV2vStdoutPipe, err := virtV2vCmd.StdoutPipe()
if err != nil {
fmt.Printf("Error setting up stdout pipe: %v\n", err)
return
}
+ teeOut := io.TeeReader(virtV2vStdoutPipe, os.Stdout)
- tee := io.TeeReader(virtV2vStdoutPipe, os.Stdout)
- virtV2vCmd.Stderr = os.Stderr
+ var teeErr io.Reader
+ if source == OVA {
+ virtV2vStderrPipe, err := virtV2vCmd.StderrPipe()
+ if err != nil {
+ fmt.Printf("Error setting up stdout pipe: %v\n", err)
+ return err
+ }
+ teeErr = io.TeeReader(virtV2vStderrPipe, os.Stderr)
+ } else {
+ virtV2vCmd.Stderr = os.Stderr
+ }
fmt.Println("exec ", virtV2vCmd)
if err = virtV2vCmd.Start(); err != nil {
@@ -187,7 +203,7 @@ func executeVirtV2v(args []string) (err error) {
}
virtV2vMonitorCmd := exec.Command("/usr/local/bin/virt-v2v-monitor")
- virtV2vMonitorCmd.Stdin = tee
+ virtV2vMonitorCmd.Stdin = teeOut
virtV2vMonitorCmd.Stdout = os.Stdout
virtV2vMonitorCmd.Stderr = os.Stderr
@@ -196,6 +212,26 @@ func executeVirtV2v(args []string) (err error) {
return
}
+ if source == OVA {
+ scanner := bufio.NewScanner(teeErr)
+ const maxCapacity = 1024 * 1024
+ buf := make([]byte, 0, 64*1024)
+ scanner.Buffer(buf, maxCapacity)
+
+ for scanner.Scan() {
+ line := scanner.Bytes()
+ if match := UEFI_RE.FindSubmatch(line); match != nil {
+ fmt.Println("UEFI firmware detected")
+ firmware = "efi"
+ }
+ }
+
+ if err = scanner.Err(); err != nil {
+ fmt.Println("Output query failed:", err)
+ return err
+ }
+ }
+
if err = virtV2vCmd.Wait(); err != nil {
fmt.Printf("Error waiting for virt-v2v to finish: %v\n", err)
return
@@ -214,13 +250,19 @@ func getXMLFile(dir, fileExtension string) (string, error) {
return "", fmt.Errorf("XML file was not found.")
}
-func ovfHandler(w http.ResponseWriter, r *http.Request) {
+func vmHandler(w http.ResponseWriter, r *http.Request) {
if xmlFilePath == "" {
fmt.Println("Error: XML file path is empty.")
http.Error(w, "XML file path is empty", http.StatusInternalServerError)
return
}
+ if err := addFirmwareToXml(xmlFilePath); err != nil {
+ fmt.Println("Error setting the firmware configuration in the ovf ", err)
+ http.Error(w, "Error setting the firmware configuration in the ovf", http.StatusInternalServerError)
+ return
+ }
+
xmlData, err := os.ReadFile(xmlFilePath)
if err != nil {
fmt.Printf("Error reading XML file: %v\n", err)
@@ -255,3 +297,66 @@ func isValidSource(source string) bool {
return false
}
}
+
+func addFirmwareToXml(filePath string) (err error) {
+ var newFirmwareData string
+ if firmware == "bios" {
+ newFirmwareData = (`
+
+ `)
+ } else {
+ newFirmwareData = (`
+
+ `)
+ }
+
+ file, err := os.Open(filePath)
+ if err != nil {
+ return
+ }
+ defer file.Close()
+
+ tempFilePath := filePath + ".tmp"
+
+ tempFile, err := os.Create(tempFilePath)
+ if err != nil {
+ return
+ }
+ defer tempFile.Close()
+
+ scanner := bufio.NewScanner(file)
+ domainFound := false
+
+ for scanner.Scan() {
+ line := scanner.Text()
+
+ if strings.Contains(line, "") {
+ domainFound = true
+ }
+
+ _, err = tempFile.WriteString(line + "\n")
+ if err != nil {
+ return
+ }
+
+ if domainFound {
+ _, err = tempFile.WriteString(newFirmwareData + "\n")
+ if err != nil {
+ return
+ }
+ domainFound = false
+ }
+ }
+
+ if err = scanner.Err(); err != nil {
+ return
+ }
+
+ err = os.Rename(tempFilePath, filePath)
+ if err != nil {
+ return
+ }
+
+ fmt.Println("XML file has been modified successfully.")
+ return
+}