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
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
// A driver is able to talk to HyperV and perform certain
|
// A driver is able to talk to HyperV and perform certain
|
||||||
// operations with it. Some of the operations on here may seem overly
|
// operations with it. Some of the operations on here may seem overly
|
||||||
// specific, but they were built specifically in mind to handle features
|
// specific, but they were built specifically in mind to handle features
|
||||||
|
@ -109,4 +113,10 @@ type Driver interface {
|
||||||
MountFloppyDrive(string, string) error
|
MountFloppyDrive(string, string) error
|
||||||
|
|
||||||
UnmountFloppyDrive(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
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
type DriverMock struct {
|
type DriverMock struct {
|
||||||
IsRunning_Called bool
|
IsRunning_Called bool
|
||||||
IsRunning_VmName string
|
IsRunning_VmName string
|
||||||
|
@ -240,6 +244,14 @@ type DriverMock struct {
|
||||||
UnmountFloppyDrive_Called bool
|
UnmountFloppyDrive_Called bool
|
||||||
UnmountFloppyDrive_VmName string
|
UnmountFloppyDrive_VmName string
|
||||||
UnmountFloppyDrive_Err error
|
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) {
|
func (d *DriverMock) IsRunning(vmName string) (bool, error) {
|
||||||
|
@ -553,3 +565,14 @@ func (d *DriverMock) UnmountFloppyDrive(vmName string) error {
|
||||||
d.UnmountFloppyDrive_VmName = vmName
|
d.UnmountFloppyDrive_VmName = vmName
|
||||||
return d.UnmountFloppyDrive_Err
|
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
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -347,3 +348,14 @@ func (d *HypervPS4Driver) verifyHypervPermissions() error {
|
||||||
|
|
||||||
return nil
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepRun struct {
|
type StepRun struct {
|
||||||
vmName string
|
GuiCancelFunc context.CancelFunc
|
||||||
|
Headless bool
|
||||||
|
vmName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
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
|
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
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +50,11 @@ func (s *StepRun) Cleanup(state multistep.StateBag) {
|
||||||
driver := state.Get("driver").(Driver)
|
driver := state.Get("driver").(Driver)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
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 running, _ := driver.IsRunning(s.vmName); running {
|
||||||
if err := driver.Stop(s.vmName); err != nil {
|
if err := driver.Stop(s.vmName); err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error shutting down VM: %s", err))
|
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
|
// Create the VM with a Fixed VHD format disk instead of Dynamic VHDX
|
||||||
FixedVHD bool `mapstructure:"use_fixed_vhd_format"`
|
FixedVHD bool `mapstructure:"use_fixed_vhd_format"`
|
||||||
|
|
||||||
|
Headless bool `mapstructure:"headless"`
|
||||||
|
|
||||||
ctx interpolate.Context
|
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,
|
SwitchVlanId: b.config.SwitchVlanId,
|
||||||
},
|
},
|
||||||
|
|
||||||
&hypervcommon.StepRun{},
|
&hypervcommon.StepRun{
|
||||||
|
Headless: b.config.Headless,
|
||||||
|
},
|
||||||
|
|
||||||
&hypervcommon.StepTypeBootCommand{
|
&hypervcommon.StepTypeBootCommand{
|
||||||
BootCommand: b.config.FlatBootCommand(),
|
BootCommand: b.config.FlatBootCommand(),
|
||||||
|
|
|
@ -98,6 +98,8 @@ type Config struct {
|
||||||
|
|
||||||
SkipExport bool `mapstructure:"skip_export"`
|
SkipExport bool `mapstructure:"skip_export"`
|
||||||
|
|
||||||
|
Headless bool `mapstructure:"headless"`
|
||||||
|
|
||||||
ctx interpolate.Context
|
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,
|
SwitchVlanId: b.config.SwitchVlanId,
|
||||||
},
|
},
|
||||||
|
|
||||||
&hypervcommon.StepRun{},
|
&hypervcommon.StepRun{
|
||||||
|
Headless: b.config.Headless,
|
||||||
|
},
|
||||||
|
|
||||||
&hypervcommon.StepTypeBootCommand{
|
&hypervcommon.StepTypeBootCommand{
|
||||||
BootCommand: b.config.FlatBootCommand(),
|
BootCommand: b.config.FlatBootCommand(),
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package hyperv
|
package hyperv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -1244,3 +1246,18 @@ param([string]$vmName, [string]$scanCodes)
|
||||||
err := ps.Run(script, vmName, scanCodes)
|
err := ps.Run(script, vmName, scanCodes)
|
||||||
return err
|
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
|
- `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.
|
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
|
- `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.
|
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
|
- `guest_additions_path` (string) - The path to the iso image for guest
|
||||||
additions.
|
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
|
- `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
|
server. The files in this directory will be available over HTTP that will
|
||||||
be requestable from the virtual machine. This is useful for hosting
|
be requestable from the virtual machine. This is useful for hosting
|
||||||
|
|
Loading…
Reference in New Issue