mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-24 03:15:36 +00:00
Merge pull request #2490 from MagnusS/update-vpnkit
Update to latest Hyperkit API
This commit is contained in:
commit
c793ea973c
@ -41,11 +41,13 @@ func runHyperKit(args []string) {
|
||||
var disks Disks
|
||||
flags.Var(&disks, "disk", "Disk config. [file=]path[,size=1G]")
|
||||
data := flags.String("data", "", "Metadata to pass to VM (either a path to a file or a string)")
|
||||
ipStr := flags.String("ip", "", "IP address for the VM")
|
||||
ipStr := flags.String("ip", "", "Preferred IPv4 address for the VM.")
|
||||
state := flags.String("state", "", "Path to directory to keep VM state in")
|
||||
vsockports := flags.String("vsock-ports", "", "List of vsock ports to forward from the guest on startup (comma separated). A unix domain socket for each port will be created in the state directory")
|
||||
networking := flags.String("networking", hyperkitNetworkingDefault, "Networking mode. Valid options are 'default', 'docker-for-mac', 'vpnkit[,socket-path]', 'vmnet' and 'none'. 'docker-for-mac' connects to the network used by Docker for Mac. 'vpnkit' connects to the VPNKit socket specified. If socket-path is omitted a new VPNKit instance will be started and 'vpnkit_eth.sock' will be created in the state directory. 'vmnet' uses the Apple vmnet framework, requires root/sudo. 'none' disables networking.`")
|
||||
|
||||
vpnKitUUID := flags.String("vpnkit-uuid", "", "Optional UUID used to identify the VPNKit connection. Overrides 'uuid.vpnkit' in the state directory.")
|
||||
|
||||
// Boot type; we try to determine automatically
|
||||
uefiBoot := flags.Bool("uefi", false, "Use UEFI boot")
|
||||
isoBoot := flags.Bool("iso", false, "Boot image is an ISO")
|
||||
@ -149,17 +151,22 @@ func runHyperKit(args []string) {
|
||||
isoPaths = append(isoPaths, isoPath)
|
||||
}
|
||||
|
||||
vpnKitKey := ""
|
||||
if *ipStr != "" {
|
||||
// If an IP address was requested construct a "special" UUID
|
||||
// for the VM.
|
||||
if ip := net.ParseIP(*ipStr); len(ip) > 0 {
|
||||
uuid := make([]byte, 16)
|
||||
uuid[12] = ip.To4()[0]
|
||||
uuid[13] = ip.To4()[1]
|
||||
uuid[14] = ip.To4()[2]
|
||||
uuid[15] = ip.To4()[3]
|
||||
vpnKitKey = fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
|
||||
// Create UUID for VPNKit or reuse an existing one from state dir. IP addresses are
|
||||
// assigned to the UUID, so to get the same IP we have to store the initial UUID. If
|
||||
// has specified a VPNKit UUID the file is ignored.
|
||||
if *vpnKitUUID == "" {
|
||||
vpnKitUUIDFile := filepath.Join(*state, "uuid.vpnkit")
|
||||
if _, err := os.Stat(vpnKitUUIDFile); os.IsNotExist(err) {
|
||||
*vpnKitUUID = uuid.NewV4().String()
|
||||
if err := ioutil.WriteFile(vpnKitUUIDFile, []byte(*vpnKitUUID), 0600); err != nil {
|
||||
log.Fatalf("Unable to write to %s: %v", vpnKitUUIDFile, err)
|
||||
}
|
||||
} else {
|
||||
uuid, err := ioutil.ReadFile(vpnKitUUIDFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to read VPNKit UUID from %s: %v", vpnKitUUIDFile, err)
|
||||
}
|
||||
*vpnKitUUID = string(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,13 +259,21 @@ func runHyperKit(args []string) {
|
||||
} else {
|
||||
h.Bootrom = *fw
|
||||
}
|
||||
h.VPNKitKey = vpnKitKey
|
||||
h.UUID = vmUUID
|
||||
h.ISOImages = isoPaths
|
||||
h.VSock = true
|
||||
h.CPUs = *cpus
|
||||
h.Memory = *mem
|
||||
|
||||
h.VPNKitUUID = *vpnKitUUID
|
||||
if *ipStr != "" {
|
||||
if ip := net.ParseIP(*ipStr); len(ip) > 0 && ip.To4() != nil {
|
||||
h.VPNKitPreferredIPv4 = ip.String()
|
||||
} else {
|
||||
log.Fatalf("Unable to parse IPv4 address: %v", *ipStr)
|
||||
}
|
||||
}
|
||||
|
||||
err = h.Run(string(cmdline))
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot run hyperkit: %v", err)
|
||||
|
@ -11,7 +11,7 @@ github.com/googleapis/gax-go 8c5154c0fe5bf18cf649634d4c6df50897a32751
|
||||
github.com/gophercloud/gophercloud 2804b72cf099b41d2e25c8afcca786f9f962ddee
|
||||
github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
|
||||
github.com/mitchellh/go-ps 4fdf99ab29366514c69ccccddab5dc58b8d84062
|
||||
github.com/moby/hyperkit a82b409a87f12fa3306813410c37f4eed270efac
|
||||
github.com/moby/hyperkit 3e31617ae866c93925e2b3bc5d8006b60985e920
|
||||
github.com/packethost/packngo 131798f2804a1b3e895ca98047d56f0d7e094e2a
|
||||
github.com/radu-matei/azure-sdk-for-go 3b12823551999669c9a325a32472508e0af7978e
|
||||
github.com/radu-matei/azure-vhd-utils e52754d5569d2a643a7775f72ff2a6cf524f4c25
|
||||
|
24
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go
generated
vendored
24
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go
generated
vendored
@ -28,6 +28,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
@ -85,8 +86,10 @@ type HyperKit struct {
|
||||
StateDir string `json:"state_dir"`
|
||||
// VPNKitSock is the location of the VPNKit socket used for networking.
|
||||
VPNKitSock string `json:"vpnkit_sock"`
|
||||
// VPNKitKey is a string containing a UUID, it can be used in conjunction with VPNKit to get consistent IP address.
|
||||
VPNKitKey string `json:"vpnkit_key"`
|
||||
// VPNKitUUID is a string containing a UUID, it can be used in conjunction with VPNKit to get consistent IP address.
|
||||
VPNKitUUID string `json:"vpnkit_uuid"`
|
||||
// VPNKitPreferredIPv4 is a string containing an IPv4 address, it can be used to request a specific IP for a UUID from VPNKit.
|
||||
VPNKitPreferredIPv4 string `json:"vpnkit_preferred_ipv4"`
|
||||
// UUID is a string containing a UUID, it sets BIOS DMI UUID for the VM (as found in /sys/class/dmi/id/product_uuid on Linux).
|
||||
UUID string `json:"uuid"`
|
||||
// Disks contains disk images to use/create.
|
||||
@ -249,6 +252,11 @@ func (h *HyperKit) execute(cmdline string) error {
|
||||
return fmt.Errorf("Bootrom %s does not exist", h.Bootrom)
|
||||
}
|
||||
}
|
||||
if h.VPNKitPreferredIPv4 != "" {
|
||||
if ip := net.ParseIP(h.VPNKitPreferredIPv4); ip == nil {
|
||||
return fmt.Errorf("Invalid VPNKit IP: %s", h.VPNKitPreferredIPv4)
|
||||
}
|
||||
}
|
||||
|
||||
// Create files
|
||||
if h.StateDir != "" {
|
||||
@ -420,11 +428,15 @@ func (h *HyperKit) buildArgs(cmdline string) {
|
||||
nextSlot := 1
|
||||
|
||||
if h.VPNKitSock != "" {
|
||||
if h.VPNKitKey == "" {
|
||||
a = append(a, "-s", fmt.Sprintf("%d:0,virtio-vpnkit,path=%s", nextSlot, h.VPNKitSock))
|
||||
} else {
|
||||
a = append(a, "-s", fmt.Sprintf("%d:0,virtio-vpnkit,path=%s,uuid=%s", nextSlot, h.VPNKitSock, h.VPNKitKey))
|
||||
var uuid string
|
||||
if h.VPNKitUUID != "" {
|
||||
uuid = fmt.Sprintf(",uuid=%s", h.VPNKitUUID)
|
||||
}
|
||||
var preferredIPv4 string
|
||||
if h.VPNKitPreferredIPv4 != "" {
|
||||
preferredIPv4 = fmt.Sprintf(",preferred_ipv4=%s", h.VPNKitPreferredIPv4)
|
||||
}
|
||||
a = append(a, "-s", fmt.Sprintf("%d:0,virtio-vpnkit,path=%s%s%s", nextSlot, h.VPNKitSock, uuid, preferredIPv4))
|
||||
nextSlot++
|
||||
}
|
||||
|
||||
|
103
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/pci_virtio_net_vpnkit.c
generated
vendored
103
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/pci_virtio_net_vpnkit.c
generated
vendored
@ -77,6 +77,8 @@
|
||||
#include <xhyve/pci_emul.h>
|
||||
#include <xhyve/mevent.h>
|
||||
#include <xhyve/virtio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
#define WPRINTF(format, ...) printf(format, __VA_ARGS__)
|
||||
|
||||
@ -93,13 +95,18 @@ struct msg_init {
|
||||
} __packed;
|
||||
|
||||
#define CMD_ETHERNET 1
|
||||
struct msg_common {
|
||||
uint8_t command;
|
||||
#define CMD_PREFERRED_IPV4 8
|
||||
|
||||
#define RESP_VIF 1
|
||||
#define RESP_DISCONNECT 2
|
||||
|
||||
struct cmd_ethernet {
|
||||
char uuid[36];
|
||||
} __packed;
|
||||
|
||||
struct msg_ethernet {
|
||||
uint8_t command; /* CMD_ETHERNET */
|
||||
struct cmd_preferred_ipv4 {
|
||||
char uuid[36];
|
||||
in_addr_t ip;
|
||||
} __packed;
|
||||
|
||||
struct vif_info {
|
||||
@ -108,6 +115,26 @@ struct vif_info {
|
||||
uint8_t mac[6];
|
||||
} __packed;
|
||||
|
||||
struct disconnect_reason {
|
||||
uint8_t len;
|
||||
char msg[256];
|
||||
} __packed;
|
||||
|
||||
struct msg_command {
|
||||
uint8_t command;
|
||||
union {
|
||||
struct cmd_ethernet ethernet;
|
||||
struct cmd_preferred_ipv4 preferred_ipv4;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct msg_response {
|
||||
uint8_t response_type;
|
||||
union {
|
||||
struct disconnect_reason disconnect;
|
||||
struct vif_info vif;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Host capabilities. Note that we only offer a few of these.
|
||||
@ -286,11 +313,11 @@ err:
|
||||
/*
|
||||
* wire protocol
|
||||
*/
|
||||
static int vpnkit_connect(int fd, const char uuid[36], struct vif_info *vif)
|
||||
static int vpnkit_connect(int fd, const char uuid[36], struct vif_info *vif, in_addr_t preferred_ipv4)
|
||||
{
|
||||
struct msg_init init_msg = {
|
||||
.magic = { 'V', 'M', 'N', '3', 'T' },
|
||||
.version = 1U,
|
||||
.version = 22U,
|
||||
};
|
||||
|
||||
/* msg.commit is not NULL terminated */
|
||||
@ -324,21 +351,49 @@ static int vpnkit_connect(int fd, const char uuid[36], struct vif_info *vif)
|
||||
init_reply.magic[4],
|
||||
init_reply.version, (int)sizeof(init_reply.commit), init_reply.commit);
|
||||
|
||||
struct msg_ethernet cmd_ethernet = {
|
||||
.command = CMD_ETHERNET,
|
||||
};
|
||||
memcpy(cmd_ethernet.uuid, uuid, sizeof(cmd_ethernet.uuid));
|
||||
if (init_reply.version != init_msg.version) {
|
||||
fprintf(stderr, "virtio-net-vpnkit: protocol version mismatch: version %d requested, got version %d.\n",
|
||||
init_msg.version,
|
||||
init_reply.version);
|
||||
}
|
||||
|
||||
if (really_write(fd, (uint8_t*)&cmd_ethernet, sizeof(cmd_ethernet)) < 0) {
|
||||
fprintf(stderr, "virtio-net-vpnkit: failed to write ethernet cmd\n");
|
||||
struct msg_command cmd;
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
if (preferred_ipv4 != 0) {
|
||||
cmd.command = CMD_PREFERRED_IPV4;
|
||||
memcpy(cmd.preferred_ipv4.uuid, uuid, sizeof(cmd.preferred_ipv4.uuid));
|
||||
/* VPNKit uses LE, so swap the IP from network byte order */
|
||||
cmd.preferred_ipv4.ip = OSSwapInt32(preferred_ipv4);
|
||||
} else {
|
||||
/* No preferred IPv4 address, falling back to requesting a dynamic address */
|
||||
cmd.command = CMD_ETHERNET;
|
||||
memcpy(cmd.ethernet.uuid, uuid, sizeof(cmd.ethernet.uuid));
|
||||
}
|
||||
|
||||
if (really_write(fd, (uint8_t*)&cmd, sizeof(cmd)) < 0) {
|
||||
fprintf(stderr, "virtio-net-vpnkit: failed to write command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (really_read(fd, (uint8_t*)vif, sizeof(*vif)) < 0) {
|
||||
fprintf(stderr, "virtio-net-vpnkit: failed to read vif info\n");
|
||||
struct msg_response reply;
|
||||
if (really_read(fd, (uint8_t*)&reply, sizeof(reply)) < 0) {
|
||||
fprintf(stderr, "virtio-net-vpnkit: failed to read response message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (reply.response_type) {
|
||||
case RESP_VIF:
|
||||
memcpy((uint8_t*)vif, (uint8_t*)&reply.vif, sizeof(*vif));
|
||||
break;
|
||||
case RESP_DISCONNECT:
|
||||
fprintf(stderr, "virtio-net-vpnkit: server disconnected: %*s\n", reply.disconnect.len, reply.disconnect.msg);
|
||||
return -1;
|
||||
default:
|
||||
fprintf(stderr, "virtio-net-vpnkit: unknown response from server: %d\n", reply.response_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -362,9 +417,11 @@ vpnkit_create(struct pci_vtnet_softc *sc, const char *opts)
|
||||
const char *path = "/var/tmp/com.docker.slirp.socket";
|
||||
char *macfile = NULL;
|
||||
char *tmp = NULL;
|
||||
char *ipv4 = NULL;
|
||||
uuid_t uuid;
|
||||
char uuid_string[37];
|
||||
struct sockaddr_un addr;
|
||||
struct in_addr preferred_ipv4 = { .s_addr = 0 };
|
||||
int fd;
|
||||
struct vpnkit_state *state = malloc(sizeof(struct vpnkit_state));
|
||||
if (!state) abort();
|
||||
@ -393,11 +450,16 @@ vpnkit_create(struct pci_vtnet_softc *sc, const char *opts)
|
||||
return 1;
|
||||
}
|
||||
memcpy(&uuid_string[0], &tmp[0], 36);
|
||||
fprintf(stdout, "Interface will have uuid %s\n", tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
} else if (strncmp(opts, "macfile=", 8) == 0) {
|
||||
macfile = copy_up_to_comma(opts + 8);
|
||||
} else if (strncmp(opts, "preferred_ipv4=", 15) == 0) {
|
||||
ipv4 = copy_up_to_comma(opts + 15);
|
||||
if (inet_aton(ipv4, &preferred_ipv4) == 0) {
|
||||
fprintf(stderr, "Unable to parse requested IP %s\n", ipv4);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "invalid option: %s\r\n", opts);
|
||||
return 1;
|
||||
@ -407,6 +469,11 @@ vpnkit_create(struct pci_vtnet_softc *sc, const char *opts)
|
||||
opts = &next[1];
|
||||
}
|
||||
|
||||
fprintf(stdout, "virtio-net-vpnkit: interface will have uuid %s\n", uuid_string);
|
||||
if (ipv4 != NULL) {
|
||||
fprintf(stdout, "virtio-net-vpnkit: requesting ip %s\n", ipv4);
|
||||
}
|
||||
|
||||
state->vif.max_packet_size = 1500;
|
||||
sc->state = state;
|
||||
|
||||
@ -423,7 +490,7 @@ vpnkit_create(struct pci_vtnet_softc *sc, const char *opts)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (vpnkit_connect(fd, uuid_string, &state->vif) == 0)
|
||||
if (vpnkit_connect(fd, uuid_string, &state->vif, preferred_ipv4.s_addr) == 0)
|
||||
/* success */
|
||||
break;
|
||||
|
||||
@ -441,8 +508,8 @@ err:
|
||||
state->fd = fd;
|
||||
|
||||
struct vif_info *info = &state->vif;
|
||||
fprintf(stdout, "Connection established with MAC=%02x:%02x:%02x:%02x:%02x:%02x and MTU %d\n",
|
||||
info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5],
|
||||
fprintf(stdout, "virtio-net-vpnkit: Connection established with MAC=%02x:%02x:%02x:%02x:%02x:%02x and MTU %d\n",
|
||||
info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5],
|
||||
(int)info->mtu);
|
||||
|
||||
if (macfile) {
|
||||
|
Loading…
Reference in New Issue
Block a user