From 27b16cee0ab09895222b064e817995b166d8d518 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Mon, 3 Dec 2018 17:43:02 -0600 Subject: [PATCH 1/5] Added a new "temporaryDevices" key to the VMware builders' statebag in order to keep track of devices that were temporarily added during build and need to be removed later by StepCleanVMX. --- builder/vmware/iso/builder.go | 1 + builder/vmware/vmx/builder.go | 1 + 2 files changed, 2 insertions(+) diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index dc49f157d..9b37d8503 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -65,6 +65,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state.Put("ui", ui) state.Put("sshConfig", &b.config.SSHConfig) state.Put("driverConfig", &b.config.DriverConfig) + state.Put("temporaryDevices", []string{}) // Devices (in .vmx) created by packer during building steps := []multistep.Step{ &vmwcommon.StepPrepareTools{ diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 22ed9555d..e3f6a8c8b 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -67,6 +67,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state.Put("ui", ui) state.Put("sshConfig", &b.config.SSHConfig) state.Put("driverConfig", &b.config.DriverConfig) + state.Put("temporaryDevices", []string{}) // Devices (in .vmx) created by packer during building // Build the steps. steps := []multistep.Step{ From 3512c3c5eaacad21a9130331c9e8f3fe36af4716 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Mon, 3 Dec 2018 17:44:23 -0600 Subject: [PATCH 2/5] Updated StepConfigureVMX to add the floppy disk device to the "temporaryDevices" statebag so that StepCleanVMX can remove it later. --- builder/vmware/common/step_configure_vmx.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/builder/vmware/common/step_configure_vmx.go b/builder/vmware/common/step_configure_vmx.go index 73f0d60fb..a4ebd7ae6 100644 --- a/builder/vmware/common/step_configure_vmx.go +++ b/builder/vmware/common/step_configure_vmx.go @@ -65,13 +65,22 @@ func (s *StepConfigureVMX) Run(_ context.Context, state multistep.StateBag) mult // Set a floppy disk, but only if we should if !s.SkipFloppy { + // Grab list of temporary builder devices so we can append the floppy to it + tmpBuildDevices := state.Get("temporaryDevices").([]string) + // Set a floppy disk if we have one if floppyPathRaw, ok := state.GetOk("floppy_path"); ok { log.Println("Floppy path present, setting in VMX") vmxData["floppy0.present"] = "TRUE" vmxData["floppy0.filetype"] = "file" vmxData["floppy0.filename"] = floppyPathRaw.(string) + + // Add it to our list of build devices to later remove + tmpBuildDevices = append(tmpBuildDevices, "floppy0") } + + // Build the list back in our statebag + state.Put("temporaryDevices", tmpBuildDevices) } // If the build is taking place on a remote ESX server, the displayName From e0d3861e81e36b10779afbc0875b4cdd29e54a21 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Mon, 3 Dec 2018 17:46:02 -0600 Subject: [PATCH 3/5] Updated StepCreateVMX to add the CDROM device that packer uses to the "temporaryDevices" statebag so that StepCleanVMX can unmount its ISO later. --- builder/vmware/iso/step_create_vmx.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/builder/vmware/iso/step_create_vmx.go b/builder/vmware/iso/step_create_vmx.go index 4fa5254f8..5a46c14ef 100644 --- a/builder/vmware/iso/step_create_vmx.go +++ b/builder/vmware/iso/step_create_vmx.go @@ -243,6 +243,13 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist return multistep.ActionHalt } + /// Now that we figured out the CDROM device to add, store it + /// to the list of temporary build devices in our statebag + tmpBuildDevices := state.Get("temporaryDevices").([]string) + tmpCdromDevice := fmt.Sprintf("%s0:%s", templateData.CDROMType, templateData.CDROMType_PrimarySecondary) + tmpBuildDevices = append(tmpBuildDevices, tmpCdromDevice) + state.Put("temporaryDevices", tmpBuildDevices) + /// Assign the network adapter type into the template if one was specified. network_adapter := strings.ToLower(config.HWConfig.NetworkAdapterType) if network_adapter != "" { From fa4998e1ec5e21553535bf7de0930a7ad409404d Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Mon, 3 Dec 2018 17:47:23 -0600 Subject: [PATCH 4/5] Modified StepCleanVMX to walk through the "temporaryDevices" statebag so that we can disable or remove its devices cleanly. This gets rid of the regex hack that was previously used to identify a cdrom-image. --- builder/vmware/common/step_clean_vmx.go | 86 +++++++++++++++++++------ 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/builder/vmware/common/step_clean_vmx.go b/builder/vmware/common/step_clean_vmx.go index db0db5aac..1db8a81ee 100644 --- a/builder/vmware/common/step_clean_vmx.go +++ b/builder/vmware/common/step_clean_vmx.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log" - "regexp" "strings" "github.com/hashicorp/packer/helper/multistep" @@ -37,40 +36,85 @@ func (s StepCleanVMX) Run(_ context.Context, state multistep.StateBag) multistep return multistep.ActionHalt } - // Delete the floppy0 entries so the floppy is no longer mounted - ui.Message("Unmounting floppy from VMX...") - for k := range vmxData { - if strings.HasPrefix(k, "floppy0.") { - log.Printf("Deleting key: %s", k) - delete(vmxData, k) - } - } - vmxData["floppy0.present"] = "FALSE" + // 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. - devRe := regexp.MustCompile(`^(ide|sata)\d:\d\.`) - for k, v := range vmxData { - ide := devRe.FindString(k) - if ide == "" || v != "cdrom-image" { - continue - } + // 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)) - ui.Message("Detaching ISO from CD-ROM 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" - vmxData[ide+"devicetype"] = "cdrom-raw" - vmxData[ide+"filename"] = "auto detect" - vmxData[ide+"clientdevice"] = "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: %s", k) + log.Printf("Deleting key for ethernet device: %s", k) delete(vmxData, k) } } From 96bdf17d2ecc2a04803fce79190f681306017225 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Mon, 3 Dec 2018 18:03:02 -0600 Subject: [PATCH 5/5] Added knowledge of the "temporaryDevices" statebag to the StepCleanVMX tests for the VMware builders. --- builder/vmware/common/step_clean_vmx_test.go | 12 ++++++++++++ builder/vmware/common/step_test.go | 1 + 2 files changed, 13 insertions(+) diff --git a/builder/vmware/common/step_clean_vmx_test.go b/builder/vmware/common/step_clean_vmx_test.go index 0f4df3df2..3987fb2c4 100644 --- a/builder/vmware/common/step_clean_vmx_test.go +++ b/builder/vmware/common/step_clean_vmx_test.go @@ -40,8 +40,12 @@ func TestStepCleanVMX_floppyPath(t *testing.T) { t.Fatalf("err: %s", err) } + // Set the path to the temporary vmx state.Put("vmx_path", vmxPath) + // Add the floppy device to the list of temporary build devices + state.Put("temporaryDevices", []string{"floppy0"}) + // Test the run if action := step.Run(context.Background(), state); action != multistep.ActionContinue { t.Fatalf("bad action: %#v", action) @@ -89,8 +93,12 @@ func TestStepCleanVMX_isoPath(t *testing.T) { t.Fatalf("err: %s", err) } + // Set the path to the temporary vmx state.Put("vmx_path", vmxPath) + // Add the cdrom device to the list of temporary build devices + state.Put("temporaryDevices", []string{"ide0:0"}) + // Test the run if action := step.Run(context.Background(), state); action != multistep.ActionContinue { t.Fatalf("bad action: %#v", action) @@ -141,8 +149,12 @@ func TestStepCleanVMX_ethernet(t *testing.T) { t.Fatalf("err: %s", err) } + // Set the path to the temporary vmx state.Put("vmx_path", vmxPath) + // TODO: Add the ethernet devices to the list of temporary build devices + // state.Put("temporaryDevices", []string{"ethernet0", "ethernet1"}) + // Test the run if action := step.Run(context.Background(), state); action != multistep.ActionContinue { t.Fatalf("bad action: %#v", action) diff --git a/builder/vmware/common/step_test.go b/builder/vmware/common/step_test.go index c8a12abb6..d1daffab5 100644 --- a/builder/vmware/common/step_test.go +++ b/builder/vmware/common/step_test.go @@ -15,5 +15,6 @@ func testState(t *testing.T) multistep.StateBag { Reader: new(bytes.Buffer), Writer: new(bytes.Buffer), }) + state.Put("temporaryDevices", []string{}) return state }