From 6f517e500ffbcbd1e405b0b3e89096bb72a15f5c Mon Sep 17 00:00:00 2001 From: Bella Khizgiyaev Date: Mon, 22 Jul 2024 19:52:51 +0300 Subject: [PATCH] change mtv to use virt-v2v kubevirt changes Signed-off-by: Bella Khizgiyaev --- pkg/controller/plan/BUILD.bazel | 2 +- pkg/controller/plan/adapter/ova/BUILD.bazel | 3 - .../plan/adapter/ova/kubevirtvmparser.go | 43 ------ pkg/controller/plan/util/BUILD.bazel | 4 + pkg/controller/plan/util/kubevirtvmparser.go | 133 ++++++++++++++++++ virt-v2v/cold/entrypoint.go | 116 +++++---------- 6 files changed, 171 insertions(+), 130 deletions(-) delete mode 100644 pkg/controller/plan/adapter/ova/kubevirtvmparser.go create mode 100644 pkg/controller/plan/util/kubevirtvmparser.go diff --git a/pkg/controller/plan/BUILD.bazel b/pkg/controller/plan/BUILD.bazel index 82ff64394..eb404d678 100644 --- a/pkg/controller/plan/BUILD.bazel +++ b/pkg/controller/plan/BUILD.bazel @@ -22,10 +22,10 @@ go_library( "//pkg/controller/base", "//pkg/controller/plan/adapter", "//pkg/controller/plan/adapter/base", - "//pkg/controller/plan/adapter/ova", "//pkg/controller/plan/context", "//pkg/controller/plan/handler", "//pkg/controller/plan/scheduler", + "//pkg/controller/plan/util", "//pkg/controller/provider/web", "//pkg/controller/provider/web/vsphere", "//pkg/controller/validation", diff --git a/pkg/controller/plan/adapter/ova/BUILD.bazel b/pkg/controller/plan/adapter/ova/BUILD.bazel index 5b97257ae..0d5368639 100644 --- a/pkg/controller/plan/adapter/ova/BUILD.bazel +++ b/pkg/controller/plan/adapter/ova/BUILD.bazel @@ -7,7 +7,6 @@ go_library( "builder.go", "client.go", "destinationclient.go", - "kubevirtvmparser.go", "validator.go", ], importpath = "github.com/konveyor/forklift-controller/pkg/controller/plan/adapter/ova", @@ -27,9 +26,7 @@ go_library( "//pkg/lib/error", "//pkg/lib/inventory/web", "//pkg/lib/itinerary", - "//pkg/lib/logging", "//vendor/github.com/go-logr/logr", - "//vendor/gopkg.in/yaml.v2:yaml_v2", "//vendor/k8s.io/api/core/v1:core", "//vendor/k8s.io/apimachinery/pkg/api/resource", "//vendor/k8s.io/utils/ptr", diff --git a/pkg/controller/plan/adapter/ova/kubevirtvmparser.go b/pkg/controller/plan/adapter/ova/kubevirtvmparser.go deleted file mode 100644 index 4071d80a7..000000000 --- a/pkg/controller/plan/adapter/ova/kubevirtvmparser.go +++ /dev/null @@ -1,43 +0,0 @@ -package ova - -import ( - liberr "github.com/konveyor/forklift-controller/pkg/lib/error" - "gopkg.in/yaml.v2" -) - -type VirtualMachineInstance struct { - ApiVersion string `yaml:"apiVersion"` - Kind string `yaml:"kind"` - Metadata Metadata `yaml:"metadata"` - Spec Spec `yaml:"spec"` -} - -type Metadata struct { - Name string `yaml:"name"` -} - -type Spec struct { - Domain Domain `yaml:"domain"` -} -type Domain struct { - OS OS `yaml:"os"` -} - -type OS struct { - Firmware string `yaml:"firmware,omitempty"` -} - -func GetFirmwareFromYaml(yamlData []byte) (firmware string, err error) { - var vmi VirtualMachineInstance - if err = yaml.Unmarshal(yamlData, &vmi); err != nil { - return - } - - if vmi.Spec.Domain.OS.Firmware != "" { - firmware = vmi.Spec.Domain.OS.Firmware - return - } - - err = liberr.New("Firmware type was not detected") - return -} diff --git a/pkg/controller/plan/util/BUILD.bazel b/pkg/controller/plan/util/BUILD.bazel index 195f4cb78..7251e3d05 100644 --- a/pkg/controller/plan/util/BUILD.bazel +++ b/pkg/controller/plan/util/BUILD.bazel @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "util", srcs = [ + "kubevirtvmparser.go", "openstack.go", "ovirt.go", "utils.go", @@ -13,7 +14,10 @@ go_library( "//pkg/apis/forklift/v1beta1", "//pkg/controller/provider/web/openstack", "//pkg/controller/provider/web/ovirt", + "//pkg/lib/error", + "//pkg/lib/logging", "//pkg/settings", + "//vendor/gopkg.in/yaml.v2:yaml_v2", "//vendor/k8s.io/api/core/v1:core", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta", ], diff --git a/pkg/controller/plan/util/kubevirtvmparser.go b/pkg/controller/plan/util/kubevirtvmparser.go new file mode 100644 index 000000000..509a86c70 --- /dev/null +++ b/pkg/controller/plan/util/kubevirtvmparser.go @@ -0,0 +1,133 @@ +package util + +import ( + "fmt" + "strings" + + liberr "github.com/konveyor/forklift-controller/pkg/lib/error" + "github.com/konveyor/forklift-controller/pkg/lib/logging" + "gopkg.in/yaml.v2" +) + +const ( + // Name. + Name = "virt-v2v-parser" +) + +// Package logger. +var log = logging.WithName(Name) + +// Map of osinfo ids to vmware guest ids. +var osV2VMap = map[string]string{ + "centos6": "centos6_64Guest", + "centos7": "centos7_64Guest", + "centos8": "centos8_64Guest", + "centos9": "centos9_64Guest", + "rhel7": "rhel7_64Guest", + "rhel8": "rhel8_64Guest", + "rhel9": "rhel9_64Guest", + "rocky": "rockylinux_64Guest", + "sles10": "sles10_64Guest", + "sles11": "sles11_64Guest", + "sles12": "sles12_64Guest", + "sles15": "sles15_64Guest", + "sles16": "sles16_64Guest", + "opensuse": "opensuse64Guest", + "debian4": "debian4_64Guest", + "debian5": "debian5_64Guest", + "debian6": "debian6_64Guest", + "debian7": "debian7_64Guest", + "debian8": "debian8_64Guest", + "debian9": "debian9_64Guest", + "debian10": "debian10_64Guest", + "debian11": "debian11_64Guest", + "debian12": "debian12_64Guest", + "ubuntu": "ubuntu64Guest", + "fedora": "fedora64Guest", + "win7": "windows7Server64Guest", + "win8": "windows8Server64Guest", + "win10": "windows9Server64Guest", + "win11": "windows11_64Guest", + "win12": "windows12_64Guest", + "win2k19": "windows2019srv_64Guest", + "win2k22": "windows2022srvNext_64Guest", +} + +type VirtualMachine struct { + ApiVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + Metadata Metadata `yaml:"metadata"` + Spec Spec `yaml:"spec"` +} + +type Metadata struct { + Name string `yaml:"name"` + Labels map[string]string `yaml:"labels"` +} + +type Spec struct { + Domain Domain `yaml:"domain"` +} + +type Domain struct { + OS OS `yaml:"os"` +} + +type OS struct { + Firmware string `yaml:"firmware"` +} + +type Bios struct{} + +type EFI struct { + SecureBoot bool `yaml:"secureBoot"` +} + +func GetFirmwareFromYaml(yamlData []byte) (firmware string, err error) { + var vm VirtualMachine + if err = yaml.Unmarshal(yamlData, &vm); err != nil { + return + } + + if vm.Spec.Domain.OS.Firmware != "" { + return + } + err = liberr.New("Firmware type was not detected") + return +} + +func GetOperationSystemFromYaml(yamlData []byte) (os string, err error) { + var vm VirtualMachine + if err = yaml.Unmarshal(yamlData, &vm); err != nil { + return + } + + labels := vm.Metadata.Labels + if osinfo, ok := labels["libguestfs.org/osinfo"]; ok { + return mapOs(osinfo), nil + + } + return +} + +func mapOs(labelOS string) (os string) { + distro := strings.SplitN(labelOS, ".", 2)[0] + + switch { + case strings.HasPrefix(distro, "rocky"): + distro = "rocky" + case strings.HasPrefix(distro, "opensuse"): + distro = "opensuse" + case strings.HasPrefix(distro, "ubuntu"): + distro = "ubuntu" + case strings.HasPrefix(distro, "fedora"): + distro = "fedora" + } + + os, ok := osV2VMap[os] + if !ok { + log.Info(fmt.Sprintf("Received %s, mapped to: %s", labelOS, os)) + os = "otherGuest64" + } + return +} diff --git a/virt-v2v/cold/entrypoint.go b/virt-v2v/cold/entrypoint.go index 91475e686..7b74eb3a3 100644 --- a/virt-v2v/cold/entrypoint.go +++ b/virt-v2v/cold/entrypoint.go @@ -1,7 +1,6 @@ package main import ( - "bufio" "context" "encoding/json" "fmt" @@ -10,8 +9,8 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "strconv" + "strings" ) const ( @@ -24,10 +23,6 @@ const ( LUKSDIR = "/etc/luks" ) -var UEFI_RE = regexp.MustCompile(`(?i)UEFI\s+bootloader?`) -var firmware = "bios" -var nameChanged bool - var ( yamlFilePath string server *http.Server @@ -36,6 +31,9 @@ var ( const LETTERS = "abcdefghijklmnopqrstuvwxyz" const LETTERS_LENGTH = len(LETTERS) +var firmware = "bios" +var nameChanged bool + func main() { source := os.Getenv("V2V_source") if source == vSphere { @@ -62,13 +60,13 @@ func main() { } var err error - xmlFilePath, err = getXMLFile(DIR, "xml") + yamlFilePath, err = getYamlFile(DIR, "yaml") if err != nil { - fmt.Println("Error getting XML file:", err) + fmt.Println("Error getting YAML file:", err) os.Exit(1) } - http.HandleFunc("/ovf", ovfHandler) + http.HandleFunc("/vm", vmHandler) http.HandleFunc("/shutdown", shutdownHandler) server = &http.Server{Addr: ":8080"} @@ -127,6 +125,7 @@ func buildCommand() []string { } virtV2vArgs = append(virtV2vArgs, "-os", DIR) + //Disks on filesystem storage. if err := LinkDisks(FS, 15); err != nil { os.Exit(1) @@ -180,27 +179,15 @@ func buildCommand() []string { return virtV2vArgs } - if err := executeVirtV2v(virtV2vArgs, source); err != nil { - fmt.Println("Error executing virt-v2v command ", err) - os.Exit(1) +func getFilesInPath(rootPath string) (paths []string, err error) { + files, err := os.ReadDir(rootPath) + if err != nil { + fmt.Println("Error reading the files in the directory ", err) + return } - - if source == OVA { - var err error - yamlFilePath, err = getYamlFile(DIR, "yaml") - if err != nil { - fmt.Println("Error gettin YAML file:", err) - os.Exit(1) - } - - http.HandleFunc("/vm", vmHandler) - http.HandleFunc("/shutdown", shutdownHandler) - server = &http.Server{Addr: ":8080"} - - fmt.Println("Starting server on :8080") - if err := server.ListenAndServe(); err != http.ErrServerClosed { - fmt.Printf("Error starting server: %v\n", err) - os.Exit(1) + for _, file := range files { + if !file.IsDir() && !strings.HasPrefix(file.Name(), "..") { + paths = append(paths, fmt.Sprintf("%s/%s", rootPath, file.Name())) } } return @@ -259,71 +246,33 @@ func LinkDisks(diskKind string, num int) (err error) { return } -func executeVirtV2v(args []string, source 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) - - 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 { - fmt.Printf("Error executing command: %v\n", err) - return - } +func executeVirtV2v(args []string) error { + v2vCmd := exec.Command("virt-v2v", args...) + monitorCmd := exec.Command("/usr/local/bin/virt-v2v-monitor") + monitorCmd.Stdout = os.Stdout + monitorCmd.Stderr = os.Stderr - virtV2vMonitorCmd := exec.Command("/usr/local/bin/virt-v2v-monitor") - virtV2vMonitorCmd.Stdin = teeOut - virtV2vMonitorCmd.Stdout = os.Stdout - virtV2vMonitorCmd.Stderr = os.Stderr + var writer *io.PipeWriter + monitorCmd.Stdin, writer = io.Pipe() + v2vCmd.Stdout = writer + v2vCmd.Stderr = writer + defer writer.Close() - if err = virtV2vMonitorCmd.Start(); err != nil { + if err := monitorCmd.Start(); err != nil { fmt.Printf("Error executing monitor command: %v\n", err) return err } - 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 + fmt.Println("exec:", v2vCmd) + if err := v2vCmd.Run(); err != nil { + fmt.Printf("Error executing v2v command: %v\n", err) + return err } // virt-v2v is done, we can close the pipe to virt-v2v-monitor writer.Close() + if err := monitorCmd.Wait(); err != nil { fmt.Printf("Error waiting for virt-v2v-monitor to finish: %v\n", err) return err } @@ -333,6 +282,7 @@ func executeVirtV2v(args []string, source string) (err error) { func getYamlFile(dir, fileExtension string) (string, error) { files, err := filepath.Glob(filepath.Join(dir, "*."+fileExtension)) + if err != nil { return "", err } if len(files) > 0 {