Make use of driver instead of directly referencing hyper

Move inline powershell to hyperv
This commit is contained in:
Taliesin Sisson 2015-10-30 08:23:30 +00:00
parent cd6213eb55
commit 422efeeaf6
20 changed files with 432 additions and 246 deletions

View File

@ -15,6 +15,12 @@ type Driver interface {
// Checks if the VM named is running. // Checks if the VM named is running.
IsRunning(string) (bool, error) IsRunning(string) (bool, error)
// Checks if the VM named is off.
IsOff(string) (bool, error)
//How long has VM been on
Uptime(vmName string) (uint64, error)
// Start starts a VM specified by the name given. // Start starts a VM specified by the name given.
Start(string) error Start(string) error
@ -32,9 +38,63 @@ type Driver interface {
// Finds the IP address of a VM connected that uses DHCP by its MAC address // Finds the IP address of a VM connected that uses DHCP by its MAC address
IpAddress(string) (string, error) IpAddress(string) (string, error)
// Finds the hostname for the ip address
GetHostName(string) (string, error)
// Finds the IP address of a host adapter connected to switch // Finds the IP address of a host adapter connected to switch
GetHostAdapterIpAddressForSwitch(string) (string, error) GetHostAdapterIpAddressForSwitch(string) (string, error)
// Type scan codes to virtual keyboard of vm // Type scan codes to virtual keyboard of vm
TypeScanCodes(string, string) error TypeScanCodes(string, string) error
//Get the ip address for network adaptor
GetVirtualMachineNetworkAdapterAddress(string) (string, error)
//Set the vlan to use for switch
SetNetworkAdapterVlanId(string, string) error
//Set the vlan to use for machine
SetVirtualMachineVlanId(string, string) error
UntagVirtualMachineNetworkAdapterVlan(string, string) error
CreateExternalVirtualSwitch(string, string) error
GetVirtualMachineSwitchName(string) (string, error)
ConnectVirtualMachineNetworkAdapterToSwitch(string, string) error
CreateVirtualSwitch(string, string) (bool, error)
DeleteVirtualSwitch(string) error
CreateVirtualMachine(string, string, int64, int64, string, uint) error
DeleteVirtualMachine(string) error
SetVirtualMachineCpu(string, uint) error
SetSecureBoot(string, bool) error
EnableVirtualMachineIntegrationService(string, string) error
ExportVirtualMachine(string, string) error
CompactDisks(string, string) error
CopyExportedVirtualMachine(string, string, string, string) error
RestartVirtualMachine(string) error
CreateDvdDrive(string, uint) (uint, uint, error)
MountDvdDrive(string, string) error
MountDvdDriveByLocation(string, string, uint, uint) error
UnmountDvdDrive(string) error
DeleteDvdDrive(string, string, string) error
UnmountFloppyDrive(vmName string) error
} }

View File

