Path: blob/master/pkg/driver/krunkit/krunkit_darwin_arm64.go
2632 views
// SPDX-FileCopyrightText: Copyright The Lima Authors1// SPDX-License-Identifier: Apache-2.023package krunkit45import (6"context"7"errors"8"fmt"9"net"10"os"11"os/exec"12"path/filepath"13"strconv"1415"github.com/docker/go-units"16"github.com/lima-vm/go-qcow2reader/image/raw"17"github.com/sirupsen/logrus"1819"github.com/lima-vm/lima/v2/pkg/driver/vz"20"github.com/lima-vm/lima/v2/pkg/imgutil/proxyimgutil"21"github.com/lima-vm/lima/v2/pkg/limatype"22"github.com/lima-vm/lima/v2/pkg/limatype/filenames"23"github.com/lima-vm/lima/v2/pkg/limayaml"24"github.com/lima-vm/lima/v2/pkg/networks"25"github.com/lima-vm/lima/v2/pkg/networks/usernet"26"github.com/lima-vm/lima/v2/pkg/store"27)2829const logLevelInfo = "3"3031// Cmdline constructs the command line arguments for krunkit based on the instance configuration.32func Cmdline(inst *limatype.Instance) (*exec.Cmd, error) {33memBytes, err := units.RAMInBytes(*inst.Config.Memory)34if err != nil {35return nil, err36}3738args := []string{39// Memory in MiB40"--memory", strconv.FormatInt(memBytes/units.MiB, 10),41"--cpus", fmt.Sprintf("%d", *inst.Config.CPUs),42"--device", fmt.Sprintf("virtio-serial,logFilePath=%s", filepath.Join(inst.Dir, filenames.SerialLog)),43"--krun-log-level", logLevelInfo,44"--restful-uri", "none://",4546// First virtio-blk device is the boot disk47"--device", fmt.Sprintf("virtio-blk,path=%s,format=raw", filepath.Join(inst.Dir, filenames.DiffDisk)),48"--device", fmt.Sprintf("virtio-blk,path=%s", filepath.Join(inst.Dir, filenames.CIDataISO)),49}5051// Add additional disks52if len(inst.Config.AdditionalDisks) > 0 {53ctx := context.Background()54diskUtil := proxyimgutil.NewDiskUtil(ctx)55for _, d := range inst.Config.AdditionalDisks {56disk, derr := store.InspectDisk(d.Name, d.FSType)57if derr != nil {58return nil, fmt.Errorf("failed to load disk %q: %w", d.Name, derr)59}60if disk.Instance != "" {61return nil, fmt.Errorf("failed to run attach disk %q, in use by instance %q", disk.Name, disk.Instance)62}63if lerr := disk.Lock(inst.Dir); lerr != nil {64return nil, fmt.Errorf("failed to lock disk %q: %w", d.Name, lerr)65}66extraDiskPath := filepath.Join(disk.Dir, filenames.DataDisk)67logrus.Infof("Mounting disk %q on %q", disk.Name, disk.MountPoint)68if cerr := diskUtil.Convert(ctx, raw.Type, extraDiskPath, extraDiskPath, nil, true); cerr != nil {69return nil, fmt.Errorf("failed to convert extra disk %q to raw: %w", extraDiskPath, cerr)70}71args = append(args, "--device", fmt.Sprintf("virtio-blk,path=%s,format=raw", extraDiskPath))72}73}7475// Network commands76networkArgs, err := buildNetworkArgs(inst)77if err != nil {78return nil, fmt.Errorf("failed to build network arguments: %w", err)79}8081// File sharing commands82if *inst.Config.MountType == limatype.VIRTIOFS {83for _, mount := range inst.Config.Mounts {84if _, err := os.Stat(mount.Location); errors.Is(err, os.ErrNotExist) {85if err := os.MkdirAll(mount.Location, 0o750); err != nil {86return nil, err87}88}89tag := limayaml.MountTag(mount.Location, *mount.MountPoint)90mountArg := fmt.Sprintf("virtio-fs,sharedDir=%s,mountTag=%s", mount.Location, tag)91args = append(args, "--device", mountArg)92}93}9495args = append(args, networkArgs...)96cmd := exec.CommandContext(context.Background(), vmType, args...)9798return cmd, nil99}100101func buildNetworkArgs(inst *limatype.Instance) ([]string, error) {102var args []string103104// Configure default usernetwork with limayaml.MACAddress(inst.Dir) for eth0 interface105firstUsernetIndex := limayaml.FirstUsernetIndex(inst.Config)106if firstUsernetIndex == -1 {107// slirp network using gvisor netstack108krunkitSock, err := usernet.SockWithDirectory(inst.Dir, "", usernet.FDSock)109if err != nil {110return nil, err111}112client, err := vz.PassFDToUnix(krunkitSock)113if err != nil {114return nil, err115}116117args = append(args, "--device", fmt.Sprintf("virtio-net,type=unixgram,fd=%d,mac=%s", client.Fd(), limayaml.MACAddress(inst.Dir)))118}119120for _, nw := range inst.Networks {121var sock string122var mac string123if nw.Lima != "" {124nwCfg, err := networks.LoadConfig()125if err != nil {126return nil, err127}128switch nw.Lima {129case networks.ModeUserV2:130sock, err = usernet.Sock(nw.Lima, usernet.QEMUSock)131if err != nil {132return nil, err133}134mac = limayaml.MACAddress(inst.Dir)135case networks.ModeShared, networks.ModeBridged:136socketVMNetInstalled, err := nwCfg.IsDaemonInstalled(networks.SocketVMNet)137if err != nil {138return nil, err139}140if !socketVMNetInstalled {141return nil, errors.New("socket_vmnet is not installed")142}143sock, err = networks.Sock(nw.Lima)144if err != nil {145return nil, err146}147mac = nw.MACAddress148default:149return nil, fmt.Errorf("invalid network spec %+v", nw)150}151} else if nw.Socket != "" {152sock = nw.Socket153mac = nw.MACAddress154} else {155return nil, fmt.Errorf("invalid network spec %+v", nw)156}157158device := fmt.Sprintf("virtio-net,type=unixstream,path=%s,mac=%s", sock, mac)159args = append(args, "--device", device)160}161162if len(args) == 0 {163return args, errors.New("no socket_vmnet networks defined")164}165166return args, nil167}168169func startUsernet(ctx context.Context, inst *limatype.Instance) (*usernet.Client, context.CancelFunc, error) {170if firstUsernetIndex := limayaml.FirstUsernetIndex(inst.Config); firstUsernetIndex != -1 {171return usernet.NewClientByName(inst.Config.Networks[firstUsernetIndex].Lima), nil, nil172}173// Start a in-process gvisor-tap-vsock174endpointSock, err := usernet.SockWithDirectory(inst.Dir, "", usernet.EndpointSock)175if err != nil {176return nil, nil, err177}178krunkitSock, err := usernet.SockWithDirectory(inst.Dir, "", usernet.FDSock)179if err != nil {180return nil, nil, err181}182os.RemoveAll(endpointSock)183os.RemoveAll(krunkitSock)184ctx, cancel := context.WithCancel(ctx)185err = usernet.StartGVisorNetstack(ctx, &usernet.GVisorNetstackOpts{186MTU: 1500,187Endpoint: endpointSock,188FdSocket: krunkitSock,189Async: true,190DefaultLeases: map[string]string{191networks.SlirpIPAddress: limayaml.MACAddress(inst.Dir),192},193Subnet: networks.SlirpNetwork,194})195if err != nil {196defer cancel()197return nil, nil, err198}199subnetIP, _, err := net.ParseCIDR(networks.SlirpNetwork)200return usernet.NewClient(endpointSock, subnetIP), cancel, err201}202203204