mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-21 18:11:35 +00:00
Update to new Hyperkit API / VPNKit protocol
This adds support for the updated Hyperkit API, which is needed to request a specific IP address in new versions of VPNKit / Docker for Mac. IPs encoded in the UUID (the old method) will now be ignored by VPNKit. A preferred IPv4 address can be requested directly via the new API. The IP is then associated with the VPNKit UUID identifying the connection. The UUID is either user specified or randomly assigned if left empty. VMs launched with the same VPNKit UUID it will get the same IP address. To avoid having to copy the assigned UUID manually, a file `uuid.vpnkit` is now saved in the state directory when the UUID is generated. The UUID from this file is reused automatically if it exists, unless a different VPNKit UUID is specified on the command line. This also means that VMs that use dynamically assigned IPs will by default get the same IP each time they are started, as long as the state directory exists. This change is incompatible with earlier versions of VPNKit / Hyperkit and a recent version of Docker for Mac has to be installed. If the feature is unsupported using the `--ip` parameter will exit with an error message. Signed-off-by: Magnus Skjegstad <magnus@skjegstad.com>
This commit is contained in:
parent
241136e910
commit
c8ba942a80
@ -41,11 +41,13 @@ func runHyperKit(args []string) {
|
|||||||
var disks Disks
|
var disks Disks
|
||||||
flags.Var(&disks, "disk", "Disk config. [file=]path[,size=1G]")
|
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)")
|
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")
|
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")
|
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.`")
|
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
|
// Boot type; we try to determine automatically
|
||||||
uefiBoot := flags.Bool("uefi", false, "Use UEFI boot")
|
uefiBoot := flags.Bool("uefi", false, "Use UEFI boot")
|
||||||
isoBoot := flags.Bool("iso", false, "Boot image is an ISO")
|
isoBoot := flags.Bool("iso", false, "Boot image is an ISO")
|
||||||
@ -149,17 +151,22 @@ func runHyperKit(args []string) {
|
|||||||
isoPaths = append(isoPaths, isoPath)
|
isoPaths = append(isoPaths, isoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
vpnKitKey := ""
|
// Create UUID for VPNKit or reuse an existing one from state dir. IP addresses are
|
||||||
if *ipStr != "" {
|
// assigned to the UUID, so to get the same IP we have to store the initial UUID. If
|
||||||
// If an IP address was requested construct a "special" UUID
|
// has specified a VPNKit UUID the file is ignored.
|
||||||
// for the VM.
|
if *vpnKitUUID == "" {
|
||||||
if ip := net.ParseIP(*ipStr); len(ip) > 0 {
|
vpnKitUUIDFile := filepath.Join(*state, "uuid.vpnkit")
|
||||||
uuid := make([]byte, 16)
|
if _, err := os.Stat(vpnKitUUIDFile); os.IsNotExist(err) {
|
||||||
uuid[12] = ip.To4()[0]
|
*vpnKitUUID = uuid.NewV4().String()
|
||||||
uuid[13] = ip.To4()[1]
|
if err := ioutil.WriteFile(vpnKitUUIDFile, []byte(*vpnKitUUID), 0600); err != nil {
|
||||||
uuid[14] = ip.To4()[2]
|
log.Fatalf("Unable to write to %s: %v", vpnKitUUIDFile, err)
|
||||||
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:])
|
} 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 {
|
} else {
|
||||||
h.Bootrom = *fw
|
h.Bootrom = *fw
|
||||||
}
|
}
|
||||||
h.VPNKitKey = vpnKitKey
|
|
||||||
h.UUID = vmUUID
|
h.UUID = vmUUID
|
||||||
h.ISOImages = isoPaths
|
h.ISOImages = isoPaths
|
||||||
h.VSock = true
|
h.VSock = true
|
||||||
h.CPUs = *cpus
|
h.CPUs = *cpus
|
||||||
h.Memory = *mem
|
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))
|
err = h.Run(string(cmdline))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Cannot run hyperkit: %v", err)
|
log.Fatalf("Cannot run hyperkit: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user