diff --git a/operator/config/manager/manager.yaml b/operator/config/manager/manager.yaml index e81b2d655..c07a9806d 100644 --- a/operator/config/manager/manager.yaml +++ b/operator/config/manager/manager.yaml @@ -76,6 +76,8 @@ spec: value: ${OVIRT_OS_MAP} - name: VSPHERE_OS_MAP value: ${VSPHERE_OS_MAP} + - name: VIRT_CUSTOMIZE_MAP + value: ${VIRT_CUSTOMIZE_MAP} livenessProbe: httpGet: path: /healthz diff --git a/operator/roles/forkliftcontroller/defaults/main.yml b/operator/roles/forkliftcontroller/defaults/main.yml index abd45093f..bfddbd38e 100644 --- a/operator/roles/forkliftcontroller/defaults/main.yml +++ b/operator/roles/forkliftcontroller/defaults/main.yml @@ -22,6 +22,7 @@ controller_configmap_name: "{{ controller_service_name }}-config" controller_service_name: "{{ app_name }}-controller" ovirt_osmap_configmap_name: "forklift-ovirt-osmap" vsphere_osmap_configmap_name: "forklift-vsphere-osmap" +virt_customize_configmap_name: "{{ app_name }}-virt-customize" controller_deployment_name: "{{ controller_service_name }}" controller_container_name: "{{ app_name }}-controller" controller_container_limits_cpu: "500m" diff --git a/operator/roles/forkliftcontroller/templates/controller/deployment-controller.yml.j2 b/operator/roles/forkliftcontroller/templates/controller/deployment-controller.yml.j2 index 917102672..7082b2b8b 100644 --- a/operator/roles/forkliftcontroller/templates/controller/deployment-controller.yml.j2 +++ b/operator/roles/forkliftcontroller/templates/controller/deployment-controller.yml.j2 @@ -111,6 +111,10 @@ spec: - name: VSPHERE_OS_MAP value: {{ vsphere_osmap_configmap_name }} {% endif %} +{% if virt_customize_configmap_name is defined %} + - name: VIRT_CUSTOMIZE_MAP + value: {{ virt_customize_configmap_name }} +{% endif %} {% if controller_profile_kind is defined and controller_profile_path is defined and controller_profile_duration is defined %} - name: PROFILE_KIND value: "{{ controller_profile_kind }}" diff --git a/pkg/controller/plan/kubevirt.go b/pkg/controller/plan/kubevirt.go index e4e60c932..e8d2856c2 100644 --- a/pkg/controller/plan/kubevirt.go +++ b/pkg/controller/plan/kubevirt.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" k8svalidation "k8s.io/apimachinery/pkg/util/validation" @@ -68,8 +69,10 @@ const ( // DV deletion on completion AnnDeleteAfterCompletion = "cdi.kubevirt.io/storage.deleteAfterCompletion" // Max Length for vm name - NameMaxLength = 63 - VddkVolumeName = "vddk-vol-mount" + NameMaxLength = 63 + VddkVolumeName = "vddk-vol-mount" + DynamicScriptsVolumeName = "scripts-volume-mount" + DynamicScriptsMountPath = "/mnt/dynamic_scripts" ) // Labels @@ -1949,6 +1952,28 @@ func (r *KubeVirt) podVolumeMounts(vmVolumes []cnv.Volume, configMap *core.Confi } } + _, exists, err := r.findConfigMapInNamespace(Settings.VirtCustomizeConfigMap, r.Plan.Spec.TargetNamespace) + if err != nil { + err = liberr.Wrap(err) + return + } + if exists { + volumes = append(volumes, core.Volume{ + Name: DynamicScriptsVolumeName, + VolumeSource: core.VolumeSource{ + ConfigMap: &core.ConfigMapVolumeSource{ + LocalObjectReference: core.LocalObjectReference{ + Name: Settings.VirtCustomizeConfigMap, + }, + }, + }, + }) + mounts = append(mounts, core.VolumeMount{ + Name: DynamicScriptsVolumeName, + MountPath: DynamicScriptsMountPath, + }) + } + // Temporary space for VDDK library volumes = append(volumes, core.Volume{ Name: VddkVolumeName, @@ -2058,6 +2083,33 @@ func (r *KubeVirt) libvirtDomain(vmCr *VirtualMachine, pvcs []*core.PersistentVo return } +func (r *KubeVirt) findConfigMapInNamespace(name string, namespace string) (configMap *core.ConfigMap, exists bool, err error) { + if err != nil { + return + } + list := &core.ConfigMapList{} + nameField := "metadata.name" + namespaceField := "metadata.namespace" + err = r.Destination.Client.List( + context.TODO(), + list, + &client.ListOptions{ + FieldSelector: fields.SelectorFromSet(map[string]string{ + nameField: name, + namespaceField: namespace, + }), + }, + ) + if err != nil { + err = liberr.Wrap(err) + return + } + if len(list.Items) > 0 { + return &list.Items[0], true, nil + } + return nil, false, nil +} + // Ensure the config map exists on the destination. func (r *KubeVirt) ensureConfigMap(vmRef ref.Ref) (configMap *core.ConfigMap, err error) { _, err = r.Source.Inventory.VM(&vmRef) diff --git a/pkg/settings/migration.go b/pkg/settings/migration.go index a32ed75b1..70413e400 100644 --- a/pkg/settings/migration.go +++ b/pkg/settings/migration.go @@ -26,6 +26,7 @@ const ( CleanupRetries = "CLEANUP_RETRIES" OvirtOsConfigMap = "OVIRT_OS_MAP" VsphereOsConfigMap = "VSPHERE_OS_MAP" + VirtCustomizeConfigMap = "VIRT_CUSTOMIZE_MAP" VddkJobActiveDeadline = "VDDK_JOB_ACTIVE_DEADLINE" VirtV2vExtraArgs = "VIRT_V2V_EXTRA_ARGS" VirtV2vExtraConfConfigMap = "VIRT_V2V_EXTRA_CONF_CONFIG_MAP" @@ -61,6 +62,8 @@ type Migration struct { OvirtOsConfigMap string // vSphere OS config map name VsphereOsConfigMap string + // vSphere OS config map name + VirtCustomizeConfigMap string // Active deadline for VDDK validation job VddkJobActiveDeadline int // Additional arguments for virt-v2v @@ -89,6 +92,11 @@ func (r *Migration) Load() (err error) { if r.SnapshotStatusCheckRate, err = getPositiveEnvLimit(SnapshotStatusCheckRate, 10); err != nil { return liberr.Wrap(err) } + if virtCustomizeConfigMap, ok := os.LookupEnv(VirtCustomizeConfigMap); ok { + r.VirtCustomizeConfigMap = virtCustomizeConfigMap + } else if Settings.Role.Has(MainRole) { + return liberr.Wrap(fmt.Errorf("failed to find environment variable %s", VirtCustomizeConfigMap)) + } if r.CleanupRetries, err = getPositiveEnvLimit(CleanupRetries, 10); err != nil { return liberr.Wrap(err) } diff --git a/virt-v2v/pkg/customize/BUILD.bazel b/virt-v2v/pkg/customize/BUILD.bazel index 37ecf9a12..ec8889d9b 100644 --- a/virt-v2v/pkg/customize/BUILD.bazel +++ b/virt-v2v/pkg/customize/BUILD.bazel @@ -6,13 +6,14 @@ go_library( "image.go", "rhel.go", "windows.go", + "utils.go", ], embedsrcs = [ "scripts/rhel/firstboot/README.md", "scripts/rhel/run/README.md", "scripts/rhel/run/network_config_util.sh", "scripts/windows/9999-restore_config.ps1", - "scripts/windows/9999-restore_config_init.bat", + "scripts/windows/9999-run-mtv-ps-scripts.bat", "scripts/windows/firstboot.bat", "scripts/rhel/run/ifcfg-double-quotes-test.d/expected-udev.rule", "scripts/rhel/run/ifcfg-double-quotes-test.d/root/etc/sysconfig/network-scripts/ifcfg-eth0", diff --git a/virt-v2v/pkg/customize/image.go b/virt-v2v/pkg/customize/image.go index 67b88e7fc..bb4cacf47 100644 --- a/virt-v2v/pkg/customize/image.go +++ b/virt-v2v/pkg/customize/image.go @@ -22,6 +22,7 @@ type DomainExecFunc func(args ...string) error func Run(disks []string, operatingSystem string) error { var err error + fmt.Printf("Customizing disks '%s'\n", disks) // Customization for vSphere source. t := utils.EmbedTool{Filesystem: &scriptFS} // windows diff --git a/virt-v2v/pkg/customize/rhel.go b/virt-v2v/pkg/customize/rhel.go index e076697ec..96076a96d 100644 --- a/virt-v2v/pkg/customize/rhel.go +++ b/virt-v2v/pkg/customize/rhel.go @@ -4,14 +4,14 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strings" + "github.com/konveyor/forklift-controller/virt-v2v/pkg/global" "github.com/konveyor/forklift-controller/virt-v2v/pkg/utils" ) func CustomizeLinux(execFunc DomainExecFunc, disks []string, dir string, t FileSystemTool) error { - fmt.Printf("Customizing disks '%v'\n", disks) - var extraArgs []string // Step 1: Create files from the filesystem @@ -24,23 +24,31 @@ func CustomizeLinux(execFunc DomainExecFunc, disks []string, dir string, t FileS return err } - // Step 3: Add scripts - if err := addRunScripts(&extraArgs, dir); err != nil { + // Step 3: Add dynamic scripts from the configmap + if _, err := os.Stat(global.DYNAMIC_SCRIPTS_MOUNT_PATH); !os.IsNotExist(err) { + fmt.Println("Adding linux dynamic scripts") + if err = addRhelDynamicScripts(&extraArgs, global.DYNAMIC_SCRIPTS_MOUNT_PATH); err != nil { + return err + } + } + + // Step 4: Add scripts from embedded FS + if err := addRhelRunScripts(&extraArgs, dir); err != nil { return err } - if err := addFirstbootScripts(&extraArgs, dir); err != nil { + if err := addRhelFirstbootScripts(&extraArgs, dir); err != nil { return err } - // Step 4: Add the disks to customize + // Step 5: Add the disks to customize addDisksToCustomize(&extraArgs, disks) - // Step 5: Adds LUKS keys, if they exist + // Step 6: Adds LUKS keys, if they exist if err := addLuksKeysToCustomize(&extraArgs); err != nil { return err } - // Step 6: Execute the customization with the collected arguments + // Step 7: Execute the customization with the collected arguments if err := execFunc(extraArgs...); err != nil { return fmt.Errorf("failed to execute domain customization: %w", err) } @@ -65,11 +73,11 @@ func handleStaticIPConfiguration(extraArgs *[]string, dir string) error { return nil } -// addFirstbootScripts appends firstboot script arguments to extraArgs -func addFirstbootScripts(extraArgs *[]string, dir string) error { +// addRhelFirstbootScripts appends firstboot script arguments to extraArgs +func addRhelFirstbootScripts(extraArgs *[]string, dir string) error { firstbootScriptsPath := filepath.Join(dir, "scripts", "rhel", "firstboot") - firstBootScripts, err := getScripts(firstbootScriptsPath) + firstBootScripts, err := getScriptsWithSuffix(firstbootScriptsPath, global.SHELL_SUFFIX) if err != nil { return err } @@ -83,11 +91,11 @@ func addFirstbootScripts(extraArgs *[]string, dir string) error { return nil } -// addRunScripts appends run script arguments to extraArgs -func addRunScripts(extraArgs *[]string, dir string) error { +// addRhelRunScripts appends run script arguments to extraArgs +func addRhelRunScripts(extraArgs *[]string, dir string) error { runScriptsPath := filepath.Join(dir, "scripts", "rhel", "run") - runScripts, err := getScripts(runScriptsPath) + runScripts, err := getScriptsWithSuffix(runScriptsPath, global.SHELL_SUFFIX) if err != nil { return err } @@ -101,29 +109,6 @@ func addRunScripts(extraArgs *[]string, dir string) error { return nil } -// getScripts retrieves all .sh scripts from the specified directory -func getScripts(directory string) ([]string, error) { - files, err := os.ReadDir(directory) - if err != nil { - return nil, fmt.Errorf("failed to read firstboot scripts directory: %w", err) - } - - var scripts []string - for _, file := range files { - if !file.IsDir() && strings.HasSuffix(file.Name(), ".sh") && !strings.HasPrefix(file.Name(), "test-") { - scriptPath := filepath.Join(directory, file.Name()) - scripts = append(scripts, scriptPath) - } - } - - return scripts, nil -} - -// addDisksToCustomize appends disk arguments to extraArgs -func addDisksToCustomize(extraArgs *[]string, disks []string) { - *extraArgs = append(*extraArgs, utils.GetScriptArgs("add", disks...)...) -} - // addLuksKeysToCustomize appends key arguments to extraArgs func addLuksKeysToCustomize(extraArgs *[]string) error { luksArgs, err := utils.AddLUKSKeys() @@ -134,3 +119,19 @@ func addLuksKeysToCustomize(extraArgs *[]string) error { return nil } + +func addRhelDynamicScripts(extraArgs *[]string, dir string) error { + dynamicScripts, err := getScriptsWithRegex(dir, global.LINUX_DYNAMIC_REGEX) + if err != nil { + return err + } + for _, script := range dynamicScripts { + fmt.Printf("Adding linux dynamic scripts '%s'\n", script) + r := regexp.MustCompile(global.LINUX_DYNAMIC_REGEX) + groups := r.FindStringSubmatch(filepath.Base(script)) + // Option from the second regex group `(run|firstboot)` + action := groups[2] + *extraArgs = append(*extraArgs, utils.GetScriptArgs(action, script)...) + } + return nil +} diff --git a/virt-v2v/pkg/customize/rhel_test.go b/virt-v2v/pkg/customize/rhel_test.go index 20c4e63b2..5d18bc1c8 100644 --- a/virt-v2v/pkg/customize/rhel_test.go +++ b/virt-v2v/pkg/customize/rhel_test.go @@ -6,6 +6,8 @@ import ( "path/filepath" "reflect" "testing" + + "github.com/konveyor/forklift-controller/virt-v2v/pkg/global" ) type MockEmbedTool struct { @@ -125,9 +127,9 @@ func TestAddFirstbootScripts(t *testing.T) { } extraArgs := []string{} - err = addFirstbootScripts(&extraArgs, tempDir) + err = addRhelFirstbootScripts(&extraArgs, tempDir) if err != nil { - t.Fatalf("addFirstbootScripts returned an error: %v", err) + t.Fatalf("addRhelFirstbootScripts returned an error: %v", err) } if len(extraArgs) == 0 || !contains(extraArgs, "--firstboot") { @@ -148,9 +150,9 @@ func TestAddRunScripts(t *testing.T) { } extraArgs := []string{} - err = addRunScripts(&extraArgs, tempDir) + err = addRhelRunScripts(&extraArgs, tempDir) if err != nil { - t.Fatalf("addRunScripts returned an error: %v", err) + t.Fatalf("addRhelRunScripts returned an error: %v", err) } if len(extraArgs) == 0 || !contains(extraArgs, "--run") { @@ -170,9 +172,9 @@ func TestGetScripts(t *testing.T) { t.Fatalf("Error WriteFile: %v", err) } - scripts, err := getScripts(tempDir) + scripts, err := getScriptsWithSuffix(tempDir, global.SHELL_SUFFIX) if err != nil { - t.Fatalf("getScripts returned an error: %v", err) + t.Fatalf("getScriptsWithSuffix returned an error: %v", err) } expectedScripts := []string{ @@ -180,7 +182,7 @@ func TestGetScripts(t *testing.T) { filepath.Join(tempDir, "test2.sh"), } if !reflect.DeepEqual(scripts, expectedScripts) { - t.Fatalf("getScripts returned incorrect scripts: got %v, want %v", scripts, expectedScripts) + t.Fatalf("getScriptsWithSuffix returned incorrect scripts: got %v, want %v", scripts, expectedScripts) } } @@ -213,9 +215,9 @@ func TestAddFirstbootScripts_NoScripts(t *testing.T) { } extraArgs := []string{} - err = addFirstbootScripts(&extraArgs, tempDir) + err = addRhelFirstbootScripts(&extraArgs, tempDir) if err != nil { - t.Fatalf("addFirstbootScripts returned an error: %v", err) + t.Fatalf("addRhelFirstbootScripts returned an error: %v", err) } // Ensure no "--firstboot" argument is added when no scripts are found @@ -233,9 +235,9 @@ func TestAddRunScripts_NoScripts(t *testing.T) { } extraArgs := []string{} - err = addRunScripts(&extraArgs, tempDir) + err = addRhelRunScripts(&extraArgs, tempDir) if err != nil { - t.Fatalf("addRunScripts returned an error: %v", err) + t.Fatalf("addRhelRunScripts returned an error: %v", err) } // Ensure no "--run" argument is added when no scripts are found @@ -283,9 +285,9 @@ func TestAddFirstbootScripts_ReadDirFails(t *testing.T) { tempDir := "/invalid-dir" extraArgs := []string{} - err := addFirstbootScripts(&extraArgs, tempDir) + err := addRhelFirstbootScripts(&extraArgs, tempDir) if err == nil { - t.Fatalf("Expected error in addFirstbootScripts due to read failure, got nil") + t.Fatalf("Expected error in addRhelFirstbootScripts due to read failure, got nil") } } @@ -294,8 +296,8 @@ func TestAddRunScripts_ReadDirFails(t *testing.T) { tempDir := "/invalid-dir" extraArgs := []string{} - err := addRunScripts(&extraArgs, tempDir) + err := addRhelRunScripts(&extraArgs, tempDir) if err == nil { - t.Fatalf("Expected error in addRunScripts due to read failure, got nil") + t.Fatalf("Expected error in addRhelRunScripts due to read failure, got nil") } } diff --git a/virt-v2v/pkg/customize/scripts/windows/9999-restore_config.ps1 b/virt-v2v/pkg/customize/scripts/windows/9999-restore_config.ps1 index 9e89d58eb..45f4264b0 100644 --- a/virt-v2v/pkg/customize/scripts/windows/9999-restore_config.ps1 +++ b/virt-v2v/pkg/customize/scripts/windows/9999-restore_config.ps1 @@ -1,15 +1,10 @@ # Migration - Reconfigure disks # Initialize the log file created by the generated script -$logFile = $env:SystemDrive + '\Program Files\Guestfs\Firstboot\scripts-done\9999-restore_config.txt' -Write-Output ('Starting 9999-restore_config.ps1 script') > $logFile -Write-Output ('') >> $logFile -# script section to re-enable all offline drives # Re-enable all offline drives -Write-Output ('Re-enabling all offline drives') >> $logFile +Write-Host 'Re-enabling all offline drives' Get-Disk | Where { $_.FriendlyName -like '*VirtIO*' } | % { - Write-Output (' - ' + $_.Number + ': ' + $_.FriendlyName + '(' + [math]::Round($_.Size/1GB,2) + 'GB)') >> $logFile + Write-Host (' - ' + $_.Number + ': ' + $_.FriendlyName + '(' + [math]::Round($_.Size/1GB,2) + 'GB)') $_ | Set-Disk -IsOffline $false $_ | Set-Disk -IsReadOnly $false } -Write-Output ('') >> $logFile diff --git a/virt-v2v/pkg/customize/scripts/windows/9999-restore_config_init.bat b/virt-v2v/pkg/customize/scripts/windows/9999-restore_config_init.bat deleted file mode 100644 index 06208d4e0..000000000 --- a/virt-v2v/pkg/customize/scripts/windows/9999-restore_config_init.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off -echo Restore configuration disks -PowerShell -NoProfile -ExecutionPolicy Bypass -Command "\'Program Files'\Guestfs\Firstboot\Scripts\9999-restore_config.ps1" diff --git a/virt-v2v/pkg/customize/scripts/windows/9999-run-mtv-ps-scripts.bat b/virt-v2v/pkg/customize/scripts/windows/9999-run-mtv-ps-scripts.bat new file mode 100644 index 000000000..c35c57dab --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/windows/9999-run-mtv-ps-scripts.bat @@ -0,0 +1,14 @@ +@echo off + +set firstboot=C:\Program Files\Guestfs\Firstboot + +set scripts=%firstboot%\scripts +set scripts_done=%firstboot%\scripts-done +echo Running MTV first boot scripts +for %%f in ("%scripts%"\*.ps1) do ( + echo running "%%f" + PowerShell -NoProfile -ExecutionPolicy Bypass -File "%%~f" + set elvl=!errorlevel! + echo .... exit code !elvl! + move "%%f" "%scripts_done%" +) \ No newline at end of file diff --git a/virt-v2v/pkg/customize/utils.go b/virt-v2v/pkg/customize/utils.go new file mode 100644 index 000000000..6ae00cbe8 --- /dev/null +++ b/virt-v2v/pkg/customize/utils.go @@ -0,0 +1,56 @@ +package customize + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/konveyor/forklift-controller/virt-v2v/pkg/utils" +) + +// getScriptsWithSuffix retrieves all scripts with suffix from the specified directory +func getScriptsWithSuffix(directory string, suffix string) ([]string, error) { + files, err := os.ReadDir(directory) + if err != nil { + return nil, fmt.Errorf("failed to read scripts directory: %w", err) + } + + var scripts []string + for _, file := range files { + if !file.IsDir() && strings.HasSuffix(file.Name(), suffix) && !strings.HasPrefix(file.Name(), "test-") { + scriptPath := filepath.Join(directory, file.Name()) + scripts = append(scripts, scriptPath) + } + } + + return scripts, nil +} + +// addDisksToCustomize appends disk arguments to extraArgs +func addDisksToCustomize(extraArgs *[]string, disks []string) { + *extraArgs = append(*extraArgs, utils.GetScriptArgs("add", disks...)...) +} + +func formatUpload(src string, dst string) string { + return fmt.Sprintf("%s:%s", src, dst) +} + +// getScriptsWithRegex retrieves all scripts with suffix from the specified directory +func getScriptsWithRegex(directory string, regex string) ([]string, error) { + files, err := os.ReadDir(directory) + if err != nil { + return nil, fmt.Errorf("failed to read scripts directory: %w", err) + } + + r := regexp.MustCompile(regex) + var scripts []string + for _, file := range files { + if !file.IsDir() && r.MatchString(file.Name()) { + scriptPath := filepath.Join(directory, file.Name()) + scripts = append(scripts, scriptPath) + } + } + return scripts, nil +} diff --git a/virt-v2v/pkg/customize/windows.go b/virt-v2v/pkg/customize/windows.go index 1e94da169..f1af89cfa 100644 --- a/virt-v2v/pkg/customize/windows.go +++ b/virt-v2v/pkg/customize/windows.go @@ -2,16 +2,13 @@ package customize import ( "fmt" + "os" "path/filepath" + "github.com/konveyor/forklift-controller/virt-v2v/pkg/global" "github.com/konveyor/forklift-controller/virt-v2v/pkg/utils" ) -const ( - WIN_FIRSTBOOT_PATH = "/Program Files/Guestfs/Firstboot" - WIN_FIRSTBOOT_SCRIPTS_PATH = "/Program Files/Guestfs/Firstboot/scripts" -) - // CustomizeWindows customizes a windows disk image by uploading scripts. // // The function writes two bash scripts to the specified local tmp directory, @@ -23,27 +20,56 @@ const ( // Returns: // - error: An error if something goes wrong during the process, or nil if successful. func CustomizeWindows(execFunc DomainExecFunc, disks []string, dir string, t FileSystemTool) error { - fmt.Printf("Customizing disks '%s'", disks) err := t.CreateFilesFromFS(dir) + if err != nil { + return fmt.Errorf("failed to create files from filesystem: %w", err) + } + + var extraArgs []string + + if _, err = os.Stat(global.DYNAMIC_SCRIPTS_MOUNT_PATH); !os.IsNotExist(err) { + fmt.Println("Adding windows dynamic scripts") + err = addWinDynamicScripts(&extraArgs, global.DYNAMIC_SCRIPTS_MOUNT_PATH) + if err != nil { + return err + } + } + + addWinFirstbootScripts(&extraArgs, dir) + + addDisksToCustomize(&extraArgs, disks) + + err = execFunc(extraArgs...) if err != nil { return err } + return nil +} + +// addRhelFirstbootScripts appends firstboot script arguments to extraArgs +func addWinFirstbootScripts(extraArgs *[]string, dir string) { windowsScriptsPath := filepath.Join(dir, "scripts", "windows") - initPath := filepath.Join(windowsScriptsPath, "9999-restore_config_init.bat") + initPath := filepath.Join(windowsScriptsPath, "9999-run-mtv-ps-scripts.bat") restoreScriptPath := filepath.Join(windowsScriptsPath, "9999-restore_config.ps1") firstbootPath := filepath.Join(windowsScriptsPath, "firstboot.bat") // Upload scripts to the windows - uploadScriptPath := fmt.Sprintf("%s:%s", restoreScriptPath, WIN_FIRSTBOOT_SCRIPTS_PATH) - uploadInitPath := fmt.Sprintf("%s:%s", initPath, WIN_FIRSTBOOT_SCRIPTS_PATH) - uploadFirstbootPath := fmt.Sprintf("%s:%s", firstbootPath, WIN_FIRSTBOOT_PATH) + uploadScriptPath := formatUpload(restoreScriptPath, global.WIN_FIRSTBOOT_SCRIPTS_PATH) + uploadInitPath := formatUpload(initPath, global.WIN_FIRSTBOOT_SCRIPTS_PATH) + uploadFirstbootPath := formatUpload(firstbootPath, global.WIN_FIRSTBOOT_PATH) - var extraArgs []string - extraArgs = append(extraArgs, utils.GetScriptArgs("upload", uploadScriptPath, uploadInitPath, uploadFirstbootPath)...) - extraArgs = append(extraArgs, utils.GetScriptArgs("add", disks...)...) - err = execFunc(extraArgs...) + *extraArgs = append(*extraArgs, utils.GetScriptArgs("upload", uploadScriptPath, uploadInitPath, uploadFirstbootPath)...) +} + +func addWinDynamicScripts(extraArgs *[]string, dir string) error { + dynamicScripts, err := getScriptsWithRegex(dir, global.WINDOWS_DYNAMIC_REGEX) if err != nil { return err } + for _, script := range dynamicScripts { + fmt.Printf("Adding windows dynamic scripts '%s'\n", script) + upload := formatUpload(script, filepath.Join(global.WIN_FIRSTBOOT_SCRIPTS_PATH, filepath.Base(script))) + *extraArgs = append(*extraArgs, utils.GetScriptArgs("upload", upload)...) + } return nil } diff --git a/virt-v2v/pkg/global/variables.go b/virt-v2v/pkg/global/variables.go index 2f9d30ddd..8d9c589a2 100644 --- a/virt-v2v/pkg/global/variables.go +++ b/virt-v2v/pkg/global/variables.go @@ -12,6 +12,13 @@ const ( VDDK = "/opt/vmware-vix-disklib-distrib" LUKSDIR = "/etc/luks" + WIN_FIRSTBOOT_PATH = "/Program Files/Guestfs/Firstboot" + WIN_FIRSTBOOT_SCRIPTS_PATH = "/Program Files/Guestfs/Firstboot/scripts" + DYNAMIC_SCRIPTS_MOUNT_PATH = "/mnt/dynamic_scripts" + WINDOWS_DYNAMIC_REGEX = `^([0-9]+_win_firstboot(([\w\-]*).ps1))$` + LINUX_DYNAMIC_REGEX = `^([0-9]+_linux_(run|firstboot)(([\w\-]*).sh))$` + SHELL_SUFFIX = ".sh" + LETTERS = "abcdefghijklmnopqrstuvwxyz" LETTERS_LENGTH = len(LETTERS) ) diff --git a/virt-v2v/pkg/utils/embed-tool.go b/virt-v2v/pkg/utils/embed-tool.go index 7b0afb43f..4c02cc1e4 100644 --- a/virt-v2v/pkg/utils/embed-tool.go +++ b/virt-v2v/pkg/utils/embed-tool.go @@ -70,8 +70,8 @@ func (t *EmbedTool) writeFileFromFS(src, dst string) error { return nil } -// getAllFilenames gets all files located inside the embedded Filesystem. -// Example of one path `scripts/windows/9999-restore_config_init.bat`. +// getAllFilenames gets all files located inside the embedded filesystem. +// Example of one path `scripts/windows/9999-run-mtv-ps-scripts.bat`. // // Returns: // - []files: The file paths which are located inside the embedded Filesystem.