@ -39,6 +39,14 @@ func (d *HypervPS4Driver) IsRunning(vmName string) (bool, error) {
return hyperv.IsRunning(vmName) return hyperv.IsRunning(vmName)
} }
func (d *HypervPS4Driver) IsOff(vmName string) (bool, error) {
return hyperv.IsOff(vmName)
}
func (d *HypervPS4Driver) Uptime(vmName string) (uint64, error) {
return hyperv.Uptime(vmName)
}
// Start starts a VM specified by the name given. // Start starts a VM specified by the name given.
func (d *HypervPS4Driver) Start(vmName string) error { func (d *HypervPS4Driver) Start(vmName string) error {
return hyperv.StartVirtualMachine(vmName) return hyperv.StartVirtualMachine(vmName)
@ -97,6 +105,11 @@ func (d *HypervPS4Driver) IpAddress(mac string) (string, error) {
return res, err return res, err
} }
// Get host name from ip address
func (d *HypervPS4Driver) GetHostName(ip string) (string, error) {
return powershell.GetHostName(ip)
}
// Finds the IP address of a host adapter connected to switch // Finds the IP address of a host adapter connected to switch
func (d *HypervPS4Driver) GetHostAdapterIpAddressForSwitch(switchName string) (string, error) { func (d *HypervPS4Driver) GetHostAdapterIpAddressForSwitch(switchName string) (string, error) {
res, err := hyperv.GetHostAdapterIpAddressForSwitch(switchName) res, err := hyperv.GetHostAdapterIpAddressForSwitch(switchName)
@ -117,6 +130,105 @@ func (d *HypervPS4Driver) TypeScanCodes(vmName string, scanCodes string) error {
return hyperv.TypeScanCodes(vmName, scanCodes) return hyperv.TypeScanCodes(vmName, scanCodes)
} }
// Get network adapter address
func (d *HypervPS4Driver) GetVirtualMachineNetworkAdapterAddress(vmName string) (string, error) {
return hyperv.GetVirtualMachineNetworkAdapterAddress(vmName)
}
//Set the vlan to use for switch
func (d *HypervPS4Driver) SetNetworkAdapterVlanId(switchName string, vlanId string) error {
return hyperv.SetNetworkAdapterVlanId(switchName, vlanId)
}
//Set the vlan to use for machine
func (d *HypervPS4Driver) SetVirtualMachineVlanId(vmName string, vlanId string) error {
return hyperv.SetVirtualMachineVlanId(vmName, vlanId)
}
func (d *HypervPS4Driver) UntagVirtualMachineNetworkAdapterVlan(vmName string, switchName string) error {
return hyperv.UntagVirtualMachineNetworkAdapterVlan(vmName, switchName)
}
func (d *HypervPS4Driver) CreateExternalVirtualSwitch(vmName string, switchName string) error {
return hyperv.CreateExternalVirtualSwitch(vmName, switchName)
}
func (d *HypervPS4Driver) GetVirtualMachineSwitchName(vmName string) (string, error) {
return hyperv.GetVirtualMachineSwitchName(vmName)
}
func (d *HypervPS4Driver) ConnectVirtualMachineNetworkAdapterToSwitch(vmName string, switchName string) error {
return hyperv.ConnectVirtualMachineNetworkAdapterToSwitch(vmName, switchName)
}
func (d *HypervPS4Driver) DeleteVirtualSwitch(switchName string) error {
return hyperv.DeleteVirtualSwitch(switchName)
}
func (d *HypervPS4Driver) CreateVirtualSwitch(switchName string, switchType string) (bool, error) {
return hyperv.CreateVirtualSwitch(switchName, switchType)
}
func (d *HypervPS4Driver) CreateVirtualMachine(vmName string, path string, ram int64, diskSize int64, switchName string, generation uint) error {
return hyperv.CreateVirtualMachine(vmName, path, ram, diskSize, switchName, generation)
}
func (d *HypervPS4Driver) DeleteVirtualMachine(vmName string) error {
return hyperv.DeleteVirtualMachine(vmName)
}
func (d *HypervPS4Driver) SetVirtualMachineCpu(vmName string, cpu uint) error {
return hyperv.SetVirtualMachineCpu(vmName, cpu)
}
func (d *HypervPS4Driver) SetSecureBoot(vmName string, enable bool) error {
return hyperv.SetSecureBoot(vmName, enable)
}
func (d *HypervPS4Driver) EnableVirtualMachineIntegrationService(vmName string, integrationServiceName string) error {
return hyperv.EnableVirtualMachineIntegrationService(vmName, integrationServiceName)
}
func (d *HypervPS4Driver) ExportVirtualMachine(vmName string, path string) error {
return hyperv.ExportVirtualMachine(vmName, path)
}
func (d *HypervPS4Driver) CompactDisks(expPath string, vhdDir string) error {
return hyperv.CompactDisks(expPath, vhdDir)
}
func (d *HypervPS4Driver) CopyExportedVirtualMachine(expPath string, outputPath string, vhdDir string, vmDir string) error {
return hyperv.CopyExportedVirtualMachine(expPath, outputPath, vhdDir, vmDir)
}
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) MountDvdDrive(vmName string, path string) error {
return hyperv.MountDvdDrive(vmName, path)
}
func (d *HypervPS4Driver) MountDvdDriveByLocation(vmName string, path string, controllerNumber uint, controllerLocation uint) error {
return hyperv.MountDvdDriveByLocation(vmName, path, controllerNumber, controllerLocation)
}
func (d *HypervPS4Driver) UnmountDvdDrive(vmName string) error {
return hyperv.UnmountDvdDrive(vmName)
}
func (d *HypervPS4Driver) DeleteDvdDrive(vmName string, controllerNumber string, controllerLocation string) error {
return hyperv.DeleteDvdDrive(vmName, controllerNumber, controllerLocation)
}
func (d *HypervPS4Driver) UnmountFloppyDrive(vmName string) error {
return hyperv.UnmountFloppyDrive(vmName)
}
func (d *HypervPS4Driver) verifyPSVersion() error { func (d *HypervPS4Driver) verifyPSVersion() error {
log.Printf("Enter method: %s", "verifyPSVersion") log.Printf("Enter method: %s", "verifyPSVersion")

View File

@ -8,19 +8,16 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"log"
"strings" "strings"
"time" "time"
"log"
powershell "github.com/mitchellh/packer/powershell"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepConfigureIp struct { type StepConfigureIp struct {
} }
func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction {
// driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
errorMsg := "Error configuring ip address: %s" errorMsg := "Error configuring ip address: %s"
@ -34,7 +31,7 @@ func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction {
var ip string var ip string
for count != 0 { for count != 0 {
cmdOut, err := hyperv.GetVirtualMachineNetworkAdapterAddress(vmName) cmdOut, err := driver.GetVirtualMachineNetworkAdapterAddress(vmName)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)
@ -45,7 +42,7 @@ func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction {
ip = strings.TrimSpace(string(cmdOut)) ip = strings.TrimSpace(string(cmdOut))
if ip != "False" { if ip != "False" {
break; break
} }
log.Println(fmt.Sprintf("Waiting for another %v minutes...", uint(duration))) log.Println(fmt.Sprintf("Waiting for another %v minutes...", uint(duration)))
@ -53,7 +50,7 @@ func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction {
count-- count--
} }
if(count == 0){ if count == 0 {
err := fmt.Errorf(errorMsg, "IP address assigned to the adapter is empty") err := fmt.Errorf(errorMsg, "IP address assigned to the adapter is empty")
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
@ -62,7 +59,7 @@ func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("ip address is " + ip) ui.Say("ip address is " + ip)
hostName, err := powershell.GetHostName(ip); hostName, err := driver.GetHostName(ip)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
@ -80,4 +77,3 @@ func (s *StepConfigureIp) Run(state multistep.StateBag) multistep.StepAction {
func (s *StepConfigureIp) Cleanup(state multistep.StateBag) { func (s *StepConfigureIp) Cleanup(state multistep.StateBag) {
// do nothing // do nothing
} }

View File

@ -8,20 +8,14 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
)
const(
vlanId = "1724"
) )
type StepConfigureVlan struct { type StepConfigureVlan struct {
vlanId string
} }
func (s *StepConfigureVlan) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConfigureVlan) Run(state multistep.StateBag) multistep.StepAction {
//config := state.Get("config").(*config) driver := state.Get("driver").(Driver)
//driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
errorMsg := "Error configuring vlan: %s" errorMsg := "Error configuring vlan: %s"
@ -30,7 +24,13 @@ func (s *StepConfigureVlan) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Configuring vlan...") ui.Say("Configuring vlan...")
err := hyperv.SetNetworkAdapterVlanId(switchName, vlanId) vlanId := s.vlanId
if vlanId == "" {
vlanId = "1724"
}
err := driver.SetNetworkAdapterVlanId(switchName, vlanId)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)
@ -38,7 +38,7 @@ func (s *StepConfigureVlan) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt return multistep.ActionHalt
} }
err = hyperv.SetVirtualMachineVlanId(vmName, vlanId) err = driver.SetVirtualMachineVlanId(vmName, vlanId)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)

View File

@ -5,11 +5,10 @@
package common package common
import ( import (
"code.google.com/p/go-uuid/uuid"
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"code.google.com/p/go-uuid/uuid"
"github.com/mitchellh/packer/powershell/hyperv"
) )
// This step creates switch for VM. // This step creates switch for VM.
@ -17,12 +16,12 @@ import (
// Produces: // Produces:
// SwitchName string - The name of the Switch // SwitchName string - The name of the Switch
type StepCreateExternalSwitch struct { type StepCreateExternalSwitch struct {
SwitchName string SwitchName string
oldSwitchName string oldSwitchName string
} }
func (s *StepCreateExternalSwitch) Run(state multistep.StateBag) multistep.StepAction { func (s *StepCreateExternalSwitch) Run(state multistep.StateBag) multistep.StepAction {
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
@ -33,16 +32,16 @@ func (s *StepCreateExternalSwitch) Run(state multistep.StateBag) multistep.StepA
packerExternalSwitchName := "paes_" + uuid.New() packerExternalSwitchName := "paes_" + uuid.New()
err = hyperv.CreateExternalVirtualSwitch(vmName, packerExternalSwitchName) err = driver.CreateExternalVirtualSwitch(vmName, packerExternalSwitchName)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating switch: %s", err) err := fmt.Errorf("Error creating switch: %s", err)
state.Put(errorMsg, err) state.Put(errorMsg, err)
ui.Error(err.Error()) ui.Error(err.Error())
s.SwitchName = ""; s.SwitchName = ""
return multistep.ActionHalt return multistep.ActionHalt
} }
switchName, err := hyperv.GetVirtualMachineSwitchName(vmName) switchName, err := driver.GetVirtualMachineSwitchName(vmName)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)
@ -59,10 +58,10 @@ func (s *StepCreateExternalSwitch) Run(state multistep.StateBag) multistep.StepA
ui.Say("External switch name is: '" + switchName + "'") ui.Say("External switch name is: '" + switchName + "'")
if(switchName != packerExternalSwitchName){ if switchName != packerExternalSwitchName {
s.SwitchName = "" s.SwitchName = ""
} else { } else {
s.SwitchName = packerExternalSwitchName s.SwitchName = packerExternalSwitchName
s.oldSwitchName = state.Get("SwitchName").(string) s.oldSwitchName = state.Get("SwitchName").(string)
} }
@ -76,7 +75,7 @@ func (s *StepCreateExternalSwitch) Cleanup(state multistep.StateBag) {
if s.SwitchName == "" { if s.SwitchName == "" {
return return
} }
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
@ -92,7 +91,7 @@ func (s *StepCreateExternalSwitch) Cleanup(state multistep.StateBag) {
return return
} }
err = hyperv.ConnectVirtualMachineNetworkAdapterToSwitch(vmName, s.oldSwitchName) err = driver.ConnectVirtualMachineNetworkAdapterToSwitch(vmName, s.oldSwitchName)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf(errMsg, err)) ui.Error(fmt.Sprintf(errMsg, err))
return return
@ -100,7 +99,7 @@ func (s *StepCreateExternalSwitch) Cleanup(state multistep.StateBag) {
state.Put("SwitchName", s.oldSwitchName) state.Put("SwitchName", s.oldSwitchName)
err = hyperv.DeleteVirtualSwitch(s.SwitchName) err = driver.DeleteVirtualSwitch(s.SwitchName)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf(errMsg, err)) ui.Error(fmt.Sprintf(errMsg, err))
} }

