Allow configurable VNC bind IP for QEMU
This commit allows for a user configurable VNC bind IP to be used for QEMU. By default this will be 127.0.0.1, alternatively, a user can use 0.0.0.0 which will bind to all interfaces. This pull request should satisfy concerns of #3570 and #3559. It is also in-line with the functionality provided by #3566 and #3565 Signed-off-by: Ian Duffy <ian@ianduffy.ie>
This commit is contained in:
parent
7759229b9d
commit
fa273f3bea
|
@ -104,6 +104,7 @@ type Config struct {
|
||||||
ShutdownCommand string `mapstructure:"shutdown_command"`
|
ShutdownCommand string `mapstructure:"shutdown_command"`
|
||||||
SSHHostPortMin uint `mapstructure:"ssh_host_port_min"`
|
SSHHostPortMin uint `mapstructure:"ssh_host_port_min"`
|
||||||
SSHHostPortMax uint `mapstructure:"ssh_host_port_max"`
|
SSHHostPortMax uint `mapstructure:"ssh_host_port_max"`
|
||||||
|
VNCBindAddress string `mapstructure:"vnc_bind_address"`
|
||||||
VNCPortMin uint `mapstructure:"vnc_port_min"`
|
VNCPortMin uint `mapstructure:"vnc_port_min"`
|
||||||
VNCPortMax uint `mapstructure:"vnc_port_max"`
|
VNCPortMax uint `mapstructure:"vnc_port_max"`
|
||||||
VMName string `mapstructure:"vm_name"`
|
VMName string `mapstructure:"vm_name"`
|
||||||
|
@ -194,6 +195,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
b.config.SSHHostPortMax = 4444
|
b.config.SSHHostPortMax = 4444
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.config.VNCBindAddress == "" {
|
||||||
|
b.config.VNCBindAddress = "127.0.0.1"
|
||||||
|
}
|
||||||
|
|
||||||
if b.config.VNCPortMin == 0 {
|
if b.config.VNCPortMin == 0 {
|
||||||
b.config.VNCPortMin = 5900
|
b.config.VNCPortMin = 5900
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,6 +132,25 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_VNCBindAddress(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Test a default boot_wait
|
||||||
|
delete(config, "vnc_bind_address")
|
||||||
|
warns, err := b.Prepare(config)
|
||||||
|
if len(warns) > 0 {
|
||||||
|
t.Fatalf("bad: %#v", warns)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.config.VNCBindAddress != "127.0.0.1" {
|
||||||
|
t.Fatalf("bad value: %s", b.config.VNCBindAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_DiskCompaction(t *testing.T) {
|
func TestBuilderPrepare_DiskCompaction(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -26,7 +26,7 @@ func (stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
// Find an open VNC port. Note that this can still fail later on
|
// Find an open VNC port. Note that this can still fail later on
|
||||||
// because we have to release the port at some point. But this does its
|
// because we have to release the port at some point. But this does its
|
||||||
// best.
|
// best.
|
||||||
msg := fmt.Sprintf("Looking for available port between %d and %d", config.VNCPortMin, config.VNCPortMax)
|
msg := fmt.Sprintf("Looking for available port between %d and %d on %s", config.VNCPortMin, config.VNCPortMax, config.VNCBindAddress)
|
||||||
ui.Say(msg)
|
ui.Say(msg)
|
||||||
log.Printf(msg)
|
log.Printf(msg)
|
||||||
var vncPort uint
|
var vncPort uint
|
||||||
|
@ -39,15 +39,16 @@ func (stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Trying port: %d", vncPort)
|
log.Printf("Trying port: %d", vncPort)
|
||||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", vncPort))
|
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", config.VNCBindAddress, vncPort))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Found available VNC port: %d", vncPort))
|
log.Printf("Found available VNC port: %d on IP: %s", vncPort, config.VNCBindAddress)
|
||||||
state.Put("vnc_port", vncPort)
|
state.Put("vnc_port", vncPort)
|
||||||
|
state.Put("vnc_ip", config.VNCBindAddress)
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,12 +61,13 @@ func (s *stepRun) Cleanup(state multistep.StateBag) {
|
||||||
func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error) {
|
func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error) {
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
isoPath := state.Get("iso_path").(string)
|
isoPath := state.Get("iso_path").(string)
|
||||||
|
vncIP := state.Get("vnc_ip").(string)
|
||||||
vncPort := state.Get("vnc_port").(uint)
|
vncPort := state.Get("vnc_port").(uint)
|
||||||
sshHostPort := state.Get("sshHostPort").(uint)
|
sshHostPort := state.Get("sshHostPort").(uint)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
driver := state.Get("driver").(Driver)
|
driver := state.Get("driver").(Driver)
|
||||||
|
|
||||||
vnc := fmt.Sprintf("0.0.0.0:%d", vncPort-5900)
|
vnc := fmt.Sprintf("%s:%d", vncIP, vncPort-5900)
|
||||||
vmName := config.VMName
|
vmName := config.VMName
|
||||||
imgPath := filepath.Join(config.OutputDir, vmName)
|
imgPath := filepath.Join(config.OutputDir, vmName)
|
||||||
|
|
||||||
|
@ -100,9 +101,22 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
|
||||||
deviceArgs = append(deviceArgs, fmt.Sprintf("%s,netdev=user.0", config.NetDevice))
|
deviceArgs = append(deviceArgs, fmt.Sprintf("%s,netdev=user.0", config.NetDevice))
|
||||||
|
|
||||||
if config.Headless == true {
|
if config.Headless == true {
|
||||||
ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" +
|
vncIpRaw, vncIpOk := state.GetOk("vnc_ip")
|
||||||
"In headless mode, errors during the boot sequence or OS setup\n" +
|
vncPortRaw, vncPortOk := state.GetOk("vnc_port")
|
||||||
"won't be easily visible. Use at your own discretion.")
|
|
||||||
|
if vncIpOk && vncPortOk {
|
||||||
|
vncIp := vncIpRaw.(string)
|
||||||
|
vncPort := vncPortRaw.(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 VNC without a password to\n"+
|
||||||
|
"%s:%d", vncIp, vncPort))
|
||||||
|
} 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.")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if qemuMajor >= 2 {
|
if qemuMajor >= 2 {
|
||||||
defaultArgs["-display"] = "sdl"
|
defaultArgs["-display"] = "sdl"
|
||||||
|
|
|
@ -306,6 +306,10 @@ default port of `5985` or whatever value you have the service set to listen on.
|
||||||
`BUILDNAME` is the name of the build. Currently, no file extension will be
|
`BUILDNAME` is the name of the build. Currently, no file extension will be
|
||||||
used unless it is specified in this option.
|
used unless it is specified in this option.
|
||||||
|
|
||||||
|
- `vnc_bind_address` (string / IP address) - The IP address that should be binded
|
||||||
|
to for VNC. By default packer will use 127.0.0.1 for this. If you wish to bind
|
||||||
|
to all interfaces use 0.0.0.0
|
||||||
|
|
||||||
- `vnc_port_min` and `vnc_port_max` (integer) - The minimum and maximum port
|
- `vnc_port_min` and `vnc_port_max` (integer) - The minimum and maximum port
|
||||||
to use for VNC access to the virtual machine. The builder uses VNC to type
|
to use for VNC access to the virtual machine. The builder uses VNC to type
|
||||||
the initial `boot_command`. Because Packer generally runs in parallel,
|
the initial `boot_command`. Because Packer generally runs in parallel,
|
||||||
|
|
Loading…
Reference in New Issue