Merge pull request #6243 from camjjack/hyper-v-gui
Using vmconnect to display gui for hyper-v
This commit is contained in:
commit
edb5c1f50d
|
@ -1,5 +1,9 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// A driver is able to talk to HyperV and perform certain
|
||||
// operations with it. Some of the operations on here may seem overly
|
||||
// specific, but they were built specifically in mind to handle features
|
||||
|
@ -109,4 +113,10 @@ type Driver interface {
|
|||
MountFloppyDrive(string, string) error
|
||||
|
||||
UnmountFloppyDrive(string) error
|
||||
|
||||
// Connect connects to a VM specified by the name given.
|
||||
Connect(string) (context.CancelFunc, error)
|
||||
|
||||
// Disconnect disconnects to a VM specified by the context cancel function.
|
||||
Disconnect(context.CancelFunc)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type DriverMock struct {
|
||||
IsRunning_Called bool
|
||||
IsRunning_VmName string
|
||||
|
@ -240,6 +244,14 @@ type DriverMock struct {
|
|||
UnmountFloppyDrive_Called bool
|
||||
UnmountFloppyDrive_VmName string
|
||||
UnmountFloppyDrive_Err error
|
||||
|
||||
Connect_Called bool
|
||||
Connect_VmName string
|
||||
Connect_Cancel context.CancelFunc
|
||||
Connect_Err error
|
||||
|
||||
Disconnect_Called bool
|
||||
Disconnect_Cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (d *DriverMock) IsRunning(vmName string) (bool, error) {
|
||||
|
@ -553,3 +565,14 @@ func (d *DriverMock) UnmountFloppyDrive(vmName string) error {
|
|||
d.UnmountFloppyDrive_VmName = vmName
|
||||
return d.UnmountFloppyDrive_Err
|
||||
}
|
||||
|
||||
func (d *DriverMock) Connect(vmName string) (context.CancelFunc, error) {
|
||||
d.Connect_Called = true
|
||||
d.Connect_VmName = vmName
|
||||
return d.Connect_Cancel, d.Connect_Err
|
||||
}
|
||||
|
||||
func (d *DriverMock) Disconnect(cancel context.CancelFunc) {
|
||||
d.Disconnect_Called = true
|
||||
d.Disconnect_Cancel = cancel
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
|
@ -347,3 +348,14 @@ func (d *HypervPS4Driver) verifyHypervPermissions() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Connect connects to a VM specified by the name given.
|
||||
func (d *HypervPS4Driver) Connect(vmName string) (context.CancelFunc, error) {
|
||||
return hyperv.ConnectVirtualMachine(vmName)
|
||||
}
|
||||
|
||||
// Disconnect disconnects to a VM specified by calling the context cancel function returned
|
||||
// from Connect.
|
||||
func (d *HypervPS4Driver) Disconnect(cancel context.CancelFunc) {
|
||||
hyperv.DisconnectVirtualMachine(cancel)
|
||||
}
|
||||
|
|
|
@ -3,13 +3,16 @@ package common
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type StepRun struct {
|
||||
vmName string
|
||||
GuiCancelFunc context.CancelFunc
|
||||
Headless bool
|
||||
vmName string
|
||||
}
|
||||
|
||||
func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
|
@ -29,6 +32,13 @@ func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.Ste
|
|||
|
||||
s.vmName = vmName
|
||||
|
||||
if !s.Headless {
|
||||
ui.Say("Attempting to connect with vmconnect...")
|
||||
s.GuiCancelFunc, err = driver.Connect(vmName)
|
||||
if err != nil {
|
||||
log.Printf(fmt.Sprintf("Non-fatal error starting vmconnect: %s. continuing...", err))
|
||||
}
|
||||
}
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
|
@ -40,6 +50,11 @@ func (s *StepRun) Cleanup(state multistep.StateBag) {
|
|||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !s.Headless && s.GuiCancelFunc != nil {
|
||||
ui.Say("Disconnecting from vmconnect...")
|
||||
s.GuiCancelFunc()
|
||||
}
|
||||
|
||||
if running, _ := driver.IsRunning(s.vmName); running {
|
||||
if err := driver.Stop(s.vmName); err != nil {
|
||||
ui.Error(fmt.Sprintf("Error shutting down VM: %s", err))
|
||||
|
|
|
@ -115,6 +115,8 @@ type Config struct {
|
|||
// Create the VM with a Fixed VHD format disk instead of Dynamic VHDX
|
||||
FixedVHD bool `mapstructure:"use_fixed_vhd_format"`
|
||||
|
||||
Headless bool `mapstructure:"headless"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
|
@ -427,7 +429,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
SwitchVlanId: b.config.SwitchVlanId,
|
||||
},
|
||||
|
||||
&hypervcommon.StepRun{},
|
||||
&hypervcommon.StepRun{
|
||||
Headless: b.config.Headless,
|
||||
},
|
||||
|
||||
&hypervcommon.StepTypeBootCommand{
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
|
|
|
@ -98,6 +98,8 @@ type Config struct {
|
|||
|
||||
SkipExport bool `mapstructure:"skip_export"`
|
||||
|
||||
Headless bool `mapstructure:"headless"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
|
@ -436,7 +438,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
SwitchVlanId: b.config.SwitchVlanId,
|
||||
},
|
||||
|
||||
&hypervcommon.StepRun{},
|
||||
&hypervcommon.StepRun{
|
||||
Headless: b.config.Headless,
|
||||
},
|
||||
|
||||
&hypervcommon.StepTypeBootCommand{
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package hyperv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -1244,3 +1246,18 @@ param([string]$vmName, [string]$scanCodes)
|
|||
err := ps.Run(script, vmName, scanCodes)
|
||||
return err
|
||||
}
|
||||
|
||||
func ConnectVirtualMachine(vmName string) (context.CancelFunc, error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cmd := exec.CommandContext(ctx, "vmconnect.exe", "localhost", vmName)
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
// Failed to start so cancel function not required
|
||||
cancel = nil
|
||||
}
|
||||
return cancel, err
|
||||
}
|
||||
|
||||
func DisconnectVirtualMachine(cancel context.CancelFunc) {
|
||||
cancel()
|
||||
}
|
||||
|
|
|
@ -102,6 +102,11 @@ can be configured for this builder.
|
|||
- `differencing_disk` (boolean) - If true enables differencing disks. Only the changes will be written to the new disk. This is especially useful if your
|
||||
source is a vhd/vhdx. This defaults to false.
|
||||
|
||||
- `headless` (boolean) - Packer defaults to building Hyper-V virtual
|
||||
machines by launching a GUI that shows the console of the machine
|
||||
being built. When this value is set to true, the machine will start without
|
||||
a console.
|
||||
|
||||
- `skip_export` (boolean) - If true skips VM export. If you are interested only in the vhd/vhdx files, you can enable this option. This will create
|
||||
inline disks which improves the build performance. There will not be any copying of source vhds to temp directory. This defaults to false.
|
||||
|
||||
|
|
|
@ -139,6 +139,11 @@ can be configured for this builder.
|
|||
- `guest_additions_path` (string) - The path to the iso image for guest
|
||||
additions.
|
||||
|
||||
- `headless` (boolean) - Packer defaults to building Hyper-V virtual
|
||||
machines by launching a GUI that shows the console of the machine
|
||||
being built. When this value is set to true, the machine will start without
|
||||
a console.
|
||||
|
||||
- `http_directory` (string) - Path to a directory to serve using an HTTP
|
||||
server. The files in this directory will be available over HTTP that will
|
||||
be requestable from the virtual machine. This is useful for hosting
|
||||
|
|
Loading…
Reference in New Issue