View File

@ -8,13 +8,12 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
) )
const ( const (
SwitchTypeInternal = "Internal" SwitchTypeInternal = "Internal"
SwitchTypePrivate = "Private" SwitchTypePrivate = "Private"
DefaultSwitchType = SwitchTypeInternal DefaultSwitchType = SwitchTypeInternal
) )
// This step creates switch for VM. // This step creates switch for VM.
@ -23,21 +22,21 @@ const (
// SwitchName string - The name of the Switch // SwitchName string - The name of the Switch
type StepCreateSwitch struct { type StepCreateSwitch struct {
// Specifies the name of the switch to be created. // Specifies the name of the switch to be created.
SwitchName string SwitchName string
// Specifies the type of the switch to be created. Allowed values are Internal and Private. To create an External // Specifies the type of the switch to be created. Allowed values are Internal and Private. To create an External
// virtual switch, specify either the NetAdapterInterfaceDescription or the NetAdapterName parameter, which // virtual switch, specify either the NetAdapterInterfaceDescription or the NetAdapterName parameter, which
// implicitly set the type of the virtual switch to External. // implicitly set the type of the virtual switch to External.
SwitchType string SwitchType string
// Specifies the name of the network adapter to be bound to the switch to be created. // Specifies the name of the network adapter to be bound to the switch to be created.
NetAdapterName string NetAdapterName string
// Specifies the interface description of the network adapter to be bound to the switch to be created. // Specifies the interface description of the network adapter to be bound to the switch to be created.
NetAdapterInterfaceDescription string NetAdapterInterfaceDescription string
createdSwitch bool createdSwitch bool
} }
func (s *StepCreateSwitch) Run(state multistep.StateBag) multistep.StepAction { func (s *StepCreateSwitch) Run(state multistep.StateBag) multistep.StepAction {
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
if len(s.SwitchType) == 0 { if len(s.SwitchType) == 0 {
@ -46,12 +45,12 @@ func (s *StepCreateSwitch) Run(state multistep.StateBag) multistep.StepAction {
ui.Say(fmt.Sprintf("Creating switch '%v' if required...", s.SwitchName)) ui.Say(fmt.Sprintf("Creating switch '%v' if required...", s.SwitchName))
createdSwitch, err := hyperv.CreateVirtualSwitch(s.SwitchName, s.SwitchType) createdSwitch, err := driver.CreateVirtualSwitch(s.SwitchName, s.SwitchType)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating switch: %s", err) err := fmt.Errorf("Error creating switch: %s", err)
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
s.SwitchName = ""; s.SwitchName = ""
return multistep.ActionHalt return multistep.ActionHalt
} }
@ -72,11 +71,11 @@ func (s *StepCreateSwitch) Cleanup(state multistep.StateBag) {
return return
} }
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Unregistering and deleting switch...") ui.Say("Unregistering and deleting switch...")
err := hyperv.DeleteVirtualSwitch(s.SwitchName) err := driver.DeleteVirtualSwitch(s.SwitchName)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf("Error deleting switch: %s", err)) ui.Error(fmt.Sprintf("Error deleting switch: %s", err))
} }

View File

