Skip to content

Commit

Permalink
OVA: workaround for virt-v2v firmware detection
Browse files Browse the repository at this point in the history
Signed-off-by: Bella Khizgiyaev <bkhizgiy@redhat.com>
  • Loading branch information
bkhizgiy authored and mnecas committed Sep 19, 2024
1 parent 1f6902a commit 31ac185
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ spec:
The VM Namespace
Only relevant for an openshift source.
type: string
newName:
description: The new name of the VM after matching DNS1123 requirements.
type: string
operatingSystem:
description: The Operating System detected by virt-v2v.
type: string
Expand Down
4 changes: 4 additions & 0 deletions operator/config/crd/bases/forklift.konveyor.io_plans.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,10 @@ spec:
The VM Namespace
Only relevant for an openshift source.
type: string
newName:
description: The new name of the VM after matching DNS1123
requirements.
type: string
operatingSystem:
description: The Operating System detected by virt-v2v.
type: string
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/forklift/v1beta1/plan/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ type VMStatus struct {
Firmware string `json:"firmware,omitempty"`
// The Operating System detected by virt-v2v.
OperatingSystem string `json:"operatingSystem,omitempty"`
// The new name of the VM after matching DNS1123 requirements.
NewName string `json:"newName,omitempty"`

// Conditions.
libcnd.Conditions `json:",inline"`
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/plan/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ go_library(
"//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",
Expand Down
2 changes: 0 additions & 2 deletions pkg/controller/plan/adapter/ova/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ go_library(
"builder.go",
"client.go",
"destinationclient.go",
"ovfparser.go",
"validator.go",
],
importpath = "github.com/konveyor/forklift-controller/pkg/controller/plan/adapter/ova",
Expand All @@ -27,7 +26,6 @@ go_library(
"//pkg/lib/error",
"//pkg/lib/inventory/web",
"//pkg/lib/itinerary",
"//pkg/lib/logging",
"//vendor/github.com/go-logr/logr",
"//vendor/k8s.io/api/core/v1:core",
"//vendor/k8s.io/apimachinery/pkg/api/resource",
Expand Down
36 changes: 21 additions & 15 deletions pkg/controller/plan/kubevirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"time"

planbase "github.com/konveyor/forklift-controller/pkg/controller/plan/adapter/base"
"github.com/konveyor/forklift-controller/pkg/controller/plan/util"
"github.com/konveyor/forklift-controller/pkg/controller/provider/web"
model "github.com/konveyor/forklift-controller/pkg/controller/provider/web/vsphere"
libref "github.com/konveyor/forklift-controller/pkg/lib/ref"
Expand All @@ -28,7 +29,6 @@ import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
k8svalidation "k8s.io/apimachinery/pkg/util/validation"
cnv "kubevirt.io/api/core/v1"
instancetypeapi "kubevirt.io/api/instancetype"
instancetype "kubevirt.io/api/instancetype/v1beta1"
Expand All @@ -38,7 +38,6 @@ import (
"github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/plan"
"github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/ref"
"github.com/konveyor/forklift-controller/pkg/controller/plan/adapter"
ovfparser "github.com/konveyor/forklift-controller/pkg/controller/plan/adapter/ova"
inspectionparser "github.com/konveyor/forklift-controller/pkg/controller/plan/adapter/vsphere"
plancontext "github.com/konveyor/forklift-controller/pkg/controller/plan/context"
libcnd "github.com/konveyor/forklift-controller/pkg/lib/condition"
Expand Down Expand Up @@ -961,7 +960,8 @@ func (r *KubeVirt) UpdateVmByConvertedConfig(vm *plan.VMStatus, pod *core.Pod, s
return nil
}

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.
The server will be accessible via virt-v2v only after the command has finished.
Expand All @@ -980,22 +980,22 @@ func (r *KubeVirt) UpdateVmByConvertedConfig(vm *plan.VMStatus, pod *core.Pod, s

switch r.Source.Provider.Type() {
case api.Ova:
vmConfigBytes, err := io.ReadAll(resp.Body)
vmConf, err := io.ReadAll(resp.Body)
if err != nil {
return liberr.Wrap(err)
return err
}
vmConfigXML := string(vmConfigBytes)
if vm.Firmware, err = ovfparser.GetFirmwareFromConfig(vmConfigXML); err != nil {
return liberr.Wrap(err)
if vm.Firmware, err = util.GetFirmwareFromYaml(vmConf); err != nil {
return err
}
case api.VSphere:
inspectionXML, err := r.getInspectionXml(pod)
if err != nil {
return err
}
if vm.OperatingSystem, err = inspectionparser.GetOperationSystemFromConfig(inspectionXML); err != nil {
return liberr.Wrap(err)
return err
}
r.Log.Info("Setting the vm OS ", vm.OperatingSystem, "vmId", vm.ID)
}

shutdownURL := fmt.Sprintf("http://%s:8080/shutdown", pod.Status.PodIP)
Expand Down Expand Up @@ -1279,13 +1279,10 @@ func (r *KubeVirt) virtualMachine(vm *plan.VMStatus) (object *cnv.VirtualMachine
//convention it will be automatically changed.
var originalName string

if errs := k8svalidation.IsDNS1123Label(vm.Name); len(errs) > 0 {
if vm.NewName != "" {
originalName = vm.Name
vm.Name, err = r.changeVmNameDNS1123(vm.Name, r.Plan.Spec.TargetNamespace)
if err != nil {
r.Log.Error(err, "Failed to update the VM name to meet DNS1123 protocol requirements.")
return
}
vm.Name = vm.NewName

r.Log.Info("VM name is incompatible with DNS1123 RFC, renaming",
"originalName", originalName, "newName", vm.Name)
}
Expand Down Expand Up @@ -1743,6 +1740,15 @@ func (r *KubeVirt) guestConversionPod(vm *plan.VMStatus, vmVolumes []cnv.Volume,
Value: vm.RootDisk,
})
}

if vm.NewName != "" {
environment = append(environment,
core.EnvVar{
Name: "V2V_NewName",
Value: vm.NewName,
})
}

// pod annotations
annotations := map[string]string{}
if r.Plan.Spec.TransferNetwork != nil {
Expand Down
10 changes: 9 additions & 1 deletion pkg/controller/plan/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
k8svalidation "k8s.io/apimachinery/pkg/util/validation"
cdi "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Expand Down Expand Up @@ -718,6 +719,13 @@ func (r *Migration) execute(vm *plan.VMStatus) (err error) {
err = nil
break
}
if errs := k8svalidation.IsDNS1123Label(vm.Name); len(errs) > 0 {
vm.NewName, err = r.kubevirt.changeVmNameDNS1123(vm.Name, r.Plan.Spec.TargetNamespace)
if err != nil {
r.Log.Error(err, "Failed to update the VM name to meet DNS1123 protocol requirements.")
return
}
}
vm.Phase = r.next(vm.Phase)
case PreHook, PostHook:
runner := HookRunner{Context: r.Context}
Expand Down Expand Up @@ -1141,7 +1149,7 @@ func (r *Migration) execute(vm *plan.VMStatus) (err error) {
if pod != nil && pod.Status.Phase != core.PodSucceeded {
err := r.kubevirt.UpdateVmByConvertedConfig(vm, pod, step)
if err != nil {
return err
return liberr.Wrap(err)
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/controller/plan/util/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -13,7 +14,9 @@ go_library(
"//pkg/apis/forklift/v1beta1",
"//pkg/controller/provider/web/openstack",
"//pkg/controller/provider/web/ovirt",
"//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",
],
Expand Down
135 changes: 135 additions & 0 deletions pkg/controller/plan/util/kubevirtvmparser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package util

import (
"fmt"
"strings"

"github.com/konveyor/forklift-controller/pkg/lib/logging"
"gopkg.in/yaml.v2"
)

const (
// Name.
Name = "kubevirt-vm-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 OS struct {
Firmware string `yaml:"firmware"`
}

type Domain struct {
OS OS `yaml:"os"`
}

type TemplateSpec struct {
Domain Domain `yaml:"domain"`
}

type Template struct {
Spec TemplateSpec `yaml:"spec"`
}

type VirtualMachineSpec struct {
Template Template `yaml:"template"`
}

type VirtualMachine struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata Metadata `yaml:"metadata"`
Spec VirtualMachineSpec `yaml:"spec"`
}

type Metadata struct {
Name string `yaml:"name"`
Labels map[string]string `yaml:"labels"`
}

func GetFirmwareFromYaml(yamlData []byte) (string, error) {
var vm VirtualMachine
if err := yaml.Unmarshal(yamlData, &vm); err != nil {
return "", err
}

firmware := vm.Spec.Template.Spec.Domain.OS.Firmware
if firmware == "" {
log.Info("Firmware type was not detected")
}

return firmware, nil
}

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[distro]
if !ok {
log.Info(fmt.Sprintf("Received %s, mapped to: %s", labelOS, os))
os = "otherGuest64"
}
return
}

0 comments on commit 31ac185

Please sign in to comment.