driver/qemu: Setup multiple port forwards

This commit is contained in:
Clint Shryock 2015-09-23 23:15:28 -05:00
parent e2b91c786d
commit e67d892ea3
2 changed files with 47 additions and 16 deletions

View File

@ -14,6 +14,7 @@ import (
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"syscall"
"time"
@ -71,7 +72,7 @@ func (d *QemuDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
return false, fmt.Errorf("Unable to parse Qemu version string: %#v", matches)
}
node.Attributes["driver.qemu"] = "true"
node.Attributes["driver.qemu"] = "1"
node.Attributes["driver.qemu.version"] = matches[1]
return true, nil
@ -92,6 +93,10 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
return nil, fmt.Errorf("Missing required Task Resource: Memory")
}
if len(task.Resources.Networks) == 0 {
return nil, fmt.Errorf("[WARN] driver.qemu: No networks are available for port mapping")
}
// Attempt to download the thing
// Should be extracted to some kind of Http Fetcher
// Right now, assume publicly accessible HTTP url
@ -162,16 +167,40 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
// TODO: Consolidate these into map of host/guest port when we have HCL
// Note: Host port must be open and available
if task.Config["guest_port"] != "" && task.Config["host_port"] != "" {
args = append(args,
"-netdev",
fmt.Sprintf("user,id=user.0,hostfwd=tcp::%s-:%s",
task.Config["host_port"],
task.Config["guest_port"]),
"-device", "virtio-net,netdev=user.0",
)
// Get and split guest ports. The guest_ports configuration must match up with
// the Reserved ports in the Task Resources
// Users can supply guest_hosts as a list of posts to map on the guest vm.
// These map 1:1 with the requested Reserved Ports from the hostmachine.
ports := strings.Split(task.Config["guest_ports"], ",")
if len(ports) == 0 {
return nil, fmt.Errorf("[ERR] driver.qemu: Error parsing required Guest Ports")
}
// TODO: support more than a single, default Network
if len(ports) != len(task.Resources.Networks[0].ReservedPorts) {
return nil, fmt.Errorf("[ERR] driver.qemu: Error matching Guest Ports with Reserved ports")
}
// Loop through the reserved ports and construct the hostfwd string, to map
// reserved ports to the ports listenting in the VM
// Ex:
// hostfwd=tcp::22000-:22,hostfwd=tcp::80-:8080
reservedPorts := task.Resources.Networks[0].ReservedPorts
var forwarding string
for i, p := range ports {
forwarding = fmt.Sprintf("%s,hostfwd=tcp::%s-:%s", forwarding, strconv.Itoa(reservedPorts[i]), p)
}
if "" == forwarding {
return nil, fmt.Errorf("[ERR] driver.qemu: Error constructing port forwarding")
}
args = append(args,
"-netdev",
fmt.Sprintf("user,id=user.0%s", forwarding),
"-device", "virtio-net,netdev=user.0",
)
// If using KVM, add optimization args
if accelerator == "kvm" {
args = append(args,

View File

@ -55,14 +55,16 @@ func TestQemuDriver_Start(t *testing.T) {
"image_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/linux-0.2.img",
"checksum": "a5e836985934c3392cbbd9b26db55a7d35a8d7ae1deb7ca559dd9c0159572544",
"accelerator": "tcg",
"host_port": "8080",
"guest_port": "8081",
"guest_ports": "22,8080",
},
Resources: &structs.Resources{
MemoryMB: 512,
Networks: []*structs.NetworkResource{
&structs.NetworkResource{
ReservedPorts: []int{22000, 80},
},
},
},
}
// add requred memory resource
task.Resources = &structs.Resources{
MemoryMB: 512,
}
handle, err := d.Start(ctx, task)