@ -8,8 +8,6 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
"strconv"
) )
// This step creates the actual virtual machine. // This step creates the actual virtual machine.
@ -17,50 +15,47 @@ import (
// Produces: // Produces:
// VMName string - The name of the VM // VMName string - The name of the VM
type StepCreateVM struct { type StepCreateVM struct {
VMName string VMName string
SwitchName string SwitchName string
RamSizeMB uint RamSizeMB uint
DiskSize uint DiskSize uint
Generation uint Generation uint
Cpu uint Cpu uint
EnabeSecureBoot bool EnabeSecureBoot bool
} }
func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction { func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Creating virtual machine...") ui.Say("Creating virtual machine...")
path := state.Get("packerTempDir").(string) path := state.Get("packerTempDir").(string)
// convert the MB to bytes // convert the MB to bytes
ramBytes := int64(s.RamSizeMB * 1024 * 1024) ram := int64(s.RamSizeMB * 1024 * 1024)
diskSizeBytes := int64(s.DiskSize * 1024 * 1024) diskSize := int64(s.DiskSize * 1024 * 1024)
ram := strconv.FormatInt(ramBytes, 10)
diskSize := strconv.FormatInt(diskSizeBytes, 10)
switchName := s.SwitchName switchName := s.SwitchName
generation := strconv.FormatInt(int64(s.Generation), 10)
cpu := strconv.FormatInt(int64(s.Cpu), 10)
enabeSecureBoot := s.EnabeSecureBoot enabeSecureBoot := s.EnabeSecureBoot
err := hyperv.CreateVirtualMachine(s.VMName, path, ram, diskSize, switchName, generation) err := driver.CreateVirtualMachine(s.VMName, path, ram, diskSize, switchName, s.Generation)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating virtual machine: %s", err) err := fmt.Errorf("Error creating virtual machine: %s", err)
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
err = hyperv.SetVirtualMachineCpu(s.VMName, cpu) err = driver.SetVirtualMachineCpu(s.VMName, s.Cpu)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating setting virtual machine cpu: %s", err) err := fmt.Errorf("Error creating setting virtual machine cpu: %s", err)
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
if generation == "2" { if s.Generation == 2 {
err = hyperv.SetSecureBoot(s.VMName, enabeSecureBoot) err = driver.SetSecureBoot(s.VMName, enabeSecureBoot)
if err != nil { if err != nil {
err := fmt.Errorf("Error setting secure boot: %s", err) err := fmt.Errorf("Error setting secure boot: %s", err)
state.Put("error", err) state.Put("error", err)
@ -80,11 +75,11 @@ func (s *StepCreateVM) Cleanup(state multistep.StateBag) {
return return
} }
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Unregistering and deleting virtual machine...") ui.Say("Unregistering and deleting virtual machine...")
err := hyperv.DeleteVirtualMachine(s.VMName) err := driver.DeleteVirtualMachine(s.VMName)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err)) ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err))
} }

View File

