Merge pull request #3188 from mitchellh/f-vbox-vrdp

Add VRDP for virtualbox, from #2638
This commit is contained in:
Chris Bednarski 2016-02-11 14:39:19 -08:00
commit 8f1a8f4956
7 changed files with 124 additions and 3 deletions

View File

@ -11,6 +11,9 @@ type RunConfig struct {
Headless bool `mapstructure:"headless"` Headless bool `mapstructure:"headless"`
RawBootWait string `mapstructure:"boot_wait"` RawBootWait string `mapstructure:"boot_wait"`
VRDPPortMin uint `mapstructure:"vrdp_port_min"`
VRDPPortMax uint `mapstructure:"vrdp_port_max"`
BootWait time.Duration `` BootWait time.Duration ``
} }
@ -19,6 +22,14 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
c.RawBootWait = "10s" c.RawBootWait = "10s"
} }
if c.VRDPPortMin == 0 {
c.VRDPPortMin = 5900
}
if c.VRDPPortMax == 0 {
c.VRDPPortMax = 6000
}
var errs []error var errs []error
var err error var err error
c.BootWait, err = time.ParseDuration(c.RawBootWait) c.BootWait, err = time.ParseDuration(c.RawBootWait)
@ -26,5 +37,10 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
} }
if c.VRDPPortMin > c.VRDPPortMax {
errs = append(
errs, fmt.Errorf("vrdp_port_min must be less than vrdp_port_max"))
}
return errs return errs
} }

View File

@ -0,0 +1,73 @@
package common
import (
"fmt"
"log"
"math/rand"
"net"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
// This step configures the VM to enable the VRDP server
// on the guest machine.
//
// Uses:
// driver Driver
// ui packer.Ui
// vmName string
//
// Produces:
// vrdp_port unit - The port that VRDP is configured to listen on.
type StepConfigureVRDP struct {
VRDPPortMin uint
VRDPPortMax uint
}
func (s *StepConfigureVRDP) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string)
log.Printf("Looking for available port between %d and %d", s.VRDPPortMin, s.VRDPPortMax)
var vrdpPort uint
portRange := int (s.VRDPPortMax - s.VRDPPortMin)
for {
if portRange > 0 {
vrdpPort = uint(rand.Intn(portRange)) + s.VRDPPortMin
} else {
vrdpPort = s.VRDPPortMin
}
log.Printf("Trying port: %d", vrdpPort)
l, err := net.Listen("tcp", fmt.Sprintf(":%d", vrdpPort))
if err == nil {
defer l.Close()
break
}
}
command := []string{
"modifyvm", vmName,
"--vrdeaddress", "127.0.0.1",
"--vrdeauthtype", "null",
"--vrde", "on",
"--vrdeport",
fmt.Sprintf("%d", vrdpPort),
}
if err := driver.VBoxManage(command...); err != nil {
err := fmt.Errorf("Error enabling VRDP: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("vrdpIp", "127.0.0.1")
state.Put("vrdpPort", vrdpPort)
return multistep.ActionContinue
}
func (s *StepConfigureVRDP) Cleanup(state multistep.StateBag) {}

View File

@ -30,9 +30,22 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Starting the virtual machine...") ui.Say("Starting the virtual machine...")
guiArgument := "gui" guiArgument := "gui"
if s.Headless == true { if s.Headless == true {
ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" + vrdpIpRaw, vrdpIpOk := state.GetOk("vrdpIp")
"In headless mode, errors during the boot sequence or OS setup\n" + vrdpPortRaw, vrdpPortOk := state.GetOk("vrdpPort")
"won't be easily visible. Use at your own discretion.")
if vrdpIpOk && vrdpPortOk {
vrdpIp := vrdpIpRaw.(string)
vrdpPort := vrdpPortRaw.(uint)
ui.Message(fmt.Sprintf(
"The VM will be run headless, without a GUI. If you want to\n"+
"view the screen of the VM, connect via VRDP without a password to\n"+
"%s:%d", vrdpIp, vrdpPort))
} else {
ui.Message("The VM will be run headless, without a GUI, as configured.\n" +
"If the run isn't succeeding as you expect, please enable the GUI\n" +
"to inspect the progress of the build.")
}
guiArgument = "headless" guiArgument = "headless"
} }
command := []string{"startvm", vmName, "--type", guiArgument} command := []string{"startvm", vmName, "--type", guiArgument}

View File

@ -208,6 +208,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&vboxcommon.StepAttachGuestAdditions{ &vboxcommon.StepAttachGuestAdditions{
GuestAdditionsMode: b.config.GuestAdditionsMode, GuestAdditionsMode: b.config.GuestAdditionsMode,
}, },
&vboxcommon.StepConfigureVRDP{
VRDPPortMin: b.config.VRDPPortMin,
VRDPPortMax: b.config.VRDPPortMax,
},
new(vboxcommon.StepAttachFloppy), new(vboxcommon.StepAttachFloppy),
&vboxcommon.StepForwardSSH{ &vboxcommon.StepForwardSSH{
CommConfig: &b.config.SSHConfig.Comm, CommConfig: &b.config.SSHConfig.Comm,

View File

@ -76,6 +76,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&vboxcommon.StepAttachGuestAdditions{ &vboxcommon.StepAttachGuestAdditions{
GuestAdditionsMode: b.config.GuestAdditionsMode, GuestAdditionsMode: b.config.GuestAdditionsMode,
}, },
&vboxcommon.StepConfigureVRDP{
VRDPPortMin: b.config.VRDPPortMin,
VRDPPortMax: b.config.VRDPPortMax,
},
new(vboxcommon.StepAttachFloppy), new(vboxcommon.StepAttachFloppy),
&vboxcommon.StepForwardSSH{ &vboxcommon.StepForwardSSH{
CommConfig: &b.config.SSHConfig.Comm, CommConfig: &b.config.SSHConfig.Comm,

View File

@ -242,6 +242,12 @@ builder.
machine, without the file extension. By default this is "packer-BUILDNAME", machine, without the file extension. By default this is "packer-BUILDNAME",
where "BUILDNAME" is the name of the build. where "BUILDNAME" is the name of the build.
- `vrdp_port_min` and `vrdp_port_max` (integer) - The minimum and maximum port
to use for VRDP access to the virtual machine. Packer uses a randomly chosen
port in this range that appears available. By default this is 5900 to 6000.
The minimum and maximum ports are inclusive.
## Boot Command ## Boot Command
The `boot_command` configuration is very important: it specifies the keys to The `boot_command` configuration is very important: it specifies the keys to

View File

@ -207,6 +207,11 @@ builder.
is exported. By default this is "packer-BUILDNAME", where "BUILDNAME" is the is exported. By default this is "packer-BUILDNAME", where "BUILDNAME" is the
name of the build. name of the build.
- `vrdp_port_min` and `vrdp_port_max` (integer) - The minimum and maximum port
to use for VRDP access to the virtual machine. Packer uses a randomly chosen
port in this range that appears available. By default this is 5900 to 6000.
The minimum and maximum ports are inclusive.
## Guest Additions ## Guest Additions
Packer will automatically download the proper guest additions for the version of Packer will automatically download the proper guest additions for the version of