mirror of
https://github.com/kemko/nomad.git
synced 2026-01-03 17:05:43 +03:00
Qemu driver takes a port_map to configure host to guest port forwarding
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -33,10 +32,10 @@ type QemuDriver struct {
|
||||
}
|
||||
|
||||
type QemuDriverConfig struct {
|
||||
ArtifactSource string `mapstructure:"artifact_source"`
|
||||
Checksum string `mapstructure:"checksum"`
|
||||
Accelerator string `mapstructure:"accelerator"`
|
||||
GuestPorts string `mapstructure:"guest_ports"`
|
||||
ArtifactSource string `mapstructure:"artifact_source"`
|
||||
Checksum string `mapstructure:"checksum"`
|
||||
Accelerator string `mapstructure:"accelerator"`
|
||||
PortMap []map[string]int `mapstructure:"port_map"` // A map of host port labels and to guest ports.
|
||||
}
|
||||
|
||||
// qemuHandle is returned from Start/Open as a handle to the PID
|
||||
@@ -82,6 +81,11 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
|
||||
if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(driverConfig.PortMap) > 1 {
|
||||
return nil, fmt.Errorf("Only one port_map block is allowed in the qemu driver config")
|
||||
}
|
||||
|
||||
// Get the image source
|
||||
source, ok := task.Config["artifact_source"]
|
||||
if !ok || source == "" {
|
||||
@@ -138,42 +142,31 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
|
||||
// the outside world to be able to reach it. VMs ran without port mappings can
|
||||
// still reach out to the world, but without port mappings it is effectively
|
||||
// firewalled
|
||||
if len(task.Resources.Networks) > 0 {
|
||||
// TODO: Consolidate these into map of host/guest port when we have HCL
|
||||
// Note: Host port must be open and available
|
||||
// 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(driverConfig.GuestPorts, ",")
|
||||
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
|
||||
protocols := []string{"udp", "tcp"}
|
||||
if len(task.Resources.Networks) > 0 && len(driverConfig.PortMap) == 1 {
|
||||
// Loop through the port map 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].Value), p)
|
||||
// Ex: hostfwd=tcp::22000-:22,hostfwd=tcp::80-:8080
|
||||
var forwarding []string
|
||||
taskPorts := task.Resources.Networks[0].MapLabelToValues()
|
||||
for label, guest := range driverConfig.PortMap[0] {
|
||||
host, ok := taskPorts[label]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Unknown port label %q", label)
|
||||
}
|
||||
|
||||
for _, p := range protocols {
|
||||
forwarding = append(forwarding, fmt.Sprintf("hostfwd=%s::%d-:%d", p, host, guest))
|
||||
}
|
||||
}
|
||||
|
||||
if "" == forwarding {
|
||||
return nil, fmt.Errorf("[ERR] driver.qemu: Error constructing port forwarding")
|
||||
if len(forwarding) != 0 {
|
||||
args = append(args,
|
||||
"-netdev",
|
||||
fmt.Sprintf("user,id=user.0%s", strings.Join(forwarding, ",")),
|
||||
"-device", "virtio-net,netdev=user.0",
|
||||
)
|
||||
}
|
||||
|
||||
args = append(args,
|
||||
"-netdev",
|
||||
fmt.Sprintf("user,id=user.0%s", forwarding),
|
||||
"-device", "virtio-net,netdev=user.0",
|
||||
)
|
||||
}
|
||||
|
||||
// If using KVM, add optimization args
|
||||
|
||||
@@ -41,7 +41,10 @@ func TestQemuDriver_StartOpen_Wait(t *testing.T) {
|
||||
"artifact_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/linux-0.2.img",
|
||||
"checksum": "sha256:a5e836985934c3392cbbd9b26db55a7d35a8d7ae1deb7ca559dd9c0159572544",
|
||||
"accelerator": "tcg",
|
||||
"guest_ports": "22,8080",
|
||||
"port_map": []map[string]int{{
|
||||
"main": 22,
|
||||
"web": 8080,
|
||||
}},
|
||||
},
|
||||
Resources: &structs.Resources{
|
||||
CPU: 500,
|
||||
|
||||
Reference in New Issue
Block a user