Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MTV-1041 | Change created virt-v2v conversion output to -o kubeVirt #1020

Merged
merged 3 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (
kubevirt.io/containerized-data-importer-api v1.59.0
libvirt.org/libvirt-go-xml v7.4.0+incompatible
sigs.k8s.io/controller-runtime v0.16.3
sigs.k8s.io/yaml v1.3.0
)

require (
Expand Down Expand Up @@ -115,7 +116,6 @@ require (
kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace github.com/gophercloud/gophercloud => github.com/kubev2v/gophercloud v0.0.0-20230629135522-9d701a75c760
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
2 changes: 1 addition & 1 deletion pkg/controller/plan/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ go_library(
"//pkg/controller/base",
"//pkg/controller/plan/adapter",
"//pkg/controller/plan/adapter/base",
"//pkg/controller/plan/adapter/ova",
"//pkg/controller/plan/adapter/vsphere",
"//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
37 changes: 21 additions & 16 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)
}
vmConfigXML := string(vmConfigBytes)
if vm.Firmware, err = ovfparser.GetFirmwareFromConfig(vmConfigXML); err != nil {
if vm.Firmware, err = util.GetFirmwareFromYaml(vmConf); err != nil {
return liberr.Wrap(err)
}
case api.VSphere:
inspectionXML, err := r.getInspectionXml(pod)
if err != nil {
return err
return liberr.Wrap(err)
}
if vm.OperatingSystem, err = inspectionparser.GetOperationSystemFromConfig(inspectionXML); err != nil {
return liberr.Wrap(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 Expand Up @@ -1794,9 +1800,8 @@ func (r *KubeVirt) guestConversionPod(vm *plan.VMStatus, vmVolumes []cnv.Volume,
InitContainers: initContainers,
Containers: []core.Container{
{
ImagePullPolicy: core.PullAlways,
Name: "virt-v2v",
Env: environment,
Name: "virt-v2v",
Env: environment,
EnvFrom: []core.EnvFromSource{
{
Prefix: "V2V_",
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
6 changes: 6 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,18 +14,23 @@ go_library(
"//pkg/apis/forklift/v1beta1",
"//pkg/controller/provider/web/openstack",
"//pkg/controller/provider/web/ovirt",
"//pkg/lib/logging",
"//pkg/settings",
"//vendor/k8s.io/api/core/v1:core",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta",
"//vendor/kubevirt.io/api/core/v1:core",
"//vendor/sigs.k8s.io/yaml",
],
)

go_test(
name = "util_test",
srcs = [
"kubevirtvmparser_test.go",
"util_suite_test.go",
"utils_test.go",
],
data = glob(["testdata/**"]),
embed = [":util"],
deps = [
"//vendor/github.com/onsi/ginkgo/v2:ginkgo",
Expand Down
78 changes: 78 additions & 0 deletions pkg/controller/plan/util/kubevirtvmparser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package util

import (
cnv "kubevirt.io/api/core/v1"
"sigs.k8s.io/yaml"

"github.com/konveyor/forklift-controller/pkg/lib/logging"
)

const (
// Name.
Name = "kubevirt-vm-parser"
)

// Package logger.
var log = logging.WithName(Name)

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 != "" {
return firmware, nil
}

// FIXME: In newer version of virt-v2v the output will change to support CNV VM format.
// With this we will support both so the migrations should not fail during the update to newer virt-v2v.
// But we still need to remove the custom templating.
// https://issues.redhat.com/browse/RHEL-58065
var cnvVm *cnv.VirtualMachine
if err := yaml.Unmarshal(yamlData, &cnvVm); err != nil {
return "", err
}
if cnvVm.Spec.Template.Spec.Domain.Firmware.Bootloader.BIOS != nil {
return "bios", nil
}
if cnvVm.Spec.Template.Spec.Domain.Firmware.Bootloader.EFI != nil {
return "uefi", nil
}

log.Info("Firmware type was not detected")
return "", nil
}
31 changes: 31 additions & 0 deletions pkg/controller/plan/util/kubevirtvmparser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package util

import (
"fmt"
"os"
"path/filepath"
"testing"
)

func TestKubevirtVmParser(t *testing.T) {
fmt.Println("test")
testFile(t, "new_format_bios.yml", "bios")
testFile(t, "new_format_efi.yml", "uefi")
testFile(t, "old_format_bios.yml", "bios")
testFile(t, "old_format_efi.yml", "uefi")
}

func testFile(t *testing.T, filename, expectedFormat string) {
data, err := os.ReadFile(filepath.Join("testdata", filename))
if err != nil {
fmt.Println(err)
}
firmware, err := GetFirmwareFromYaml(data)
if err != nil {
fmt.Println(err)
}
fmt.Println(firmware)
if firmware != expectedFormat {
t.Fatalf("Failed to parse '%s' from file '%s'", expectedFormat, filename)
}
}
38 changes: 38 additions & 0 deletions pkg/controller/plan/util/testdata/new_format_bios.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
# generated by virt-v2v 2.5.8fedora=40,release=1.fc40
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: mnecas-win-2022
labels:
libguestfs.org/virt-v2v-version: "2.5.8"
libguestfs.org/genid: f2fc75e8-4961-1425-4740-fcf2bc09685a
libguestfs.org/osinfo: win2k22
libguestfs.org/source: vmware
spec:
template:
spec:
domain:
firmware:
bootloader:
bios: {}
resources:
clock:
timer:
hpet:
present: false
hyperv: {}
pit:
tickPolicy: delay
rtc:
tickPolicy: catchup
utc: {}
requests:
memory: 8192Mi
features:
cpu:
sockets: 2
cores: 2
thread: 1
terminationGracePeriodSeconds: 0

Loading
Loading