Skip to content

Commit

Permalink
Refactor virt-v2v
Browse files Browse the repository at this point in the history
Structure the virt-v2v directory into separate packages for isolation.

Signed-off-by: Martin Necas <[email protected]>
  • Loading branch information
mnecas committed Sep 11, 2024
1 parent 9c75aca commit 11ca0f1
Show file tree
Hide file tree
Showing 28 changed files with 765 additions and 634 deletions.
51 changes: 1 addition & 50 deletions virt-v2v/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_image",
Expand Down Expand Up @@ -90,34 +89,6 @@ container_image(
visibility = ["//visibility:public"],
)

go_library(
name = "cold_lib",
srcs = [
"customize-image.go",
"customize-rhel.go",
"embed-tool.go",
"entrypoint.go",
"xml-reader.go",
],
embedsrcs = [
"scripts/windows/9999-restore_config.ps1",
"scripts/windows/9999-restore_config_init.bat",
"scripts/windows/firstboot.bat",
"scripts/rhel/firstboot/README.md",
"scripts/rhel/run/README.md",
"scripts/rhel/run/network_config_util.sh",
"scripts/rhel/run/network_config_util_test",
],
importpath = "github.com/konveyor/forklift-controller/virt-v2v",
visibility = ["//visibility:private"],
)

go_binary(
name = "virt-v2v-wrapper",
embed = [":cold_lib"],
visibility = ["//visibility:public"],
)

container_image(
name = "forklift-virt-v2v",
base = ":virt-v2v-layer",
Expand All @@ -129,24 +100,14 @@ container_image(
"LIBGUESTFS_PATH": "/usr/lib64/guestfs/appliance",
},
files = [
":virt-v2v-wrapper",
"//cmd:virt-v2v-wrapper",
"@forklift//cmd/image-converter",
"@forklift//cmd/virt-v2v-monitor",
],
user = "1001",
visibility = ["//visibility:public"],
)

go_test(
name = "cold_test",
srcs = [
"cold_test.go",
"customize-rhel_test.go",
],
data = glob(["testdata/**"]),
embed = [":cold_lib"],
)

