From d878f4dd8e5fb9d65513c35f4475e14ed9ac02ba Mon Sep 17 00:00:00 2001 From: Taliesin Sisson Date: Sat, 5 Dec 2015 03:03:33 -0800 Subject: [PATCH] A workaround for bug in Windows 10 and Windows 2016 where you have to specify a path when creating a dvd drive --- builder/hyperv/common/driver.go | 2 +- builder/hyperv/common/driver_ps_4.go | 4 +- builder/hyperv/common/step_mount_dvddrive.go | 2 +- .../common/step_mount_guest_additions.go | 190 ++++++++--------- .../common/step_mount_secondary_dvd_images.go | 196 +++++++++--------- powershell/hyperv/hyperv.go | 9 +- 6 files changed, 202 insertions(+), 201 deletions(-) diff --git a/builder/hyperv/common/driver.go b/builder/hyperv/common/driver.go index 44fa37c90..a62e3112b 100644 --- a/builder/hyperv/common/driver.go +++ b/builder/hyperv/common/driver.go @@ -86,7 +86,7 @@ type Driver interface { RestartVirtualMachine(string) error - CreateDvdDrive(string, uint) (uint, uint, error) + CreateDvdDrive(string, string, uint) (uint, uint, error) MountDvdDrive(string, string, uint, uint) error diff --git a/builder/hyperv/common/driver_ps_4.go b/builder/hyperv/common/driver_ps_4.go index 0e6507ede..15d6c6817 100644 --- a/builder/hyperv/common/driver_ps_4.go +++ b/builder/hyperv/common/driver_ps_4.go @@ -205,8 +205,8 @@ func (d *HypervPS4Driver) RestartVirtualMachine(vmName string) error { return hyperv.RestartVirtualMachine(vmName) } -func (d *HypervPS4Driver) CreateDvdDrive(vmName string, generation uint) (uint, uint, error) { - return hyperv.CreateDvdDrive(vmName, generation) +func (d *HypervPS4Driver) CreateDvdDrive(vmName string, isoPath string, generation uint) (uint, uint, error) { + return hyperv.CreateDvdDrive(vmName, isoPath, generation) } func (d *HypervPS4Driver) MountDvdDrive(vmName string, path string, controllerNumber uint, controllerLocation uint) error { diff --git a/builder/hyperv/common/step_mount_dvddrive.go b/builder/hyperv/common/step_mount_dvddrive.go index 346af2c9e..cff69627e 100644 --- a/builder/hyperv/common/step_mount_dvddrive.go +++ b/builder/hyperv/common/step_mount_dvddrive.go @@ -30,7 +30,7 @@ func (s *StepMountDvdDrive) Run(state multistep.StateBag) multistep.StepAction { // For IDE, there are only 2 controllers (0,1) with 2 locations each (0,1) var dvdControllerProperties DvdControllerProperties - controllerNumber, controllerLocation, err := driver.CreateDvdDrive(vmName, s.Generation) + controllerNumber, controllerLocation, err := driver.CreateDvdDrive(vmName, isoPath, s.Generation) if err != nil { state.Put("error", err) ui.Error(err.Error()) diff --git a/builder/hyperv/common/step_mount_guest_additions.go b/builder/hyperv/common/step_mount_guest_additions.go index ee6b69afc..dff8b90c3 100644 --- a/builder/hyperv/common/step_mount_guest_additions.go +++ b/builder/hyperv/common/step_mount_guest_additions.go @@ -1,96 +1,96 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved. -// Licensed under the Apache License, Version 2.0. -// See License.txt in the project root for license information. -package common - -import ( - "fmt" - "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/packer" - "log" -) - -type StepMountGuestAdditions struct { - GuestAdditionsMode string - GuestAdditionsPath string - Generation uint -} - -func (s *StepMountGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packer.Ui) - - if s.GuestAdditionsMode != "attach" { - ui.Say("Skipping mounting Integration Services Setup Disk...") - return multistep.ActionContinue - } - - driver := state.Get("driver").(Driver) - ui.Say("Mounting Integration Services Setup Disk...") - - vmName := state.Get("vmName").(string) - - // should be able to mount up to 60 additional iso images using SCSI - // but Windows would only allow a max of 22 due to available drive letters - // Will Windows assign DVD drives to A: and B: ? - - // For IDE, there are only 2 controllers (0,1) with 2 locations each (0,1) - - var dvdControllerProperties DvdControllerProperties - - controllerNumber, controllerLocation, err := driver.CreateDvdDrive(vmName, s.Generation) - if err != nil { - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - dvdControllerProperties.ControllerNumber = controllerNumber - dvdControllerProperties.ControllerLocation = controllerLocation - dvdControllerProperties.Existing = false - state.Put("guest.dvd.properties", dvdControllerProperties) - - ui.Say(fmt.Sprintf("Mounting Integration Services dvd drive %s ...", s.GuestAdditionsPath)) - err = driver.MountDvdDrive(vmName, s.GuestAdditionsPath, controllerNumber, controllerLocation) - if err != nil { - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", s.GuestAdditionsPath, controllerNumber, controllerLocation)) - - return multistep.ActionContinue -} - -func (s *StepMountGuestAdditions) Cleanup(state multistep.StateBag) { - if s.GuestAdditionsMode != "attach" { - return - } - - dvdControllerState := state.Get("guest.dvd.properties") - - if dvdControllerState == nil { - return - } - - dvdController := dvdControllerState.(DvdControllerProperties) - ui := state.Get("ui").(packer.Ui) - driver := state.Get("driver").(Driver) - vmName := state.Get("vmName").(string) - errorMsg := "Error unmounting Integration Services dvd drive: %s" - - ui.Say("Cleanup Integration Services dvd drive...") - - if dvdController.Existing { - err := driver.UnmountDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) - if err != nil { - log.Print(fmt.Sprintf(errorMsg, err)) - } - } else { - err := driver.DeleteDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) - if err != nil { - log.Print(fmt.Sprintf(errorMsg, err)) - } - } +// Copyright (c) Microsoft Open Technologies, Inc. +// All Rights Reserved. +// Licensed under the Apache License, Version 2.0. +// See License.txt in the project root for license information. +package common + +import ( + "fmt" + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" + "log" +) + +type StepMountGuestAdditions struct { + GuestAdditionsMode string + GuestAdditionsPath string + Generation uint +} + +func (s *StepMountGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + + if s.GuestAdditionsMode != "attach" { + ui.Say("Skipping mounting Integration Services Setup Disk...") + return multistep.ActionContinue + } + + driver := state.Get("driver").(Driver) + ui.Say("Mounting Integration Services Setup Disk...") + + vmName := state.Get("vmName").(string) + + // should be able to mount up to 60 additional iso images using SCSI + // but Windows would only allow a max of 22 due to available drive letters + // Will Windows assign DVD drives to A: and B: ? + + // For IDE, there are only 2 controllers (0,1) with 2 locations each (0,1) + + var dvdControllerProperties DvdControllerProperties + + controllerNumber, controllerLocation, err := driver.CreateDvdDrive(vmName, s.GuestAdditionsPath, s.Generation) + if err != nil { + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + dvdControllerProperties.ControllerNumber = controllerNumber + dvdControllerProperties.ControllerLocation = controllerLocation + dvdControllerProperties.Existing = false + state.Put("guest.dvd.properties", dvdControllerProperties) + + ui.Say(fmt.Sprintf("Mounting Integration Services dvd drive %s ...", s.GuestAdditionsPath)) + err = driver.MountDvdDrive(vmName, s.GuestAdditionsPath, controllerNumber, controllerLocation) + if err != nil { + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", s.GuestAdditionsPath, controllerNumber, controllerLocation)) + + return multistep.ActionContinue +} + +func (s *StepMountGuestAdditions) Cleanup(state multistep.StateBag) { + if s.GuestAdditionsMode != "attach" { + return + } + + dvdControllerState := state.Get("guest.dvd.properties") + + if dvdControllerState == nil { + return + } + + dvdController := dvdControllerState.(DvdControllerProperties) + ui := state.Get("ui").(packer.Ui) + driver := state.Get("driver").(Driver) + vmName := state.Get("vmName").(string) + errorMsg := "Error unmounting Integration Services dvd drive: %s" + + ui.Say("Cleanup Integration Services dvd drive...") + + if dvdController.Existing { + err := driver.UnmountDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) + if err != nil { + log.Print(fmt.Sprintf(errorMsg, err)) + } + } else { + err := driver.DeleteDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) + if err != nil { + log.Print(fmt.Sprintf(errorMsg, err)) + } + } } \ No newline at end of file diff --git a/builder/hyperv/common/step_mount_secondary_dvd_images.go b/builder/hyperv/common/step_mount_secondary_dvd_images.go index 548fd4a8a..eb5ce25bc 100644 --- a/builder/hyperv/common/step_mount_secondary_dvd_images.go +++ b/builder/hyperv/common/step_mount_secondary_dvd_images.go @@ -1,98 +1,98 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved. -// Licensed under the Apache License, Version 2.0. -// See License.txt in the project root for license information. -package common - -import ( - "fmt" - "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/packer" - "log" -) - -type StepMountSecondaryDvdImages struct { - IsoPaths []string - Generation uint -} - -type DvdControllerProperties struct { - ControllerNumber uint - ControllerLocation uint - Existing bool -} - -func (s *StepMountSecondaryDvdImages) Run(state multistep.StateBag) multistep.StepAction { - driver := state.Get("driver").(Driver) - ui := state.Get("ui").(packer.Ui) - ui.Say("Mounting secondary DVD images...") - - vmName := state.Get("vmName").(string) - - // should be able to mount up to 60 additional iso images using SCSI - // but Windows would only allow a max of 22 due to available drive letters - // Will Windows assign DVD drives to A: and B: ? - - // For IDE, there are only 2 controllers (0,1) with 2 locations each (0,1) - var dvdProperties []DvdControllerProperties - - for _, isoPath := range s.IsoPaths { - var properties DvdControllerProperties - - controllerNumber, controllerLocation, err := driver.CreateDvdDrive(vmName, s.Generation) - if err != nil { - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - properties.ControllerNumber = controllerNumber - properties.ControllerLocation = controllerLocation - properties.Existing = false - dvdProperties = append(dvdProperties, properties) - state.Put("secondary.dvd.properties", dvdProperties) - - ui.Say(fmt.Sprintf("Mounting secondary dvd drive %s ...", isoPath)) - err = driver.MountDvdDrive(vmName, isoPath, controllerNumber, controllerLocation) - if err != nil { - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", isoPath, controllerNumber, controllerLocation)) - } - - return multistep.ActionContinue -} - -func (s *StepMountSecondaryDvdImages) Cleanup(state multistep.StateBag) { - dvdControllersState := state.Get("secondary.dvd.properties") - - if dvdControllersState == nil { - return - } - - dvdControllers := dvdControllersState.([]DvdControllerProperties) - driver := state.Get("driver").(Driver) - ui := state.Get("ui").(packer.Ui) - vmName := state.Get("vmName").(string) - errorMsg := "Error unmounting secondary dvd drive: %s" - - ui.Say("Clean up secondary dvd drives...") - - for _, dvdController := range dvdControllers { - - if dvdController.Existing { - err := driver.UnmountDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) - if err != nil { - log.Print(fmt.Sprintf(errorMsg, err)) - } - } else { - err := driver.DeleteDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) - if err != nil { - log.Print(fmt.Sprintf(errorMsg, err)) - } - } - } -} +// Copyright (c) Microsoft Open Technologies, Inc. +// All Rights Reserved. +// Licensed under the Apache License, Version 2.0. +// See License.txt in the project root for license information. +package common + +import ( + "fmt" + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" + "log" +) + +type StepMountSecondaryDvdImages struct { + IsoPaths []string + Generation uint +} + +type DvdControllerProperties struct { + ControllerNumber uint + ControllerLocation uint + Existing bool +} + +func (s *StepMountSecondaryDvdImages) Run(state multistep.StateBag) multistep.StepAction { + driver := state.Get("driver").(Driver) + ui := state.Get("ui").(packer.Ui) + ui.Say("Mounting secondary DVD images...") + + vmName := state.Get("vmName").(string) + + // should be able to mount up to 60 additional iso images using SCSI + // but Windows would only allow a max of 22 due to available drive letters + // Will Windows assign DVD drives to A: and B: ? + + // For IDE, there are only 2 controllers (0,1) with 2 locations each (0,1) + var dvdProperties []DvdControllerProperties + + for _, isoPath := range s.IsoPaths { + var properties DvdControllerProperties + + controllerNumber, controllerLocation, err := driver.CreateDvdDrive(vmName, isoPath, s.Generation) + if err != nil { + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + properties.ControllerNumber = controllerNumber + properties.ControllerLocation = controllerLocation + properties.Existing = false + dvdProperties = append(dvdProperties, properties) + state.Put("secondary.dvd.properties", dvdProperties) + + ui.Say(fmt.Sprintf("Mounting secondary dvd drive %s ...", isoPath)) + err = driver.MountDvdDrive(vmName, isoPath, controllerNumber, controllerLocation) + if err != nil { + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", isoPath, controllerNumber, controllerLocation)) + } + + return multistep.ActionContinue +} + +func (s *StepMountSecondaryDvdImages) Cleanup(state multistep.StateBag) { + dvdControllersState := state.Get("secondary.dvd.properties") + + if dvdControllersState == nil { + return + } + + dvdControllers := dvdControllersState.([]DvdControllerProperties) + driver := state.Get("driver").(Driver) + ui := state.Get("ui").(packer.Ui) + vmName := state.Get("vmName").(string) + errorMsg := "Error unmounting secondary dvd drive: %s" + + ui.Say("Clean up secondary dvd drives...") + + for _, dvdController := range dvdControllers { + + if dvdController.Existing { + err := driver.UnmountDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) + if err != nil { + log.Print(fmt.Sprintf(errorMsg, err)) + } + } else { + err := driver.DeleteDvdDrive(vmName, dvdController.ControllerNumber, dvdController.ControllerLocation) + if err != nil { + log.Print(fmt.Sprintf(errorMsg, err)) + } + } + } +} diff --git a/powershell/hyperv/hyperv.go b/powershell/hyperv/hyperv.go index 41556ba64..7a981cb1e 100644 --- a/powershell/hyperv/hyperv.go +++ b/powershell/hyperv/hyperv.go @@ -51,7 +51,7 @@ $ip return cmdOut, err } -func CreateDvdDrive(vmName string, generation uint) (uint, uint, error) { +func CreateDvdDrive(vmName string, isoPath string, generation uint) (uint, uint, error) { var ps powershell.PowerShellCmd var script string var controllerNumber uint @@ -89,12 +89,13 @@ $lastControllerNumber } script = ` -param([string]$vmName,[int]$controllerNumber) -$dvdController = Add-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -Passthru +param([string]$vmName, [string]$isoPath, [int]$controllerNumber) +$dvdController = Add-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -path $isoPath -Passthru +Set-VMDvdDrive -path $null $dvdController.ControllerLocation ` - cmdOut, err := ps.Output(script, vmName, strconv.FormatInt(int64(controllerNumber), 10)) + cmdOut, err := ps.Output(script, vmName, isoPath, strconv.FormatInt(int64(controllerNumber), 10)) if err != nil { return controllerNumber, 0, err }