Fixes #1 and Fixes #2 by allowing qemuargs to operate and override defaults.

This commit is contained in:
Tom Hite 2013-10-07 20:58:08 -05:00
parent ba1ca4d2fb
commit 2f8f2d5ad1
3 changed files with 132 additions and 37 deletions

View File

@ -17,14 +17,27 @@ import (
const BuilderId = "transcend.qemu"
var netDevice = map[string]bool{
"ne2k_pci": true,
"i82551": true,
"i82557b": true,
"i82559er": true,
"rtl8139": true,
"e1000": true,
"pcnet": true,
"virtio": true,
"ne2k_pci": true,
"i82551": true,
"i82557b": true,
"i82559er": true,
"rtl8139": true,
"e1000": true,
"pcnet": true,
"virtio": true,
"virtio-net": true,
"usb-net": true,
"i82559a": true,
"i82559b": true,
"i82559c": true,
"i82550": true,
"i82562": true,
"i82557a": true,
"i82557c": true,
"i82801": true,
"vmxnet3": true,
"i82558a": true,
"i82558b": true,
}
var diskInterface = map[string]bool{

View File

@ -35,6 +35,84 @@ func cancelCallback(state multistep.StateBag) bool {
return cancel
}
func (s *stepRun) getCommandArgs(
bootDrive string,
state multistep.StateBag) []string {
ui := state.Get("ui").(packer.Ui)
config := state.Get("config").(*config)
vmName := config.VMName
imgPath := filepath.Join(config.OutputDir,
fmt.Sprintf("%s.%s", vmName, strings.ToLower(config.Format)))
isoPath := state.Get("iso_path").(string)
vncPort := state.Get("vnc_port").(uint)
guiArgument := "sdl"
sshHostPort := state.Get("sshHostPort").(uint)
vnc := fmt.Sprintf("0.0.0.0:%d", vncPort-5900)
if config.Headless == true {
ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" +
"In headless mode, errors during the boot sequence or OS setup\n" +
"won't be easily visible. Use at your own discretion.")
guiArgument = "none"
}
defaultArgs := make(map[string]string)
defaultArgs["-name"] = vmName
defaultArgs["-machine"] = fmt.Sprintf("type=pc-1.0,accel=%s", config.Accelerator)
defaultArgs["-display"] = guiArgument
defaultArgs["-netdev"] = "user,id=user.0"
defaultArgs["-device"] = fmt.Sprintf("%s,netdev=user.0", config.NetDevice)
defaultArgs["-drive"] = fmt.Sprintf("file=%s,if=%s", imgPath, config.DiskInterface)
defaultArgs["-cdrom"] = isoPath
defaultArgs["-boot"] = bootDrive
defaultArgs["-m"] = "512m"
defaultArgs["-redir"] = fmt.Sprintf("tcp:%v::22", sshHostPort)
defaultArgs["-vnc"] = vnc
inArgs := make(map[string][]string)
if len(config.QemuArgs) > 0 {
ui.Say("Overriding defaults Qemu arguments with QemuArgs...")
// becuase qemu supports multiple appearances of the same
// switch, just different values, each key in the args hash
// will have an array of string values
for _, qemuArgs := range config.QemuArgs {
key := qemuArgs[0]
val := strings.Join(qemuArgs[1:], "")
if _, ok := inArgs[key]; !ok {
inArgs[key] = make([]string, 0)
}
if len(val) > 0 {
inArgs[key] = append(inArgs[key], val)
}
}
}
// get any remaining missing default args from the default settings
for key := range defaultArgs {
if _, ok := inArgs[key]; !ok {
arg := make([]string, 1)
arg[0] = defaultArgs[key]
inArgs[key] = arg
}
}
// Flatten to array of strings
outArgs := make([]string, 0)
for key, values := range inArgs {
if len(values) > 0 {
for idx := range values {
outArgs = append(outArgs, key, values[idx])
}
} else {
outArgs = append(outArgs, key)
}
}
return outArgs
}
func (s *stepRun) runVM(
sendBootCommands bool,
bootDrive string,
@ -45,35 +123,8 @@ func (s *stepRun) runVM(
ui := state.Get("ui").(packer.Ui)
vmName := config.VMName
imgPath := filepath.Join(config.OutputDir,
fmt.Sprintf("%s.%s", vmName, strings.ToLower(config.Format)))
isoPath := state.Get("iso_path").(string)
vncPort := state.Get("vnc_port").(uint)
guiArgument := "sdl"
sshHostPort := state.Get("sshHostPort").(uint)
vnc := fmt.Sprintf("0.0.0.0:%d", vncPort-5900)
ui.Say("Starting the virtual machine for OS Install...")
if config.Headless == true {
ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" +
"In headless mode, errors during the boot sequence or OS setup\n" +
"won't be easily visible. Use at your own discretion.")
guiArgument = "none"
}
command := []string{
"-name", vmName,
"-machine", fmt.Sprintf("type=pc-1.0,accel=%s", config.Accelerator),
"-display", guiArgument,
"-net", fmt.Sprintf("nic,model=%s", config.NetDevice),
"-net", "user",
"-drive", fmt.Sprintf("file=%s,if=%s", imgPath, config.DiskInterface),
"-cdrom", isoPath,
"-boot", bootDrive,
"-m", "512m",
"-redir", fmt.Sprintf("tcp:%v::22", sshHostPort),
"-vnc", vnc,
}
command := s.getCommandArgs(bootDrive, state)
if err := driver.Qemu(vmName, command...); err != nil {
err := fmt.Errorf("Error launching VM: %s", err)
ui.Error(err.Error())

View File

@ -223,7 +223,38 @@ Optional:
values "ne2k_pci," "i82551," "i82557b," "i82559er," "rtl8139," "e1000,"
"pcnet" or "virtio." The Qemu builder uses "virtio" by default.
* `qemuargs` (array of strings reserved for future use).
* `qemuargs` (array of array of strings) - Allows complete control over
the qemu command line (though not, at this time, qemu-img). Each array
of strings makes up a command line switch that overrides matching default
switch/value pairs. Any value specified as an empty string is ignored.
All values after the switch are concatenated with no separater. For instance:
<pre class="prettyprint">
. . .
"qemuargs": [
[ "-m", "1024m" ],
[ "--no-acpi", "" ],
[
"-netdev",
"user,id=mynet0,",
"hostfwd=hostip:hostport-guestip:guestport",
""
],
[ "-device", "virtio-net,netdev=mynet0" ]
]
. . .
</pre>
would produce the following (not including other defaults supplied by the builder and not otherwise conflicting with the qemuargs):
<pre class="prettyprint">
qemu-system-x86 -m 1024m --no-acpi -netdev user,id=mynet0,hostfwd=hostip:hostport-guestip:guestport -device virtio-net,netdev=mynet0"
</pre>
Note that the qemu command line allows extreme flexibility, so beware of
conflicting arguments causing failures of your run. To see the defaults,
look in the packer.log file and search for the qemu-system-x86 command. The
arguments are all printed for review.
* `output_directory` (string) - This is the path to the directory where the
resulting virtual machine will be created. This may be relative or absolute.