packer-cn/builder/vmware/common/step_clean_vmx.go

133 lines
4.4 KiB
Go

package common
import (
"context"
"fmt"
"log"
"strings"
"github.com/hashicorp/packer/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
)
// This step cleans up the VMX by removing or changing this prior to
// being ready for use.
//
// Uses:
// ui packersdk.Ui
// vmx_path string
//
// Produces:
// <nothing>
type StepCleanVMX struct {
RemoveEthernetInterfaces bool
VNCEnabled bool
}
func (s StepCleanVMX) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packersdk.Ui)
vmxPath := state.Get("vmx_path").(string)
ui.Say("Cleaning VMX prior to finishing up...")
vmxData, err := ReadVMX(vmxPath)
if err != nil {
state.Put("error", fmt.Errorf("Error reading VMX: %s", err))
return multistep.ActionHalt
}
// Grab our list of devices added during the build out of the statebag
for _, device := range state.Get("temporaryDevices").([]string) {
// Instead of doing this in one pass which would be more efficient,
// we do it per device-type so that the logic appears to be the same
// as the prior implementation.
// Walk through all the devices that were temporarily added and figure
// out which type it is in order to figure out how to disable it.
// Right now only floppy, cdrom devices, ethernet, and devices that use
// ".present" are supported.
if strings.HasPrefix(device, "floppy") {
// We can identify a floppy device because it begins with "floppy"
ui.Message(fmt.Sprintf("Unmounting %s from VMX...", device))
// Delete the floppy%d entries so the floppy is no longer mounted
for k := range vmxData {
if strings.HasPrefix(k, fmt.Sprintf("%s.", device)) {
log.Printf("Deleting key for floppy device: %s", k)
delete(vmxData, k)
}
}
vmxData[fmt.Sprintf("%s.present", device)] = "FALSE"
} else if strings.HasPrefix(vmxData[fmt.Sprintf("%s.devicetype", device)], "cdrom-") {
// We can identify something is a cdrom if it has a ".devicetype"
// attribute that begins with "cdrom-"
ui.Message(fmt.Sprintf("Detaching ISO from CD-ROM device %s...", device))
// Simply turn the CDROM device into a native cdrom instead of an iso
vmxData[fmt.Sprintf("%s.devicetype", device)] = "cdrom-raw"
vmxData[fmt.Sprintf("%s.filename", device)] = "auto detect"
vmxData[fmt.Sprintf("%s.clientdevice", device)] = "TRUE"
} else if strings.HasPrefix(device, "ethernet") && s.RemoveEthernetInterfaces {
// We can identify an ethernet device because it begins with "ethernet"
// Although we're supporting this, as of now it's not in use due
// to these interfaces not ever being added to the "temporaryDevices" statebag.
ui.Message(fmt.Sprintf("Removing %s interface...", device))
// Delete the ethernet%d entries so the ethernet interface is removed.
// This corresponds to the same logic defined below.
for k := range vmxData {
if strings.HasPrefix(k, fmt.Sprintf("%s.", device)) {
log.Printf("Deleting key for ethernet device: %s", k)
delete(vmxData, k)
}
}
} else {
// First check to see if we can simply disable the device
if _, ok := vmxData[fmt.Sprintf("%s.present", device)]; ok {
ui.Message(fmt.Sprintf("Disabling device %s of an unknown device type...", device))
vmxData[fmt.Sprintf("%s.present", device)] = "FALSE"
} else {
// Okay, so this wasn't so simple. Let's just log info about the
// device and not tamper with any of its keys
log.Printf("Refusing to remove device due to being of an unsupported type: %s\n", device)
for k := range vmxData {
if strings.HasPrefix(k, fmt.Sprintf("%s.", device)) {
log.Printf("Leaving unsupported device key: %s\n", k)
}
}
}
}
}
// Disable the VNC server if necessary
if s.VNCEnabled {
ui.Message("Disabling VNC server...")
vmxData["remotedisplay.vnc.enabled"] = "FALSE"
}
// Disable any ethernet devices if necessary
if s.RemoveEthernetInterfaces {
ui.Message("Removing Ethernet Interfaces...")
for k := range vmxData {
if strings.HasPrefix(k, "ethernet") {
log.Printf("Deleting key for ethernet device: %s", k)
delete(vmxData, k)
}
}
}
// Rewrite the VMX
if err := WriteVMX(vmxPath, vmxData); err != nil {
state.Put("error", fmt.Errorf("Error writing VMX: %s", err))
return multistep.ActionHalt
}
return multistep.ActionContinue
}
func (StepCleanVMX) Cleanup(multistep.StateBag) {}