rpmtree(
name = "virt-v2v",
rpms = [
Expand Down Expand Up @@ -502,13 +463,3 @@ rpmtree(
],
visibility = ["//visibility:public"],
)

go_test(
name = "virt-v2v_test",
srcs = [
"cold_test.go",
"customize-rhel_test.go",
],
data = glob(["testdata/**"]),
embed = [":virt-v2v_lib"],
)
33 changes: 33 additions & 0 deletions virt-v2v/cmd/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")

go_library(
name = "cmd_lib",
srcs = ["entrypoint.go"],
importpath = "github.com/konveyor/forklift-controller/virt-v2v/cmd",
visibility = ["//visibility:private"],
deps = [
"//virt-v2v/pkg/customize",
"//virt-v2v/pkg/global",
"//virt-v2v/pkg/server",
"//virt-v2v/pkg/utils",
],
)

go_binary(
name = "virt-v2v-wrapper",
embed = [":cmd_lib"],
visibility = ["//visibility:public"],
)

go_test(
name = "entrypoint_test",
srcs = ["entrypoint_test.go"],
embed = [":cmd_lib"],
)

go_test(
name = "cmd_test",
srcs = ["entrypoint_test.go"],
embed = [":cmd_lib"],
deps = ["//virt-v2v/pkg/global"],
)
203 changes: 203 additions & 0 deletions virt-v2v/cmd/entrypoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package main

import (
_ "embed"
"encoding/json"
"fmt"
"io"
"os"
"os/exec"
"strings"

"github.com/konveyor/forklift-controller/virt-v2v/pkg/customize"
"github.com/konveyor/forklift-controller/virt-v2v/pkg/global"
"github.com/konveyor/forklift-controller/virt-v2v/pkg/server"
"github.com/konveyor/forklift-controller/virt-v2v/pkg/utils"
)

func main() {
var err error
if _, found := os.LookupEnv("V2V_inPlace"); found {
err = convertVirtV2vInPlace()
} else {
err = convertVirtV2v()
}

if err != nil {
fmt.Println("Error executing virt-v2v command ", err)
os.Exit(1)
}
}

func convertVirtV2vInPlace() error {
args := []string{"-v", "-x", "-i", "libvirtxml"}
args = append(args, "--root")
if val, found := os.LookupEnv("V2V_RootDisk"); found {
args = append(args, val)
} else {
args = append(args, "first")
}
args = append(args, "/mnt/v2v/input.xml")
return executeVirtV2v("/usr/libexec/virt-v2v-in-place", args)
}

func virtV2vBuildCommand() (args []string, err error) {
args = []string{"-v", "-x"}
source := os.Getenv("V2V_source")

requiredEnvVars := map[string][]string{
global.VSPHERE: {"V2V_libvirtURL", "V2V_secretKey", "V2V_vmName"},
global.OVA: {"V2V_diskPath", "V2V_vmName"},
}

if envVars, ok := requiredEnvVars[source]; ok {
if !utils.CheckEnvVariablesSet(envVars...) {
return nil, fmt.Errorf("Following environment variables need to be defined: %v\n", envVars)
}
} else {
providers := make([]string, len(requiredEnvVars))
for key := range requiredEnvVars {
providers = append(providers, key)
}
return nil, fmt.Errorf("virt-v2v supports the following providers: {%v}. Provided: %s\n", strings.Join(providers, ", "), source)
}
fmt.Println("Preparing virt-v2v")

if err = utils.VirtV2VPrepEnvironment(); err != nil {
return
}

args = append(args, "-o", "local", "-os", global.DIR)

switch source {
case global.VSPHERE:
vsphereArgs, err := virtV2vVsphereArgs()
if err != nil {
return nil, err
}
args = append(args, vsphereArgs...)
case global.OVA:
args = append(args, "-i", "ova", os.Getenv("V2V_diskPath"))
}

return args, nil
}

func virtV2vVsphereArgs() (args []string, err error) {
args = append(args, "--root")
if utils.CheckEnvVariablesSet("V2V_RootDisk") {
args = append(args, os.Getenv("V2V_RootDisk"))
} else {
args = append(args, "first")
}
args = append(args, "-i", "libvirt", "-ic", os.Getenv("V2V_libvirtURL"))
args = append(args, "-ip", "/etc/secret/secretKey")

if envStaticIPs := os.Getenv("V2V_staticIPs"); envStaticIPs != "" {
for _, macToIp := range strings.Split(envStaticIPs, "_") {
args = append(args, "--mac", macToIp)
}
}

// Adds LUKS keys, if they exist
luksArgs, err := utils.AddLUKSKeys()
if err != nil {
return nil, fmt.Errorf("Error adding LUKS keys: %v", err)
}
args = append(args, luksArgs...)

if info, err := os.Stat(global.VDDK); err == nil && info.IsDir() {
args = append(args,
"-it", "vddk",
"-io", fmt.Sprintf("vddk-libdir=%s", global.VDDK),
"-io", fmt.Sprintf("vddk-thumbprint=%s", os.Getenv("V2V_fingerprint")),
)
}
var extraArgs []string
if envExtraArgs := os.Getenv("V2V_extra_args"); envExtraArgs != "" {
if err := json.Unmarshal([]byte(envExtraArgs), &extraArgs); err != nil {
return nil, fmt.Errorf("Error parsing extra arguments %v", err)
}
}
args = append(args, extraArgs...)

args = append(args, "--", os.Getenv("V2V_vmName"))
return args, nil
}

func convertVirtV2v() (err error) {
source := os.Getenv("V2V_source")
if source == global.VSPHERE {
if _, err := os.Stat("/etc/secret/cacert"); err == nil {
// use the specified certificate
err = os.Symlink("/etc/secret/cacert", "/opt/ca-bundle.crt")
if err != nil {
fmt.Println("Error creating ca cert link ", err)
os.Exit(1)
}
} else {
// otherwise, keep system pool certificates
err := os.Symlink("/etc/pki/tls/certs/ca-bundle.crt.bak", "/opt/ca-bundle.crt")
if err != nil {
fmt.Println("Error creating ca cert link ", err)
os.Exit(1)
}
}
}

args, err := virtV2vBuildCommand()
if err != nil {
return
}
if err = executeVirtV2v("virt-v2v", args); err != nil {
return
}

xmlFilePath, err := server.GetXMLFile(global.DIR, "xml")
if err != nil {
fmt.Println("Error getting XML file:", err)
return err
}

err = customize.Run(source, xmlFilePath)
if err != nil {
fmt.Println("Error customizing the VM:", err)
return err
}

return
}

func executeVirtV2v(command string, args []string) error {
v2vCmd := exec.Command(command, args...)
monitorCmd := exec.Command("/usr/local/bin/virt-v2v-monitor")
monitorCmd.Stdout = os.Stdout
monitorCmd.Stderr = os.Stderr

var writer *io.PipeWriter
monitorCmd.Stdin, writer = io.Pipe()
v2vCmd.Stdout = writer
v2vCmd.Stderr = writer
defer writer.Close()

if err := monitorCmd.Start(); err != nil {
fmt.Printf("Error executing monitor command: %v\n", err)
return err
}

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
}

return nil
}
28 changes: 3 additions & 25 deletions virt-v2v/cold_test.go → virt-v2v/cmd/entrypoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,12 @@ package main
import (
"strings"
"testing"
)

func TestGenName(t *testing.T) {
cases := []struct {
diskNum int
expected string
}{
{1, "a"},
{26, "z"},
{27, "aa"},
{28, "ab"},
{52, "az"},
{53, "ba"},
{55, "bc"},
{702, "zz"},
{754, "abz"},
}

for _, c := range cases {
got := genName(c.diskNum)
if got != c.expected {
t.Errorf("genName(%d) = %s; want %s", c.diskNum, got, c.expected)
}
}
}
"github.com/konveyor/forklift-controller/virt-v2v/pkg/global"
)

func TestStaticIPs(t *testing.T) {
t.Setenv("V2V_source", VSPHERE)
t.Setenv("V2V_source", global.VSPHERE)
t.Setenv("V2V_libvirtURL", "http://fake.com")
t.Setenv("V2V_secretKey", "fake")
t.Setenv("V2V_vmName", "test")
Expand Down
Loading

0 comments on commit 11ca0f1

Please sign in to comment.