QEMU: Initial QMP support
This commit is contained in:
parent
ba66d5d857
commit
afe9ba2869
|
@ -117,6 +117,8 @@ type Config struct {
|
|||
OutputDir string `mapstructure:"output_directory"`
|
||||
QemuArgs [][]string `mapstructure:"qemuargs"`
|
||||
QemuBinary string `mapstructure:"qemu_binary"`
|
||||
QMPEnable bool `mapstructure:"qmp_enable"`
|
||||
QMPSocketPath string `mapstructure:"qmp_socket_path"`
|
||||
ShutdownCommand string `mapstructure:"shutdown_command"`
|
||||
SSHHostPortMin int `mapstructure:"ssh_host_port_min"`
|
||||
SSHHostPortMax int `mapstructure:"ssh_host_port_max"`
|
||||
|
@ -344,6 +346,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max"))
|
||||
}
|
||||
|
||||
if b.config.SSHHostPortMin < 0 {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("ssh_host_port_min must be positive"))
|
||||
|
@ -354,6 +357,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))
|
||||
}
|
||||
|
||||
if b.config.QMPEnable && b.config.QMPSocketPath == "" {
|
||||
socketName := fmt.Sprintf("%s.monitor", b.config.VMName)
|
||||
b.config.QMPSocketPath = filepath.Join(b.config.OutputDir, socketName)
|
||||
}
|
||||
|
||||
if b.config.QemuArgs == nil {
|
||||
b.config.QemuArgs = make([][]string, 0)
|
||||
}
|
||||
|
@ -425,6 +433,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
steps = append(steps,
|
||||
new(stepConfigureVNC),
|
||||
steprun,
|
||||
new(stepConfigureQMP),
|
||||
&stepTypeBootCommand{},
|
||||
)
|
||||
|
||||
|
|
|
@ -598,3 +598,25 @@ func TestBuilderPrepare_QemuArgs(t *testing.T) {
|
|||
t.Fatalf("bad: %#v", b.config.QemuArgs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_QMP(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// QMP Defaults
|
||||
config["qmp_enable"] = true
|
||||
config["output_directory"] = "not-a-real-directory"
|
||||
b = Builder{}
|
||||
warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
expected := "not-a-real-directory/packer-foo.monitor"
|
||||
if !reflect.DeepEqual(b.config.QMPSocketPath, expected) {
|
||||
t.Fatalf("Bad QMP socket Path: %s", b.config.QMPSocketPath)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package qemu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/digitalocean/go-qemu/qmp"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// This step configures the VM to enable the QMP listener.
|
||||
//
|
||||
// Uses:
|
||||
// config *config
|
||||
// ui packer.Ui
|
||||
//
|
||||
// Produces:
|
||||
type stepConfigureQMP struct {
|
||||
monitor *qmp.SocketMonitor
|
||||
}
|
||||
|
||||
func (s *stepConfigureQMP) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !config.QMPEnable {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("Opening QMP socket at: %s", config.QMPSocketPath)
|
||||
ui.Say(msg)
|
||||
log.Print(msg)
|
||||
|
||||
// Open QMP socket
|
||||
var err error
|
||||
s.monitor, err = qmp.NewSocketMonitor("unix", config.QMPSocketPath, 2*time.Second)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error opening QMP socket: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
QMPMonitor := s.monitor
|
||||
|
||||
log.Printf("QMP socket open SUCCESS")
|
||||
|
||||
state.Put("qmp_monitor", QMPMonitor)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepConfigureQMP) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -85,6 +85,10 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
|
|||
defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0")
|
||||
}
|
||||
|
||||
if config.QMPEnable {
|
||||
defaultArgs["-qmp"] = fmt.Sprintf("unix:%s,server,nowait", config.QMPSocketPath)
|
||||
}
|
||||
|
||||
rawVersion, err := driver.Version()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -282,6 +282,13 @@ Linux server and have not enabled X11 forwarding (`ssh -X`).
|
|||
switch/value pairs. Any value specified as an empty string is ignored. All
|
||||
values after the switch are concatenated with no separator.
|
||||
|
||||
- `qmp_enable` (bool) - Enable QMP socket. Location is specified by
|
||||
`qmp_socket_path`.
|
||||
Defaults to false.
|
||||
|
||||
- `qmp_socket_path` (string) - QMP Socket Path when `qmp_enable` is true.
|
||||
Defaults to `output_directory`/`vm_name`.monitor.
|
||||
|
||||
~> **Warning:** The qemu command line allows extreme flexibility, so beware
|
||||
of conflicting arguments causing failures of your run. For instance, using
|
||||
--no-acpi could break the ability to send power signal type commands (e.g.,
|
||||
|
|
Loading…
Reference in New Issue