@ -8,15 +8,13 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepDisableVlan struct { type StepDisableVlan struct {
} }
func (s *StepDisableVlan) Run(state multistep.StateBag) multistep.StepAction { func (s *StepDisableVlan) Run(state multistep.StateBag) multistep.StepAction {
//config := state.Get("config").(*config) driver := state.Get("driver").(Driver)
//driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
errorMsg := "Error disabling vlan: %s" errorMsg := "Error disabling vlan: %s"
@ -25,7 +23,7 @@ func (s *StepDisableVlan) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Disabling vlan...") ui.Say("Disabling vlan...")
err := hyperv.UntagVirtualMachineNetworkAdapterVlan(vmName, switchName) err := driver.UntagVirtualMachineNetworkAdapterVlan(vmName, switchName)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepEnableIntegrationService struct { type StepEnableIntegrationService struct {
@ -16,13 +15,14 @@ type StepEnableIntegrationService struct {
} }
func (s *StepEnableIntegrationService) Run(state multistep.StateBag) multistep.StepAction { func (s *StepEnableIntegrationService) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Enabling Integration Service...") ui.Say("Enabling Integration Service...")
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
s.name = "Guest Service Interface" s.name = "Guest Service Interface"
err := hyperv.EnableVirtualMachineIntegrationService(vmName, s.name) err := driver.EnableVirtualMachineIntegrationService(vmName, s.name)
if err != nil { if err != nil {
err := fmt.Errorf("Error enabling Integration Service: %s", err) err := fmt.Errorf("Error enabling Integration Service: %s", err)

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
"io/ioutil" "io/ioutil"
"path/filepath" "path/filepath"
) )
@ -24,6 +23,7 @@ type StepExportVm struct {
} }
func (s *StepExportVm) Run(state multistep.StateBag) multistep.StepAction { func (s *StepExportVm) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
var err error var err error
@ -45,7 +45,7 @@ func (s *StepExportVm) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Exporting vm...") ui.Say("Exporting vm...")
err = hyperv.ExportVirtualMachine(vmName, vmExportPath) err = driver.ExportVirtualMachine(vmName, vmExportPath)
if err != nil { if err != nil {
errorMsg = "Error exporting vm: %s" errorMsg = "Error exporting vm: %s"
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
@ -61,7 +61,7 @@ func (s *StepExportVm) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Skipping disk compaction...") ui.Say("Skipping disk compaction...")
} else { } else {
ui.Say("Compacting disks...") ui.Say("Compacting disks...")
err = hyperv.CompactDisks(expPath, vhdDir) err = driver.CompactDisks(expPath, vhdDir)
if err != nil { if err != nil {
errorMsg = "Error compacting disks: %s" errorMsg = "Error compacting disks: %s"
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
@ -72,7 +72,7 @@ func (s *StepExportVm) Run(state multistep.StateBag) multistep.StepAction {
} }
ui.Say("Coping to output dir...") ui.Say("Coping to output dir...")
err = hyperv.CopyExportedVirtualMachine(expPath, outputPath, vhdDir, vmDir) err = driver.CopyExportedVirtualMachine(expPath, outputPath, vhdDir, vmDir)
if err != nil { if err != nil {
errorMsg = "Error exporting vm: %s" errorMsg = "Error exporting vm: %s"
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)

View File

@ -9,7 +9,6 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
powershell "github.com/mitchellh/packer/powershell" powershell "github.com/mitchellh/packer/powershell"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepMountDvdDrive struct { type StepMountDvdDrive struct {
@ -18,7 +17,7 @@ type StepMountDvdDrive struct {
} }
func (s *StepMountDvdDrive) Run(state multistep.StateBag) multistep.StepAction { func (s *StepMountDvdDrive) Run(state multistep.StateBag) multistep.StepAction {
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
errorMsg := "Error mounting dvd drive: %s" errorMsg := "Error mounting dvd drive: %s"
@ -56,7 +55,7 @@ func (s *StepMountDvdDrive) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Mounting dvd drive...") ui.Say("Mounting dvd drive...")
err = hyperv.MountDvdDrive(vmName, isoPath) err = driver.MountDvdDrive(vmName, isoPath)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)
@ -74,6 +73,8 @@ func (s *StepMountDvdDrive) Cleanup(state multistep.StateBag) {
return return
} }
driver := state.Get("driver").(Driver)
errorMsg := "Error unmounting dvd drive: %s" errorMsg := "Error unmounting dvd drive: %s"
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
@ -81,7 +82,7 @@ func (s *StepMountDvdDrive) Cleanup(state multistep.StateBag) {
ui.Say("Unmounting dvd drive...") ui.Say("Unmounting dvd drive...")
err := hyperv.UnmountDvdDrive(vmName) err := driver.UnmountDvdDrive(vmName)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf(errorMsg, err)) ui.Error(fmt.Sprintf(errorMsg, err))
} }

View File

@ -6,28 +6,24 @@ package common
import ( import (
"fmt" "fmt"
"os"
"strings"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell" "github.com/mitchellh/packer/powershell"
"github.com/mitchellh/packer/powershell/hyperv" "github.com/mitchellh/packer/powershell/hyperv"
"log"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"os"
"path/filepath" "path/filepath"
"strings"
) )
const (
const(
FloppyFileName = "assets.vfd" FloppyFileName = "assets.vfd"
) )
type StepSetUnattendedProductKey struct { type StepSetUnattendedProductKey struct {
Files []string Files []string
ProductKey string ProductKey string
} }
@ -36,15 +32,15 @@ func (s *StepSetUnattendedProductKey) Run(state multistep.StateBag) multistep.St
if s.ProductKey == "" { if s.ProductKey == "" {
ui.Say("No product key specified...") ui.Say("No product key specified...")
return multistep.ActionContinue return multistep.ActionContinue
} }
index := -1 index := -1
for i, value := range s.Files { for i, value := range s.Files {
if s.caseInsensitiveContains(value, "Autounattend.xml") { if s.caseInsensitiveContains(value, "Autounattend.xml") {
index = i index = i
break break
} }
} }
ui.Say("Setting product key in Autounattend.xml...") ui.Say("Setting product key in Autounattend.xml...")
@ -59,10 +55,9 @@ func (s *StepSetUnattendedProductKey) Run(state multistep.StateBag) multistep.St
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *StepSetUnattendedProductKey) caseInsensitiveContains(str, substr string) bool { func (s *StepSetUnattendedProductKey) caseInsensitiveContains(str, substr string) bool {
str, substr = strings.ToUpper(str), strings.ToUpper(substr) str, substr = strings.ToUpper(str), strings.ToUpper(substr)
return strings.Contains(str, substr) return strings.Contains(str, substr)
} }
func (s *StepSetUnattendedProductKey) copyAutounattend(path string) (string, error) { func (s *StepSetUnattendedProductKey) copyAutounattend(path string) (string, error) {
@ -92,12 +87,9 @@ func (s *StepSetUnattendedProductKey) copyAutounattend(path string) (string, err
return autounattend, nil return autounattend, nil
} }
func (s *StepSetUnattendedProductKey) Cleanup(state multistep.StateBag) { func (s *StepSetUnattendedProductKey) Cleanup(state multistep.StateBag) {
} }
type StepMountFloppydrive struct { type StepMountFloppydrive struct {
floppyPath string floppyPath string
} }
@ -119,7 +111,7 @@ func (s *StepMountFloppydrive) Run(state multistep.StateBag) multistep.StepActio
if err != nil { if err != nil {
state.Put("error", fmt.Errorf("Error preparing floppy: %s", err)) state.Put("error", fmt.Errorf("Error preparing floppy: %s", err))
return multistep.ActionHalt return multistep.ActionHalt
} }
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
@ -135,7 +127,8 @@ func (s *StepMountFloppydrive) Run(state multistep.StateBag) multistep.StepActio
// Track the path so that we can unregister it from Hyper-V later // Track the path so that we can unregister it from Hyper-V later
s.floppyPath = floppyPath s.floppyPath = floppyPath
return multistep.ActionContinue} return multistep.ActionContinue
}
func (s *StepMountFloppydrive) Cleanup(state multistep.StateBag) { func (s *StepMountFloppydrive) Cleanup(state multistep.StateBag) {
if s.floppyPath == "" { if s.floppyPath == "" {

View File

@ -8,9 +8,10 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
powershell "github.com/mitchellh/packer/powershell" hyperv "github.com/mitchellh/packer/powershell/hyperv"
"log" "log"
"os" "os"
"strconv"
) )
type StepMountSecondaryDvdImages struct { type StepMountSecondaryDvdImages struct {
@ -88,67 +89,22 @@ func (s *StepMountSecondaryDvdImages) addAndMountIntegrationServicesSetupDisk(vm
} }
func (s *StepMountSecondaryDvdImages) addAndMountDvdDisk(vmName string, isoPath string) (DvdControllerProperties, error) { func (s *StepMountSecondaryDvdImages) addAndMountDvdDisk(vmName string, isoPath string) (DvdControllerProperties, error) {
var properties DvdControllerProperties var properties DvdControllerProperties
var script powershell.ScriptBuilder
powershell := new(powershell.PowerShellCmd)
controllerNumber := "0" controllerNumber, controllerLocation, err := hyperv.CreateDvdDrive(vmName, s.Generation)
if s.Generation < 2 {
// get the controller number that the OS install disk is mounted on
// generation 1 requires dvd to be added to ide controller, generation 2 uses scsi for dvd drives
script.Reset()
script.WriteLine("param([string]$vmName)")
script.WriteLine("$dvdDrives = (Get-VMDvdDrive -VMName $vmName)")
script.WriteLine("$lastControllerNumber = $dvdDrives | Sort-Object ControllerNumber | Select-Object -Last 1 | %{$_.ControllerNumber}")
script.WriteLine("if (!$lastControllerNumber) {")
script.WriteLine(" $lastControllerNumber = 0")
script.WriteLine("} elseif (!$lastControllerNumber -or ($dvdDrives | ?{ $_.ControllerNumber -eq $lastControllerNumber} | measure).count -gt 1) {")
script.WriteLine(" $lastControllerNumber += 1")
script.WriteLine("}")
script.WriteLine("$lastControllerNumber")
controllerNumber, err := powershell.Output(script.String(), vmName)
if err != nil {
return properties, err
}
if controllerNumber != "0" && controllerNumber != "1" {
//There are only 2 ide controllers, try to use the one the hdd is attached too
controllerNumber = "0"
}
}
script.Reset()
script.WriteLine("param([string]$vmName,[int]$controllerNumber)")
script.WriteLine("Add-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber")
err := powershell.Run(script.String(), vmName, controllerNumber)
if err != nil { if err != nil {
return properties, err return properties, err
} }
// we could try to get the controller location and number in one call, but this way we do not properties.ControllerNumber = strconv.FormatInt(int64(controllerNumber), 10)
// need to parse the output properties.ControllerLocation = strconv.FormatInt(int64(controllerLocation), 10)
script.Reset()
script.WriteLine("param([string]$vmName)")
script.WriteLine("(Get-VMDvdDrive -VMName $vmName | Where-Object {$_.Path -eq $null}).ControllerLocation")
controllerLocation, err := powershell.Output(script.String(), vmName)
if err != nil {
return properties, err
}
script.Reset() err = hyperv.MountDvdDriveByLocation(vmName, isoPath, controllerNumber, controllerLocation)
script.WriteLine("param([string]$vmName,[string]$path,[string]$controllerNumber,[string]$controllerLocation)")
script.WriteLine("Set-VMDvdDrive -VMName $vmName -Path $path -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation")
err = powershell.Run(script.String(), vmName, isoPath, controllerNumber, controllerLocation)
if err != nil { if err != nil {
return properties, err return properties, err
} }
log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", isoPath, controllerNumber, controllerLocation)) log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", isoPath, controllerNumber, controllerLocation))
properties.ControllerNumber = controllerNumber
properties.ControllerLocation = controllerLocation
return properties, nil return properties, nil
} }

View File

@ -5,15 +5,14 @@
package common package common
import ( import (
"bytes"
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"time"
// "net"
"log" "log"
"os/exec" "os/exec"
"strings" "strings"
"bytes" "time"
) )
const port string = "13000" const port string = "13000"
@ -29,36 +28,6 @@ func (s *StepPollingInstalation) Run(state multistep.StateBag) multistep.StepAct
vmIp := state.Get("ip").(string) vmIp := state.Get("ip").(string)
ui.Say("Start polling VM to check the installation is complete...") ui.Say("Start polling VM to check the installation is complete...")
/*
count := 30
var minutes time.Duration = 1
sleepMin := time.Minute * minutes
host := vmIp + ":" + port
timeoutSec := time.Second * 15
for count > 0 {
ui.Say(fmt.Sprintf("Connecting vm (%s)...", host ))
conn, err := net.DialTimeout("tcp", host, timeoutSec)
if err == nil {
ui.Say("Done!")
conn.Close()
break;
}
log.Println(err)
ui.Say(fmt.Sprintf("Waiting more %v minutes...", uint(minutes)))
time.Sleep(sleepMin)
count--
}
if count == 0 {
err := fmt.Errorf(errorMsg, "a signal from vm was not received in a given time period ")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
*/
host := "'" + vmIp + "'," + port host := "'" + vmIp + "'," + port
var blockBuffer bytes.Buffer var blockBuffer bytes.Buffer
@ -73,7 +42,7 @@ func (s *StepPollingInstalation) Run(state multistep.StateBag) multistep.StepAct
var res string var res string
for count > 0 { for count > 0 {
log.Println(fmt.Sprintf("Connecting vm (%s)...", host )) log.Println(fmt.Sprintf("Connecting vm (%s)...", host))
cmd := exec.Command("powershell", blockBuffer.String()) cmd := exec.Command("powershell", blockBuffer.String())
cmdOut, err := cmd.Output() cmdOut, err := cmd.Output()
if err != nil { if err != nil {
@ -88,8 +57,8 @@ func (s *StepPollingInstalation) Run(state multistep.StateBag) multistep.StepAct
if res != "False" { if res != "False" {
ui.Say("Signal was received from the VM") ui.Say("Signal was received from the VM")
// Sleep before starting provision // Sleep before starting provision
time.Sleep(time.Second*30) time.Sleep(time.Second * 30)
break; break
} }
log.Println(fmt.Sprintf("Slipping for more %v seconds...", uint(duration))) log.Println(fmt.Sprintf("Slipping for more %v seconds...", uint(duration)))

View File

@ -9,14 +9,13 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"time" "time"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepRebootVm struct { type StepRebootVm struct {
} }
func (s *StepRebootVm) Run(state multistep.StateBag) multistep.StepAction { func (s *StepRebootVm) Run(state multistep.StateBag) multistep.StepAction {
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
errorMsg := "Error rebooting vm: %s" errorMsg := "Error rebooting vm: %s"
@ -24,7 +23,7 @@ func (s *StepRebootVm) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Rebooting vm...") ui.Say("Rebooting vm...")
err := hyperv.RestartVirtualMachine(vmName) err := driver.RestartVirtualMachine(vmName)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)

View File

@ -8,22 +8,20 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepUnmountDvdDrive struct { type StepUnmountDvdDrive struct {
} }
func (s *StepUnmountDvdDrive) Run(state multistep.StateBag) multistep.StepAction { func (s *StepUnmountDvdDrive) Run(state multistep.StateBag) multistep.StepAction {
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
ui.Say("Unmounting dvd drive...") ui.Say("Unmounting dvd drive...")
err := hyperv.UnmountDvdDrive(vmName) err := driver.UnmountDvdDrive(vmName)
if err != nil { if err != nil {
err := fmt.Errorf("Error unmounting dvd drive: %s", err) err := fmt.Errorf("Error unmounting dvd drive: %s", err)
state.Put("error", err) state.Put("error", err)

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/powershell/hyperv"
) )
type StepUnmountFloppyDrive struct { type StepUnmountFloppyDrive struct {
@ -16,7 +15,7 @@ type StepUnmountFloppyDrive struct {
} }
func (s *StepUnmountFloppyDrive) Run(state multistep.StateBag) multistep.StepAction { func (s *StepUnmountFloppyDrive) Run(state multistep.StateBag) multistep.StepAction {
//driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
if s.Generation > 1 { if s.Generation > 1 {
@ -28,7 +27,7 @@ func (s *StepUnmountFloppyDrive) Run(state multistep.StateBag) multistep.StepAct
ui.Say("Unmounting floppy drive (Run)...") ui.Say("Unmounting floppy drive (Run)...")
err := hyperv.UnmountFloppyDrive(vmName) err := driver.UnmountFloppyDrive(vmName)
if err != nil { if err != nil {
err := fmt.Errorf(errorMsg, err) err := fmt.Errorf(errorMsg, err)
state.Put("error", err) state.Put("error", err)

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
powershell "github.com/mitchellh/packer/powershell"
"log" "log"
) )
@ -16,6 +15,7 @@ type StepUnmountSecondaryDvdImages struct {
} }
func (s *StepUnmountSecondaryDvdImages) Run(state multistep.StateBag) multistep.StepAction { func (s *StepUnmountSecondaryDvdImages) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Unmounting Integration Services Setup Disk...") ui.Say("Unmounting Integration Services Setup Disk...")
@ -28,17 +28,7 @@ func (s *StepUnmountSecondaryDvdImages) Run(state multistep.StateBag) multistep.
log.Println(fmt.Sprintf("Found DVD properties %d", len(dvdProperties))) log.Println(fmt.Sprintf("Found DVD properties %d", len(dvdProperties)))
for _, dvdProperty := range dvdProperties { for _, dvdProperty := range dvdProperties {
controllerNumber := dvdProperty.ControllerNumber err := driver.DeleteDvdDrive(vmName, dvdProperty.ControllerNumber, dvdProperty.ControllerLocation)
controllerLocation := dvdProperty.ControllerLocation
var script powershell.ScriptBuilder
powershell := new(powershell.PowerShellCmd)
script.WriteLine("param([string]$vmName,[int]$controllerNumber,[int]$controllerLocation)")
script.WriteLine("$vmDvdDrive = Get-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation")
script.WriteLine("if (!$vmDvdDrive) {throw 'unable to find dvd drive'}")
script.WriteLine("Remove-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation")
err := powershell.Run(script.String(), vmName, controllerNumber, controllerLocation)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())

View File

@ -8,10 +8,7 @@ import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"strings"
"strconv"
"time" "time"
powershell "github.com/mitchellh/packer/powershell"
) )
const ( const (
@ -22,29 +19,25 @@ type StepWaitForPowerOff struct {
} }
func (s *StepWaitForPowerOff) Run(state multistep.StateBag) multistep.StepAction { func (s *StepWaitForPowerOff) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
ui.Say("Waiting for vm to be powered down...") ui.Say("Waiting for vm to be powered down...")
var script powershell.ScriptBuilder
script.WriteLine("param([string]$vmName)")
script.WriteLine("(Get-VM -Name $vmName).State -eq [Microsoft.HyperV.PowerShell.VMState]::Off")
isOffScript := script.String()
for { for {
powershell := new(powershell.PowerShellCmd) isOff, err := driver.IsOff(vmName)
cmdOut, err := powershell.Output(isOffScript, vmName);
if err != nil { if err != nil {
err := fmt.Errorf("Error checking VM's state: %s", err) err := fmt.Errorf("Error checking if vm is off: %s", err)
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
if cmdOut == "True" { if isOff {
break break
} else { } else {
time.Sleep(time.Second * SleepSeconds); time.Sleep(time.Second * SleepSeconds)
} }
} }
@ -56,29 +49,24 @@ func (s *StepWaitForPowerOff) Cleanup(state multistep.StateBag) {
type StepWaitForInstallToComplete struct { type StepWaitForInstallToComplete struct {
ExpectedRebootCount uint ExpectedRebootCount uint
ActionName string ActionName string
} }
func (s *StepWaitForInstallToComplete) Run(state multistep.StateBag) multistep.StepAction { func (s *StepWaitForInstallToComplete) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
if(len(s.ActionName)>0){ if len(s.ActionName) > 0 {
ui.Say(fmt.Sprintf("%v ! Waiting for VM to reboot %v times...",s.ActionName, s.ExpectedRebootCount)) ui.Say(fmt.Sprintf("%v ! Waiting for VM to reboot %v times...", s.ActionName, s.ExpectedRebootCount))
} }
var rebootCount uint var rebootCount uint
var lastUptime uint64 var lastUptime uint64
var script powershell.ScriptBuilder
script.WriteLine("param([string]$vmName)")
script.WriteLine("(Get-VM -Name $vmName).Uptime.TotalSeconds")
uptimeScript := script.String()
for rebootCount < s.ExpectedRebootCount { for rebootCount < s.ExpectedRebootCount {
powershell := new(powershell.PowerShellCmd) uptime, err := driver.Uptime(vmName)
cmdOut, err := powershell.Output(uptimeScript, vmName);
if err != nil { if err != nil {
err := fmt.Errorf("Error checking uptime: %s", err) err := fmt.Errorf("Error checking uptime: %s", err)
state.Put("error", err) state.Put("error", err)
@ -86,20 +74,18 @@ func (s *StepWaitForInstallToComplete) Run(state multistep.StateBag) multistep.S
return multistep.ActionHalt return multistep.ActionHalt
} }
uptime, _ := strconv.ParseUint(strings.TrimSpace(string(cmdOut)), 10, 64) if uptime < lastUptime {
if uint64(uptime) < lastUptime {
rebootCount++ rebootCount++
ui.Say(fmt.Sprintf("%v -> Detected reboot %v after %v seconds...", s.ActionName, rebootCount, lastUptime)) ui.Say(fmt.Sprintf("%v -> Detected reboot %v after %v seconds...", s.ActionName, rebootCount, lastUptime))
} }
lastUptime = uptime lastUptime = uptime
if (rebootCount < s.ExpectedRebootCount) { if rebootCount < s.ExpectedRebootCount {
time.Sleep(time.Second * SleepSeconds); time.Sleep(time.Second * SleepSeconds)
} }
} }
return multistep.ActionContinue return multistep.ActionContinue
} }

View File

@ -2,6 +2,7 @@ package hyperv
import ( import (
"github.com/mitchellh/packer/powershell" "github.com/mitchellh/packer/powershell"
"strconv"
"strings" "strings"
) )
@ -50,6 +51,73 @@ $ip
return cmdOut, err return cmdOut, err
} }
func CreateDvdDrive(vmName string, generation uint) (uint, uint, error) {
var ps powershell.PowerShellCmd
var script string
var controllerNumber uint
controllerNumber = 0
if generation < 2 {
// get the controller number that the OS install disk is mounted on
// generation 1 requires dvd to be added to ide controller, generation 2 uses scsi for dvd drives
script = `
param([string]$vmName)
$dvdDrives = (Get-VMDvdDrive -VMName $vmName)
$lastControllerNumber = $dvdDrives | Sort-Object ControllerNumber | Select-Object -Last 1 | %{$_.ControllerNumber}
if (!$lastControllerNumber) {
$lastControllerNumber = 0
} elseif (!$lastControllerNumber -or ($dvdDrives | ?{ $_.ControllerNumber -eq $lastControllerNumber} | measure).count -gt 1) {
$lastControllerNumber += 1
}
$lastControllerNumber
`
cmdOut, err := ps.Output(script, vmName)
if err != nil {
return 0, 0, err
}
controllerNumberTemp, err := strconv.ParseUint(strings.TrimSpace(cmdOut), 10, 64)
if err != nil {
return 0, 0, err
}
controllerNumber = uint(controllerNumberTemp)
if controllerNumber != 0 && controllerNumber != 1 {
//There are only 2 ide controllers, try to use the one the hdd is attached too
controllerNumber = 0
}
}
script = `
param([string]$vmName,[int]$controllerNumber)
Add-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber
`
cmdOut, err := ps.Output(script, vmName)
if err != nil {
return controllerNumber, 0, err
}
// we could try to get the controller location and number in one call, but this way we do not
// need to parse the output
script = `
param([string]$vmName)
(Get-VMDvdDrive -VMName $vmName | Where-Object {$_.Path -eq $null}).ControllerLocation
`
cmdOut, err = ps.Output(script, vmName)
if err != nil {
return controllerNumber, 0, err
}
controllerLocationTemp, err := strconv.ParseUint(strings.TrimSpace(cmdOut), 10, 64)
if err != nil {
return controllerNumber, 0, err
}
controllerLocation := uint(controllerLocationTemp)
return controllerNumber, controllerLocation, err
}
func MountDvdDrive(vmName string, path string) error { func MountDvdDrive(vmName string, path string) error {
var script = ` var script = `
@ -62,6 +130,18 @@ Set-VMDvdDrive -VMName $vmName -Path $path
return err return err
} }
func MountDvdDriveByLocation(vmName string, path string, controllerNumber uint, controllerLocation uint) error {
var script = `
param([string]$vmName,[string]$path,[string]$controllerNumber,[string]$controllerLocation)
Set-VMDvdDrive -VMName $vmName -Path $path -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation
`
var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, path, strconv.FormatInt(int64(controllerNumber), 10), strconv.FormatInt(int64(controllerLocation), 10))
return err
}
func UnmountDvdDrive(vmName string) error { func UnmountDvdDrive(vmName string) error {
var script = ` var script = `
param([string]$vmName) param([string]$vmName)
@ -73,6 +153,19 @@ Get-VMDvdDrive -VMName $vmName | Set-VMDvdDrive -Path $null
return err return err
} }
func DeleteDvdDrive(vmName string, controllerNumber string, controllerLocation string) error {
var script = `
param([string]$vmName,[int]$controllerNumber,[int]$controllerLocation)
$vmDvdDrive = Get-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation
if (!$vmDvdDrive) {throw 'unable to find dvd drive'}
Remove-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation
`
var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, controllerNumber, controllerLocation)
return err
}
func MountFloppyDrive(vmName string, path string) error { func MountFloppyDrive(vmName string, path string) error {
var script = ` var script = `
param([string]$vmName, [string]$path) param([string]$vmName, [string]$path)
@ -96,9 +189,9 @@ Set-VMFloppyDiskDrive -VMName $vmName -Path $null
return err return err
} }
func CreateVirtualMachine(vmName string, path string, ram string, diskSize string, switchName string, generation string) error { func CreateVirtualMachine(vmName string, path string, ram int64, diskSize int64, switchName string, generation uint) error {
if generation == "2" { if generation == 2 {
var script = ` var script = `
param([string]$vmName, [string]$path, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [int]$generation) param([string]$vmName, [string]$path, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [int]$generation)
$vhdx = $vmName + '.vhdx' $vhdx = $vmName + '.vhdx'
@ -106,7 +199,7 @@ $vhdPath = Join-Path -Path $path -ChildPath $vhdx
New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName -Generation $generation New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName -Generation $generation
` `
var ps powershell.PowerShellCmd var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, path, ram, diskSize, switchName, generation) err := ps.Run(script, vmName, path, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), switchName, strconv.FormatInt(int64(generation), 10))
return err return err
} else { } else {
var script = ` var script = `
@ -116,12 +209,12 @@ $vhdPath = Join-Path -Path $path -ChildPath $vhdx
New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName
` `
var ps powershell.PowerShellCmd var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, path, ram, diskSize, switchName) err := ps.Run(script, vmName, path, strconv.FormatInt(ram, 10), strconv.FormatInt(diskSize, 10), switchName)
return err return err
} }
} }
func SetVirtualMachineCpu(vmName string, cpu string) error { func SetVirtualMachineCpu(vmName string, cpu uint) error {
var script = ` var script = `
param([string]$vmName, [int]$cpu) param([string]$vmName, [int]$cpu)
@ -129,7 +222,7 @@ Set-VMProcessor -VMName $vmName -Count $cpu
` `
var ps powershell.PowerShellCmd var ps powershell.PowerShellCmd
err := ps.Run(script, vmName, cpu) err := ps.Run(script, vmName, strconv.FormatInt(int64(cpu), 10))
return err return err
} }
@ -425,10 +518,53 @@ $vm.State -eq [Microsoft.HyperV.PowerShell.VMState]::Running
var ps powershell.PowerShellCmd var ps powershell.PowerShellCmd
cmdOut, err := ps.Output(script, vmName) cmdOut, err := ps.Output(script, vmName)
if err != nil {
return false, err
}
var isRunning = strings.TrimSpace(cmdOut) == "True" var isRunning = strings.TrimSpace(cmdOut) == "True"
return isRunning, err return isRunning, err
} }
func IsOff(vmName string) (bool, error) {
var script = `
param([string]$vmName)
$vm = Get-VM -Name $vmName -ErrorAction SilentlyContinue
$vm.State -eq [Microsoft.HyperV.PowerShell.VMState]::Off
`
var ps powershell.PowerShellCmd
cmdOut, err := ps.Output(script, vmName)
if err != nil {
return false, err
}
var isRunning = strings.TrimSpace(cmdOut) == "True"
return isRunning, err
}
func Uptime(vmName string) (uint64, error) {
var script = `
param([string]$vmName)
$vm = Get-VM -Name $vmName -ErrorAction SilentlyContinue
$vm.Uptime.TotalSeconds
`
var ps powershell.PowerShellCmd
cmdOut, err := ps.Output(script, vmName)
if err != nil {
return 0, err
}
uptime, err := strconv.ParseUint(strings.TrimSpace(string(cmdOut)), 10, 64)
return uptime, err
}
func Mac(vmName string) (string, error) { func Mac(vmName string) (string, error) {
var script = ` var script = `
param([string]$vmName, [int]$adapterIndex) param([string]$vmName, [int]$adapterIndex)