From ebcd6174d41c953bdb09df4ce069dbd216eaefcd Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Tue, 30 Oct 2018 03:18:57 +0300 Subject: [PATCH] Optionally use SATA controller for CD-ROM devices (#174) --- driver/vm.go | 27 ++++++++++++------- driver/vm_cdrom.go | 2 +- examples/macos/macos-10.13.json | 1 + iso/builder.go | 8 +++--- iso/builder_acc_test.go | 48 +++++++++++++++++++++++++++++++++ iso/config.go | 1 + iso/step_add_cdrom.go | 26 +++++++++++++----- 7 files changed, 92 insertions(+), 21 deletions(-) diff --git a/driver/vm.go b/driver/vm.go index 690d40869..5214b6d14 100644 --- a/driver/vm.go +++ b/driver/vm.go @@ -115,10 +115,6 @@ func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) { devices := object.VirtualDeviceList{} - devices, err = addIDE(devices) - if err != nil { - return nil, err - } devices, err = addDisk(d, devices, config) if err != nil { return nil, err @@ -477,23 +473,34 @@ func addIDE(devices object.VirtualDeviceList) (object.VirtualDeviceList, error) return devices, nil } -func (vm *VirtualMachine) AddCdrom(isoPath string) error { +func (vm *VirtualMachine) AddCdrom(controllerType string, isoPath string) error { devices, err := vm.vm.Device(vm.driver.ctx) if err != nil { return err } - sata, err := vm.FindSATAController() - if err != nil { - return err + + var controller *types.VirtualController + if controllerType == "sata" { + c, err := vm.FindSATAController() + if err != nil { + return err + } + controller = c.GetVirtualController() + } else { + c, err := devices.FindIDEController("") + if err != nil { + return err + } + controller = c.GetVirtualController() } - cdrom, err := vm.CreateCdrom(sata) + cdrom, err := vm.CreateCdrom(controller) if err != nil { return err } if isoPath != "" { - cdrom = devices.InsertIso(cdrom, isoPath) + devices.InsertIso(cdrom, isoPath) } return vm.addDevice(cdrom) diff --git a/driver/vm_cdrom.go b/driver/vm_cdrom.go index e0a155eea..2dfc65af1 100644 --- a/driver/vm_cdrom.go +++ b/driver/vm_cdrom.go @@ -24,7 +24,7 @@ func (vm *VirtualMachine) FindSATAController() (*types.VirtualAHCIController, er return c.(*types.VirtualAHCIController), nil } -func (vm *VirtualMachine) CreateCdrom(c *types.VirtualAHCIController) (*types.VirtualCdrom, error) { +func (vm *VirtualMachine) CreateCdrom(c *types.VirtualController) (*types.VirtualCdrom, error) { l, err := vm.Devices() if err != nil { return nil, err diff --git a/examples/macos/macos-10.13.json b/examples/macos/macos-10.13.json index eea54280f..779834a7e 100644 --- a/examples/macos/macos-10.13.json +++ b/examples/macos/macos-10.13.json @@ -26,6 +26,7 @@ "ich7m.present": "TRUE", "smc.present": "TRUE" }, + "cdrom_type": "sata", "iso_paths": [ "[datastore-mac] ISO/macOS 10.13.3.iso", diff --git a/iso/builder.go b/iso/builder.go index 556c98539..9b6aa9fe2 100644 --- a/iso/builder.go +++ b/iso/builder.go @@ -43,6 +43,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &common.StepConfigureHardware{ Config: &b.config.HardwareConfig, }, + &StepAddCDRom{ + Config: &b.config.CDRomConfig, + }, &common.StepConfigParams{ Config: &b.config.ConfigParamsConfig, }, @@ -50,9 +53,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe if b.config.Comm.Type != "none" { steps = append(steps, - &StepAddCDRom{ - Config: &b.config.CDRomConfig, - }, &packerCommon.StepCreateFloppy{ Files: b.config.FloppyFiles, Directories: b.config.FloppyDirectories, @@ -79,7 +79,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &common.StepShutdown{ Config: &b.config.ShutdownConfig, }, - &StepRemoveCDRom{}, &StepRemoveFloppy{ Datastore: b.config.Datastore, Host: b.config.Host, @@ -88,6 +87,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe } steps = append(steps, + &StepRemoveCDRom{}, &common.StepCreateSnapshot{ CreateSnapshot: b.config.CreateSnapshot, }, diff --git a/iso/builder_acc_test.go b/iso/builder_acc_test.go index 4ba61f658..eb84e587b 100644 --- a/iso/builder_acc_test.go +++ b/iso/builder_acc_test.go @@ -166,6 +166,19 @@ func checkHardware(t *testing.T) builderT.TestCheckFunc { t.Errorf("Invalid firmware: expected 'efi', got '%v'", fw) } + l, err := vm.Devices() + if err != nil { + t.Fatalf("Cannot read VM devices: %v", err) + } + c := l.PickController((*types.VirtualIDEController)(nil)) + if c == nil { + t.Errorf("VM should have IDE controller") + } + s := l.PickController((*types.VirtualAHCIController)(nil)) + if s != nil { + t.Errorf("VM should have no SATA controllers") + } + return nil } } @@ -204,6 +217,41 @@ func checkLimit(t *testing.T) builderT.TestCheckFunc { } } +func TestISOBuilderAcc_sata(t *testing.T) { + builderT.Test(t, builderT.TestCase{ + Builder: &Builder{}, + Template: sataConfig(), + Check: checkSata(t), + }) +} + +func sataConfig() string { + config := defaultConfig() + config["cdrom_type"] = "sata" + + return commonT.RenderConfig(config) +} + +func checkSata(t *testing.T) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := commonT.TestConn(t) + + vm := commonT.GetVM(t, d, artifacts) + + l, err := vm.Devices() + if err != nil { + t.Fatalf("Cannot read VM devices: %v", err) + } + + c := l.PickController((*types.VirtualAHCIController)(nil)) + if c == nil { + t.Errorf("VM has no SATA controllers") + } + + return nil + } +} + func TestISOBuilderAcc_cdrom(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, diff --git a/iso/config.go b/iso/config.go index a995767ff..0cc2c3bdf 100644 --- a/iso/config.go +++ b/iso/config.go @@ -47,6 +47,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs = packer.MultiErrorAppend(errs, c.LocationConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...) + errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare()...) diff --git a/iso/step_add_cdrom.go b/iso/step_add_cdrom.go index 60819a198..97633fd4b 100644 --- a/iso/step_add_cdrom.go +++ b/iso/step_add_cdrom.go @@ -9,6 +9,7 @@ import ( ) type CDRomConfig struct { + CdromType string `mapstructure:"cdrom_type"` ISOPaths []string `mapstructure:"iso_paths"` } @@ -16,19 +17,32 @@ type StepAddCDRom struct { Config *CDRomConfig } +func (c *CDRomConfig) Prepare() []error { + var errs []error + + if (c.CdromType != "" && c.CdromType != "ide" && c.CdromType != "sata") { + errs = append(errs, fmt.Errorf("'cdrom_type' must be 'ide' or 'sata'")) + } + + return errs +} + func (s *StepAddCDRom) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) vm := state.Get("vm").(*driver.VirtualMachine) - ui.Say("Adding CD-ROM drives...") - if err := vm.AddSATAController(); err != nil { - state.Put("error", fmt.Errorf("error adding SATA controller: %v", err)) - return multistep.ActionHalt + if s.Config.CdromType == "sata" { + ui.Say("Adding SATA controller...") + if err := vm.AddSATAController(); err != nil { + state.Put("error", fmt.Errorf("error adding SATA controller: %v", err)) + return multistep.ActionHalt + } } + ui.Say("Mount ISO images...") for _, path := range s.Config.ISOPaths { - if err := vm.AddCdrom(path); err != nil { - state.Put("error", fmt.Errorf("error adding a cdrom: %v", err)) + if err := vm.AddCdrom(s.Config.CdromType, path); err != nil { + state.Put("error", fmt.Errorf("error mounting an image: %v", err)) return multistep.ActionHalt } }