From f30235af07cc81067e4da2147a8d637d23e3204f Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 21 May 2025 17:59:46 +0530 Subject: [PATCH 01/49] driver(internal): use existing driver.Driver as plugin interface Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 457265aedd7..eddcc1fb2b2 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -71,6 +71,9 @@ type Driver interface { // GuestAgentConn returns the guest agent connection, or nil (if forwarded by ssh). GuestAgentConn(_ context.Context) (net.Conn, error) + + // Returns the driver name. + Name() string } type BaseDriver struct { @@ -152,3 +155,7 @@ func (d *BaseDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { // use the unix socket forwarded by host agent return nil, nil } + +func (d *BaseDriver) Name() string { + return "" +} From c9d0f99afe01de7ed3eb2d7f371423335380de3b Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 13:06:41 +0530 Subject: [PATCH 02/49] driver(internal): registry init Signed-off-by: Ansuman Sahoo --- pkg/registry/registry.go | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pkg/registry/registry.go diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go new file mode 100644 index 00000000000..93244bf101b --- /dev/null +++ b/pkg/registry/registry.go @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package registry + +import ( + "sync" + + "github.com/lima-vm/lima/pkg/driver" +) + +type Registry struct { + drivers map[string]driver.Driver + mu sync.RWMutex +} + +func NewRegistry() *Registry { + return &Registry{ + drivers: make(map[string]driver.Driver), + } +} + +func (r *Registry) Register(driver driver.Driver) { + r.mu.Lock() + defer r.mu.Unlock() + + name := driver.Name() + if _, exists := r.drivers[name]; exists { + return + } + + r.drivers[name] = driver +} + +func (r *Registry) Get(name string) (driver.Driver, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + + driver, exists := r.drivers[name] + return driver, exists +} + +var DefaultRegistry *Registry + +func Register(driver driver.Driver) { + if DefaultRegistry != nil { + DefaultRegistry.Register(driver) + } +} From fda3db4c765bfa96798798961826f788b8ff79ff Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 16:34:44 +0530 Subject: [PATCH 03/49] refactor(BaseDriver): remove driver.BaseDriver from Lima level Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 90 -------------------------------------- pkg/driverutil/instance.go | 3 +- pkg/hostagent/hostagent.go | 10 ++--- pkg/instance/create.go | 5 +-- pkg/instance/delete.go | 5 +-- pkg/instance/start.go | 4 +- pkg/snapshot/snapshot.go | 17 ++----- 7 files changed, 12 insertions(+), 122 deletions(-) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index eddcc1fb2b2..d064ba8498e 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -5,16 +5,10 @@ package driver import ( "context" - "errors" "net" - - "github.com/lima-vm/lima/pkg/store" ) // Driver interface is used by hostagent for managing vm. -// -// This interface is extended by BaseDriver which provides default implementation. -// All other driver definition must extend BaseDriver. type Driver interface { // Validate returns error if the current driver isn't support for given config Validate() error @@ -75,87 +69,3 @@ type Driver interface { // Returns the driver name. Name() string } - -type BaseDriver struct { - Instance *store.Instance - - SSHLocalPort int - VSockPort int - VirtioPort string -} - -var _ Driver = (*BaseDriver)(nil) - -func (d *BaseDriver) Validate() error { - return nil -} - -func (d *BaseDriver) Initialize(_ context.Context) error { - return nil -} - -func (d *BaseDriver) CreateDisk(_ context.Context) error { - return nil -} - -func (d *BaseDriver) Start(_ context.Context) (chan error, error) { - return nil, nil -} - -func (d *BaseDriver) CanRunGUI() bool { - return false -} - -func (d *BaseDriver) RunGUI() error { - return nil -} - -func (d *BaseDriver) Stop(_ context.Context) error { - return nil -} - -func (d *BaseDriver) Register(_ context.Context) error { - return nil -} - -func (d *BaseDriver) Unregister(_ context.Context) error { - return nil -} - -func (d *BaseDriver) ChangeDisplayPassword(_ context.Context, _ string) error { - return nil -} - -func (d *BaseDriver) GetDisplayConnection(_ context.Context) (string, error) { - return "", nil -} - -func (d *BaseDriver) CreateSnapshot(_ context.Context, _ string) error { - return errors.New("unimplemented") -} - -func (d *BaseDriver) ApplySnapshot(_ context.Context, _ string) error { - return errors.New("unimplemented") -} - -func (d *BaseDriver) DeleteSnapshot(_ context.Context, _ string) error { - return errors.New("unimplemented") -} - -func (d *BaseDriver) ListSnapshots(_ context.Context) (string, error) { - return "", errors.New("unimplemented") -} - -func (d *BaseDriver) ForwardGuestAgent() bool { - // if driver is not providing, use host agent - return d.VSockPort == 0 && d.VirtioPort == "" -} - -func (d *BaseDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { - // use the unix socket forwarded by host agent - return nil, nil -} - -func (d *BaseDriver) Name() string { - return "" -} diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index d7c443ff5d2..3dbe2590a51 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -7,11 +7,12 @@ import ( "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/qemu" + "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/vz" "github.com/lima-vm/lima/pkg/wsl2" ) -func CreateTargetDriverInstance(base *driver.BaseDriver) driver.Driver { +func CreateTargetDriverInstance(inst *store.Instance, SSHLocalPort int) driver.Driver { limaDriver := base.Instance.Config.VMType if *limaDriver == limayaml.VZ { return vz.New(base) diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index c0452c8ba72..1a6dd22f637 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -131,13 +131,9 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt } } - baseDriver := driver.BaseDriver{ - Instance: inst, - SSHLocalPort: sshLocalPort, - } - limaDriver := driverutil.CreateTargetDriverInstance(&baseDriver) - vSockPort := baseDriver.VSockPort - virtioPort := baseDriver.VirtioPort + limaDriver := driverutil.CreateTargetDriverInstance(inst, sshLocalPort) + var vSockPort int + var virtioPort string if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { return nil, err diff --git a/pkg/instance/create.go b/pkg/instance/create.go index b9088785976..7b69ccc3100 100644 --- a/pkg/instance/create.go +++ b/pkg/instance/create.go @@ -11,7 +11,6 @@ import ( "path/filepath" "github.com/lima-vm/lima/pkg/cidata" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driverutil" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/osutil" @@ -76,9 +75,7 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY return nil, err } - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) if err := limaDriver.Register(ctx); err != nil { return nil, err diff --git a/pkg/instance/delete.go b/pkg/instance/delete.go index c4078d48a11..ca9a8ae3c01 100644 --- a/pkg/instance/delete.go +++ b/pkg/instance/delete.go @@ -9,7 +9,6 @@ import ( "fmt" "os" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driverutil" "github.com/lima-vm/lima/pkg/store" ) @@ -37,9 +36,7 @@ func Delete(ctx context.Context, inst *store.Instance, force bool) error { } func unregister(ctx context.Context, inst *store.Instance) error { - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) return limaDriver.Unregister(ctx) } diff --git a/pkg/instance/start.go b/pkg/instance/start.go index acd3741e0bd..49671e0b7f7 100644 --- a/pkg/instance/start.go +++ b/pkg/instance/start.go @@ -90,9 +90,7 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { return nil, err } } - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) if err := limaDriver.Validate(); err != nil { return nil, err diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index 520a41d92a4..9c48fc0c50a 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -6,35 +6,26 @@ package snapshot import ( "context" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driverutil" "github.com/lima-vm/lima/pkg/store" ) func Del(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) return limaDriver.DeleteSnapshot(ctx, tag) } func Save(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) return limaDriver.CreateSnapshot(ctx, tag) } func Load(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) return limaDriver.ApplySnapshot(ctx, tag) } func List(ctx context.Context, inst *store.Instance) (string, error) { - limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ - Instance: inst, - }) + limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) return limaDriver.ListSnapshots(ctx) } From bf9d0cbd967a67efe557736542022b2d9a86c485 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 16:52:55 +0530 Subject: [PATCH 04/49] refactor(BaseDriver): remove driver.BaseDriver from driver(qemu) level Signed-off-by: Ansuman Sahoo --- pkg/networks/usernet/client.go | 13 ++++++------- pkg/qemu/qemu_driver.go | 27 ++++++++++++++++----------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/pkg/networks/usernet/client.go b/pkg/networks/usernet/client.go index 2296f103ed1..c55c1e8c2a3 100644 --- a/pkg/networks/usernet/client.go +++ b/pkg/networks/usernet/client.go @@ -16,11 +16,10 @@ import ( gvproxyclient "github.com/containers/gvisor-tap-vsock/pkg/client" "github.com/containers/gvisor-tap-vsock/pkg/types" - - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/httpclientutil" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/networks/usernet/dnshosts" + "github.com/lima-vm/lima/pkg/store" ) type Client struct { @@ -32,18 +31,18 @@ type Client struct { subnet net.IP } -func (c *Client) ConfigureDriver(ctx context.Context, driver *driver.BaseDriver) error { - macAddress := limayaml.MACAddress(driver.Instance.Dir) +func (c *Client) ConfigureDriver(ctx context.Context, inst *store.Instance, sshLocalPort int) error { + macAddress := limayaml.MACAddress(inst.Dir) ipAddress, err := c.ResolveIPAddress(ctx, macAddress) if err != nil { return err } - err = c.ResolveAndForwardSSH(ipAddress, driver.SSHLocalPort) + err = c.ResolveAndForwardSSH(ipAddress, sshLocalPort) if err != nil { return err } - hosts := driver.Instance.Config.HostResolver.Hosts - hosts[fmt.Sprintf("%s.internal", driver.Instance.Hostname)] = ipAddress + hosts := inst.Config.HostResolver.Hosts + hosts[fmt.Sprintf("%s.internal", inst.Hostname)] = ipAddress err = c.AddDNSHosts(hosts) return err } diff --git a/pkg/qemu/qemu_driver.go b/pkg/qemu/qemu_driver.go index e28b23429d5..cce1c0333a7 100644 --- a/pkg/qemu/qemu_driver.go +++ b/pkg/qemu/qemu_driver.go @@ -26,7 +26,6 @@ import ( "github.com/digitalocean/go-qemu/qmp/raw" "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/executil" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/networks/usernet" @@ -37,23 +36,29 @@ import ( ) type LimaQemuDriver struct { - *driver.BaseDriver + Instance *store.Instance + SSHLocalPort int + VSockPort int + VirtioPort string + qCmd *exec.Cmd qWaitCh chan error vhostCmds []*exec.Cmd } -func New(driver *driver.BaseDriver) *LimaQemuDriver { - driver.VSockPort = 0 - driver.VirtioPort = filenames.VirtioPort +func New(inst *store.Instance) *LimaQemuDriver { // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 // but on Windows default Unix socket forwarding is not available + var virtioPort string + virtioPort = filenames.VirtioPort if runtime.GOOS != "windows" { - driver.VirtioPort = "" + virtioPort = "" } return &LimaQemuDriver{ - BaseDriver: driver, + Instance: inst, + VSockPort: 0, + VirtioPort: virtioPort, } } @@ -212,7 +217,7 @@ func (l *LimaQemuDriver) Start(ctx context.Context) (chan error, error) { go func() { if usernetIndex := limayaml.FirstUsernetIndex(l.Instance.Config); usernetIndex != -1 { client := usernet.NewClientByName(l.Instance.Config.Networks[usernetIndex].Lima) - err := client.ConfigureDriver(ctx, l.BaseDriver) + err := client.ConfigureDriver(ctx, l.Instance, l.SSHLocalPort) if err != nil { l.qWaitCh <- err } @@ -260,11 +265,11 @@ func (l *LimaQemuDriver) checkBinarySignature() error { } // The codesign --xml option is only available on macOS Monterey and later if !macOSProductVersion.LessThan(*semver.New("12.0.0")) { - qExe, _, err := Exe(l.BaseDriver.Instance.Arch) + qExe, _, err := Exe(l.Instance.Arch) if err != nil { - return fmt.Errorf("failed to find the QEMU binary for the architecture %q: %w", l.BaseDriver.Instance.Arch, err) + return fmt.Errorf("failed to find the QEMU binary for the architecture %q: %w", l.Instance.Arch, err) } - if accel := Accel(l.BaseDriver.Instance.Arch); accel == "hvf" { + if accel := Accel(l.Instance.Arch); accel == "hvf" { entitlementutil.AskToSignIfNotSignedProperly(qExe) } } From 91814ea33a959ac3279248ba38c14a61753e08c9 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 17:13:22 +0530 Subject: [PATCH 05/49] refactor(BaseDriver): remove driver.BaseDriver from driver(vz) level Signed-off-by: Ansuman Sahoo --- pkg/vz/disk.go | 27 ++++---- pkg/vz/vm_darwin.go | 135 ++++++++++++++++++------------------- pkg/vz/vz_driver_darwin.go | 22 +++--- pkg/vz/vz_driver_others.go | 43 ------------ 4 files changed, 93 insertions(+), 134 deletions(-) delete mode 100644 pkg/vz/vz_driver_others.go diff --git a/pkg/vz/disk.go b/pkg/vz/disk.go index 06194faf5d2..509b5ba67ca 100644 --- a/pkg/vz/disk.go +++ b/pkg/vz/disk.go @@ -11,16 +11,15 @@ import ( "path/filepath" "github.com/docker/go-units" - - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/fileutils" "github.com/lima-vm/lima/pkg/imgutil/proxyimgutil" "github.com/lima-vm/lima/pkg/iso9660util" + "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" ) -func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error { - diffDisk := filepath.Join(driver.Instance.Dir, filenames.DiffDisk) +func EnsureDisk(ctx context.Context, inst *store.Instance) error { + diffDisk := filepath.Join(inst.Dir, filenames.DiffDisk) if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) { // disk is already ensured return err @@ -28,21 +27,21 @@ func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error { diskUtil := proxyimgutil.NewDiskUtil() - baseDisk := filepath.Join(driver.Instance.Dir, filenames.BaseDisk) - kernel := filepath.Join(driver.Instance.Dir, filenames.Kernel) - kernelCmdline := filepath.Join(driver.Instance.Dir, filenames.KernelCmdline) - initrd := filepath.Join(driver.Instance.Dir, filenames.Initrd) + baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk) + kernel := filepath.Join(inst.Dir, filenames.Kernel) + kernelCmdline := filepath.Join(inst.Dir, filenames.KernelCmdline) + initrd := filepath.Join(inst.Dir, filenames.Initrd) if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) { var ensuredBaseDisk bool - errs := make([]error, len(driver.Instance.Config.Images)) - for i, f := range driver.Instance.Config.Images { - if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *driver.Instance.Config.Arch); err != nil { + errs := make([]error, len(inst.Config.Images)) + for i, f := range inst.Config.Images { + if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *inst.Config.Arch); err != nil { errs[i] = err continue } if f.Kernel != nil { // ensure decompress kernel because vz expects it to be decompressed - if _, err := fileutils.DownloadFile(ctx, kernel, f.Kernel.File, true, "the kernel", *driver.Instance.Config.Arch); err != nil { + if _, err := fileutils.DownloadFile(ctx, kernel, f.Kernel.File, true, "the kernel", *inst.Config.Arch); err != nil { errs[i] = err continue } @@ -54,7 +53,7 @@ func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error { } } if f.Initrd != nil { - if _, err := fileutils.DownloadFile(ctx, initrd, *f.Initrd, false, "the initrd", *driver.Instance.Config.Arch); err != nil { + if _, err := fileutils.DownloadFile(ctx, initrd, *f.Initrd, false, "the initrd", *inst.Config.Arch); err != nil { errs[i] = err continue } @@ -66,7 +65,7 @@ func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error { return fileutils.Errors(errs) } } - diskSize, _ := units.RAMInBytes(*driver.Instance.Config.Disk) + diskSize, _ := units.RAMInBytes(*inst.Config.Disk) if diskSize == 0 { return nil } diff --git a/pkg/vz/vm_darwin.go b/pkg/vz/vm_darwin.go index 9ea33a8642b..147af63fddb 100644 --- a/pkg/vz/vm_darwin.go +++ b/pkg/vz/vm_darwin.go @@ -24,7 +24,6 @@ import ( "github.com/lima-vm/go-qcow2reader/image/raw" "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/imgutil/proxyimgutil" "github.com/lima-vm/lima/pkg/iso9660util" "github.com/lima-vm/lima/pkg/limayaml" @@ -51,13 +50,13 @@ type virtualMachineWrapper struct { // Hold all *os.File created via socketpair() so that they won't get garbage collected. f.FD() gets invalid if f gets garbage collected. var vmNetworkFiles = make([]*os.File, 1) -func startVM(ctx context.Context, driver *driver.BaseDriver) (*virtualMachineWrapper, chan error, error) { - usernetClient, err := startUsernet(ctx, driver) +func startVM(ctx context.Context, inst *store.Instance, sshLocalPort int) (*virtualMachineWrapper, chan error, error) { + usernetClient, err := startUsernet(ctx, inst) if err != nil { return nil, nil, err } - machine, err := createVM(driver) + machine, err := createVM(inst) if err != nil { return nil, nil, err } @@ -95,7 +94,7 @@ func startVM(ctx context.Context, driver *driver.BaseDriver) (*virtualMachineWra case newState := <-machine.StateChangedNotify(): switch newState { case vz.VirtualMachineStateRunning: - pidFile := filepath.Join(driver.Instance.Dir, filenames.PIDFile(*driver.Instance.Config.VMType)) + pidFile := filepath.Join(inst.Dir, filenames.PIDFile(*inst.Config.VMType)) if _, err := os.Stat(pidFile); !errors.Is(err, os.ErrNotExist) { logrus.Errorf("pidfile %q already exists", pidFile) errCh <- err @@ -107,7 +106,7 @@ func startVM(ctx context.Context, driver *driver.BaseDriver) (*virtualMachineWra filesToRemove[pidFile] = struct{}{} logrus.Info("[VZ] - vm state change: running") - err := usernetClient.ConfigureDriver(ctx, driver) + err := usernetClient.ConfigureDriver(ctx, inst, sshLocalPort) if err != nil { errCh <- err } @@ -116,7 +115,7 @@ func startVM(ctx context.Context, driver *driver.BaseDriver) (*virtualMachineWra wrapper.mu.Lock() wrapper.stopped = true wrapper.mu.Unlock() - _ = usernetClient.UnExposeSSH(driver.SSHLocalPort) + _ = usernetClient.UnExposeSSH(inst.SSHLocalPort) errCh <- errors.New("vz driver state stopped") default: logrus.Debugf("[VZ] - vm state change: %q", newState) @@ -128,17 +127,17 @@ func startVM(ctx context.Context, driver *driver.BaseDriver) (*virtualMachineWra return wrapper, errCh, err } -func startUsernet(ctx context.Context, driver *driver.BaseDriver) (*usernet.Client, error) { - if firstUsernetIndex := limayaml.FirstUsernetIndex(driver.Instance.Config); firstUsernetIndex != -1 { - nwName := driver.Instance.Config.Networks[firstUsernetIndex].Lima +func startUsernet(ctx context.Context, inst *store.Instance) (*usernet.Client, error) { + if firstUsernetIndex := limayaml.FirstUsernetIndex(inst.Config); firstUsernetIndex != -1 { + nwName := inst.Config.Networks[firstUsernetIndex].Lima return usernet.NewClientByName(nwName), nil } // Start a in-process gvisor-tap-vsock - endpointSock, err := usernet.SockWithDirectory(driver.Instance.Dir, "", usernet.EndpointSock) + endpointSock, err := usernet.SockWithDirectory(inst.Dir, "", usernet.EndpointSock) if err != nil { return nil, err } - vzSock, err := usernet.SockWithDirectory(driver.Instance.Dir, "", usernet.FDSock) + vzSock, err := usernet.SockWithDirectory(inst.Dir, "", usernet.FDSock) if err != nil { return nil, err } @@ -150,7 +149,7 @@ func startUsernet(ctx context.Context, driver *driver.BaseDriver) (*usernet.Clie FdSocket: vzSock, Async: true, DefaultLeases: map[string]string{ - networks.SlirpIPAddress: limayaml.MACAddress(driver.Instance.Dir), + networks.SlirpIPAddress: limayaml.MACAddress(inst.Dir), }, Subnet: networks.SlirpNetwork, }) @@ -161,41 +160,41 @@ func startUsernet(ctx context.Context, driver *driver.BaseDriver) (*usernet.Clie return usernet.NewClient(endpointSock, subnetIP), err } -func createVM(driver *driver.BaseDriver) (*vz.VirtualMachine, error) { - vmConfig, err := createInitialConfig(driver) +func createVM(inst *store.Instance) (*vz.VirtualMachine, error) { + vmConfig, err := createInitialConfig(inst) if err != nil { return nil, err } - if err = attachPlatformConfig(driver, vmConfig); err != nil { + if err = attachPlatformConfig(inst, vmConfig); err != nil { return nil, err } - if err = attachSerialPort(driver, vmConfig); err != nil { + if err = attachSerialPort(inst, vmConfig); err != nil { return nil, err } - if err = attachNetwork(driver, vmConfig); err != nil { + if err = attachNetwork(inst, vmConfig); err != nil { return nil, err } - if err = attachDisks(driver, vmConfig); err != nil { + if err = attachDisks(inst, vmConfig); err != nil { return nil, err } - if err = attachDisplay(driver, vmConfig); err != nil { + if err = attachDisplay(inst, vmConfig); err != nil { return nil, err } - if err = attachFolderMounts(driver, vmConfig); err != nil { + if err = attachFolderMounts(inst, vmConfig); err != nil { return nil, err } - if err = attachAudio(driver, vmConfig); err != nil { + if err = attachAudio(inst, vmConfig); err != nil { return nil, err } - if err = attachOtherDevices(driver, vmConfig); err != nil { + if err = attachOtherDevices(inst, vmConfig); err != nil { return nil, err } @@ -207,20 +206,20 @@ func createVM(driver *driver.BaseDriver) (*vz.VirtualMachine, error) { return vz.NewVirtualMachine(vmConfig) } -func createInitialConfig(driver *driver.BaseDriver) (*vz.VirtualMachineConfiguration, error) { - bootLoader, err := bootLoader(driver) +func createInitialConfig(inst *store.Instance) (*vz.VirtualMachineConfiguration, error) { + bootLoader, err := bootLoader(inst) if err != nil { return nil, err } - bytes, err := units.RAMInBytes(*driver.Instance.Config.Memory) + bytes, err := units.RAMInBytes(*inst.Config.Memory) if err != nil { return nil, err } vmConfig, err := vz.NewVirtualMachineConfiguration( bootLoader, - uint(*driver.Instance.Config.CPUs), + uint(*inst.Config.CPUs), uint64(bytes), ) if err != nil { @@ -229,8 +228,8 @@ func createInitialConfig(driver *driver.BaseDriver) (*vz.VirtualMachineConfigura return vmConfig, nil } -func attachPlatformConfig(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error { - machineIdentifier, err := getMachineIdentifier(driver) +func attachPlatformConfig(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { + machineIdentifier, err := getMachineIdentifier(inst) if err != nil { return err } @@ -241,7 +240,7 @@ func attachPlatformConfig(driver *driver.BaseDriver, vmConfig *vz.VirtualMachine } // nested virt - if *driver.Instance.Config.NestedVirtualization { + if *inst.Config.NestedVirtualization { macOSProductVersion, err := osutil.ProductVersion() if err != nil { return fmt.Errorf("failed to get macOS product version: %w", err) @@ -264,8 +263,8 @@ func attachPlatformConfig(driver *driver.BaseDriver, vmConfig *vz.VirtualMachine return nil } -func attachSerialPort(driver *driver.BaseDriver, config *vz.VirtualMachineConfiguration) error { - path := filepath.Join(driver.Instance.Dir, filenames.SerialVirtioLog) +func attachSerialPort(inst *store.Instance, config *vz.VirtualMachineConfiguration) error { + path := filepath.Join(inst.Dir, filenames.SerialVirtioLog) serialPortAttachment, err := vz.NewFileSerialPortAttachment(path, false) if err != nil { return err @@ -302,14 +301,14 @@ func newVirtioNetworkDeviceConfiguration(attachment vz.NetworkDeviceAttachment, return networkConfig, nil } -func attachNetwork(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error { +func attachNetwork(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { var configurations []*vz.VirtioNetworkDeviceConfiguration - // Configure default usernetwork with limayaml.MACAddress(driver.Instance.Dir) for eth0 interface - firstUsernetIndex := limayaml.FirstUsernetIndex(driver.Instance.Config) + // Configure default usernetwork with limayaml.MACAddress(inst.Dir) for eth0 interface + firstUsernetIndex := limayaml.FirstUsernetIndex(inst.Config) if firstUsernetIndex == -1 { // slirp network using gvisor netstack - vzSock, err := usernet.SockWithDirectory(driver.Instance.Dir, "", usernet.FDSock) + vzSock, err := usernet.SockWithDirectory(inst.Dir, "", usernet.FDSock) if err != nil { return err } @@ -317,13 +316,13 @@ func attachNetwork(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigu if err != nil { return err } - networkConfig, err := newVirtioFileNetworkDeviceConfiguration(networkConn, limayaml.MACAddress(driver.Instance.Dir)) + networkConfig, err := newVirtioFileNetworkDeviceConfiguration(networkConn, limayaml.MACAddress(inst.Dir)) if err != nil { return err } configurations = append(configurations, networkConfig) } else { - vzSock, err := usernet.Sock(driver.Instance.Config.Networks[firstUsernetIndex].Lima, usernet.FDSock) + vzSock, err := usernet.Sock(inst.Config.Networks[firstUsernetIndex].Lima, usernet.FDSock) if err != nil { return err } @@ -331,14 +330,14 @@ func attachNetwork(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigu if err != nil { return err } - networkConfig, err := newVirtioFileNetworkDeviceConfiguration(networkConn, limayaml.MACAddress(driver.Instance.Dir)) + networkConfig, err := newVirtioFileNetworkDeviceConfiguration(networkConn, limayaml.MACAddress(inst.Dir)) if err != nil { return err } configurations = append(configurations, networkConfig) } - for i, nw := range driver.Instance.Networks { + for i, nw := range inst.Networks { if nw.VZNAT != nil && *nw.VZNAT { attachment, err := vz.NewNATNetworkDeviceAttachment() if err != nil { @@ -434,10 +433,10 @@ func validateDiskFormat(diskPath string) error { return nil } -func attachDisks(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error { - baseDiskPath := filepath.Join(driver.Instance.Dir, filenames.BaseDisk) - diffDiskPath := filepath.Join(driver.Instance.Dir, filenames.DiffDisk) - ciDataPath := filepath.Join(driver.Instance.Dir, filenames.CIDataISO) +func attachDisks(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { + baseDiskPath := filepath.Join(inst.Dir, filenames.BaseDisk) + diffDiskPath := filepath.Join(inst.Dir, filenames.DiffDisk) + ciDataPath := filepath.Join(inst.Dir, filenames.CIDataISO) isBaseDiskCDROM, err := iso9660util.IsISO9660(baseDiskPath) if err != nil { return err @@ -473,7 +472,7 @@ func attachDisks(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigura diskUtil := proxyimgutil.NewDiskUtil() - for _, d := range driver.Instance.Config.AdditionalDisks { + for _, d := range inst.Config.AdditionalDisks { diskName := d.Name disk, err := store.InspectDisk(diskName) if err != nil { @@ -484,7 +483,7 @@ func attachDisks(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigura return fmt.Errorf("failed to run attach disk %q, in use by instance %q", diskName, disk.Instance) } logrus.Infof("Mounting disk %q on %q", diskName, disk.MountPoint) - err = disk.Lock(driver.Instance.Dir) + err = disk.Lock(inst.Dir) if err != nil { return fmt.Errorf("failed to run lock disk %q: %w", diskName, err) } @@ -523,8 +522,8 @@ func attachDisks(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigura return nil } -func attachDisplay(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error { - switch *driver.Instance.Config.Video.Display { +func attachDisplay(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { + switch *inst.Config.Video.Display { case "vz", "default": graphicsDeviceConfiguration, err := vz.NewVirtioGraphicsDeviceConfiguration() if err != nil { @@ -543,14 +542,14 @@ func attachDisplay(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigu case "none": return nil default: - return fmt.Errorf("unexpected video display %q", *driver.Instance.Config.Video.Display) + return fmt.Errorf("unexpected video display %q", *inst.Config.Video.Display) } } -func attachFolderMounts(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error { +func attachFolderMounts(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { var mounts []vz.DirectorySharingDeviceConfiguration - if *driver.Instance.Config.MountType == limayaml.VIRTIOFS { - for i, mount := range driver.Instance.Config.Mounts { + if *inst.Config.MountType == limayaml.VIRTIOFS { + for i, mount := range inst.Config.Mounts { if _, err := os.Stat(mount.Location); errors.Is(err, os.ErrNotExist) { err := os.MkdirAll(mount.Location, 0o750) if err != nil { @@ -577,7 +576,7 @@ func attachFolderMounts(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineCo } } - if *driver.Instance.Config.Rosetta.Enabled { + if *inst.Config.Rosetta.Enabled { logrus.Info("Setting up Rosetta share") directorySharingDeviceConfig, err := createRosettaDirectoryShareConfiguration() if err != nil { @@ -593,8 +592,8 @@ func attachFolderMounts(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineCo return nil } -func attachAudio(driver *driver.BaseDriver, config *vz.VirtualMachineConfiguration) error { - switch *driver.Instance.Config.Audio.Device { +func attachAudio(inst *store.Instance, config *vz.VirtualMachineConfiguration) error { + switch *inst.Config.Audio.Device { case "vz", "default": outputStream, err := vz.NewVirtioSoundDeviceHostOutputStreamConfiguration() if err != nil { @@ -612,11 +611,11 @@ func attachAudio(driver *driver.BaseDriver, config *vz.VirtualMachineConfigurati case "", "none": return nil default: - return fmt.Errorf("unexpected audio device %q", *driver.Instance.Config.Audio.Device) + return fmt.Errorf("unexpected audio device %q", *inst.Config.Audio.Device) } } -func attachOtherDevices(_ *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error { +func attachOtherDevices(_ *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { entropyConfig, err := vz.NewVirtioEntropyDeviceConfiguration() if err != nil { return err @@ -690,8 +689,8 @@ func attachOtherDevices(_ *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigu return nil } -func getMachineIdentifier(driver *driver.BaseDriver) (*vz.GenericMachineIdentifier, error) { - identifier := filepath.Join(driver.Instance.Dir, filenames.VzIdentifier) +func getMachineIdentifier(inst *store.Instance) (*vz.GenericMachineIdentifier, error) { + identifier := filepath.Join(inst.Dir, filenames.VzIdentifier) if _, err := os.Stat(identifier); os.IsNotExist(err) { machineIdentifier, err := vz.NewGenericMachineIdentifier() if err != nil { @@ -706,15 +705,15 @@ func getMachineIdentifier(driver *driver.BaseDriver) (*vz.GenericMachineIdentifi return vz.NewGenericMachineIdentifierWithDataPath(identifier) } -func bootLoader(driver *driver.BaseDriver) (vz.BootLoader, error) { - linuxBootLoader, err := linuxBootLoader(driver) +func bootLoader(inst *store.Instance) (vz.BootLoader, error) { + linuxBootLoader, err := linuxBootLoader(inst) if linuxBootLoader != nil { return linuxBootLoader, nil } else if !errors.Is(err, os.ErrNotExist) { return nil, err } - efiVariableStore, err := getEFI(driver) + efiVariableStore, err := getEFI(inst) if err != nil { return nil, err } @@ -722,10 +721,10 @@ func bootLoader(driver *driver.BaseDriver) (vz.BootLoader, error) { return vz.NewEFIBootLoader(vz.WithEFIVariableStore(efiVariableStore)) } -func linuxBootLoader(driver *driver.BaseDriver) (*vz.LinuxBootLoader, error) { - kernel := filepath.Join(driver.Instance.Dir, filenames.Kernel) - kernelCmdline := filepath.Join(driver.Instance.Dir, filenames.KernelCmdline) - initrd := filepath.Join(driver.Instance.Dir, filenames.Initrd) +func linuxBootLoader(inst *store.Instance) (*vz.LinuxBootLoader, error) { + kernel := filepath.Join(inst.Dir, filenames.Kernel) + kernelCmdline := filepath.Join(inst.Dir, filenames.KernelCmdline) + initrd := filepath.Join(inst.Dir, filenames.Initrd) if _, err := os.Stat(kernel); err != nil { if errors.Is(err, os.ErrNotExist) { logrus.Debugf("Kernel file %q not found", kernel) @@ -747,8 +746,8 @@ func linuxBootLoader(driver *driver.BaseDriver) (*vz.LinuxBootLoader, error) { return vz.NewLinuxBootLoader(kernel, opt...) } -func getEFI(driver *driver.BaseDriver) (*vz.EFIVariableStore, error) { - efi := filepath.Join(driver.Instance.Dir, filenames.VzEfi) +func getEFI(inst *store.Instance) (*vz.EFIVariableStore, error) { + efi := filepath.Join(inst.Dir, filenames.VzEfi) if _, err := os.Stat(efi); os.IsNotExist(err) { return vz.NewEFIVariableStore(efi, vz.WithCreatingEFIVariableStore()) } diff --git a/pkg/vz/vz_driver_darwin.go b/pkg/vz/vz_driver_darwin.go index ee1b34b910f..d218f205e57 100644 --- a/pkg/vz/vz_driver_darwin.go +++ b/pkg/vz/vz_driver_darwin.go @@ -18,10 +18,10 @@ import ( "github.com/coreos/go-semver/semver" "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/reflectutil" + "github.com/lima-vm/lima/pkg/store" ) var knownYamlProperties = []string{ @@ -68,16 +68,20 @@ var knownYamlProperties = []string{ const Enabled = true type LimaVzDriver struct { - *driver.BaseDriver + Instance *store.Instance + + SSHLocalPort int + VSockPort int + VirtioPort string machine *virtualMachineWrapper } -func New(driver *driver.BaseDriver) *LimaVzDriver { - driver.VSockPort = 2222 - driver.VirtioPort = "" +func New(inst *store.Instance) *LimaVzDriver { return &LimaVzDriver{ - BaseDriver: driver, + Instance: inst, + VSockPort: 2222, + VirtioPort: "", } } @@ -167,17 +171,17 @@ func (l *LimaVzDriver) Validate() error { } func (l *LimaVzDriver) Initialize(_ context.Context) error { - _, err := getMachineIdentifier(l.BaseDriver) + _, err := getMachineIdentifier(l.Instance) return err } func (l *LimaVzDriver) CreateDisk(ctx context.Context) error { - return EnsureDisk(ctx, l.BaseDriver) + return EnsureDisk(ctx, l.Instance) } func (l *LimaVzDriver) Start(ctx context.Context) (chan error, error) { logrus.Infof("Starting VZ (hint: to watch the boot progress, see %q)", filepath.Join(l.Instance.Dir, "serial*.log")) - vm, errCh, err := startVM(ctx, l.BaseDriver) + vm, errCh, err := startVM(ctx, l.Instance, l.SSHLocalPort) if err != nil { if errors.Is(err, vz.ErrUnsupportedOSVersion) { return nil, fmt.Errorf("vz driver requires macOS 13 or higher to run: %w", err) diff --git a/pkg/vz/vz_driver_others.go b/pkg/vz/vz_driver_others.go deleted file mode 100644 index 66265628a49..00000000000 --- a/pkg/vz/vz_driver_others.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build !darwin || no_vz - -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package vz - -import ( - "context" - "errors" - - "github.com/lima-vm/lima/pkg/driver" -) - -var ErrUnsupported = errors.New("vm driver 'vz' needs macOS 13 or later (Hint: try recompiling Lima if you are seeing this error on macOS 13)") - -const Enabled = false - -type LimaVzDriver struct { - *driver.BaseDriver -} - -func New(driver *driver.BaseDriver) *LimaVzDriver { - return &LimaVzDriver{ - BaseDriver: driver, - } -} - -func (l *LimaVzDriver) Validate() error { - return ErrUnsupported -} - -func (l *LimaVzDriver) CreateDisk(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) Start(_ context.Context) (chan error, error) { - return nil, ErrUnsupported -} - -func (l *LimaVzDriver) Stop(_ context.Context) error { - return ErrUnsupported -} From c1a08a1fb7db886508248fa7321ac37c25361e86 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 17:24:05 +0530 Subject: [PATCH 06/49] refactor(BaseDriver): remove driver.BaseDriver from driver(wsl2) level Signed-off-by: Ansuman Sahoo --- pkg/wsl2/fs.go | 12 +++++----- pkg/wsl2/wsl_driver_others.go | 43 ---------------------------------- pkg/wsl2/wsl_driver_windows.go | 24 +++++++++++-------- 3 files changed, 20 insertions(+), 59 deletions(-) delete mode 100644 pkg/wsl2/wsl_driver_others.go diff --git a/pkg/wsl2/fs.go b/pkg/wsl2/fs.go index 8a3060ac924..53823a7fb06 100644 --- a/pkg/wsl2/fs.go +++ b/pkg/wsl2/fs.go @@ -11,19 +11,19 @@ import ( "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/fileutils" + "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" ) // EnsureFs downloads the root fs. -func EnsureFs(ctx context.Context, driver *driver.BaseDriver) error { - baseDisk := filepath.Join(driver.Instance.Dir, filenames.BaseDisk) +func EnsureFs(ctx context.Context, inst *store.Instance) error { + baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk) if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) { var ensuredBaseDisk bool - errs := make([]error, len(driver.Instance.Config.Images)) - for i, f := range driver.Instance.Config.Images { - if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *driver.Instance.Config.Arch); err != nil { + errs := make([]error, len(inst.Config.Images)) + for i, f := range inst.Config.Images { + if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *inst.Config.Arch); err != nil { errs[i] = err continue } diff --git a/pkg/wsl2/wsl_driver_others.go b/pkg/wsl2/wsl_driver_others.go deleted file mode 100644 index 4ad86d02768..00000000000 --- a/pkg/wsl2/wsl_driver_others.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build !windows || no_wsl - -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package wsl2 - -import ( - "context" - "errors" - - "github.com/lima-vm/lima/pkg/driver" -) - -var ErrUnsupported = errors.New("vm driver 'wsl2' requires Windows 10 build 19041 or later (Hint: try recompiling Lima if you are seeing this error on Windows 10+)") - -const Enabled = false - -type LimaWslDriver struct { - *driver.BaseDriver -} - -func New(driver *driver.BaseDriver) *LimaWslDriver { - return &LimaWslDriver{ - BaseDriver: driver, - } -} - -func (l *LimaWslDriver) Validate() error { - return ErrUnsupported -} - -func (l *LimaWslDriver) CreateDisk(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) Start(_ context.Context) (chan error, error) { - return nil, ErrUnsupported -} - -func (l *LimaWslDriver) Stop(_ context.Context) error { - return ErrUnsupported -} diff --git a/pkg/wsl2/wsl_driver_windows.go b/pkg/wsl2/wsl_driver_windows.go index 4ad7d472452..15d83b71e9f 100644 --- a/pkg/wsl2/wsl_driver_windows.go +++ b/pkg/wsl2/wsl_driver_windows.go @@ -13,7 +13,6 @@ import ( "github.com/Microsoft/go-winio/pkg/guid" "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/freeport" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/reflectutil" @@ -47,18 +46,23 @@ var knownYamlProperties = []string{ const Enabled = true type LimaWslDriver struct { - *driver.BaseDriver + Instance *store.Instance + + SSHLocalPort int + VSockPort int + VirtioPort string } -func New(driver *driver.BaseDriver) *LimaWslDriver { +func New(inst *store.Instance) *LimaWslDriver { port, err := freeport.VSock() if err != nil { logrus.WithError(err).Error("failed to get free VSock port") } - driver.VSockPort = port - driver.VirtioPort = "" + return &LimaWslDriver{ - BaseDriver: driver, + Instance: inst, + VSockPort: port, + VirtioPort: "", } } @@ -123,10 +127,10 @@ func (l *LimaWslDriver) Start(ctx context.Context) (chan error, error) { distroName := "lima-" + l.Instance.Name if status == store.StatusUninitialized { - if err := EnsureFs(ctx, l.BaseDriver); err != nil { + if err := EnsureFs(ctx, l.Instance); err != nil { return nil, err } - if err := initVM(ctx, l.BaseDriver.Instance.Dir, distroName); err != nil { + if err := initVM(ctx, l.Instance.Dir, distroName); err != nil { return nil, err } } @@ -139,8 +143,8 @@ func (l *LimaWslDriver) Start(ctx context.Context) (chan error, error) { if err := provisionVM( ctx, - l.BaseDriver.Instance.Dir, - l.BaseDriver.Instance.Name, + l.Instance.Dir, + l.Instance.Name, distroName, errCh, ); err != nil { From 57a208092dbf0dc0363275fb43627f8634f4c737 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 18:08:41 +0530 Subject: [PATCH 07/49] refactor(BaseDriver): make drivers implement the driver.Driver interface Signed-off-by: Ansuman Sahoo --- pkg/qemu/qemu_driver.go | 38 +++++++++++++++++++++--- pkg/vz/vz_driver_darwin.go | 50 ++++++++++++++++++++++++++++--- pkg/wsl2/wsl_driver_windows.go | 54 +++++++++++++++++++++++++++++++--- 3 files changed, 130 insertions(+), 12 deletions(-) diff --git a/pkg/qemu/qemu_driver.go b/pkg/qemu/qemu_driver.go index cce1c0333a7..0608a6245ba 100644 --- a/pkg/qemu/qemu_driver.go +++ b/pkg/qemu/qemu_driver.go @@ -47,7 +47,7 @@ type LimaQemuDriver struct { vhostCmds []*exec.Cmd } -func New(inst *store.Instance) *LimaQemuDriver { +func New(inst *store.Instance, sshLocalPort int) *LimaQemuDriver { // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 // but on Windows default Unix socket forwarding is not available var virtioPort string @@ -56,9 +56,10 @@ func New(inst *store.Instance) *LimaQemuDriver { virtioPort = "" } return &LimaQemuDriver{ - Instance: inst, - VSockPort: 0, - VirtioPort: virtioPort, + Instance: inst, + VSockPort: 0, + VirtioPort: virtioPort, + SSHLocalPort: sshLocalPort, } } @@ -503,3 +504,32 @@ func (a *qArgTemplateApplier) applyTemplate(qArg string) (string, error) { } return b.String(), nil } + +func (l *LimaQemuDriver) Name() string { + return "qemu" +} + +func (l *LimaQemuDriver) Initialize(_ context.Context) error { + return nil +} + +func (l *LimaQemuDriver) CanRunGUI() bool { + return false +} + +func (l *LimaQemuDriver) RunGUI() error { + return nil +} + +func (l *LimaQemuDriver) Register(_ context.Context) error { + return nil +} + +func (l *LimaQemuDriver) Unregister(_ context.Context) error { + return nil +} + +func (l *LimaQemuDriver) ForwardGuestAgent() bool { + // if driver is not providing, use host agent + return l.VSockPort == 0 && l.VirtioPort == "" +} diff --git a/pkg/vz/vz_driver_darwin.go b/pkg/vz/vz_driver_darwin.go index d218f205e57..dbba1dc1a01 100644 --- a/pkg/vz/vz_driver_darwin.go +++ b/pkg/vz/vz_driver_darwin.go @@ -77,11 +77,12 @@ type LimaVzDriver struct { machine *virtualMachineWrapper } -func New(inst *store.Instance) *LimaVzDriver { +func New(inst *store.Instance, sshLocalPort int) *LimaVzDriver { return &LimaVzDriver{ - Instance: inst, - VSockPort: 2222, - VirtioPort: "", + Instance: inst, + VSockPort: 2222, + VirtioPort: "", + SSHLocalPort: sshLocalPort, } } @@ -248,3 +249,44 @@ func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { } return nil, errors.New("unable to connect to guest agent via vsock port 2222") } + +func (l *LimaVzDriver) Name() string { + return "vz" +} + +func (l *LimaVzDriver) Register(_ context.Context) error { + return nil +} + +func (l *LimaVzDriver) Unregister(_ context.Context) error { + return nil +} + +func (l *LimaVzDriver) ChangeDisplayPassword(_ context.Context, _ string) error { + return nil +} + +func (l *LimaVzDriver) GetDisplayConnection(_ context.Context) (string, error) { + return "", nil +} + +func (l *LimaVzDriver) CreateSnapshot(_ context.Context, _ string) error { + return errors.New("unimplemented") +} + +func (l *LimaVzDriver) ApplySnapshot(_ context.Context, _ string) error { + return errors.New("unimplemented") +} + +func (l *LimaVzDriver) DeleteSnapshot(_ context.Context, _ string) error { + return errors.New("unimplemented") +} + +func (l *LimaVzDriver) ListSnapshots(_ context.Context) (string, error) { + return "", errors.New("unimplemented") +} + +func (l *LimaVzDriver) ForwardGuestAgent() bool { + // If driver is not providing, use host agent + return l.VSockPort == 0 && l.VirtioPort == "" +} diff --git a/pkg/wsl2/wsl_driver_windows.go b/pkg/wsl2/wsl_driver_windows.go index 15d83b71e9f..7ccbc5a2b60 100644 --- a/pkg/wsl2/wsl_driver_windows.go +++ b/pkg/wsl2/wsl_driver_windows.go @@ -53,16 +53,17 @@ type LimaWslDriver struct { VirtioPort string } -func New(inst *store.Instance) *LimaWslDriver { +func New(inst *store.Instance, sshLocalPort int) *LimaWslDriver { port, err := freeport.VSock() if err != nil { logrus.WithError(err).Error("failed to get free VSock port") } return &LimaWslDriver{ - Instance: inst, - VSockPort: port, - VirtioPort: "", + Instance: inst, + VSockPort: port, + VirtioPort: "", + SSHLocalPort: sshLocalPort, } } @@ -205,3 +206,48 @@ func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { } return winio.Dial(ctx, sockAddr) } + +func (l *LimaWslDriver) Name() string { + return "wsl2" +} + +func (l *LimaWslDriver) Initialize(_ context.Context) error { + return nil +} + +func (l *LimaWslDriver) CreateDisk(_ context.Context) error { + return nil +} + +func (l *LimaWslDriver) Register(_ context.Context) error { + return nil +} + +func (l *LimaWslDriver) ChangeDisplayPassword(_ context.Context, _ string) error { + return nil +} + +func (l *LimaWslDriver) GetDisplayConnection(_ context.Context) (string, error) { + return "", nil +} + +func (l *LimaWslDriver) CreateSnapshot(_ context.Context, _ string) error { + return fmt.Errorf("unimplemented") +} + +func (l *LimaWslDriver) ApplySnapshot(_ context.Context, _ string) error { + return fmt.Errorf("unimplemented") +} + +func (l *LimaWslDriver) DeleteSnapshot(_ context.Context, _ string) error { + return fmt.Errorf("unimplemented") +} + +func (l *LimaWslDriver) ListSnapshots(_ context.Context) (string, error) { + return "", fmt.Errorf("unimplemented") +} + +func (l *LimaWslDriver) ForwardGuestAgent() bool { + // If driver is not providing, use host agent + return l.VSockPort == 0 && l.VirtioPort == "" +} From 82955c15d8ef3e11e32918edd8369ff93064a300 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 20:32:04 +0530 Subject: [PATCH 08/49] driver(internal): divide the driver.Driver interface and define some plugin related functions Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 72 +++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index d064ba8498e..5f7fe0c828a 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -6,10 +6,12 @@ package driver import ( "context" "net" + + "github.com/lima-vm/lima/pkg/store" ) -// Driver interface is used by hostagent for managing vm. -type Driver interface { +// Basic lifecycle operations +type Lifecycle interface { // Validate returns error if the current driver isn't support for given config Validate() error @@ -29,6 +31,13 @@ type Driver interface { // The second argument may contain error occurred while starting driver Start(_ context.Context) (chan error, error) + // Stop will terminate the running vm instance. + // It returns error if there are any errors during Stop + Stop(_ context.Context) error +} + +// GUI-related operations +type GUI interface { // CanRunGUI returns bool to indicate if the hostagent need to run GUI synchronously CanRunGUI() bool @@ -36,36 +45,51 @@ type Driver interface { // It returns error if there are any failures RunGUI() error - // Stop will terminate the running vm instance. - // It returns error if there are any errors during Stop - Stop(_ context.Context) error - - // Register will add an instance to a registry. - // It returns error if there are any errors during Register - Register(_ context.Context) error - - // Unregister will perform any cleanup related to the vm instance. - // It returns error if there are any errors during Unregister - Unregister(_ context.Context) error - - ChangeDisplayPassword(_ context.Context, password string) error - - GetDisplayConnection(_ context.Context) (string, error) - - CreateSnapshot(_ context.Context, tag string) error - - ApplySnapshot(_ context.Context, tag string) error + ChangeDisplayPassword(ctx context.Context, password string) error + GetDisplayConnection(ctx context.Context) (string, error) +} - DeleteSnapshot(_ context.Context, tag string) error +// Snapshot operations +type Snapshot interface { + CreateSnapshot(ctx context.Context, tag string) error + ApplySnapshot(ctx context.Context, tag string) error + DeleteSnapshot(ctx context.Context, tag string) error + ListSnapshots(ctx context.Context) (string, error) +} - ListSnapshots(_ context.Context) (string, error) +// Registration operations +type Registration interface { + Register(ctx context.Context) error + Unregister(ctx context.Context) error +} +// Guest agent operations +type GuestAgent interface { // ForwardGuestAgent returns if the guest agent sock needs forwarding by host agent. ForwardGuestAgent() bool // GuestAgentConn returns the guest agent connection, or nil (if forwarded by ssh). GuestAgentConn(_ context.Context) (net.Conn, error) +} - // Returns the driver name. +type Plugin interface { + // Name returns the name of the driver Name() string + + // Enabled returns whether this driver is available on the current platform. + // Also checks whether this driver can handle the given config + Enabled() bool + + // NewDriver returns a new driver instance. Only to be used to embed internal drivers + NewDriver(ctx context.Context, inst *store.Instance, sshLocalPort int) Driver +} + +// Driver interface is used by hostagent for managing vm. +type Driver interface { + Lifecycle + GUI + Snapshot + Registration + GuestAgent + Plugin } From b1f6a2a46c1a978ba89111ba551d60b16cbe742d Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 23 May 2025 20:59:54 +0530 Subject: [PATCH 09/49] driver(internal): change lima to support internal drivers Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 6 +----- pkg/driverutil/driverutil.go | 25 +++++++++++++------------ pkg/driverutil/instance.go | 25 ++++++++++++++----------- pkg/hostagent/hostagent.go | 6 +++++- pkg/instance/create.go | 5 ++++- pkg/instance/delete.go | 5 ++++- pkg/instance/start.go | 7 +++++-- pkg/limainfo/limainfo.go | 2 +- pkg/registry/registry.go | 21 +++++++++++++++++++-- pkg/snapshot/snapshot.go | 23 +++++++++++++++++++---- 10 files changed, 85 insertions(+), 40 deletions(-) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 5f7fe0c828a..35ca0e11596 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -76,12 +76,8 @@ type Plugin interface { // Name returns the name of the driver Name() string - // Enabled returns whether this driver is available on the current platform. - // Also checks whether this driver can handle the given config - Enabled() bool - // NewDriver returns a new driver instance. Only to be used to embed internal drivers - NewDriver(ctx context.Context, inst *store.Instance, sshLocalPort int) Driver + NewDriver(inst *store.Instance, sshLocalPort int) Driver } // Driver interface is used by hostagent for managing vm. diff --git a/pkg/driverutil/driverutil.go b/pkg/driverutil/driverutil.go index eb27833e7ad..a7c6f2f2570 100644 --- a/pkg/driverutil/driverutil.go +++ b/pkg/driverutil/driverutil.go @@ -4,19 +4,20 @@ package driverutil import ( - "github.com/lima-vm/lima/pkg/limayaml" - "github.com/lima-vm/lima/pkg/vz" - "github.com/lima-vm/lima/pkg/wsl2" + "github.com/lima-vm/lima/pkg/registry" ) -// Drivers returns the available drivers. -func Drivers() []string { - drivers := []string{limayaml.QEMU} - if vz.Enabled { - drivers = append(drivers, limayaml.VZ) - } - if wsl2.Enabled { - drivers = append(drivers, limayaml.WSL2) +// AvailableDrivers returns a list of available driver names +func AvailableDrivers() []string { + var available []string + + for _, name := range registry.DefaultRegistry.List() { + driver, _ := registry.DefaultRegistry.Get(name) + if err := driver.Validate(); err == nil { + return available + } + available = append(available, name) } - return drivers + + return available } diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index 3dbe2590a51..6bbbe88009d 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -4,21 +4,24 @@ package driverutil import ( + "fmt" + "github.com/lima-vm/lima/pkg/driver" - "github.com/lima-vm/lima/pkg/limayaml" - "github.com/lima-vm/lima/pkg/qemu" + "github.com/lima-vm/lima/pkg/registry" "github.com/lima-vm/lima/pkg/store" - "github.com/lima-vm/lima/pkg/vz" - "github.com/lima-vm/lima/pkg/wsl2" ) -func CreateTargetDriverInstance(inst *store.Instance, SSHLocalPort int) driver.Driver { - limaDriver := base.Instance.Config.VMType - if *limaDriver == limayaml.VZ { - return vz.New(base) +// CreateTargetDriverInstance creates the appropriate driver for an instance +func CreateTargetDriverInstance(inst *store.Instance, sshLocalPort int) (driver.Driver, error) { + limaDriver := inst.Config.VMType + driver, exists := registry.DefaultRegistry.Get(string(*limaDriver)) + if !exists { + return nil, fmt.Errorf("unknown or unsupported VM type: %s", *limaDriver) } - if *limaDriver == limayaml.WSL2 { - return wsl2.New(base) + + if err := driver.Validate(); err != nil { + return nil, fmt.Errorf("driver validation failed: %w", err) } - return qemu.New(base) + + return driver.NewDriver(inst, sshLocalPort), nil } diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 1a6dd22f637..ceaec3f808d 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -131,7 +131,11 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt } } - limaDriver := driverutil.CreateTargetDriverInstance(inst, sshLocalPort) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, sshLocalPort) + if err != nil { + return nil, fmt.Errorf("failed to create driver instance: %w", err) + } + var vSockPort int var virtioPort string diff --git a/pkg/instance/create.go b/pkg/instance/create.go index 7b69ccc3100..6af427110a8 100644 --- a/pkg/instance/create.go +++ b/pkg/instance/create.go @@ -75,7 +75,10 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY return nil, err } - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return nil, fmt.Errorf("failed to create driver instance: %w", err) + } if err := limaDriver.Register(ctx); err != nil { return nil, err diff --git a/pkg/instance/delete.go b/pkg/instance/delete.go index ca9a8ae3c01..9ad4d10b878 100644 --- a/pkg/instance/delete.go +++ b/pkg/instance/delete.go @@ -36,7 +36,10 @@ func Delete(ctx context.Context, inst *store.Instance, force bool) error { } func unregister(ctx context.Context, inst *store.Instance) error { - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return fmt.Errorf("failed to create driver instance: %w", err) + } return limaDriver.Unregister(ctx) } diff --git a/pkg/instance/start.go b/pkg/instance/start.go index 49671e0b7f7..44680124f7e 100644 --- a/pkg/instance/start.go +++ b/pkg/instance/start.go @@ -90,7 +90,10 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { return nil, err } } - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return nil, fmt.Errorf("failed to create driver instance: %w", err) + } if err := limaDriver.Validate(); err != nil { return nil, err @@ -102,7 +105,7 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { // Check if the instance has been created (the base disk already exists) baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk) - _, err := os.Stat(baseDisk) + _, err = os.Stat(baseDisk) created := err == nil if err := limaDriver.CreateDisk(ctx); err != nil { diff --git a/pkg/limainfo/limainfo.go b/pkg/limainfo/limainfo.go index 5311cca2805..5eb37c3204b 100644 --- a/pkg/limainfo/limainfo.go +++ b/pkg/limainfo/limainfo.go @@ -45,7 +45,7 @@ func New() (*LimaInfo, error) { info := &LimaInfo{ Version: version.Version, DefaultTemplate: y, - VMTypes: driverutil.Drivers(), + VMTypes: driverutil.AvailableDrivers(), GuestAgents: make(map[limayaml.Arch]GuestAgent), } info.Templates, err = templatestore.Templates() diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 93244bf101b..b84ba121042 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -7,6 +7,7 @@ import ( "sync" "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/store" ) type Registry struct { @@ -20,7 +21,7 @@ func NewRegistry() *Registry { } } -func (r *Registry) Register(driver driver.Driver) { +func (r *Registry) Register(driver driver.Driver, inst *store.Instance, sshLocalPort int) { r.mu.Lock() defer r.mu.Unlock() @@ -32,6 +33,17 @@ func (r *Registry) Register(driver driver.Driver) { r.drivers[name] = driver } +func (r *Registry) List() []string { + r.mu.RLock() + defer r.mu.RUnlock() + + var names []string + for name := range r.drivers { + names = append(names, name) + } + return names +} + func (r *Registry) Get(name string) (driver.Driver, bool) { r.mu.RLock() defer r.mu.RUnlock() @@ -44,6 +56,11 @@ var DefaultRegistry *Registry func Register(driver driver.Driver) { if DefaultRegistry != nil { - DefaultRegistry.Register(driver) + name := driver.Name() + if _, exists := DefaultRegistry.drivers[name]; exists { + return + } + + DefaultRegistry.drivers[name] = driver } } diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index 9c48fc0c50a..b41579e273a 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -5,27 +5,42 @@ package snapshot import ( "context" + "fmt" "github.com/lima-vm/lima/pkg/driverutil" "github.com/lima-vm/lima/pkg/store" ) func Del(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return fmt.Errorf("failed to create driver instance: %w", err) + } + return limaDriver.DeleteSnapshot(ctx, tag) } func Save(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return fmt.Errorf("failed to create driver instance: %w", err) + } return limaDriver.CreateSnapshot(ctx, tag) } func Load(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return fmt.Errorf("failed to create driver instance: %w", err) + } return limaDriver.ApplySnapshot(ctx, tag) } func List(ctx context.Context, inst *store.Instance) (string, error) { - limaDriver := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + if err != nil { + return "", fmt.Errorf("failed to create driver instance: %w", err) + } + return limaDriver.ListSnapshots(ctx) } From 96e6a2a67493f1014e8b5ca20a98c68eb49fe45f Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Sat, 24 May 2025 17:59:34 +0530 Subject: [PATCH 10/49] driver(internal): add blank imports and make changes to Lima for internal drivers Signed-off-by: Ansuman Sahoo --- cmd/limactl/main.go | 1 + pkg/builtins/drivers.go | 10 ++++++++++ pkg/driver/driver.go | 5 ++++- pkg/driverutil/instance.go | 4 +++- pkg/hostagent/hostagent.go | 4 ++-- pkg/registry/registry.go | 17 ++++------------- 6 files changed, 24 insertions(+), 17 deletions(-) create mode 100644 pkg/builtins/drivers.go diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index a006f0bb33f..dcdb7e2f1b5 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -15,6 +15,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/cobra" + _ "github.com/lima-vm/lima/pkg/builtins" // register built-in drivers "github.com/lima-vm/lima/pkg/debugutil" "github.com/lima-vm/lima/pkg/fsutil" "github.com/lima-vm/lima/pkg/osutil" diff --git a/pkg/builtins/drivers.go b/pkg/builtins/drivers.go new file mode 100644 index 00000000000..5ae3f563eaa --- /dev/null +++ b/pkg/builtins/drivers.go @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package builtins + +import ( + _ "github.com/lima-vm/lima/pkg/qemu" + _ "github.com/lima-vm/lima/pkg/vz" + _ "github.com/lima-vm/lima/pkg/wsl2" +) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 35ca0e11596..e9a5d9e1028 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -77,7 +77,7 @@ type Plugin interface { Name() string // NewDriver returns a new driver instance. Only to be used to embed internal drivers - NewDriver(inst *store.Instance, sshLocalPort int) Driver + SetConfig(inst *store.Instance, sshLocalPort int) } // Driver interface is used by hostagent for managing vm. @@ -88,4 +88,7 @@ type Driver interface { Registration GuestAgent Plugin + + GetVSockPort() int + GetVirtioPort() string } diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index 6bbbe88009d..591cb66ea02 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -19,9 +19,11 @@ func CreateTargetDriverInstance(inst *store.Instance, sshLocalPort int) (driver. return nil, fmt.Errorf("unknown or unsupported VM type: %s", *limaDriver) } + driver.SetConfig(inst, sshLocalPort) + if err := driver.Validate(); err != nil { return nil, fmt.Errorf("driver validation failed: %w", err) } - return driver.NewDriver(inst, sshLocalPort), nil + return driver, nil } diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index ceaec3f808d..1ac97b18986 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -136,8 +136,8 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt return nil, fmt.Errorf("failed to create driver instance: %w", err) } - var vSockPort int - var virtioPort string + vSockPort := limaDriver.GetVSockPort() + virtioPort := limaDriver.GetVirtioPort() if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { return nil, err diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index b84ba121042..50101b67ce0 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -7,7 +7,6 @@ import ( "sync" "github.com/lima-vm/lima/pkg/driver" - "github.com/lima-vm/lima/pkg/store" ) type Registry struct { @@ -21,18 +20,6 @@ func NewRegistry() *Registry { } } -func (r *Registry) Register(driver driver.Driver, inst *store.Instance, sshLocalPort int) { - r.mu.Lock() - defer r.mu.Unlock() - - name := driver.Name() - if _, exists := r.drivers[name]; exists { - return - } - - r.drivers[name] = driver -} - func (r *Registry) List() []string { r.mu.RLock() defer r.mu.RUnlock() @@ -54,6 +41,10 @@ func (r *Registry) Get(name string) (driver.Driver, bool) { var DefaultRegistry *Registry +func init() { + DefaultRegistry = NewRegistry() +} + func Register(driver driver.Driver) { if DefaultRegistry != nil { name := driver.Name() From f02c49b8d7640c1e942b2d6e8401c3f8c9a433e3 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Sat, 24 May 2025 18:01:49 +0530 Subject: [PATCH 11/49] driver(internal): add register files and make drivers compatible for internal plugins Signed-off-by: Ansuman Sahoo --- pkg/qemu/qemu_driver.go | 24 +++++-- pkg/qemu/register.go | 10 +++ pkg/vz/register.go | 10 +++ pkg/vz/vz_driver_darwin.go | 24 +++++-- pkg/vz/vz_driver_others.go | 118 +++++++++++++++++++++++++++++++++ pkg/wsl2/register.go | 10 +++ pkg/wsl2/wsl_driver_others.go | 118 +++++++++++++++++++++++++++++++++ pkg/wsl2/wsl_driver_windows.go | 24 +++++-- 8 files changed, 323 insertions(+), 15 deletions(-) create mode 100644 pkg/qemu/register.go create mode 100644 pkg/vz/register.go create mode 100644 pkg/vz/vz_driver_others.go create mode 100644 pkg/wsl2/register.go create mode 100644 pkg/wsl2/wsl_driver_others.go diff --git a/pkg/qemu/qemu_driver.go b/pkg/qemu/qemu_driver.go index 0608a6245ba..8864a79d8de 100644 --- a/pkg/qemu/qemu_driver.go +++ b/pkg/qemu/qemu_driver.go @@ -26,6 +26,7 @@ import ( "github.com/digitalocean/go-qemu/qmp/raw" "github.com/sirupsen/logrus" + "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/executil" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/networks/usernet" @@ -47,7 +48,9 @@ type LimaQemuDriver struct { vhostCmds []*exec.Cmd } -func New(inst *store.Instance, sshLocalPort int) *LimaQemuDriver { +var _ driver.Driver = (*LimaQemuDriver)(nil) + +func New() *LimaQemuDriver { // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 // but on Windows default Unix socket forwarding is not available var virtioPort string @@ -56,13 +59,24 @@ func New(inst *store.Instance, sshLocalPort int) *LimaQemuDriver { virtioPort = "" } return &LimaQemuDriver{ - Instance: inst, - VSockPort: 0, - VirtioPort: virtioPort, - SSHLocalPort: sshLocalPort, + VSockPort: 0, + VirtioPort: virtioPort, } } +func (l *LimaQemuDriver) SetConfig(inst *store.Instance, sshLocalPort int) { + l.Instance = inst + l.SSHLocalPort = sshLocalPort +} + +func (l *LimaQemuDriver) GetVirtioPort() string { + return l.VirtioPort +} + +func (l *LimaQemuDriver) GetVSockPort() int { + return l.VSockPort +} + func (l *LimaQemuDriver) Validate() error { if runtime.GOOS == "darwin" { if err := l.checkBinarySignature(); err != nil { diff --git a/pkg/qemu/register.go b/pkg/qemu/register.go new file mode 100644 index 00000000000..58558d4198a --- /dev/null +++ b/pkg/qemu/register.go @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package qemu + +import "github.com/lima-vm/lima/pkg/registry" + +func init() { + registry.Register(New()) +} diff --git a/pkg/vz/register.go b/pkg/vz/register.go new file mode 100644 index 00000000000..31fc1f21eea --- /dev/null +++ b/pkg/vz/register.go @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package vz + +import "github.com/lima-vm/lima/pkg/registry" + +func init() { + registry.Register(New()) +} diff --git a/pkg/vz/vz_driver_darwin.go b/pkg/vz/vz_driver_darwin.go index dbba1dc1a01..87a7b6d6aae 100644 --- a/pkg/vz/vz_driver_darwin.go +++ b/pkg/vz/vz_driver_darwin.go @@ -18,6 +18,7 @@ import ( "github.com/coreos/go-semver/semver" "github.com/sirupsen/logrus" + "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/reflectutil" @@ -77,15 +78,28 @@ type LimaVzDriver struct { machine *virtualMachineWrapper } -func New(inst *store.Instance, sshLocalPort int) *LimaVzDriver { +var _ driver.Driver = (*LimaVzDriver)(nil) + +func New() *LimaVzDriver { return &LimaVzDriver{ - Instance: inst, - VSockPort: 2222, - VirtioPort: "", - SSHLocalPort: sshLocalPort, + VSockPort: 2222, + VirtioPort: "", } } +func (l *LimaVzDriver) SetConfig(inst *store.Instance, sshLocalPort int) { + l.Instance = inst + l.SSHLocalPort = sshLocalPort +} + +func (l *LimaVzDriver) GetVirtioPort() string { + return l.VirtioPort +} + +func (l *LimaVzDriver) GetVSockPort() int { + return l.VSockPort +} + func (l *LimaVzDriver) Validate() error { macOSProductVersion, err := osutil.ProductVersion() if err != nil { diff --git a/pkg/vz/vz_driver_others.go b/pkg/vz/vz_driver_others.go new file mode 100644 index 00000000000..44e76d8909a --- /dev/null +++ b/pkg/vz/vz_driver_others.go @@ -0,0 +1,118 @@ +//go:build !darwin || no_vz + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package vz + +import ( + "context" + "errors" + "net" + + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/store" +) + +var ErrUnsupported = errors.New("vm driver 'vz' needs macOS 13 or later (Hint: try recompiling Lima if you are seeing this error on macOS 13)") + +const Enabled = false + +type LimaVzDriver struct { + Instance *store.Instance + + SSHLocalPort int + VSockPort int + VirtioPort string +} + +var _ driver.Driver = (*LimaVzDriver)(nil) + +func New() *LimaVzDriver { + return &LimaVzDriver{} +} + +func (l *LimaVzDriver) GetVirtioPort() string { + return l.VirtioPort +} + +func (l *LimaVzDriver) GetVSockPort() int { + return l.VSockPort +} + +func (l *LimaVzDriver) Validate() error { + return ErrUnsupported +} + +func (l *LimaVzDriver) Initialize(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) CreateDisk(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) Start(_ context.Context) (chan error, error) { + return nil, ErrUnsupported +} + +func (l *LimaVzDriver) Stop(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) CanRunGUI() bool { + return false +} + +func (l *LimaVzDriver) RunGUI() error { + return ErrUnsupported +} + +func (l *LimaVzDriver) ChangeDisplayPassword(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) GetDisplayConnection(_ context.Context) (string, error) { + return "", ErrUnsupported +} + +func (l *LimaVzDriver) CreateSnapshot(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) ApplySnapshot(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) DeleteSnapshot(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) ListSnapshots(_ context.Context) (string, error) { + return "", ErrUnsupported +} + +func (l *LimaVzDriver) Register(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) Unregister(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaVzDriver) ForwardGuestAgent() bool { + return false +} + +func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { + return nil, ErrUnsupported +} + +func (l *LimaVzDriver) Name() string { + return "vz" +} + +func (l *LimaVzDriver) SetConfig(inst *store.Instance, sshLocalPort int) { + l.Instance = inst + l.SSHLocalPort = sshLocalPort +} diff --git a/pkg/wsl2/register.go b/pkg/wsl2/register.go new file mode 100644 index 00000000000..5ec58b197ac --- /dev/null +++ b/pkg/wsl2/register.go @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package wsl2 + +import "github.com/lima-vm/lima/pkg/registry" + +func init() { + registry.Register(New()) +} diff --git a/pkg/wsl2/wsl_driver_others.go b/pkg/wsl2/wsl_driver_others.go new file mode 100644 index 00000000000..07c5b37e951 --- /dev/null +++ b/pkg/wsl2/wsl_driver_others.go @@ -0,0 +1,118 @@ +//go:build !windows || no_wsl + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package wsl2 + +import ( + "context" + "errors" + "net" + + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/store" +) + +var ErrUnsupported = errors.New("vm driver 'wsl2' requires Windows 10 build 19041 or later (Hint: try recompiling Lima if you are seeing this error on Windows 10+)") + +const Enabled = false + +type LimaWslDriver struct { + Instance *store.Instance + + SSHLocalPort int + VSockPort int + VirtioPort string +} + +var _ driver.Driver = (*LimaWslDriver)(nil) + +func New() *LimaWslDriver { + return &LimaWslDriver{} +} + +func (l *LimaWslDriver) GetVirtioPort() string { + return l.VirtioPort +} + +func (l *LimaWslDriver) GetVSockPort() int { + return l.VSockPort +} + +func (l *LimaWslDriver) Validate() error { + return ErrUnsupported +} + +func (l *LimaWslDriver) Initialize(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) CreateDisk(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) Start(_ context.Context) (chan error, error) { + return nil, ErrUnsupported +} + +func (l *LimaWslDriver) Stop(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) CanRunGUI() bool { + return false +} + +func (l *LimaWslDriver) RunGUI() error { + return ErrUnsupported +} + +func (l *LimaWslDriver) ChangeDisplayPassword(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) GetDisplayConnection(_ context.Context) (string, error) { + return "", ErrUnsupported +} + +func (l *LimaWslDriver) CreateSnapshot(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) ApplySnapshot(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) DeleteSnapshot(_ context.Context, _ string) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) ListSnapshots(_ context.Context) (string, error) { + return "", ErrUnsupported +} + +func (l *LimaWslDriver) Register(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) Unregister(_ context.Context) error { + return ErrUnsupported +} + +func (l *LimaWslDriver) ForwardGuestAgent() bool { + return false +} + +func (l *LimaWslDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { + return nil, ErrUnsupported +} + +func (l *LimaWslDriver) Name() string { + return "vz" +} + +func (l *LimaWslDriver) SetConfig(inst *store.Instance, sshLocalPort int) { + l.Instance = inst + l.SSHLocalPort = sshLocalPort +} diff --git a/pkg/wsl2/wsl_driver_windows.go b/pkg/wsl2/wsl_driver_windows.go index 7ccbc5a2b60..218150c869b 100644 --- a/pkg/wsl2/wsl_driver_windows.go +++ b/pkg/wsl2/wsl_driver_windows.go @@ -13,6 +13,7 @@ import ( "github.com/Microsoft/go-winio/pkg/guid" "github.com/sirupsen/logrus" + "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/freeport" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/reflectutil" @@ -53,20 +54,33 @@ type LimaWslDriver struct { VirtioPort string } -func New(inst *store.Instance, sshLocalPort int) *LimaWslDriver { +var _ driver.Driver = (*LimaWslDriver)(nil) + +func New() *LimaWslDriver { port, err := freeport.VSock() if err != nil { logrus.WithError(err).Error("failed to get free VSock port") } return &LimaWslDriver{ - Instance: inst, - VSockPort: port, - VirtioPort: "", - SSHLocalPort: sshLocalPort, + VSockPort: port, + VirtioPort: "", } } +func (l *LimaWslDriver) GetVirtioPort() string { + return l.VirtioPort +} + +func (l *LimaWslDriver) GetVSockPort() int { + return l.VSockPort +} + +func (l *LimaWslDriver) SetConfig(inst *store.Instance, sshLocalPort int) { + l.Instance = inst + l.SSHLocalPort = sshLocalPort +} + func (l *LimaWslDriver) Validate() error { if *l.Instance.Config.MountType != limayaml.WSLMount { return fmt.Errorf("field `mountType` must be %q for WSL2 driver, got %q", limayaml.WSLMount, *l.Instance.Config.MountType) From 535a08047040aa15333129d760269ecb0522e50f Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Sat, 24 May 2025 22:27:38 +0530 Subject: [PATCH 12/49] driver(internal): list available built-in drivers Signed-off-by: Ansuman Sahoo --- cmd/limactl/start.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmd/limactl/start.go b/cmd/limactl/start.go index 0d78bc1e0cd..8ea316e4096 100644 --- a/cmd/limactl/start.go +++ b/cmd/limactl/start.go @@ -21,6 +21,7 @@ import ( "github.com/lima-vm/lima/pkg/limatmpl" "github.com/lima-vm/lima/pkg/limayaml" networks "github.com/lima-vm/lima/pkg/networks/reconcile" + "github.com/lima-vm/lima/pkg/registry" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" "github.com/lima-vm/lima/pkg/templatestore" @@ -32,6 +33,7 @@ func registerCreateFlags(cmd *cobra.Command, commentPrefix string) { flags := cmd.Flags() flags.String("name", "", commentPrefix+"Override the instance name") flags.Bool("list-templates", false, commentPrefix+"List available templates and exit") + flags.Bool("list-drivers", false, commentPrefix+"List available drivers and exit") editflags.RegisterCreate(cmd, commentPrefix) } @@ -54,6 +56,9 @@ $ limactl create --set='.cpus = 2 | .memory = "2GiB"' To see the template list: $ limactl create --list-templates +To see the drivers list: +$ limactl create --list-drivers + To create an instance "default" from a local file: $ limactl create --name=default /usr/local/share/lima/templates/fedora.yaml @@ -393,6 +398,14 @@ func createStartActionCommon(cmd *cobra.Command, _ []string) (exit bool, err err _, _ = fmt.Fprintln(w, f.Name) } return true, nil + } else if listDrivers, err := cmd.Flags().GetBool("list-drivers"); err != nil { + return true, err + } else if listDrivers { + w := cmd.OutOrStdout() + for _, d := range registry.DefaultRegistry.List() { + _, _ = fmt.Fprintln(w, d) + } + return true, nil } return false, nil } From bb413edf1a73c09f5648e6b227127e7bd27e816d Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Sun, 25 May 2025 16:42:38 +0530 Subject: [PATCH 13/49] driver(internal): fix CI checks and lint errors Signed-off-by: Ansuman Sahoo --- pkg/builtins/drivers.go | 1 + pkg/driver/driver.go | 12 ++++++------ pkg/driverutil/driverutil.go | 23 ----------------------- pkg/driverutil/instance.go | 2 +- pkg/limainfo/limainfo.go | 4 ++-- 5 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 pkg/driverutil/driverutil.go diff --git a/pkg/builtins/drivers.go b/pkg/builtins/drivers.go index 5ae3f563eaa..6deb3a646c1 100644 --- a/pkg/builtins/drivers.go +++ b/pkg/builtins/drivers.go @@ -4,6 +4,7 @@ package builtins import ( + // Import all built-in drivers to register them in the registry. _ "github.com/lima-vm/lima/pkg/qemu" _ "github.com/lima-vm/lima/pkg/vz" _ "github.com/lima-vm/lima/pkg/wsl2" diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index e9a5d9e1028..0156e094c56 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -10,7 +10,7 @@ import ( "github.com/lima-vm/lima/pkg/store" ) -// Basic lifecycle operations +// Lifecycle defines basic lifecycle operations. type Lifecycle interface { // Validate returns error if the current driver isn't support for given config Validate() error @@ -36,7 +36,7 @@ type Lifecycle interface { Stop(_ context.Context) error } -// GUI-related operations +// GUI defines GUI-related operations. type GUI interface { // CanRunGUI returns bool to indicate if the hostagent need to run GUI synchronously CanRunGUI() bool @@ -49,7 +49,7 @@ type GUI interface { GetDisplayConnection(ctx context.Context) (string, error) } -// Snapshot operations +// Snapshot defines operations for managing snapshots. type Snapshot interface { CreateSnapshot(ctx context.Context, tag string) error ApplySnapshot(ctx context.Context, tag string) error @@ -57,13 +57,13 @@ type Snapshot interface { ListSnapshots(ctx context.Context) (string, error) } -// Registration operations +// Registration defines operations for registering and unregistering the driver instance. type Registration interface { Register(ctx context.Context) error Unregister(ctx context.Context) error } -// Guest agent operations +// GuestAgent defines operations for the guest agent. type GuestAgent interface { // ForwardGuestAgent returns if the guest agent sock needs forwarding by host agent. ForwardGuestAgent() bool @@ -76,7 +76,7 @@ type Plugin interface { // Name returns the name of the driver Name() string - // NewDriver returns a new driver instance. Only to be used to embed internal drivers + // SetConfig sets the configuration for the instance. SetConfig(inst *store.Instance, sshLocalPort int) } diff --git a/pkg/driverutil/driverutil.go b/pkg/driverutil/driverutil.go deleted file mode 100644 index a7c6f2f2570..00000000000 --- a/pkg/driverutil/driverutil.go +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package driverutil - -import ( - "github.com/lima-vm/lima/pkg/registry" -) - -// AvailableDrivers returns a list of available driver names -func AvailableDrivers() []string { - var available []string - - for _, name := range registry.DefaultRegistry.List() { - driver, _ := registry.DefaultRegistry.Get(name) - if err := driver.Validate(); err == nil { - return available - } - available = append(available, name) - } - - return available -} diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index 591cb66ea02..ab1f1b413c6 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -11,7 +11,7 @@ import ( "github.com/lima-vm/lima/pkg/store" ) -// CreateTargetDriverInstance creates the appropriate driver for an instance +// CreateTargetDriverInstance creates the appropriate driver for an instance. func CreateTargetDriverInstance(inst *store.Instance, sshLocalPort int) (driver.Driver, error) { limaDriver := inst.Config.VMType driver, exists := registry.DefaultRegistry.Get(string(*limaDriver)) diff --git a/pkg/limainfo/limainfo.go b/pkg/limainfo/limainfo.go index 5eb37c3204b..0bd1876b6b4 100644 --- a/pkg/limainfo/limainfo.go +++ b/pkg/limainfo/limainfo.go @@ -9,8 +9,8 @@ import ( "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/driverutil" "github.com/lima-vm/lima/pkg/limayaml" + "github.com/lima-vm/lima/pkg/registry" "github.com/lima-vm/lima/pkg/store/dirnames" "github.com/lima-vm/lima/pkg/templatestore" "github.com/lima-vm/lima/pkg/usrlocalsharelima" @@ -45,7 +45,7 @@ func New() (*LimaInfo, error) { info := &LimaInfo{ Version: version.Version, DefaultTemplate: y, - VMTypes: driverutil.AvailableDrivers(), + VMTypes: registry.DefaultRegistry.List(), GuestAgents: make(map[limayaml.Arch]GuestAgent), } info.Templates, err = templatestore.Templates() From 457ddea106b212c9f86cb7547a03735481818188 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Sun, 25 May 2025 18:47:05 +0530 Subject: [PATCH 14/49] refactor(driver): move qemu,vz and wsl2 to pkg/driver Signed-off-by: Ansuman Sahoo --- pkg/builtins/drivers.go | 6 +++--- pkg/{ => driver}/qemu/entitlementutil/entitlementutil.go | 0 pkg/{ => driver}/qemu/qemu.go | 1 + pkg/{ => driver}/qemu/qemu_driver.go | 2 +- pkg/{ => driver}/qemu/qemu_test.go | 0 pkg/{ => driver}/qemu/register.go | 0 pkg/{ => driver}/vz/disk.go | 0 pkg/{ => driver}/vz/errors_darwin.go | 0 pkg/{ => driver}/vz/network_darwin.go | 0 pkg/{ => driver}/vz/network_darwin_test.go | 0 pkg/{ => driver}/vz/register.go | 0 pkg/{ => driver}/vz/rosetta_directory_share.go | 0 pkg/{ => driver}/vz/rosetta_directory_share_arm64.go | 0 pkg/{ => driver}/vz/vm_darwin.go | 0 pkg/{ => driver}/vz/vz_driver_darwin.go | 0 pkg/{ => driver}/vz/vz_driver_others.go | 0 pkg/{ => driver}/wsl2/fs.go | 0 pkg/{ => driver}/wsl2/lima-init.TEMPLATE | 0 pkg/{ => driver}/wsl2/register.go | 0 pkg/{ => driver}/wsl2/vm_windows.go | 0 pkg/{ => driver}/wsl2/wsl_driver_others.go | 0 pkg/{ => driver}/wsl2/wsl_driver_windows.go | 0 pkg/{imgutil => }/qemuimgutil/qemuimgutil.go | 0 pkg/{imgutil => }/qemuimgutil/qemuimgutil_test.go | 0 24 files changed, 5 insertions(+), 4 deletions(-) rename pkg/{ => driver}/qemu/entitlementutil/entitlementutil.go (100%) rename pkg/{ => driver}/qemu/qemu.go (99%) rename pkg/{ => driver}/qemu/qemu_driver.go (99%) rename pkg/{ => driver}/qemu/qemu_test.go (100%) rename pkg/{ => driver}/qemu/register.go (100%) rename pkg/{ => driver}/vz/disk.go (100%) rename pkg/{ => driver}/vz/errors_darwin.go (100%) rename pkg/{ => driver}/vz/network_darwin.go (100%) rename pkg/{ => driver}/vz/network_darwin_test.go (100%) rename pkg/{ => driver}/vz/register.go (100%) rename pkg/{ => driver}/vz/rosetta_directory_share.go (100%) rename pkg/{ => driver}/vz/rosetta_directory_share_arm64.go (100%) rename pkg/{ => driver}/vz/vm_darwin.go (100%) rename pkg/{ => driver}/vz/vz_driver_darwin.go (100%) rename pkg/{ => driver}/vz/vz_driver_others.go (100%) rename pkg/{ => driver}/wsl2/fs.go (100%) rename pkg/{ => driver}/wsl2/lima-init.TEMPLATE (100%) rename pkg/{ => driver}/wsl2/register.go (100%) rename pkg/{ => driver}/wsl2/vm_windows.go (100%) rename pkg/{ => driver}/wsl2/wsl_driver_others.go (100%) rename pkg/{ => driver}/wsl2/wsl_driver_windows.go (100%) rename pkg/{imgutil => }/qemuimgutil/qemuimgutil.go (100%) rename pkg/{imgutil => }/qemuimgutil/qemuimgutil_test.go (100%) diff --git a/pkg/builtins/drivers.go b/pkg/builtins/drivers.go index 6deb3a646c1..0f7b646d641 100644 --- a/pkg/builtins/drivers.go +++ b/pkg/builtins/drivers.go @@ -5,7 +5,7 @@ package builtins import ( // Import all built-in drivers to register them in the registry. - _ "github.com/lima-vm/lima/pkg/qemu" - _ "github.com/lima-vm/lima/pkg/vz" - _ "github.com/lima-vm/lima/pkg/wsl2" + _ "github.com/lima-vm/lima/pkg/driver/qemu" + _ "github.com/lima-vm/lima/pkg/driver/vz" + _ "github.com/lima-vm/lima/pkg/driver/wsl2" ) diff --git a/pkg/qemu/entitlementutil/entitlementutil.go b/pkg/driver/qemu/entitlementutil/entitlementutil.go similarity index 100% rename from pkg/qemu/entitlementutil/entitlementutil.go rename to pkg/driver/qemu/entitlementutil/entitlementutil.go diff --git a/pkg/qemu/qemu.go b/pkg/driver/qemu/qemu.go similarity index 99% rename from pkg/qemu/qemu.go rename to pkg/driver/qemu/qemu.go index 2fb08886ffc..44360a4eda9 100644 --- a/pkg/qemu/qemu.go +++ b/pkg/driver/qemu/qemu.go @@ -34,6 +34,7 @@ import ( "github.com/lima-vm/lima/pkg/networks" "github.com/lima-vm/lima/pkg/networks/usernet" "github.com/lima-vm/lima/pkg/osutil" + "github.com/lima-vm/lima/pkg/qemuimgutil" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" ) diff --git a/pkg/qemu/qemu_driver.go b/pkg/driver/qemu/qemu_driver.go similarity index 99% rename from pkg/qemu/qemu_driver.go rename to pkg/driver/qemu/qemu_driver.go index 8864a79d8de..c026dab21c1 100644 --- a/pkg/qemu/qemu_driver.go +++ b/pkg/driver/qemu/qemu_driver.go @@ -27,11 +27,11 @@ import ( "github.com/sirupsen/logrus" "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/driver/qemu/entitlementutil" "github.com/lima-vm/lima/pkg/executil" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/networks/usernet" "github.com/lima-vm/lima/pkg/osutil" - "github.com/lima-vm/lima/pkg/qemu/entitlementutil" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" ) diff --git a/pkg/qemu/qemu_test.go b/pkg/driver/qemu/qemu_test.go similarity index 100% rename from pkg/qemu/qemu_test.go rename to pkg/driver/qemu/qemu_test.go diff --git a/pkg/qemu/register.go b/pkg/driver/qemu/register.go similarity index 100% rename from pkg/qemu/register.go rename to pkg/driver/qemu/register.go diff --git a/pkg/vz/disk.go b/pkg/driver/vz/disk.go similarity index 100% rename from pkg/vz/disk.go rename to pkg/driver/vz/disk.go diff --git a/pkg/vz/errors_darwin.go b/pkg/driver/vz/errors_darwin.go similarity index 100% rename from pkg/vz/errors_darwin.go rename to pkg/driver/vz/errors_darwin.go diff --git a/pkg/vz/network_darwin.go b/pkg/driver/vz/network_darwin.go similarity index 100% rename from pkg/vz/network_darwin.go rename to pkg/driver/vz/network_darwin.go diff --git a/pkg/vz/network_darwin_test.go b/pkg/driver/vz/network_darwin_test.go similarity index 100% rename from pkg/vz/network_darwin_test.go rename to pkg/driver/vz/network_darwin_test.go diff --git a/pkg/vz/register.go b/pkg/driver/vz/register.go similarity index 100% rename from pkg/vz/register.go rename to pkg/driver/vz/register.go diff --git a/pkg/vz/rosetta_directory_share.go b/pkg/driver/vz/rosetta_directory_share.go similarity index 100% rename from pkg/vz/rosetta_directory_share.go rename to pkg/driver/vz/rosetta_directory_share.go diff --git a/pkg/vz/rosetta_directory_share_arm64.go b/pkg/driver/vz/rosetta_directory_share_arm64.go similarity index 100% rename from pkg/vz/rosetta_directory_share_arm64.go rename to pkg/driver/vz/rosetta_directory_share_arm64.go diff --git a/pkg/vz/vm_darwin.go b/pkg/driver/vz/vm_darwin.go similarity index 100% rename from pkg/vz/vm_darwin.go rename to pkg/driver/vz/vm_darwin.go diff --git a/pkg/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go similarity index 100% rename from pkg/vz/vz_driver_darwin.go rename to pkg/driver/vz/vz_driver_darwin.go diff --git a/pkg/vz/vz_driver_others.go b/pkg/driver/vz/vz_driver_others.go similarity index 100% rename from pkg/vz/vz_driver_others.go rename to pkg/driver/vz/vz_driver_others.go diff --git a/pkg/wsl2/fs.go b/pkg/driver/wsl2/fs.go similarity index 100% rename from pkg/wsl2/fs.go rename to pkg/driver/wsl2/fs.go diff --git a/pkg/wsl2/lima-init.TEMPLATE b/pkg/driver/wsl2/lima-init.TEMPLATE similarity index 100% rename from pkg/wsl2/lima-init.TEMPLATE rename to pkg/driver/wsl2/lima-init.TEMPLATE diff --git a/pkg/wsl2/register.go b/pkg/driver/wsl2/register.go similarity index 100% rename from pkg/wsl2/register.go rename to pkg/driver/wsl2/register.go diff --git a/pkg/wsl2/vm_windows.go b/pkg/driver/wsl2/vm_windows.go similarity index 100% rename from pkg/wsl2/vm_windows.go rename to pkg/driver/wsl2/vm_windows.go diff --git a/pkg/wsl2/wsl_driver_others.go b/pkg/driver/wsl2/wsl_driver_others.go similarity index 100% rename from pkg/wsl2/wsl_driver_others.go rename to pkg/driver/wsl2/wsl_driver_others.go diff --git a/pkg/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go similarity index 100% rename from pkg/wsl2/wsl_driver_windows.go rename to pkg/driver/wsl2/wsl_driver_windows.go diff --git a/pkg/imgutil/qemuimgutil/qemuimgutil.go b/pkg/qemuimgutil/qemuimgutil.go similarity index 100% rename from pkg/imgutil/qemuimgutil/qemuimgutil.go rename to pkg/qemuimgutil/qemuimgutil.go diff --git a/pkg/imgutil/qemuimgutil/qemuimgutil_test.go b/pkg/qemuimgutil/qemuimgutil_test.go similarity index 100% rename from pkg/imgutil/qemuimgutil/qemuimgutil_test.go rename to pkg/qemuimgutil/qemuimgutil_test.go From 13840aca04340209829b98ac75d5ecb1546ebc5f Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 26 May 2025 18:40:21 +0530 Subject: [PATCH 15/49] driver(internal): refactor Snapshot to SnapshotManager in driver interface Signed-off-by: Ansuman Sahoo --- cmd/limactl/start.go | 2 -- pkg/driver/driver.go | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cmd/limactl/start.go b/cmd/limactl/start.go index 8ea316e4096..7d482b89fe3 100644 --- a/cmd/limactl/start.go +++ b/cmd/limactl/start.go @@ -56,8 +56,6 @@ $ limactl create --set='.cpus = 2 | .memory = "2GiB"' To see the template list: $ limactl create --list-templates -To see the drivers list: -$ limactl create --list-drivers To create an instance "default" from a local file: $ limactl create --name=default /usr/local/share/lima/templates/fedora.yaml diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 0156e094c56..693ce91a9ff 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -49,8 +49,8 @@ type GUI interface { GetDisplayConnection(ctx context.Context) (string, error) } -// Snapshot defines operations for managing snapshots. -type Snapshot interface { +// SnapshotManager defines operations for managing snapshots. +type SnapshotManager interface { CreateSnapshot(ctx context.Context, tag string) error ApplySnapshot(ctx context.Context, tag string) error DeleteSnapshot(ctx context.Context, tag string) error @@ -84,7 +84,7 @@ type Plugin interface { type Driver interface { Lifecycle GUI - Snapshot + SnapshotManager Registration GuestAgent Plugin From dd276d314b391e5b53001ec562f4f806ea5b7363 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 26 May 2025 18:43:21 +0530 Subject: [PATCH 16/49] driver(internal): compile vz on darwin, wsl2 on windows only and implement common error Signed-off-by: Ansuman Sahoo --- cmd/limactl/main.go | 2 +- cmd/limactl/main_darwin.go | 9 ++ cmd/limactl/main_windows.go | 9 ++ pkg/driver/vz/errors_darwin.go | 5 +- pkg/driver/vz/register.go | 2 + pkg/driver/vz/vz_driver_darwin.go | 8 +- pkg/driver/vz/vz_driver_others.go | 118 -------------------------- pkg/driver/wsl2/errors_windows.go | 11 +++ pkg/driver/wsl2/register.go | 2 + pkg/driver/wsl2/wsl_driver_others.go | 118 -------------------------- pkg/driver/wsl2/wsl_driver_windows.go | 8 +- 11 files changed, 46 insertions(+), 246 deletions(-) create mode 100644 cmd/limactl/main_darwin.go create mode 100644 cmd/limactl/main_windows.go delete mode 100644 pkg/driver/vz/vz_driver_others.go create mode 100644 pkg/driver/wsl2/errors_windows.go delete mode 100644 pkg/driver/wsl2/wsl_driver_others.go diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index dcdb7e2f1b5..6500e1aa069 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -15,8 +15,8 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/cobra" - _ "github.com/lima-vm/lima/pkg/builtins" // register built-in drivers "github.com/lima-vm/lima/pkg/debugutil" + _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms "github.com/lima-vm/lima/pkg/fsutil" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/store/dirnames" diff --git a/cmd/limactl/main_darwin.go b/cmd/limactl/main_darwin.go new file mode 100644 index 00000000000..28d8c7f29a2 --- /dev/null +++ b/cmd/limactl/main_darwin.go @@ -0,0 +1,9 @@ +//go:build darwin && !no_vz + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +// Import vz driver to register it in the registry on darwin. +import _ "github.com/lima-vm/lima/pkg/driver/vz" diff --git a/cmd/limactl/main_windows.go b/cmd/limactl/main_windows.go new file mode 100644 index 00000000000..871029c8a4f --- /dev/null +++ b/cmd/limactl/main_windows.go @@ -0,0 +1,9 @@ +//go:build windows && !no_wsl + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +// Import wsl2 driver to register it in the registry on windows. +import _ "github.com/lima-vm/lima/pkg/driver/wsl2" diff --git a/pkg/driver/vz/errors_darwin.go b/pkg/driver/vz/errors_darwin.go index 2bc832cf98b..aa180c70255 100644 --- a/pkg/driver/vz/errors_darwin.go +++ b/pkg/driver/vz/errors_darwin.go @@ -8,4 +8,7 @@ package vz import "errors" //nolint:revive,staticcheck // false positives with proper nouns -var errRosettaUnsupported = errors.New("Rosetta is unsupported on non-ARM64 hosts") +var ( + errRosettaUnsupported = errors.New("Rosetta is unsupported on non-ARM64 hosts") + errUnimplemented = errors.New("unimplemented") +) diff --git a/pkg/driver/vz/register.go b/pkg/driver/vz/register.go index 31fc1f21eea..750be4b37c2 100644 --- a/pkg/driver/vz/register.go +++ b/pkg/driver/vz/register.go @@ -1,3 +1,5 @@ +//go:build darwin && !no_vz + // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/driver/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go index 87a7b6d6aae..c5471d00b13 100644 --- a/pkg/driver/vz/vz_driver_darwin.go +++ b/pkg/driver/vz/vz_driver_darwin.go @@ -285,19 +285,19 @@ func (l *LimaVzDriver) GetDisplayConnection(_ context.Context) (string, error) { } func (l *LimaVzDriver) CreateSnapshot(_ context.Context, _ string) error { - return errors.New("unimplemented") + return errUnimplemented } func (l *LimaVzDriver) ApplySnapshot(_ context.Context, _ string) error { - return errors.New("unimplemented") + return errUnimplemented } func (l *LimaVzDriver) DeleteSnapshot(_ context.Context, _ string) error { - return errors.New("unimplemented") + return errUnimplemented } func (l *LimaVzDriver) ListSnapshots(_ context.Context) (string, error) { - return "", errors.New("unimplemented") + return "", errUnimplemented } func (l *LimaVzDriver) ForwardGuestAgent() bool { diff --git a/pkg/driver/vz/vz_driver_others.go b/pkg/driver/vz/vz_driver_others.go deleted file mode 100644 index 44e76d8909a..00000000000 --- a/pkg/driver/vz/vz_driver_others.go +++ /dev/null @@ -1,118 +0,0 @@ -//go:build !darwin || no_vz - -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package vz - -import ( - "context" - "errors" - "net" - - "github.com/lima-vm/lima/pkg/driver" - "github.com/lima-vm/lima/pkg/store" -) - -var ErrUnsupported = errors.New("vm driver 'vz' needs macOS 13 or later (Hint: try recompiling Lima if you are seeing this error on macOS 13)") - -const Enabled = false - -type LimaVzDriver struct { - Instance *store.Instance - - SSHLocalPort int - VSockPort int - VirtioPort string -} - -var _ driver.Driver = (*LimaVzDriver)(nil) - -func New() *LimaVzDriver { - return &LimaVzDriver{} -} - -func (l *LimaVzDriver) GetVirtioPort() string { - return l.VirtioPort -} - -func (l *LimaVzDriver) GetVSockPort() int { - return l.VSockPort -} - -func (l *LimaVzDriver) Validate() error { - return ErrUnsupported -} - -func (l *LimaVzDriver) Initialize(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) CreateDisk(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) Start(_ context.Context) (chan error, error) { - return nil, ErrUnsupported -} - -func (l *LimaVzDriver) Stop(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) CanRunGUI() bool { - return false -} - -func (l *LimaVzDriver) RunGUI() error { - return ErrUnsupported -} - -func (l *LimaVzDriver) ChangeDisplayPassword(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) GetDisplayConnection(_ context.Context) (string, error) { - return "", ErrUnsupported -} - -func (l *LimaVzDriver) CreateSnapshot(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) ApplySnapshot(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) DeleteSnapshot(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) ListSnapshots(_ context.Context) (string, error) { - return "", ErrUnsupported -} - -func (l *LimaVzDriver) Register(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) Unregister(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaVzDriver) ForwardGuestAgent() bool { - return false -} - -func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { - return nil, ErrUnsupported -} - -func (l *LimaVzDriver) Name() string { - return "vz" -} - -func (l *LimaVzDriver) SetConfig(inst *store.Instance, sshLocalPort int) { - l.Instance = inst - l.SSHLocalPort = sshLocalPort -} diff --git a/pkg/driver/wsl2/errors_windows.go b/pkg/driver/wsl2/errors_windows.go new file mode 100644 index 00000000000..2c615ca5458 --- /dev/null +++ b/pkg/driver/wsl2/errors_windows.go @@ -0,0 +1,11 @@ +//go:build windows && !no_wsl + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package wsl2 + +import "errors" + +//nolint:revive,staticcheck // false positives with proper nouns +var errUnimplemented = errors.New("unimplemented") diff --git a/pkg/driver/wsl2/register.go b/pkg/driver/wsl2/register.go index 5ec58b197ac..ccbc516d75e 100644 --- a/pkg/driver/wsl2/register.go +++ b/pkg/driver/wsl2/register.go @@ -1,3 +1,5 @@ +//go:build windows && !no_wsl + // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/driver/wsl2/wsl_driver_others.go b/pkg/driver/wsl2/wsl_driver_others.go deleted file mode 100644 index 07c5b37e951..00000000000 --- a/pkg/driver/wsl2/wsl_driver_others.go +++ /dev/null @@ -1,118 +0,0 @@ -//go:build !windows || no_wsl - -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package wsl2 - -import ( - "context" - "errors" - "net" - - "github.com/lima-vm/lima/pkg/driver" - "github.com/lima-vm/lima/pkg/store" -) - -var ErrUnsupported = errors.New("vm driver 'wsl2' requires Windows 10 build 19041 or later (Hint: try recompiling Lima if you are seeing this error on Windows 10+)") - -const Enabled = false - -type LimaWslDriver struct { - Instance *store.Instance - - SSHLocalPort int - VSockPort int - VirtioPort string -} - -var _ driver.Driver = (*LimaWslDriver)(nil) - -func New() *LimaWslDriver { - return &LimaWslDriver{} -} - -func (l *LimaWslDriver) GetVirtioPort() string { - return l.VirtioPort -} - -func (l *LimaWslDriver) GetVSockPort() int { - return l.VSockPort -} - -func (l *LimaWslDriver) Validate() error { - return ErrUnsupported -} - -func (l *LimaWslDriver) Initialize(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) CreateDisk(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) Start(_ context.Context) (chan error, error) { - return nil, ErrUnsupported -} - -func (l *LimaWslDriver) Stop(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) CanRunGUI() bool { - return false -} - -func (l *LimaWslDriver) RunGUI() error { - return ErrUnsupported -} - -func (l *LimaWslDriver) ChangeDisplayPassword(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) GetDisplayConnection(_ context.Context) (string, error) { - return "", ErrUnsupported -} - -func (l *LimaWslDriver) CreateSnapshot(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) ApplySnapshot(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) DeleteSnapshot(_ context.Context, _ string) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) ListSnapshots(_ context.Context) (string, error) { - return "", ErrUnsupported -} - -func (l *LimaWslDriver) Register(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) Unregister(_ context.Context) error { - return ErrUnsupported -} - -func (l *LimaWslDriver) ForwardGuestAgent() bool { - return false -} - -func (l *LimaWslDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { - return nil, ErrUnsupported -} - -func (l *LimaWslDriver) Name() string { - return "vz" -} - -func (l *LimaWslDriver) SetConfig(inst *store.Instance, sshLocalPort int) { - l.Instance = inst - l.SSHLocalPort = sshLocalPort -} diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index 218150c869b..420f8892f99 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -246,19 +246,19 @@ func (l *LimaWslDriver) GetDisplayConnection(_ context.Context) (string, error) } func (l *LimaWslDriver) CreateSnapshot(_ context.Context, _ string) error { - return fmt.Errorf("unimplemented") + return errUnimplemented } func (l *LimaWslDriver) ApplySnapshot(_ context.Context, _ string) error { - return fmt.Errorf("unimplemented") + return errUnimplemented } func (l *LimaWslDriver) DeleteSnapshot(_ context.Context, _ string) error { - return fmt.Errorf("unimplemented") + return errUnimplemented } func (l *LimaWslDriver) ListSnapshots(_ context.Context) (string, error) { - return "", fmt.Errorf("unimplemented") + return "", errUnimplemented } func (l *LimaWslDriver) ForwardGuestAgent() bool { From a20c982458e6a68299c90bb2ff5baa89d4938f37 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 27 May 2025 16:01:07 +0530 Subject: [PATCH 17/49] refactor(driver): remove redundant builtins pkg Signed-off-by: Ansuman Sahoo --- cmd/limactl/disk.go | 2 +- pkg/builtins/drivers.go | 11 ----------- pkg/networks/usernet/client.go | 1 + 3 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 pkg/builtins/drivers.go diff --git a/cmd/limactl/disk.go b/cmd/limactl/disk.go index 7f19b069c5d..fc735c42ea5 100644 --- a/cmd/limactl/disk.go +++ b/cmd/limactl/disk.go @@ -14,10 +14,10 @@ import ( contfs "github.com/containerd/continuity/fs" "github.com/docker/go-units" - "github.com/lima-vm/go-qcow2reader" "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/lima-vm/go-qcow2reader" "github.com/lima-vm/lima/pkg/imgutil/proxyimgutil" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" diff --git a/pkg/builtins/drivers.go b/pkg/builtins/drivers.go deleted file mode 100644 index 0f7b646d641..00000000000 --- a/pkg/builtins/drivers.go +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package builtins - -import ( - // Import all built-in drivers to register them in the registry. - _ "github.com/lima-vm/lima/pkg/driver/qemu" - _ "github.com/lima-vm/lima/pkg/driver/vz" - _ "github.com/lima-vm/lima/pkg/driver/wsl2" -) diff --git a/pkg/networks/usernet/client.go b/pkg/networks/usernet/client.go index c55c1e8c2a3..8bc478cb0f2 100644 --- a/pkg/networks/usernet/client.go +++ b/pkg/networks/usernet/client.go @@ -16,6 +16,7 @@ import ( gvproxyclient "github.com/containers/gvisor-tap-vsock/pkg/client" "github.com/containers/gvisor-tap-vsock/pkg/types" + "github.com/lima-vm/lima/pkg/httpclientutil" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/networks/usernet/dnshosts" From c56295cd3034614c0c24e48883feff9ad03904e1 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 27 May 2025 18:21:49 +0530 Subject: [PATCH 18/49] driver(external): proto file init Signed-off-by: Ansuman Sahoo --- pkg/driver/external/proto/driver.proto | 144 +++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 pkg/driver/external/proto/driver.proto diff --git a/pkg/driver/external/proto/driver.proto b/pkg/driver/external/proto/driver.proto new file mode 100644 index 00000000000..f50d46ca565 --- /dev/null +++ b/pkg/driver/external/proto/driver.proto @@ -0,0 +1,144 @@ +// [WIP]: Please do not review this file yet. + +syntax = "proto3"; + +package driver; + +option go_package = "github.com/lima-vm/lima/pkg/driver/external/proto"; + +import "google/protobuf/empty.proto"; + +service Driver { + rpc Validate(google.protobuf.Empty) returns (ValidateResponse); + rpc Initialize(google.protobuf.Empty) returns (InitializeResponse); + rpc CreateDisk(google.protobuf.Empty) returns (CreateDiskResponse); + rpc Start(google.protobuf.Empty) returns (StartResponse); + rpc Stop(google.protobuf.Empty) returns (StopResponse); + + rpc Name(google.protobuf.Empty) returns (NameResponse); + rpc SetConfig(SetConfigRequest) returns (SetConfigResponse); + + rpc GetVSockPort(google.protobuf.Empty) returns (GetVSockPortResponse); + rpc GetVirtioPort(google.protobuf.Empty) returns (GetVirtioPortResponse); +} + +message Empty {} + +message InstanceConfig { + string id = 1; + string name = 2; + string dir = 3; + string arch = 4; + string cpuType = 5; + repeated string rosetta = 6; + int32 cpus = 7; + string memory = 8; + string disk = 9; + string kernel = 10; + string initrd = 11; + bool headless = 12; + bool mountHostUsers = 13; + bool enableSharing = 14; + string ssh = 15; + string sshLocalPort = 16; + repeated Mount mounts = 17; + repeated Port ports = 18; + repeated Network networks = 19; + string containerd = 20; + string containerdUser = 21; + string containerdNamespace = 22; + string vmType = 23; + repeated string requirements = 24; + repeated string firmware = 25; + repeated AdditionalDisk additionalDisks = 26; + ProxyCommand proxyCommand = 27; +} + +message Mount { + string location = 1; + string mountPoint = 2; + bool writable = 3; + string sshfs = 4; + int32 ninep = 5; +} + +message Port { + string guestPort = 1; + string hostPort = 2; + string proto = 3; +} + +message Network { + string lima = 1; + string socket_vmnet = 2; +} + +message AdditionalDisk { + string location = 1; + bool writable = 2; + string size = 3; +} + +message ProxyCommand { + string command = 1; +} + +message ValidateResponse { + bool valid = 1; + string error = 2; +} + +message InitializeResponse { + bool success = 1; + string error = 2; +} + +message CreateDiskResponse { + bool success = 1; + string error = 2; +} + +message StartResponse { + bool success = 1; + string error = 2; +} + +message StopResponse { + bool success = 1; + string error = 2; +} + +message RegisterResponse { + bool success = 1; + string error = 2; +} + + +message UnregisterResponse { + bool success = 1; + string error = 2; +} + +message NameResponse { + string name = 1; +} + +message SetConfigRequest { + bytes instance_config_json = 1; + int32 ssh_local_port = 3; +} + +message SetConfigResponse { + bool success = 1; + string error = 2; +} + + +message GetVSockPortResponse { + int32 port = 1; +} + + +message GetVirtioPortResponse { + string port = 1; +} From 439802de6b03f3b22219feeee7965fa981a5576b Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 28 May 2025 21:45:22 +0530 Subject: [PATCH 19/49] driver(external): external driver manager init Signed-off-by: Ansuman Sahoo --- pkg/registry/registry.go | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 50101b67ce0..9d61584a1f8 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -7,16 +7,19 @@ import ( "sync" "github.com/lima-vm/lima/pkg/driver" + "github.com/sirupsen/logrus" ) type Registry struct { - drivers map[string]driver.Driver - mu sync.RWMutex + drivers map[string]driver.Driver + externalDrivers map[string]string // For now mapping external driver names to paths + mu sync.RWMutex } func NewRegistry() *Registry { return &Registry{ - drivers: make(map[string]driver.Driver), + drivers: make(map[string]driver.Driver), + externalDrivers: make(map[string]string), } } @@ -28,6 +31,10 @@ func (r *Registry) List() []string { for name := range r.drivers { names = append(names, name) } + + for name := range r.externalDrivers { + names = append(names, name+" (external)") + } return names } @@ -39,6 +46,32 @@ func (r *Registry) Get(name string) (driver.Driver, bool) { return driver, exists } +func (r *Registry) GetExternalDriver(name string) (string, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + + plugin, exists := r.externalDrivers[name] + return plugin, exists +} + +func (r *Registry) RegisterPlugin(name, path string) { + r.mu.Lock() + defer r.mu.Unlock() + + if _, exists := r.externalDrivers[name]; exists { + logrus.Debugf("Plugin %q is already registered, skipping", name) + return + } + + r.externalDrivers[name] = path + logrus.Debugf("Registered plugin %q at %s", name, path) +} + +func (r *Registry) DiscoverPlugins() error { + // TODO: Implement plugin discovery logic + return nil +} + var DefaultRegistry *Registry func init() { From 252c024832be2ff4dd1802d3a72d59571fc6e365 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 28 May 2025 21:46:52 +0530 Subject: [PATCH 20/49] driver(external): complete proto file for driver interface Signed-off-by: Ansuman Sahoo --- pkg/driver/external/proto/driver.proto | 150 ++++++++++++++----------- 1 file changed, 86 insertions(+), 64 deletions(-) diff --git a/pkg/driver/external/proto/driver.proto b/pkg/driver/external/proto/driver.proto index f50d46ca565..909cbfd657b 100644 --- a/pkg/driver/external/proto/driver.proto +++ b/pkg/driver/external/proto/driver.proto @@ -15,6 +15,22 @@ service Driver { rpc Start(google.protobuf.Empty) returns (StartResponse); rpc Stop(google.protobuf.Empty) returns (StopResponse); + rpc CanRunGUI(google.protobuf.Empty) returns (CanRunGUIResponse); + rpc RunGUI(google.protobuf.Empty) returns (RunGUIResponse); + rpc ChangeDisplayPassword(ChangeDisplayPasswordRequest) returns (ChangeDisplayPasswordResponse); + rpc GetDisplayConnection(google.protobuf.Empty) returns (GetDisplayConnectionResponse); + + rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse); + rpc ApplySnapshot(ApplySnapshotRequest) returns (ApplySnapshotResponse); + rpc DeleteSnapshot(DeleteSnapshotRequest) returns (DeleteSnapshotResponse); + rpc ListSnapshots(google.protobuf.Empty) returns (ListSnapshotsResponse); + + rpc Register(google.protobuf.Empty) returns (RegisterResponse); + rpc Unregister(google.protobuf.Empty) returns (UnregisterResponse); + + rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); + rpc GuestAgentConn(google.protobuf.Empty) returns (GuestAgentConnResponse); + rpc Name(google.protobuf.Empty) returns (NameResponse); rpc SetConfig(SetConfigRequest) returns (SetConfigResponse); @@ -22,67 +38,6 @@ service Driver { rpc GetVirtioPort(google.protobuf.Empty) returns (GetVirtioPortResponse); } -message Empty {} - -message InstanceConfig { - string id = 1; - string name = 2; - string dir = 3; - string arch = 4; - string cpuType = 5; - repeated string rosetta = 6; - int32 cpus = 7; - string memory = 8; - string disk = 9; - string kernel = 10; - string initrd = 11; - bool headless = 12; - bool mountHostUsers = 13; - bool enableSharing = 14; - string ssh = 15; - string sshLocalPort = 16; - repeated Mount mounts = 17; - repeated Port ports = 18; - repeated Network networks = 19; - string containerd = 20; - string containerdUser = 21; - string containerdNamespace = 22; - string vmType = 23; - repeated string requirements = 24; - repeated string firmware = 25; - repeated AdditionalDisk additionalDisks = 26; - ProxyCommand proxyCommand = 27; -} - -message Mount { - string location = 1; - string mountPoint = 2; - bool writable = 3; - string sshfs = 4; - int32 ninep = 5; -} - -message Port { - string guestPort = 1; - string hostPort = 2; - string proto = 3; -} - -message Network { - string lima = 1; - string socket_vmnet = 2; -} - -message AdditionalDisk { - string location = 1; - bool writable = 2; - string size = 3; -} - -message ProxyCommand { - string command = 1; -} - message ValidateResponse { bool valid = 1; string error = 2; @@ -113,7 +68,6 @@ message RegisterResponse { string error = 2; } - message UnregisterResponse { bool success = 1; string error = 2; @@ -133,12 +87,80 @@ message SetConfigResponse { string error = 2; } - message GetVSockPortResponse { int32 port = 1; } - message GetVirtioPortResponse { string port = 1; } + +message CanRunGUIResponse { + bool can_run = 1; +} + +message RunGUIResponse { + bool success = 1; + string error = 2; +} + +message ChangeDisplayPasswordRequest { + string password = 1; +} + +message ChangeDisplayPasswordResponse { + bool success = 1; + string error = 2; +} + +message GetDisplayConnectionResponse { + string connection = 1; + string error = 2; +} + +message CreateSnapshotRequest { + string tag = 1; +} + +message CreateSnapshotResponse { + bool success = 1; + string error = 2; +} + +message ApplySnapshotRequest { + string tag = 1; +} + +message ApplySnapshotResponse { + bool success = 1; + string error = 2; +} + +message DeleteSnapshotRequest { + string tag = 1; +} + +message DeleteSnapshotResponse { + bool success = 1; + string error = 2; +} + +message ListSnapshotsResponse { + string snapshots = 1; + string error = 2; +} + +message ForwardGuestAgentResponse { + bool should_forward = 1; +} + +message GuestAgentConnResponse { + string connection_id = 1; + string error = 2; +} + +message ConnectionData { + string connection_id = 1; + bytes data = 2; + bool close = 3; +} \ No newline at end of file From 9a9387a8cf74fd54a1f1cf622af7808a38c794ef Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Thu, 29 May 2025 22:11:03 +0530 Subject: [PATCH 21/49] driver(external): finalise proto file and generate gRPC code Signed-off-by: Ansuman Sahoo --- pkg/driver/external/driver.pb.go | 1522 ++++++++++++++++++ pkg/driver/external/{proto => }/driver.proto | 18 +- pkg/driver/external/driver_grpc.pb.go | 889 ++++++++++ 3 files changed, 2415 insertions(+), 14 deletions(-) create mode 100644 pkg/driver/external/driver.pb.go rename pkg/driver/external/{proto => }/driver.proto (90%) create mode 100644 pkg/driver/external/driver_grpc.pb.go diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go new file mode 100644 index 00000000000..662b14194e7 --- /dev/null +++ b/pkg/driver/external/driver.pb.go @@ -0,0 +1,1522 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v5.29.3 +// source: pkg/driver/external/driver.proto + +package external + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ValidateResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ValidateResponse) Reset() { + *x = ValidateResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ValidateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateResponse) ProtoMessage() {} + +func (x *ValidateResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateResponse.ProtoReflect.Descriptor instead. +func (*ValidateResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} +} + +func (x *ValidateResponse) GetValid() bool { + if x != nil { + return x.Valid + } + return false +} + +func (x *ValidateResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type InitializeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InitializeResponse) Reset() { + *x = InitializeResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InitializeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitializeResponse) ProtoMessage() {} + +func (x *InitializeResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InitializeResponse.ProtoReflect.Descriptor instead. +func (*InitializeResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} +} + +func (x *InitializeResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *InitializeResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type CreateDiskResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateDiskResponse) Reset() { + *x = CreateDiskResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateDiskResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateDiskResponse) ProtoMessage() {} + +func (x *CreateDiskResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateDiskResponse.ProtoReflect.Descriptor instead. +func (*CreateDiskResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateDiskResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *CreateDiskResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type StartResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StartResponse) Reset() { + *x = StartResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartResponse) ProtoMessage() {} + +func (x *StartResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. +func (*StartResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} +} + +func (x *StartResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *StartResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type StopResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StopResponse) Reset() { + *x = StopResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StopResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StopResponse) ProtoMessage() {} + +func (x *StopResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StopResponse.ProtoReflect.Descriptor instead. +func (*StopResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} +} + +func (x *StopResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *StopResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type RegisterResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterResponse) Reset() { + *x = RegisterResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterResponse) ProtoMessage() {} + +func (x *RegisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead. +func (*RegisterResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} +} + +func (x *RegisterResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *RegisterResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type UnregisterResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UnregisterResponse) Reset() { + *x = UnregisterResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnregisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnregisterResponse) ProtoMessage() {} + +func (x *UnregisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnregisterResponse.ProtoReflect.Descriptor instead. +func (*UnregisterResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} +} + +func (x *UnregisterResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *UnregisterResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type NameResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NameResponse) Reset() { + *x = NameResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NameResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NameResponse) ProtoMessage() {} + +func (x *NameResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NameResponse.ProtoReflect.Descriptor instead. +func (*NameResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} +} + +func (x *NameResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SetConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + InstanceConfigJson []byte `protobuf:"bytes,1,opt,name=instance_config_json,json=instanceConfigJson,proto3" json:"instance_config_json,omitempty"` + SshLocalPort int32 `protobuf:"varint,3,opt,name=ssh_local_port,json=sshLocalPort,proto3" json:"ssh_local_port,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SetConfigRequest) Reset() { + *x = SetConfigRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetConfigRequest) ProtoMessage() {} + +func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead. +func (*SetConfigRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} +} + +func (x *SetConfigRequest) GetInstanceConfigJson() []byte { + if x != nil { + return x.InstanceConfigJson + } + return nil +} + +func (x *SetConfigRequest) GetSshLocalPort() int32 { + if x != nil { + return x.SshLocalPort + } + return 0 +} + +type SetConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SetConfigResponse) Reset() { + *x = SetConfigResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetConfigResponse) ProtoMessage() {} + +func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead. +func (*SetConfigResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} +} + +func (x *SetConfigResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *SetConfigResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type GetVSockPortResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Port int32 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetVSockPortResponse) Reset() { + *x = GetVSockPortResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetVSockPortResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVSockPortResponse) ProtoMessage() {} + +func (x *GetVSockPortResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVSockPortResponse.ProtoReflect.Descriptor instead. +func (*GetVSockPortResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} +} + +func (x *GetVSockPortResponse) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +type GetVirtioPortResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Port string `protobuf:"bytes,1,opt,name=port,proto3" json:"port,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetVirtioPortResponse) Reset() { + *x = GetVirtioPortResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetVirtioPortResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVirtioPortResponse) ProtoMessage() {} + +func (x *GetVirtioPortResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVirtioPortResponse.ProtoReflect.Descriptor instead. +func (*GetVirtioPortResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{11} +} + +func (x *GetVirtioPortResponse) GetPort() string { + if x != nil { + return x.Port + } + return "" +} + +type CanRunGUIResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + CanRun bool `protobuf:"varint,1,opt,name=can_run,json=canRun,proto3" json:"can_run,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CanRunGUIResponse) Reset() { + *x = CanRunGUIResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CanRunGUIResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CanRunGUIResponse) ProtoMessage() {} + +func (x *CanRunGUIResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CanRunGUIResponse.ProtoReflect.Descriptor instead. +func (*CanRunGUIResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{12} +} + +func (x *CanRunGUIResponse) GetCanRun() bool { + if x != nil { + return x.CanRun + } + return false +} + +type RunGUIResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunGUIResponse) Reset() { + *x = RunGUIResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunGUIResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunGUIResponse) ProtoMessage() {} + +func (x *RunGUIResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunGUIResponse.ProtoReflect.Descriptor instead. +func (*RunGUIResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{13} +} + +func (x *RunGUIResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *RunGUIResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type ChangeDisplayPasswordRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ChangeDisplayPasswordRequest) Reset() { + *x = ChangeDisplayPasswordRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ChangeDisplayPasswordRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChangeDisplayPasswordRequest) ProtoMessage() {} + +func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChangeDisplayPasswordRequest.ProtoReflect.Descriptor instead. +func (*ChangeDisplayPasswordRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{14} +} + +func (x *ChangeDisplayPasswordRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type ChangeDisplayPasswordResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ChangeDisplayPasswordResponse) Reset() { + *x = ChangeDisplayPasswordResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ChangeDisplayPasswordResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChangeDisplayPasswordResponse) ProtoMessage() {} + +func (x *ChangeDisplayPasswordResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChangeDisplayPasswordResponse.ProtoReflect.Descriptor instead. +func (*ChangeDisplayPasswordResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{15} +} + +func (x *ChangeDisplayPasswordResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *ChangeDisplayPasswordResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type GetDisplayConnectionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Connection string `protobuf:"bytes,1,opt,name=connection,proto3" json:"connection,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetDisplayConnectionResponse) Reset() { + *x = GetDisplayConnectionResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetDisplayConnectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetDisplayConnectionResponse) ProtoMessage() {} + +func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetDisplayConnectionResponse.ProtoReflect.Descriptor instead. +func (*GetDisplayConnectionResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{16} +} + +func (x *GetDisplayConnectionResponse) GetConnection() string { + if x != nil { + return x.Connection + } + return "" +} + +func (x *GetDisplayConnectionResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type CreateSnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateSnapshotRequest) Reset() { + *x = CreateSnapshotRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSnapshotRequest) ProtoMessage() {} + +func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateSnapshotRequest.ProtoReflect.Descriptor instead. +func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{17} +} + +func (x *CreateSnapshotRequest) GetTag() string { + if x != nil { + return x.Tag + } + return "" +} + +type CreateSnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateSnapshotResponse) Reset() { + *x = CreateSnapshotResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSnapshotResponse) ProtoMessage() {} + +func (x *CreateSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateSnapshotResponse.ProtoReflect.Descriptor instead. +func (*CreateSnapshotResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{18} +} + +func (x *CreateSnapshotResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *CreateSnapshotResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type ApplySnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ApplySnapshotRequest) Reset() { + *x = ApplySnapshotRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ApplySnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplySnapshotRequest) ProtoMessage() {} + +func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplySnapshotRequest.ProtoReflect.Descriptor instead. +func (*ApplySnapshotRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{19} +} + +func (x *ApplySnapshotRequest) GetTag() string { + if x != nil { + return x.Tag + } + return "" +} + +type ApplySnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ApplySnapshotResponse) Reset() { + *x = ApplySnapshotResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ApplySnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplySnapshotResponse) ProtoMessage() {} + +func (x *ApplySnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplySnapshotResponse.ProtoReflect.Descriptor instead. +func (*ApplySnapshotResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{20} +} + +func (x *ApplySnapshotResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *ApplySnapshotResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type DeleteSnapshotRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteSnapshotRequest) Reset() { + *x = DeleteSnapshotRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSnapshotRequest) ProtoMessage() {} + +func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSnapshotRequest.ProtoReflect.Descriptor instead. +func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{21} +} + +func (x *DeleteSnapshotRequest) GetTag() string { + if x != nil { + return x.Tag + } + return "" +} + +type DeleteSnapshotResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteSnapshotResponse) Reset() { + *x = DeleteSnapshotResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSnapshotResponse) ProtoMessage() {} + +func (x *DeleteSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSnapshotResponse.ProtoReflect.Descriptor instead. +func (*DeleteSnapshotResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{22} +} + +func (x *DeleteSnapshotResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *DeleteSnapshotResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type ListSnapshotsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Snapshots string `protobuf:"bytes,1,opt,name=snapshots,proto3" json:"snapshots,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSnapshotsResponse) Reset() { + *x = ListSnapshotsResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSnapshotsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSnapshotsResponse) ProtoMessage() {} + +func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListSnapshotsResponse.ProtoReflect.Descriptor instead. +func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{23} +} + +func (x *ListSnapshotsResponse) GetSnapshots() string { + if x != nil { + return x.Snapshots + } + return "" +} + +func (x *ListSnapshotsResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type ForwardGuestAgentResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + ShouldForward bool `protobuf:"varint,1,opt,name=should_forward,json=shouldForward,proto3" json:"should_forward,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ForwardGuestAgentResponse) Reset() { + *x = ForwardGuestAgentResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ForwardGuestAgentResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ForwardGuestAgentResponse) ProtoMessage() {} + +func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ForwardGuestAgentResponse.ProtoReflect.Descriptor instead. +func (*ForwardGuestAgentResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{24} +} + +func (x *ForwardGuestAgentResponse) GetShouldForward() bool { + if x != nil { + return x.ShouldForward + } + return false +} + +type GuestAgentConnResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + NetConn []byte `protobuf:"bytes,1,opt,name=net_conn,json=netConn,proto3" json:"net_conn,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GuestAgentConnResponse) Reset() { + *x = GuestAgentConnResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GuestAgentConnResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GuestAgentConnResponse) ProtoMessage() {} + +func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GuestAgentConnResponse.ProtoReflect.Descriptor instead. +func (*GuestAgentConnResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{25} +} + +func (x *GuestAgentConnResponse) GetNetConn() []byte { + if x != nil { + return x.NetConn + } + return nil +} + +func (x *GuestAgentConnResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +var File_pkg_driver_external_driver_proto protoreflect.FileDescriptor + +const file_pkg_driver_external_driver_proto_rawDesc = "" + + "\n" + + " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\">\n" + + "\x10ValidateResponse\x12\x14\n" + + "\x05valid\x18\x01 \x01(\bR\x05valid\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"D\n" + + "\x12InitializeResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"D\n" + + "\x12CreateDiskResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"?\n" + + "\rStartResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\">\n" + + "\fStopResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"B\n" + + "\x10RegisterResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"D\n" + + "\x12UnregisterResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"\"\n" + + "\fNameResponse\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"j\n" + + "\x10SetConfigRequest\x120\n" + + "\x14instance_config_json\x18\x01 \x01(\fR\x12instanceConfigJson\x12$\n" + + "\x0essh_local_port\x18\x03 \x01(\x05R\fsshLocalPort\"C\n" + + "\x11SetConfigResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"*\n" + + "\x14GetVSockPortResponse\x12\x12\n" + + "\x04port\x18\x01 \x01(\x05R\x04port\"+\n" + + "\x15GetVirtioPortResponse\x12\x12\n" + + "\x04port\x18\x01 \x01(\tR\x04port\",\n" + + "\x11CanRunGUIResponse\x12\x17\n" + + "\acan_run\x18\x01 \x01(\bR\x06canRun\"@\n" + + "\x0eRunGUIResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\":\n" + + "\x1cChangeDisplayPasswordRequest\x12\x1a\n" + + "\bpassword\x18\x01 \x01(\tR\bpassword\"O\n" + + "\x1dChangeDisplayPasswordResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"T\n" + + "\x1cGetDisplayConnectionResponse\x12\x1e\n" + + "\n" + + "connection\x18\x01 \x01(\tR\n" + + "connection\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\")\n" + + "\x15CreateSnapshotRequest\x12\x10\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\"H\n" + + "\x16CreateSnapshotResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"(\n" + + "\x14ApplySnapshotRequest\x12\x10\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\"G\n" + + "\x15ApplySnapshotResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\")\n" + + "\x15DeleteSnapshotRequest\x12\x10\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\"H\n" + + "\x16DeleteSnapshotResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"K\n" + + "\x15ListSnapshotsResponse\x12\x1c\n" + + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"B\n" + + "\x19ForwardGuestAgentResponse\x12%\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"I\n" + + "\x16GuestAgentConnResponse\x12\x19\n" + + "\bnet_conn\x18\x01 \x01(\fR\anetConn\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error2\x94\n" + + "\n" + + "\x06Driver\x125\n" + + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x11.ValidateResponse\x129\n" + + "\n" + + "Initialize\x12\x16.google.protobuf.Empty\x1a\x13.InitializeResponse\x129\n" + + "\n" + + "CreateDisk\x12\x16.google.protobuf.Empty\x1a\x13.CreateDiskResponse\x121\n" + + "\x05Start\x12\x16.google.protobuf.Empty\x1a\x0e.StartResponse0\x01\x12-\n" + + "\x04Stop\x12\x16.google.protobuf.Empty\x1a\r.StopResponse\x127\n" + + "\tCanRunGUI\x12\x16.google.protobuf.Empty\x1a\x12.CanRunGUIResponse\x121\n" + + "\x06RunGUI\x12\x16.google.protobuf.Empty\x1a\x0f.RunGUIResponse\x12V\n" + + "\x15ChangeDisplayPassword\x12\x1d.ChangeDisplayPasswordRequest\x1a\x1e.ChangeDisplayPasswordResponse\x12M\n" + + "\x14GetDisplayConnection\x12\x16.google.protobuf.Empty\x1a\x1d.GetDisplayConnectionResponse\x12A\n" + + "\x0eCreateSnapshot\x12\x16.CreateSnapshotRequest\x1a\x17.CreateSnapshotResponse\x12>\n" + + "\rApplySnapshot\x12\x15.ApplySnapshotRequest\x1a\x16.ApplySnapshotResponse\x12A\n" + + "\x0eDeleteSnapshot\x12\x16.DeleteSnapshotRequest\x1a\x17.DeleteSnapshotResponse\x12?\n" + + "\rListSnapshots\x12\x16.google.protobuf.Empty\x1a\x16.ListSnapshotsResponse\x125\n" + + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x11.RegisterResponse\x129\n" + + "\n" + + "Unregister\x12\x16.google.protobuf.Empty\x1a\x13.UnregisterResponse\x12G\n" + + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12C\n" + + "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse0\x01\x12-\n" + + "\x04Name\x12\x16.google.protobuf.Empty\x1a\r.NameResponse\x122\n" + + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x12.SetConfigResponse\x12=\n" + + "\fGetVSockPort\x12\x16.google.protobuf.Empty\x1a\x15.GetVSockPortResponse\x12?\n" + + "\rGetVirtioPort\x12\x16.google.protobuf.Empty\x1a\x16.GetVirtioPortResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" + +var ( + file_pkg_driver_external_driver_proto_rawDescOnce sync.Once + file_pkg_driver_external_driver_proto_rawDescData []byte +) + +func file_pkg_driver_external_driver_proto_rawDescGZIP() []byte { + file_pkg_driver_external_driver_proto_rawDescOnce.Do(func() { + file_pkg_driver_external_driver_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc))) + }) + return file_pkg_driver_external_driver_proto_rawDescData +} + +var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 26) +var file_pkg_driver_external_driver_proto_goTypes = []any{ + (*ValidateResponse)(nil), // 0: ValidateResponse + (*InitializeResponse)(nil), // 1: InitializeResponse + (*CreateDiskResponse)(nil), // 2: CreateDiskResponse + (*StartResponse)(nil), // 3: StartResponse + (*StopResponse)(nil), // 4: StopResponse + (*RegisterResponse)(nil), // 5: RegisterResponse + (*UnregisterResponse)(nil), // 6: UnregisterResponse + (*NameResponse)(nil), // 7: NameResponse + (*SetConfigRequest)(nil), // 8: SetConfigRequest + (*SetConfigResponse)(nil), // 9: SetConfigResponse + (*GetVSockPortResponse)(nil), // 10: GetVSockPortResponse + (*GetVirtioPortResponse)(nil), // 11: GetVirtioPortResponse + (*CanRunGUIResponse)(nil), // 12: CanRunGUIResponse + (*RunGUIResponse)(nil), // 13: RunGUIResponse + (*ChangeDisplayPasswordRequest)(nil), // 14: ChangeDisplayPasswordRequest + (*ChangeDisplayPasswordResponse)(nil), // 15: ChangeDisplayPasswordResponse + (*GetDisplayConnectionResponse)(nil), // 16: GetDisplayConnectionResponse + (*CreateSnapshotRequest)(nil), // 17: CreateSnapshotRequest + (*CreateSnapshotResponse)(nil), // 18: CreateSnapshotResponse + (*ApplySnapshotRequest)(nil), // 19: ApplySnapshotRequest + (*ApplySnapshotResponse)(nil), // 20: ApplySnapshotResponse + (*DeleteSnapshotRequest)(nil), // 21: DeleteSnapshotRequest + (*DeleteSnapshotResponse)(nil), // 22: DeleteSnapshotResponse + (*ListSnapshotsResponse)(nil), // 23: ListSnapshotsResponse + (*ForwardGuestAgentResponse)(nil), // 24: ForwardGuestAgentResponse + (*GuestAgentConnResponse)(nil), // 25: GuestAgentConnResponse + (*emptypb.Empty)(nil), // 26: google.protobuf.Empty +} +var file_pkg_driver_external_driver_proto_depIdxs = []int32{ + 26, // 0: Driver.Validate:input_type -> google.protobuf.Empty + 26, // 1: Driver.Initialize:input_type -> google.protobuf.Empty + 26, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty + 26, // 3: Driver.Start:input_type -> google.protobuf.Empty + 26, // 4: Driver.Stop:input_type -> google.protobuf.Empty + 26, // 5: Driver.CanRunGUI:input_type -> google.protobuf.Empty + 26, // 6: Driver.RunGUI:input_type -> google.protobuf.Empty + 14, // 7: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest + 26, // 8: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty + 17, // 9: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest + 19, // 10: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest + 21, // 11: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest + 26, // 12: Driver.ListSnapshots:input_type -> google.protobuf.Empty + 26, // 13: Driver.Register:input_type -> google.protobuf.Empty + 26, // 14: Driver.Unregister:input_type -> google.protobuf.Empty + 26, // 15: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty + 26, // 16: Driver.GuestAgentConn:input_type -> google.protobuf.Empty + 26, // 17: Driver.Name:input_type -> google.protobuf.Empty + 8, // 18: Driver.SetConfig:input_type -> SetConfigRequest + 26, // 19: Driver.GetVSockPort:input_type -> google.protobuf.Empty + 26, // 20: Driver.GetVirtioPort:input_type -> google.protobuf.Empty + 0, // 21: Driver.Validate:output_type -> ValidateResponse + 1, // 22: Driver.Initialize:output_type -> InitializeResponse + 2, // 23: Driver.CreateDisk:output_type -> CreateDiskResponse + 3, // 24: Driver.Start:output_type -> StartResponse + 4, // 25: Driver.Stop:output_type -> StopResponse + 12, // 26: Driver.CanRunGUI:output_type -> CanRunGUIResponse + 13, // 27: Driver.RunGUI:output_type -> RunGUIResponse + 15, // 28: Driver.ChangeDisplayPassword:output_type -> ChangeDisplayPasswordResponse + 16, // 29: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse + 18, // 30: Driver.CreateSnapshot:output_type -> CreateSnapshotResponse + 20, // 31: Driver.ApplySnapshot:output_type -> ApplySnapshotResponse + 22, // 32: Driver.DeleteSnapshot:output_type -> DeleteSnapshotResponse + 23, // 33: Driver.ListSnapshots:output_type -> ListSnapshotsResponse + 5, // 34: Driver.Register:output_type -> RegisterResponse + 6, // 35: Driver.Unregister:output_type -> UnregisterResponse + 24, // 36: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse + 25, // 37: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse + 7, // 38: Driver.Name:output_type -> NameResponse + 9, // 39: Driver.SetConfig:output_type -> SetConfigResponse + 10, // 40: Driver.GetVSockPort:output_type -> GetVSockPortResponse + 11, // 41: Driver.GetVirtioPort:output_type -> GetVirtioPortResponse + 21, // [21:42] is the sub-list for method output_type + 0, // [0:21] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pkg_driver_external_driver_proto_init() } +func file_pkg_driver_external_driver_proto_init() { + if File_pkg_driver_external_driver_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc)), + NumEnums: 0, + NumMessages: 26, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_pkg_driver_external_driver_proto_goTypes, + DependencyIndexes: file_pkg_driver_external_driver_proto_depIdxs, + MessageInfos: file_pkg_driver_external_driver_proto_msgTypes, + }.Build() + File_pkg_driver_external_driver_proto = out.File + file_pkg_driver_external_driver_proto_goTypes = nil + file_pkg_driver_external_driver_proto_depIdxs = nil +} diff --git a/pkg/driver/external/proto/driver.proto b/pkg/driver/external/driver.proto similarity index 90% rename from pkg/driver/external/proto/driver.proto rename to pkg/driver/external/driver.proto index 909cbfd657b..86898e8250a 100644 --- a/pkg/driver/external/proto/driver.proto +++ b/pkg/driver/external/driver.proto @@ -1,10 +1,6 @@ -// [WIP]: Please do not review this file yet. - syntax = "proto3"; -package driver; - -option go_package = "github.com/lima-vm/lima/pkg/driver/external/proto"; +option go_package = "github.com/lima-vm/lima/pkg/driver/external"; import "google/protobuf/empty.proto"; @@ -12,7 +8,7 @@ service Driver { rpc Validate(google.protobuf.Empty) returns (ValidateResponse); rpc Initialize(google.protobuf.Empty) returns (InitializeResponse); rpc CreateDisk(google.protobuf.Empty) returns (CreateDiskResponse); - rpc Start(google.protobuf.Empty) returns (StartResponse); + rpc Start(google.protobuf.Empty) returns (stream StartResponse); rpc Stop(google.protobuf.Empty) returns (StopResponse); rpc CanRunGUI(google.protobuf.Empty) returns (CanRunGUIResponse); @@ -29,7 +25,7 @@ service Driver { rpc Unregister(google.protobuf.Empty) returns (UnregisterResponse); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); - rpc GuestAgentConn(google.protobuf.Empty) returns (GuestAgentConnResponse); + rpc GuestAgentConn(google.protobuf.Empty) returns (stream GuestAgentConnResponse); rpc Name(google.protobuf.Empty) returns (NameResponse); rpc SetConfig(SetConfigRequest) returns (SetConfigResponse); @@ -155,12 +151,6 @@ message ForwardGuestAgentResponse { } message GuestAgentConnResponse { - string connection_id = 1; + bytes net_conn = 1; string error = 2; -} - -message ConnectionData { - string connection_id = 1; - bytes data = 2; - bool close = 3; } \ No newline at end of file diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go new file mode 100644 index 00000000000..0ec8bd21df9 --- /dev/null +++ b/pkg/driver/external/driver_grpc.pb.go @@ -0,0 +1,889 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.29.3 +// source: pkg/driver/external/driver.proto + +package external + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Driver_Validate_FullMethodName = "/Driver/Validate" + Driver_Initialize_FullMethodName = "/Driver/Initialize" + Driver_CreateDisk_FullMethodName = "/Driver/CreateDisk" + Driver_Start_FullMethodName = "/Driver/Start" + Driver_Stop_FullMethodName = "/Driver/Stop" + Driver_CanRunGUI_FullMethodName = "/Driver/CanRunGUI" + Driver_RunGUI_FullMethodName = "/Driver/RunGUI" + Driver_ChangeDisplayPassword_FullMethodName = "/Driver/ChangeDisplayPassword" + Driver_GetDisplayConnection_FullMethodName = "/Driver/GetDisplayConnection" + Driver_CreateSnapshot_FullMethodName = "/Driver/CreateSnapshot" + Driver_ApplySnapshot_FullMethodName = "/Driver/ApplySnapshot" + Driver_DeleteSnapshot_FullMethodName = "/Driver/DeleteSnapshot" + Driver_ListSnapshots_FullMethodName = "/Driver/ListSnapshots" + Driver_Register_FullMethodName = "/Driver/Register" + Driver_Unregister_FullMethodName = "/Driver/Unregister" + Driver_ForwardGuestAgent_FullMethodName = "/Driver/ForwardGuestAgent" + Driver_GuestAgentConn_FullMethodName = "/Driver/GuestAgentConn" + Driver_Name_FullMethodName = "/Driver/Name" + Driver_SetConfig_FullMethodName = "/Driver/SetConfig" + Driver_GetVSockPort_FullMethodName = "/Driver/GetVSockPort" + Driver_GetVirtioPort_FullMethodName = "/Driver/GetVirtioPort" +) + +// DriverClient is the client API for Driver service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type DriverClient interface { + Validate(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ValidateResponse, error) + Initialize(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InitializeResponse, error) + CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateDiskResponse, error) + Start(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StartResponse], error) + Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StopResponse, error) + CanRunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CanRunGUIResponse, error) + RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RunGUIResponse, error) + ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*ChangeDisplayPasswordResponse, error) + GetDisplayConnection(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetDisplayConnectionResponse, error) + CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) + ApplySnapshot(ctx context.Context, in *ApplySnapshotRequest, opts ...grpc.CallOption) (*ApplySnapshotResponse, error) + DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*DeleteSnapshotResponse, error) + ListSnapshots(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) + Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RegisterResponse, error) + Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*UnregisterResponse, error) + ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) + GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GuestAgentConnResponse], error) + Name(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NameResponse, error) + SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) + GetVSockPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVSockPortResponse, error) + GetVirtioPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVirtioPortResponse, error) +} + +type driverClient struct { + cc grpc.ClientConnInterface +} + +func NewDriverClient(cc grpc.ClientConnInterface) DriverClient { + return &driverClient{cc} +} + +func (c *driverClient) Validate(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ValidateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ValidateResponse) + err := c.cc.Invoke(ctx, Driver_Validate_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) Initialize(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InitializeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(InitializeResponse) + err := c.cc.Invoke(ctx, Driver_Initialize_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateDiskResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateDiskResponse) + err := c.cc.Invoke(ctx, Driver_CreateDisk_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) Start(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StartResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &Driver_ServiceDesc.Streams[0], Driver_Start_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[emptypb.Empty, StartResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type Driver_StartClient = grpc.ServerStreamingClient[StartResponse] + +func (c *driverClient) Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StopResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(StopResponse) + err := c.cc.Invoke(ctx, Driver_Stop_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) CanRunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CanRunGUIResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CanRunGUIResponse) + err := c.cc.Invoke(ctx, Driver_CanRunGUI_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RunGUIResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RunGUIResponse) + err := c.cc.Invoke(ctx, Driver_RunGUI_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*ChangeDisplayPasswordResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ChangeDisplayPasswordResponse) + err := c.cc.Invoke(ctx, Driver_ChangeDisplayPassword_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) GetDisplayConnection(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetDisplayConnectionResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetDisplayConnectionResponse) + err := c.cc.Invoke(ctx, Driver_GetDisplayConnection_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateSnapshotResponse) + err := c.cc.Invoke(ctx, Driver_CreateSnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) ApplySnapshot(ctx context.Context, in *ApplySnapshotRequest, opts ...grpc.CallOption) (*ApplySnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ApplySnapshotResponse) + err := c.cc.Invoke(ctx, Driver_ApplySnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*DeleteSnapshotResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteSnapshotResponse) + err := c.cc.Invoke(ctx, Driver_DeleteSnapshot_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) ListSnapshots(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListSnapshotsResponse) + err := c.cc.Invoke(ctx, Driver_ListSnapshots_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RegisterResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RegisterResponse) + err := c.cc.Invoke(ctx, Driver_Register_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*UnregisterResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UnregisterResponse) + err := c.cc.Invoke(ctx, Driver_Unregister_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ForwardGuestAgentResponse) + err := c.cc.Invoke(ctx, Driver_ForwardGuestAgent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GuestAgentConnResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &Driver_ServiceDesc.Streams[1], Driver_GuestAgentConn_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[emptypb.Empty, GuestAgentConnResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type Driver_GuestAgentConnClient = grpc.ServerStreamingClient[GuestAgentConnResponse] + +func (c *driverClient) Name(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NameResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(NameResponse) + err := c.cc.Invoke(ctx, Driver_Name_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SetConfigResponse) + err := c.cc.Invoke(ctx, Driver_SetConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) GetVSockPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVSockPortResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetVSockPortResponse) + err := c.cc.Invoke(ctx, Driver_GetVSockPort_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverClient) GetVirtioPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVirtioPortResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetVirtioPortResponse) + err := c.cc.Invoke(ctx, Driver_GetVirtioPort_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// DriverServer is the server API for Driver service. +// All implementations must embed UnimplementedDriverServer +// for forward compatibility. +type DriverServer interface { + Validate(context.Context, *emptypb.Empty) (*ValidateResponse, error) + Initialize(context.Context, *emptypb.Empty) (*InitializeResponse, error) + CreateDisk(context.Context, *emptypb.Empty) (*CreateDiskResponse, error) + Start(*emptypb.Empty, grpc.ServerStreamingServer[StartResponse]) error + Stop(context.Context, *emptypb.Empty) (*StopResponse, error) + CanRunGUI(context.Context, *emptypb.Empty) (*CanRunGUIResponse, error) + RunGUI(context.Context, *emptypb.Empty) (*RunGUIResponse, error) + ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*ChangeDisplayPasswordResponse, error) + GetDisplayConnection(context.Context, *emptypb.Empty) (*GetDisplayConnectionResponse, error) + CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) + ApplySnapshot(context.Context, *ApplySnapshotRequest) (*ApplySnapshotResponse, error) + DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error) + ListSnapshots(context.Context, *emptypb.Empty) (*ListSnapshotsResponse, error) + Register(context.Context, *emptypb.Empty) (*RegisterResponse, error) + Unregister(context.Context, *emptypb.Empty) (*UnregisterResponse, error) + ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) + GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error + Name(context.Context, *emptypb.Empty) (*NameResponse, error) + SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) + GetVSockPort(context.Context, *emptypb.Empty) (*GetVSockPortResponse, error) + GetVirtioPort(context.Context, *emptypb.Empty) (*GetVirtioPortResponse, error) + mustEmbedUnimplementedDriverServer() +} + +// UnimplementedDriverServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedDriverServer struct{} + +func (UnimplementedDriverServer) Validate(context.Context, *emptypb.Empty) (*ValidateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Validate not implemented") +} +func (UnimplementedDriverServer) Initialize(context.Context, *emptypb.Empty) (*InitializeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Initialize not implemented") +} +func (UnimplementedDriverServer) CreateDisk(context.Context, *emptypb.Empty) (*CreateDiskResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateDisk not implemented") +} +func (UnimplementedDriverServer) Start(*emptypb.Empty, grpc.ServerStreamingServer[StartResponse]) error { + return status.Errorf(codes.Unimplemented, "method Start not implemented") +} +func (UnimplementedDriverServer) Stop(context.Context, *emptypb.Empty) (*StopResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented") +} +func (UnimplementedDriverServer) CanRunGUI(context.Context, *emptypb.Empty) (*CanRunGUIResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CanRunGUI not implemented") +} +func (UnimplementedDriverServer) RunGUI(context.Context, *emptypb.Empty) (*RunGUIResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RunGUI not implemented") +} +func (UnimplementedDriverServer) ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*ChangeDisplayPasswordResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ChangeDisplayPassword not implemented") +} +func (UnimplementedDriverServer) GetDisplayConnection(context.Context, *emptypb.Empty) (*GetDisplayConnectionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetDisplayConnection not implemented") +} +func (UnimplementedDriverServer) CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateSnapshot not implemented") +} +func (UnimplementedDriverServer) ApplySnapshot(context.Context, *ApplySnapshotRequest) (*ApplySnapshotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshot not implemented") +} +func (UnimplementedDriverServer) DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteSnapshot not implemented") +} +func (UnimplementedDriverServer) ListSnapshots(context.Context, *emptypb.Empty) (*ListSnapshotsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") +} +func (UnimplementedDriverServer) Register(context.Context, *emptypb.Empty) (*RegisterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") +} +func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*UnregisterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Unregister not implemented") +} +func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ForwardGuestAgent not implemented") +} +func (UnimplementedDriverServer) GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error { + return status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") +} +func (UnimplementedDriverServer) Name(context.Context, *emptypb.Empty) (*NameResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Name not implemented") +} +func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetConfig not implemented") +} +func (UnimplementedDriverServer) GetVSockPort(context.Context, *emptypb.Empty) (*GetVSockPortResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVSockPort not implemented") +} +func (UnimplementedDriverServer) GetVirtioPort(context.Context, *emptypb.Empty) (*GetVirtioPortResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVirtioPort not implemented") +} +func (UnimplementedDriverServer) mustEmbedUnimplementedDriverServer() {} +func (UnimplementedDriverServer) testEmbeddedByValue() {} + +// UnsafeDriverServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to DriverServer will +// result in compilation errors. +type UnsafeDriverServer interface { + mustEmbedUnimplementedDriverServer() +} + +func RegisterDriverServer(s grpc.ServiceRegistrar, srv DriverServer) { + // If the following call pancis, it indicates UnimplementedDriverServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Driver_ServiceDesc, srv) +} + +func _Driver_Validate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).Validate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_Validate_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).Validate(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_Initialize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).Initialize(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_Initialize_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).Initialize(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_CreateDisk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).CreateDisk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_CreateDisk_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).CreateDisk(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_Start_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(emptypb.Empty) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(DriverServer).Start(m, &grpc.GenericServerStream[emptypb.Empty, StartResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type Driver_StartServer = grpc.ServerStreamingServer[StartResponse] + +func _Driver_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).Stop(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_Stop_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).Stop(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_CanRunGUI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).CanRunGUI(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_CanRunGUI_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).CanRunGUI(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_RunGUI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).RunGUI(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_RunGUI_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).RunGUI(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_ChangeDisplayPassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ChangeDisplayPasswordRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).ChangeDisplayPassword(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_ChangeDisplayPassword_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).ChangeDisplayPassword(ctx, req.(*ChangeDisplayPasswordRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_GetDisplayConnection_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).GetDisplayConnection(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_GetDisplayConnection_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).GetDisplayConnection(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_CreateSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).CreateSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_CreateSnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).CreateSnapshot(ctx, req.(*CreateSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_ApplySnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ApplySnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).ApplySnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_ApplySnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).ApplySnapshot(ctx, req.(*ApplySnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_DeleteSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).DeleteSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_DeleteSnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).DeleteSnapshot(ctx, req.(*DeleteSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_ListSnapshots_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).ListSnapshots(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).Register(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_Register_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).Register(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_Unregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).Unregister(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_Unregister_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).Unregister(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_ForwardGuestAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).ForwardGuestAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_ForwardGuestAgent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).ForwardGuestAgent(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_GuestAgentConn_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(emptypb.Empty) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(DriverServer).GuestAgentConn(m, &grpc.GenericServerStream[emptypb.Empty, GuestAgentConnResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type Driver_GuestAgentConnServer = grpc.ServerStreamingServer[GuestAgentConnResponse] + +func _Driver_Name_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).Name(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_Name_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).Name(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).SetConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_SetConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).SetConfig(ctx, req.(*SetConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_GetVSockPort_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).GetVSockPort(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_GetVSockPort_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).GetVSockPort(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Driver_GetVirtioPort_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).GetVirtioPort(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_GetVirtioPort_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).GetVirtioPort(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +// Driver_ServiceDesc is the grpc.ServiceDesc for Driver service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Driver_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Driver", + HandlerType: (*DriverServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Validate", + Handler: _Driver_Validate_Handler, + }, + { + MethodName: "Initialize", + Handler: _Driver_Initialize_Handler, + }, + { + MethodName: "CreateDisk", + Handler: _Driver_CreateDisk_Handler, + }, + { + MethodName: "Stop", + Handler: _Driver_Stop_Handler, + }, + { + MethodName: "CanRunGUI", + Handler: _Driver_CanRunGUI_Handler, + }, + { + MethodName: "RunGUI", + Handler: _Driver_RunGUI_Handler, + }, + { + MethodName: "ChangeDisplayPassword", + Handler: _Driver_ChangeDisplayPassword_Handler, + }, + { + MethodName: "GetDisplayConnection", + Handler: _Driver_GetDisplayConnection_Handler, + }, + { + MethodName: "CreateSnapshot", + Handler: _Driver_CreateSnapshot_Handler, + }, + { + MethodName: "ApplySnapshot", + Handler: _Driver_ApplySnapshot_Handler, + }, + { + MethodName: "DeleteSnapshot", + Handler: _Driver_DeleteSnapshot_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _Driver_ListSnapshots_Handler, + }, + { + MethodName: "Register", + Handler: _Driver_Register_Handler, + }, + { + MethodName: "Unregister", + Handler: _Driver_Unregister_Handler, + }, + { + MethodName: "ForwardGuestAgent", + Handler: _Driver_ForwardGuestAgent_Handler, + }, + { + MethodName: "Name", + Handler: _Driver_Name_Handler, + }, + { + MethodName: "SetConfig", + Handler: _Driver_SetConfig_Handler, + }, + { + MethodName: "GetVSockPort", + Handler: _Driver_GetVSockPort_Handler, + }, + { + MethodName: "GetVirtioPort", + Handler: _Driver_GetVirtioPort_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Start", + Handler: _Driver_Start_Handler, + ServerStreams: true, + }, + { + StreamName: "GuestAgentConn", + Handler: _Driver_GuestAgentConn_Handler, + ServerStreams: true, + }, + }, + Metadata: "pkg/driver/external/driver.proto", +} From 0f4687296ee4f23fed8cd72454b8c5d8eb5156e2 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Thu, 29 May 2025 22:11:43 +0530 Subject: [PATCH 22/49] driver(external): implement server defination Signed-off-by: Ansuman Sahoo --- pkg/driver/external/server.go | 164 ++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 pkg/driver/external/server.go diff --git a/pkg/driver/external/server.go b/pkg/driver/external/server.go new file mode 100644 index 00000000000..73fcb3eb316 --- /dev/null +++ b/pkg/driver/external/server.go @@ -0,0 +1,164 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package external + +import ( + "io" + "net" + "os" + "os/signal" + "sync" + "syscall" + "time" + + "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" + + "github.com/lima-vm/lima/pkg/driver" +) + +type Server struct { + UnimplementedDriverServer + driver driver.Driver + logger *logrus.Logger +} + +func Serve(driver driver.Driver) { + logger := logrus.New() + logger.SetLevel(logrus.DebugLevel) + logger.SetFormatter(&logrus.TextFormatter{ + FullTimestamp: true, + }) + logger.Infof("Starting external driver server for %s", driver.Name()) + + pipeConn := &PipeConn{ + Reader: os.Stdin, + Writer: os.Stdout, + } + + listener := NewPipeListener(pipeConn) + + kaProps := keepalive.ServerParameters{ + Time: 10 * time.Second, + Timeout: 20 * time.Second, + } + + kaPolicy := keepalive.EnforcementPolicy{ + MinTime: 2 * time.Second, + PermitWithoutStream: true, + } + + server := grpc.NewServer( + grpc.KeepaliveParams(kaProps), + grpc.KeepaliveEnforcementPolicy(kaPolicy), + ) + + RegisterDriverServer(server, &Server{ + driver: driver, + logger: logger, + }) + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + go func() { + <-sigs + logger.Info("Received shutdown signal, stopping server...") + server.Stop() + os.Exit(0) + }() + + logger.Info("Server starting...") + if err := server.Serve(listener); err != nil { + logger.Fatalf("Failed to serve: %v", err) + } +} + +type PipeConn struct { + Reader io.Reader + Writer io.Writer +} + +func (p *PipeConn) Read(b []byte) (n int, err error) { + return p.Reader.Read(b) +} + +func (p *PipeConn) Write(b []byte) (n int, err error) { + return p.Writer.Write(b) +} + +func (p *PipeConn) Close() error { + return nil +} + +func (p *PipeConn) LocalAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) RemoteAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) SetDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetReadDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetWriteDeadline(t time.Time) error { + return nil +} + +type pipeAddr struct{} + +func (pipeAddr) Network() string { return "pipe" } +func (pipeAddr) String() string { return "pipe" } + +type PipeListener struct { + conn net.Conn + connSent bool + mu sync.Mutex + closed bool +} + +func NewPipeListener(conn net.Conn) *PipeListener { + return &PipeListener{ + conn: conn, + connSent: false, + closed: false, + } +} + +func (l *PipeListener) Accept() (net.Conn, error) { + l.mu.Lock() + defer l.mu.Unlock() + + if l.closed { + return nil, net.ErrClosed + } + + if l.connSent { + select {} + } + + l.connSent = true + return l.conn, nil +} + +func (l *PipeListener) Close() error { + l.mu.Lock() + defer l.mu.Unlock() + + if !l.closed { + l.closed = true + } + return nil +} + +func (l *PipeListener) Addr() net.Addr { + return pipeAddr{} +} From 5979bf3093e2212421f21b3d6e7ec24bc17c016c Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 30 May 2025 22:29:24 +0530 Subject: [PATCH 23/49] driver(external): implement the grpc client and server Signed-off-by: Ansuman Sahoo --- pkg/driver/external/client/client.go | 116 ++++++++++++++++ pkg/driver/external/server/methods.go | 185 ++++++++++++++++++++++++++ pkg/driver/external/server/pipe.go | 98 ++++++++++++++ pkg/driver/external/server/server.go | 75 +++++++++++ 4 files changed, 474 insertions(+) create mode 100644 pkg/driver/external/client/client.go create mode 100644 pkg/driver/external/server/methods.go create mode 100644 pkg/driver/external/server/pipe.go create mode 100644 pkg/driver/external/server/server.go diff --git a/pkg/driver/external/client/client.go b/pkg/driver/external/client/client.go new file mode 100644 index 00000000000..cd07e3c418d --- /dev/null +++ b/pkg/driver/external/client/client.go @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "context" + "io" + "math" + "net" + "time" + + pb "github.com/lima-vm/lima/pkg/driver/external" + "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" +) + +type DriverClient struct { + Stdin io.WriteCloser + Stdout io.ReadCloser + Conn *grpc.ClientConn + DriverSvc pb.DriverClient + logger *logrus.Logger +} + +func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus.Logger) (*DriverClient, error) { + pipeConn := &PipeConn{ + Reader: stdout, + Writer: stdin, + } + + opts := []grpc.DialOption{ + grpc.WithDefaultCallOptions( + grpc.MaxCallRecvMsgSize(math.MaxInt64), + grpc.MaxCallSendMsgSize(math.MaxInt64), + ), + grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { + return pipeConn, nil + }), + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithKeepaliveParams(keepalive.ClientParameters{ + Time: 10 * time.Second, + Timeout: 20 * time.Second, + PermitWithoutStream: true, + }), + } + + conn, err := grpc.NewClient("pipe://", opts...) + if err != nil { + logger.Errorf("failed to create gRPC driver client connection: %v", err) + return nil, err + } + + driverSvc := pb.NewDriverClient(conn) + + return &DriverClient{ + Stdin: stdin, + Stdout: stdout, + Conn: conn, + DriverSvc: driverSvc, + logger: logger, + }, nil +} + +type PipeConn struct { + Reader io.Reader + Writer io.Writer +} + +func (p *PipeConn) Read(b []byte) (n int, err error) { + return p.Reader.Read(b) +} + +func (p *PipeConn) Write(b []byte) (n int, err error) { + return p.Writer.Write(b) +} + +func (p *PipeConn) Close() error { + var err error + if closer, ok := p.Reader.(io.Closer); ok { + err = closer.Close() + } + if closer, ok := p.Writer.(io.Closer); ok { + if closeErr := closer.Close(); closeErr != nil && err == nil { + err = closeErr + } + } + return err +} + +func (p *PipeConn) LocalAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) RemoteAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) SetDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetReadDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetWriteDeadline(t time.Time) error { + return nil +} + +type pipeAddr struct{} + +func (pipeAddr) Network() string { return "pipe" } +func (pipeAddr) String() string { return "pipe" } diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go new file mode 100644 index 00000000000..d0c04378a9a --- /dev/null +++ b/pkg/driver/external/server/methods.go @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package server + +import ( + "context" + + pb "github.com/lima-vm/lima/pkg/driver/external" + "google.golang.org/protobuf/types/known/emptypb" +) + +// TODO: Add more 3 functions Start, SetConfig & GuestAgentConn + +func (s *DriverServer) Name(ctx context.Context, empty *emptypb.Empty) (*pb.NameResponse, error) { + s.logger.Debug("Received Name request") + return &pb.NameResponse{Name: s.driver.Name()}, nil +} + +func (s *DriverServer) GetVirtioPort(ctx context.Context, empty *emptypb.Empty) (*pb.GetVirtioPortResponse, error) { + s.logger.Debug("Received GetVirtioPort request") + return &pb.GetVirtioPortResponse{ + Port: s.driver.GetVirtioPort(), + }, nil +} + +func (s *DriverServer) GetVSockPort(ctx context.Context, empty *emptypb.Empty) (*pb.GetVSockPortResponse, error) { + s.logger.Debug("Received GetVSockPort request") + return &pb.GetVSockPortResponse{ + Port: int64(s.driver.GetVSockPort()), + }, nil +} + +func (s *DriverServer) Validate(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debugf("Received Validate request") + err := s.driver.Validate() + if err != nil { + s.logger.Errorf("Validation failed: %v", err) + return empty, err + } + s.logger.Debug("Validation succeeded") + return empty, nil +} + +func (s *DriverServer) Initialize(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debug("Received Initialize request") + err := s.driver.Initialize(ctx) + if err != nil { + s.logger.Errorf("Initialization failed: %v", err) + return empty, err + } + s.logger.Debug("Initialization succeeded") + return empty, nil +} + +func (s *DriverServer) CreateDisk(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debug("Received CreateDisk request") + err := s.driver.CreateDisk(ctx) + if err != nil { + s.logger.Errorf("CreateDisk failed: %v", err) + return empty, err + } + s.logger.Debug("CreateDisk succeeded") + return empty, nil +} + +func (s *DriverServer) Stop(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debug("Received Stop request") + err := s.driver.Stop(ctx) + if err != nil { + s.logger.Errorf("Stop failed: %v", err) + return empty, err + } + s.logger.Debug("Stop succeeded") + return empty, nil +} + +func (s *DriverServer) CanRunGUI(ctx context.Context, empty *emptypb.Empty) (*pb.CanRunGUIResponse, error) { + s.logger.Debug("Received CanRunGUI request") + return &pb.CanRunGUIResponse{CanRun: s.driver.CanRunGUI()}, nil +} + +func (s *DriverServer) RunGUI(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debug("Received RunGUI request") + err := s.driver.RunGUI() + if err != nil { + s.logger.Errorf("RunGUI failed: %v", err) + return empty, err + } + s.logger.Debug("RunGUI succeeded") + return empty, nil +} + +func (s *DriverServer) ChangeDisplayPassword(ctx context.Context, req *pb.ChangeDisplayPasswordRequest) (*emptypb.Empty, error) { + s.logger.Debug("Received ChangeDisplayPassword request") + err := s.driver.ChangeDisplayPassword(ctx, req.Password) + if err != nil { + s.logger.Errorf("ChangeDisplayPassword failed: %v", err) + return &emptypb.Empty{}, err + } + s.logger.Debug("ChangeDisplayPassword succeeded") + return &emptypb.Empty{}, nil +} + +func (s *DriverServer) GetDisplayConnection(ctx context.Context, empty *emptypb.Empty) (*pb.GetDisplayConnectionResponse, error) { + s.logger.Debug("Received GetDisplayConnection request") + conn, err := s.driver.GetDisplayConnection(ctx) + if err != nil { + s.logger.Errorf("GetDisplayConnection failed: %v", err) + return nil, err + } + s.logger.Debug("GetDisplayConnection succeeded") + return &pb.GetDisplayConnectionResponse{Connection: conn}, nil +} + +func (s *DriverServer) CreateSnapshot(ctx context.Context, req *pb.CreateSnapshotRequest) (*emptypb.Empty, error) { + s.logger.Debugf("Received CreateSnapshot request with tag: %s", req.Tag) + err := s.driver.CreateSnapshot(ctx, req.Tag) + if err != nil { + s.logger.Errorf("CreateSnapshot failed: %v", err) + return &emptypb.Empty{}, err + } + s.logger.Debug("CreateSnapshot succeeded") + return &emptypb.Empty{}, nil +} + +func (s *DriverServer) ApplySnapshot(ctx context.Context, req *pb.ApplySnapshotRequest) (*emptypb.Empty, error) { + s.logger.Debugf("Received ApplySnapshot request with tag: %s", req.Tag) + err := s.driver.ApplySnapshot(ctx, req.Tag) + if err != nil { + s.logger.Errorf("ApplySnapshot failed: %v", err) + return &emptypb.Empty{}, err + } + s.logger.Debug("ApplySnapshot succeeded") + return &emptypb.Empty{}, nil +} + +func (s *DriverServer) DeleteSnapshot(ctx context.Context, req *pb.DeleteSnapshotRequest) (*emptypb.Empty, error) { + s.logger.Debugf("Received DeleteSnapshot request with tag: %s", req.Tag) + err := s.driver.DeleteSnapshot(ctx, req.Tag) + if err != nil { + s.logger.Errorf("DeleteSnapshot failed: %v", err) + return &emptypb.Empty{}, err + } + s.logger.Debug("DeleteSnapshot succeeded") + return &emptypb.Empty{}, nil +} + +func (s *DriverServer) ListSnapshots(ctx context.Context, empty *emptypb.Empty) (*pb.ListSnapshotsResponse, error) { + s.logger.Debug("Received ListSnapshots request") + snapshots, err := s.driver.ListSnapshots(ctx) + if err != nil { + s.logger.Errorf("ListSnapshots failed: %v", err) + return nil, err + } + s.logger.Debug("ListSnapshots succeeded") + return &pb.ListSnapshotsResponse{Snapshots: snapshots}, nil +} + +func (s *DriverServer) Register(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debug("Received Register request") + err := s.driver.Register(ctx) + if err != nil { + s.logger.Errorf("Register failed: %v", err) + return empty, err + } + s.logger.Debug("Register succeeded") + return empty, nil +} + +func (s *DriverServer) Unregister(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { + s.logger.Debug("Received Unregister request") + err := s.driver.Unregister(ctx) + if err != nil { + s.logger.Errorf("Unregister failed: %v", err) + return empty, err + } + s.logger.Debug("Unregister succeeded") + return empty, nil +} + +func (s *DriverServer) ForwardGuestAgent(ctx context.Context, empty *emptypb.Empty) (*pb.ForwardGuestAgentResponse, error) { + s.logger.Debug("Received ForwardGuestAgent request") + return &pb.ForwardGuestAgentResponse{ShouldForward: s.driver.ForwardGuestAgent()}, nil +} diff --git a/pkg/driver/external/server/pipe.go b/pkg/driver/external/server/pipe.go new file mode 100644 index 00000000000..6acd59abb86 --- /dev/null +++ b/pkg/driver/external/server/pipe.go @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package server + +import ( + "io" + "net" + "sync" + "time" +) + +type PipeConn struct { + Reader io.Reader + Writer io.Writer +} + +func (p *PipeConn) Read(b []byte) (n int, err error) { + return p.Reader.Read(b) +} + +func (p *PipeConn) Write(b []byte) (n int, err error) { + return p.Writer.Write(b) +} + +func (p *PipeConn) Close() error { + return nil +} + +func (p *PipeConn) LocalAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) RemoteAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) SetDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetReadDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetWriteDeadline(t time.Time) error { + return nil +} + +type pipeAddr struct{} + +func (pipeAddr) Network() string { return "pipe" } +func (pipeAddr) String() string { return "pipe" } + +type PipeListener struct { + conn net.Conn + connSent bool + mu sync.Mutex + closed bool +} + +func NewPipeListener(conn net.Conn) *PipeListener { + return &PipeListener{ + conn: conn, + connSent: false, + closed: false, + } +} + +func (l *PipeListener) Accept() (net.Conn, error) { + l.mu.Lock() + defer l.mu.Unlock() + + if l.closed { + return nil, net.ErrClosed + } + + if l.connSent { + select {} + } + + l.connSent = true + return l.conn, nil +} + +func (l *PipeListener) Close() error { + l.mu.Lock() + defer l.mu.Unlock() + + if !l.closed { + l.closed = true + } + return nil +} + +func (l *PipeListener) Addr() net.Addr { + return pipeAddr{} +} diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go new file mode 100644 index 00000000000..57a0da1f091 --- /dev/null +++ b/pkg/driver/external/server/server.go @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package server + +import ( + "os" + "os/signal" + "syscall" + "time" + + "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" + + "github.com/lima-vm/lima/pkg/driver" + pb "github.com/lima-vm/lima/pkg/driver/external" +) + +type DriverServer struct { + pb.UnimplementedDriverServer + driver driver.Driver + logger *logrus.Logger +} + +func Serve(driver driver.Driver) { + logger := logrus.New() + logger.SetLevel(logrus.DebugLevel) + logger.SetFormatter(&logrus.TextFormatter{ + FullTimestamp: true, + }) + logger.Infof("Starting external driver server for %s", driver.Name()) + + pipeConn := &PipeConn{ + Reader: os.Stdin, + Writer: os.Stdout, + } + + listener := NewPipeListener(pipeConn) + + kaProps := keepalive.ServerParameters{ + Time: 10 * time.Second, + Timeout: 20 * time.Second, + } + + kaPolicy := keepalive.EnforcementPolicy{ + MinTime: 2 * time.Second, + PermitWithoutStream: true, + } + + server := grpc.NewServer( + grpc.KeepaliveParams(kaProps), + grpc.KeepaliveEnforcementPolicy(kaPolicy), + ) + + pb.RegisterDriverServer(server, &DriverServer{ + driver: driver, + logger: logger, + }) + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + go func() { + <-sigs + logger.Info("Received shutdown signal, stopping server...") + server.Stop() + os.Exit(0) + }() + + logger.Info("Server starting...") + if err := server.Serve(listener); err != nil { + logger.Fatalf("Failed to serve: %v", err) + } +} From 637e2b61e794c8a18ccd23fce122665dc41e776a Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 30 May 2025 22:33:19 +0530 Subject: [PATCH 24/49] driver(external): remove error from the grpc response payload Signed-off-by: Ansuman Sahoo --- pkg/driver/external/driver.pb.go | 1117 ++++++------------------- pkg/driver/external/driver.proto | 84 +- pkg/driver/external/driver_grpc.pb.go | 110 +-- pkg/driver/external/server.go | 164 ---- 4 files changed, 305 insertions(+), 1170 deletions(-) delete mode 100644 pkg/driver/external/server.go diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index 662b14194e7..bc6b608fcf9 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -22,162 +22,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type ValidateResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ValidateResponse) Reset() { - *x = ValidateResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ValidateResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ValidateResponse) ProtoMessage() {} - -func (x *ValidateResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ValidateResponse.ProtoReflect.Descriptor instead. -func (*ValidateResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} -} - -func (x *ValidateResponse) GetValid() bool { - if x != nil { - return x.Valid - } - return false -} - -func (x *ValidateResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type InitializeResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *InitializeResponse) Reset() { - *x = InitializeResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *InitializeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InitializeResponse) ProtoMessage() {} - -func (x *InitializeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InitializeResponse.ProtoReflect.Descriptor instead. -func (*InitializeResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} -} - -func (x *InitializeResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *InitializeResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type CreateDiskResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CreateDiskResponse) Reset() { - *x = CreateDiskResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CreateDiskResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateDiskResponse) ProtoMessage() {} - -func (x *CreateDiskResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateDiskResponse.ProtoReflect.Descriptor instead. -func (*CreateDiskResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} -} - -func (x *CreateDiskResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *CreateDiskResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - type StartResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` @@ -188,7 +32,7 @@ type StartResponse struct { func (x *StartResponse) Reset() { *x = StartResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -200,7 +44,7 @@ func (x *StartResponse) String() string { func (*StartResponse) ProtoMessage() {} func (x *StartResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -213,7 +57,7 @@ func (x *StartResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. func (*StartResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} } func (x *StartResponse) GetSuccess() bool { @@ -230,162 +74,6 @@ func (x *StartResponse) GetError() string { return "" } -type StopResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StopResponse) Reset() { - *x = StopResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StopResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StopResponse) ProtoMessage() {} - -func (x *StopResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StopResponse.ProtoReflect.Descriptor instead. -func (*StopResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} -} - -func (x *StopResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *StopResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type RegisterResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RegisterResponse) Reset() { - *x = RegisterResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RegisterResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterResponse) ProtoMessage() {} - -func (x *RegisterResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead. -func (*RegisterResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} -} - -func (x *RegisterResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *RegisterResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type UnregisterResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UnregisterResponse) Reset() { - *x = UnregisterResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UnregisterResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnregisterResponse) ProtoMessage() {} - -func (x *UnregisterResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UnregisterResponse.ProtoReflect.Descriptor instead. -func (*UnregisterResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} -} - -func (x *UnregisterResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *UnregisterResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - type NameResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -395,7 +83,7 @@ type NameResponse struct { func (x *NameResponse) Reset() { *x = NameResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -407,7 +95,7 @@ func (x *NameResponse) String() string { func (*NameResponse) ProtoMessage() {} func (x *NameResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -420,7 +108,7 @@ func (x *NameResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NameResponse.ProtoReflect.Descriptor instead. func (*NameResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} } func (x *NameResponse) GetName() string { @@ -433,14 +121,14 @@ func (x *NameResponse) GetName() string { type SetConfigRequest struct { state protoimpl.MessageState `protogen:"open.v1"` InstanceConfigJson []byte `protobuf:"bytes,1,opt,name=instance_config_json,json=instanceConfigJson,proto3" json:"instance_config_json,omitempty"` - SshLocalPort int32 `protobuf:"varint,3,opt,name=ssh_local_port,json=sshLocalPort,proto3" json:"ssh_local_port,omitempty"` + SshLocalPort int64 `protobuf:"varint,3,opt,name=ssh_local_port,json=sshLocalPort,proto3" json:"ssh_local_port,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *SetConfigRequest) Reset() { *x = SetConfigRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -452,7 +140,7 @@ func (x *SetConfigRequest) String() string { func (*SetConfigRequest) ProtoMessage() {} func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -465,7 +153,7 @@ func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead. func (*SetConfigRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} } func (x *SetConfigRequest) GetInstanceConfigJson() []byte { @@ -475,7 +163,7 @@ func (x *SetConfigRequest) GetInstanceConfigJson() []byte { return nil } -func (x *SetConfigRequest) GetSshLocalPort() int32 { +func (x *SetConfigRequest) GetSshLocalPort() int64 { if x != nil { return x.SshLocalPort } @@ -492,254 +180,19 @@ type SetConfigResponse struct { func (x *SetConfigResponse) Reset() { *x = SetConfigResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SetConfigResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetConfigResponse) ProtoMessage() {} - -func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead. -func (*SetConfigResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} -} - -func (x *SetConfigResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *SetConfigResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type GetVSockPortResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Port int32 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetVSockPortResponse) Reset() { - *x = GetVSockPortResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetVSockPortResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetVSockPortResponse) ProtoMessage() {} - -func (x *GetVSockPortResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetVSockPortResponse.ProtoReflect.Descriptor instead. -func (*GetVSockPortResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} -} - -func (x *GetVSockPortResponse) GetPort() int32 { - if x != nil { - return x.Port - } - return 0 -} - -type GetVirtioPortResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Port string `protobuf:"bytes,1,opt,name=port,proto3" json:"port,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetVirtioPortResponse) Reset() { - *x = GetVirtioPortResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetVirtioPortResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetVirtioPortResponse) ProtoMessage() {} - -func (x *GetVirtioPortResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetVirtioPortResponse.ProtoReflect.Descriptor instead. -func (*GetVirtioPortResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{11} -} - -func (x *GetVirtioPortResponse) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -type CanRunGUIResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - CanRun bool `protobuf:"varint,1,opt,name=can_run,json=canRun,proto3" json:"can_run,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CanRunGUIResponse) Reset() { - *x = CanRunGUIResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CanRunGUIResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CanRunGUIResponse) ProtoMessage() {} - -func (x *CanRunGUIResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CanRunGUIResponse.ProtoReflect.Descriptor instead. -func (*CanRunGUIResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{12} -} - -func (x *CanRunGUIResponse) GetCanRun() bool { - if x != nil { - return x.CanRun - } - return false -} - -type RunGUIResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RunGUIResponse) Reset() { - *x = RunGUIResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RunGUIResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RunGUIResponse) ProtoMessage() {} - -func (x *RunGUIResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RunGUIResponse.ProtoReflect.Descriptor instead. -func (*RunGUIResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{13} -} - -func (x *RunGUIResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *RunGUIResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type ChangeDisplayPasswordRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ChangeDisplayPasswordRequest) Reset() { - *x = ChangeDisplayPasswordRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[14] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ChangeDisplayPasswordRequest) String() string { +func (x *SetConfigResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ChangeDisplayPasswordRequest) ProtoMessage() {} +func (*SetConfigResponse) ProtoMessage() {} -func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[14] +func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -750,41 +203,47 @@ func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ChangeDisplayPasswordRequest.ProtoReflect.Descriptor instead. -func (*ChangeDisplayPasswordRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{14} +// Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead. +func (*SetConfigResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} } -func (x *ChangeDisplayPasswordRequest) GetPassword() string { +func (x *SetConfigResponse) GetSuccess() bool { if x != nil { - return x.Password + return x.Success + } + return false +} + +func (x *SetConfigResponse) GetError() string { + if x != nil { + return x.Error } return "" } -type ChangeDisplayPasswordResponse struct { +type GetVSockPortResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Port int64 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ChangeDisplayPasswordResponse) Reset() { - *x = ChangeDisplayPasswordResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[15] +func (x *GetVSockPortResponse) Reset() { + *x = GetVSockPortResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ChangeDisplayPasswordResponse) String() string { +func (x *GetVSockPortResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ChangeDisplayPasswordResponse) ProtoMessage() {} +func (*GetVSockPortResponse) ProtoMessage() {} -func (x *ChangeDisplayPasswordResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[15] +func (x *GetVSockPortResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -795,48 +254,40 @@ func (x *ChangeDisplayPasswordResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ChangeDisplayPasswordResponse.ProtoReflect.Descriptor instead. -func (*ChangeDisplayPasswordResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{15} -} - -func (x *ChangeDisplayPasswordResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false +// Deprecated: Use GetVSockPortResponse.ProtoReflect.Descriptor instead. +func (*GetVSockPortResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} } -func (x *ChangeDisplayPasswordResponse) GetError() string { +func (x *GetVSockPortResponse) GetPort() int64 { if x != nil { - return x.Error + return x.Port } - return "" + return 0 } -type GetDisplayConnectionResponse struct { +type GetVirtioPortResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Connection string `protobuf:"bytes,1,opt,name=connection,proto3" json:"connection,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Port string `protobuf:"bytes,1,opt,name=port,proto3" json:"port,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *GetDisplayConnectionResponse) Reset() { - *x = GetDisplayConnectionResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[16] +func (x *GetVirtioPortResponse) Reset() { + *x = GetVirtioPortResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *GetDisplayConnectionResponse) String() string { +func (x *GetVirtioPortResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetDisplayConnectionResponse) ProtoMessage() {} +func (*GetVirtioPortResponse) ProtoMessage() {} -func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[16] +func (x *GetVirtioPortResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -847,47 +298,40 @@ func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetDisplayConnectionResponse.ProtoReflect.Descriptor instead. -func (*GetDisplayConnectionResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{16} -} - -func (x *GetDisplayConnectionResponse) GetConnection() string { - if x != nil { - return x.Connection - } - return "" +// Deprecated: Use GetVirtioPortResponse.ProtoReflect.Descriptor instead. +func (*GetVirtioPortResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} } -func (x *GetDisplayConnectionResponse) GetError() string { +func (x *GetVirtioPortResponse) GetPort() string { if x != nil { - return x.Error + return x.Port } return "" } -type CreateSnapshotRequest struct { +type CanRunGUIResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + CanRun bool `protobuf:"varint,1,opt,name=can_run,json=canRun,proto3" json:"can_run,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *CreateSnapshotRequest) Reset() { - *x = CreateSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[17] +func (x *CanRunGUIResponse) Reset() { + *x = CanRunGUIResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *CreateSnapshotRequest) String() string { +func (x *CanRunGUIResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*CreateSnapshotRequest) ProtoMessage() {} +func (*CanRunGUIResponse) ProtoMessage() {} -func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[17] +func (x *CanRunGUIResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -898,41 +342,40 @@ func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use CreateSnapshotRequest.ProtoReflect.Descriptor instead. -func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{17} +// Deprecated: Use CanRunGUIResponse.ProtoReflect.Descriptor instead. +func (*CanRunGUIResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} } -func (x *CreateSnapshotRequest) GetTag() string { +func (x *CanRunGUIResponse) GetCanRun() bool { if x != nil { - return x.Tag + return x.CanRun } - return "" + return false } -type CreateSnapshotResponse struct { +type ChangeDisplayPasswordRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *CreateSnapshotResponse) Reset() { - *x = CreateSnapshotResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[18] +func (x *ChangeDisplayPasswordRequest) Reset() { + *x = ChangeDisplayPasswordRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *CreateSnapshotResponse) String() string { +func (x *ChangeDisplayPasswordRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*CreateSnapshotResponse) ProtoMessage() {} +func (*ChangeDisplayPasswordRequest) ProtoMessage() {} -func (x *CreateSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[18] +func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -943,47 +386,40 @@ func (x *CreateSnapshotResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use CreateSnapshotResponse.ProtoReflect.Descriptor instead. -func (*CreateSnapshotResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{18} -} - -func (x *CreateSnapshotResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false +// Deprecated: Use ChangeDisplayPasswordRequest.ProtoReflect.Descriptor instead. +func (*ChangeDisplayPasswordRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} } -func (x *CreateSnapshotResponse) GetError() string { +func (x *ChangeDisplayPasswordRequest) GetPassword() string { if x != nil { - return x.Error + return x.Password } return "" } -type ApplySnapshotRequest struct { +type GetDisplayConnectionResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + Connection string `protobuf:"bytes,1,opt,name=connection,proto3" json:"connection,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ApplySnapshotRequest) Reset() { - *x = ApplySnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[19] +func (x *GetDisplayConnectionResponse) Reset() { + *x = GetDisplayConnectionResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ApplySnapshotRequest) String() string { +func (x *GetDisplayConnectionResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ApplySnapshotRequest) ProtoMessage() {} +func (*GetDisplayConnectionResponse) ProtoMessage() {} -func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[19] +func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -994,41 +430,40 @@ func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ApplySnapshotRequest.ProtoReflect.Descriptor instead. -func (*ApplySnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{19} +// Deprecated: Use GetDisplayConnectionResponse.ProtoReflect.Descriptor instead. +func (*GetDisplayConnectionResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} } -func (x *ApplySnapshotRequest) GetTag() string { +func (x *GetDisplayConnectionResponse) GetConnection() string { if x != nil { - return x.Tag + return x.Connection } return "" } -type ApplySnapshotResponse struct { +type CreateSnapshotRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ApplySnapshotResponse) Reset() { - *x = ApplySnapshotResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[20] +func (x *CreateSnapshotRequest) Reset() { + *x = CreateSnapshotRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ApplySnapshotResponse) String() string { +func (x *CreateSnapshotRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ApplySnapshotResponse) ProtoMessage() {} +func (*CreateSnapshotRequest) ProtoMessage() {} -func (x *ApplySnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[20] +func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1039,47 +474,40 @@ func (x *ApplySnapshotResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ApplySnapshotResponse.ProtoReflect.Descriptor instead. -func (*ApplySnapshotResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{20} -} - -func (x *ApplySnapshotResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false +// Deprecated: Use CreateSnapshotRequest.ProtoReflect.Descriptor instead. +func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} } -func (x *ApplySnapshotResponse) GetError() string { +func (x *CreateSnapshotRequest) GetTag() string { if x != nil { - return x.Error + return x.Tag } return "" } -type DeleteSnapshotRequest struct { +type ApplySnapshotRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *DeleteSnapshotRequest) Reset() { - *x = DeleteSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[21] +func (x *ApplySnapshotRequest) Reset() { + *x = ApplySnapshotRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *DeleteSnapshotRequest) String() string { +func (x *ApplySnapshotRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DeleteSnapshotRequest) ProtoMessage() {} +func (*ApplySnapshotRequest) ProtoMessage() {} -func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[21] +func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1090,41 +518,40 @@ func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DeleteSnapshotRequest.ProtoReflect.Descriptor instead. -func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{21} +// Deprecated: Use ApplySnapshotRequest.ProtoReflect.Descriptor instead. +func (*ApplySnapshotRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} } -func (x *DeleteSnapshotRequest) GetTag() string { +func (x *ApplySnapshotRequest) GetTag() string { if x != nil { return x.Tag } return "" } -type DeleteSnapshotResponse struct { +type DeleteSnapshotRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *DeleteSnapshotResponse) Reset() { - *x = DeleteSnapshotResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[22] +func (x *DeleteSnapshotRequest) Reset() { + *x = DeleteSnapshotRequest{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *DeleteSnapshotResponse) String() string { +func (x *DeleteSnapshotRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DeleteSnapshotResponse) ProtoMessage() {} +func (*DeleteSnapshotRequest) ProtoMessage() {} -func (x *DeleteSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[22] +func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1135,21 +562,14 @@ func (x *DeleteSnapshotResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DeleteSnapshotResponse.ProtoReflect.Descriptor instead. -func (*DeleteSnapshotResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{22} -} - -func (x *DeleteSnapshotResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false +// Deprecated: Use DeleteSnapshotRequest.ProtoReflect.Descriptor instead. +func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{11} } -func (x *DeleteSnapshotResponse) GetError() string { +func (x *DeleteSnapshotRequest) GetTag() string { if x != nil { - return x.Error + return x.Tag } return "" } @@ -1157,14 +577,13 @@ func (x *DeleteSnapshotResponse) GetError() string { type ListSnapshotsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Snapshots string `protobuf:"bytes,1,opt,name=snapshots,proto3" json:"snapshots,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ListSnapshotsResponse) Reset() { *x = ListSnapshotsResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[23] + mi := &file_pkg_driver_external_driver_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1176,7 +595,7 @@ func (x *ListSnapshotsResponse) String() string { func (*ListSnapshotsResponse) ProtoMessage() {} func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[23] + mi := &file_pkg_driver_external_driver_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1189,7 +608,7 @@ func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSnapshotsResponse.ProtoReflect.Descriptor instead. func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{23} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{12} } func (x *ListSnapshotsResponse) GetSnapshots() string { @@ -1199,13 +618,6 @@ func (x *ListSnapshotsResponse) GetSnapshots() string { return "" } -func (x *ListSnapshotsResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - type ForwardGuestAgentResponse struct { state protoimpl.MessageState `protogen:"open.v1"` ShouldForward bool `protobuf:"varint,1,opt,name=should_forward,json=shouldForward,proto3" json:"should_forward,omitempty"` @@ -1215,7 +627,7 @@ type ForwardGuestAgentResponse struct { func (x *ForwardGuestAgentResponse) Reset() { *x = ForwardGuestAgentResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[24] + mi := &file_pkg_driver_external_driver_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1227,7 +639,7 @@ func (x *ForwardGuestAgentResponse) String() string { func (*ForwardGuestAgentResponse) ProtoMessage() {} func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[24] + mi := &file_pkg_driver_external_driver_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1240,7 +652,7 @@ func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardGuestAgentResponse.ProtoReflect.Descriptor instead. func (*ForwardGuestAgentResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{24} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{13} } func (x *ForwardGuestAgentResponse) GetShouldForward() bool { @@ -1253,14 +665,13 @@ func (x *ForwardGuestAgentResponse) GetShouldForward() bool { type GuestAgentConnResponse struct { state protoimpl.MessageState `protogen:"open.v1"` NetConn []byte `protobuf:"bytes,1,opt,name=net_conn,json=netConn,proto3" json:"net_conn,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GuestAgentConnResponse) Reset() { *x = GuestAgentConnResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[25] + mi := &file_pkg_driver_external_driver_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1272,7 +683,7 @@ func (x *GuestAgentConnResponse) String() string { func (*GuestAgentConnResponse) ProtoMessage() {} func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[25] + mi := &file_pkg_driver_external_driver_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1285,7 +696,7 @@ func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GuestAgentConnResponse.ProtoReflect.Descriptor instead. func (*GuestAgentConnResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{25} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{14} } func (x *GuestAgentConnResponse) GetNetConn() []byte { @@ -1295,109 +706,66 @@ func (x *GuestAgentConnResponse) GetNetConn() []byte { return nil } -func (x *GuestAgentConnResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - var File_pkg_driver_external_driver_proto protoreflect.FileDescriptor const file_pkg_driver_external_driver_proto_rawDesc = "" + "\n" + - " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\">\n" + - "\x10ValidateResponse\x12\x14\n" + - "\x05valid\x18\x01 \x01(\bR\x05valid\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"D\n" + - "\x12InitializeResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"D\n" + - "\x12CreateDiskResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"?\n" + + " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"?\n" + "\rStartResponse\x12\x18\n" + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\">\n" + - "\fStopResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"B\n" + - "\x10RegisterResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"D\n" + - "\x12UnregisterResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + "\x05error\x18\x02 \x01(\tR\x05error\"\"\n" + "\fNameResponse\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\"j\n" + "\x10SetConfigRequest\x120\n" + "\x14instance_config_json\x18\x01 \x01(\fR\x12instanceConfigJson\x12$\n" + - "\x0essh_local_port\x18\x03 \x01(\x05R\fsshLocalPort\"C\n" + + "\x0essh_local_port\x18\x03 \x01(\x03R\fsshLocalPort\"C\n" + "\x11SetConfigResponse\x12\x18\n" + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + "\x05error\x18\x02 \x01(\tR\x05error\"*\n" + "\x14GetVSockPortResponse\x12\x12\n" + - "\x04port\x18\x01 \x01(\x05R\x04port\"+\n" + + "\x04port\x18\x01 \x01(\x03R\x04port\"+\n" + "\x15GetVirtioPortResponse\x12\x12\n" + "\x04port\x18\x01 \x01(\tR\x04port\",\n" + "\x11CanRunGUIResponse\x12\x17\n" + - "\acan_run\x18\x01 \x01(\bR\x06canRun\"@\n" + - "\x0eRunGUIResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\":\n" + + "\acan_run\x18\x01 \x01(\bR\x06canRun\":\n" + "\x1cChangeDisplayPasswordRequest\x12\x1a\n" + - "\bpassword\x18\x01 \x01(\tR\bpassword\"O\n" + - "\x1dChangeDisplayPasswordResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"T\n" + + "\bpassword\x18\x01 \x01(\tR\bpassword\">\n" + "\x1cGetDisplayConnectionResponse\x12\x1e\n" + "\n" + "connection\x18\x01 \x01(\tR\n" + - "connection\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\")\n" + + "connection\")\n" + "\x15CreateSnapshotRequest\x12\x10\n" + - "\x03tag\x18\x01 \x01(\tR\x03tag\"H\n" + - "\x16CreateSnapshotResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"(\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\"(\n" + "\x14ApplySnapshotRequest\x12\x10\n" + - "\x03tag\x18\x01 \x01(\tR\x03tag\"G\n" + - "\x15ApplySnapshotResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\")\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\")\n" + "\x15DeleteSnapshotRequest\x12\x10\n" + - "\x03tag\x18\x01 \x01(\tR\x03tag\"H\n" + - "\x16DeleteSnapshotResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"K\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\"5\n" + "\x15ListSnapshotsResponse\x12\x1c\n" + - "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"B\n" + + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\"B\n" + "\x19ForwardGuestAgentResponse\x12%\n" + - "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"I\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"3\n" + "\x16GuestAgentConnResponse\x12\x19\n" + - "\bnet_conn\x18\x01 \x01(\fR\anetConn\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error2\x94\n" + + "\bnet_conn\x18\x01 \x01(\fR\anetConn2\xad\n" + "\n" + - "\x06Driver\x125\n" + - "\bValidate\x12\x16.google.protobuf.Empty\x1a\x11.ValidateResponse\x129\n" + + "\x06Driver\x12:\n" + + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + - "Initialize\x12\x16.google.protobuf.Empty\x1a\x13.InitializeResponse\x129\n" + + "Initialize\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + - "CreateDisk\x12\x16.google.protobuf.Empty\x1a\x13.CreateDiskResponse\x121\n" + - "\x05Start\x12\x16.google.protobuf.Empty\x1a\x0e.StartResponse0\x01\x12-\n" + - "\x04Stop\x12\x16.google.protobuf.Empty\x1a\r.StopResponse\x127\n" + - "\tCanRunGUI\x12\x16.google.protobuf.Empty\x1a\x12.CanRunGUIResponse\x121\n" + - "\x06RunGUI\x12\x16.google.protobuf.Empty\x1a\x0f.RunGUIResponse\x12V\n" + - "\x15ChangeDisplayPassword\x12\x1d.ChangeDisplayPasswordRequest\x1a\x1e.ChangeDisplayPasswordResponse\x12M\n" + - "\x14GetDisplayConnection\x12\x16.google.protobuf.Empty\x1a\x1d.GetDisplayConnectionResponse\x12A\n" + - "\x0eCreateSnapshot\x12\x16.CreateSnapshotRequest\x1a\x17.CreateSnapshotResponse\x12>\n" + - "\rApplySnapshot\x12\x15.ApplySnapshotRequest\x1a\x16.ApplySnapshotResponse\x12A\n" + - "\x0eDeleteSnapshot\x12\x16.DeleteSnapshotRequest\x1a\x17.DeleteSnapshotResponse\x12?\n" + - "\rListSnapshots\x12\x16.google.protobuf.Empty\x1a\x16.ListSnapshotsResponse\x125\n" + - "\bRegister\x12\x16.google.protobuf.Empty\x1a\x11.RegisterResponse\x129\n" + + "CreateDisk\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x121\n" + + "\x05Start\x12\x16.google.protobuf.Empty\x1a\x0e.StartResponse0\x01\x126\n" + + "\x04Stop\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x127\n" + + "\tCanRunGUI\x12\x16.google.protobuf.Empty\x1a\x12.CanRunGUIResponse\x128\n" + + "\x06RunGUI\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12N\n" + + "\x15ChangeDisplayPassword\x12\x1d.ChangeDisplayPasswordRequest\x1a\x16.google.protobuf.Empty\x12M\n" + + "\x14GetDisplayConnection\x12\x16.google.protobuf.Empty\x1a\x1d.GetDisplayConnectionResponse\x12@\n" + + "\x0eCreateSnapshot\x12\x16.CreateSnapshotRequest\x1a\x16.google.protobuf.Empty\x12>\n" + + "\rApplySnapshot\x12\x15.ApplySnapshotRequest\x1a\x16.google.protobuf.Empty\x12@\n" + + "\x0eDeleteSnapshot\x12\x16.DeleteSnapshotRequest\x1a\x16.google.protobuf.Empty\x12?\n" + + "\rListSnapshots\x12\x16.google.protobuf.Empty\x1a\x16.ListSnapshotsResponse\x12:\n" + + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + - "Unregister\x12\x16.google.protobuf.Empty\x1a\x13.UnregisterResponse\x12G\n" + + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12C\n" + "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse0\x01\x12-\n" + "\x04Name\x12\x16.google.protobuf.Empty\x1a\r.NameResponse\x122\n" + @@ -1417,79 +785,68 @@ func file_pkg_driver_external_driver_proto_rawDescGZIP() []byte { return file_pkg_driver_external_driver_proto_rawDescData } -var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 26) +var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_pkg_driver_external_driver_proto_goTypes = []any{ - (*ValidateResponse)(nil), // 0: ValidateResponse - (*InitializeResponse)(nil), // 1: InitializeResponse - (*CreateDiskResponse)(nil), // 2: CreateDiskResponse - (*StartResponse)(nil), // 3: StartResponse - (*StopResponse)(nil), // 4: StopResponse - (*RegisterResponse)(nil), // 5: RegisterResponse - (*UnregisterResponse)(nil), // 6: UnregisterResponse - (*NameResponse)(nil), // 7: NameResponse - (*SetConfigRequest)(nil), // 8: SetConfigRequest - (*SetConfigResponse)(nil), // 9: SetConfigResponse - (*GetVSockPortResponse)(nil), // 10: GetVSockPortResponse - (*GetVirtioPortResponse)(nil), // 11: GetVirtioPortResponse - (*CanRunGUIResponse)(nil), // 12: CanRunGUIResponse - (*RunGUIResponse)(nil), // 13: RunGUIResponse - (*ChangeDisplayPasswordRequest)(nil), // 14: ChangeDisplayPasswordRequest - (*ChangeDisplayPasswordResponse)(nil), // 15: ChangeDisplayPasswordResponse - (*GetDisplayConnectionResponse)(nil), // 16: GetDisplayConnectionResponse - (*CreateSnapshotRequest)(nil), // 17: CreateSnapshotRequest - (*CreateSnapshotResponse)(nil), // 18: CreateSnapshotResponse - (*ApplySnapshotRequest)(nil), // 19: ApplySnapshotRequest - (*ApplySnapshotResponse)(nil), // 20: ApplySnapshotResponse - (*DeleteSnapshotRequest)(nil), // 21: DeleteSnapshotRequest - (*DeleteSnapshotResponse)(nil), // 22: DeleteSnapshotResponse - (*ListSnapshotsResponse)(nil), // 23: ListSnapshotsResponse - (*ForwardGuestAgentResponse)(nil), // 24: ForwardGuestAgentResponse - (*GuestAgentConnResponse)(nil), // 25: GuestAgentConnResponse - (*emptypb.Empty)(nil), // 26: google.protobuf.Empty + (*StartResponse)(nil), // 0: StartResponse + (*NameResponse)(nil), // 1: NameResponse + (*SetConfigRequest)(nil), // 2: SetConfigRequest + (*SetConfigResponse)(nil), // 3: SetConfigResponse + (*GetVSockPortResponse)(nil), // 4: GetVSockPortResponse + (*GetVirtioPortResponse)(nil), // 5: GetVirtioPortResponse + (*CanRunGUIResponse)(nil), // 6: CanRunGUIResponse + (*ChangeDisplayPasswordRequest)(nil), // 7: ChangeDisplayPasswordRequest + (*GetDisplayConnectionResponse)(nil), // 8: GetDisplayConnectionResponse + (*CreateSnapshotRequest)(nil), // 9: CreateSnapshotRequest + (*ApplySnapshotRequest)(nil), // 10: ApplySnapshotRequest + (*DeleteSnapshotRequest)(nil), // 11: DeleteSnapshotRequest + (*ListSnapshotsResponse)(nil), // 12: ListSnapshotsResponse + (*ForwardGuestAgentResponse)(nil), // 13: ForwardGuestAgentResponse + (*GuestAgentConnResponse)(nil), // 14: GuestAgentConnResponse + (*emptypb.Empty)(nil), // 15: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ - 26, // 0: Driver.Validate:input_type -> google.protobuf.Empty - 26, // 1: Driver.Initialize:input_type -> google.protobuf.Empty - 26, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty - 26, // 3: Driver.Start:input_type -> google.protobuf.Empty - 26, // 4: Driver.Stop:input_type -> google.protobuf.Empty - 26, // 5: Driver.CanRunGUI:input_type -> google.protobuf.Empty - 26, // 6: Driver.RunGUI:input_type -> google.protobuf.Empty - 14, // 7: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest - 26, // 8: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty - 17, // 9: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest - 19, // 10: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest - 21, // 11: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest - 26, // 12: Driver.ListSnapshots:input_type -> google.protobuf.Empty - 26, // 13: Driver.Register:input_type -> google.protobuf.Empty - 26, // 14: Driver.Unregister:input_type -> google.protobuf.Empty - 26, // 15: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 26, // 16: Driver.GuestAgentConn:input_type -> google.protobuf.Empty - 26, // 17: Driver.Name:input_type -> google.protobuf.Empty - 8, // 18: Driver.SetConfig:input_type -> SetConfigRequest - 26, // 19: Driver.GetVSockPort:input_type -> google.protobuf.Empty - 26, // 20: Driver.GetVirtioPort:input_type -> google.protobuf.Empty - 0, // 21: Driver.Validate:output_type -> ValidateResponse - 1, // 22: Driver.Initialize:output_type -> InitializeResponse - 2, // 23: Driver.CreateDisk:output_type -> CreateDiskResponse - 3, // 24: Driver.Start:output_type -> StartResponse - 4, // 25: Driver.Stop:output_type -> StopResponse - 12, // 26: Driver.CanRunGUI:output_type -> CanRunGUIResponse - 13, // 27: Driver.RunGUI:output_type -> RunGUIResponse - 15, // 28: Driver.ChangeDisplayPassword:output_type -> ChangeDisplayPasswordResponse - 16, // 29: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse - 18, // 30: Driver.CreateSnapshot:output_type -> CreateSnapshotResponse - 20, // 31: Driver.ApplySnapshot:output_type -> ApplySnapshotResponse - 22, // 32: Driver.DeleteSnapshot:output_type -> DeleteSnapshotResponse - 23, // 33: Driver.ListSnapshots:output_type -> ListSnapshotsResponse - 5, // 34: Driver.Register:output_type -> RegisterResponse - 6, // 35: Driver.Unregister:output_type -> UnregisterResponse - 24, // 36: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 25, // 37: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse - 7, // 38: Driver.Name:output_type -> NameResponse - 9, // 39: Driver.SetConfig:output_type -> SetConfigResponse - 10, // 40: Driver.GetVSockPort:output_type -> GetVSockPortResponse - 11, // 41: Driver.GetVirtioPort:output_type -> GetVirtioPortResponse + 15, // 0: Driver.Validate:input_type -> google.protobuf.Empty + 15, // 1: Driver.Initialize:input_type -> google.protobuf.Empty + 15, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty + 15, // 3: Driver.Start:input_type -> google.protobuf.Empty + 15, // 4: Driver.Stop:input_type -> google.protobuf.Empty + 15, // 5: Driver.CanRunGUI:input_type -> google.protobuf.Empty + 15, // 6: Driver.RunGUI:input_type -> google.protobuf.Empty + 7, // 7: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest + 15, // 8: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty + 9, // 9: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest + 10, // 10: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest + 11, // 11: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest + 15, // 12: Driver.ListSnapshots:input_type -> google.protobuf.Empty + 15, // 13: Driver.Register:input_type -> google.protobuf.Empty + 15, // 14: Driver.Unregister:input_type -> google.protobuf.Empty + 15, // 15: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty + 15, // 16: Driver.GuestAgentConn:input_type -> google.protobuf.Empty + 15, // 17: Driver.Name:input_type -> google.protobuf.Empty + 2, // 18: Driver.SetConfig:input_type -> SetConfigRequest + 15, // 19: Driver.GetVSockPort:input_type -> google.protobuf.Empty + 15, // 20: Driver.GetVirtioPort:input_type -> google.protobuf.Empty + 15, // 21: Driver.Validate:output_type -> google.protobuf.Empty + 15, // 22: Driver.Initialize:output_type -> google.protobuf.Empty + 15, // 23: Driver.CreateDisk:output_type -> google.protobuf.Empty + 0, // 24: Driver.Start:output_type -> StartResponse + 15, // 25: Driver.Stop:output_type -> google.protobuf.Empty + 6, // 26: Driver.CanRunGUI:output_type -> CanRunGUIResponse + 15, // 27: Driver.RunGUI:output_type -> google.protobuf.Empty + 15, // 28: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty + 8, // 29: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse + 15, // 30: Driver.CreateSnapshot:output_type -> google.protobuf.Empty + 15, // 31: Driver.ApplySnapshot:output_type -> google.protobuf.Empty + 15, // 32: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty + 12, // 33: Driver.ListSnapshots:output_type -> ListSnapshotsResponse + 15, // 34: Driver.Register:output_type -> google.protobuf.Empty + 15, // 35: Driver.Unregister:output_type -> google.protobuf.Empty + 13, // 36: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse + 14, // 37: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse + 1, // 38: Driver.Name:output_type -> NameResponse + 3, // 39: Driver.SetConfig:output_type -> SetConfigResponse + 4, // 40: Driver.GetVSockPort:output_type -> GetVSockPortResponse + 5, // 41: Driver.GetVirtioPort:output_type -> GetVirtioPortResponse 21, // [21:42] is the sub-list for method output_type 0, // [0:21] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -1508,7 +865,7 @@ func file_pkg_driver_external_driver_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc)), NumEnums: 0, - NumMessages: 26, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index 86898e8250a..3ff6bacd2cf 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -5,24 +5,24 @@ option go_package = "github.com/lima-vm/lima/pkg/driver/external"; import "google/protobuf/empty.proto"; service Driver { - rpc Validate(google.protobuf.Empty) returns (ValidateResponse); - rpc Initialize(google.protobuf.Empty) returns (InitializeResponse); - rpc CreateDisk(google.protobuf.Empty) returns (CreateDiskResponse); + rpc Validate(google.protobuf.Empty) returns (google.protobuf.Empty); + rpc Initialize(google.protobuf.Empty) returns (google.protobuf.Empty); + rpc CreateDisk(google.protobuf.Empty) returns (google.protobuf.Empty); rpc Start(google.protobuf.Empty) returns (stream StartResponse); - rpc Stop(google.protobuf.Empty) returns (StopResponse); + rpc Stop(google.protobuf.Empty) returns (google.protobuf.Empty); rpc CanRunGUI(google.protobuf.Empty) returns (CanRunGUIResponse); - rpc RunGUI(google.protobuf.Empty) returns (RunGUIResponse); - rpc ChangeDisplayPassword(ChangeDisplayPasswordRequest) returns (ChangeDisplayPasswordResponse); + rpc RunGUI(google.protobuf.Empty) returns (google.protobuf.Empty); + rpc ChangeDisplayPassword(ChangeDisplayPasswordRequest) returns (google.protobuf.Empty); rpc GetDisplayConnection(google.protobuf.Empty) returns (GetDisplayConnectionResponse); - rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse); - rpc ApplySnapshot(ApplySnapshotRequest) returns (ApplySnapshotResponse); - rpc DeleteSnapshot(DeleteSnapshotRequest) returns (DeleteSnapshotResponse); + rpc CreateSnapshot(CreateSnapshotRequest) returns (google.protobuf.Empty); + rpc ApplySnapshot(ApplySnapshotRequest) returns (google.protobuf.Empty); + rpc DeleteSnapshot(DeleteSnapshotRequest) returns (google.protobuf.Empty); rpc ListSnapshots(google.protobuf.Empty) returns (ListSnapshotsResponse); - rpc Register(google.protobuf.Empty) returns (RegisterResponse); - rpc Unregister(google.protobuf.Empty) returns (UnregisterResponse); + rpc Register(google.protobuf.Empty) returns (google.protobuf.Empty); + rpc Unregister(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); rpc GuestAgentConn(google.protobuf.Empty) returns (stream GuestAgentConnResponse); @@ -34,48 +34,18 @@ service Driver { rpc GetVirtioPort(google.protobuf.Empty) returns (GetVirtioPortResponse); } -message ValidateResponse { - bool valid = 1; - string error = 2; -} - -message InitializeResponse { - bool success = 1; - string error = 2; -} - -message CreateDiskResponse { - bool success = 1; - string error = 2; -} - message StartResponse { bool success = 1; string error = 2; } -message StopResponse { - bool success = 1; - string error = 2; -} - -message RegisterResponse { - bool success = 1; - string error = 2; -} - -message UnregisterResponse { - bool success = 1; - string error = 2; -} - message NameResponse { string name = 1; } message SetConfigRequest { bytes instance_config_json = 1; - int32 ssh_local_port = 3; + int64 ssh_local_port = 3; } message SetConfigResponse { @@ -84,7 +54,7 @@ message SetConfigResponse { } message GetVSockPortResponse { - int32 port = 1; + int64 port = 1; } message GetVirtioPortResponse { @@ -95,55 +65,28 @@ message CanRunGUIResponse { bool can_run = 1; } -message RunGUIResponse { - bool success = 1; - string error = 2; -} - message ChangeDisplayPasswordRequest { string password = 1; } -message ChangeDisplayPasswordResponse { - bool success = 1; - string error = 2; -} - message GetDisplayConnectionResponse { string connection = 1; - string error = 2; } message CreateSnapshotRequest { string tag = 1; } -message CreateSnapshotResponse { - bool success = 1; - string error = 2; -} - message ApplySnapshotRequest { string tag = 1; } -message ApplySnapshotResponse { - bool success = 1; - string error = 2; -} - message DeleteSnapshotRequest { string tag = 1; } -message DeleteSnapshotResponse { - bool success = 1; - string error = 2; -} - message ListSnapshotsResponse { string snapshots = 1; - string error = 2; } message ForwardGuestAgentResponse { @@ -152,5 +95,4 @@ message ForwardGuestAgentResponse { message GuestAgentConnResponse { bytes net_conn = 1; - string error = 2; } \ No newline at end of file diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index 0ec8bd21df9..c2eeb282eb3 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -47,21 +47,21 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type DriverClient interface { - Validate(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ValidateResponse, error) - Initialize(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InitializeResponse, error) - CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateDiskResponse, error) + Validate(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + Initialize(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Start(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StartResponse], error) - Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StopResponse, error) + Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) CanRunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CanRunGUIResponse, error) - RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RunGUIResponse, error) - ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*ChangeDisplayPasswordResponse, error) + RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetDisplayConnection(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetDisplayConnectionResponse, error) - CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) - ApplySnapshot(ctx context.Context, in *ApplySnapshotRequest, opts ...grpc.CallOption) (*ApplySnapshotResponse, error) - DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*DeleteSnapshotResponse, error) + CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ApplySnapshot(ctx context.Context, in *ApplySnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) ListSnapshots(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) - Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RegisterResponse, error) - Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*UnregisterResponse, error) + Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GuestAgentConnResponse], error) Name(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NameResponse, error) @@ -78,9 +78,9 @@ func NewDriverClient(cc grpc.ClientConnInterface) DriverClient { return &driverClient{cc} } -func (c *driverClient) Validate(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ValidateResponse, error) { +func (c *driverClient) Validate(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ValidateResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_Validate_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -88,9 +88,9 @@ func (c *driverClient) Validate(ctx context.Context, in *emptypb.Empty, opts ... return out, nil } -func (c *driverClient) Initialize(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InitializeResponse, error) { +func (c *driverClient) Initialize(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(InitializeResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_Initialize_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -98,9 +98,9 @@ func (c *driverClient) Initialize(ctx context.Context, in *emptypb.Empty, opts . return out, nil } -func (c *driverClient) CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateDiskResponse, error) { +func (c *driverClient) CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CreateDiskResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_CreateDisk_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -127,9 +127,9 @@ func (c *driverClient) Start(ctx context.Context, in *emptypb.Empty, opts ...grp // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type Driver_StartClient = grpc.ServerStreamingClient[StartResponse] -func (c *driverClient) Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StopResponse, error) { +func (c *driverClient) Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(StopResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_Stop_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -147,9 +147,9 @@ func (c *driverClient) CanRunGUI(ctx context.Context, in *emptypb.Empty, opts .. return out, nil } -func (c *driverClient) RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RunGUIResponse, error) { +func (c *driverClient) RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(RunGUIResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_RunGUI_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -157,9 +157,9 @@ func (c *driverClient) RunGUI(ctx context.Context, in *emptypb.Empty, opts ...gr return out, nil } -func (c *driverClient) ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*ChangeDisplayPasswordResponse, error) { +func (c *driverClient) ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ChangeDisplayPasswordResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_ChangeDisplayPassword_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -177,9 +177,9 @@ func (c *driverClient) GetDisplayConnection(ctx context.Context, in *emptypb.Emp return out, nil } -func (c *driverClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) { +func (c *driverClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CreateSnapshotResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_CreateSnapshot_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -187,9 +187,9 @@ func (c *driverClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotReq return out, nil } -func (c *driverClient) ApplySnapshot(ctx context.Context, in *ApplySnapshotRequest, opts ...grpc.CallOption) (*ApplySnapshotResponse, error) { +func (c *driverClient) ApplySnapshot(ctx context.Context, in *ApplySnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ApplySnapshotResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_ApplySnapshot_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -197,9 +197,9 @@ func (c *driverClient) ApplySnapshot(ctx context.Context, in *ApplySnapshotReque return out, nil } -func (c *driverClient) DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*DeleteSnapshotResponse, error) { +func (c *driverClient) DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(DeleteSnapshotResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_DeleteSnapshot_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -217,9 +217,9 @@ func (c *driverClient) ListSnapshots(ctx context.Context, in *emptypb.Empty, opt return out, nil } -func (c *driverClient) Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*RegisterResponse, error) { +func (c *driverClient) Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(RegisterResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_Register_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -227,9 +227,9 @@ func (c *driverClient) Register(ctx context.Context, in *emptypb.Empty, opts ... return out, nil } -func (c *driverClient) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*UnregisterResponse, error) { +func (c *driverClient) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(UnregisterResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_Unregister_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -310,21 +310,21 @@ func (c *driverClient) GetVirtioPort(ctx context.Context, in *emptypb.Empty, opt // All implementations must embed UnimplementedDriverServer // for forward compatibility. type DriverServer interface { - Validate(context.Context, *emptypb.Empty) (*ValidateResponse, error) - Initialize(context.Context, *emptypb.Empty) (*InitializeResponse, error) - CreateDisk(context.Context, *emptypb.Empty) (*CreateDiskResponse, error) + Validate(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + Initialize(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + CreateDisk(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Start(*emptypb.Empty, grpc.ServerStreamingServer[StartResponse]) error - Stop(context.Context, *emptypb.Empty) (*StopResponse, error) + Stop(context.Context, *emptypb.Empty) (*emptypb.Empty, error) CanRunGUI(context.Context, *emptypb.Empty) (*CanRunGUIResponse, error) - RunGUI(context.Context, *emptypb.Empty) (*RunGUIResponse, error) - ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*ChangeDisplayPasswordResponse, error) + RunGUI(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*emptypb.Empty, error) GetDisplayConnection(context.Context, *emptypb.Empty) (*GetDisplayConnectionResponse, error) - CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) - ApplySnapshot(context.Context, *ApplySnapshotRequest) (*ApplySnapshotResponse, error) - DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error) + CreateSnapshot(context.Context, *CreateSnapshotRequest) (*emptypb.Empty, error) + ApplySnapshot(context.Context, *ApplySnapshotRequest) (*emptypb.Empty, error) + DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*emptypb.Empty, error) ListSnapshots(context.Context, *emptypb.Empty) (*ListSnapshotsResponse, error) - Register(context.Context, *emptypb.Empty) (*RegisterResponse, error) - Unregister(context.Context, *emptypb.Empty) (*UnregisterResponse, error) + Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error Name(context.Context, *emptypb.Empty) (*NameResponse, error) @@ -341,49 +341,49 @@ type DriverServer interface { // pointer dereference when methods are called. type UnimplementedDriverServer struct{} -func (UnimplementedDriverServer) Validate(context.Context, *emptypb.Empty) (*ValidateResponse, error) { +func (UnimplementedDriverServer) Validate(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Validate not implemented") } -func (UnimplementedDriverServer) Initialize(context.Context, *emptypb.Empty) (*InitializeResponse, error) { +func (UnimplementedDriverServer) Initialize(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Initialize not implemented") } -func (UnimplementedDriverServer) CreateDisk(context.Context, *emptypb.Empty) (*CreateDiskResponse, error) { +func (UnimplementedDriverServer) CreateDisk(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateDisk not implemented") } func (UnimplementedDriverServer) Start(*emptypb.Empty, grpc.ServerStreamingServer[StartResponse]) error { return status.Errorf(codes.Unimplemented, "method Start not implemented") } -func (UnimplementedDriverServer) Stop(context.Context, *emptypb.Empty) (*StopResponse, error) { +func (UnimplementedDriverServer) Stop(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented") } func (UnimplementedDriverServer) CanRunGUI(context.Context, *emptypb.Empty) (*CanRunGUIResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CanRunGUI not implemented") } -func (UnimplementedDriverServer) RunGUI(context.Context, *emptypb.Empty) (*RunGUIResponse, error) { +func (UnimplementedDriverServer) RunGUI(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method RunGUI not implemented") } -func (UnimplementedDriverServer) ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*ChangeDisplayPasswordResponse, error) { +func (UnimplementedDriverServer) ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method ChangeDisplayPassword not implemented") } func (UnimplementedDriverServer) GetDisplayConnection(context.Context, *emptypb.Empty) (*GetDisplayConnectionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetDisplayConnection not implemented") } -func (UnimplementedDriverServer) CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error) { +func (UnimplementedDriverServer) CreateSnapshot(context.Context, *CreateSnapshotRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateSnapshot not implemented") } -func (UnimplementedDriverServer) ApplySnapshot(context.Context, *ApplySnapshotRequest) (*ApplySnapshotResponse, error) { +func (UnimplementedDriverServer) ApplySnapshot(context.Context, *ApplySnapshotRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshot not implemented") } -func (UnimplementedDriverServer) DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error) { +func (UnimplementedDriverServer) DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteSnapshot not implemented") } func (UnimplementedDriverServer) ListSnapshots(context.Context, *emptypb.Empty) (*ListSnapshotsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") } -func (UnimplementedDriverServer) Register(context.Context, *emptypb.Empty) (*RegisterResponse, error) { +func (UnimplementedDriverServer) Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") } -func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*UnregisterResponse, error) { +func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Unregister not implemented") } func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { diff --git a/pkg/driver/external/server.go b/pkg/driver/external/server.go deleted file mode 100644 index 73fcb3eb316..00000000000 --- a/pkg/driver/external/server.go +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package external - -import ( - "io" - "net" - "os" - "os/signal" - "sync" - "syscall" - "time" - - "github.com/sirupsen/logrus" - "google.golang.org/grpc" - "google.golang.org/grpc/keepalive" - - "github.com/lima-vm/lima/pkg/driver" -) - -type Server struct { - UnimplementedDriverServer - driver driver.Driver - logger *logrus.Logger -} - -func Serve(driver driver.Driver) { - logger := logrus.New() - logger.SetLevel(logrus.DebugLevel) - logger.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - }) - logger.Infof("Starting external driver server for %s", driver.Name()) - - pipeConn := &PipeConn{ - Reader: os.Stdin, - Writer: os.Stdout, - } - - listener := NewPipeListener(pipeConn) - - kaProps := keepalive.ServerParameters{ - Time: 10 * time.Second, - Timeout: 20 * time.Second, - } - - kaPolicy := keepalive.EnforcementPolicy{ - MinTime: 2 * time.Second, - PermitWithoutStream: true, - } - - server := grpc.NewServer( - grpc.KeepaliveParams(kaProps), - grpc.KeepaliveEnforcementPolicy(kaPolicy), - ) - - RegisterDriverServer(server, &Server{ - driver: driver, - logger: logger, - }) - - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - - go func() { - <-sigs - logger.Info("Received shutdown signal, stopping server...") - server.Stop() - os.Exit(0) - }() - - logger.Info("Server starting...") - if err := server.Serve(listener); err != nil { - logger.Fatalf("Failed to serve: %v", err) - } -} - -type PipeConn struct { - Reader io.Reader - Writer io.Writer -} - -func (p *PipeConn) Read(b []byte) (n int, err error) { - return p.Reader.Read(b) -} - -func (p *PipeConn) Write(b []byte) (n int, err error) { - return p.Writer.Write(b) -} - -func (p *PipeConn) Close() error { - return nil -} - -func (p *PipeConn) LocalAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) RemoteAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) SetDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetReadDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetWriteDeadline(t time.Time) error { - return nil -} - -type pipeAddr struct{} - -func (pipeAddr) Network() string { return "pipe" } -func (pipeAddr) String() string { return "pipe" } - -type PipeListener struct { - conn net.Conn - connSent bool - mu sync.Mutex - closed bool -} - -func NewPipeListener(conn net.Conn) *PipeListener { - return &PipeListener{ - conn: conn, - connSent: false, - closed: false, - } -} - -func (l *PipeListener) Accept() (net.Conn, error) { - l.mu.Lock() - defer l.mu.Unlock() - - if l.closed { - return nil, net.ErrClosed - } - - if l.connSent { - select {} - } - - l.connSent = true - return l.conn, nil -} - -func (l *PipeListener) Close() error { - l.mu.Lock() - defer l.mu.Unlock() - - if !l.closed { - l.closed = true - } - return nil -} - -func (l *PipeListener) Addr() net.Addr { - return pipeAddr{} -} From e01f06d7215311520d21f19c8873a7e1411d2e16 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 30 May 2025 22:33:55 +0530 Subject: [PATCH 25/49] driver(external): add discovery of external drivers Signed-off-by: Ansuman Sahoo --- pkg/registry/registry.go | 92 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 9d61584a1f8..573997704f1 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -4,9 +4,15 @@ package registry import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" "sync" "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/usrlocalsharelima" "github.com/sirupsen/logrus" ) @@ -68,10 +74,94 @@ func (r *Registry) RegisterPlugin(name, path string) { } func (r *Registry) DiscoverPlugins() error { - // TODO: Implement plugin discovery logic + limaShareDir, err := usrlocalsharelima.Dir() + if err != nil { + return fmt.Errorf("failed to determine Lima share directory: %w", err) + } + stdPluginDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") + + if _, err := os.Stat(stdPluginDir); err == nil { + if err := r.discoverPluginsInDir(stdPluginDir); err != nil { + logrus.Warnf("Error discovering plugins in %s: %v", stdPluginDir, err) + } + } + + if pluginPaths := os.Getenv("LIMA_DRIVERS_PATH"); pluginPaths != "" { + paths := filepath.SplitList(pluginPaths) + for _, path := range paths { + if path == "" { + continue + } + + info, err := os.Stat(path) + if err != nil { + logrus.Warnf("Error accessing plugin path %s: %v", path, err) + continue + } + + if info.IsDir() { + if err := r.discoverPluginsInDir(path); err != nil { + logrus.Warnf("Error discovering plugins in %s: %v", path, err) + } + } else if isExecutable(info.Mode()) { + r.registerPluginFile(path) + } + } + } + + return nil +} + +func (r *Registry) discoverPluginsInDir(dir string) error { + entries, err := os.ReadDir(dir) + if err != nil { + return fmt.Errorf("failed to read plugin directory %s: %w", dir, err) + } + + for _, entry := range entries { + if entry.IsDir() { + continue + } + + info, err := entry.Info() + if err != nil { + logrus.Warnf("Failed to get info for %s: %v", entry.Name(), err) + continue + } + + if !isExecutable(info.Mode()) { + continue + } + + pluginPath := filepath.Join(dir, entry.Name()) + r.registerPluginFile(pluginPath) + } + return nil } +func (r *Registry) registerPluginFile(path string) { + base := filepath.Base(path) + if !strings.HasPrefix(base, "lima-plugin-") { + return + } + + name := strings.TrimPrefix(base, "lima-plugin-") + name = strings.TrimSuffix(name, filepath.Ext(name)) + + cmd := exec.Command(path, "--version") + if err := cmd.Run(); err != nil { + logrus.Warnf("Plugin %s failed version check: %v", path, err) + return + } + + r.RegisterPlugin(name, path) +} + +func isExecutable(mode os.FileMode) bool { + return mode&0111 != 0 +} + var DefaultRegistry *Registry func init() { From fbf975390d1d666f02b2a702400863d1ff26187d Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 2 Jun 2025 17:03:10 +0530 Subject: [PATCH 26/49] driver(internal): consolidate some functions to single GetInfo() function Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 25 +++++++++++-------------- pkg/driver/qemu/qemu_driver.go | 21 +++++++-------------- pkg/driver/vz/vz_driver_darwin.go | 24 ++++++++++++------------ pkg/driver/wsl2/wsl_driver_windows.go | 20 +++++++++----------- pkg/hostagent/hostagent.go | 6 +++--- pkg/instance/start.go | 2 +- pkg/registry/registry.go | 2 +- 7 files changed, 44 insertions(+), 56 deletions(-) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 693ce91a9ff..65a96c39ed2 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -38,9 +38,6 @@ type Lifecycle interface { // GUI defines GUI-related operations. type GUI interface { - // CanRunGUI returns bool to indicate if the hostagent need to run GUI synchronously - CanRunGUI() bool - // RunGUI is for starting GUI synchronously by hostagent. This method should be wait and return only after vm terminates // It returns error if there are any failures RunGUI() error @@ -72,14 +69,6 @@ type GuestAgent interface { GuestAgentConn(_ context.Context) (net.Conn, error) } -type Plugin interface { - // Name returns the name of the driver - Name() string - - // SetConfig sets the configuration for the instance. - SetConfig(inst *store.Instance, sshLocalPort int) -} - // Driver interface is used by hostagent for managing vm. type Driver interface { Lifecycle @@ -87,8 +76,16 @@ type Driver interface { SnapshotManager Registration GuestAgent - Plugin - GetVSockPort() int - GetVirtioPort() string + GetInfo() Info + + // SetConfig sets the configuration for the instance. + SetConfig(inst *store.Instance, sshLocalPort int) +} + +type Info struct { + DriverName string + CanRunGUI bool + VsockPort int + VirtioPort string } diff --git a/pkg/driver/qemu/qemu_driver.go b/pkg/driver/qemu/qemu_driver.go index c026dab21c1..ee29208c752 100644 --- a/pkg/driver/qemu/qemu_driver.go +++ b/pkg/driver/qemu/qemu_driver.go @@ -69,14 +69,6 @@ func (l *LimaQemuDriver) SetConfig(inst *store.Instance, sshLocalPort int) { l.SSHLocalPort = sshLocalPort } -func (l *LimaQemuDriver) GetVirtioPort() string { - return l.VirtioPort -} - -func (l *LimaQemuDriver) GetVSockPort() int { - return l.VSockPort -} - func (l *LimaQemuDriver) Validate() error { if runtime.GOOS == "darwin" { if err := l.checkBinarySignature(); err != nil { @@ -519,18 +511,19 @@ func (a *qArgTemplateApplier) applyTemplate(qArg string) (string, error) { return b.String(), nil } -func (l *LimaQemuDriver) Name() string { - return "qemu" +func (l *LimaQemuDriver) GetInfo() driver.Info { + return driver.Info{ + DriverName: "qemu", + CanRunGUI: false, + VsockPort: l.VSockPort, + VirtioPort: l.VirtioPort, + } } func (l *LimaQemuDriver) Initialize(_ context.Context) error { return nil } -func (l *LimaQemuDriver) CanRunGUI() bool { - return false -} - func (l *LimaQemuDriver) RunGUI() error { return nil } diff --git a/pkg/driver/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go index c5471d00b13..6eb7c643c41 100644 --- a/pkg/driver/vz/vz_driver_darwin.go +++ b/pkg/driver/vz/vz_driver_darwin.go @@ -92,14 +92,6 @@ func (l *LimaVzDriver) SetConfig(inst *store.Instance, sshLocalPort int) { l.SSHLocalPort = sshLocalPort } -func (l *LimaVzDriver) GetVirtioPort() string { - return l.VirtioPort -} - -func (l *LimaVzDriver) GetVSockPort() int { - return l.VSockPort -} - func (l *LimaVzDriver) Validate() error { macOSProductVersion, err := osutil.ProductVersion() if err != nil { @@ -208,7 +200,7 @@ func (l *LimaVzDriver) Start(ctx context.Context) (chan error, error) { return errCh, nil } -func (l *LimaVzDriver) CanRunGUI() bool { +func (l *LimaVzDriver) canRunGUI() bool { switch *l.Instance.Config.Video.Display { case "vz", "default": return true @@ -218,7 +210,7 @@ func (l *LimaVzDriver) CanRunGUI() bool { } func (l *LimaVzDriver) RunGUI() error { - if l.CanRunGUI() { + if l.canRunGUI() { return l.machine.StartGraphicApplication(1920, 1200) } return fmt.Errorf("RunGUI is not supported for the given driver '%s' and display '%s'", "vz", *l.Instance.Config.Video.Display) @@ -264,8 +256,16 @@ func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { return nil, errors.New("unable to connect to guest agent via vsock port 2222") } -func (l *LimaVzDriver) Name() string { - return "vz" +func (l *LimaVzDriver) GetInfo() driver.Info { + var info driver.Info + if l.Instance != nil && l.Instance.Config != nil { + info.CanRunGUI = l.canRunGUI() + } + + info.DriverName = "vz" + info.VsockPort = l.VSockPort + info.VirtioPort = l.VirtioPort + return info } func (l *LimaVzDriver) Register(_ context.Context) error { diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index 420f8892f99..cf744847cfb 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -68,14 +68,6 @@ func New() *LimaWslDriver { } } -func (l *LimaWslDriver) GetVirtioPort() string { - return l.VirtioPort -} - -func (l *LimaWslDriver) GetVSockPort() int { - return l.VSockPort -} - func (l *LimaWslDriver) SetConfig(inst *store.Instance, sshLocalPort int) { l.Instance = inst l.SSHLocalPort = sshLocalPort @@ -173,7 +165,8 @@ func (l *LimaWslDriver) Start(ctx context.Context) (chan error, error) { // CanRunGUI requires WSLg, which requires specific version of WSL2 to be installed. // TODO: Add check and add support for WSLg (instead of VNC) to hostagent. -func (l *LimaWslDriver) CanRunGUI() bool { +func (l *LimaWslDriver) canRunGUI() bool { + // return *l.InstConfig.Video.Display == "wsl" return false } @@ -221,8 +214,13 @@ func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { return winio.Dial(ctx, sockAddr) } -func (l *LimaWslDriver) Name() string { - return "wsl2" +func (l *LimaWslDriver) GetInfo() driver.Info { + return driver.Info{ + DriverName: "wsl", + CanRunGUI: l.canRunGUI(), + VsockPort: l.VSockPort, + VirtioPort: l.VirtioPort, + } } func (l *LimaWslDriver) Initialize(_ context.Context) error { diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 1ac97b18986..446d3e97083 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -136,8 +136,8 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt return nil, fmt.Errorf("failed to create driver instance: %w", err) } - vSockPort := limaDriver.GetVSockPort() - virtioPort := limaDriver.GetVirtioPort() + vSockPort := limaDriver.GetInfo().VsockPort + virtioPort := limaDriver.GetInfo().VirtioPort if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { return nil, err @@ -361,7 +361,7 @@ func (a *HostAgent) Run(ctx context.Context) error { logrus.Infof("VNC Password: `%s`", vncpwdfile) } - if a.driver.CanRunGUI() { + if a.driver.GetInfo().CanRunGUI { go func() { err = a.startRoutinesAndWait(ctx, errCh) if err != nil { diff --git a/pkg/instance/start.go b/pkg/instance/start.go index 44680124f7e..6a6a4e97da8 100644 --- a/pkg/instance/start.go +++ b/pkg/instance/start.go @@ -189,7 +189,7 @@ func Start(ctx context.Context, inst *store.Instance, limactl string, launchHost "hostagent", "--pidfile", haPIDPath, "--socket", haSockPath) - if prepared.Driver.CanRunGUI() { + if prepared.Driver.GetInfo().CanRunGUI { args = append(args, "--run-gui") } if prepared.GuestAgent != "" { diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 573997704f1..d2dd5aff2f1 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -170,7 +170,7 @@ func init() { func Register(driver driver.Driver) { if DefaultRegistry != nil { - name := driver.Name() + name := driver.GetInfo().DriverName if _, exists := DefaultRegistry.drivers[name]; exists { return } From f01df5ec34bfbec8b3a6edd84ded8b96412d7e1b Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 2 Jun 2025 17:04:33 +0530 Subject: [PATCH 27/49] driver(external): consolidate some functions to single GetInfo() rpc call Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 8 +- pkg/driver/external/driver.pb.go | 439 +++++++------------------- pkg/driver/external/driver.proto | 34 +- pkg/driver/external/driver_grpc.pb.go | 152 ++------- pkg/driver/external/server/methods.go | 28 +- pkg/driver/external/server/server.go | 2 +- 6 files changed, 154 insertions(+), 509 deletions(-) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 65a96c39ed2..752aab69d68 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -84,8 +84,8 @@ type Driver interface { } type Info struct { - DriverName string - CanRunGUI bool - VsockPort int - VirtioPort string + DriverName string `json:"driverName"` + CanRunGUI bool `json:"canRunGui,omitempty"` + VsockPort int `json:"vsockPort"` + VirtioPort string `json:"virtioPort"` } diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index bc6b608fcf9..40fdc432dc4 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -22,28 +22,27 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type StartResponse struct { +type InfoResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + InfoJson []byte `protobuf:"bytes,1,opt,name=info_json,json=infoJson,proto3" json:"info_json,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *StartResponse) Reset() { - *x = StartResponse{} +func (x *InfoResponse) Reset() { + *x = InfoResponse{} mi := &file_pkg_driver_external_driver_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *StartResponse) String() string { +func (x *InfoResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*StartResponse) ProtoMessage() {} +func (*InfoResponse) ProtoMessage() {} -func (x *StartResponse) ProtoReflect() protoreflect.Message { +func (x *InfoResponse) ProtoReflect() protoreflect.Message { mi := &file_pkg_driver_external_driver_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -55,46 +54,40 @@ func (x *StartResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. -func (*StartResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use InfoResponse.ProtoReflect.Descriptor instead. +func (*InfoResponse) Descriptor() ([]byte, []int) { return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} } -func (x *StartResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *StartResponse) GetError() string { +func (x *InfoResponse) GetInfoJson() []byte { if x != nil { - return x.Error + return x.InfoJson } - return "" + return nil } -type NameResponse struct { +type StartResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *NameResponse) Reset() { - *x = NameResponse{} +func (x *StartResponse) Reset() { + *x = StartResponse{} mi := &file_pkg_driver_external_driver_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *NameResponse) String() string { +func (x *StartResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*NameResponse) ProtoMessage() {} +func (*StartResponse) ProtoMessage() {} -func (x *NameResponse) ProtoReflect() protoreflect.Message { +func (x *StartResponse) ProtoReflect() protoreflect.Message { mi := &file_pkg_driver_external_driver_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -106,14 +99,21 @@ func (x *NameResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use NameResponse.ProtoReflect.Descriptor instead. -func (*NameResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. +func (*StartResponse) Descriptor() ([]byte, []int) { return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} } -func (x *NameResponse) GetName() string { +func (x *StartResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *StartResponse) GetError() string { if x != nil { - return x.Name + return x.Error } return "" } @@ -170,190 +170,6 @@ func (x *SetConfigRequest) GetSshLocalPort() int64 { return 0 } -type SetConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SetConfigResponse) Reset() { - *x = SetConfigResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SetConfigResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetConfigResponse) ProtoMessage() {} - -func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead. -func (*SetConfigResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} -} - -func (x *SetConfigResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *SetConfigResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type GetVSockPortResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Port int64 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetVSockPortResponse) Reset() { - *x = GetVSockPortResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetVSockPortResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetVSockPortResponse) ProtoMessage() {} - -func (x *GetVSockPortResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetVSockPortResponse.ProtoReflect.Descriptor instead. -func (*GetVSockPortResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} -} - -func (x *GetVSockPortResponse) GetPort() int64 { - if x != nil { - return x.Port - } - return 0 -} - -type GetVirtioPortResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Port string `protobuf:"bytes,1,opt,name=port,proto3" json:"port,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetVirtioPortResponse) Reset() { - *x = GetVirtioPortResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetVirtioPortResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetVirtioPortResponse) ProtoMessage() {} - -func (x *GetVirtioPortResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetVirtioPortResponse.ProtoReflect.Descriptor instead. -func (*GetVirtioPortResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} -} - -func (x *GetVirtioPortResponse) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -type CanRunGUIResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - CanRun bool `protobuf:"varint,1,opt,name=can_run,json=canRun,proto3" json:"can_run,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CanRunGUIResponse) Reset() { - *x = CanRunGUIResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CanRunGUIResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CanRunGUIResponse) ProtoMessage() {} - -func (x *CanRunGUIResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CanRunGUIResponse.ProtoReflect.Descriptor instead. -func (*CanRunGUIResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} -} - -func (x *CanRunGUIResponse) GetCanRun() bool { - if x != nil { - return x.CanRun - } - return false -} - type ChangeDisplayPasswordRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"` @@ -363,7 +179,7 @@ type ChangeDisplayPasswordRequest struct { func (x *ChangeDisplayPasswordRequest) Reset() { *x = ChangeDisplayPasswordRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -375,7 +191,7 @@ func (x *ChangeDisplayPasswordRequest) String() string { func (*ChangeDisplayPasswordRequest) ProtoMessage() {} func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -388,7 +204,7 @@ func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayPasswordRequest.ProtoReflect.Descriptor instead. func (*ChangeDisplayPasswordRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} } func (x *ChangeDisplayPasswordRequest) GetPassword() string { @@ -407,7 +223,7 @@ type GetDisplayConnectionResponse struct { func (x *GetDisplayConnectionResponse) Reset() { *x = GetDisplayConnectionResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -419,7 +235,7 @@ func (x *GetDisplayConnectionResponse) String() string { func (*GetDisplayConnectionResponse) ProtoMessage() {} func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -432,7 +248,7 @@ func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDisplayConnectionResponse.ProtoReflect.Descriptor instead. func (*GetDisplayConnectionResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} } func (x *GetDisplayConnectionResponse) GetConnection() string { @@ -451,7 +267,7 @@ type CreateSnapshotRequest struct { func (x *CreateSnapshotRequest) Reset() { *x = CreateSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -463,7 +279,7 @@ func (x *CreateSnapshotRequest) String() string { func (*CreateSnapshotRequest) ProtoMessage() {} func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -476,7 +292,7 @@ func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateSnapshotRequest.ProtoReflect.Descriptor instead. func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} } func (x *CreateSnapshotRequest) GetTag() string { @@ -495,7 +311,7 @@ type ApplySnapshotRequest struct { func (x *ApplySnapshotRequest) Reset() { *x = ApplySnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -507,7 +323,7 @@ func (x *ApplySnapshotRequest) String() string { func (*ApplySnapshotRequest) ProtoMessage() {} func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -520,7 +336,7 @@ func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplySnapshotRequest.ProtoReflect.Descriptor instead. func (*ApplySnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} } func (x *ApplySnapshotRequest) GetTag() string { @@ -539,7 +355,7 @@ type DeleteSnapshotRequest struct { func (x *DeleteSnapshotRequest) Reset() { *x = DeleteSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[11] + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -551,7 +367,7 @@ func (x *DeleteSnapshotRequest) String() string { func (*DeleteSnapshotRequest) ProtoMessage() {} func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[11] + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -564,7 +380,7 @@ func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteSnapshotRequest.ProtoReflect.Descriptor instead. func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{11} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} } func (x *DeleteSnapshotRequest) GetTag() string { @@ -583,7 +399,7 @@ type ListSnapshotsResponse struct { func (x *ListSnapshotsResponse) Reset() { *x = ListSnapshotsResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[12] + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -595,7 +411,7 @@ func (x *ListSnapshotsResponse) String() string { func (*ListSnapshotsResponse) ProtoMessage() {} func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[12] + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -608,7 +424,7 @@ func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSnapshotsResponse.ProtoReflect.Descriptor instead. func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{12} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} } func (x *ListSnapshotsResponse) GetSnapshots() string { @@ -627,7 +443,7 @@ type ForwardGuestAgentResponse struct { func (x *ForwardGuestAgentResponse) Reset() { *x = ForwardGuestAgentResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[13] + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -639,7 +455,7 @@ func (x *ForwardGuestAgentResponse) String() string { func (*ForwardGuestAgentResponse) ProtoMessage() {} func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[13] + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -652,7 +468,7 @@ func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardGuestAgentResponse.ProtoReflect.Descriptor instead. func (*ForwardGuestAgentResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{13} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} } func (x *ForwardGuestAgentResponse) GetShouldForward() bool { @@ -671,7 +487,7 @@ type GuestAgentConnResponse struct { func (x *GuestAgentConnResponse) Reset() { *x = GuestAgentConnResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[14] + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -683,7 +499,7 @@ func (x *GuestAgentConnResponse) String() string { func (*GuestAgentConnResponse) ProtoMessage() {} func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[14] + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -696,7 +512,7 @@ func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GuestAgentConnResponse.ProtoReflect.Descriptor instead. func (*GuestAgentConnResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{14} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} } func (x *GuestAgentConnResponse) GetNetConn() []byte { @@ -710,24 +526,15 @@ var File_pkg_driver_external_driver_proto protoreflect.FileDescriptor const file_pkg_driver_external_driver_proto_rawDesc = "" + "\n" + - " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"?\n" + + " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"+\n" + + "\fInfoResponse\x12\x1b\n" + + "\tinfo_json\x18\x01 \x01(\fR\binfoJson\"?\n" + "\rStartResponse\x12\x18\n" + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"\"\n" + - "\fNameResponse\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\"j\n" + + "\x05error\x18\x02 \x01(\tR\x05error\"j\n" + "\x10SetConfigRequest\x120\n" + "\x14instance_config_json\x18\x01 \x01(\fR\x12instanceConfigJson\x12$\n" + - "\x0essh_local_port\x18\x03 \x01(\x03R\fsshLocalPort\"C\n" + - "\x11SetConfigResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x14\n" + - "\x05error\x18\x02 \x01(\tR\x05error\"*\n" + - "\x14GetVSockPortResponse\x12\x12\n" + - "\x04port\x18\x01 \x01(\x03R\x04port\"+\n" + - "\x15GetVirtioPortResponse\x12\x12\n" + - "\x04port\x18\x01 \x01(\tR\x04port\",\n" + - "\x11CanRunGUIResponse\x12\x17\n" + - "\acan_run\x18\x01 \x01(\bR\x06canRun\":\n" + + "\x0essh_local_port\x18\x03 \x01(\x03R\fsshLocalPort\":\n" + "\x1cChangeDisplayPasswordRequest\x12\x1a\n" + "\bpassword\x18\x01 \x01(\tR\bpassword\">\n" + "\x1cGetDisplayConnectionResponse\x12\x1e\n" + @@ -745,8 +552,7 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\x19ForwardGuestAgentResponse\x12%\n" + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"3\n" + "\x16GuestAgentConnResponse\x12\x19\n" + - "\bnet_conn\x18\x01 \x01(\fR\anetConn2\xad\n" + - "\n" + + "\bnet_conn\x18\x01 \x01(\fR\anetConn2\xfb\b\n" + "\x06Driver\x12:\n" + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + @@ -754,8 +560,7 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\n" + "CreateDisk\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x121\n" + "\x05Start\x12\x16.google.protobuf.Empty\x1a\x0e.StartResponse0\x01\x126\n" + - "\x04Stop\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x127\n" + - "\tCanRunGUI\x12\x16.google.protobuf.Empty\x1a\x12.CanRunGUIResponse\x128\n" + + "\x04Stop\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x128\n" + "\x06RunGUI\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12N\n" + "\x15ChangeDisplayPassword\x12\x1d.ChangeDisplayPasswordRequest\x1a\x16.google.protobuf.Empty\x12M\n" + "\x14GetDisplayConnection\x12\x16.google.protobuf.Empty\x1a\x1d.GetDisplayConnectionResponse\x12@\n" + @@ -767,11 +572,9 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\n" + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12C\n" + - "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse0\x01\x12-\n" + - "\x04Name\x12\x16.google.protobuf.Empty\x1a\r.NameResponse\x122\n" + - "\tSetConfig\x12\x11.SetConfigRequest\x1a\x12.SetConfigResponse\x12=\n" + - "\fGetVSockPort\x12\x16.google.protobuf.Empty\x1a\x15.GetVSockPortResponse\x12?\n" + - "\rGetVirtioPort\x12\x16.google.protobuf.Empty\x1a\x16.GetVirtioPortResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" + "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse0\x01\x126\n" + + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x16.google.protobuf.Empty\x120\n" + + "\aGetInfo\x12\x16.google.protobuf.Empty\x1a\r.InfoResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" var ( file_pkg_driver_external_driver_proto_rawDescOnce sync.Once @@ -785,70 +588,60 @@ func file_pkg_driver_external_driver_proto_rawDescGZIP() []byte { return file_pkg_driver_external_driver_proto_rawDescData } -var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_pkg_driver_external_driver_proto_goTypes = []any{ - (*StartResponse)(nil), // 0: StartResponse - (*NameResponse)(nil), // 1: NameResponse + (*InfoResponse)(nil), // 0: InfoResponse + (*StartResponse)(nil), // 1: StartResponse (*SetConfigRequest)(nil), // 2: SetConfigRequest - (*SetConfigResponse)(nil), // 3: SetConfigResponse - (*GetVSockPortResponse)(nil), // 4: GetVSockPortResponse - (*GetVirtioPortResponse)(nil), // 5: GetVirtioPortResponse - (*CanRunGUIResponse)(nil), // 6: CanRunGUIResponse - (*ChangeDisplayPasswordRequest)(nil), // 7: ChangeDisplayPasswordRequest - (*GetDisplayConnectionResponse)(nil), // 8: GetDisplayConnectionResponse - (*CreateSnapshotRequest)(nil), // 9: CreateSnapshotRequest - (*ApplySnapshotRequest)(nil), // 10: ApplySnapshotRequest - (*DeleteSnapshotRequest)(nil), // 11: DeleteSnapshotRequest - (*ListSnapshotsResponse)(nil), // 12: ListSnapshotsResponse - (*ForwardGuestAgentResponse)(nil), // 13: ForwardGuestAgentResponse - (*GuestAgentConnResponse)(nil), // 14: GuestAgentConnResponse - (*emptypb.Empty)(nil), // 15: google.protobuf.Empty + (*ChangeDisplayPasswordRequest)(nil), // 3: ChangeDisplayPasswordRequest + (*GetDisplayConnectionResponse)(nil), // 4: GetDisplayConnectionResponse + (*CreateSnapshotRequest)(nil), // 5: CreateSnapshotRequest + (*ApplySnapshotRequest)(nil), // 6: ApplySnapshotRequest + (*DeleteSnapshotRequest)(nil), // 7: DeleteSnapshotRequest + (*ListSnapshotsResponse)(nil), // 8: ListSnapshotsResponse + (*ForwardGuestAgentResponse)(nil), // 9: ForwardGuestAgentResponse + (*GuestAgentConnResponse)(nil), // 10: GuestAgentConnResponse + (*emptypb.Empty)(nil), // 11: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ - 15, // 0: Driver.Validate:input_type -> google.protobuf.Empty - 15, // 1: Driver.Initialize:input_type -> google.protobuf.Empty - 15, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty - 15, // 3: Driver.Start:input_type -> google.protobuf.Empty - 15, // 4: Driver.Stop:input_type -> google.protobuf.Empty - 15, // 5: Driver.CanRunGUI:input_type -> google.protobuf.Empty - 15, // 6: Driver.RunGUI:input_type -> google.protobuf.Empty - 7, // 7: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest - 15, // 8: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty - 9, // 9: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest - 10, // 10: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest - 11, // 11: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest - 15, // 12: Driver.ListSnapshots:input_type -> google.protobuf.Empty - 15, // 13: Driver.Register:input_type -> google.protobuf.Empty - 15, // 14: Driver.Unregister:input_type -> google.protobuf.Empty - 15, // 15: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 15, // 16: Driver.GuestAgentConn:input_type -> google.protobuf.Empty - 15, // 17: Driver.Name:input_type -> google.protobuf.Empty - 2, // 18: Driver.SetConfig:input_type -> SetConfigRequest - 15, // 19: Driver.GetVSockPort:input_type -> google.protobuf.Empty - 15, // 20: Driver.GetVirtioPort:input_type -> google.protobuf.Empty - 15, // 21: Driver.Validate:output_type -> google.protobuf.Empty - 15, // 22: Driver.Initialize:output_type -> google.protobuf.Empty - 15, // 23: Driver.CreateDisk:output_type -> google.protobuf.Empty - 0, // 24: Driver.Start:output_type -> StartResponse - 15, // 25: Driver.Stop:output_type -> google.protobuf.Empty - 6, // 26: Driver.CanRunGUI:output_type -> CanRunGUIResponse - 15, // 27: Driver.RunGUI:output_type -> google.protobuf.Empty - 15, // 28: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty - 8, // 29: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse - 15, // 30: Driver.CreateSnapshot:output_type -> google.protobuf.Empty - 15, // 31: Driver.ApplySnapshot:output_type -> google.protobuf.Empty - 15, // 32: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty - 12, // 33: Driver.ListSnapshots:output_type -> ListSnapshotsResponse - 15, // 34: Driver.Register:output_type -> google.protobuf.Empty - 15, // 35: Driver.Unregister:output_type -> google.protobuf.Empty - 13, // 36: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 14, // 37: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse - 1, // 38: Driver.Name:output_type -> NameResponse - 3, // 39: Driver.SetConfig:output_type -> SetConfigResponse - 4, // 40: Driver.GetVSockPort:output_type -> GetVSockPortResponse - 5, // 41: Driver.GetVirtioPort:output_type -> GetVirtioPortResponse - 21, // [21:42] is the sub-list for method output_type - 0, // [0:21] is the sub-list for method input_type + 11, // 0: Driver.Validate:input_type -> google.protobuf.Empty + 11, // 1: Driver.Initialize:input_type -> google.protobuf.Empty + 11, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty + 11, // 3: Driver.Start:input_type -> google.protobuf.Empty + 11, // 4: Driver.Stop:input_type -> google.protobuf.Empty + 11, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty + 3, // 6: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest + 11, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty + 5, // 8: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest + 6, // 9: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest + 7, // 10: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest + 11, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty + 11, // 12: Driver.Register:input_type -> google.protobuf.Empty + 11, // 13: Driver.Unregister:input_type -> google.protobuf.Empty + 11, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty + 11, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty + 2, // 16: Driver.SetConfig:input_type -> SetConfigRequest + 11, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty + 11, // 18: Driver.Validate:output_type -> google.protobuf.Empty + 11, // 19: Driver.Initialize:output_type -> google.protobuf.Empty + 11, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty + 1, // 21: Driver.Start:output_type -> StartResponse + 11, // 22: Driver.Stop:output_type -> google.protobuf.Empty + 11, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty + 11, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty + 4, // 25: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse + 11, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty + 11, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty + 11, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty + 8, // 29: Driver.ListSnapshots:output_type -> ListSnapshotsResponse + 11, // 30: Driver.Register:output_type -> google.protobuf.Empty + 11, // 31: Driver.Unregister:output_type -> google.protobuf.Empty + 9, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse + 10, // 33: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse + 11, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty + 0, // 35: Driver.GetInfo:output_type -> InfoResponse + 18, // [18:36] is the sub-list for method output_type + 0, // [0:18] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -865,7 +658,7 @@ func file_pkg_driver_external_driver_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc)), NumEnums: 0, - NumMessages: 15, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index 3ff6bacd2cf..b1d4d5d58a2 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -11,7 +11,6 @@ service Driver { rpc Start(google.protobuf.Empty) returns (stream StartResponse); rpc Stop(google.protobuf.Empty) returns (google.protobuf.Empty); - rpc CanRunGUI(google.protobuf.Empty) returns (CanRunGUIResponse); rpc RunGUI(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ChangeDisplayPassword(ChangeDisplayPasswordRequest) returns (google.protobuf.Empty); rpc GetDisplayConnection(google.protobuf.Empty) returns (GetDisplayConnectionResponse); @@ -27,11 +26,13 @@ service Driver { rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); rpc GuestAgentConn(google.protobuf.Empty) returns (stream GuestAgentConnResponse); - rpc Name(google.protobuf.Empty) returns (NameResponse); - rpc SetConfig(SetConfigRequest) returns (SetConfigResponse); - - rpc GetVSockPort(google.protobuf.Empty) returns (GetVSockPortResponse); - rpc GetVirtioPort(google.protobuf.Empty) returns (GetVirtioPortResponse); + rpc SetConfig(SetConfigRequest) returns (google.protobuf.Empty); + + rpc GetInfo(google.protobuf.Empty) returns (InfoResponse); +} + +message InfoResponse{ + bytes info_json = 1; } message StartResponse { @@ -39,32 +40,11 @@ message StartResponse { string error = 2; } -message NameResponse { - string name = 1; -} - message SetConfigRequest { bytes instance_config_json = 1; int64 ssh_local_port = 3; } -message SetConfigResponse { - bool success = 1; - string error = 2; -} - -message GetVSockPortResponse { - int64 port = 1; -} - -message GetVirtioPortResponse { - string port = 1; -} - -message CanRunGUIResponse { - bool can_run = 1; -} - message ChangeDisplayPasswordRequest { string password = 1; } diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index c2eeb282eb3..cf69dad0cd9 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -25,7 +25,6 @@ const ( Driver_CreateDisk_FullMethodName = "/Driver/CreateDisk" Driver_Start_FullMethodName = "/Driver/Start" Driver_Stop_FullMethodName = "/Driver/Stop" - Driver_CanRunGUI_FullMethodName = "/Driver/CanRunGUI" Driver_RunGUI_FullMethodName = "/Driver/RunGUI" Driver_ChangeDisplayPassword_FullMethodName = "/Driver/ChangeDisplayPassword" Driver_GetDisplayConnection_FullMethodName = "/Driver/GetDisplayConnection" @@ -37,10 +36,8 @@ const ( Driver_Unregister_FullMethodName = "/Driver/Unregister" Driver_ForwardGuestAgent_FullMethodName = "/Driver/ForwardGuestAgent" Driver_GuestAgentConn_FullMethodName = "/Driver/GuestAgentConn" - Driver_Name_FullMethodName = "/Driver/Name" Driver_SetConfig_FullMethodName = "/Driver/SetConfig" - Driver_GetVSockPort_FullMethodName = "/Driver/GetVSockPort" - Driver_GetVirtioPort_FullMethodName = "/Driver/GetVirtioPort" + Driver_GetInfo_FullMethodName = "/Driver/GetInfo" ) // DriverClient is the client API for Driver service. @@ -52,7 +49,6 @@ type DriverClient interface { CreateDisk(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Start(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StartResponse], error) Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) - CanRunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CanRunGUIResponse, error) RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ChangeDisplayPassword(ctx context.Context, in *ChangeDisplayPasswordRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetDisplayConnection(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetDisplayConnectionResponse, error) @@ -64,10 +60,8 @@ type DriverClient interface { Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GuestAgentConnResponse], error) - Name(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NameResponse, error) - SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) - GetVSockPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVSockPortResponse, error) - GetVirtioPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVirtioPortResponse, error) + SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) } type driverClient struct { @@ -137,16 +131,6 @@ func (c *driverClient) Stop(ctx context.Context, in *emptypb.Empty, opts ...grpc return out, nil } -func (c *driverClient) CanRunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CanRunGUIResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CanRunGUIResponse) - err := c.cc.Invoke(ctx, Driver_CanRunGUI_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *driverClient) RunGUI(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) @@ -266,19 +250,9 @@ func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, op // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type Driver_GuestAgentConnClient = grpc.ServerStreamingClient[GuestAgentConnResponse] -func (c *driverClient) Name(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*NameResponse, error) { +func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(NameResponse) - err := c.cc.Invoke(ctx, Driver_Name_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SetConfigResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_SetConfig_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -286,20 +260,10 @@ func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts return out, nil } -func (c *driverClient) GetVSockPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVSockPortResponse, error) { +func (c *driverClient) GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetVSockPortResponse) - err := c.cc.Invoke(ctx, Driver_GetVSockPort_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *driverClient) GetVirtioPort(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetVirtioPortResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetVirtioPortResponse) - err := c.cc.Invoke(ctx, Driver_GetVirtioPort_FullMethodName, in, out, cOpts...) + out := new(InfoResponse) + err := c.cc.Invoke(ctx, Driver_GetInfo_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -315,7 +279,6 @@ type DriverServer interface { CreateDisk(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Start(*emptypb.Empty, grpc.ServerStreamingServer[StartResponse]) error Stop(context.Context, *emptypb.Empty) (*emptypb.Empty, error) - CanRunGUI(context.Context, *emptypb.Empty) (*CanRunGUIResponse, error) RunGUI(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ChangeDisplayPassword(context.Context, *ChangeDisplayPasswordRequest) (*emptypb.Empty, error) GetDisplayConnection(context.Context, *emptypb.Empty) (*GetDisplayConnectionResponse, error) @@ -327,10 +290,8 @@ type DriverServer interface { Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error - Name(context.Context, *emptypb.Empty) (*NameResponse, error) - SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) - GetVSockPort(context.Context, *emptypb.Empty) (*GetVSockPortResponse, error) - GetVirtioPort(context.Context, *emptypb.Empty) (*GetVirtioPortResponse, error) + SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) + GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) mustEmbedUnimplementedDriverServer() } @@ -356,9 +317,6 @@ func (UnimplementedDriverServer) Start(*emptypb.Empty, grpc.ServerStreamingServe func (UnimplementedDriverServer) Stop(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented") } -func (UnimplementedDriverServer) CanRunGUI(context.Context, *emptypb.Empty) (*CanRunGUIResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CanRunGUI not implemented") -} func (UnimplementedDriverServer) RunGUI(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method RunGUI not implemented") } @@ -392,17 +350,11 @@ func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Emp func (UnimplementedDriverServer) GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error { return status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") } -func (UnimplementedDriverServer) Name(context.Context, *emptypb.Empty) (*NameResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Name not implemented") -} -func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) { +func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method SetConfig not implemented") } -func (UnimplementedDriverServer) GetVSockPort(context.Context, *emptypb.Empty) (*GetVSockPortResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetVSockPort not implemented") -} -func (UnimplementedDriverServer) GetVirtioPort(context.Context, *emptypb.Empty) (*GetVirtioPortResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetVirtioPort not implemented") +func (UnimplementedDriverServer) GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented") } func (UnimplementedDriverServer) mustEmbedUnimplementedDriverServer() {} func (UnimplementedDriverServer) testEmbeddedByValue() {} @@ -508,24 +460,6 @@ func _Driver_Stop_Handler(srv interface{}, ctx context.Context, dec func(interfa return interceptor(ctx, in, info, handler) } -func _Driver_CanRunGUI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DriverServer).CanRunGUI(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Driver_CanRunGUI_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DriverServer).CanRunGUI(ctx, req.(*emptypb.Empty)) - } - return interceptor(ctx, in, info, handler) -} - func _Driver_RunGUI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -717,24 +651,6 @@ func _Driver_GuestAgentConn_Handler(srv interface{}, stream grpc.ServerStream) e // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type Driver_GuestAgentConnServer = grpc.ServerStreamingServer[GuestAgentConnResponse] -func _Driver_Name_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DriverServer).Name(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Driver_Name_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DriverServer).Name(ctx, req.(*emptypb.Empty)) - } - return interceptor(ctx, in, info, handler) -} - func _Driver_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetConfigRequest) if err := dec(in); err != nil { @@ -753,38 +669,20 @@ func _Driver_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } -func _Driver_GetVSockPort_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DriverServer).GetVSockPort(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Driver_GetVSockPort_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DriverServer).GetVSockPort(ctx, req.(*emptypb.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _Driver_GetVirtioPort_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _Driver_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(DriverServer).GetVirtioPort(ctx, in) + return srv.(DriverServer).GetInfo(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Driver_GetVirtioPort_FullMethodName, + FullMethod: Driver_GetInfo_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DriverServer).GetVirtioPort(ctx, req.(*emptypb.Empty)) + return srv.(DriverServer).GetInfo(ctx, req.(*emptypb.Empty)) } return interceptor(ctx, in, info, handler) } @@ -812,10 +710,6 @@ var Driver_ServiceDesc = grpc.ServiceDesc{ MethodName: "Stop", Handler: _Driver_Stop_Handler, }, - { - MethodName: "CanRunGUI", - Handler: _Driver_CanRunGUI_Handler, - }, { MethodName: "RunGUI", Handler: _Driver_RunGUI_Handler, @@ -856,21 +750,13 @@ var Driver_ServiceDesc = grpc.ServiceDesc{ MethodName: "ForwardGuestAgent", Handler: _Driver_ForwardGuestAgent_Handler, }, - { - MethodName: "Name", - Handler: _Driver_Name_Handler, - }, { MethodName: "SetConfig", Handler: _Driver_SetConfig_Handler, }, { - MethodName: "GetVSockPort", - Handler: _Driver_GetVSockPort_Handler, - }, - { - MethodName: "GetVirtioPort", - Handler: _Driver_GetVirtioPort_Handler, + MethodName: "GetInfo", + Handler: _Driver_GetInfo_Handler, }, }, Streams: []grpc.StreamDesc{ diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index d0c04378a9a..e3064bb12d4 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -12,22 +12,13 @@ import ( // TODO: Add more 3 functions Start, SetConfig & GuestAgentConn -func (s *DriverServer) Name(ctx context.Context, empty *emptypb.Empty) (*pb.NameResponse, error) { - s.logger.Debug("Received Name request") - return &pb.NameResponse{Name: s.driver.Name()}, nil -} - -func (s *DriverServer) GetVirtioPort(ctx context.Context, empty *emptypb.Empty) (*pb.GetVirtioPortResponse, error) { - s.logger.Debug("Received GetVirtioPort request") - return &pb.GetVirtioPortResponse{ - Port: s.driver.GetVirtioPort(), - }, nil -} - -func (s *DriverServer) GetVSockPort(ctx context.Context, empty *emptypb.Empty) (*pb.GetVSockPortResponse, error) { - s.logger.Debug("Received GetVSockPort request") - return &pb.GetVSockPortResponse{ - Port: int64(s.driver.GetVSockPort()), +func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { + s.logger.Debug("Received GetInfo request") + return &pb.InfoResponse{ + DriverName: s.driver.GetInfo().DriverName, + CanRunGui: s.driver.GetInfo().CanRunGUI, + VsockPort: int64(s.driver.GetInfo().VsockPort), + VirtioPort: s.driver.GetInfo().VirtioPort, }, nil } @@ -75,11 +66,6 @@ func (s *DriverServer) Stop(ctx context.Context, empty *emptypb.Empty) (*emptypb return empty, nil } -func (s *DriverServer) CanRunGUI(ctx context.Context, empty *emptypb.Empty) (*pb.CanRunGUIResponse, error) { - s.logger.Debug("Received CanRunGUI request") - return &pb.CanRunGUIResponse{CanRun: s.driver.CanRunGUI()}, nil -} - func (s *DriverServer) RunGUI(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { s.logger.Debug("Received RunGUI request") err := s.driver.RunGUI() diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 57a0da1f091..c1c50918057 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -29,7 +29,7 @@ func Serve(driver driver.Driver) { logger.SetFormatter(&logrus.TextFormatter{ FullTimestamp: true, }) - logger.Infof("Starting external driver server for %s", driver.Name()) + logger.Infof("Starting external driver server for %s", driver.GetInfo().DriverName) pipeConn := &PipeConn{ Reader: os.Stdin, From 9b2281961dcd51ae7e2c647cf445eaa6d4f538ae Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 2 Jun 2025 21:45:34 +0530 Subject: [PATCH 28/49] driver(external): implement Start() & SetConfig() as server methods Signed-off-by: Ansuman Sahoo --- pkg/driver/external/server/methods.go | 98 +++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index e3064bb12d4..40486b0b716 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -5,20 +5,106 @@ package server import ( "context" + "encoding/json" - pb "github.com/lima-vm/lima/pkg/driver/external" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" + + pb "github.com/lima-vm/lima/pkg/driver/external" + "github.com/lima-vm/lima/pkg/store" ) -// TODO: Add more 3 functions Start, SetConfig & GuestAgentConn +func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) error { + s.logger.Debug("Received Start request") + errChan, err := s.driver.Start(stream.Context()) + if err != nil { + s.logger.Errorf("Start failed: %v", err) + return nil + } + + for { + select { + case err, ok := <-errChan: + if !ok { + s.logger.Debug("Start error channel closed") + if err := stream.Send(&pb.StartResponse{Success: true}); err != nil { + s.logger.Errorf("Failed to send success response: %v", err) + return status.Errorf(codes.Internal, "failed to send success response: %v", err) + } + return nil + } + if err != nil { + s.logger.Errorf("Error during Start: %v", err) + if err := stream.Send(&pb.StartResponse{Error: err.Error(), Success: false}); err != nil { + s.logger.Errorf("Failed to send error response: %v", err) + return status.Errorf(codes.Internal, "failed to send error response: %v", err) + } + } + case <-stream.Context().Done(): + s.logger.Debug("Stream context done, stopping Start") + return nil + } + } +} + +func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) (*emptypb.Empty, error) { + s.logger.Debugf("Received SetConfig request") + var inst *store.Instance + + if err := json.Unmarshal(req.InstanceConfigJson, inst); err != nil { + s.logger.Errorf("Failed to unmarshal InstanceConfigJson: %v", err) + return &emptypb.Empty{}, err + } + + s.driver.SetConfig(inst, int(req.SshLocalPort)) + + return &emptypb.Empty{}, nil +} + +// TODO +// func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_GuestAgentConnServer) error { +// s.logger.Debug("Received GuestAgentConn request") +// conn, err := s.driver.GuestAgentConn(stream.Context()) +// if err != nil { +// s.logger.Errorf("GuestAgentConn failed: %v", err) +// return err +// } + +// defer conn.Close() + +// buf := make([]byte, 1024) + +// for { +// n, err := conn.Read(buf) +// if err != nil { +// if err == io.EOF { +// return nil +// } +// return status.Errorf(codes.Internal, "error reading: %v", err) +// } + +// msg := &pb.GuestAgentConnResponse{NetConn: buf[:n]} +// if err := stream.Send(msg); err != nil { +// return err +// } +// } +// s.logger.Debug("GuestAgentConn succeeded") +// return nil +// } func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { s.logger.Debug("Received GetInfo request") + info := s.driver.GetInfo() + + infoJson, err := json.Marshal(info) + if err != nil { + s.logger.Errorf("Failed to marshal driver info: %v", err) + return nil, status.Errorf(codes.Internal, "failed to marshal driver info: %v", err) + } + return &pb.InfoResponse{ - DriverName: s.driver.GetInfo().DriverName, - CanRunGui: s.driver.GetInfo().CanRunGUI, - VsockPort: int64(s.driver.GetInfo().VsockPort), - VirtioPort: s.driver.GetInfo().VirtioPort, + InfoJson: infoJson, }, nil } From e2e0fd7c790db0390468dd3605a2087c0d6a6f01 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 3 Jun 2025 22:40:45 +0530 Subject: [PATCH 29/49] driver(external): complete client grpc implementation and one server function Signed-off-by: Ansuman Sahoo --- pkg/driver/external/client/client.go | 51 ---- pkg/driver/external/client/methods.go | 341 ++++++++++++++++++++++++++ pkg/driver/external/client/pipe.go | 61 +++++ pkg/driver/external/client/stream.go | 93 +++++++ pkg/driver/external/server/methods.go | 59 +++-- 5 files changed, 524 insertions(+), 81 deletions(-) create mode 100644 pkg/driver/external/client/methods.go create mode 100644 pkg/driver/external/client/pipe.go create mode 100644 pkg/driver/external/client/stream.go diff --git a/pkg/driver/external/client/client.go b/pkg/driver/external/client/client.go index cd07e3c418d..9d536939af2 100644 --- a/pkg/driver/external/client/client.go +++ b/pkg/driver/external/client/client.go @@ -63,54 +63,3 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus. logger: logger, }, nil } - -type PipeConn struct { - Reader io.Reader - Writer io.Writer -} - -func (p *PipeConn) Read(b []byte) (n int, err error) { - return p.Reader.Read(b) -} - -func (p *PipeConn) Write(b []byte) (n int, err error) { - return p.Writer.Write(b) -} - -func (p *PipeConn) Close() error { - var err error - if closer, ok := p.Reader.(io.Closer); ok { - err = closer.Close() - } - if closer, ok := p.Writer.(io.Closer); ok { - if closeErr := closer.Close(); closeErr != nil && err == nil { - err = closeErr - } - } - return err -} - -func (p *PipeConn) LocalAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) RemoteAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) SetDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetReadDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetWriteDeadline(t time.Time) error { - return nil -} - -type pipeAddr struct{} - -func (pipeAddr) Network() string { return "pipe" } -func (pipeAddr) String() string { return "pipe" } diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go new file mode 100644 index 00000000000..6e3f7f02d57 --- /dev/null +++ b/pkg/driver/external/client/methods.go @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "context" + "encoding/json" + "errors" + "net" + "time" + + "google.golang.org/protobuf/types/known/emptypb" + + "github.com/lima-vm/lima/pkg/driver" + pb "github.com/lima-vm/lima/pkg/driver/external" + "github.com/lima-vm/lima/pkg/store" +) + +func (d *DriverClient) Validate() error { + d.logger.Debug("Validating driver for the given config") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.Validate(ctx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Validation failed: %v", err) + return err + } + + d.logger.Debug("Driver validated successfully") + return nil +} + +func (d *DriverClient) Initialize(ctx context.Context) error { + d.logger.Debug("Initializing driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + _, err := d.DriverSvc.Initialize(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Initialization failed: %v", err) + return err + } + + d.logger.Debug("Driver instance initialized successfully") + return nil +} + +func (d *DriverClient) CreateDisk(ctx context.Context) error { + d.logger.Debug("Creating disk for the instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + _, err := d.DriverSvc.CreateDisk(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Disk creation failed: %v", err) + return err + } + + d.logger.Debug("Disk created successfully") + return nil +} + +func (d *DriverClient) Start(ctx context.Context) (chan error, error) { + d.logger.Debug("Starting driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + stream, err := d.DriverSvc.Start(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to start driver instance: %v", err) + return nil, err + } + + errCh := make(chan error, 1) + go func() { + for { + errorStream, err := stream.Recv() + if err != nil { + d.logger.Errorf("Error receiving response from driver: %v", err) + return + } + d.logger.Debugf("Received response: %v", errorStream) + if !errorStream.Success { + errCh <- errors.New(errorStream.Error) + } else { + errCh <- nil + return + } + } + }() + + d.logger.Debug("Driver instance started successfully") + return errCh, nil +} + +func (d *DriverClient) Stop(ctx context.Context) error { + d.logger.Debug("Stopping driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + _, err := d.DriverSvc.Stop(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to stop driver instance: %v", err) + return err + } + + d.logger.Debug("Driver instance stopped successfully") + return nil +} + +func (d *DriverClient) RunGUI() error { + d.logger.Debug("Running GUI for the driver instance") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.RunGUI(ctx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to run GUI: %v", err) + return err + } + + d.logger.Debug("GUI started successfully") + return nil +} + +func (d *DriverClient) ChangeDisplayPassword(ctx context.Context, password string) error { + d.logger.Debug("Changing display password for the driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.ChangeDisplayPassword(connCtx, &pb.ChangeDisplayPasswordRequest{ + Password: password, + }) + if err != nil { + d.logger.Errorf("Failed to change display password: %v", err) + return err + } + + d.logger.Debug("Display password changed successfully") + return nil +} + +func (d *DriverClient) GetDisplayConnection(ctx context.Context) (string, error) { + d.logger.Debug("Getting display connection for the driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + resp, err := d.DriverSvc.GetDisplayConnection(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to get display connection: %v", err) + return "", err + } + + d.logger.Debugf("Display connection retrieved: %s", resp.Connection) + return resp.Connection, nil +} + +func (d *DriverClient) CreateSnapshot(ctx context.Context, tag string) error { + d.logger.Debugf("Creating snapshot with tag: %s", tag) + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.CreateSnapshot(connCtx, &pb.CreateSnapshotRequest{ + Tag: tag, + }) + if err != nil { + d.logger.Errorf("Failed to create snapshot: %v", err) + return err + } + + d.logger.Debugf("Snapshot '%s' created successfully", tag) + return nil +} + +func (d *DriverClient) ApplySnapshot(ctx context.Context, tag string) error { + d.logger.Debugf("Applying snapshot with tag: %s", tag) + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.ApplySnapshot(connCtx, &pb.ApplySnapshotRequest{ + Tag: tag, + }) + if err != nil { + d.logger.Errorf("Failed to apply snapshot: %v", err) + return err + } + + d.logger.Debugf("Snapshot '%s' applied successfully", tag) + return nil +} + +func (d *DriverClient) DeleteSnapshot(ctx context.Context, tag string) error { + d.logger.Debugf("Deleting snapshot with tag: %s", tag) + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.DeleteSnapshot(connCtx, &pb.DeleteSnapshotRequest{ + Tag: tag, + }) + if err != nil { + d.logger.Errorf("Failed to delete snapshot: %v", err) + return err + } + + d.logger.Debugf("Snapshot '%s' deleted successfully", tag) + return nil +} + +func (d *DriverClient) ListSnapshots(ctx context.Context) (string, error) { + d.logger.Debug("Listing snapshots") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + resp, err := d.DriverSvc.ListSnapshots(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to list snapshots: %v", err) + return "", err + } + + d.logger.Debugf("Snapshots listed successfully: %s", resp.Snapshots) + return resp.Snapshots, nil +} + +func (d *DriverClient) Register(ctx context.Context) error { + d.logger.Debug("Registering driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + _, err := d.DriverSvc.Register(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to register driver instance: %v", err) + return err + } + + d.logger.Debug("Driver instance registered successfully") + return nil +} + +func (d *DriverClient) Unregister(ctx context.Context) error { + d.logger.Debug("Unregistering driver instance") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := d.DriverSvc.Unregister(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to unregister driver instance: %v", err) + return err + } + + d.logger.Debug("Driver instance unregistered successfully") + return nil +} + +func (d *DriverClient) ForwardGuestAgent() bool { + d.logger.Debug("Checking if guest agent needs to be forwarded") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to check guest agent forwarding: %v", err) + return false + } + + d.logger.Debugf("Guest agent forwarding status: %v", resp.ShouldForward) + return resp.ShouldForward +} + +// NOTE: This method is might not work correctly. +func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { + d.logger.Debug("Getting guest agent connection") + + connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + connStream, err := d.DriverSvc.GuestAgentConn(connCtx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to get guest agent connection: %v", err) + return nil, err + } + + return streamToConn(connStream), nil +} + +func (d *DriverClient) GetInfo() driver.Info { + d.logger.Debug("Getting driver info") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := d.DriverSvc.GetInfo(ctx, &emptypb.Empty{}) + if err != nil { + d.logger.Errorf("Failed to get driver info: %v", err) + return driver.Info{} + } + + var info driver.Info + if err := json.Unmarshal(resp.InfoJson, &info); err != nil { + d.logger.Errorf("Failed to unmarshal driver info: %v", err) + return driver.Info{} + } + + d.logger.Debugf("Driver info retrieved: %+v", info) + return info +} + +func (d *DriverClient) SetConfig(inst *store.Instance, sshLocalPort int) { + d.logger.Debugf("Setting config for instance %s with SSH local port %d", inst.Name, sshLocalPort) + + instJson, err := json.Marshal(inst) + if err != nil { + d.logger.Errorf("Failed to marshal instance config: %v", err) + return + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err = d.DriverSvc.SetConfig(ctx, &pb.SetConfigRequest{ + InstanceConfigJson: instJson, + SshLocalPort: int64(sshLocalPort), + }) + if err != nil { + d.logger.Errorf("Failed to set config: %v", err) + return + } + + d.logger.Debugf("Config set successfully for instance %s", inst.Name) +} diff --git a/pkg/driver/external/client/pipe.go b/pkg/driver/external/client/pipe.go new file mode 100644 index 00000000000..9dfc36ae791 --- /dev/null +++ b/pkg/driver/external/client/pipe.go @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "io" + "net" + "time" +) + +type PipeConn struct { + Reader io.Reader + Writer io.Writer +} + +func (p *PipeConn) Read(b []byte) (n int, err error) { + return p.Reader.Read(b) +} + +func (p *PipeConn) Write(b []byte) (n int, err error) { + return p.Writer.Write(b) +} + +func (p *PipeConn) Close() error { + var err error + if closer, ok := p.Reader.(io.Closer); ok { + err = closer.Close() + } + if closer, ok := p.Writer.(io.Closer); ok { + if closeErr := closer.Close(); closeErr != nil && err == nil { + err = closeErr + } + } + return err +} + +func (p *PipeConn) LocalAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) RemoteAddr() net.Addr { + return pipeAddr{} +} + +func (p *PipeConn) SetDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetReadDeadline(t time.Time) error { + return nil +} + +func (p *PipeConn) SetWriteDeadline(t time.Time) error { + return nil +} + +type pipeAddr struct{} + +func (pipeAddr) Network() string { return "pipe" } +func (pipeAddr) String() string { return "pipe" } diff --git a/pkg/driver/external/client/stream.go b/pkg/driver/external/client/stream.go new file mode 100644 index 00000000000..ff16a8fe636 --- /dev/null +++ b/pkg/driver/external/client/stream.go @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "errors" + "io" + "net" + "sync" + "time" + + pb "github.com/lima-vm/lima/pkg/driver/external" +) + +type streamConn struct { + stream pb.Driver_GuestAgentConnClient + readBuf []byte + readMu sync.Mutex + closeCh chan struct{} + closeOnce sync.Once + closed bool +} + +func streamToConn(stream pb.Driver_GuestAgentConnClient) *streamConn { + return &streamConn{ + stream: stream, + closeCh: make(chan struct{}), + } +} + +func (c *streamConn) Read(b []byte) (int, error) { + c.readMu.Lock() + defer c.readMu.Unlock() + + if c.closed { + return 0, io.EOF + } + + // Use any leftover data first + if len(c.readBuf) > 0 { + n := copy(b, c.readBuf) + c.readBuf = c.readBuf[n:] + return n, nil + } + + // Receive from stream + msg, err := c.stream.Recv() + if err != nil { + if err == io.EOF { + c.closed = true + return 0, io.EOF + } + return 0, err + } + + // Copy data to buffer + n := copy(b, msg.NetConn) + if n < len(msg.NetConn) { + // Store remaining data for next read + c.readBuf = make([]byte, len(msg.NetConn)-n) + copy(c.readBuf, msg.NetConn[n:]) + } + + return n, nil +} + +func (c *streamConn) Write(b []byte) (int, error) { + return 0, errors.New("write not supported on read-only stream connection") +} + +func (c *streamConn) Close() error { + c.closeOnce.Do(func() { + c.readMu.Lock() + c.closed = true + c.readMu.Unlock() + close(c.closeCh) + c.stream.CloseSend() + }) + return nil +} + +func (c *streamConn) LocalAddr() net.Addr { return &grpcAddr{} } +func (c *streamConn) RemoteAddr() net.Addr { return &grpcAddr{} } + +func (c *streamConn) SetDeadline(t time.Time) error { return nil } +func (c *streamConn) SetReadDeadline(t time.Time) error { return nil } +func (c *streamConn) SetWriteDeadline(t time.Time) error { return nil } + +type grpcAddr struct{} + +func (grpcAddr) Network() string { return "grpc" } +func (grpcAddr) String() string { return "grpc-stream" } diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 40486b0b716..fbadb00b9b8 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -6,6 +6,7 @@ package server import ( "context" "encoding/json" + "io" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -62,36 +63,34 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) return &emptypb.Empty{}, nil } -// TODO -// func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_GuestAgentConnServer) error { -// s.logger.Debug("Received GuestAgentConn request") -// conn, err := s.driver.GuestAgentConn(stream.Context()) -// if err != nil { -// s.logger.Errorf("GuestAgentConn failed: %v", err) -// return err -// } - -// defer conn.Close() - -// buf := make([]byte, 1024) - -// for { -// n, err := conn.Read(buf) -// if err != nil { -// if err == io.EOF { -// return nil -// } -// return status.Errorf(codes.Internal, "error reading: %v", err) -// } - -// msg := &pb.GuestAgentConnResponse{NetConn: buf[:n]} -// if err := stream.Send(msg); err != nil { -// return err -// } -// } -// s.logger.Debug("GuestAgentConn succeeded") -// return nil -// } +// NOTE: If this doesn't work, try with bidirectional streaming(like in buildkit) and see if that helps. +func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_GuestAgentConnServer) error { + s.logger.Debug("Received GuestAgentConn request") + conn, err := s.driver.GuestAgentConn(stream.Context()) + if err != nil { + s.logger.Errorf("GuestAgentConn failed: %v", err) + return err + } + + defer conn.Close() + + buf := make([]byte, 32*1<<10) + + for { + n, err := conn.Read(buf) + if err != nil { + if err == io.EOF { + return nil + } + return status.Errorf(codes.Internal, "error reading: %v", err) + } + + msg := &pb.GuestAgentConnResponse{NetConn: buf[:n]} + if err := stream.Send(msg); err != nil { + return err + } + } +} func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { s.logger.Debug("Received GetInfo request") From 43a13052b4e18da3577d73464d8da1cc7d9bc129 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 3 Jun 2025 22:42:23 +0530 Subject: [PATCH 30/49] driver(external): tweak some external driver manager code Signed-off-by: Ansuman Sahoo --- pkg/driver/qemu/cmd/main.go | 14 +++++ pkg/registry/registry.go | 118 +++++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 49 deletions(-) create mode 100644 pkg/driver/qemu/cmd/main.go diff --git a/pkg/driver/qemu/cmd/main.go b/pkg/driver/qemu/cmd/main.go new file mode 100644 index 00000000000..6e4b1d68015 --- /dev/null +++ b/pkg/driver/qemu/cmd/main.go @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "github.com/lima-vm/lima/pkg/driver/external/server" + "github.com/lima-vm/lima/pkg/driver/qemu" +) + +func main() { + driver := qemu.New() + server.Serve(driver) +} diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index d2dd5aff2f1..a77486cbf15 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -4,7 +4,9 @@ package registry import ( + "context" "fmt" + "io" "os" "os/exec" "path/filepath" @@ -12,20 +14,31 @@ import ( "sync" "github.com/lima-vm/lima/pkg/driver" - "github.com/lima-vm/lima/pkg/usrlocalsharelima" + "github.com/lima-vm/lima/pkg/driver/external/client" "github.com/sirupsen/logrus" ) +type ExternalDriver struct { + Name string + Command *exec.Cmd + Stdin io.WriteCloser + Stdout io.ReadCloser + Client *client.DriverClient // Client is the gRPC client for the external driver + Path string + ctx context.Context + cancelFunc context.CancelFunc +} + type Registry struct { - drivers map[string]driver.Driver - externalDrivers map[string]string // For now mapping external driver names to paths + internalDrivers map[string]driver.Driver + externalDrivers map[string]*ExternalDriver mu sync.RWMutex } func NewRegistry() *Registry { return &Registry{ - drivers: make(map[string]driver.Driver), - externalDrivers: make(map[string]string), + internalDrivers: make(map[string]driver.Driver), + externalDrivers: make(map[string]*ExternalDriver), } } @@ -34,10 +47,11 @@ func (r *Registry) List() []string { defer r.mu.RUnlock() var names []string - for name := range r.drivers { + for name := range r.internalDrivers { names = append(names, name) } + r.DiscoverDrivers() for name := range r.externalDrivers { names = append(names, name+" (external)") } @@ -48,46 +62,48 @@ func (r *Registry) Get(name string) (driver.Driver, bool) { r.mu.RLock() defer r.mu.RUnlock() - driver, exists := r.drivers[name] - return driver, exists -} - -func (r *Registry) GetExternalDriver(name string) (string, bool) { - r.mu.RLock() - defer r.mu.RUnlock() + driver, exists := r.internalDrivers[name] + if !exists { + externalDriver, exists := r.externalDrivers[name] + if exists { + return externalDriver.Client, true + } - plugin, exists := r.externalDrivers[name] - return plugin, exists + } + return driver, exists } -func (r *Registry) RegisterPlugin(name, path string) { +func (r *Registry) RegisterDriver(name, path string) { r.mu.Lock() defer r.mu.Unlock() if _, exists := r.externalDrivers[name]; exists { - logrus.Debugf("Plugin %q is already registered, skipping", name) + logrus.Debugf("Driver %q is already registered, skipping", name) return } - r.externalDrivers[name] = path - logrus.Debugf("Registered plugin %q at %s", name, path) + r.externalDrivers[name].Path = path + logrus.Debugf("Registered driver %q at %s", name, path) } -func (r *Registry) DiscoverPlugins() error { - limaShareDir, err := usrlocalsharelima.Dir() - if err != nil { - return fmt.Errorf("failed to determine Lima share directory: %w", err) - } - stdPluginDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") - - if _, err := os.Stat(stdPluginDir); err == nil { - if err := r.discoverPluginsInDir(stdPluginDir); err != nil { - logrus.Warnf("Error discovering plugins in %s: %v", stdPluginDir, err) - } - } - - if pluginPaths := os.Getenv("LIMA_DRIVERS_PATH"); pluginPaths != "" { - paths := filepath.SplitList(pluginPaths) +func (r *Registry) DiscoverDrivers() error { + // limaShareDir, err := usrlocalsharelima.Dir() + // if err != nil { + // return fmt.Errorf("failed to determine Lima share directory: %w", err) + // } + // fmt.Printf("Discovering drivers in %s\n", limaShareDir) + // stdDriverDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") + + // if _, err := os.Stat(stdDriverDir); err == nil { + // if err := r.discoverDriversInDir(stdDriverDir); err != nil { + // logrus.Warnf("Error discovering drivers in %s: %v", stdDriverDir, err) + // } + // } + + if driverPaths := os.Getenv("LIMA_DRIVERS_PATH"); driverPaths != "" { + fmt.Printf("Discovering drivers in LIMA_DRIVERS_PATH: %s\n", driverPaths) + paths := filepath.SplitList(driverPaths) + fmt.Println("Driver paths:", paths) for _, path := range paths { if path == "" { continue @@ -95,16 +111,19 @@ func (r *Registry) DiscoverPlugins() error { info, err := os.Stat(path) if err != nil { - logrus.Warnf("Error accessing plugin path %s: %v", path, err) + logrus.Warnf("Error accessing driver path %s: %v", path, err) continue } + fmt.Printf("Info for %s: %+v\n", path, info) + fmt.Printf("IsExecutable: %v\n", isExecutable(info.Mode())) + fmt.Printf("IsDir: %v\n", info.IsDir()) if info.IsDir() { - if err := r.discoverPluginsInDir(path); err != nil { - logrus.Warnf("Error discovering plugins in %s: %v", path, err) + if err := r.discoverDriversInDir(path); err != nil { + logrus.Warnf("Error discovering drivers in %s: %v", path, err) } } else if isExecutable(info.Mode()) { - r.registerPluginFile(path) + r.registerDriverFile(path) } } } @@ -112,10 +131,10 @@ func (r *Registry) DiscoverPlugins() error { return nil } -func (r *Registry) discoverPluginsInDir(dir string) error { +func (r *Registry) discoverDriversInDir(dir string) error { entries, err := os.ReadDir(dir) if err != nil { - return fmt.Errorf("failed to read plugin directory %s: %w", dir, err) + return fmt.Errorf("failed to read driver directory %s: %w", dir, err) } for _, entry := range entries { @@ -133,29 +152,29 @@ func (r *Registry) discoverPluginsInDir(dir string) error { continue } - pluginPath := filepath.Join(dir, entry.Name()) - r.registerPluginFile(pluginPath) + driverPath := filepath.Join(dir, entry.Name()) + r.registerDriverFile(driverPath) } return nil } -func (r *Registry) registerPluginFile(path string) { +func (r *Registry) registerDriverFile(path string) { base := filepath.Base(path) - if !strings.HasPrefix(base, "lima-plugin-") { + if !strings.HasPrefix(base, "lima-driver-") { return } - name := strings.TrimPrefix(base, "lima-plugin-") + name := strings.TrimPrefix(base, "lima-driver-") name = strings.TrimSuffix(name, filepath.Ext(name)) cmd := exec.Command(path, "--version") if err := cmd.Run(); err != nil { - logrus.Warnf("Plugin %s failed version check: %v", path, err) + logrus.Warnf("driver %s failed version check: %v", path, err) return } - r.RegisterPlugin(name, path) + r.RegisterDriver(name, path) } func isExecutable(mode os.FileMode) bool { @@ -166,15 +185,16 @@ var DefaultRegistry *Registry func init() { DefaultRegistry = NewRegistry() + DefaultRegistry.DiscoverDrivers() } func Register(driver driver.Driver) { if DefaultRegistry != nil { name := driver.GetInfo().DriverName - if _, exists := DefaultRegistry.drivers[name]; exists { + if _, exists := DefaultRegistry.internalDrivers[name]; exists { return } - DefaultRegistry.drivers[name] = driver + DefaultRegistry.internalDrivers[name] = driver } } From 6d652e0f420a33bb845a6562c4ba7fa371261320 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 4 Jun 2025 22:10:51 +0530 Subject: [PATCH 31/49] driver(external): complete external driver manager and registering process Signed-off-by: Ansuman Sahoo --- pkg/registry/registry.go | 121 ++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 28 deletions(-) diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index a77486cbf15..1f7adce6aae 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -4,6 +4,7 @@ package registry import ( + "bufio" "context" "fmt" "io" @@ -12,9 +13,11 @@ import ( "path/filepath" "strings" "sync" + "time" "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/client" + "github.com/lima-vm/lima/pkg/usrlocalsharelima" "github.com/sirupsen/logrus" ) @@ -26,6 +29,7 @@ type ExternalDriver struct { Client *client.DriverClient // Client is the gRPC client for the external driver Path string ctx context.Context + logger *logrus.Logger cancelFunc context.CancelFunc } @@ -42,6 +46,64 @@ func NewRegistry() *Registry { } } +func (e *ExternalDriver) Start() error { + e.logger.Infof("Starting external driver at %s", e.Path) + + ctx, cancel := context.WithCancel(context.Background()) + cmd := exec.CommandContext(ctx, e.Path) + + stdin, err := cmd.StdinPipe() + if err != nil { + cancel() + return fmt.Errorf("failed to create stdin pipe: %w", err) + } + + stdout, err := cmd.StdoutPipe() + if err != nil { + cancel() + return fmt.Errorf("failed to create stdout pipe: %w", err) + } + + stderr, err := cmd.StderrPipe() + if err != nil { + cancel() + return fmt.Errorf("failed to create stderr pipe: %w", err) + } + + if err := cmd.Start(); err != nil { + cancel() + return fmt.Errorf("failed to start external driver: %w", err) + } + + driverLogger := e.logger.WithField("driver", e.Name) + + go func() { + scanner := bufio.NewScanner(stderr) + for scanner.Scan() { + driverLogger.Info(scanner.Text()) + } + }() + + time.Sleep(4 * time.Second) + + driverClient, err := client.NewDriverClient(stdin, stdout, e.logger) + if err != nil { + cancel() + cmd.Process.Kill() + return fmt.Errorf("failed to create driver client: %w", err) + } + + e.Command = cmd + e.Stdin = stdin + e.Stdout = stdout + e.Client = driverClient + e.ctx = ctx + e.cancelFunc = cancel + + driverLogger.Infof("External driver %s started successfully", e.Name) + return nil +} + func (r *Registry) List() []string { r.mu.RLock() defer r.mu.RUnlock() @@ -51,7 +113,6 @@ func (r *Registry) List() []string { names = append(names, name) } - r.DiscoverDrivers() for name := range r.externalDrivers { names = append(names, name+" (external)") } @@ -66,6 +127,11 @@ func (r *Registry) Get(name string) (driver.Driver, bool) { if !exists { externalDriver, exists := r.externalDrivers[name] if exists { + externalDriver.logger.Debugf("Using external driver %q", name) + if err := externalDriver.Start(); err != nil { + externalDriver.logger.Errorf("Failed to start external driver %q: %v", name, err) + return nil, false + } return externalDriver.Client, true } @@ -77,33 +143,38 @@ func (r *Registry) RegisterDriver(name, path string) { r.mu.Lock() defer r.mu.Unlock() - if _, exists := r.externalDrivers[name]; exists { + if _, exists := DefaultRegistry.externalDrivers[name]; exists { logrus.Debugf("Driver %q is already registered, skipping", name) return } - r.externalDrivers[name].Path = path - logrus.Debugf("Registered driver %q at %s", name, path) + log := logrus.New() + log.SetFormatter(&logrus.TextFormatter{ + FullTimestamp: true, + }) + + DefaultRegistry.externalDrivers[name] = &ExternalDriver{ + Name: name, + Path: path, + logger: log, + } } func (r *Registry) DiscoverDrivers() error { - // limaShareDir, err := usrlocalsharelima.Dir() - // if err != nil { - // return fmt.Errorf("failed to determine Lima share directory: %w", err) - // } - // fmt.Printf("Discovering drivers in %s\n", limaShareDir) - // stdDriverDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") - - // if _, err := os.Stat(stdDriverDir); err == nil { - // if err := r.discoverDriversInDir(stdDriverDir); err != nil { - // logrus.Warnf("Error discovering drivers in %s: %v", stdDriverDir, err) - // } - // } + limaShareDir, err := usrlocalsharelima.Dir() + if err != nil { + return fmt.Errorf("failed to determine Lima share directory: %w", err) + } + stdDriverDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") + + if _, err := os.Stat(stdDriverDir); err == nil { + if err := r.discoverDriversInDir(stdDriverDir); err != nil { + logrus.Warnf("Error discovering drivers in %s: %v", stdDriverDir, err) + } + } if driverPaths := os.Getenv("LIMA_DRIVERS_PATH"); driverPaths != "" { - fmt.Printf("Discovering drivers in LIMA_DRIVERS_PATH: %s\n", driverPaths) paths := filepath.SplitList(driverPaths) - fmt.Println("Driver paths:", paths) for _, path := range paths { if path == "" { continue @@ -114,9 +185,6 @@ func (r *Registry) DiscoverDrivers() error { logrus.Warnf("Error accessing driver path %s: %v", path, err) continue } - fmt.Printf("Info for %s: %+v\n", path, info) - fmt.Printf("IsExecutable: %v\n", isExecutable(info.Mode())) - fmt.Printf("IsDir: %v\n", info.IsDir()) if info.IsDir() { if err := r.discoverDriversInDir(path); err != nil { @@ -162,18 +230,13 @@ func (r *Registry) discoverDriversInDir(dir string) error { func (r *Registry) registerDriverFile(path string) { base := filepath.Base(path) if !strings.HasPrefix(base, "lima-driver-") { + fmt.Printf("Skipping %s: does not start with 'lima-driver-'\n", base) return } name := strings.TrimPrefix(base, "lima-driver-") name = strings.TrimSuffix(name, filepath.Ext(name)) - cmd := exec.Command(path, "--version") - if err := cmd.Run(); err != nil { - logrus.Warnf("driver %s failed version check: %v", path, err) - return - } - r.RegisterDriver(name, path) } @@ -185,7 +248,9 @@ var DefaultRegistry *Registry func init() { DefaultRegistry = NewRegistry() - DefaultRegistry.DiscoverDrivers() + if err := DefaultRegistry.DiscoverDrivers(); err != nil { + logrus.Warnf("Error discovering drivers: %v", err) + } } func Register(driver driver.Driver) { From 0e0c20789aa9660258aa2b2618f62cce035cc291 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 4 Jun 2025 22:11:43 +0530 Subject: [PATCH 32/49] driver(external): some tweaks around server and client code Signed-off-by: Ansuman Sahoo --- cmd/limactl/main.go | 2 +- pkg/driver/external/client/client.go | 16 +++++++++------- pkg/driver/external/client/methods.go | 6 ++---- pkg/driver/external/client/pipe.go | 7 +++++++ pkg/driver/external/server/methods.go | 6 +++--- pkg/driver/external/server/server.go | 3 --- pkg/driver/qemu/cmd/main.go | 1 + pkg/driverutil/instance.go | 4 ---- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index 6500e1aa069..ce6a7f391b1 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -16,7 +16,7 @@ import ( "github.com/spf13/cobra" "github.com/lima-vm/lima/pkg/debugutil" - _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms + // _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms "github.com/lima-vm/lima/pkg/fsutil" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/store/dirnames" diff --git a/pkg/driver/external/client/client.go b/pkg/driver/external/client/client.go index 9d536939af2..22f3babc740 100644 --- a/pkg/driver/external/client/client.go +++ b/pkg/driver/external/client/client.go @@ -26,11 +26,7 @@ type DriverClient struct { } func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus.Logger) (*DriverClient, error) { - pipeConn := &PipeConn{ - Reader: stdout, - Writer: stdin, - } - + pipeConn := newPipeConn(stdin, stdout) opts := []grpc.DialOption{ grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt64), @@ -47,9 +43,15 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus. }), } - conn, err := grpc.NewClient("pipe://", opts...) + // conn, err := grpc.NewClient("pipe", opts...) + // if err != nil { + // logger.Errorf("failed to create gRPC driver client connection: %v", err) + // return nil, err + // } + + conn, err := grpc.Dial("pipe", opts...) if err != nil { - logger.Errorf("failed to create gRPC driver client connection: %v", err) + logger.Errorf("failed to dial gRPC driver client connection: %v", err) return nil, err } diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 6e3f7f02d57..5dd9a5bfa24 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -51,9 +51,7 @@ func (d *DriverClient) Initialize(ctx context.Context) error { func (d *DriverClient) CreateDisk(ctx context.Context) error { d.logger.Debug("Creating disk for the instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - _, err := d.DriverSvc.CreateDisk(connCtx, &emptypb.Empty{}) + _, err := d.DriverSvc.CreateDisk(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Disk creation failed: %v", err) return err @@ -66,7 +64,7 @@ func (d *DriverClient) CreateDisk(ctx context.Context) error { func (d *DriverClient) Start(ctx context.Context) (chan error, error) { d.logger.Debug("Starting driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + connCtx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() stream, err := d.DriverSvc.Start(connCtx, &emptypb.Empty{}) if err != nil { diff --git a/pkg/driver/external/client/pipe.go b/pkg/driver/external/client/pipe.go index 9dfc36ae791..2bd20d54786 100644 --- a/pkg/driver/external/client/pipe.go +++ b/pkg/driver/external/client/pipe.go @@ -14,6 +14,13 @@ type PipeConn struct { Writer io.Writer } +func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) *PipeConn { + return &PipeConn{ + Reader: reader, + Writer: writer, + } +} + func (p *PipeConn) Read(b []byte) (n int, err error) { return p.Reader.Read(b) } diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index fbadb00b9b8..3affc30c268 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -51,14 +51,14 @@ func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) (*emptypb.Empty, error) { s.logger.Debugf("Received SetConfig request") - var inst *store.Instance + var inst store.Instance - if err := json.Unmarshal(req.InstanceConfigJson, inst); err != nil { + if err := json.Unmarshal(req.InstanceConfigJson, &inst); err != nil { s.logger.Errorf("Failed to unmarshal InstanceConfigJson: %v", err) return &emptypb.Empty{}, err } - s.driver.SetConfig(inst, int(req.SshLocalPort)) + s.driver.SetConfig(&inst, int(req.SshLocalPort)) return &emptypb.Empty{}, nil } diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index c1c50918057..7dd00a2469c 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -26,9 +26,6 @@ type DriverServer struct { func Serve(driver driver.Driver) { logger := logrus.New() logger.SetLevel(logrus.DebugLevel) - logger.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - }) logger.Infof("Starting external driver server for %s", driver.GetInfo().DriverName) pipeConn := &PipeConn{ diff --git a/pkg/driver/qemu/cmd/main.go b/pkg/driver/qemu/cmd/main.go index 6e4b1d68015..1d78c86e072 100644 --- a/pkg/driver/qemu/cmd/main.go +++ b/pkg/driver/qemu/cmd/main.go @@ -8,6 +8,7 @@ import ( "github.com/lima-vm/lima/pkg/driver/qemu" ) +// To be used as an external driver for Lima. func main() { driver := qemu.New() server.Serve(driver) diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index ab1f1b413c6..a32ff341b73 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -21,9 +21,5 @@ func CreateTargetDriverInstance(inst *store.Instance, sshLocalPort int) (driver. driver.SetConfig(inst, sshLocalPort) - if err := driver.Validate(); err != nil { - return nil, fmt.Errorf("driver validation failed: %w", err) - } - return driver, nil } From e324e7bccc144645adfda09d99d18f0aead00f8e Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Thu, 5 Jun 2025 23:08:19 +0530 Subject: [PATCH 33/49] driver(external): server logs to a file and fixed json marshal error in SetConfig() Signed-off-by: Ansuman Sahoo --- pkg/driver/external/client/methods.go | 66 +++++++------------------- pkg/driver/external/server/methods.go | 5 +- pkg/registry/registry.go | 31 ++++++------- pkg/store/filenames/filenames.go | 67 ++++++++++++++------------- pkg/store/instance.go | 36 ++++++++++++++ 5 files changed, 105 insertions(+), 100 deletions(-) diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 5dd9a5bfa24..2079cebc9e5 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -20,7 +20,7 @@ import ( func (d *DriverClient) Validate() error { d.logger.Debug("Validating driver for the given config") - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _, err := d.DriverSvc.Validate(ctx, &emptypb.Empty{}) @@ -36,9 +36,7 @@ func (d *DriverClient) Validate() error { func (d *DriverClient) Initialize(ctx context.Context) error { d.logger.Debug("Initializing driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - _, err := d.DriverSvc.Initialize(connCtx, &emptypb.Empty{}) + _, err := d.DriverSvc.Initialize(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Initialization failed: %v", err) return err @@ -64,9 +62,7 @@ func (d *DriverClient) CreateDisk(ctx context.Context) error { func (d *DriverClient) Start(ctx context.Context) (chan error, error) { d.logger.Debug("Starting driver instance") - connCtx, cancel := context.WithTimeout(ctx, time.Minute) - defer cancel() - stream, err := d.DriverSvc.Start(connCtx, &emptypb.Empty{}) + stream, err := d.DriverSvc.Start(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to start driver instance: %v", err) return nil, err @@ -97,7 +93,7 @@ func (d *DriverClient) Start(ctx context.Context) (chan error, error) { func (d *DriverClient) Stop(ctx context.Context) error { d.logger.Debug("Stopping driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + connCtx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() _, err := d.DriverSvc.Stop(connCtx, &emptypb.Empty{}) if err != nil { @@ -112,7 +108,7 @@ func (d *DriverClient) Stop(ctx context.Context) error { func (d *DriverClient) RunGUI() error { d.logger.Debug("Running GUI for the driver instance") - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _, err := d.DriverSvc.RunGUI(ctx, &emptypb.Empty{}) @@ -128,10 +124,7 @@ func (d *DriverClient) RunGUI() error { func (d *DriverClient) ChangeDisplayPassword(ctx context.Context, password string) error { d.logger.Debug("Changing display password for the driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - _, err := d.DriverSvc.ChangeDisplayPassword(connCtx, &pb.ChangeDisplayPasswordRequest{ + _, err := d.DriverSvc.ChangeDisplayPassword(ctx, &pb.ChangeDisplayPasswordRequest{ Password: password, }) if err != nil { @@ -146,10 +139,7 @@ func (d *DriverClient) ChangeDisplayPassword(ctx context.Context, password strin func (d *DriverClient) GetDisplayConnection(ctx context.Context) (string, error) { d.logger.Debug("Getting display connection for the driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - resp, err := d.DriverSvc.GetDisplayConnection(connCtx, &emptypb.Empty{}) + resp, err := d.DriverSvc.GetDisplayConnection(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to get display connection: %v", err) return "", err @@ -162,10 +152,7 @@ func (d *DriverClient) GetDisplayConnection(ctx context.Context) (string, error) func (d *DriverClient) CreateSnapshot(ctx context.Context, tag string) error { d.logger.Debugf("Creating snapshot with tag: %s", tag) - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - _, err := d.DriverSvc.CreateSnapshot(connCtx, &pb.CreateSnapshotRequest{ + _, err := d.DriverSvc.CreateSnapshot(ctx, &pb.CreateSnapshotRequest{ Tag: tag, }) if err != nil { @@ -180,10 +167,7 @@ func (d *DriverClient) CreateSnapshot(ctx context.Context, tag string) error { func (d *DriverClient) ApplySnapshot(ctx context.Context, tag string) error { d.logger.Debugf("Applying snapshot with tag: %s", tag) - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - _, err := d.DriverSvc.ApplySnapshot(connCtx, &pb.ApplySnapshotRequest{ + _, err := d.DriverSvc.ApplySnapshot(ctx, &pb.ApplySnapshotRequest{ Tag: tag, }) if err != nil { @@ -198,10 +182,7 @@ func (d *DriverClient) ApplySnapshot(ctx context.Context, tag string) error { func (d *DriverClient) DeleteSnapshot(ctx context.Context, tag string) error { d.logger.Debugf("Deleting snapshot with tag: %s", tag) - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - _, err := d.DriverSvc.DeleteSnapshot(connCtx, &pb.DeleteSnapshotRequest{ + _, err := d.DriverSvc.DeleteSnapshot(ctx, &pb.DeleteSnapshotRequest{ Tag: tag, }) if err != nil { @@ -216,10 +197,7 @@ func (d *DriverClient) DeleteSnapshot(ctx context.Context, tag string) error { func (d *DriverClient) ListSnapshots(ctx context.Context) (string, error) { d.logger.Debug("Listing snapshots") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - resp, err := d.DriverSvc.ListSnapshots(connCtx, &emptypb.Empty{}) + resp, err := d.DriverSvc.ListSnapshots(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to list snapshots: %v", err) return "", err @@ -232,9 +210,7 @@ func (d *DriverClient) ListSnapshots(ctx context.Context) (string, error) { func (d *DriverClient) Register(ctx context.Context) error { d.logger.Debug("Registering driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - _, err := d.DriverSvc.Register(connCtx, &emptypb.Empty{}) + _, err := d.DriverSvc.Register(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to register driver instance: %v", err) return err @@ -247,10 +223,7 @@ func (d *DriverClient) Register(ctx context.Context) error { func (d *DriverClient) Unregister(ctx context.Context) error { d.logger.Debug("Unregistering driver instance") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - _, err := d.DriverSvc.Unregister(connCtx, &emptypb.Empty{}) + _, err := d.DriverSvc.Unregister(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to unregister driver instance: %v", err) return err @@ -263,7 +236,7 @@ func (d *DriverClient) Unregister(ctx context.Context) error { func (d *DriverClient) ForwardGuestAgent() bool { d.logger.Debug("Checking if guest agent needs to be forwarded") - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() resp, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{}) @@ -280,10 +253,7 @@ func (d *DriverClient) ForwardGuestAgent() bool { func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { d.logger.Debug("Getting guest agent connection") - connCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - connStream, err := d.DriverSvc.GuestAgentConn(connCtx, &emptypb.Empty{}) + connStream, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to get guest agent connection: %v", err) return nil, err @@ -295,7 +265,7 @@ func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { func (d *DriverClient) GetInfo() driver.Info { d.logger.Debug("Getting driver info") - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() resp, err := d.DriverSvc.GetInfo(ctx, &emptypb.Empty{}) @@ -317,13 +287,13 @@ func (d *DriverClient) GetInfo() driver.Info { func (d *DriverClient) SetConfig(inst *store.Instance, sshLocalPort int) { d.logger.Debugf("Setting config for instance %s with SSH local port %d", inst.Name, sshLocalPort) - instJson, err := json.Marshal(inst) + instJson, err := inst.MarshalJSON() if err != nil { d.logger.Errorf("Failed to marshal instance config: %v", err) return } - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _, err = d.DriverSvc.SetConfig(ctx, &pb.SetConfigRequest{ diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 3affc30c268..aeede3baa0f 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -6,6 +6,7 @@ package server import ( "context" "encoding/json" + "errors" "io" "google.golang.org/grpc/codes" @@ -53,7 +54,7 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) s.logger.Debugf("Received SetConfig request") var inst store.Instance - if err := json.Unmarshal(req.InstanceConfigJson, &inst); err != nil { + if err := inst.UnmarshalJSON(req.InstanceConfigJson); err != nil { s.logger.Errorf("Failed to unmarshal InstanceConfigJson: %v", err) return &emptypb.Empty{}, err } @@ -79,7 +80,7 @@ func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_Gue for { n, err := conn.Read(buf) if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil } return status.Errorf(codes.Internal, "error reading: %v", err) diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 1f7adce6aae..03a9426b8e4 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -4,7 +4,6 @@ package registry import ( - "bufio" "context" "fmt" "io" @@ -17,6 +16,7 @@ import ( "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/client" + "github.com/lima-vm/lima/pkg/store/filenames" "github.com/lima-vm/lima/pkg/usrlocalsharelima" "github.com/sirupsen/logrus" ) @@ -64,12 +64,21 @@ func (e *ExternalDriver) Start() error { return fmt.Errorf("failed to create stdout pipe: %w", err) } - stderr, err := cmd.StderrPipe() + sharedDir, err := usrlocalsharelima.Dir() if err != nil { cancel() - return fmt.Errorf("failed to create stderr pipe: %w", err) + return fmt.Errorf("failed to determine Lima share directory: %w", err) + } + logPath := filepath.Join(sharedDir, filenames.ExternalDriverStderrLog) + logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + cancel() + return fmt.Errorf("failed to open external driver log file: %w", err) } + // Redirect stderr to the log file + cmd.Stderr = logFile + if err := cmd.Start(); err != nil { cancel() return fmt.Errorf("failed to start external driver: %w", err) @@ -77,14 +86,7 @@ func (e *ExternalDriver) Start() error { driverLogger := e.logger.WithField("driver", e.Name) - go func() { - scanner := bufio.NewScanner(stderr) - for scanner.Scan() { - driverLogger.Info(scanner.Text()) - } - }() - - time.Sleep(4 * time.Second) + time.Sleep(time.Millisecond * 100) driverClient, err := client.NewDriverClient(stdin, stdout, e.logger) if err != nil { @@ -148,15 +150,10 @@ func (r *Registry) RegisterDriver(name, path string) { return } - log := logrus.New() - log.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - }) - DefaultRegistry.externalDrivers[name] = &ExternalDriver{ Name: name, Path: path, - logger: log, + logger: logrus.New(), } } diff --git a/pkg/store/filenames/filenames.go b/pkg/store/filenames/filenames.go index cfb825fc0ee..846f897d748 100644 --- a/pkg/store/filenames/filenames.go +++ b/pkg/store/filenames/filenames.go @@ -31,39 +31,40 @@ const ( // Filenames that may appear under an instance directory const ( - LimaYAML = "lima.yaml" - LimaVersion = "lima-version" // Lima version used to create instance - CIDataISO = "cidata.iso" - CIDataISODir = "cidata" - CloudConfig = "cloud-config.yaml" - BaseDisk = "basedisk" - DiffDisk = "diffdisk" - Kernel = "kernel" - KernelCmdline = "kernel.cmdline" - Initrd = "initrd" - QMPSock = "qmp.sock" - SerialLog = "serial.log" // default serial (ttyS0, but ttyAMA0 on qemu-system-{arm,aarch64}) - SerialSock = "serial.sock" - SerialPCILog = "serialp.log" // pci serial (ttyS0 on qemu-system-{arm,aarch64}) - SerialPCISock = "serialp.sock" - SerialVirtioLog = "serialv.log" // virtio serial - SerialVirtioSock = "serialv.sock" - SSHSock = "ssh.sock" - SSHConfig = "ssh.config" - VhostSock = "virtiofsd-%d.sock" - VNCDisplayFile = "vncdisplay" - VNCPasswordFile = "vncpassword" - GuestAgentSock = "ga.sock" - VirtioPort = "io.lima-vm.guest_agent.0" - HostAgentPID = "ha.pid" - HostAgentSock = "ha.sock" - HostAgentStdoutLog = "ha.stdout.log" - HostAgentStderrLog = "ha.stderr.log" - VzIdentifier = "vz-identifier" - VzEfi = "vz-efi" // efi variable store - QemuEfiCodeFD = "qemu-efi-code.fd" // efi code; not always created - QemuEfiFullFD = "qemu-efi-full.fd" // concatenated efi vars and code; not always created - AnsibleInventoryYAML = "ansible-inventory.yaml" + LimaYAML = "lima.yaml" + LimaVersion = "lima-version" // Lima version used to create instance + CIDataISO = "cidata.iso" + CIDataISODir = "cidata" + CloudConfig = "cloud-config.yaml" + BaseDisk = "basedisk" + DiffDisk = "diffdisk" + Kernel = "kernel" + KernelCmdline = "kernel.cmdline" + Initrd = "initrd" + QMPSock = "qmp.sock" + SerialLog = "serial.log" // default serial (ttyS0, but ttyAMA0 on qemu-system-{arm,aarch64}) + SerialSock = "serial.sock" + SerialPCILog = "serialp.log" // pci serial (ttyS0 on qemu-system-{arm,aarch64}) + SerialPCISock = "serialp.sock" + SerialVirtioLog = "serialv.log" // virtio serial + SerialVirtioSock = "serialv.sock" + SSHSock = "ssh.sock" + SSHConfig = "ssh.config" + VhostSock = "virtiofsd-%d.sock" + VNCDisplayFile = "vncdisplay" + VNCPasswordFile = "vncpassword" + GuestAgentSock = "ga.sock" + VirtioPort = "io.lima-vm.guest_agent.0" + HostAgentPID = "ha.pid" + HostAgentSock = "ha.sock" + HostAgentStdoutLog = "ha.stdout.log" + HostAgentStderrLog = "ha.stderr.log" + ExternalDriverStderrLog = "ed.stderr.log" + VzIdentifier = "vz-identifier" + VzEfi = "vz-efi" // efi variable store + QemuEfiCodeFD = "qemu-efi-code.fd" // efi code; not always created + QemuEfiFullFD = "qemu-efi-full.fd" // concatenated efi vars and code; not always created + AnsibleInventoryYAML = "ansible-inventory.yaml" // SocketDir is the default location for forwarded sockets with a relative paths in HostSocket. SocketDir = "sock" diff --git a/pkg/store/instance.go b/pkg/store/instance.go index 19b4b2270dc..5031b1c145c 100644 --- a/pkg/store/instance.go +++ b/pkg/store/instance.go @@ -5,6 +5,7 @@ package store import ( "context" + "encoding/json" "errors" "fmt" "io" @@ -438,3 +439,38 @@ func (inst *Instance) Unprotect() error { inst.Protected = false return nil } + +func (inst *Instance) MarshalJSON() ([]byte, error) { + type Alias Instance + errorsAsStrings := make([]string, len(inst.Errors)) + for i, err := range inst.Errors { + if err != nil { + errorsAsStrings[i] = err.Error() + } + } + return json.Marshal(&struct { + *Alias + Errors []string `json:"errors,omitempty"` + }{ + Alias: (*Alias)(inst), + Errors: errorsAsStrings, + }) +} + +func (inst *Instance) UnmarshalJSON(data []byte) error { + type Alias Instance + aux := &struct { + *Alias + Errors []string `json:"errors,omitempty"` + }{ + Alias: (*Alias)(inst), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + inst.Errors = nil + for _, msg := range aux.Errors { + inst.Errors = append(inst.Errors, errors.New(msg)) + } + return nil +} From 62754a460ca4efd336129175d6b7f485e77fe0a3 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 6 Jun 2025 22:10:30 +0530 Subject: [PATCH 34/49] driver(external): implement bidirectional streaming for GuestAgentConn() Signed-off-by: Ansuman Sahoo --- pkg/driver/external/client/methods.go | 2 +- pkg/driver/external/driver.pb.go | 34 +++++++++++++-------------- pkg/driver/external/driver.proto | 4 ++-- pkg/driver/external/driver_grpc.pb.go | 27 +++++++-------------- pkg/driver/external/server/methods.go | 22 +++++++++++++---- pkg/store/filenames/filenames.go | 2 +- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 2079cebc9e5..64c25015c1e 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -253,7 +253,7 @@ func (d *DriverClient) ForwardGuestAgent() bool { func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { d.logger.Debug("Getting guest agent connection") - connStream, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) + connStream, err := d.DriverSvc.GuestAgentConn(ctx) if err != nil { d.logger.Errorf("Failed to get guest agent connection: %v", err) return nil, err diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index 40fdc432dc4..2558ac45dad 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -478,27 +478,27 @@ func (x *ForwardGuestAgentResponse) GetShouldForward() bool { return false } -type GuestAgentConnResponse struct { +type GuestAgentConnStream struct { state protoimpl.MessageState `protogen:"open.v1"` NetConn []byte `protobuf:"bytes,1,opt,name=net_conn,json=netConn,proto3" json:"net_conn,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *GuestAgentConnResponse) Reset() { - *x = GuestAgentConnResponse{} +func (x *GuestAgentConnStream) Reset() { + *x = GuestAgentConnStream{} mi := &file_pkg_driver_external_driver_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *GuestAgentConnResponse) String() string { +func (x *GuestAgentConnStream) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GuestAgentConnResponse) ProtoMessage() {} +func (*GuestAgentConnStream) ProtoMessage() {} -func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { +func (x *GuestAgentConnStream) ProtoReflect() protoreflect.Message { mi := &file_pkg_driver_external_driver_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -510,12 +510,12 @@ func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GuestAgentConnResponse.ProtoReflect.Descriptor instead. -func (*GuestAgentConnResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use GuestAgentConnStream.ProtoReflect.Descriptor instead. +func (*GuestAgentConnStream) Descriptor() ([]byte, []int) { return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} } -func (x *GuestAgentConnResponse) GetNetConn() []byte { +func (x *GuestAgentConnStream) GetNetConn() []byte { if x != nil { return x.NetConn } @@ -550,9 +550,9 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\x15ListSnapshotsResponse\x12\x1c\n" + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\"B\n" + "\x19ForwardGuestAgentResponse\x12%\n" + - "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"3\n" + - "\x16GuestAgentConnResponse\x12\x19\n" + - "\bnet_conn\x18\x01 \x01(\fR\anetConn2\xfb\b\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"1\n" + + "\x14GuestAgentConnStream\x12\x19\n" + + "\bnet_conn\x18\x01 \x01(\fR\anetConn2\xfa\b\n" + "\x06Driver\x12:\n" + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + @@ -571,8 +571,8 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + - "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12C\n" + - "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse0\x01\x126\n" + + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12B\n" + + "\x0eGuestAgentConn\x12\x15.GuestAgentConnStream\x1a\x15.GuestAgentConnStream(\x010\x01\x126\n" + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x16.google.protobuf.Empty\x120\n" + "\aGetInfo\x12\x16.google.protobuf.Empty\x1a\r.InfoResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" @@ -600,7 +600,7 @@ var file_pkg_driver_external_driver_proto_goTypes = []any{ (*DeleteSnapshotRequest)(nil), // 7: DeleteSnapshotRequest (*ListSnapshotsResponse)(nil), // 8: ListSnapshotsResponse (*ForwardGuestAgentResponse)(nil), // 9: ForwardGuestAgentResponse - (*GuestAgentConnResponse)(nil), // 10: GuestAgentConnResponse + (*GuestAgentConnStream)(nil), // 10: GuestAgentConnStream (*emptypb.Empty)(nil), // 11: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ @@ -619,7 +619,7 @@ var file_pkg_driver_external_driver_proto_depIdxs = []int32{ 11, // 12: Driver.Register:input_type -> google.protobuf.Empty 11, // 13: Driver.Unregister:input_type -> google.protobuf.Empty 11, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 11, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty + 10, // 15: Driver.GuestAgentConn:input_type -> GuestAgentConnStream 2, // 16: Driver.SetConfig:input_type -> SetConfigRequest 11, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty 11, // 18: Driver.Validate:output_type -> google.protobuf.Empty @@ -637,7 +637,7 @@ var file_pkg_driver_external_driver_proto_depIdxs = []int32{ 11, // 30: Driver.Register:output_type -> google.protobuf.Empty 11, // 31: Driver.Unregister:output_type -> google.protobuf.Empty 9, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 10, // 33: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse + 10, // 33: Driver.GuestAgentConn:output_type -> GuestAgentConnStream 11, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty 0, // 35: Driver.GetInfo:output_type -> InfoResponse 18, // [18:36] is the sub-list for method output_type diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index b1d4d5d58a2..dc2d67b6593 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -24,7 +24,7 @@ service Driver { rpc Unregister(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); - rpc GuestAgentConn(google.protobuf.Empty) returns (stream GuestAgentConnResponse); + rpc GuestAgentConn(stream GuestAgentConnStream) returns (stream GuestAgentConnStream); rpc SetConfig(SetConfigRequest) returns (google.protobuf.Empty); @@ -73,6 +73,6 @@ message ForwardGuestAgentResponse { bool should_forward = 1; } -message GuestAgentConnResponse { +message GuestAgentConnStream { bytes net_conn = 1; } \ No newline at end of file diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index cf69dad0cd9..e9325262169 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -59,7 +59,7 @@ type DriverClient interface { Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) - GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GuestAgentConnResponse], error) + GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[GuestAgentConnStream, GuestAgentConnStream], error) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) } @@ -231,24 +231,18 @@ func (c *driverClient) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, return out, nil } -func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GuestAgentConnResponse], error) { +func (c *driverClient) GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[GuestAgentConnStream, GuestAgentConnStream], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &Driver_ServiceDesc.Streams[1], Driver_GuestAgentConn_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[emptypb.Empty, GuestAgentConnResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } + x := &grpc.GenericClientStream[GuestAgentConnStream, GuestAgentConnStream]{ClientStream: stream} return x, nil } // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type Driver_GuestAgentConnClient = grpc.ServerStreamingClient[GuestAgentConnResponse] +type Driver_GuestAgentConnClient = grpc.BidiStreamingClient[GuestAgentConnStream, GuestAgentConnStream] func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -289,7 +283,7 @@ type DriverServer interface { Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) - GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error + GuestAgentConn(grpc.BidiStreamingServer[GuestAgentConnStream, GuestAgentConnStream]) error SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) mustEmbedUnimplementedDriverServer() @@ -347,7 +341,7 @@ func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*e func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ForwardGuestAgent not implemented") } -func (UnimplementedDriverServer) GuestAgentConn(*emptypb.Empty, grpc.ServerStreamingServer[GuestAgentConnResponse]) error { +func (UnimplementedDriverServer) GuestAgentConn(grpc.BidiStreamingServer[GuestAgentConnStream, GuestAgentConnStream]) error { return status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") } func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) { @@ -641,15 +635,11 @@ func _Driver_ForwardGuestAgent_Handler(srv interface{}, ctx context.Context, dec } func _Driver_GuestAgentConn_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(emptypb.Empty) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(DriverServer).GuestAgentConn(m, &grpc.GenericServerStream[emptypb.Empty, GuestAgentConnResponse]{ServerStream: stream}) + return srv.(DriverServer).GuestAgentConn(&grpc.GenericServerStream[GuestAgentConnStream, GuestAgentConnStream]{ServerStream: stream}) } // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type Driver_GuestAgentConnServer = grpc.ServerStreamingServer[GuestAgentConnResponse] +type Driver_GuestAgentConnServer = grpc.BidiStreamingServer[GuestAgentConnStream, GuestAgentConnStream] func _Driver_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetConfigRequest) @@ -769,6 +759,7 @@ var Driver_ServiceDesc = grpc.ServiceDesc{ StreamName: "GuestAgentConn", Handler: _Driver_GuestAgentConn_Handler, ServerStreams: true, + ClientStreams: true, }, }, Metadata: "pkg/driver/external/driver.proto", diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index aeede3baa0f..1fdbe4f7d18 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -64,8 +64,7 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) return &emptypb.Empty{}, nil } -// NOTE: If this doesn't work, try with bidirectional streaming(like in buildkit) and see if that helps. -func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_GuestAgentConnServer) error { +func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) error { s.logger.Debug("Received GuestAgentConn request") conn, err := s.driver.GuestAgentConn(stream.Context()) if err != nil { @@ -73,10 +72,23 @@ func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_Gue return err } - defer conn.Close() + go func() { + for { + msg, err := stream.Recv() + if err != nil { + return + } + if len(msg.NetConn) > 0 { + _, err = conn.Write(msg.NetConn) + if err != nil { + s.logger.Errorf("Error writing to connection: %v", err) + return + } + } + } + }() buf := make([]byte, 32*1<<10) - for { n, err := conn.Read(buf) if err != nil { @@ -86,7 +98,7 @@ func (s *DriverServer) GuestAgentConn(empty *emptypb.Empty, stream pb.Driver_Gue return status.Errorf(codes.Internal, "error reading: %v", err) } - msg := &pb.GuestAgentConnResponse{NetConn: buf[:n]} + msg := &pb.GuestAgentConnStream{NetConn: buf[:n]} if err := stream.Send(msg); err != nil { return err } diff --git a/pkg/store/filenames/filenames.go b/pkg/store/filenames/filenames.go index 846f897d748..eb61560d4b8 100644 --- a/pkg/store/filenames/filenames.go +++ b/pkg/store/filenames/filenames.go @@ -59,7 +59,7 @@ const ( HostAgentSock = "ha.sock" HostAgentStdoutLog = "ha.stdout.log" HostAgentStderrLog = "ha.stderr.log" - ExternalDriverStderrLog = "ed.stderr.log" + ExternalDriverStderrLog = "driver.stderr.log" VzIdentifier = "vz-identifier" VzEfi = "vz-efi" // efi variable store QemuEfiCodeFD = "qemu-efi-code.fd" // efi code; not always created From 9abdd1049f0e0db6754bd2e5106041107f7ea7f9 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 10 Jun 2025 00:27:12 +0530 Subject: [PATCH 35/49] driver(external): manage external driver lifecycle Signed-off-by: Ansuman Sahoo --- cmd/limactl/main.go | 3 ++ pkg/registry/registry.go | 59 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index ce6a7f391b1..2cbeba2e21f 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -19,6 +19,7 @@ import ( // _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms "github.com/lima-vm/lima/pkg/fsutil" "github.com/lima-vm/lima/pkg/osutil" + "github.com/lima-vm/lima/pkg/registry" "github.com/lima-vm/lima/pkg/store/dirnames" "github.com/lima-vm/lima/pkg/version" ) @@ -44,6 +45,8 @@ func main() { handleExitCoder(err) logrus.Fatal(err) } + + defer registry.DefaultRegistry.StopAllExternalDrivers() } func newApp() *cobra.Command { diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 03a9426b8e4..3c3b2bf0da3 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -106,6 +106,52 @@ func (e *ExternalDriver) Start() error { return nil } +func (e *ExternalDriver) cleanup() { + if e.cancelFunc != nil { + e.cancelFunc() + } + if e.Stdin != nil { + e.Stdin.Close() + } + if e.Stdout != nil { + e.Stdout.Close() + } + e.Command = nil + e.Client = nil + e.ctx = nil + e.cancelFunc = nil +} + +func (e *ExternalDriver) Stop() error { + if e.Command == nil || e.Command.Process == nil { + return fmt.Errorf("external driver %s is not running", e.Name) + } + + e.logger.Infof("Stopping external driver %s", e.Name) + e.cleanup() + + e.logger.Infof("External driver %s stopped successfully", e.Name) + return nil +} + +func (r *Registry) StopAllExternalDrivers() { + r.mu.Lock() + defer r.mu.Unlock() + + for name, driver := range r.externalDrivers { + // Only try to stop if the driver is actually running + if driver.Command != nil && driver.Command.Process != nil { + if err := driver.Stop(); err != nil { + logrus.Errorf("Failed to stop external driver %s: %v", name, err) + } else { + logrus.Infof("External driver %s stopped successfully", name) + } + } + // Always remove from registry + delete(r.externalDrivers, name) + } +} + func (r *Registry) List() []string { r.mu.RLock() defer r.mu.RUnlock() @@ -130,13 +176,18 @@ func (r *Registry) Get(name string) (driver.Driver, bool) { externalDriver, exists := r.externalDrivers[name] if exists { externalDriver.logger.Debugf("Using external driver %q", name) - if err := externalDriver.Start(); err != nil { - externalDriver.logger.Errorf("Failed to start external driver %q: %v", name, err) - return nil, false + if externalDriver.Client == nil || externalDriver.Command == nil || externalDriver.Command.Process == nil { + logrus.Infof("Starting new instance of external driver %q", name) + if err := externalDriver.Start(); err != nil { + externalDriver.logger.Errorf("Failed to start external driver %q: %v", name, err) + return nil, false + } + } else { + logrus.Infof("Reusing existing external driver %q instance", name) } + return externalDriver.Client, true } - } return driver, exists } From eefabda26d7782e36e697786323527ee8143c4ce Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 10 Jun 2025 18:52:12 +0530 Subject: [PATCH 36/49] driver(external): revamp grpchijack and GuestAgentConn() Signed-off-by: Ansuman Sahoo --- cmd/limactl/main_darwin.go | 2 +- pkg/driver/external/client/client.go | 9 +- .../external/client/grpchijack/hijack.go | 135 ++++++++++++++++++ pkg/driver/external/client/methods.go | 3 +- pkg/driver/external/client/pipe.go | 14 +- pkg/driver/external/client/stream.go | 93 ------------ pkg/driver/external/driver.pb.go | 38 ++--- pkg/driver/external/driver.proto | 6 +- pkg/driver/external/driver_grpc.pb.go | 16 +-- pkg/driver/external/server/methods.go | 14 +- pkg/driver/external/server/pipe.go | 3 +- 11 files changed, 185 insertions(+), 148 deletions(-) create mode 100644 pkg/driver/external/client/grpchijack/hijack.go delete mode 100644 pkg/driver/external/client/stream.go diff --git a/cmd/limactl/main_darwin.go b/cmd/limactl/main_darwin.go index 28d8c7f29a2..b933ed98b85 100644 --- a/cmd/limactl/main_darwin.go +++ b/cmd/limactl/main_darwin.go @@ -6,4 +6,4 @@ package main // Import vz driver to register it in the registry on darwin. -import _ "github.com/lima-vm/lima/pkg/driver/vz" +// import _ "github.com/lima-vm/lima/pkg/driver/vz" diff --git a/pkg/driver/external/client/client.go b/pkg/driver/external/client/client.go index 22f3babc740..b7141cad11d 100644 --- a/pkg/driver/external/client/client.go +++ b/pkg/driver/external/client/client.go @@ -8,13 +8,11 @@ import ( "io" "math" "net" - "time" pb "github.com/lima-vm/lima/pkg/driver/external" "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/keepalive" ) type DriverClient struct { @@ -36,11 +34,6 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus. return pipeConn, nil }), grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithKeepaliveParams(keepalive.ClientParameters{ - Time: 10 * time.Second, - Timeout: 20 * time.Second, - PermitWithoutStream: true, - }), } // conn, err := grpc.NewClient("pipe", opts...) @@ -48,6 +41,8 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus. // logger.Errorf("failed to create gRPC driver client connection: %v", err) // return nil, err // } + // -> ERRO[2025-06-04T21:32:54+05:30] Failed to set config: rpc error: code = + // Unavailable desc = name resolver error: produced zero addresses conn, err := grpc.Dial("pipe", opts...) if err != nil { diff --git a/pkg/driver/external/client/grpchijack/hijack.go b/pkg/driver/external/client/grpchijack/hijack.go new file mode 100644 index 00000000000..5b19d51ab51 --- /dev/null +++ b/pkg/driver/external/client/grpchijack/hijack.go @@ -0,0 +1,135 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package grpchijack + +import ( + "errors" + "fmt" + "io" + "net" + "sync" + "time" + + pb "github.com/lima-vm/lima/pkg/driver/external" + "google.golang.org/grpc" +) + +type streamConn struct { + stream pb.Driver_GuestAgentConnClient + readBuf []byte + lastBuf []byte + readMu sync.Mutex + writeMu sync.Mutex + closeCh chan struct{} + closedOnce sync.Once + closed bool +} + +func StreamToConn(stream pb.Driver_GuestAgentConnClient) *streamConn { + return &streamConn{ + stream: stream, + closeCh: make(chan struct{}), + } +} + +func (c *streamConn) Read(b []byte) (int, error) { + c.readMu.Lock() + defer c.readMu.Unlock() + + if c.closed { + return 0, io.EOF + } + + if c.lastBuf != nil { + n := copy(b, c.lastBuf) + c.lastBuf = c.lastBuf[n:] + if len(c.lastBuf) == 0 { + c.lastBuf = nil + } + return n, nil + } + + msg := new(pb.BytesMessage) + msg, err := c.stream.Recv() + if err != nil { + c.closed = true + if err == io.EOF { + return 0, io.EOF + } + return 0, fmt.Errorf("stream receive error: %w", err) + } + + n := copy(b, msg.Data) + if n < len(msg.Data) { + c.readBuf = make([]byte, len(msg.Data)-n) + copy(c.readBuf, msg.Data[n:]) + } + + return n, nil +} + +func (c *streamConn) Write(b []byte) (int, error) { + c.writeMu.Lock() + defer c.writeMu.Unlock() + + if c.closed { + return 0, errors.New("connection closed") + } + + err := c.stream.Send(&pb.BytesMessage{Data: b}) + if err != nil { + c.closed = true + return 0, fmt.Errorf("stream send error: %w", err) + } + + return len(b), nil +} + +func (c *streamConn) Close() error { + c.closedOnce.Do(func() { + defer func() { + close(c.closeCh) + }() + + if cs, ok := c.stream.(grpc.ClientStream); ok { + c.writeMu.Lock() + err := cs.CloseSend() + c.writeMu.Unlock() + if err != nil { + return + } + } + + c.readMu.Lock() + for { + m := new(pb.BytesMessage) + m.Data = c.readBuf + err := c.stream.RecvMsg(m) + if err != nil { + if !errors.Is(err, io.EOF) { + c.readMu.Unlock() + return + } + err = nil + break + } + c.readBuf = m.Data[:cap(m.Data)] + c.lastBuf = append(c.lastBuf, c.readBuf...) + } + c.readMu.Unlock() + }) + return nil +} + +func (c *streamConn) LocalAddr() net.Addr { return &grpcAddr{} } +func (c *streamConn) RemoteAddr() net.Addr { return &grpcAddr{} } + +func (c *streamConn) SetDeadline(t time.Time) error { return nil } +func (c *streamConn) SetReadDeadline(t time.Time) error { return nil } +func (c *streamConn) SetWriteDeadline(t time.Time) error { return nil } + +type grpcAddr struct{} + +func (grpcAddr) Network() string { return "grpc" } +func (grpcAddr) String() string { return "grpc-stream" } diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 64c25015c1e..76f90e3f0d7 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -14,6 +14,7 @@ import ( "github.com/lima-vm/lima/pkg/driver" pb "github.com/lima-vm/lima/pkg/driver/external" + "github.com/lima-vm/lima/pkg/driver/external/client/grpchijack" "github.com/lima-vm/lima/pkg/store" ) @@ -259,7 +260,7 @@ func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { return nil, err } - return streamToConn(connStream), nil + return grpchijack.StreamToConn(connStream), nil } func (d *DriverClient) GetInfo() driver.Info { diff --git a/pkg/driver/external/client/pipe.go b/pkg/driver/external/client/pipe.go index 2bd20d54786..ab20228c4fa 100644 --- a/pkg/driver/external/client/pipe.go +++ b/pkg/driver/external/client/pipe.go @@ -12,9 +12,10 @@ import ( type PipeConn struct { Reader io.Reader Writer io.Writer + Closer io.Closer } -func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) *PipeConn { +func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) net.Conn { return &PipeConn{ Reader: reader, Writer: writer, @@ -30,16 +31,7 @@ func (p *PipeConn) Write(b []byte) (n int, err error) { } func (p *PipeConn) Close() error { - var err error - if closer, ok := p.Reader.(io.Closer); ok { - err = closer.Close() - } - if closer, ok := p.Writer.(io.Closer); ok { - if closeErr := closer.Close(); closeErr != nil && err == nil { - err = closeErr - } - } - return err + return p.Closer.Close() } func (p *PipeConn) LocalAddr() net.Addr { diff --git a/pkg/driver/external/client/stream.go b/pkg/driver/external/client/stream.go deleted file mode 100644 index ff16a8fe636..00000000000 --- a/pkg/driver/external/client/stream.go +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package client - -import ( - "errors" - "io" - "net" - "sync" - "time" - - pb "github.com/lima-vm/lima/pkg/driver/external" -) - -type streamConn struct { - stream pb.Driver_GuestAgentConnClient - readBuf []byte - readMu sync.Mutex - closeCh chan struct{} - closeOnce sync.Once - closed bool -} - -func streamToConn(stream pb.Driver_GuestAgentConnClient) *streamConn { - return &streamConn{ - stream: stream, - closeCh: make(chan struct{}), - } -} - -func (c *streamConn) Read(b []byte) (int, error) { - c.readMu.Lock() - defer c.readMu.Unlock() - - if c.closed { - return 0, io.EOF - } - - // Use any leftover data first - if len(c.readBuf) > 0 { - n := copy(b, c.readBuf) - c.readBuf = c.readBuf[n:] - return n, nil - } - - // Receive from stream - msg, err := c.stream.Recv() - if err != nil { - if err == io.EOF { - c.closed = true - return 0, io.EOF - } - return 0, err - } - - // Copy data to buffer - n := copy(b, msg.NetConn) - if n < len(msg.NetConn) { - // Store remaining data for next read - c.readBuf = make([]byte, len(msg.NetConn)-n) - copy(c.readBuf, msg.NetConn[n:]) - } - - return n, nil -} - -func (c *streamConn) Write(b []byte) (int, error) { - return 0, errors.New("write not supported on read-only stream connection") -} - -func (c *streamConn) Close() error { - c.closeOnce.Do(func() { - c.readMu.Lock() - c.closed = true - c.readMu.Unlock() - close(c.closeCh) - c.stream.CloseSend() - }) - return nil -} - -func (c *streamConn) LocalAddr() net.Addr { return &grpcAddr{} } -func (c *streamConn) RemoteAddr() net.Addr { return &grpcAddr{} } - -func (c *streamConn) SetDeadline(t time.Time) error { return nil } -func (c *streamConn) SetReadDeadline(t time.Time) error { return nil } -func (c *streamConn) SetWriteDeadline(t time.Time) error { return nil } - -type grpcAddr struct{} - -func (grpcAddr) Network() string { return "grpc" } -func (grpcAddr) String() string { return "grpc-stream" } diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index 2558ac45dad..72b3581ed1f 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -478,27 +478,27 @@ func (x *ForwardGuestAgentResponse) GetShouldForward() bool { return false } -type GuestAgentConnStream struct { +type BytesMessage struct { state protoimpl.MessageState `protogen:"open.v1"` - NetConn []byte `protobuf:"bytes,1,opt,name=net_conn,json=netConn,proto3" json:"net_conn,omitempty"` + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *GuestAgentConnStream) Reset() { - *x = GuestAgentConnStream{} +func (x *BytesMessage) Reset() { + *x = BytesMessage{} mi := &file_pkg_driver_external_driver_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *GuestAgentConnStream) String() string { +func (x *BytesMessage) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GuestAgentConnStream) ProtoMessage() {} +func (*BytesMessage) ProtoMessage() {} -func (x *GuestAgentConnStream) ProtoReflect() protoreflect.Message { +func (x *BytesMessage) ProtoReflect() protoreflect.Message { mi := &file_pkg_driver_external_driver_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -510,14 +510,14 @@ func (x *GuestAgentConnStream) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GuestAgentConnStream.ProtoReflect.Descriptor instead. -func (*GuestAgentConnStream) Descriptor() ([]byte, []int) { +// Deprecated: Use BytesMessage.ProtoReflect.Descriptor instead. +func (*BytesMessage) Descriptor() ([]byte, []int) { return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} } -func (x *GuestAgentConnStream) GetNetConn() []byte { +func (x *BytesMessage) GetData() []byte { if x != nil { - return x.NetConn + return x.Data } return nil } @@ -550,9 +550,9 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\x15ListSnapshotsResponse\x12\x1c\n" + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\"B\n" + "\x19ForwardGuestAgentResponse\x12%\n" + - "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"1\n" + - "\x14GuestAgentConnStream\x12\x19\n" + - "\bnet_conn\x18\x01 \x01(\fR\anetConn2\xfa\b\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"\"\n" + + "\fBytesMessage\x12\x12\n" + + "\x04data\x18\x01 \x01(\fR\x04data2\xea\b\n" + "\x06Driver\x12:\n" + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + @@ -571,8 +571,8 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + - "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12B\n" + - "\x0eGuestAgentConn\x12\x15.GuestAgentConnStream\x1a\x15.GuestAgentConnStream(\x010\x01\x126\n" + + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x122\n" + + "\x0eGuestAgentConn\x12\r.BytesMessage\x1a\r.BytesMessage(\x010\x01\x126\n" + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x16.google.protobuf.Empty\x120\n" + "\aGetInfo\x12\x16.google.protobuf.Empty\x1a\r.InfoResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" @@ -600,7 +600,7 @@ var file_pkg_driver_external_driver_proto_goTypes = []any{ (*DeleteSnapshotRequest)(nil), // 7: DeleteSnapshotRequest (*ListSnapshotsResponse)(nil), // 8: ListSnapshotsResponse (*ForwardGuestAgentResponse)(nil), // 9: ForwardGuestAgentResponse - (*GuestAgentConnStream)(nil), // 10: GuestAgentConnStream + (*BytesMessage)(nil), // 10: BytesMessage (*emptypb.Empty)(nil), // 11: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ @@ -619,7 +619,7 @@ var file_pkg_driver_external_driver_proto_depIdxs = []int32{ 11, // 12: Driver.Register:input_type -> google.protobuf.Empty 11, // 13: Driver.Unregister:input_type -> google.protobuf.Empty 11, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 10, // 15: Driver.GuestAgentConn:input_type -> GuestAgentConnStream + 10, // 15: Driver.GuestAgentConn:input_type -> BytesMessage 2, // 16: Driver.SetConfig:input_type -> SetConfigRequest 11, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty 11, // 18: Driver.Validate:output_type -> google.protobuf.Empty @@ -637,7 +637,7 @@ var file_pkg_driver_external_driver_proto_depIdxs = []int32{ 11, // 30: Driver.Register:output_type -> google.protobuf.Empty 11, // 31: Driver.Unregister:output_type -> google.protobuf.Empty 9, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 10, // 33: Driver.GuestAgentConn:output_type -> GuestAgentConnStream + 10, // 33: Driver.GuestAgentConn:output_type -> BytesMessage 11, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty 0, // 35: Driver.GetInfo:output_type -> InfoResponse 18, // [18:36] is the sub-list for method output_type diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index dc2d67b6593..4ab6d5ff980 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -24,7 +24,7 @@ service Driver { rpc Unregister(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); - rpc GuestAgentConn(stream GuestAgentConnStream) returns (stream GuestAgentConnStream); + rpc GuestAgentConn(stream BytesMessage) returns (stream BytesMessage); rpc SetConfig(SetConfigRequest) returns (google.protobuf.Empty); @@ -73,6 +73,6 @@ message ForwardGuestAgentResponse { bool should_forward = 1; } -message GuestAgentConnStream { - bytes net_conn = 1; +message BytesMessage { + bytes data = 1; } \ No newline at end of file diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index e9325262169..2b4ce35f29c 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -59,7 +59,7 @@ type DriverClient interface { Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) - GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[GuestAgentConnStream, GuestAgentConnStream], error) + GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[BytesMessage, BytesMessage], error) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) } @@ -231,18 +231,18 @@ func (c *driverClient) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, return out, nil } -func (c *driverClient) GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[GuestAgentConnStream, GuestAgentConnStream], error) { +func (c *driverClient) GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[BytesMessage, BytesMessage], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &Driver_ServiceDesc.Streams[1], Driver_GuestAgentConn_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[GuestAgentConnStream, GuestAgentConnStream]{ClientStream: stream} + x := &grpc.GenericClientStream[BytesMessage, BytesMessage]{ClientStream: stream} return x, nil } // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type Driver_GuestAgentConnClient = grpc.BidiStreamingClient[GuestAgentConnStream, GuestAgentConnStream] +type Driver_GuestAgentConnClient = grpc.BidiStreamingClient[BytesMessage, BytesMessage] func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -283,7 +283,7 @@ type DriverServer interface { Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) - GuestAgentConn(grpc.BidiStreamingServer[GuestAgentConnStream, GuestAgentConnStream]) error + GuestAgentConn(grpc.BidiStreamingServer[BytesMessage, BytesMessage]) error SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) mustEmbedUnimplementedDriverServer() @@ -341,7 +341,7 @@ func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*e func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ForwardGuestAgent not implemented") } -func (UnimplementedDriverServer) GuestAgentConn(grpc.BidiStreamingServer[GuestAgentConnStream, GuestAgentConnStream]) error { +func (UnimplementedDriverServer) GuestAgentConn(grpc.BidiStreamingServer[BytesMessage, BytesMessage]) error { return status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") } func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) { @@ -635,11 +635,11 @@ func _Driver_ForwardGuestAgent_Handler(srv interface{}, ctx context.Context, dec } func _Driver_GuestAgentConn_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(DriverServer).GuestAgentConn(&grpc.GenericServerStream[GuestAgentConnStream, GuestAgentConnStream]{ServerStream: stream}) + return srv.(DriverServer).GuestAgentConn(&grpc.GenericServerStream[BytesMessage, BytesMessage]{ServerStream: stream}) } // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type Driver_GuestAgentConnServer = grpc.BidiStreamingServer[GuestAgentConnStream, GuestAgentConnStream] +type Driver_GuestAgentConnServer = grpc.BidiStreamingServer[BytesMessage, BytesMessage] func _Driver_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetConfigRequest) diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 1fdbe4f7d18..ec8cc305d45 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -66,11 +66,12 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) error { s.logger.Debug("Received GuestAgentConn request") - conn, err := s.driver.GuestAgentConn(stream.Context()) + conn, err := s.driver.GuestAgentConn(context.Background()) if err != nil { s.logger.Errorf("GuestAgentConn failed: %v", err) return err } + s.logger.Debug("GuestAgentConn succeeded") go func() { for { @@ -78,10 +79,12 @@ func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) err if err != nil { return } - if len(msg.NetConn) > 0 { - _, err = conn.Write(msg.NetConn) + s.logger.Debugf("Received message from stream: %d bytes", len(msg.Data)) + if len(msg.Data) > 0 { + _, err = conn.Write(msg.Data) if err != nil { s.logger.Errorf("Error writing to connection: %v", err) + conn.Close() return } } @@ -93,13 +96,16 @@ func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) err n, err := conn.Read(buf) if err != nil { if errors.Is(err, io.EOF) { + s.logger.Debugf("Connection closed by guest agent %v", err) return nil } return status.Errorf(codes.Internal, "error reading: %v", err) } + s.logger.Debugf("Sending %d bytes to stream", n) - msg := &pb.GuestAgentConnStream{NetConn: buf[:n]} + msg := &pb.BytesMessage{Data: buf[:n]} if err := stream.Send(msg); err != nil { + s.logger.Errorf("Failed to send message to stream: %v", err) return err } } diff --git a/pkg/driver/external/server/pipe.go b/pkg/driver/external/server/pipe.go index 6acd59abb86..8bb1e4cf217 100644 --- a/pkg/driver/external/server/pipe.go +++ b/pkg/driver/external/server/pipe.go @@ -13,6 +13,7 @@ import ( type PipeConn struct { Reader io.Reader Writer io.Writer + Closer io.Closer } func (p *PipeConn) Read(b []byte) (n int, err error) { @@ -24,7 +25,7 @@ func (p *PipeConn) Write(b []byte) (n int, err error) { } func (p *PipeConn) Close() error { - return nil + return p.Closer.Close() } func (p *PipeConn) LocalAddr() net.Addr { From a4d2fcd82c8c29e9f96714435ccded7c9e85eddc Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 11 Jun 2025 15:22:47 +0530 Subject: [PATCH 37/49] driver(external): fix a nil pointer deref Signed-off-by: Ansuman Sahoo --- pkg/driver/external/client/pipe.go | 2 ++ pkg/driver/external/server/server.go | 1 + 2 files changed, 3 insertions(+) diff --git a/pkg/driver/external/client/pipe.go b/pkg/driver/external/client/pipe.go index ab20228c4fa..48b7985e2f7 100644 --- a/pkg/driver/external/client/pipe.go +++ b/pkg/driver/external/client/pipe.go @@ -6,6 +6,7 @@ package client import ( "io" "net" + "os" "time" ) @@ -19,6 +20,7 @@ func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) net.Conn { return &PipeConn{ Reader: reader, Writer: writer, + Closer: os.Stdout, } } diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 7dd00a2469c..16a0c670aa3 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -31,6 +31,7 @@ func Serve(driver driver.Driver) { pipeConn := &PipeConn{ Reader: os.Stdin, Writer: os.Stdout, + Closer: os.Stdout, } listener := NewPipeListener(pipeConn) From cc54d5c9b2ddd4d2907500b0cd0b98088c4ef39a Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 11 Jun 2025 17:44:41 +0530 Subject: [PATCH 38/49] driver(external): create driver logs in instance directory Signed-off-by: Ansuman Sahoo --- pkg/driverutil/instance.go | 2 +- pkg/registry/registry.go | 37 ++++++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index a32ff341b73..ac7b1fffd91 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -14,7 +14,7 @@ import ( // CreateTargetDriverInstance creates the appropriate driver for an instance. func CreateTargetDriverInstance(inst *store.Instance, sshLocalPort int) (driver.Driver, error) { limaDriver := inst.Config.VMType - driver, exists := registry.DefaultRegistry.Get(string(*limaDriver)) + driver, exists := registry.DefaultRegistry.Get(string(*limaDriver), inst.Name) if !exists { return nil, fmt.Errorf("unknown or unsupported VM type: %s", *limaDriver) } diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 3c3b2bf0da3..6cf06423e28 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -16,21 +16,23 @@ import ( "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/client" + "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" "github.com/lima-vm/lima/pkg/usrlocalsharelima" "github.com/sirupsen/logrus" ) type ExternalDriver struct { - Name string - Command *exec.Cmd - Stdin io.WriteCloser - Stdout io.ReadCloser - Client *client.DriverClient // Client is the gRPC client for the external driver - Path string - ctx context.Context - logger *logrus.Logger - cancelFunc context.CancelFunc + Name string + InstanceName string + Command *exec.Cmd + Stdin io.WriteCloser + Stdout io.ReadCloser + Client *client.DriverClient // Client is the gRPC client for the external driver + Path string + ctx context.Context + logger *logrus.Logger + cancelFunc context.CancelFunc } type Registry struct { @@ -46,8 +48,12 @@ func NewRegistry() *Registry { } } -func (e *ExternalDriver) Start() error { +func (e *ExternalDriver) Start(instName string) error { e.logger.Infof("Starting external driver at %s", e.Path) + if instName == "" { + return fmt.Errorf("instance name cannot be empty") + } + e.InstanceName = instName ctx, cancel := context.WithCancel(context.Background()) cmd := exec.CommandContext(ctx, e.Path) @@ -64,12 +70,12 @@ func (e *ExternalDriver) Start() error { return fmt.Errorf("failed to create stdout pipe: %w", err) } - sharedDir, err := usrlocalsharelima.Dir() + instanceDir, err := store.InstanceDir(e.InstanceName) if err != nil { cancel() - return fmt.Errorf("failed to determine Lima share directory: %w", err) + return fmt.Errorf("failed to determine instance directory: %w", err) } - logPath := filepath.Join(sharedDir, filenames.ExternalDriverStderrLog) + logPath := filepath.Join(instanceDir, filenames.ExternalDriverStderrLog) logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { cancel() @@ -167,7 +173,7 @@ func (r *Registry) List() []string { return names } -func (r *Registry) Get(name string) (driver.Driver, bool) { +func (r *Registry) Get(name, instName string) (driver.Driver, bool) { r.mu.RLock() defer r.mu.RUnlock() @@ -178,12 +184,13 @@ func (r *Registry) Get(name string) (driver.Driver, bool) { externalDriver.logger.Debugf("Using external driver %q", name) if externalDriver.Client == nil || externalDriver.Command == nil || externalDriver.Command.Process == nil { logrus.Infof("Starting new instance of external driver %q", name) - if err := externalDriver.Start(); err != nil { + if err := externalDriver.Start(instName); err != nil { externalDriver.logger.Errorf("Failed to start external driver %q: %v", name, err) return nil, false } } else { logrus.Infof("Reusing existing external driver %q instance", name) + r.externalDrivers[name].InstanceName = instName } return externalDriver.Client, true From aab01621f76bba9cd6d1bc90f08dff40f8fa55ec Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 13 Jun 2025 22:56:05 +0530 Subject: [PATCH 39/49] driver(external): proxy vsock to ga.sock for vz Signed-off-by: Ansuman Sahoo --- .../external/client/grpchijack/hijack.go | 264 +++++++++--------- pkg/driver/external/client/methods.go | 15 +- pkg/driver/external/driver.pb.go | 111 +++----- pkg/driver/external/driver.proto | 6 +- pkg/driver/external/driver_grpc.pb.go | 50 ++-- pkg/driver/external/server/methods.go | 50 +--- pkg/driver/external/server/server.go | 34 ++- .../qemu/cmd/{ => lima-driver-qemu}/main.go | 0 pkg/driver/vz/cmd/lima-driver-vz/main.go | 15 + pkg/networks/usernet/client.go | 3 + 10 files changed, 257 insertions(+), 291 deletions(-) rename pkg/driver/qemu/cmd/{ => lima-driver-qemu}/main.go (100%) create mode 100644 pkg/driver/vz/cmd/lima-driver-vz/main.go diff --git a/pkg/driver/external/client/grpchijack/hijack.go b/pkg/driver/external/client/grpchijack/hijack.go index 5b19d51ab51..eab93d620a6 100644 --- a/pkg/driver/external/client/grpchijack/hijack.go +++ b/pkg/driver/external/client/grpchijack/hijack.go @@ -1,135 +1,135 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-FileCopyrightText: Copyright The Lima Authors +// // SPDX-License-Identifier: Apache-2.0 package grpchijack -import ( - "errors" - "fmt" - "io" - "net" - "sync" - "time" - - pb "github.com/lima-vm/lima/pkg/driver/external" - "google.golang.org/grpc" -) - -type streamConn struct { - stream pb.Driver_GuestAgentConnClient - readBuf []byte - lastBuf []byte - readMu sync.Mutex - writeMu sync.Mutex - closeCh chan struct{} - closedOnce sync.Once - closed bool -} - -func StreamToConn(stream pb.Driver_GuestAgentConnClient) *streamConn { - return &streamConn{ - stream: stream, - closeCh: make(chan struct{}), - } -} - -func (c *streamConn) Read(b []byte) (int, error) { - c.readMu.Lock() - defer c.readMu.Unlock() - - if c.closed { - return 0, io.EOF - } - - if c.lastBuf != nil { - n := copy(b, c.lastBuf) - c.lastBuf = c.lastBuf[n:] - if len(c.lastBuf) == 0 { - c.lastBuf = nil - } - return n, nil - } - - msg := new(pb.BytesMessage) - msg, err := c.stream.Recv() - if err != nil { - c.closed = true - if err == io.EOF { - return 0, io.EOF - } - return 0, fmt.Errorf("stream receive error: %w", err) - } - - n := copy(b, msg.Data) - if n < len(msg.Data) { - c.readBuf = make([]byte, len(msg.Data)-n) - copy(c.readBuf, msg.Data[n:]) - } - - return n, nil -} - -func (c *streamConn) Write(b []byte) (int, error) { - c.writeMu.Lock() - defer c.writeMu.Unlock() - - if c.closed { - return 0, errors.New("connection closed") - } - - err := c.stream.Send(&pb.BytesMessage{Data: b}) - if err != nil { - c.closed = true - return 0, fmt.Errorf("stream send error: %w", err) - } - - return len(b), nil -} - -func (c *streamConn) Close() error { - c.closedOnce.Do(func() { - defer func() { - close(c.closeCh) - }() - - if cs, ok := c.stream.(grpc.ClientStream); ok { - c.writeMu.Lock() - err := cs.CloseSend() - c.writeMu.Unlock() - if err != nil { - return - } - } - - c.readMu.Lock() - for { - m := new(pb.BytesMessage) - m.Data = c.readBuf - err := c.stream.RecvMsg(m) - if err != nil { - if !errors.Is(err, io.EOF) { - c.readMu.Unlock() - return - } - err = nil - break - } - c.readBuf = m.Data[:cap(m.Data)] - c.lastBuf = append(c.lastBuf, c.readBuf...) - } - c.readMu.Unlock() - }) - return nil -} - -func (c *streamConn) LocalAddr() net.Addr { return &grpcAddr{} } -func (c *streamConn) RemoteAddr() net.Addr { return &grpcAddr{} } - -func (c *streamConn) SetDeadline(t time.Time) error { return nil } -func (c *streamConn) SetReadDeadline(t time.Time) error { return nil } -func (c *streamConn) SetWriteDeadline(t time.Time) error { return nil } - -type grpcAddr struct{} - -func (grpcAddr) Network() string { return "grpc" } -func (grpcAddr) String() string { return "grpc-stream" } +// import ( +// "errors" +// "fmt" +// "io" +// "net" +// "sync" +// "time" + +// pb "github.com/lima-vm/lima/pkg/driver/external" +// "google.golang.org/grpc" +// ) + +// type streamConn struct { +// stream pb.Driver_GuestAgentConnClient +// readBuf []byte +// lastBuf []byte +// readMu sync.Mutex +// writeMu sync.Mutex +// closeCh chan struct{} +// closedOnce sync.Once +// closed bool +// } + +// func StreamToConn(stream pb.Driver_GuestAgentConnClient) *streamConn { +// return &streamConn{ +// stream: stream, +// closeCh: make(chan struct{}), +// } +// } + +// func (c *streamConn) Read(b []byte) (int, error) { +// c.readMu.Lock() +// defer c.readMu.Unlock() + +// if c.closed { +// return 0, io.EOF +// } + +// if c.lastBuf != nil { +// n := copy(b, c.lastBuf) +// c.lastBuf = c.lastBuf[n:] +// if len(c.lastBuf) == 0 { +// c.lastBuf = nil +// } +// return n, nil +// } + +// msg := new(pb.BytesMessage) +// msg, err := c.stream.Recv() +// if err != nil { +// c.closed = true +// if err == io.EOF { +// return 0, io.EOF +// } +// return 0, fmt.Errorf("stream receive error: %w", err) +// } + +// n := copy(b, msg.Data) +// if n < len(msg.Data) { +// c.readBuf = make([]byte, len(msg.Data)-n) +// copy(c.readBuf, msg.Data[n:]) +// } + +// return n, nil +// } + +// func (c *streamConn) Write(b []byte) (int, error) { +// c.writeMu.Lock() +// defer c.writeMu.Unlock() + +// if c.closed { +// return 0, errors.New("connection closed") +// } + +// err := c.stream.Send(&pb.BytesMessage{Data: b}) +// if err != nil { +// c.closed = true +// return 0, fmt.Errorf("stream send error: %w", err) +// } + +// return len(b), nil +// } + +// func (c *streamConn) Close() error { +// c.closedOnce.Do(func() { +// defer func() { +// close(c.closeCh) +// }() + +// if cs, ok := c.stream.(grpc.ClientStream); ok { +// c.writeMu.Lock() +// err := cs.CloseSend() +// c.writeMu.Unlock() +// if err != nil { +// return +// } +// } + +// c.readMu.Lock() +// for { +// m := new(pb.BytesMessage) +// m.Data = c.readBuf +// err := c.stream.RecvMsg(m) +// if err != nil { +// if !errors.Is(err, io.EOF) { +// c.readMu.Unlock() +// return +// } +// err = nil +// break +// } +// c.readBuf = m.Data[:cap(m.Data)] +// c.lastBuf = append(c.lastBuf, c.readBuf...) +// } +// c.readMu.Unlock() +// }) +// return nil +// } + +// func (c *streamConn) LocalAddr() net.Addr { return &grpcAddr{} } +// func (c *streamConn) RemoteAddr() net.Addr { return &grpcAddr{} } + +// func (c *streamConn) SetDeadline(t time.Time) error { return nil } +// func (c *streamConn) SetReadDeadline(t time.Time) error { return nil } +// func (c *streamConn) SetWriteDeadline(t time.Time) error { return nil } + +// type grpcAddr struct{} + +// func (grpcAddr) Network() string { return "grpc" } +// func (grpcAddr) String() string { return "grpc-stream" } diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 76f90e3f0d7..6dc4e51561f 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -14,7 +14,6 @@ import ( "github.com/lima-vm/lima/pkg/driver" pb "github.com/lima-vm/lima/pkg/driver/external" - "github.com/lima-vm/lima/pkg/driver/external/client/grpchijack" "github.com/lima-vm/lima/pkg/store" ) @@ -240,27 +239,23 @@ func (d *DriverClient) ForwardGuestAgent() bool { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - resp, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{}) + _, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to check guest agent forwarding: %v", err) return false } - d.logger.Debugf("Guest agent forwarding status: %v", resp.ShouldForward) - return resp.ShouldForward + return true } -// NOTE: This method is might not work correctly. func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { - d.logger.Debug("Getting guest agent connection") - - connStream, err := d.DriverSvc.GuestAgentConn(ctx) + d.logger.Info("Getting guest agent connection") + _, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to get guest agent connection: %v", err) return nil, err } - - return grpchijack.StreamToConn(connStream), nil + return nil, nil } func (d *DriverClient) GetInfo() driver.Info { diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index 72b3581ed1f..29719a4a2ec 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -478,50 +478,6 @@ func (x *ForwardGuestAgentResponse) GetShouldForward() bool { return false } -type BytesMessage struct { - state protoimpl.MessageState `protogen:"open.v1"` - Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BytesMessage) Reset() { - *x = BytesMessage{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BytesMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BytesMessage) ProtoMessage() {} - -func (x *BytesMessage) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BytesMessage.ProtoReflect.Descriptor instead. -func (*BytesMessage) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} -} - -func (x *BytesMessage) GetData() []byte { - if x != nil { - return x.Data - } - return nil -} - var File_pkg_driver_external_driver_proto protoreflect.FileDescriptor const file_pkg_driver_external_driver_proto_rawDesc = "" + @@ -550,9 +506,7 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\x15ListSnapshotsResponse\x12\x1c\n" + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\"B\n" + "\x19ForwardGuestAgentResponse\x12%\n" + - "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward\"\"\n" + - "\fBytesMessage\x12\x12\n" + - "\x04data\x18\x01 \x01(\fR\x04data2\xea\b\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward2\xf8\b\n" + "\x06Driver\x12:\n" + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + @@ -571,8 +525,8 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + - "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x122\n" + - "\x0eGuestAgentConn\x12\r.BytesMessage\x1a\r.BytesMessage(\x010\x01\x126\n" + + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12@\n" + + "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x126\n" + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x16.google.protobuf.Empty\x120\n" + "\aGetInfo\x12\x16.google.protobuf.Empty\x1a\r.InfoResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" @@ -588,7 +542,7 @@ func file_pkg_driver_external_driver_proto_rawDescGZIP() []byte { return file_pkg_driver_external_driver_proto_rawDescData } -var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_pkg_driver_external_driver_proto_goTypes = []any{ (*InfoResponse)(nil), // 0: InfoResponse (*StartResponse)(nil), // 1: StartResponse @@ -600,45 +554,44 @@ var file_pkg_driver_external_driver_proto_goTypes = []any{ (*DeleteSnapshotRequest)(nil), // 7: DeleteSnapshotRequest (*ListSnapshotsResponse)(nil), // 8: ListSnapshotsResponse (*ForwardGuestAgentResponse)(nil), // 9: ForwardGuestAgentResponse - (*BytesMessage)(nil), // 10: BytesMessage - (*emptypb.Empty)(nil), // 11: google.protobuf.Empty + (*emptypb.Empty)(nil), // 10: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ - 11, // 0: Driver.Validate:input_type -> google.protobuf.Empty - 11, // 1: Driver.Initialize:input_type -> google.protobuf.Empty - 11, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty - 11, // 3: Driver.Start:input_type -> google.protobuf.Empty - 11, // 4: Driver.Stop:input_type -> google.protobuf.Empty - 11, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty + 10, // 0: Driver.Validate:input_type -> google.protobuf.Empty + 10, // 1: Driver.Initialize:input_type -> google.protobuf.Empty + 10, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty + 10, // 3: Driver.Start:input_type -> google.protobuf.Empty + 10, // 4: Driver.Stop:input_type -> google.protobuf.Empty + 10, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty 3, // 6: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest - 11, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty + 10, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty 5, // 8: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest 6, // 9: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest 7, // 10: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest - 11, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty - 11, // 12: Driver.Register:input_type -> google.protobuf.Empty - 11, // 13: Driver.Unregister:input_type -> google.protobuf.Empty - 11, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 10, // 15: Driver.GuestAgentConn:input_type -> BytesMessage + 10, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty + 10, // 12: Driver.Register:input_type -> google.protobuf.Empty + 10, // 13: Driver.Unregister:input_type -> google.protobuf.Empty + 10, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty + 10, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty 2, // 16: Driver.SetConfig:input_type -> SetConfigRequest - 11, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty - 11, // 18: Driver.Validate:output_type -> google.protobuf.Empty - 11, // 19: Driver.Initialize:output_type -> google.protobuf.Empty - 11, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty + 10, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty + 10, // 18: Driver.Validate:output_type -> google.protobuf.Empty + 10, // 19: Driver.Initialize:output_type -> google.protobuf.Empty + 10, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty 1, // 21: Driver.Start:output_type -> StartResponse - 11, // 22: Driver.Stop:output_type -> google.protobuf.Empty - 11, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty - 11, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty + 10, // 22: Driver.Stop:output_type -> google.protobuf.Empty + 10, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty + 10, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty 4, // 25: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse - 11, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty - 11, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty - 11, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty + 10, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty + 10, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty + 10, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty 8, // 29: Driver.ListSnapshots:output_type -> ListSnapshotsResponse - 11, // 30: Driver.Register:output_type -> google.protobuf.Empty - 11, // 31: Driver.Unregister:output_type -> google.protobuf.Empty + 10, // 30: Driver.Register:output_type -> google.protobuf.Empty + 10, // 31: Driver.Unregister:output_type -> google.protobuf.Empty 9, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 10, // 33: Driver.GuestAgentConn:output_type -> BytesMessage - 11, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty + 10, // 33: Driver.GuestAgentConn:output_type -> google.protobuf.Empty + 10, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty 0, // 35: Driver.GetInfo:output_type -> InfoResponse 18, // [18:36] is the sub-list for method output_type 0, // [0:18] is the sub-list for method input_type @@ -658,7 +611,7 @@ func file_pkg_driver_external_driver_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc)), NumEnums: 0, - NumMessages: 11, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index 4ab6d5ff980..82c77feec64 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -24,7 +24,7 @@ service Driver { rpc Unregister(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); - rpc GuestAgentConn(stream BytesMessage) returns (stream BytesMessage); + rpc GuestAgentConn(google.protobuf.Empty) returns (google.protobuf.Empty); rpc SetConfig(SetConfigRequest) returns (google.protobuf.Empty); @@ -71,8 +71,4 @@ message ListSnapshotsResponse { message ForwardGuestAgentResponse { bool should_forward = 1; -} - -message BytesMessage { - bytes data = 1; } \ No newline at end of file diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index 2b4ce35f29c..5e1dcde983c 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -59,7 +59,7 @@ type DriverClient interface { Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) - GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[BytesMessage, BytesMessage], error) + GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) } @@ -231,19 +231,16 @@ func (c *driverClient) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, return out, nil } -func (c *driverClient) GuestAgentConn(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[BytesMessage, BytesMessage], error) { +func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &Driver_ServiceDesc.Streams[1], Driver_GuestAgentConn_FullMethodName, cOpts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, Driver_GuestAgentConn_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[BytesMessage, BytesMessage]{ClientStream: stream} - return x, nil + return out, nil } -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type Driver_GuestAgentConnClient = grpc.BidiStreamingClient[BytesMessage, BytesMessage] - func (c *driverClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) @@ -283,7 +280,7 @@ type DriverServer interface { Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) - GuestAgentConn(grpc.BidiStreamingServer[BytesMessage, BytesMessage]) error + GuestAgentConn(context.Context, *emptypb.Empty) (*emptypb.Empty, error) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) mustEmbedUnimplementedDriverServer() @@ -341,8 +338,8 @@ func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*e func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ForwardGuestAgent not implemented") } -func (UnimplementedDriverServer) GuestAgentConn(grpc.BidiStreamingServer[BytesMessage, BytesMessage]) error { - return status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") +func (UnimplementedDriverServer) GuestAgentConn(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") } func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method SetConfig not implemented") @@ -634,13 +631,24 @@ func _Driver_ForwardGuestAgent_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } -func _Driver_GuestAgentConn_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(DriverServer).GuestAgentConn(&grpc.GenericServerStream[BytesMessage, BytesMessage]{ServerStream: stream}) +func _Driver_GuestAgentConn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverServer).GuestAgentConn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Driver_GuestAgentConn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverServer).GuestAgentConn(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) } -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type Driver_GuestAgentConnServer = grpc.BidiStreamingServer[BytesMessage, BytesMessage] - func _Driver_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetConfigRequest) if err := dec(in); err != nil { @@ -740,6 +748,10 @@ var Driver_ServiceDesc = grpc.ServiceDesc{ MethodName: "ForwardGuestAgent", Handler: _Driver_ForwardGuestAgent_Handler, }, + { + MethodName: "GuestAgentConn", + Handler: _Driver_GuestAgentConn_Handler, + }, { MethodName: "SetConfig", Handler: _Driver_SetConfig_Handler, @@ -755,12 +767,6 @@ var Driver_ServiceDesc = grpc.ServiceDesc{ Handler: _Driver_Start_Handler, ServerStreams: true, }, - { - StreamName: "GuestAgentConn", - Handler: _Driver_GuestAgentConn_Handler, - ServerStreams: true, - ClientStreams: true, - }, }, Metadata: "pkg/driver/external/driver.proto", } diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index ec8cc305d45..65047544e27 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -6,8 +6,7 @@ package server import ( "context" "encoding/json" - "errors" - "io" + "path/filepath" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -15,6 +14,7 @@ import ( pb "github.com/lima-vm/lima/pkg/driver/external" "github.com/lima-vm/lima/pkg/store" + "github.com/lima-vm/lima/pkg/store/filenames" ) func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) error { @@ -64,51 +64,17 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) return &emptypb.Empty{}, nil } -func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) error { +func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { s.logger.Debug("Received GuestAgentConn request") - conn, err := s.driver.GuestAgentConn(context.Background()) + conn, err := s.driver.GuestAgentConn(ctx) if err != nil { s.logger.Errorf("GuestAgentConn failed: %v", err) - return err + return &emptypb.Empty{}, status.Errorf(codes.Internal, "failed to establish guest agent connection: %v", err) } - s.logger.Debug("GuestAgentConn succeeded") - go func() { - for { - msg, err := stream.Recv() - if err != nil { - return - } - s.logger.Debugf("Received message from stream: %d bytes", len(msg.Data)) - if len(msg.Data) > 0 { - _, err = conn.Write(msg.Data) - if err != nil { - s.logger.Errorf("Error writing to connection: %v", err) - conn.Close() - return - } - } - } - }() - - buf := make([]byte, 32*1<<10) - for { - n, err := conn.Read(buf) - if err != nil { - if errors.Is(err, io.EOF) { - s.logger.Debugf("Connection closed by guest agent %v", err) - return nil - } - return status.Errorf(codes.Internal, "error reading: %v", err) - } - s.logger.Debugf("Sending %d bytes to stream", n) - - msg := &pb.BytesMessage{Data: buf[:n]} - if err := stream.Send(msg); err != nil { - s.logger.Errorf("Failed to send message to stream: %v", err) - return err - } - } + go HandleProxyConnection(conn, filepath.Join("/Users/ansumansahoo/.lima/default/", filenames.GuestAgentSock)) + s.logger.Debug("GuestAgentConn succeeded, connection handled") + return &emptypb.Empty{}, nil } func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 16a0c670aa3..1b7e47e61ec 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -4,6 +4,8 @@ package server import ( + "io" + "net" "os" "os/signal" "syscall" @@ -42,7 +44,7 @@ func Serve(driver driver.Driver) { } kaPolicy := keepalive.EnforcementPolicy{ - MinTime: 2 * time.Second, + MinTime: 10 * time.Second, PermitWithoutStream: true, } @@ -71,3 +73,33 @@ func Serve(driver driver.Driver) { logger.Fatalf("Failed to serve: %v", err) } } + +func HandleProxyConnection(conn net.Conn, unixSocketPath string) { + defer conn.Close() + + logrus.Infof("Handling proxy connection from %s", conn.LocalAddr()) + + unixConn, err := net.Dial("unix", unixSocketPath) + if err != nil { + logrus.Errorf("Failed to connect to unix socket %s: %v", unixSocketPath, err) + return + } + defer unixConn.Close() + + logrus.Infof("Successfully established proxy tunnel: %s <--> %s", conn.LocalAddr(), unixSocketPath) + + go func() { + _, err := io.Copy(conn, unixConn) + if err != nil { + logrus.Errorf("Error copying from unix to vsock: %v", err) + } + }() + + _, err = io.Copy(unixConn, conn) + if err != nil { + logrus.Errorf("Error copying from vsock to unix: %v", err) + } + + logrus.Infof("Proxy session ended for %s", conn.LocalAddr()) + +} diff --git a/pkg/driver/qemu/cmd/main.go b/pkg/driver/qemu/cmd/lima-driver-qemu/main.go similarity index 100% rename from pkg/driver/qemu/cmd/main.go rename to pkg/driver/qemu/cmd/lima-driver-qemu/main.go diff --git a/pkg/driver/vz/cmd/lima-driver-vz/main.go b/pkg/driver/vz/cmd/lima-driver-vz/main.go new file mode 100644 index 00000000000..b60edf8d996 --- /dev/null +++ b/pkg/driver/vz/cmd/lima-driver-vz/main.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "github.com/lima-vm/lima/pkg/driver/external/server" + "github.com/lima-vm/lima/pkg/driver/vz" +) + +// To be used as an external driver for Lima. +func main() { + driver := vz.New() + server.Serve(driver) +} diff --git a/pkg/networks/usernet/client.go b/pkg/networks/usernet/client.go index 8bc478cb0f2..4ed790321e0 100644 --- a/pkg/networks/usernet/client.go +++ b/pkg/networks/usernet/client.go @@ -43,6 +43,9 @@ func (c *Client) ConfigureDriver(ctx context.Context, inst *store.Instance, sshL return err } hosts := inst.Config.HostResolver.Hosts + if hosts == nil { + hosts = make(map[string]string) + } hosts[fmt.Sprintf("%s.internal", inst.Hostname)] = ipAddress err = c.AddDNSHosts(hosts) return err From d13a7dea029c7b3926b1f7d638b852e840ac4dfa Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 18 Jun 2025 03:19:46 +0530 Subject: [PATCH 40/49] driver(external): change grpc transport to unix sockets Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 9 +- pkg/driver/external/client/client.go | 34 ++-- .../external/client/grpchijack/hijack.go | 6 +- pkg/driver/external/client/methods.go | 2 + pkg/driver/external/client/pipe.go | 114 +++++------ pkg/driver/external/driver.proto | 4 + pkg/driver/external/server/methods.go | 64 +++++- pkg/driver/external/server/pipe.go | 188 +++++++++--------- pkg/driver/external/server/server.go | 61 +++--- pkg/driver/qemu/qemu_driver.go | 15 +- pkg/driver/vz/cmd/lima-driver-vz/main.go | 2 + pkg/driver/vz/vz_driver_darwin.go | 3 + pkg/driver/wsl2/wsl_driver_windows.go | 13 +- pkg/hostagent/hostagent.go | 6 +- pkg/registry/registry.go | 36 ++-- pkg/store/filenames/filenames.go | 1 + 16 files changed, 321 insertions(+), 237 deletions(-) diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 752aab69d68..8a91ad721a4 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -84,8 +84,9 @@ type Driver interface { } type Info struct { - DriverName string `json:"driverName"` - CanRunGUI bool `json:"canRunGui,omitempty"` - VsockPort int `json:"vsockPort"` - VirtioPort string `json:"virtioPort"` + DriverName string `json:"driverName"` + CanRunGUI bool `json:"canRunGui,omitempty"` + VsockPort int `json:"vsockPort"` + VirtioPort string `json:"virtioPort"` + InstanceDir string `json:"instanceDir,omitempty"` } diff --git a/pkg/driver/external/client/client.go b/pkg/driver/external/client/client.go index b7141cad11d..675dfb6fb61 100644 --- a/pkg/driver/external/client/client.go +++ b/pkg/driver/external/client/client.go @@ -5,8 +5,6 @@ package client import ( "context" - "io" - "math" "net" pb "github.com/lima-vm/lima/pkg/driver/external" @@ -16,22 +14,19 @@ import ( ) type DriverClient struct { - Stdin io.WriteCloser - Stdout io.ReadCloser - Conn *grpc.ClientConn - DriverSvc pb.DriverClient - logger *logrus.Logger + socketPath string + Conn *grpc.ClientConn + DriverSvc pb.DriverClient + logger *logrus.Logger } -func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus.Logger) (*DriverClient, error) { - pipeConn := newPipeConn(stdin, stdout) +func NewDriverClient(socketPath string, logger *logrus.Logger) (*DriverClient, error) { + // pipeConn := newPipeConn(stdin, stdout) opts := []grpc.DialOption{ - grpc.WithDefaultCallOptions( - grpc.MaxCallRecvMsgSize(math.MaxInt64), - grpc.MaxCallSendMsgSize(math.MaxInt64), - ), + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(16 << 20)), + grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(16 << 20)), grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { - return pipeConn, nil + return net.Dial("unix", socketPath) }), grpc.WithTransportCredentials(insecure.NewCredentials()), } @@ -44,7 +39,7 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus. // -> ERRO[2025-06-04T21:32:54+05:30] Failed to set config: rpc error: code = // Unavailable desc = name resolver error: produced zero addresses - conn, err := grpc.Dial("pipe", opts...) + conn, err := grpc.Dial("unix://"+socketPath, opts...) if err != nil { logger.Errorf("failed to dial gRPC driver client connection: %v", err) return nil, err @@ -53,10 +48,9 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus. driverSvc := pb.NewDriverClient(conn) return &DriverClient{ - Stdin: stdin, - Stdout: stdout, - Conn: conn, - DriverSvc: driverSvc, - logger: logger, + socketPath: socketPath, + Conn: conn, + DriverSvc: driverSvc, + logger: logger, }, nil } diff --git a/pkg/driver/external/client/grpchijack/hijack.go b/pkg/driver/external/client/grpchijack/hijack.go index eab93d620a6..b4b003fe5e8 100644 --- a/pkg/driver/external/client/grpchijack/hijack.go +++ b/pkg/driver/external/client/grpchijack/hijack.go @@ -50,7 +50,7 @@ package grpchijack // return n, nil // } -// msg := new(pb.BytesMessage) +// msg := new(pb.NetConn) // msg, err := c.stream.Recv() // if err != nil { // c.closed = true @@ -77,7 +77,7 @@ package grpchijack // return 0, errors.New("connection closed") // } -// err := c.stream.Send(&pb.BytesMessage{Data: b}) +// err := c.stream.Send(&pb.NetConn{Data: b}) // if err != nil { // c.closed = true // return 0, fmt.Errorf("stream send error: %w", err) @@ -103,7 +103,7 @@ package grpchijack // c.readMu.Lock() // for { -// m := new(pb.BytesMessage) +// m := new(pb.) // m.Data = c.readBuf // err := c.stream.RecvMsg(m) // if err != nil { diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 6dc4e51561f..d1c2e009d0f 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -10,6 +10,8 @@ import ( "net" "time" + // "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/emptypb" "github.com/lima-vm/lima/pkg/driver" diff --git a/pkg/driver/external/client/pipe.go b/pkg/driver/external/client/pipe.go index 48b7985e2f7..aa30a70f86a 100644 --- a/pkg/driver/external/client/pipe.go +++ b/pkg/driver/external/client/pipe.go @@ -3,60 +3,60 @@ package client -import ( - "io" - "net" - "os" - "time" -) - -type PipeConn struct { - Reader io.Reader - Writer io.Writer - Closer io.Closer -} - -func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) net.Conn { - return &PipeConn{ - Reader: reader, - Writer: writer, - Closer: os.Stdout, - } -} - -func (p *PipeConn) Read(b []byte) (n int, err error) { - return p.Reader.Read(b) -} - -func (p *PipeConn) Write(b []byte) (n int, err error) { - return p.Writer.Write(b) -} - -func (p *PipeConn) Close() error { - return p.Closer.Close() -} - -func (p *PipeConn) LocalAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) RemoteAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) SetDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetReadDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetWriteDeadline(t time.Time) error { - return nil -} - -type pipeAddr struct{} - -func (pipeAddr) Network() string { return "pipe" } -func (pipeAddr) String() string { return "pipe" } +// import ( +// "io" +// "net" +// "os" +// "time" +// ) + +// type PipeConn struct { +// Reader io.Reader +// Writer io.Writer +// Closer io.Closer +// } + +// func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) net.Conn { +// return &PipeConn{ +// Reader: reader, +// Writer: writer, +// Closer: os.Stdout, +// } +// } + +// func (p *PipeConn) Read(b []byte) (n int, err error) { +// return p.Reader.Read(b) +// } + +// func (p *PipeConn) Write(b []byte) (n int, err error) { +// return p.Writer.Write(b) +// } + +// func (p *PipeConn) Close() error { +// return p.Closer.Close() +// } + +// func (p *PipeConn) LocalAddr() net.Addr { +// return pipeAddr{} +// } + +// func (p *PipeConn) RemoteAddr() net.Addr { +// return pipeAddr{} +// } + +// func (p *PipeConn) SetDeadline(t time.Time) error { +// return nil +// } + +// func (p *PipeConn) SetReadDeadline(t time.Time) error { +// return nil +// } + +// func (p *PipeConn) SetWriteDeadline(t time.Time) error { +// return nil +// } + +// type pipeAddr struct{} + +// func (pipeAddr) Network() string { return "pipe" } +// func (pipeAddr) String() string { return "pipe" } diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index 82c77feec64..db93410562e 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -31,6 +31,10 @@ service Driver { rpc GetInfo(google.protobuf.Empty) returns (InfoResponse); } +// message NetConn { +// bytes data = 1; +// } + message InfoResponse{ bytes info_json = 1; } diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 65047544e27..5eef59be394 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -6,15 +6,20 @@ package server import ( "context" "encoding/json" + "net" "path/filepath" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + // "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" + "github.com/lima-vm/lima/pkg/bicopy" pb "github.com/lima-vm/lima/pkg/driver/external" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" + "github.com/sirupsen/logrus" ) func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) error { @@ -72,11 +77,68 @@ func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) return &emptypb.Empty{}, status.Errorf(codes.Internal, "failed to establish guest agent connection: %v", err) } - go HandleProxyConnection(conn, filepath.Join("/Users/ansumansahoo/.lima/default/", filenames.GuestAgentSock)) + unixSocketPath := filepath.Join(s.driver.GetInfo().InstanceDir, filenames.GuestAgentSock) + var d net.Dialer + unixConn, err := d.DialContext(ctx, "unix", unixSocketPath) + if err != nil { + logrus.Errorf("Failed to connect to unix socket %s: %v", unixSocketPath, err) + return nil, status.Errorf(codes.Internal, "failed to connect to unix socket %s: %v", unixSocketPath, err) + } + + go bicopy.Bicopy(conn, unixConn, nil) + s.logger.Debug("GuestAgentConn succeeded, connection handled") return &emptypb.Empty{}, nil } +// func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) error { +// s.logger.Debug("Received GuestAgentConn request") +// conn, err := s.driver.GuestAgentConn(stream.Context()) +// if err != nil { +// s.logger.Errorf("GuestAgentConn failed: %v", err) +// return err +// } + +// s.logger.Debug("GuestAgentConn succeeded") + +// go func() { +// for { +// msg, err := stream.Recv() +// if err != nil { +// return +// } +// s.logger.Debugf("Received message from stream: %d bytes", len(msg.Data)) +// if len(msg.Data) > 0 { +// _, err = conn.Write(msg.Data) +// if err != nil { +// s.logger.Errorf("Error writing to connection: %v", err) +// conn.Close() +// return +// } +// } +// } +// }() + +// buf := make([]byte, 32*1<<10) +// for { +// n, err := conn.Read(buf) +// if err != nil { +// if errors.Is(err, io.EOF) { +// s.logger.Debugf("Connection closed by guest agent %v", err) +// return nil +// } +// return status.Errorf(codes.Internal, "error reading: %v", err) +// } +// s.logger.Debugf("Sending %d bytes to stream", n) + +// msg := &pb.NetConn{Data: buf[:n]} +// if err := stream.Send(msg); err != nil { +// s.logger.Errorf("Failed to send message to stream: %v", err) +// return err +// } +// } +// } + func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { s.logger.Debug("Received GetInfo request") info := s.driver.GetInfo() diff --git a/pkg/driver/external/server/pipe.go b/pkg/driver/external/server/pipe.go index 8bb1e4cf217..d3c567121ec 100644 --- a/pkg/driver/external/server/pipe.go +++ b/pkg/driver/external/server/pipe.go @@ -3,97 +3,97 @@ package server -import ( - "io" - "net" - "sync" - "time" -) - -type PipeConn struct { - Reader io.Reader - Writer io.Writer - Closer io.Closer -} - -func (p *PipeConn) Read(b []byte) (n int, err error) { - return p.Reader.Read(b) -} - -func (p *PipeConn) Write(b []byte) (n int, err error) { - return p.Writer.Write(b) -} - -func (p *PipeConn) Close() error { - return p.Closer.Close() -} - -func (p *PipeConn) LocalAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) RemoteAddr() net.Addr { - return pipeAddr{} -} - -func (p *PipeConn) SetDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetReadDeadline(t time.Time) error { - return nil -} - -func (p *PipeConn) SetWriteDeadline(t time.Time) error { - return nil -} - -type pipeAddr struct{} - -func (pipeAddr) Network() string { return "pipe" } -func (pipeAddr) String() string { return "pipe" } - -type PipeListener struct { - conn net.Conn - connSent bool - mu sync.Mutex - closed bool -} - -func NewPipeListener(conn net.Conn) *PipeListener { - return &PipeListener{ - conn: conn, - connSent: false, - closed: false, - } -} - -func (l *PipeListener) Accept() (net.Conn, error) { - l.mu.Lock() - defer l.mu.Unlock() - - if l.closed { - return nil, net.ErrClosed - } - - if l.connSent { - select {} - } - - l.connSent = true - return l.conn, nil -} - -func (l *PipeListener) Close() error { - l.mu.Lock() - defer l.mu.Unlock() - - if !l.closed { - l.closed = true - } - return nil -} - -func (l *PipeListener) Addr() net.Addr { - return pipeAddr{} -} +// import ( +// "io" +// "net" +// "sync" +// "time" +// ) + +// type PipeConn struct { +// Reader io.Reader +// Writer io.Writer +// Closer io.Closer +// } + +// func (p *PipeConn) Read(b []byte) (n int, err error) { +// return p.Reader.Read(b) +// } + +// func (p *PipeConn) Write(b []byte) (n int, err error) { +// return p.Writer.Write(b) +// } + +// func (p *PipeConn) Close() error { +// return p.Closer.Close() +// } + +// func (p *PipeConn) LocalAddr() net.Addr { +// return pipeAddr{} +// } + +// func (p *PipeConn) RemoteAddr() net.Addr { +// return pipeAddr{} +// } + +// func (p *PipeConn) SetDeadline(t time.Time) error { +// return nil +// } + +// func (p *PipeConn) SetReadDeadline(t time.Time) error { +// return nil +// } + +// func (p *PipeConn) SetWriteDeadline(t time.Time) error { +// return nil +// } + +// type pipeAddr struct{} + +// func (pipeAddr) Network() string { return "pipe" } +// func (pipeAddr) String() string { return "pipe" } + +// type PipeListener struct { +// conn net.Conn +// connSent bool +// mu sync.Mutex +// closed bool +// } + +// func NewPipeListener(conn net.Conn) *PipeListener { +// return &PipeListener{ +// conn: conn, +// connSent: false, +// closed: false, +// } +// } + +// func (l *PipeListener) Accept() (net.Conn, error) { +// l.mu.Lock() +// defer l.mu.Unlock() + +// if l.closed { +// return nil, net.ErrClosed +// } + +// if l.connSent { +// select {} +// } + +// l.connSent = true +// return l.conn, nil +// } + +// func (l *PipeListener) Close() error { +// l.mu.Lock() +// defer l.mu.Unlock() + +// if !l.closed { +// l.closed = true +// } +// return nil +// } + +// func (l *PipeListener) Addr() net.Addr { +// return pipeAddr{} +// } diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 1b7e47e61ec..39dbd21f0de 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -4,10 +4,12 @@ package server import ( - "io" + "context" + "fmt" "net" "os" "os/signal" + "path/filepath" "syscall" "time" @@ -15,6 +17,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/keepalive" + "github.com/lima-vm/lima/pkg/bicopy" "github.com/lima-vm/lima/pkg/driver" pb "github.com/lima-vm/lima/pkg/driver/external" ) @@ -28,15 +31,33 @@ type DriverServer struct { func Serve(driver driver.Driver) { logger := logrus.New() logger.SetLevel(logrus.DebugLevel) - logger.Infof("Starting external driver server for %s", driver.GetInfo().DriverName) + // pipeConn := &PipeConn{ + // Reader: os.Stdin, + // Writer: os.Stdout, + // Closer: os.Stdout, + // } + + // listener := NewPipeListener(pipeConn) + + socketPath := filepath.Join(os.TempDir(), fmt.Sprintf("lima-driver-%s-%d.sock", driver.GetInfo().DriverName, os.Getpid())) - pipeConn := &PipeConn{ - Reader: os.Stdin, - Writer: os.Stdout, - Closer: os.Stdout, + defer func() { + if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) { + logger.Warnf("Failed to remove socket file: %v", err) + } + }() + + if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) { + logger.Fatalf("Failed to remove existing socket file: %v", err) + } + + listener, err := net.Listen("unix", socketPath) + if err != nil { + logger.Fatalf("Failed to listen on Unix socket: %v", err) } + defer listener.Close() - listener := NewPipeListener(pipeConn) + fmt.Println(socketPath) kaProps := keepalive.ServerParameters{ Time: 10 * time.Second, @@ -64,42 +85,30 @@ func Serve(driver driver.Driver) { go func() { <-sigs logger.Info("Received shutdown signal, stopping server...") - server.Stop() + server.GracefulStop() os.Exit(0) }() - logger.Info("Server starting...") + logger.Infof("Starting external driver server for %s", driver.GetInfo().DriverName) + logger.Infof("Server starting on Unix socket: %s", socketPath) if err := server.Serve(listener); err != nil { logger.Fatalf("Failed to serve: %v", err) } } -func HandleProxyConnection(conn net.Conn, unixSocketPath string) { - defer conn.Close() - +func HandleProxyConnection(ctx context.Context, conn net.Conn, unixSocketPath string) { logrus.Infof("Handling proxy connection from %s", conn.LocalAddr()) - unixConn, err := net.Dial("unix", unixSocketPath) + var d net.Dialer + unixConn, err := d.DialContext(ctx, "unix", unixSocketPath) if err != nil { logrus.Errorf("Failed to connect to unix socket %s: %v", unixSocketPath, err) return } - defer unixConn.Close() logrus.Infof("Successfully established proxy tunnel: %s <--> %s", conn.LocalAddr(), unixSocketPath) - go func() { - _, err := io.Copy(conn, unixConn) - if err != nil { - logrus.Errorf("Error copying from unix to vsock: %v", err) - } - }() - - _, err = io.Copy(unixConn, conn) - if err != nil { - logrus.Errorf("Error copying from vsock to unix: %v", err) - } + go bicopy.Bicopy(unixConn, conn, nil) logrus.Infof("Proxy session ended for %s", conn.LocalAddr()) - } diff --git a/pkg/driver/qemu/qemu_driver.go b/pkg/driver/qemu/qemu_driver.go index ee29208c752..8ed74654acc 100644 --- a/pkg/driver/qemu/qemu_driver.go +++ b/pkg/driver/qemu/qemu_driver.go @@ -512,12 +512,15 @@ func (a *qArgTemplateApplier) applyTemplate(qArg string) (string, error) { } func (l *LimaQemuDriver) GetInfo() driver.Info { - return driver.Info{ - DriverName: "qemu", - CanRunGUI: false, - VsockPort: l.VSockPort, - VirtioPort: l.VirtioPort, - } + var info driver.Info + if l.Instance != nil && l.Instance.Dir != "" { + info.InstanceDir = l.Instance.Dir + } + info.DriverName = "qemu" + info.CanRunGUI = false + info.VirtioPort = l.VirtioPort + info.VsockPort = l.VSockPort + return info } func (l *LimaQemuDriver) Initialize(_ context.Context) error { diff --git a/pkg/driver/vz/cmd/lima-driver-vz/main.go b/pkg/driver/vz/cmd/lima-driver-vz/main.go index b60edf8d996..267df019d6b 100644 --- a/pkg/driver/vz/cmd/lima-driver-vz/main.go +++ b/pkg/driver/vz/cmd/lima-driver-vz/main.go @@ -1,3 +1,5 @@ +//go:build (darwin && amd64) || (darwin && arm64) + // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/driver/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go index 6eb7c643c41..fde266237b1 100644 --- a/pkg/driver/vz/vz_driver_darwin.go +++ b/pkg/driver/vz/vz_driver_darwin.go @@ -265,6 +265,9 @@ func (l *LimaVzDriver) GetInfo() driver.Info { info.DriverName = "vz" info.VsockPort = l.VSockPort info.VirtioPort = l.VirtioPort + if l.Instance != nil && l.Instance.Dir != "" { + info.InstanceDir = l.Instance.Dir + } return info } diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index cf744847cfb..160bcf9566a 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -215,12 +215,15 @@ func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { } func (l *LimaWslDriver) GetInfo() driver.Info { - return driver.Info{ - DriverName: "wsl", - CanRunGUI: l.canRunGUI(), - VsockPort: l.VSockPort, - VirtioPort: l.VirtioPort, + var info driver.Info + if l.Instance != nil && l.Instance.Dir != "" { + info.InstanceDir = l.Instance.Dir } + info.DriverName = "wsl" + info.CanRunGUI = l.canRunGUI() + info.VirtioPort = l.VirtioPort + info.VsockPort = l.VSockPort + return info } func (l *LimaWslDriver) Initialize(_ context.Context) error { diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 446d3e97083..59fdcf93874 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -379,7 +379,7 @@ func (a *HostAgent) startRoutinesAndWait(ctx context.Context, errCh <-chan error } stBooting := stBase a.emitEvent(ctx, events.Event{Status: stBooting}) - ctxHA, cancelHA := context.WithCancel(ctx) + ctxHA, cancelHA := context.WithCancelCause(ctx) go func() { stRunning := stBase if haErr := a.startHostAgentRoutines(ctxHA); haErr != nil { @@ -393,7 +393,7 @@ func (a *HostAgent) startRoutinesAndWait(ctx context.Context, errCh <-chan error select { case driverErr := <-errCh: logrus.Infof("Driver stopped due to error: %q", driverErr) - cancelHA() + cancelHA(driverErr) if closeErr := a.close(); closeErr != nil { logrus.WithError(closeErr).Warn("an error during shutting down the host agent") } @@ -401,7 +401,7 @@ func (a *HostAgent) startRoutinesAndWait(ctx context.Context, errCh <-chan error return err case sig := <-a.signalCh: logrus.Infof("Received %s, shutting down the host agent", osutil.SignalName(sig)) - cancelHA() + cancelHA(nil) // no error, just a signal if closeErr := a.close(); closeErr != nil { logrus.WithError(closeErr).Warn("an error during shutting down the host agent") } diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 6cf06423e28..8400c0a32aa 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -4,9 +4,9 @@ package registry import ( + "bufio" "context" "fmt" - "io" "os" "os/exec" "path/filepath" @@ -26,8 +26,7 @@ type ExternalDriver struct { Name string InstanceName string Command *exec.Cmd - Stdin io.WriteCloser - Stdout io.ReadCloser + SocketPath string Client *client.DriverClient // Client is the gRPC client for the external driver Path string ctx context.Context @@ -58,16 +57,10 @@ func (e *ExternalDriver) Start(instName string) error { ctx, cancel := context.WithCancel(context.Background()) cmd := exec.CommandContext(ctx, e.Path) - stdin, err := cmd.StdinPipe() - if err != nil { - cancel() - return fmt.Errorf("failed to create stdin pipe: %w", err) - } - stdout, err := cmd.StdoutPipe() if err != nil { cancel() - return fmt.Errorf("failed to create stdout pipe: %w", err) + return fmt.Errorf("failed to create stdout pipe for external driver: %w", err) } instanceDir, err := store.InstanceDir(e.InstanceName) @@ -94,7 +87,18 @@ func (e *ExternalDriver) Start(instName string) error { time.Sleep(time.Millisecond * 100) - driverClient, err := client.NewDriverClient(stdin, stdout, e.logger) + scanner := bufio.NewScanner(stdout) + var socketPath string + if scanner.Scan() { + socketPath = strings.TrimSpace(scanner.Text()) + } else { + cancel() + cmd.Process.Kill() + return fmt.Errorf("failed to read socket path from driver") + } + e.SocketPath = socketPath + + driverClient, err := client.NewDriverClient(e.SocketPath, e.logger) if err != nil { cancel() cmd.Process.Kill() @@ -102,8 +106,6 @@ func (e *ExternalDriver) Start(instName string) error { } e.Command = cmd - e.Stdin = stdin - e.Stdout = stdout e.Client = driverClient e.ctx = ctx e.cancelFunc = cancel @@ -116,12 +118,10 @@ func (e *ExternalDriver) cleanup() { if e.cancelFunc != nil { e.cancelFunc() } - if e.Stdin != nil { - e.Stdin.Close() - } - if e.Stdout != nil { - e.Stdout.Close() + if err := os.Remove(e.SocketPath); err != nil && !os.IsNotExist(err) { + e.logger.Warnf("Failed to remove socket file: %v", err) } + e.Command = nil e.Client = nil e.ctx = nil diff --git a/pkg/store/filenames/filenames.go b/pkg/store/filenames/filenames.go index eb61560d4b8..0bfec19995e 100644 --- a/pkg/store/filenames/filenames.go +++ b/pkg/store/filenames/filenames.go @@ -60,6 +60,7 @@ const ( HostAgentStdoutLog = "ha.stdout.log" HostAgentStderrLog = "ha.stderr.log" ExternalDriverStderrLog = "driver.stderr.log" + ExternalDriverSock = "driver.sock" VzIdentifier = "vz-identifier" VzEfi = "vz-efi" // efi variable store QemuEfiCodeFD = "qemu-efi-code.fd" // efi code; not always created From cd92ddb351035809f8cad6189ff98cf9bd56fe53 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Thu, 19 Jun 2025 02:47:03 +0530 Subject: [PATCH 41/49] driver(external): resolve GuestAgentConn() issue by proxying via new socket Signed-off-by: Ansuman Sahoo --- .../external/client/grpchijack/hijack.go | 135 ----------- pkg/driver/external/client/methods.go | 15 +- pkg/driver/external/driver.pb.go | 214 +++++++++++------- pkg/driver/external/driver.proto | 8 +- pkg/driver/external/driver_grpc.pb.go | 10 +- pkg/driver/external/server/methods.go | 81 ++----- 6 files changed, 173 insertions(+), 290 deletions(-) delete mode 100644 pkg/driver/external/client/grpchijack/hijack.go diff --git a/pkg/driver/external/client/grpchijack/hijack.go b/pkg/driver/external/client/grpchijack/hijack.go deleted file mode 100644 index b4b003fe5e8..00000000000 --- a/pkg/driver/external/client/grpchijack/hijack.go +++ /dev/null @@ -1,135 +0,0 @@ -// // SPDX-FileCopyrightText: Copyright The Lima Authors -// // SPDX-License-Identifier: Apache-2.0 - -package grpchijack - -// import ( -// "errors" -// "fmt" -// "io" -// "net" -// "sync" -// "time" - -// pb "github.com/lima-vm/lima/pkg/driver/external" -// "google.golang.org/grpc" -// ) - -// type streamConn struct { -// stream pb.Driver_GuestAgentConnClient -// readBuf []byte -// lastBuf []byte -// readMu sync.Mutex -// writeMu sync.Mutex -// closeCh chan struct{} -// closedOnce sync.Once -// closed bool -// } - -// func StreamToConn(stream pb.Driver_GuestAgentConnClient) *streamConn { -// return &streamConn{ -// stream: stream, -// closeCh: make(chan struct{}), -// } -// } - -// func (c *streamConn) Read(b []byte) (int, error) { -// c.readMu.Lock() -// defer c.readMu.Unlock() - -// if c.closed { -// return 0, io.EOF -// } - -// if c.lastBuf != nil { -// n := copy(b, c.lastBuf) -// c.lastBuf = c.lastBuf[n:] -// if len(c.lastBuf) == 0 { -// c.lastBuf = nil -// } -// return n, nil -// } - -// msg := new(pb.NetConn) -// msg, err := c.stream.Recv() -// if err != nil { -// c.closed = true -// if err == io.EOF { -// return 0, io.EOF -// } -// return 0, fmt.Errorf("stream receive error: %w", err) -// } - -// n := copy(b, msg.Data) -// if n < len(msg.Data) { -// c.readBuf = make([]byte, len(msg.Data)-n) -// copy(c.readBuf, msg.Data[n:]) -// } - -// return n, nil -// } - -// func (c *streamConn) Write(b []byte) (int, error) { -// c.writeMu.Lock() -// defer c.writeMu.Unlock() - -// if c.closed { -// return 0, errors.New("connection closed") -// } - -// err := c.stream.Send(&pb.NetConn{Data: b}) -// if err != nil { -// c.closed = true -// return 0, fmt.Errorf("stream send error: %w", err) -// } - -// return len(b), nil -// } - -// func (c *streamConn) Close() error { -// c.closedOnce.Do(func() { -// defer func() { -// close(c.closeCh) -// }() - -// if cs, ok := c.stream.(grpc.ClientStream); ok { -// c.writeMu.Lock() -// err := cs.CloseSend() -// c.writeMu.Unlock() -// if err != nil { -// return -// } -// } - -// c.readMu.Lock() -// for { -// m := new(pb.) -// m.Data = c.readBuf -// err := c.stream.RecvMsg(m) -// if err != nil { -// if !errors.Is(err, io.EOF) { -// c.readMu.Unlock() -// return -// } -// err = nil -// break -// } -// c.readBuf = m.Data[:cap(m.Data)] -// c.lastBuf = append(c.lastBuf, c.readBuf...) -// } -// c.readMu.Unlock() -// }) -// return nil -// } - -// func (c *streamConn) LocalAddr() net.Addr { return &grpcAddr{} } -// func (c *streamConn) RemoteAddr() net.Addr { return &grpcAddr{} } - -// func (c *streamConn) SetDeadline(t time.Time) error { return nil } -// func (c *streamConn) SetReadDeadline(t time.Time) error { return nil } -// func (c *streamConn) SetWriteDeadline(t time.Time) error { return nil } - -// type grpcAddr struct{} - -// func (grpcAddr) Network() string { return "grpc" } -// func (grpcAddr) String() string { return "grpc-stream" } diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index d1c2e009d0f..3be9f4f059b 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -241,23 +241,30 @@ func (d *DriverClient) ForwardGuestAgent() bool { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - _, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{}) + resp, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to check guest agent forwarding: %v", err) return false } - return true + return resp.ShouldForward } func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { d.logger.Info("Getting guest agent connection") - _, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) + resp, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to get guest agent connection: %v", err) return nil, err } - return nil, nil + + var nd net.Dialer + unixConn, err := nd.DialContext(ctx, "unix", resp.SocketPath) + if err != nil { + d.logger.Errorf("Failed to connect to guest agent socket %s: %v", resp.SocketPath, err) + return nil, err + } + return unixConn, nil } func (d *DriverClient) GetInfo() driver.Info { diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index 29719a4a2ec..8330f23523a 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -22,6 +22,50 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type GuestAgentConnResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + SocketPath string `protobuf:"bytes,1,opt,name=socket_path,json=socketPath,proto3" json:"socket_path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GuestAgentConnResponse) Reset() { + *x = GuestAgentConnResponse{} + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GuestAgentConnResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GuestAgentConnResponse) ProtoMessage() {} + +func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GuestAgentConnResponse.ProtoReflect.Descriptor instead. +func (*GuestAgentConnResponse) Descriptor() ([]byte, []int) { + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} +} + +func (x *GuestAgentConnResponse) GetSocketPath() string { + if x != nil { + return x.SocketPath + } + return "" +} + type InfoResponse struct { state protoimpl.MessageState `protogen:"open.v1"` InfoJson []byte `protobuf:"bytes,1,opt,name=info_json,json=infoJson,proto3" json:"info_json,omitempty"` @@ -31,7 +75,7 @@ type InfoResponse struct { func (x *InfoResponse) Reset() { *x = InfoResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[0] + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -43,7 +87,7 @@ func (x *InfoResponse) String() string { func (*InfoResponse) ProtoMessage() {} func (x *InfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[0] + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -56,7 +100,7 @@ func (x *InfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InfoResponse.ProtoReflect.Descriptor instead. func (*InfoResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} } func (x *InfoResponse) GetInfoJson() []byte { @@ -76,7 +120,7 @@ type StartResponse struct { func (x *StartResponse) Reset() { *x = StartResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[1] + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -88,7 +132,7 @@ func (x *StartResponse) String() string { func (*StartResponse) ProtoMessage() {} func (x *StartResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[1] + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -101,7 +145,7 @@ func (x *StartResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. func (*StartResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} } func (x *StartResponse) GetSuccess() bool { @@ -128,7 +172,7 @@ type SetConfigRequest struct { func (x *SetConfigRequest) Reset() { *x = SetConfigRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[2] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -140,7 +184,7 @@ func (x *SetConfigRequest) String() string { func (*SetConfigRequest) ProtoMessage() {} func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[2] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -153,7 +197,7 @@ func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead. func (*SetConfigRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} } func (x *SetConfigRequest) GetInstanceConfigJson() []byte { @@ -179,7 +223,7 @@ type ChangeDisplayPasswordRequest struct { func (x *ChangeDisplayPasswordRequest) Reset() { *x = ChangeDisplayPasswordRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -191,7 +235,7 @@ func (x *ChangeDisplayPasswordRequest) String() string { func (*ChangeDisplayPasswordRequest) ProtoMessage() {} func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -204,7 +248,7 @@ func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayPasswordRequest.ProtoReflect.Descriptor instead. func (*ChangeDisplayPasswordRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} } func (x *ChangeDisplayPasswordRequest) GetPassword() string { @@ -223,7 +267,7 @@ type GetDisplayConnectionResponse struct { func (x *GetDisplayConnectionResponse) Reset() { *x = GetDisplayConnectionResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -235,7 +279,7 @@ func (x *GetDisplayConnectionResponse) String() string { func (*GetDisplayConnectionResponse) ProtoMessage() {} func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -248,7 +292,7 @@ func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDisplayConnectionResponse.ProtoReflect.Descriptor instead. func (*GetDisplayConnectionResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} } func (x *GetDisplayConnectionResponse) GetConnection() string { @@ -267,7 +311,7 @@ type CreateSnapshotRequest struct { func (x *CreateSnapshotRequest) Reset() { *x = CreateSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -279,7 +323,7 @@ func (x *CreateSnapshotRequest) String() string { func (*CreateSnapshotRequest) ProtoMessage() {} func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -292,7 +336,7 @@ func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateSnapshotRequest.ProtoReflect.Descriptor instead. func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} } func (x *CreateSnapshotRequest) GetTag() string { @@ -311,7 +355,7 @@ type ApplySnapshotRequest struct { func (x *ApplySnapshotRequest) Reset() { *x = ApplySnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -323,7 +367,7 @@ func (x *ApplySnapshotRequest) String() string { func (*ApplySnapshotRequest) ProtoMessage() {} func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -336,7 +380,7 @@ func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplySnapshotRequest.ProtoReflect.Descriptor instead. func (*ApplySnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} } func (x *ApplySnapshotRequest) GetTag() string { @@ -355,7 +399,7 @@ type DeleteSnapshotRequest struct { func (x *DeleteSnapshotRequest) Reset() { *x = DeleteSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -367,7 +411,7 @@ func (x *DeleteSnapshotRequest) String() string { func (*DeleteSnapshotRequest) ProtoMessage() {} func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -380,7 +424,7 @@ func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteSnapshotRequest.ProtoReflect.Descriptor instead. func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} } func (x *DeleteSnapshotRequest) GetTag() string { @@ -399,7 +443,7 @@ type ListSnapshotsResponse struct { func (x *ListSnapshotsResponse) Reset() { *x = ListSnapshotsResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -411,7 +455,7 @@ func (x *ListSnapshotsResponse) String() string { func (*ListSnapshotsResponse) ProtoMessage() {} func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -424,7 +468,7 @@ func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSnapshotsResponse.ProtoReflect.Descriptor instead. func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} } func (x *ListSnapshotsResponse) GetSnapshots() string { @@ -443,7 +487,7 @@ type ForwardGuestAgentResponse struct { func (x *ForwardGuestAgentResponse) Reset() { *x = ForwardGuestAgentResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -455,7 +499,7 @@ func (x *ForwardGuestAgentResponse) String() string { func (*ForwardGuestAgentResponse) ProtoMessage() {} func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + mi := &file_pkg_driver_external_driver_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -468,7 +512,7 @@ func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardGuestAgentResponse.ProtoReflect.Descriptor instead. func (*ForwardGuestAgentResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} } func (x *ForwardGuestAgentResponse) GetShouldForward() bool { @@ -482,7 +526,10 @@ var File_pkg_driver_external_driver_proto protoreflect.FileDescriptor const file_pkg_driver_external_driver_proto_rawDesc = "" + "\n" + - " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"+\n" + + " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"9\n" + + "\x16GuestAgentConnResponse\x12\x1f\n" + + "\vsocket_path\x18\x01 \x01(\tR\n" + + "socketPath\"+\n" + "\fInfoResponse\x12\x1b\n" + "\tinfo_json\x18\x01 \x01(\fR\binfoJson\"?\n" + "\rStartResponse\x12\x18\n" + @@ -506,7 +553,7 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\x15ListSnapshotsResponse\x12\x1c\n" + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\"B\n" + "\x19ForwardGuestAgentResponse\x12%\n" + - "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward2\xf8\b\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward2\xf9\b\n" + "\x06Driver\x12:\n" + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + @@ -525,8 +572,8 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + - "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12@\n" + - "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x126\n" + + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12A\n" + + "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse\x126\n" + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x16.google.protobuf.Empty\x120\n" + "\aGetInfo\x12\x16.google.protobuf.Empty\x1a\r.InfoResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" @@ -542,57 +589,58 @@ func file_pkg_driver_external_driver_proto_rawDescGZIP() []byte { return file_pkg_driver_external_driver_proto_rawDescData } -var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_pkg_driver_external_driver_proto_goTypes = []any{ - (*InfoResponse)(nil), // 0: InfoResponse - (*StartResponse)(nil), // 1: StartResponse - (*SetConfigRequest)(nil), // 2: SetConfigRequest - (*ChangeDisplayPasswordRequest)(nil), // 3: ChangeDisplayPasswordRequest - (*GetDisplayConnectionResponse)(nil), // 4: GetDisplayConnectionResponse - (*CreateSnapshotRequest)(nil), // 5: CreateSnapshotRequest - (*ApplySnapshotRequest)(nil), // 6: ApplySnapshotRequest - (*DeleteSnapshotRequest)(nil), // 7: DeleteSnapshotRequest - (*ListSnapshotsResponse)(nil), // 8: ListSnapshotsResponse - (*ForwardGuestAgentResponse)(nil), // 9: ForwardGuestAgentResponse - (*emptypb.Empty)(nil), // 10: google.protobuf.Empty + (*GuestAgentConnResponse)(nil), // 0: GuestAgentConnResponse + (*InfoResponse)(nil), // 1: InfoResponse + (*StartResponse)(nil), // 2: StartResponse + (*SetConfigRequest)(nil), // 3: SetConfigRequest + (*ChangeDisplayPasswordRequest)(nil), // 4: ChangeDisplayPasswordRequest + (*GetDisplayConnectionResponse)(nil), // 5: GetDisplayConnectionResponse + (*CreateSnapshotRequest)(nil), // 6: CreateSnapshotRequest + (*ApplySnapshotRequest)(nil), // 7: ApplySnapshotRequest + (*DeleteSnapshotRequest)(nil), // 8: DeleteSnapshotRequest + (*ListSnapshotsResponse)(nil), // 9: ListSnapshotsResponse + (*ForwardGuestAgentResponse)(nil), // 10: ForwardGuestAgentResponse + (*emptypb.Empty)(nil), // 11: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ - 10, // 0: Driver.Validate:input_type -> google.protobuf.Empty - 10, // 1: Driver.Initialize:input_type -> google.protobuf.Empty - 10, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty - 10, // 3: Driver.Start:input_type -> google.protobuf.Empty - 10, // 4: Driver.Stop:input_type -> google.protobuf.Empty - 10, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty - 3, // 6: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest - 10, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty - 5, // 8: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest - 6, // 9: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest - 7, // 10: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest - 10, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty - 10, // 12: Driver.Register:input_type -> google.protobuf.Empty - 10, // 13: Driver.Unregister:input_type -> google.protobuf.Empty - 10, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 10, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty - 2, // 16: Driver.SetConfig:input_type -> SetConfigRequest - 10, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty - 10, // 18: Driver.Validate:output_type -> google.protobuf.Empty - 10, // 19: Driver.Initialize:output_type -> google.protobuf.Empty - 10, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty - 1, // 21: Driver.Start:output_type -> StartResponse - 10, // 22: Driver.Stop:output_type -> google.protobuf.Empty - 10, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty - 10, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty - 4, // 25: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse - 10, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty - 10, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty - 10, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty - 8, // 29: Driver.ListSnapshots:output_type -> ListSnapshotsResponse - 10, // 30: Driver.Register:output_type -> google.protobuf.Empty - 10, // 31: Driver.Unregister:output_type -> google.protobuf.Empty - 9, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 10, // 33: Driver.GuestAgentConn:output_type -> google.protobuf.Empty - 10, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty - 0, // 35: Driver.GetInfo:output_type -> InfoResponse + 11, // 0: Driver.Validate:input_type -> google.protobuf.Empty + 11, // 1: Driver.Initialize:input_type -> google.protobuf.Empty + 11, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty + 11, // 3: Driver.Start:input_type -> google.protobuf.Empty + 11, // 4: Driver.Stop:input_type -> google.protobuf.Empty + 11, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty + 4, // 6: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest + 11, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty + 6, // 8: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest + 7, // 9: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest + 8, // 10: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest + 11, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty + 11, // 12: Driver.Register:input_type -> google.protobuf.Empty + 11, // 13: Driver.Unregister:input_type -> google.protobuf.Empty + 11, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty + 11, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty + 3, // 16: Driver.SetConfig:input_type -> SetConfigRequest + 11, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty + 11, // 18: Driver.Validate:output_type -> google.protobuf.Empty + 11, // 19: Driver.Initialize:output_type -> google.protobuf.Empty + 11, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty + 2, // 21: Driver.Start:output_type -> StartResponse + 11, // 22: Driver.Stop:output_type -> google.protobuf.Empty + 11, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty + 11, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty + 5, // 25: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse + 11, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty + 11, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty + 11, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty + 9, // 29: Driver.ListSnapshots:output_type -> ListSnapshotsResponse + 11, // 30: Driver.Register:output_type -> google.protobuf.Empty + 11, // 31: Driver.Unregister:output_type -> google.protobuf.Empty + 10, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse + 0, // 33: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse + 11, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty + 1, // 35: Driver.GetInfo:output_type -> InfoResponse 18, // [18:36] is the sub-list for method output_type 0, // [0:18] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -611,7 +659,7 @@ func file_pkg_driver_external_driver_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc)), NumEnums: 0, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index db93410562e..5e8e8564193 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -24,16 +24,16 @@ service Driver { rpc Unregister(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); - rpc GuestAgentConn(google.protobuf.Empty) returns (google.protobuf.Empty); + rpc GuestAgentConn(google.protobuf.Empty) returns (GuestAgentConnResponse); rpc SetConfig(SetConfigRequest) returns (google.protobuf.Empty); rpc GetInfo(google.protobuf.Empty) returns (InfoResponse); } -// message NetConn { -// bytes data = 1; -// } +message GuestAgentConnResponse { + string socket_path = 1; +} message InfoResponse{ bytes info_json = 1; diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index 5e1dcde983c..4662a507045 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -59,7 +59,7 @@ type DriverClient interface { Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) - GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GuestAgentConnResponse, error) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) } @@ -231,9 +231,9 @@ func (c *driverClient) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, return out, nil } -func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { +func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GuestAgentConnResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(emptypb.Empty) + out := new(GuestAgentConnResponse) err := c.cc.Invoke(ctx, Driver_GuestAgentConn_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -280,7 +280,7 @@ type DriverServer interface { Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) - GuestAgentConn(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + GuestAgentConn(context.Context, *emptypb.Empty) (*GuestAgentConnResponse, error) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) mustEmbedUnimplementedDriverServer() @@ -338,7 +338,7 @@ func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*e func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ForwardGuestAgent not implemented") } -func (UnimplementedDriverServer) GuestAgentConn(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { +func (UnimplementedDriverServer) GuestAgentConn(context.Context, *emptypb.Empty) (*GuestAgentConnResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") } func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) { diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 5eef59be394..20ac27af23e 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "net" + "os" "path/filepath" "google.golang.org/grpc/codes" @@ -19,7 +20,6 @@ import ( pb "github.com/lima-vm/lima/pkg/driver/external" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" - "github.com/sirupsen/logrus" ) func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) error { @@ -69,75 +69,38 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) return &emptypb.Empty{}, nil } -func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { +func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) (*pb.GuestAgentConnResponse, error) { s.logger.Debug("Received GuestAgentConn request") conn, err := s.driver.GuestAgentConn(ctx) if err != nil { s.logger.Errorf("GuestAgentConn failed: %v", err) - return &emptypb.Empty{}, status.Errorf(codes.Internal, "failed to establish guest agent connection: %v", err) + return nil, err } - unixSocketPath := filepath.Join(s.driver.GetInfo().InstanceDir, filenames.GuestAgentSock) - var d net.Dialer - unixConn, err := d.DialContext(ctx, "unix", unixSocketPath) + proxySocketPath := filepath.Join(s.driver.GetInfo().InstanceDir, filenames.ExternalDriverSock) + os.Remove(proxySocketPath) + + listener, err := net.Listen("unix", proxySocketPath) if err != nil { - logrus.Errorf("Failed to connect to unix socket %s: %v", unixSocketPath, err) - return nil, status.Errorf(codes.Internal, "failed to connect to unix socket %s: %v", unixSocketPath, err) + s.logger.Errorf("Failed to create proxy socket: %v", err) + return nil, err } - go bicopy.Bicopy(conn, unixConn, nil) + go func() { + defer listener.Close() + defer conn.Close() - s.logger.Debug("GuestAgentConn succeeded, connection handled") - return &emptypb.Empty{}, nil -} + proxyConn, err := listener.Accept() + if err != nil { + s.logger.Errorf("Failed to accept proxy connection: %v", err) + return + } -// func (s *DriverServer) GuestAgentConn(stream pb.Driver_GuestAgentConnServer) error { -// s.logger.Debug("Received GuestAgentConn request") -// conn, err := s.driver.GuestAgentConn(stream.Context()) -// if err != nil { -// s.logger.Errorf("GuestAgentConn failed: %v", err) -// return err -// } - -// s.logger.Debug("GuestAgentConn succeeded") - -// go func() { -// for { -// msg, err := stream.Recv() -// if err != nil { -// return -// } -// s.logger.Debugf("Received message from stream: %d bytes", len(msg.Data)) -// if len(msg.Data) > 0 { -// _, err = conn.Write(msg.Data) -// if err != nil { -// s.logger.Errorf("Error writing to connection: %v", err) -// conn.Close() -// return -// } -// } -// } -// }() - -// buf := make([]byte, 32*1<<10) -// for { -// n, err := conn.Read(buf) -// if err != nil { -// if errors.Is(err, io.EOF) { -// s.logger.Debugf("Connection closed by guest agent %v", err) -// return nil -// } -// return status.Errorf(codes.Internal, "error reading: %v", err) -// } -// s.logger.Debugf("Sending %d bytes to stream", n) - -// msg := &pb.NetConn{Data: buf[:n]} -// if err := stream.Send(msg); err != nil { -// s.logger.Errorf("Failed to send message to stream: %v", err) -// return err -// } -// } -// } + bicopy.Bicopy(conn, proxyConn, nil) + }() + + return &pb.GuestAgentConnResponse{SocketPath: proxySocketPath}, nil +} func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { s.logger.Debug("Received GetInfo request") From b690b219dd3579022780680b08e3941377435397 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Thu, 19 Jun 2025 23:05:10 +0530 Subject: [PATCH 42/49] driver(external): move proxy conn code to driver level Signed-off-by: Ansuman Sahoo --- pkg/driver/driver.go | 7 + pkg/driver/external/client/methods.go | 12 +- pkg/driver/external/driver.pb.go | 214 +++++++------------ pkg/driver/external/driver.proto | 6 +- pkg/driver/external/driver_grpc.pb.go | 10 +- pkg/driver/external/server/methods.go | 33 +-- pkg/driver/qemu/cmd/lima-driver-qemu/main.go | 4 +- pkg/driver/qemu/qemu_driver.go | 5 +- pkg/driver/qemu/register.go | 7 +- pkg/driver/vz/cmd/lima-driver-vz/main.go | 3 +- pkg/driver/vz/register.go | 7 +- pkg/driver/vz/vz_driver_darwin.go | 30 ++- pkg/driver/wsl2/cmd/lima-driver-wsl/main.go | 18 ++ pkg/driver/wsl2/register.go | 7 +- pkg/driver/wsl2/wsl_driver_windows.go | 37 +++- 15 files changed, 207 insertions(+), 193 deletions(-) create mode 100644 pkg/driver/wsl2/cmd/lima-driver-wsl/main.go diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 8a91ad721a4..cf6c8bd898f 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -90,3 +90,10 @@ type Info struct { VirtioPort string `json:"virtioPort"` InstanceDir string `json:"instanceDir,omitempty"` } + +type DriverType = string + +const ( + DriverTypeInternal DriverType = "internal" + DriverTypeExternal DriverType = "external" +) diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 3be9f4f059b..527d68aafea 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -10,8 +10,6 @@ import ( "net" "time" - // "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" "github.com/lima-vm/lima/pkg/driver" @@ -252,19 +250,13 @@ func (d *DriverClient) ForwardGuestAgent() bool { func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { d.logger.Info("Getting guest agent connection") - resp, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) + _, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to get guest agent connection: %v", err) return nil, err } - var nd net.Dialer - unixConn, err := nd.DialContext(ctx, "unix", resp.SocketPath) - if err != nil { - d.logger.Errorf("Failed to connect to guest agent socket %s: %v", resp.SocketPath, err) - return nil, err - } - return unixConn, nil + return nil, nil } func (d *DriverClient) GetInfo() driver.Info { diff --git a/pkg/driver/external/driver.pb.go b/pkg/driver/external/driver.pb.go index 8330f23523a..29719a4a2ec 100644 --- a/pkg/driver/external/driver.pb.go +++ b/pkg/driver/external/driver.pb.go @@ -22,50 +22,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type GuestAgentConnResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - SocketPath string `protobuf:"bytes,1,opt,name=socket_path,json=socketPath,proto3" json:"socket_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GuestAgentConnResponse) Reset() { - *x = GuestAgentConnResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GuestAgentConnResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GuestAgentConnResponse) ProtoMessage() {} - -func (x *GuestAgentConnResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GuestAgentConnResponse.ProtoReflect.Descriptor instead. -func (*GuestAgentConnResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} -} - -func (x *GuestAgentConnResponse) GetSocketPath() string { - if x != nil { - return x.SocketPath - } - return "" -} - type InfoResponse struct { state protoimpl.MessageState `protogen:"open.v1"` InfoJson []byte `protobuf:"bytes,1,opt,name=info_json,json=infoJson,proto3" json:"info_json,omitempty"` @@ -75,7 +31,7 @@ type InfoResponse struct { func (x *InfoResponse) Reset() { *x = InfoResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[1] + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -87,7 +43,7 @@ func (x *InfoResponse) String() string { func (*InfoResponse) ProtoMessage() {} func (x *InfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[1] + mi := &file_pkg_driver_external_driver_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -100,7 +56,7 @@ func (x *InfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InfoResponse.ProtoReflect.Descriptor instead. func (*InfoResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{0} } func (x *InfoResponse) GetInfoJson() []byte { @@ -120,7 +76,7 @@ type StartResponse struct { func (x *StartResponse) Reset() { *x = StartResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[2] + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -132,7 +88,7 @@ func (x *StartResponse) String() string { func (*StartResponse) ProtoMessage() {} func (x *StartResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[2] + mi := &file_pkg_driver_external_driver_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -145,7 +101,7 @@ func (x *StartResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. func (*StartResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{1} } func (x *StartResponse) GetSuccess() bool { @@ -172,7 +128,7 @@ type SetConfigRequest struct { func (x *SetConfigRequest) Reset() { *x = SetConfigRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -184,7 +140,7 @@ func (x *SetConfigRequest) String() string { func (*SetConfigRequest) ProtoMessage() {} func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[3] + mi := &file_pkg_driver_external_driver_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -197,7 +153,7 @@ func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead. func (*SetConfigRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{2} } func (x *SetConfigRequest) GetInstanceConfigJson() []byte { @@ -223,7 +179,7 @@ type ChangeDisplayPasswordRequest struct { func (x *ChangeDisplayPasswordRequest) Reset() { *x = ChangeDisplayPasswordRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -235,7 +191,7 @@ func (x *ChangeDisplayPasswordRequest) String() string { func (*ChangeDisplayPasswordRequest) ProtoMessage() {} func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[4] + mi := &file_pkg_driver_external_driver_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -248,7 +204,7 @@ func (x *ChangeDisplayPasswordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayPasswordRequest.ProtoReflect.Descriptor instead. func (*ChangeDisplayPasswordRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{3} } func (x *ChangeDisplayPasswordRequest) GetPassword() string { @@ -267,7 +223,7 @@ type GetDisplayConnectionResponse struct { func (x *GetDisplayConnectionResponse) Reset() { *x = GetDisplayConnectionResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -279,7 +235,7 @@ func (x *GetDisplayConnectionResponse) String() string { func (*GetDisplayConnectionResponse) ProtoMessage() {} func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[5] + mi := &file_pkg_driver_external_driver_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -292,7 +248,7 @@ func (x *GetDisplayConnectionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDisplayConnectionResponse.ProtoReflect.Descriptor instead. func (*GetDisplayConnectionResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{4} } func (x *GetDisplayConnectionResponse) GetConnection() string { @@ -311,7 +267,7 @@ type CreateSnapshotRequest struct { func (x *CreateSnapshotRequest) Reset() { *x = CreateSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -323,7 +279,7 @@ func (x *CreateSnapshotRequest) String() string { func (*CreateSnapshotRequest) ProtoMessage() {} func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[6] + mi := &file_pkg_driver_external_driver_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -336,7 +292,7 @@ func (x *CreateSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateSnapshotRequest.ProtoReflect.Descriptor instead. func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{5} } func (x *CreateSnapshotRequest) GetTag() string { @@ -355,7 +311,7 @@ type ApplySnapshotRequest struct { func (x *ApplySnapshotRequest) Reset() { *x = ApplySnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -367,7 +323,7 @@ func (x *ApplySnapshotRequest) String() string { func (*ApplySnapshotRequest) ProtoMessage() {} func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[7] + mi := &file_pkg_driver_external_driver_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -380,7 +336,7 @@ func (x *ApplySnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplySnapshotRequest.ProtoReflect.Descriptor instead. func (*ApplySnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{6} } func (x *ApplySnapshotRequest) GetTag() string { @@ -399,7 +355,7 @@ type DeleteSnapshotRequest struct { func (x *DeleteSnapshotRequest) Reset() { *x = DeleteSnapshotRequest{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -411,7 +367,7 @@ func (x *DeleteSnapshotRequest) String() string { func (*DeleteSnapshotRequest) ProtoMessage() {} func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[8] + mi := &file_pkg_driver_external_driver_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -424,7 +380,7 @@ func (x *DeleteSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteSnapshotRequest.ProtoReflect.Descriptor instead. func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{7} } func (x *DeleteSnapshotRequest) GetTag() string { @@ -443,7 +399,7 @@ type ListSnapshotsResponse struct { func (x *ListSnapshotsResponse) Reset() { *x = ListSnapshotsResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -455,7 +411,7 @@ func (x *ListSnapshotsResponse) String() string { func (*ListSnapshotsResponse) ProtoMessage() {} func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[9] + mi := &file_pkg_driver_external_driver_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -468,7 +424,7 @@ func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSnapshotsResponse.ProtoReflect.Descriptor instead. func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{8} } func (x *ListSnapshotsResponse) GetSnapshots() string { @@ -487,7 +443,7 @@ type ForwardGuestAgentResponse struct { func (x *ForwardGuestAgentResponse) Reset() { *x = ForwardGuestAgentResponse{} - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -499,7 +455,7 @@ func (x *ForwardGuestAgentResponse) String() string { func (*ForwardGuestAgentResponse) ProtoMessage() {} func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_driver_external_driver_proto_msgTypes[10] + mi := &file_pkg_driver_external_driver_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -512,7 +468,7 @@ func (x *ForwardGuestAgentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardGuestAgentResponse.ProtoReflect.Descriptor instead. func (*ForwardGuestAgentResponse) Descriptor() ([]byte, []int) { - return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{10} + return file_pkg_driver_external_driver_proto_rawDescGZIP(), []int{9} } func (x *ForwardGuestAgentResponse) GetShouldForward() bool { @@ -526,10 +482,7 @@ var File_pkg_driver_external_driver_proto protoreflect.FileDescriptor const file_pkg_driver_external_driver_proto_rawDesc = "" + "\n" + - " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"9\n" + - "\x16GuestAgentConnResponse\x12\x1f\n" + - "\vsocket_path\x18\x01 \x01(\tR\n" + - "socketPath\"+\n" + + " pkg/driver/external/driver.proto\x1a\x1bgoogle/protobuf/empty.proto\"+\n" + "\fInfoResponse\x12\x1b\n" + "\tinfo_json\x18\x01 \x01(\fR\binfoJson\"?\n" + "\rStartResponse\x12\x18\n" + @@ -553,7 +506,7 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\x15ListSnapshotsResponse\x12\x1c\n" + "\tsnapshots\x18\x01 \x01(\tR\tsnapshots\"B\n" + "\x19ForwardGuestAgentResponse\x12%\n" + - "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward2\xf9\b\n" + + "\x0eshould_forward\x18\x01 \x01(\bR\rshouldForward2\xf8\b\n" + "\x06Driver\x12:\n" + "\bValidate\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + @@ -572,8 +525,8 @@ const file_pkg_driver_external_driver_proto_rawDesc = "" + "\bRegister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12<\n" + "\n" + "Unregister\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12G\n" + - "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12A\n" + - "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x17.GuestAgentConnResponse\x126\n" + + "\x11ForwardGuestAgent\x12\x16.google.protobuf.Empty\x1a\x1a.ForwardGuestAgentResponse\x12@\n" + + "\x0eGuestAgentConn\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x126\n" + "\tSetConfig\x12\x11.SetConfigRequest\x1a\x16.google.protobuf.Empty\x120\n" + "\aGetInfo\x12\x16.google.protobuf.Empty\x1a\r.InfoResponseB-Z+github.com/lima-vm/lima/pkg/driver/externalb\x06proto3" @@ -589,58 +542,57 @@ func file_pkg_driver_external_driver_proto_rawDescGZIP() []byte { return file_pkg_driver_external_driver_proto_rawDescData } -var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_pkg_driver_external_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_pkg_driver_external_driver_proto_goTypes = []any{ - (*GuestAgentConnResponse)(nil), // 0: GuestAgentConnResponse - (*InfoResponse)(nil), // 1: InfoResponse - (*StartResponse)(nil), // 2: StartResponse - (*SetConfigRequest)(nil), // 3: SetConfigRequest - (*ChangeDisplayPasswordRequest)(nil), // 4: ChangeDisplayPasswordRequest - (*GetDisplayConnectionResponse)(nil), // 5: GetDisplayConnectionResponse - (*CreateSnapshotRequest)(nil), // 6: CreateSnapshotRequest - (*ApplySnapshotRequest)(nil), // 7: ApplySnapshotRequest - (*DeleteSnapshotRequest)(nil), // 8: DeleteSnapshotRequest - (*ListSnapshotsResponse)(nil), // 9: ListSnapshotsResponse - (*ForwardGuestAgentResponse)(nil), // 10: ForwardGuestAgentResponse - (*emptypb.Empty)(nil), // 11: google.protobuf.Empty + (*InfoResponse)(nil), // 0: InfoResponse + (*StartResponse)(nil), // 1: StartResponse + (*SetConfigRequest)(nil), // 2: SetConfigRequest + (*ChangeDisplayPasswordRequest)(nil), // 3: ChangeDisplayPasswordRequest + (*GetDisplayConnectionResponse)(nil), // 4: GetDisplayConnectionResponse + (*CreateSnapshotRequest)(nil), // 5: CreateSnapshotRequest + (*ApplySnapshotRequest)(nil), // 6: ApplySnapshotRequest + (*DeleteSnapshotRequest)(nil), // 7: DeleteSnapshotRequest + (*ListSnapshotsResponse)(nil), // 8: ListSnapshotsResponse + (*ForwardGuestAgentResponse)(nil), // 9: ForwardGuestAgentResponse + (*emptypb.Empty)(nil), // 10: google.protobuf.Empty } var file_pkg_driver_external_driver_proto_depIdxs = []int32{ - 11, // 0: Driver.Validate:input_type -> google.protobuf.Empty - 11, // 1: Driver.Initialize:input_type -> google.protobuf.Empty - 11, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty - 11, // 3: Driver.Start:input_type -> google.protobuf.Empty - 11, // 4: Driver.Stop:input_type -> google.protobuf.Empty - 11, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty - 4, // 6: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest - 11, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty - 6, // 8: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest - 7, // 9: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest - 8, // 10: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest - 11, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty - 11, // 12: Driver.Register:input_type -> google.protobuf.Empty - 11, // 13: Driver.Unregister:input_type -> google.protobuf.Empty - 11, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty - 11, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty - 3, // 16: Driver.SetConfig:input_type -> SetConfigRequest - 11, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty - 11, // 18: Driver.Validate:output_type -> google.protobuf.Empty - 11, // 19: Driver.Initialize:output_type -> google.protobuf.Empty - 11, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty - 2, // 21: Driver.Start:output_type -> StartResponse - 11, // 22: Driver.Stop:output_type -> google.protobuf.Empty - 11, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty - 11, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty - 5, // 25: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse - 11, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty - 11, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty - 11, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty - 9, // 29: Driver.ListSnapshots:output_type -> ListSnapshotsResponse - 11, // 30: Driver.Register:output_type -> google.protobuf.Empty - 11, // 31: Driver.Unregister:output_type -> google.protobuf.Empty - 10, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse - 0, // 33: Driver.GuestAgentConn:output_type -> GuestAgentConnResponse - 11, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty - 1, // 35: Driver.GetInfo:output_type -> InfoResponse + 10, // 0: Driver.Validate:input_type -> google.protobuf.Empty + 10, // 1: Driver.Initialize:input_type -> google.protobuf.Empty + 10, // 2: Driver.CreateDisk:input_type -> google.protobuf.Empty + 10, // 3: Driver.Start:input_type -> google.protobuf.Empty + 10, // 4: Driver.Stop:input_type -> google.protobuf.Empty + 10, // 5: Driver.RunGUI:input_type -> google.protobuf.Empty + 3, // 6: Driver.ChangeDisplayPassword:input_type -> ChangeDisplayPasswordRequest + 10, // 7: Driver.GetDisplayConnection:input_type -> google.protobuf.Empty + 5, // 8: Driver.CreateSnapshot:input_type -> CreateSnapshotRequest + 6, // 9: Driver.ApplySnapshot:input_type -> ApplySnapshotRequest + 7, // 10: Driver.DeleteSnapshot:input_type -> DeleteSnapshotRequest + 10, // 11: Driver.ListSnapshots:input_type -> google.protobuf.Empty + 10, // 12: Driver.Register:input_type -> google.protobuf.Empty + 10, // 13: Driver.Unregister:input_type -> google.protobuf.Empty + 10, // 14: Driver.ForwardGuestAgent:input_type -> google.protobuf.Empty + 10, // 15: Driver.GuestAgentConn:input_type -> google.protobuf.Empty + 2, // 16: Driver.SetConfig:input_type -> SetConfigRequest + 10, // 17: Driver.GetInfo:input_type -> google.protobuf.Empty + 10, // 18: Driver.Validate:output_type -> google.protobuf.Empty + 10, // 19: Driver.Initialize:output_type -> google.protobuf.Empty + 10, // 20: Driver.CreateDisk:output_type -> google.protobuf.Empty + 1, // 21: Driver.Start:output_type -> StartResponse + 10, // 22: Driver.Stop:output_type -> google.protobuf.Empty + 10, // 23: Driver.RunGUI:output_type -> google.protobuf.Empty + 10, // 24: Driver.ChangeDisplayPassword:output_type -> google.protobuf.Empty + 4, // 25: Driver.GetDisplayConnection:output_type -> GetDisplayConnectionResponse + 10, // 26: Driver.CreateSnapshot:output_type -> google.protobuf.Empty + 10, // 27: Driver.ApplySnapshot:output_type -> google.protobuf.Empty + 10, // 28: Driver.DeleteSnapshot:output_type -> google.protobuf.Empty + 8, // 29: Driver.ListSnapshots:output_type -> ListSnapshotsResponse + 10, // 30: Driver.Register:output_type -> google.protobuf.Empty + 10, // 31: Driver.Unregister:output_type -> google.protobuf.Empty + 9, // 32: Driver.ForwardGuestAgent:output_type -> ForwardGuestAgentResponse + 10, // 33: Driver.GuestAgentConn:output_type -> google.protobuf.Empty + 10, // 34: Driver.SetConfig:output_type -> google.protobuf.Empty + 0, // 35: Driver.GetInfo:output_type -> InfoResponse 18, // [18:36] is the sub-list for method output_type 0, // [0:18] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -659,7 +611,7 @@ func file_pkg_driver_external_driver_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_pkg_driver_external_driver_proto_rawDesc), len(file_pkg_driver_external_driver_proto_rawDesc)), NumEnums: 0, - NumMessages: 11, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/driver/external/driver.proto b/pkg/driver/external/driver.proto index 5e8e8564193..82c77feec64 100644 --- a/pkg/driver/external/driver.proto +++ b/pkg/driver/external/driver.proto @@ -24,17 +24,13 @@ service Driver { rpc Unregister(google.protobuf.Empty) returns (google.protobuf.Empty); rpc ForwardGuestAgent(google.protobuf.Empty) returns (ForwardGuestAgentResponse); - rpc GuestAgentConn(google.protobuf.Empty) returns (GuestAgentConnResponse); + rpc GuestAgentConn(google.protobuf.Empty) returns (google.protobuf.Empty); rpc SetConfig(SetConfigRequest) returns (google.protobuf.Empty); rpc GetInfo(google.protobuf.Empty) returns (InfoResponse); } -message GuestAgentConnResponse { - string socket_path = 1; -} - message InfoResponse{ bytes info_json = 1; } diff --git a/pkg/driver/external/driver_grpc.pb.go b/pkg/driver/external/driver_grpc.pb.go index 4662a507045..5e1dcde983c 100644 --- a/pkg/driver/external/driver_grpc.pb.go +++ b/pkg/driver/external/driver_grpc.pb.go @@ -59,7 +59,7 @@ type DriverClient interface { Register(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Unregister(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ForwardGuestAgentResponse, error) - GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GuestAgentConnResponse, error) + GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) GetInfo(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*InfoResponse, error) } @@ -231,9 +231,9 @@ func (c *driverClient) ForwardGuestAgent(ctx context.Context, in *emptypb.Empty, return out, nil } -func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GuestAgentConnResponse, error) { +func (c *driverClient) GuestAgentConn(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GuestAgentConnResponse) + out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Driver_GuestAgentConn_FullMethodName, in, out, cOpts...) if err != nil { return nil, err @@ -280,7 +280,7 @@ type DriverServer interface { Register(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Unregister(context.Context, *emptypb.Empty) (*emptypb.Empty, error) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) - GuestAgentConn(context.Context, *emptypb.Empty) (*GuestAgentConnResponse, error) + GuestAgentConn(context.Context, *emptypb.Empty) (*emptypb.Empty, error) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) GetInfo(context.Context, *emptypb.Empty) (*InfoResponse, error) mustEmbedUnimplementedDriverServer() @@ -338,7 +338,7 @@ func (UnimplementedDriverServer) Unregister(context.Context, *emptypb.Empty) (*e func (UnimplementedDriverServer) ForwardGuestAgent(context.Context, *emptypb.Empty) (*ForwardGuestAgentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ForwardGuestAgent not implemented") } -func (UnimplementedDriverServer) GuestAgentConn(context.Context, *emptypb.Empty) (*GuestAgentConnResponse, error) { +func (UnimplementedDriverServer) GuestAgentConn(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method GuestAgentConn not implemented") } func (UnimplementedDriverServer) SetConfig(context.Context, *SetConfigRequest) (*emptypb.Empty, error) { diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 20ac27af23e..57a3d2233b6 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -6,9 +6,6 @@ package server import ( "context" "encoding/json" - "net" - "os" - "path/filepath" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -16,10 +13,8 @@ import ( // "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" - "github.com/lima-vm/lima/pkg/bicopy" pb "github.com/lima-vm/lima/pkg/driver/external" "github.com/lima-vm/lima/pkg/store" - "github.com/lima-vm/lima/pkg/store/filenames" ) func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) error { @@ -69,37 +64,15 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) return &emptypb.Empty{}, nil } -func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) (*pb.GuestAgentConnResponse, error) { +func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { s.logger.Debug("Received GuestAgentConn request") - conn, err := s.driver.GuestAgentConn(ctx) + _, err := s.driver.GuestAgentConn(ctx) if err != nil { s.logger.Errorf("GuestAgentConn failed: %v", err) return nil, err } - proxySocketPath := filepath.Join(s.driver.GetInfo().InstanceDir, filenames.ExternalDriverSock) - os.Remove(proxySocketPath) - - listener, err := net.Listen("unix", proxySocketPath) - if err != nil { - s.logger.Errorf("Failed to create proxy socket: %v", err) - return nil, err - } - - go func() { - defer listener.Close() - defer conn.Close() - - proxyConn, err := listener.Accept() - if err != nil { - s.logger.Errorf("Failed to accept proxy connection: %v", err) - return - } - - bicopy.Bicopy(conn, proxyConn, nil) - }() - - return &pb.GuestAgentConnResponse{SocketPath: proxySocketPath}, nil + return &emptypb.Empty{}, nil } func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { diff --git a/pkg/driver/qemu/cmd/lima-driver-qemu/main.go b/pkg/driver/qemu/cmd/lima-driver-qemu/main.go index 1d78c86e072..19e6e8df798 100644 --- a/pkg/driver/qemu/cmd/lima-driver-qemu/main.go +++ b/pkg/driver/qemu/cmd/lima-driver-qemu/main.go @@ -4,12 +4,14 @@ package main import ( + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/driver/external/server" "github.com/lima-vm/lima/pkg/driver/qemu" ) // To be used as an external driver for Lima. func main() { - driver := qemu.New() + driver := qemu.New(driver.DriverTypeExternal) server.Serve(driver) } diff --git a/pkg/driver/qemu/qemu_driver.go b/pkg/driver/qemu/qemu_driver.go index 8ed74654acc..a04e8de7ba2 100644 --- a/pkg/driver/qemu/qemu_driver.go +++ b/pkg/driver/qemu/qemu_driver.go @@ -42,6 +42,8 @@ type LimaQemuDriver struct { VSockPort int VirtioPort string + DriverType driver.DriverType + qCmd *exec.Cmd qWaitCh chan error @@ -50,7 +52,7 @@ type LimaQemuDriver struct { var _ driver.Driver = (*LimaQemuDriver)(nil) -func New() *LimaQemuDriver { +func New(driverType driver.DriverType) *LimaQemuDriver { // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 // but on Windows default Unix socket forwarding is not available var virtioPort string @@ -61,6 +63,7 @@ func New() *LimaQemuDriver { return &LimaQemuDriver{ VSockPort: 0, VirtioPort: virtioPort, + DriverType: driverType, } } diff --git a/pkg/driver/qemu/register.go b/pkg/driver/qemu/register.go index 58558d4198a..bede04cfc94 100644 --- a/pkg/driver/qemu/register.go +++ b/pkg/driver/qemu/register.go @@ -3,8 +3,11 @@ package qemu -import "github.com/lima-vm/lima/pkg/registry" +import ( + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/registry" +) func init() { - registry.Register(New()) + registry.Register(New(driver.DriverTypeInternal)) } diff --git a/pkg/driver/vz/cmd/lima-driver-vz/main.go b/pkg/driver/vz/cmd/lima-driver-vz/main.go index 267df019d6b..332dbb4c055 100644 --- a/pkg/driver/vz/cmd/lima-driver-vz/main.go +++ b/pkg/driver/vz/cmd/lima-driver-vz/main.go @@ -6,12 +6,13 @@ package main import ( + "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/server" "github.com/lima-vm/lima/pkg/driver/vz" ) // To be used as an external driver for Lima. func main() { - driver := vz.New() + driver := vz.New(driver.DriverTypeExternal) server.Serve(driver) } diff --git a/pkg/driver/vz/register.go b/pkg/driver/vz/register.go index 750be4b37c2..959d21599ae 100644 --- a/pkg/driver/vz/register.go +++ b/pkg/driver/vz/register.go @@ -5,8 +5,11 @@ package vz -import "github.com/lima-vm/lima/pkg/registry" +import ( + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/registry" +) func init() { - registry.Register(New()) + registry.Register(New(driver.DriverTypeInternal)) } diff --git a/pkg/driver/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go index fde266237b1..349e01d3612 100644 --- a/pkg/driver/vz/vz_driver_darwin.go +++ b/pkg/driver/vz/vz_driver_darwin.go @@ -18,11 +18,13 @@ import ( "github.com/coreos/go-semver/semver" "github.com/sirupsen/logrus" + "github.com/lima-vm/lima/pkg/bicopy" "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/reflectutil" "github.com/lima-vm/lima/pkg/store" + "github.com/lima-vm/lima/pkg/store/filenames" ) var knownYamlProperties = []string{ @@ -75,15 +77,18 @@ type LimaVzDriver struct { VSockPort int VirtioPort string + DriverType driver.DriverType + machine *virtualMachineWrapper } var _ driver.Driver = (*LimaVzDriver)(nil) -func New() *LimaVzDriver { +func New(driverType driver.DriverType) *LimaVzDriver { return &LimaVzDriver{ VSockPort: 2222, VirtioPort: "", + DriverType: driverType, } } @@ -250,9 +255,32 @@ func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { for _, socket := range l.machine.SocketDevices() { connect, err := socket.Connect(uint32(l.VSockPort)) if err == nil && connect.SourcePort() != 0 { + if l.DriverType == driver.DriverTypeExternal { + proxySocketPath := filepath.Join(l.GetInfo().InstanceDir, filenames.GuestAgentSock) + + listener, err := net.Listen("unix", proxySocketPath) + if err != nil { + logrus.Errorf("Failed to create proxy socket: %v", err) + return nil, err + } + + go func() { + defer listener.Close() + defer connect.Close() + + proxyConn, err := listener.Accept() + if err != nil { + logrus.Errorf("Failed to accept proxy connection: %v", err) + return + } + + bicopy.Bicopy(connect, proxyConn, nil) + }() + } return connect, nil } } + return nil, errors.New("unable to connect to guest agent via vsock port 2222") } diff --git a/pkg/driver/wsl2/cmd/lima-driver-wsl/main.go b/pkg/driver/wsl2/cmd/lima-driver-wsl/main.go new file mode 100644 index 00000000000..2d125772d83 --- /dev/null +++ b/pkg/driver/wsl2/cmd/lima-driver-wsl/main.go @@ -0,0 +1,18 @@ +//go:build windows && !no_wsl + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/driver/external/server" + "github.com/lima-vm/lima/pkg/driver/wsl2" +) + +// To be used as an external driver for Lima. +func main() { + driver := wsl2.New(driver.DriverTypeExternal) + server.Serve(driver) +} diff --git a/pkg/driver/wsl2/register.go b/pkg/driver/wsl2/register.go index ccbc516d75e..75f977e10be 100644 --- a/pkg/driver/wsl2/register.go +++ b/pkg/driver/wsl2/register.go @@ -5,8 +5,11 @@ package wsl2 -import "github.com/lima-vm/lima/pkg/registry" +import ( + "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/registry" +) func init() { - registry.Register(New()) + registry.Register(New(driver.DriverTypeInternal)) } diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index 160bcf9566a..d612332ed6f 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -7,17 +7,20 @@ import ( "context" "fmt" "net" + "path/filepath" "regexp" "github.com/Microsoft/go-winio" "github.com/Microsoft/go-winio/pkg/guid" "github.com/sirupsen/logrus" + "github.com/lima-vm/lima/pkg/bicopy" "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/freeport" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/reflectutil" "github.com/lima-vm/lima/pkg/store" + "github.com/lima-vm/lima/pkg/store/filenames" "github.com/lima-vm/lima/pkg/windows" ) @@ -52,11 +55,13 @@ type LimaWslDriver struct { SSHLocalPort int VSockPort int VirtioPort string + + DriverType driver.DriverType } var _ driver.Driver = (*LimaWslDriver)(nil) -func New() *LimaWslDriver { +func New(driverType driver.DriverType) *LimaWslDriver { port, err := freeport.VSock() if err != nil { logrus.WithError(err).Error("failed to get free VSock port") @@ -65,6 +70,7 @@ func New() *LimaWslDriver { return &LimaWslDriver{ VSockPort: port, VirtioPort: "", + DriverType: driverType, } } @@ -211,7 +217,34 @@ func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { VMID: VMIDGUID, ServiceID: winio.VsockServiceID(uint32(l.VSockPort)), } - return winio.Dial(ctx, sockAddr) + conn, err := winio.Dial(ctx, sockAddr) + if err != nil { + return nil, err + } + + if l.DriverType == driver.DriverTypeExternal { + proxySocketPath := filepath.Join(l.GetInfo().InstanceDir, filenames.GuestAgentSock) + + listener, err := net.Listen("unix", proxySocketPath) + if err != nil { + logrus.Errorf("Failed to create proxy socket: %v", err) + return nil, err + } + + go func() { + defer listener.Close() + defer conn.Close() + + proxyConn, err := listener.Accept() + if err != nil { + logrus.Errorf("Failed to accept proxy connection: %v", err) + return + } + + bicopy.Bicopy(conn, proxyConn, nil) + }() + } + return conn, nil } func (l *LimaWslDriver) GetInfo() driver.Info { From ebbfcbd10e949d3e0ac24d7e724fa5bd59096322 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 20 Jun 2025 01:31:23 +0530 Subject: [PATCH 43/49] driver(external): clean code and fix driver discovery in libexec Signed-off-by: Ansuman Sahoo --- pkg/driver/external/client/client.go | 9 --- pkg/driver/external/client/pipe.go | 62 ----------------- pkg/driver/external/server/pipe.go | 99 ---------------------------- pkg/driver/external/server/server.go | 26 -------- pkg/registry/registry.go | 8 +-- pkg/store/filenames/filenames.go | 1 - 6 files changed, 4 insertions(+), 201 deletions(-) delete mode 100644 pkg/driver/external/client/pipe.go delete mode 100644 pkg/driver/external/server/pipe.go diff --git a/pkg/driver/external/client/client.go b/pkg/driver/external/client/client.go index 675dfb6fb61..8c95f2f0bd7 100644 --- a/pkg/driver/external/client/client.go +++ b/pkg/driver/external/client/client.go @@ -21,7 +21,6 @@ type DriverClient struct { } func NewDriverClient(socketPath string, logger *logrus.Logger) (*DriverClient, error) { - // pipeConn := newPipeConn(stdin, stdout) opts := []grpc.DialOption{ grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(16 << 20)), grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(16 << 20)), @@ -31,14 +30,6 @@ func NewDriverClient(socketPath string, logger *logrus.Logger) (*DriverClient, e grpc.WithTransportCredentials(insecure.NewCredentials()), } - // conn, err := grpc.NewClient("pipe", opts...) - // if err != nil { - // logger.Errorf("failed to create gRPC driver client connection: %v", err) - // return nil, err - // } - // -> ERRO[2025-06-04T21:32:54+05:30] Failed to set config: rpc error: code = - // Unavailable desc = name resolver error: produced zero addresses - conn, err := grpc.Dial("unix://"+socketPath, opts...) if err != nil { logger.Errorf("failed to dial gRPC driver client connection: %v", err) diff --git a/pkg/driver/external/client/pipe.go b/pkg/driver/external/client/pipe.go deleted file mode 100644 index aa30a70f86a..00000000000 --- a/pkg/driver/external/client/pipe.go +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package client - -// import ( -// "io" -// "net" -// "os" -// "time" -// ) - -// type PipeConn struct { -// Reader io.Reader -// Writer io.Writer -// Closer io.Closer -// } - -// func newPipeConn(writer io.WriteCloser, reader io.ReadCloser) net.Conn { -// return &PipeConn{ -// Reader: reader, -// Writer: writer, -// Closer: os.Stdout, -// } -// } - -// func (p *PipeConn) Read(b []byte) (n int, err error) { -// return p.Reader.Read(b) -// } - -// func (p *PipeConn) Write(b []byte) (n int, err error) { -// return p.Writer.Write(b) -// } - -// func (p *PipeConn) Close() error { -// return p.Closer.Close() -// } - -// func (p *PipeConn) LocalAddr() net.Addr { -// return pipeAddr{} -// } - -// func (p *PipeConn) RemoteAddr() net.Addr { -// return pipeAddr{} -// } - -// func (p *PipeConn) SetDeadline(t time.Time) error { -// return nil -// } - -// func (p *PipeConn) SetReadDeadline(t time.Time) error { -// return nil -// } - -// func (p *PipeConn) SetWriteDeadline(t time.Time) error { -// return nil -// } - -// type pipeAddr struct{} - -// func (pipeAddr) Network() string { return "pipe" } -// func (pipeAddr) String() string { return "pipe" } diff --git a/pkg/driver/external/server/pipe.go b/pkg/driver/external/server/pipe.go deleted file mode 100644 index d3c567121ec..00000000000 --- a/pkg/driver/external/server/pipe.go +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Lima Authors -// SPDX-License-Identifier: Apache-2.0 - -package server - -// import ( -// "io" -// "net" -// "sync" -// "time" -// ) - -// type PipeConn struct { -// Reader io.Reader -// Writer io.Writer -// Closer io.Closer -// } - -// func (p *PipeConn) Read(b []byte) (n int, err error) { -// return p.Reader.Read(b) -// } - -// func (p *PipeConn) Write(b []byte) (n int, err error) { -// return p.Writer.Write(b) -// } - -// func (p *PipeConn) Close() error { -// return p.Closer.Close() -// } - -// func (p *PipeConn) LocalAddr() net.Addr { -// return pipeAddr{} -// } - -// func (p *PipeConn) RemoteAddr() net.Addr { -// return pipeAddr{} -// } - -// func (p *PipeConn) SetDeadline(t time.Time) error { -// return nil -// } - -// func (p *PipeConn) SetReadDeadline(t time.Time) error { -// return nil -// } - -// func (p *PipeConn) SetWriteDeadline(t time.Time) error { -// return nil -// } - -// type pipeAddr struct{} - -// func (pipeAddr) Network() string { return "pipe" } -// func (pipeAddr) String() string { return "pipe" } - -// type PipeListener struct { -// conn net.Conn -// connSent bool -// mu sync.Mutex -// closed bool -// } - -// func NewPipeListener(conn net.Conn) *PipeListener { -// return &PipeListener{ -// conn: conn, -// connSent: false, -// closed: false, -// } -// } - -// func (l *PipeListener) Accept() (net.Conn, error) { -// l.mu.Lock() -// defer l.mu.Unlock() - -// if l.closed { -// return nil, net.ErrClosed -// } - -// if l.connSent { -// select {} -// } - -// l.connSent = true -// return l.conn, nil -// } - -// func (l *PipeListener) Close() error { -// l.mu.Lock() -// defer l.mu.Unlock() - -// if !l.closed { -// l.closed = true -// } -// return nil -// } - -// func (l *PipeListener) Addr() net.Addr { -// return pipeAddr{} -// } diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 39dbd21f0de..82914de9029 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -4,7 +4,6 @@ package server import ( - "context" "fmt" "net" "os" @@ -17,7 +16,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/keepalive" - "github.com/lima-vm/lima/pkg/bicopy" "github.com/lima-vm/lima/pkg/driver" pb "github.com/lima-vm/lima/pkg/driver/external" ) @@ -31,13 +29,6 @@ type DriverServer struct { func Serve(driver driver.Driver) { logger := logrus.New() logger.SetLevel(logrus.DebugLevel) - // pipeConn := &PipeConn{ - // Reader: os.Stdin, - // Writer: os.Stdout, - // Closer: os.Stdout, - // } - - // listener := NewPipeListener(pipeConn) socketPath := filepath.Join(os.TempDir(), fmt.Sprintf("lima-driver-%s-%d.sock", driver.GetInfo().DriverName, os.Getpid())) @@ -95,20 +86,3 @@ func Serve(driver driver.Driver) { logger.Fatalf("Failed to serve: %v", err) } } - -func HandleProxyConnection(ctx context.Context, conn net.Conn, unixSocketPath string) { - logrus.Infof("Handling proxy connection from %s", conn.LocalAddr()) - - var d net.Dialer - unixConn, err := d.DialContext(ctx, "unix", unixSocketPath) - if err != nil { - logrus.Errorf("Failed to connect to unix socket %s: %v", unixSocketPath, err) - return - } - - logrus.Infof("Successfully established proxy tunnel: %s <--> %s", conn.LocalAddr(), unixSocketPath) - - go bicopy.Bicopy(unixConn, conn, nil) - - logrus.Infof("Proxy session ended for %s", conn.LocalAddr()) -} diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 8400c0a32aa..ae6bc543037 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -18,7 +18,6 @@ import ( "github.com/lima-vm/lima/pkg/driver/external/client" "github.com/lima-vm/lima/pkg/store" "github.com/lima-vm/lima/pkg/store/filenames" - "github.com/lima-vm/lima/pkg/usrlocalsharelima" "github.com/sirupsen/logrus" ) @@ -216,12 +215,13 @@ func (r *Registry) RegisterDriver(name, path string) { } func (r *Registry) DiscoverDrivers() error { - limaShareDir, err := usrlocalsharelima.Dir() + homeDir, err := os.UserHomeDir() if err != nil { - return fmt.Errorf("failed to determine Lima share directory: %w", err) + return err } - stdDriverDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") + stdDriverDir := filepath.Join(homeDir, ".local", "libexec", "lima", "drivers") + logrus.Infof("Discovering drivers in %s", stdDriverDir) if _, err := os.Stat(stdDriverDir); err == nil { if err := r.discoverDriversInDir(stdDriverDir); err != nil { logrus.Warnf("Error discovering drivers in %s: %v", stdDriverDir, err) diff --git a/pkg/store/filenames/filenames.go b/pkg/store/filenames/filenames.go index 0bfec19995e..eb61560d4b8 100644 --- a/pkg/store/filenames/filenames.go +++ b/pkg/store/filenames/filenames.go @@ -60,7 +60,6 @@ const ( HostAgentStdoutLog = "ha.stdout.log" HostAgentStderrLog = "ha.stderr.log" ExternalDriverStderrLog = "driver.stderr.log" - ExternalDriverSock = "driver.sock" VzIdentifier = "vz-identifier" VzEfi = "vz-efi" // efi variable store QemuEfiCodeFD = "qemu-efi-code.fd" // efi code; not always created From 963f97cee5bbbcc22877733562fe3292819a499b Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Sat, 21 Jun 2025 02:33:52 +0530 Subject: [PATCH 44/49] driver(external): tweak some code and move the conenction proxy to server-level Signed-off-by: Ansuman Sahoo --- .../qemu/cmd => cmd}/lima-driver-qemu/main.go | 4 +- .../vz/cmd => cmd}/lima-driver-vz/main.go | 5 +- .../lima-driver-wsl2}/main.go | 3 +- cmd/limactl/main.go | 6 +- cmd/limactl/start.go | 8 +- pkg/driver/driver.go | 19 +- pkg/driver/external/client/methods.go | 19 +- pkg/driver/external/server/methods.go | 36 ++- pkg/driver/external/server/server.go | 114 ++++++++- pkg/driver/qemu/qemu_driver.go | 19 +- pkg/driver/qemu/register.go | 3 +- pkg/driver/vz/register.go | 3 +- pkg/driver/vz/vz_driver_darwin.go | 47 +--- pkg/driver/wsl2/register.go | 3 +- pkg/driver/wsl2/wsl_driver_windows.go | 50 +--- pkg/driverutil/instance.go | 25 +- pkg/hostagent/hostagent.go | 12 +- pkg/instance/create.go | 2 +- pkg/instance/delete.go | 2 +- pkg/instance/start.go | 4 +- pkg/limainfo/limainfo.go | 4 +- pkg/registry/registry.go | 242 ++++-------------- pkg/snapshot/snapshot.go | 8 +- pkg/usrlocalsharelima/usrlocalsharelima.go | 8 + 24 files changed, 302 insertions(+), 344 deletions(-) rename {pkg/driver/qemu/cmd => cmd}/lima-driver-qemu/main.go (77%) rename {pkg/driver/vz/cmd => cmd}/lima-driver-vz/main.go (69%) rename {pkg/driver/wsl2/cmd/lima-driver-wsl => cmd/lima-driver-wsl2}/main.go (79%) diff --git a/pkg/driver/qemu/cmd/lima-driver-qemu/main.go b/cmd/lima-driver-qemu/main.go similarity index 77% rename from pkg/driver/qemu/cmd/lima-driver-qemu/main.go rename to cmd/lima-driver-qemu/main.go index 19e6e8df798..1d78c86e072 100644 --- a/pkg/driver/qemu/cmd/lima-driver-qemu/main.go +++ b/cmd/lima-driver-qemu/main.go @@ -4,14 +4,12 @@ package main import ( - "github.com/lima-vm/lima/pkg/driver" - "github.com/lima-vm/lima/pkg/driver/external/server" "github.com/lima-vm/lima/pkg/driver/qemu" ) // To be used as an external driver for Lima. func main() { - driver := qemu.New(driver.DriverTypeExternal) + driver := qemu.New() server.Serve(driver) } diff --git a/pkg/driver/vz/cmd/lima-driver-vz/main.go b/cmd/lima-driver-vz/main.go similarity index 69% rename from pkg/driver/vz/cmd/lima-driver-vz/main.go rename to cmd/lima-driver-vz/main.go index 332dbb4c055..fc0ae38132e 100644 --- a/pkg/driver/vz/cmd/lima-driver-vz/main.go +++ b/cmd/lima-driver-vz/main.go @@ -1,4 +1,4 @@ -//go:build (darwin && amd64) || (darwin && arm64) +//go:build darwin // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 @@ -6,13 +6,12 @@ package main import ( - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/server" "github.com/lima-vm/lima/pkg/driver/vz" ) // To be used as an external driver for Lima. func main() { - driver := vz.New(driver.DriverTypeExternal) + driver := vz.New() server.Serve(driver) } diff --git a/pkg/driver/wsl2/cmd/lima-driver-wsl/main.go b/cmd/lima-driver-wsl2/main.go similarity index 79% rename from pkg/driver/wsl2/cmd/lima-driver-wsl/main.go rename to cmd/lima-driver-wsl2/main.go index 2d125772d83..73ecfd570b5 100644 --- a/pkg/driver/wsl2/cmd/lima-driver-wsl/main.go +++ b/cmd/lima-driver-wsl2/main.go @@ -6,13 +6,12 @@ package main import ( - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/server" "github.com/lima-vm/lima/pkg/driver/wsl2" ) // To be used as an external driver for Lima. func main() { - driver := wsl2.New(driver.DriverTypeExternal) + driver := wsl2.New() server.Serve(driver) } diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index 2cbeba2e21f..85e54753d45 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -16,10 +16,10 @@ import ( "github.com/spf13/cobra" "github.com/lima-vm/lima/pkg/debugutil" - // _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms + "github.com/lima-vm/lima/pkg/driver/external/server" + _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms "github.com/lima-vm/lima/pkg/fsutil" "github.com/lima-vm/lima/pkg/osutil" - "github.com/lima-vm/lima/pkg/registry" "github.com/lima-vm/lima/pkg/store/dirnames" "github.com/lima-vm/lima/pkg/version" ) @@ -46,7 +46,7 @@ func main() { logrus.Fatal(err) } - defer registry.DefaultRegistry.StopAllExternalDrivers() + defer server.StopAllExternalDrivers() } func newApp() *cobra.Command { diff --git a/cmd/limactl/start.go b/cmd/limactl/start.go index 7d482b89fe3..63ebfec723e 100644 --- a/cmd/limactl/start.go +++ b/cmd/limactl/start.go @@ -400,8 +400,12 @@ func createStartActionCommon(cmd *cobra.Command, _ []string) (exit bool, err err return true, err } else if listDrivers { w := cmd.OutOrStdout() - for _, d := range registry.DefaultRegistry.List() { - _, _ = fmt.Fprintln(w, d) + for k, v := range registry.List() { + if v != "internal" { + _, _ = fmt.Fprintln(w, k+"(external)") + continue + } + _, _ = fmt.Fprintln(w, k) } return true, nil } diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index cf6c8bd898f..e0a4759c25f 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -43,7 +43,7 @@ type GUI interface { RunGUI() error ChangeDisplayPassword(ctx context.Context, password string) error - GetDisplayConnection(ctx context.Context) (string, error) + DisplayConnection(ctx context.Context) (string, error) } // SnapshotManager defines operations for managing snapshots. @@ -66,7 +66,7 @@ type GuestAgent interface { ForwardGuestAgent() bool // GuestAgentConn returns the guest agent connection, or nil (if forwarded by ssh). - GuestAgentConn(_ context.Context) (net.Conn, error) + GuestAgentConn(_ context.Context) (net.Conn, string, error) } // Driver interface is used by hostagent for managing vm. @@ -77,10 +77,14 @@ type Driver interface { Registration GuestAgent - GetInfo() Info + Info() Info // SetConfig sets the configuration for the instance. - SetConfig(inst *store.Instance, sshLocalPort int) + Configure(inst *store.Instance, sshLocalPort int) *ConfiguredDriver +} + +type ConfiguredDriver struct { + Driver } type Info struct { @@ -90,10 +94,3 @@ type Info struct { VirtioPort string `json:"virtioPort"` InstanceDir string `json:"instanceDir,omitempty"` } - -type DriverType = string - -const ( - DriverTypeInternal DriverType = "internal" - DriverTypeExternal DriverType = "external" -) diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index 527d68aafea..396f46db49b 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -136,7 +136,7 @@ func (d *DriverClient) ChangeDisplayPassword(ctx context.Context, password strin return nil } -func (d *DriverClient) GetDisplayConnection(ctx context.Context) (string, error) { +func (d *DriverClient) DisplayConnection(ctx context.Context) (string, error) { d.logger.Debug("Getting display connection for the driver instance") resp, err := d.DriverSvc.GetDisplayConnection(ctx, &emptypb.Empty{}) @@ -248,18 +248,18 @@ func (d *DriverClient) ForwardGuestAgent() bool { return resp.ShouldForward } -func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) { +func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, string, error) { d.logger.Info("Getting guest agent connection") _, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Failed to get guest agent connection: %v", err) - return nil, err + return nil, "", err } - return nil, nil + return nil, "", nil } -func (d *DriverClient) GetInfo() driver.Info { +func (d *DriverClient) Info() driver.Info { d.logger.Debug("Getting driver info") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -281,13 +281,13 @@ func (d *DriverClient) GetInfo() driver.Info { return info } -func (d *DriverClient) SetConfig(inst *store.Instance, sshLocalPort int) { +func (d *DriverClient) Configure(inst *store.Instance, sshLocalPort int) *driver.ConfiguredDriver { d.logger.Debugf("Setting config for instance %s with SSH local port %d", inst.Name, sshLocalPort) instJson, err := inst.MarshalJSON() if err != nil { d.logger.Errorf("Failed to marshal instance config: %v", err) - return + return nil } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -299,8 +299,11 @@ func (d *DriverClient) SetConfig(inst *store.Instance, sshLocalPort int) { }) if err != nil { d.logger.Errorf("Failed to set config: %v", err) - return + return nil } d.logger.Debugf("Config set successfully for instance %s", inst.Name) + return &driver.ConfiguredDriver{ + Driver: d, + } } diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index 57a3d2233b6..8ff5cc44e11 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -6,6 +6,8 @@ package server import ( "context" "encoding/json" + "net" + "path/filepath" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -13,8 +15,11 @@ import ( // "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" + "github.com/lima-vm/lima/pkg/bicopy" pb "github.com/lima-vm/lima/pkg/driver/external" "github.com/lima-vm/lima/pkg/store" + "github.com/lima-vm/lima/pkg/store/filenames" + "github.com/sirupsen/logrus" ) func (s *DriverServer) Start(empty *emptypb.Empty, stream pb.Driver_StartServer) error { @@ -59,25 +64,48 @@ func (s *DriverServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) return &emptypb.Empty{}, err } - s.driver.SetConfig(&inst, int(req.SshLocalPort)) + _ = s.driver.Configure(&inst, int(req.SshLocalPort)) return &emptypb.Empty{}, nil } func (s *DriverServer) GuestAgentConn(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { s.logger.Debug("Received GuestAgentConn request") - _, err := s.driver.GuestAgentConn(ctx) + conn, connType, err := s.driver.GuestAgentConn(ctx) if err != nil { s.logger.Errorf("GuestAgentConn failed: %v", err) return nil, err } + if connType != "unix" { + proxySocketPath := filepath.Join(s.driver.Info().InstanceDir, filenames.GuestAgentSock) + + listener, err := net.Listen("unix", proxySocketPath) + if err != nil { + logrus.Errorf("Failed to create proxy socket: %v", err) + return nil, err + } + + go func() { + defer listener.Close() + defer conn.Close() + + proxyConn, err := listener.Accept() + if err != nil { + logrus.Errorf("Failed to accept proxy connection: %v", err) + return + } + + bicopy.Bicopy(conn, proxyConn, nil) + }() + } + return &emptypb.Empty{}, nil } func (s *DriverServer) GetInfo(ctx context.Context, empty *emptypb.Empty) (*pb.InfoResponse, error) { s.logger.Debug("Received GetInfo request") - info := s.driver.GetInfo() + info := s.driver.Info() infoJson, err := json.Marshal(info) if err != nil { @@ -158,7 +186,7 @@ func (s *DriverServer) ChangeDisplayPassword(ctx context.Context, req *pb.Change func (s *DriverServer) GetDisplayConnection(ctx context.Context, empty *emptypb.Empty) (*pb.GetDisplayConnectionResponse, error) { s.logger.Debug("Received GetDisplayConnection request") - conn, err := s.driver.GetDisplayConnection(ctx) + conn, err := s.driver.DisplayConnection(ctx) if err != nil { s.logger.Errorf("GetDisplayConnection failed: %v", err) return nil, err diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 82914de9029..b81e7597e82 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -4,11 +4,15 @@ package server import ( + "bufio" + "context" "fmt" "net" "os" + "os/exec" "os/signal" "path/filepath" + "strings" "syscall" "time" @@ -18,6 +22,10 @@ import ( "github.com/lima-vm/lima/pkg/driver" pb "github.com/lima-vm/lima/pkg/driver/external" + "github.com/lima-vm/lima/pkg/driver/external/client" + "github.com/lima-vm/lima/pkg/registry" + "github.com/lima-vm/lima/pkg/store" + "github.com/lima-vm/lima/pkg/store/filenames" ) type DriverServer struct { @@ -30,7 +38,7 @@ func Serve(driver driver.Driver) { logger := logrus.New() logger.SetLevel(logrus.DebugLevel) - socketPath := filepath.Join(os.TempDir(), fmt.Sprintf("lima-driver-%s-%d.sock", driver.GetInfo().DriverName, os.Getpid())) + socketPath := filepath.Join(os.TempDir(), fmt.Sprintf("lima-driver-%s-%d.sock", driver.Info().DriverName, os.Getpid())) defer func() { if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) { @@ -80,9 +88,111 @@ func Serve(driver driver.Driver) { os.Exit(0) }() - logger.Infof("Starting external driver server for %s", driver.GetInfo().DriverName) + logger.Infof("Starting external driver server for %s", driver.Info().DriverName) logger.Infof("Server starting on Unix socket: %s", socketPath) if err := server.Serve(listener); err != nil { logger.Fatalf("Failed to serve: %v", err) } } + +func Start(extDriver *registry.ExternalDriver, instName string) error { + extDriver.Logger.Infof("Starting external driver at %s", extDriver.Path) + if instName == "" { + return fmt.Errorf("instance name cannot be empty") + } + extDriver.InstanceName = instName + + ctx, cancel := context.WithCancel(context.Background()) + cmd := exec.CommandContext(ctx, extDriver.Path) + + stdout, err := cmd.StdoutPipe() + if err != nil { + cancel() + return fmt.Errorf("failed to create stdout pipe for external driver: %w", err) + } + + instanceDir, err := store.InstanceDir(extDriver.InstanceName) + if err != nil { + cancel() + return fmt.Errorf("failed to determine instance directory: %w", err) + } + logPath := filepath.Join(instanceDir, filenames.ExternalDriverStderrLog) + logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + cancel() + return fmt.Errorf("failed to open external driver log file: %w", err) + } + + // Redirect stderr to the log file + cmd.Stderr = logFile + + if err := cmd.Start(); err != nil { + cancel() + return fmt.Errorf("failed to start external driver: %w", err) + } + + driverLogger := extDriver.Logger.WithField("driver", extDriver.Name) + + time.Sleep(time.Millisecond * 100) + + scanner := bufio.NewScanner(stdout) + var socketPath string + if scanner.Scan() { + socketPath = strings.TrimSpace(scanner.Text()) + } else { + cancel() + cmd.Process.Kill() + return fmt.Errorf("failed to read socket path from driver") + } + extDriver.SocketPath = socketPath + + driverClient, err := client.NewDriverClient(extDriver.SocketPath, extDriver.Logger) + if err != nil { + cancel() + cmd.Process.Kill() + return fmt.Errorf("failed to create driver client: %w", err) + } + + extDriver.Command = cmd + extDriver.Client = driverClient + extDriver.Ctx = ctx + extDriver.CancelFunc = cancel + + driverLogger.Infof("External driver %s started successfully", extDriver.Name) + return nil +} + +func Stop(extDriver *registry.ExternalDriver) error { + if extDriver.Command == nil || extDriver.Command.Process == nil { + return fmt.Errorf("external driver %s is not running", extDriver.Name) + } + + extDriver.Logger.Infof("Stopping external driver %s", extDriver.Name) + if extDriver.CancelFunc != nil { + extDriver.CancelFunc() + } + if err := os.Remove(extDriver.SocketPath); err != nil && !os.IsNotExist(err) { + extDriver.Logger.Warnf("Failed to remove socket file: %v", err) + } + + extDriver.Command = nil + extDriver.Client = nil + extDriver.Ctx = nil + extDriver.CancelFunc = nil + + extDriver.Logger.Infof("External driver %s stopped successfully", extDriver.Name) + return nil +} + +func StopAllExternalDrivers() { + for name, driver := range registry.ExternalDrivers { + if driver.Command != nil && driver.Command.Process != nil { + if err := Stop(driver); err != nil { + logrus.Errorf("Failed to stop external driver %s: %v", name, err) + } else { + logrus.Infof("External driver %s stopped successfully", name) + } + } + delete(registry.ExternalDrivers, name) + } +} diff --git a/pkg/driver/qemu/qemu_driver.go b/pkg/driver/qemu/qemu_driver.go index a04e8de7ba2..2740ec0adff 100644 --- a/pkg/driver/qemu/qemu_driver.go +++ b/pkg/driver/qemu/qemu_driver.go @@ -42,8 +42,6 @@ type LimaQemuDriver struct { VSockPort int VirtioPort string - DriverType driver.DriverType - qCmd *exec.Cmd qWaitCh chan error @@ -52,7 +50,7 @@ type LimaQemuDriver struct { var _ driver.Driver = (*LimaQemuDriver)(nil) -func New(driverType driver.DriverType) *LimaQemuDriver { +func New() *LimaQemuDriver { // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 // but on Windows default Unix socket forwarding is not available var virtioPort string @@ -63,13 +61,16 @@ func New(driverType driver.DriverType) *LimaQemuDriver { return &LimaQemuDriver{ VSockPort: 0, VirtioPort: virtioPort, - DriverType: driverType, } } -func (l *LimaQemuDriver) SetConfig(inst *store.Instance, sshLocalPort int) { +func (l *LimaQemuDriver) Configure(inst *store.Instance, sshLocalPort int) *driver.ConfiguredDriver { l.Instance = inst l.SSHLocalPort = sshLocalPort + + return &driver.ConfiguredDriver{ + Driver: l, + } } func (l *LimaQemuDriver) Validate() error { @@ -244,7 +245,7 @@ func (l *LimaQemuDriver) ChangeDisplayPassword(_ context.Context, password strin return l.changeVNCPassword(password) } -func (l *LimaQemuDriver) GetDisplayConnection(_ context.Context) (string, error) { +func (l *LimaQemuDriver) DisplayConnection(_ context.Context) (string, error) { return l.getVNCDisplayPort() } @@ -456,10 +457,10 @@ func (l *LimaQemuDriver) ListSnapshots(_ context.Context) (string, error) { return List(qCfg, l.Instance.Status == store.StatusRunning) } -func (l *LimaQemuDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { +func (l *LimaQemuDriver) GuestAgentConn(ctx context.Context) (net.Conn, string, error) { var d net.Dialer dialContext, err := d.DialContext(ctx, "unix", filepath.Join(l.Instance.Dir, filenames.GuestAgentSock)) - return dialContext, err + return dialContext, "unix", err } type qArgTemplateApplier struct { @@ -514,7 +515,7 @@ func (a *qArgTemplateApplier) applyTemplate(qArg string) (string, error) { return b.String(), nil } -func (l *LimaQemuDriver) GetInfo() driver.Info { +func (l *LimaQemuDriver) Info() driver.Info { var info driver.Info if l.Instance != nil && l.Instance.Dir != "" { info.InstanceDir = l.Instance.Dir diff --git a/pkg/driver/qemu/register.go b/pkg/driver/qemu/register.go index bede04cfc94..c1a563db574 100644 --- a/pkg/driver/qemu/register.go +++ b/pkg/driver/qemu/register.go @@ -4,10 +4,9 @@ package qemu import ( - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/registry" ) func init() { - registry.Register(New(driver.DriverTypeInternal)) + registry.Register(New()) } diff --git a/pkg/driver/vz/register.go b/pkg/driver/vz/register.go index 959d21599ae..ffdde812bbc 100644 --- a/pkg/driver/vz/register.go +++ b/pkg/driver/vz/register.go @@ -6,10 +6,9 @@ package vz import ( - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/registry" ) func init() { - registry.Register(New(driver.DriverTypeInternal)) + registry.Register(New()) } diff --git a/pkg/driver/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go index 349e01d3612..fe83f61b5b9 100644 --- a/pkg/driver/vz/vz_driver_darwin.go +++ b/pkg/driver/vz/vz_driver_darwin.go @@ -18,13 +18,11 @@ import ( "github.com/coreos/go-semver/semver" "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/bicopy" "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/reflectutil" "github.com/lima-vm/lima/pkg/store" - "github.com/lima-vm/lima/pkg/store/filenames" ) var knownYamlProperties = []string{ @@ -77,24 +75,25 @@ type LimaVzDriver struct { VSockPort int VirtioPort string - DriverType driver.DriverType - machine *virtualMachineWrapper } var _ driver.Driver = (*LimaVzDriver)(nil) -func New(driverType driver.DriverType) *LimaVzDriver { +func New() *LimaVzDriver { return &LimaVzDriver{ VSockPort: 2222, VirtioPort: "", - DriverType: driverType, } } -func (l *LimaVzDriver) SetConfig(inst *store.Instance, sshLocalPort int) { +func (l *LimaVzDriver) Configure(inst *store.Instance, sshLocalPort int) *driver.ConfiguredDriver { l.Instance = inst l.SSHLocalPort = sshLocalPort + + return &driver.ConfiguredDriver{ + Driver: l, + } } func (l *LimaVzDriver) Validate() error { @@ -251,40 +250,16 @@ func (l *LimaVzDriver) Stop(_ context.Context) error { return errors.New("vz: CanRequestStop is not supported") } -func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, error) { +func (l *LimaVzDriver) GuestAgentConn(_ context.Context) (net.Conn, string, error) { for _, socket := range l.machine.SocketDevices() { connect, err := socket.Connect(uint32(l.VSockPort)) - if err == nil && connect.SourcePort() != 0 { - if l.DriverType == driver.DriverTypeExternal { - proxySocketPath := filepath.Join(l.GetInfo().InstanceDir, filenames.GuestAgentSock) - - listener, err := net.Listen("unix", proxySocketPath) - if err != nil { - logrus.Errorf("Failed to create proxy socket: %v", err) - return nil, err - } - - go func() { - defer listener.Close() - defer connect.Close() - - proxyConn, err := listener.Accept() - if err != nil { - logrus.Errorf("Failed to accept proxy connection: %v", err) - return - } - - bicopy.Bicopy(connect, proxyConn, nil) - }() - } - return connect, nil - } + return connect, "vsock", err } - return nil, errors.New("unable to connect to guest agent via vsock port 2222") + return nil, "", errors.New("unable to connect to guest agent via vsock port 2222") } -func (l *LimaVzDriver) GetInfo() driver.Info { +func (l *LimaVzDriver) Info() driver.Info { var info driver.Info if l.Instance != nil && l.Instance.Config != nil { info.CanRunGUI = l.canRunGUI() @@ -311,7 +286,7 @@ func (l *LimaVzDriver) ChangeDisplayPassword(_ context.Context, _ string) error return nil } -func (l *LimaVzDriver) GetDisplayConnection(_ context.Context) (string, error) { +func (l *LimaVzDriver) DisplayConnection(_ context.Context) (string, error) { return "", nil } diff --git a/pkg/driver/wsl2/register.go b/pkg/driver/wsl2/register.go index 75f977e10be..377e1beea63 100644 --- a/pkg/driver/wsl2/register.go +++ b/pkg/driver/wsl2/register.go @@ -6,10 +6,9 @@ package wsl2 import ( - "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/registry" ) func init() { - registry.Register(New(driver.DriverTypeInternal)) + registry.Register(New()) } diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index d612332ed6f..e41c0873a29 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -7,20 +7,17 @@ import ( "context" "fmt" "net" - "path/filepath" "regexp" "github.com/Microsoft/go-winio" "github.com/Microsoft/go-winio/pkg/guid" "github.com/sirupsen/logrus" - "github.com/lima-vm/lima/pkg/bicopy" "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/freeport" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/reflectutil" "github.com/lima-vm/lima/pkg/store" - "github.com/lima-vm/lima/pkg/store/filenames" "github.com/lima-vm/lima/pkg/windows" ) @@ -55,13 +52,11 @@ type LimaWslDriver struct { SSHLocalPort int VSockPort int VirtioPort string - - DriverType driver.DriverType } var _ driver.Driver = (*LimaWslDriver)(nil) -func New(driverType driver.DriverType) *LimaWslDriver { +func New() *LimaWslDriver { port, err := freeport.VSock() if err != nil { logrus.WithError(err).Error("failed to get free VSock port") @@ -70,13 +65,16 @@ func New(driverType driver.DriverType) *LimaWslDriver { return &LimaWslDriver{ VSockPort: port, VirtioPort: "", - DriverType: driverType, } } -func (l *LimaWslDriver) SetConfig(inst *store.Instance, sshLocalPort int) { +func (l *LimaWslDriver) Configure(inst *store.Instance, sshLocalPort int) *driver.ConfiguredDriver { l.Instance = inst l.SSHLocalPort = sshLocalPort + + return &driver.ConfiguredDriver{ + Driver: l, + } } func (l *LimaWslDriver) Validate() error { @@ -204,14 +202,14 @@ func (l *LimaWslDriver) Unregister(ctx context.Context) error { // GuestAgentConn returns the guest agent connection, or nil (if forwarded by ssh). // As of 08-01-2024, github.com/mdlayher/vsock does not natively support vsock on // Windows, so use the winio library to create the connection. -func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { +func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, string, error) { VMIDStr, err := windows.GetInstanceVMID(fmt.Sprintf("lima-%s", l.Instance.Name)) if err != nil { - return nil, err + return nil, "", err } VMIDGUID, err := guid.FromString(VMIDStr) if err != nil { - return nil, err + return nil, "", err } sockAddr := &winio.HvsockAddr{ VMID: VMIDGUID, @@ -219,35 +217,13 @@ func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, error) { } conn, err := winio.Dial(ctx, sockAddr) if err != nil { - return nil, err + return nil, "", err } - if l.DriverType == driver.DriverTypeExternal { - proxySocketPath := filepath.Join(l.GetInfo().InstanceDir, filenames.GuestAgentSock) - - listener, err := net.Listen("unix", proxySocketPath) - if err != nil { - logrus.Errorf("Failed to create proxy socket: %v", err) - return nil, err - } - - go func() { - defer listener.Close() - defer conn.Close() - - proxyConn, err := listener.Accept() - if err != nil { - logrus.Errorf("Failed to accept proxy connection: %v", err) - return - } - - bicopy.Bicopy(conn, proxyConn, nil) - }() - } - return conn, nil + return conn, "vsock", nil } -func (l *LimaWslDriver) GetInfo() driver.Info { +func (l *LimaWslDriver) Info() driver.Info { var info driver.Info if l.Instance != nil && l.Instance.Dir != "" { info.InstanceDir = l.Instance.Dir @@ -275,7 +251,7 @@ func (l *LimaWslDriver) ChangeDisplayPassword(_ context.Context, _ string) error return nil } -func (l *LimaWslDriver) GetDisplayConnection(_ context.Context) (string, error) { +func (l *LimaWslDriver) DisplayConnection(_ context.Context) (string, error) { return "", nil } diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index ac7b1fffd91..387dab664b6 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -7,19 +7,36 @@ import ( "fmt" "github.com/lima-vm/lima/pkg/driver" + "github.com/lima-vm/lima/pkg/driver/external/server" "github.com/lima-vm/lima/pkg/registry" "github.com/lima-vm/lima/pkg/store" + "github.com/sirupsen/logrus" ) // CreateTargetDriverInstance creates the appropriate driver for an instance. -func CreateTargetDriverInstance(inst *store.Instance, sshLocalPort int) (driver.Driver, error) { +func CreateConfiguredDriver(inst *store.Instance, sshLocalPort int) (*driver.ConfiguredDriver, error) { limaDriver := inst.Config.VMType - driver, exists := registry.DefaultRegistry.Get(string(*limaDriver), inst.Name) + extDriver, intDriver, exists := registry.Get(string(*limaDriver)) if !exists { return nil, fmt.Errorf("unknown or unsupported VM type: %s", *limaDriver) } - driver.SetConfig(inst, sshLocalPort) + if extDriver != nil { + extDriver.Logger.Debugf("Using external driver %q", extDriver.Name) + if extDriver.Client == nil || extDriver.Command == nil || extDriver.Command.Process == nil { + logrus.Infof("Starting new instance of external driver %q", extDriver.Name) + if err := server.Start(extDriver, inst.Name); err != nil { + extDriver.Logger.Errorf("Failed to start external driver %q: %v", extDriver.Name, err) + return nil, err + } + } else { + logrus.Infof("Reusing existing external driver %q instance", extDriver.Name) + extDriver.InstanceName = inst.Name + } - return driver, nil + return extDriver.Client.Configure(inst, sshLocalPort), nil + } + + logrus.Infof("Using internal driver %q", intDriver.Info().DriverName) + return intDriver.Configure(inst, sshLocalPort), nil } diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 59fdcf93874..12b7eca29ce 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -131,13 +131,13 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt } } - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, sshLocalPort) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, sshLocalPort) if err != nil { return nil, fmt.Errorf("failed to create driver instance: %w", err) } - vSockPort := limaDriver.GetInfo().VsockPort - virtioPort := limaDriver.GetInfo().VirtioPort + vSockPort := limaDriver.Info().VsockPort + virtioPort := limaDriver.Info().VirtioPort if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { return nil, err @@ -340,7 +340,7 @@ func (a *HostAgent) Run(ctx context.Context) error { return err } if strings.Contains(vncoptions, "to=") { - vncport, err = a.driver.GetDisplayConnection(ctx) + vncport, err = a.driver.DisplayConnection(ctx) if err != nil { return err } @@ -361,7 +361,7 @@ func (a *HostAgent) Run(ctx context.Context) error { logrus.Infof("VNC Password: `%s`", vncpwdfile) } - if a.driver.GetInfo().CanRunGUI { + if a.driver.Info().CanRunGUI { go func() { err = a.startRoutinesAndWait(ctx, errCh) if err != nil { @@ -623,7 +623,7 @@ func (a *HostAgent) getOrCreateClient(ctx context.Context) (*guestagentclient.Gu } func (a *HostAgent) createConnection(ctx context.Context) (net.Conn, error) { - conn, err := a.driver.GuestAgentConn(ctx) + conn, _, err := a.driver.GuestAgentConn(ctx) // default to forwarded sock if conn == nil && err == nil { var d net.Dialer diff --git a/pkg/instance/create.go b/pkg/instance/create.go index 6af427110a8..5bb0912ae99 100644 --- a/pkg/instance/create.go +++ b/pkg/instance/create.go @@ -75,7 +75,7 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY return nil, err } - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return nil, fmt.Errorf("failed to create driver instance: %w", err) } diff --git a/pkg/instance/delete.go b/pkg/instance/delete.go index 9ad4d10b878..9dc55f3bd1e 100644 --- a/pkg/instance/delete.go +++ b/pkg/instance/delete.go @@ -36,7 +36,7 @@ func Delete(ctx context.Context, inst *store.Instance, force bool) error { } func unregister(ctx context.Context, inst *store.Instance) error { - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return fmt.Errorf("failed to create driver instance: %w", err) } diff --git a/pkg/instance/start.go b/pkg/instance/start.go index 6a6a4e97da8..e6f1d54fbcb 100644 --- a/pkg/instance/start.go +++ b/pkg/instance/start.go @@ -90,7 +90,7 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { return nil, err } } - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return nil, fmt.Errorf("failed to create driver instance: %w", err) } @@ -189,7 +189,7 @@ func Start(ctx context.Context, inst *store.Instance, limactl string, launchHost "hostagent", "--pidfile", haPIDPath, "--socket", haSockPath) - if prepared.Driver.GetInfo().CanRunGUI { + if prepared.Driver.Info().CanRunGUI { args = append(args, "--run-gui") } if prepared.GuestAgent != "" { diff --git a/pkg/limainfo/limainfo.go b/pkg/limainfo/limainfo.go index 0bd1876b6b4..7de30ad7816 100644 --- a/pkg/limainfo/limainfo.go +++ b/pkg/limainfo/limainfo.go @@ -22,7 +22,7 @@ type LimaInfo struct { Templates []templatestore.Template `json:"templates"` DefaultTemplate *limayaml.LimaYAML `json:"defaultTemplate"` LimaHome string `json:"limaHome"` - VMTypes []string `json:"vmTypes"` // since Lima v0.14.2 + VMTypes map[string]string `json:"vmTypes"` // since Lima v0.14.2 GuestAgents map[limayaml.Arch]GuestAgent `json:"guestAgents"` // since Lima v1.1.0 } @@ -45,7 +45,7 @@ func New() (*LimaInfo, error) { info := &LimaInfo{ Version: version.Version, DefaultTemplate: y, - VMTypes: registry.DefaultRegistry.List(), + VMTypes: registry.List(), GuestAgents: make(map[limayaml.Arch]GuestAgent), } info.Templates, err = templatestore.Templates() diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index ae6bc543037..65e10aca599 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -4,20 +4,16 @@ package registry import ( - "bufio" "context" "fmt" "os" "os/exec" "path/filepath" "strings" - "sync" - "time" "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/driver/external/client" - "github.com/lima-vm/lima/pkg/store" - "github.com/lima-vm/lima/pkg/store/filenames" + "github.com/lima-vm/lima/pkg/usrlocalsharelima" "github.com/sirupsen/logrus" ) @@ -28,203 +24,61 @@ type ExternalDriver struct { SocketPath string Client *client.DriverClient // Client is the gRPC client for the external driver Path string - ctx context.Context - logger *logrus.Logger - cancelFunc context.CancelFunc + Ctx context.Context + Logger *logrus.Logger + CancelFunc context.CancelFunc } -type Registry struct { - internalDrivers map[string]driver.Driver - externalDrivers map[string]*ExternalDriver - mu sync.RWMutex -} - -func NewRegistry() *Registry { - return &Registry{ - internalDrivers: make(map[string]driver.Driver), - externalDrivers: make(map[string]*ExternalDriver), - } -} - -func (e *ExternalDriver) Start(instName string) error { - e.logger.Infof("Starting external driver at %s", e.Path) - if instName == "" { - return fmt.Errorf("instance name cannot be empty") - } - e.InstanceName = instName - - ctx, cancel := context.WithCancel(context.Background()) - cmd := exec.CommandContext(ctx, e.Path) - - stdout, err := cmd.StdoutPipe() - if err != nil { - cancel() - return fmt.Errorf("failed to create stdout pipe for external driver: %w", err) - } - - instanceDir, err := store.InstanceDir(e.InstanceName) - if err != nil { - cancel() - return fmt.Errorf("failed to determine instance directory: %w", err) - } - logPath := filepath.Join(instanceDir, filenames.ExternalDriverStderrLog) - logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) - if err != nil { - cancel() - return fmt.Errorf("failed to open external driver log file: %w", err) - } - - // Redirect stderr to the log file - cmd.Stderr = logFile - - if err := cmd.Start(); err != nil { - cancel() - return fmt.Errorf("failed to start external driver: %w", err) - } - - driverLogger := e.logger.WithField("driver", e.Name) - - time.Sleep(time.Millisecond * 100) - - scanner := bufio.NewScanner(stdout) - var socketPath string - if scanner.Scan() { - socketPath = strings.TrimSpace(scanner.Text()) - } else { - cancel() - cmd.Process.Kill() - return fmt.Errorf("failed to read socket path from driver") - } - e.SocketPath = socketPath - - driverClient, err := client.NewDriverClient(e.SocketPath, e.logger) - if err != nil { - cancel() - cmd.Process.Kill() - return fmt.Errorf("failed to create driver client: %w", err) - } - - e.Command = cmd - e.Client = driverClient - e.ctx = ctx - e.cancelFunc = cancel - - driverLogger.Infof("External driver %s started successfully", e.Name) - return nil -} - -func (e *ExternalDriver) cleanup() { - if e.cancelFunc != nil { - e.cancelFunc() - } - if err := os.Remove(e.SocketPath); err != nil && !os.IsNotExist(err) { - e.logger.Warnf("Failed to remove socket file: %v", err) - } - - e.Command = nil - e.Client = nil - e.ctx = nil - e.cancelFunc = nil -} - -func (e *ExternalDriver) Stop() error { - if e.Command == nil || e.Command.Process == nil { - return fmt.Errorf("external driver %s is not running", e.Name) - } - - e.logger.Infof("Stopping external driver %s", e.Name) - e.cleanup() - - e.logger.Infof("External driver %s stopped successfully", e.Name) - return nil -} - -func (r *Registry) StopAllExternalDrivers() { - r.mu.Lock() - defer r.mu.Unlock() - - for name, driver := range r.externalDrivers { - // Only try to stop if the driver is actually running - if driver.Command != nil && driver.Command.Process != nil { - if err := driver.Stop(); err != nil { - logrus.Errorf("Failed to stop external driver %s: %v", name, err) - } else { - logrus.Infof("External driver %s stopped successfully", name) - } - } - // Always remove from registry - delete(r.externalDrivers, name) - } -} - -func (r *Registry) List() []string { - r.mu.RLock() - defer r.mu.RUnlock() +var ( + internalDrivers = make(map[string]driver.Driver) + ExternalDrivers = make(map[string]*ExternalDriver) +) - var names []string - for name := range r.internalDrivers { - names = append(names, name) +func List() map[string]string { + vmTypes := make(map[string]string) + for name := range internalDrivers { + vmTypes[name] = "internal" } - - for name := range r.externalDrivers { - names = append(names, name+" (external)") + for name, d := range ExternalDrivers { + vmTypes[name] = d.Path } - return names + return vmTypes } -func (r *Registry) Get(name, instName string) (driver.Driver, bool) { - r.mu.RLock() - defer r.mu.RUnlock() - - driver, exists := r.internalDrivers[name] +func Get(name string) (*ExternalDriver, driver.Driver, bool) { + internalDriver, exists := internalDrivers[name] if !exists { - externalDriver, exists := r.externalDrivers[name] + externalDriver, exists := ExternalDrivers[name] if exists { - externalDriver.logger.Debugf("Using external driver %q", name) - if externalDriver.Client == nil || externalDriver.Command == nil || externalDriver.Command.Process == nil { - logrus.Infof("Starting new instance of external driver %q", name) - if err := externalDriver.Start(instName); err != nil { - externalDriver.logger.Errorf("Failed to start external driver %q: %v", name, err) - return nil, false - } - } else { - logrus.Infof("Reusing existing external driver %q instance", name) - r.externalDrivers[name].InstanceName = instName - } - - return externalDriver.Client, true + return externalDriver, nil, exists } } - return driver, exists + return nil, internalDriver, exists } -func (r *Registry) RegisterDriver(name, path string) { - r.mu.Lock() - defer r.mu.Unlock() - - if _, exists := DefaultRegistry.externalDrivers[name]; exists { +func RegisterExternalDriver(name, path string) { + if _, exists := ExternalDrivers[name]; exists { logrus.Debugf("Driver %q is already registered, skipping", name) return } - - DefaultRegistry.externalDrivers[name] = &ExternalDriver{ + ExternalDrivers[name] = &ExternalDriver{ Name: name, Path: path, - logger: logrus.New(), + Logger: logrus.New(), } } -func (r *Registry) DiscoverDrivers() error { - homeDir, err := os.UserHomeDir() +func DiscoverDrivers() error { + prefix, err := usrlocalsharelima.Prefix() if err != nil { return err } - stdDriverDir := filepath.Join(homeDir, ".local", "libexec", "lima", "drivers") + stdDriverDir := filepath.Join(prefix, "libexec", "lima") logrus.Infof("Discovering drivers in %s", stdDriverDir) if _, err := os.Stat(stdDriverDir); err == nil { - if err := r.discoverDriversInDir(stdDriverDir); err != nil { - logrus.Warnf("Error discovering drivers in %s: %v", stdDriverDir, err) + if err := discoverDriversInDir(stdDriverDir); err != nil { + logrus.Warnf("Error discovering drivers in %q: %v", stdDriverDir, err) } } @@ -237,16 +91,16 @@ func (r *Registry) DiscoverDrivers() error { info, err := os.Stat(path) if err != nil { - logrus.Warnf("Error accessing driver path %s: %v", path, err) + logrus.Warnf("Error accessing driver path %q: %v", path, err) continue } if info.IsDir() { - if err := r.discoverDriversInDir(path); err != nil { - logrus.Warnf("Error discovering drivers in %s: %v", path, err) + if err := discoverDriversInDir(path); err != nil { + logrus.Warnf("Error discovering drivers in %q: %v", path, err) } } else if isExecutable(info.Mode()) { - r.registerDriverFile(path) + registerDriverFile(path) } } } @@ -254,10 +108,10 @@ func (r *Registry) DiscoverDrivers() error { return nil } -func (r *Registry) discoverDriversInDir(dir string) error { +func discoverDriversInDir(dir string) error { entries, err := os.ReadDir(dir) if err != nil { - return fmt.Errorf("failed to read driver directory %s: %w", dir, err) + return fmt.Errorf("failed to read driver directory %q: %w", dir, err) } for _, entry := range entries { @@ -267,7 +121,7 @@ func (r *Registry) discoverDriversInDir(dir string) error { info, err := entry.Info() if err != nil { - logrus.Warnf("Failed to get info for %s: %v", entry.Name(), err) + logrus.Warnf("Failed to get info for %q: %v", entry.Name(), err) continue } @@ -276,45 +130,37 @@ func (r *Registry) discoverDriversInDir(dir string) error { } driverPath := filepath.Join(dir, entry.Name()) - r.registerDriverFile(driverPath) + registerDriverFile(driverPath) } return nil } -func (r *Registry) registerDriverFile(path string) { +func registerDriverFile(path string) { base := filepath.Base(path) if !strings.HasPrefix(base, "lima-driver-") { - fmt.Printf("Skipping %s: does not start with 'lima-driver-'\n", base) return } name := strings.TrimPrefix(base, "lima-driver-") - name = strings.TrimSuffix(name, filepath.Ext(name)) - r.RegisterDriver(name, path) + RegisterExternalDriver(name, path) } func isExecutable(mode os.FileMode) bool { return mode&0111 != 0 } -var DefaultRegistry *Registry - func init() { - DefaultRegistry = NewRegistry() - if err := DefaultRegistry.DiscoverDrivers(); err != nil { + if err := DiscoverDrivers(); err != nil { logrus.Warnf("Error discovering drivers: %v", err) } } func Register(driver driver.Driver) { - if DefaultRegistry != nil { - name := driver.GetInfo().DriverName - if _, exists := DefaultRegistry.internalDrivers[name]; exists { - return - } - - DefaultRegistry.internalDrivers[name] = driver + name := driver.Info().DriverName + if _, exists := internalDrivers[name]; exists { + return } + internalDrivers[name] = driver } diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index b41579e273a..14f7f24c30f 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -12,7 +12,7 @@ import ( ) func Del(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return fmt.Errorf("failed to create driver instance: %w", err) } @@ -21,7 +21,7 @@ func Del(ctx context.Context, inst *store.Instance, tag string) error { } func Save(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return fmt.Errorf("failed to create driver instance: %w", err) } @@ -29,7 +29,7 @@ func Save(ctx context.Context, inst *store.Instance, tag string) error { } func Load(ctx context.Context, inst *store.Instance, tag string) error { - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return fmt.Errorf("failed to create driver instance: %w", err) } @@ -37,7 +37,7 @@ func Load(ctx context.Context, inst *store.Instance, tag string) error { } func List(ctx context.Context, inst *store.Instance) (string, error) { - limaDriver, err := driverutil.CreateTargetDriverInstance(inst, 0) + limaDriver, err := driverutil.CreateConfiguredDriver(inst, 0) if err != nil { return "", fmt.Errorf("failed to create driver instance: %w", err) } diff --git a/pkg/usrlocalsharelima/usrlocalsharelima.go b/pkg/usrlocalsharelima/usrlocalsharelima.go index 0f08e609486..d86824780f8 100644 --- a/pkg/usrlocalsharelima/usrlocalsharelima.go +++ b/pkg/usrlocalsharelima/usrlocalsharelima.go @@ -165,3 +165,11 @@ func chooseGABinary(candidates []string) (string, error) { return entries[0], nil } } + +func Prefix() (string, error) { + dir, err := Dir() + if err != nil { + return "", err + } + return filepath.Dir(filepath.Dir(dir)), nil +} From f2cd7f04d085cf12f9d48d9d234b42a86b4fd0ff Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 23 Jun 2025 21:41:42 +0530 Subject: [PATCH 45/49] driver(registry): prioritize internal drivers Signed-off-by: Ansuman Sahoo --- pkg/registry/registry.go | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 65e10aca599..838b9772b99 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -35,6 +35,10 @@ var ( ) func List() map[string]string { + if err := discoverDrivers(); err != nil { + logrus.Warnf("Error discovering drivers: %v", err) + } + vmTypes := make(map[string]string) for name := range internalDrivers { vmTypes[name] = "internal" @@ -46,6 +50,10 @@ func List() map[string]string { } func Get(name string) (*ExternalDriver, driver.Driver, bool) { + if err := discoverDrivers(); err != nil { + logrus.Warnf("Error discovering drivers: %v", err) + } + internalDriver, exists := internalDrivers[name] if !exists { externalDriver, exists := ExternalDrivers[name] @@ -56,11 +64,16 @@ func Get(name string) (*ExternalDriver, driver.Driver, bool) { return nil, internalDriver, exists } -func RegisterExternalDriver(name, path string) { +func registerExternalDriver(name, path string) { if _, exists := ExternalDrivers[name]; exists { - logrus.Debugf("Driver %q is already registered, skipping", name) return } + + if _, exists := internalDrivers[name]; exists { + logrus.Warnf("Driver %q is already registered as an internal driver, skipping external registration", name) + return + } + ExternalDrivers[name] = &ExternalDriver{ Name: name, Path: path, @@ -68,7 +81,7 @@ func RegisterExternalDriver(name, path string) { } } -func DiscoverDrivers() error { +func discoverDrivers() error { prefix, err := usrlocalsharelima.Prefix() if err != nil { return err @@ -144,19 +157,13 @@ func registerDriverFile(path string) { name := strings.TrimPrefix(base, "lima-driver-") - RegisterExternalDriver(name, path) + registerExternalDriver(name, path) } func isExecutable(mode os.FileMode) bool { return mode&0111 != 0 } -func init() { - if err := DiscoverDrivers(); err != nil { - logrus.Warnf("Error discovering drivers: %v", err) - } -} - func Register(driver driver.Driver) { name := driver.Info().DriverName if _, exists := internalDrivers[name]; exists { From c8b411323c70949e985899b8fcb9332b50751a03 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Tue, 24 Jun 2025 23:45:10 +0530 Subject: [PATCH 46/49] driver(build): update Makefile to build drivers as internal or external Signed-off-by: Ansuman Sahoo --- Makefile | 34 +++++++++++++++++++++++++++++++--- cmd/lima-driver-qemu/main.go | 3 +-- cmd/lima-driver-vz/main.go | 3 +-- cmd/lima-driver-wsl2/main.go | 5 ++--- cmd/limactl/main.go | 1 - cmd/limactl/main_darwin.go | 4 ++-- cmd/limactl/main_qemu.go | 9 +++++++++ cmd/limactl/main_windows.go | 2 +- pkg/driver/qemu/register.go | 2 ++ pkg/driver/vz/register.go | 2 +- pkg/driver/wsl2/register.go | 2 +- pkg/registry/registry.go | 10 +++++----- 12 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 cmd/limactl/main_qemu.go diff --git a/Makefile b/Makefile index c9da565c716..6069ef39b0a 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,7 @@ binaries: limactl helpers guestagents \ ################################################################################ # _output/bin .PHONY: limactl lima helpers -limactl: _output/bin/limactl$(exe) lima +limactl: _output/bin/limactl$(exe) external-drivers lima ### Listing Dependencies @@ -241,18 +241,46 @@ endif # calls the native resolver library and not the simplistic version in the Go library. ENVS__output/bin/limactl$(exe) = CGO_ENABLED=1 GOOS="$(GOOS)" GOARCH="$(GOARCH)" CC="$(CC)" +LIMACTL_DRIVER_TAGS := +ifneq (,$(findstring vz,$(EXTERNAL_DRIVERS))) +LIMACTL_DRIVER_TAGS += external_vz +endif +ifneq (,$(findstring qemu,$(EXTERNAL_DRIVERS))) +LIMACTL_DRIVER_TAGS += external_qemu +endif +ifneq (,$(findstring wsl2,$(EXTERNAL_DRIVERS))) +LIMACTL_DRIVER_TAGS += external_wsl2 +endif + +GO_BUILDTAGS ?= +GO_BUILDTAGS_LIMACTL := $(strip $(GO_BUILDTAGS) $(LIMACTL_DRIVER_TAGS)) + _output/bin/limactl$(exe): $(LIMACTL_DEPS) $$(call force_build,$$@) -# If the previous cross-compilation was for GOOS=windows, limactl.exe might still be present. ifneq ($(GOOS),windows) # @rm -rf _output/bin/limactl.exe else @rm -rf _output/bin/limactl endif - $(ENVS_$@) $(GO_BUILD) -o $@ ./cmd/limactl + $(ENVS_$@) $(GO_BUILD) -tags '$(GO_BUILDTAGS_LIMACTL)' -o $@ ./cmd/limactl ifeq ($(GOOS),darwin) codesign -f -v --entitlements vz.entitlements -s - $@ endif +DRIVER_INSTALL_DIR := _output/libexec/lima + +.PHONY: external-drivers +external-drivers: +ifneq ($(EXTERNAL_DRIVERS),) + @mkdir -p $(DRIVER_INSTALL_DIR) + @for drv in $(EXTERNAL_DRIVERS); do \ + echo "Building $$drv as external"; \ + $(GO_BUILD) -o $(DRIVER_INSTALL_DIR)/lima-driver-$$drv ./cmd/lima-driver-$$drv; \ + if [ "$$drv" = "vz" ]; then \ + codesign -f -v --entitlements vz.entitlements -s - $(DRIVER_INSTALL_DIR)/lima-driver-vz; \ + fi; \ + done +endif + LIMA_CMDS = $(sort lima lima$(bat)) # $(sort ...) deduplicates the list LIMA_DEPS = $(addprefix _output/bin/,$(LIMA_CMDS)) lima: $(LIMA_DEPS) diff --git a/cmd/lima-driver-qemu/main.go b/cmd/lima-driver-qemu/main.go index 1d78c86e072..e7ef0e7713e 100644 --- a/cmd/lima-driver-qemu/main.go +++ b/cmd/lima-driver-qemu/main.go @@ -10,6 +10,5 @@ import ( // To be used as an external driver for Lima. func main() { - driver := qemu.New() - server.Serve(driver) + server.Serve(qemu.New()) } diff --git a/cmd/lima-driver-vz/main.go b/cmd/lima-driver-vz/main.go index fc0ae38132e..6717429e838 100644 --- a/cmd/lima-driver-vz/main.go +++ b/cmd/lima-driver-vz/main.go @@ -12,6 +12,5 @@ import ( // To be used as an external driver for Lima. func main() { - driver := vz.New() - server.Serve(driver) + server.Serve(vz.New()) } diff --git a/cmd/lima-driver-wsl2/main.go b/cmd/lima-driver-wsl2/main.go index 73ecfd570b5..9b1328e7efb 100644 --- a/cmd/lima-driver-wsl2/main.go +++ b/cmd/lima-driver-wsl2/main.go @@ -1,4 +1,4 @@ -//go:build windows && !no_wsl +//go:build windows // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 @@ -12,6 +12,5 @@ import ( // To be used as an external driver for Lima. func main() { - driver := wsl2.New() - server.Serve(driver) + server.Serve(wsl2.New()) } diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index 85e54753d45..ccf69f70273 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -17,7 +17,6 @@ import ( "github.com/lima-vm/lima/pkg/debugutil" "github.com/lima-vm/lima/pkg/driver/external/server" - _ "github.com/lima-vm/lima/pkg/driver/qemu" // register qemu driver for all platforms "github.com/lima-vm/lima/pkg/fsutil" "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/store/dirnames" diff --git a/cmd/limactl/main_darwin.go b/cmd/limactl/main_darwin.go index b933ed98b85..013961969ec 100644 --- a/cmd/limactl/main_darwin.go +++ b/cmd/limactl/main_darwin.go @@ -1,4 +1,4 @@ -//go:build darwin && !no_vz +//go:build !external_vz // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 @@ -6,4 +6,4 @@ package main // Import vz driver to register it in the registry on darwin. -// import _ "github.com/lima-vm/lima/pkg/driver/vz" +import _ "github.com/lima-vm/lima/pkg/driver/vz" diff --git a/cmd/limactl/main_qemu.go b/cmd/limactl/main_qemu.go new file mode 100644 index 00000000000..ae2dab08f10 --- /dev/null +++ b/cmd/limactl/main_qemu.go @@ -0,0 +1,9 @@ +//go:build !external_qemu + +// SPDX-FileCopyrightText: Copyright The Lima Authors +// SPDX-License-Identifier: Apache-2.0 + +package main + +// Import qemu driver to register it in the registry on all platforms. +import _ "github.com/lima-vm/lima/pkg/driver/qemu" diff --git a/cmd/limactl/main_windows.go b/cmd/limactl/main_windows.go index 871029c8a4f..698362e082b 100644 --- a/cmd/limactl/main_windows.go +++ b/cmd/limactl/main_windows.go @@ -1,4 +1,4 @@ -//go:build windows && !no_wsl +//go:build !external_wsl2 // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/driver/qemu/register.go b/pkg/driver/qemu/register.go index c1a563db574..2c4a319004e 100644 --- a/pkg/driver/qemu/register.go +++ b/pkg/driver/qemu/register.go @@ -1,3 +1,5 @@ +//go:build !external_qemu + // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/driver/vz/register.go b/pkg/driver/vz/register.go index ffdde812bbc..4ab7d594cd8 100644 --- a/pkg/driver/vz/register.go +++ b/pkg/driver/vz/register.go @@ -1,4 +1,4 @@ -//go:build darwin && !no_vz +//go:build darwin && !external_vz // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/driver/wsl2/register.go b/pkg/driver/wsl2/register.go index 377e1beea63..ca5c3fa25f8 100644 --- a/pkg/driver/wsl2/register.go +++ b/pkg/driver/wsl2/register.go @@ -1,4 +1,4 @@ -//go:build windows && !no_wsl +//go:build windows && !external_wsl2 // SPDX-FileCopyrightText: Copyright The Lima Authors // SPDX-License-Identifier: Apache-2.0 diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 838b9772b99..479d68e2fe3 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -70,7 +70,7 @@ func registerExternalDriver(name, path string) { } if _, exists := internalDrivers[name]; exists { - logrus.Warnf("Driver %q is already registered as an internal driver, skipping external registration", name) + logrus.Debugf("Driver %q is already registered as an internal driver, skipping external registration", name) return } @@ -88,10 +88,10 @@ func discoverDrivers() error { } stdDriverDir := filepath.Join(prefix, "libexec", "lima") - logrus.Infof("Discovering drivers in %s", stdDriverDir) + logrus.Debugf("Discovering external drivers in %s", stdDriverDir) if _, err := os.Stat(stdDriverDir); err == nil { if err := discoverDriversInDir(stdDriverDir); err != nil { - logrus.Warnf("Error discovering drivers in %q: %v", stdDriverDir, err) + logrus.Warnf("Error discovering external drivers in %q: %v", stdDriverDir, err) } } @@ -104,13 +104,13 @@ func discoverDrivers() error { info, err := os.Stat(path) if err != nil { - logrus.Warnf("Error accessing driver path %q: %v", path, err) + logrus.Warnf("Error accessing external driver path %q: %v", path, err) continue } if info.IsDir() { if err := discoverDriversInDir(path); err != nil { - logrus.Warnf("Error discovering drivers in %q: %v", path, err) + logrus.Warnf("Error discovering external drivers in %q: %v", path, err) } } else if isExecutable(info.Mode()) { registerDriverFile(path) From 53e7cd1856cd9aa8a694932f5dd6bdfd2b99904c Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Wed, 25 Jun 2025 18:13:41 +0530 Subject: [PATCH 47/49] driver(registry): avoid parenthesized info while listing drivers Signed-off-by: Ansuman Sahoo --- cmd/limactl/start.go | 6 +----- pkg/limainfo/limainfo.go | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cmd/limactl/start.go b/cmd/limactl/start.go index 63ebfec723e..476f29e4c72 100644 --- a/cmd/limactl/start.go +++ b/cmd/limactl/start.go @@ -400,11 +400,7 @@ func createStartActionCommon(cmd *cobra.Command, _ []string) (exit bool, err err return true, err } else if listDrivers { w := cmd.OutOrStdout() - for k, v := range registry.List() { - if v != "internal" { - _, _ = fmt.Fprintln(w, k+"(external)") - continue - } + for k := range registry.List() { _, _ = fmt.Fprintln(w, k) } return true, nil diff --git a/pkg/limainfo/limainfo.go b/pkg/limainfo/limainfo.go index 7de30ad7816..5ad8fd59cf7 100644 --- a/pkg/limainfo/limainfo.go +++ b/pkg/limainfo/limainfo.go @@ -22,10 +22,14 @@ type LimaInfo struct { Templates []templatestore.Template `json:"templates"` DefaultTemplate *limayaml.LimaYAML `json:"defaultTemplate"` LimaHome string `json:"limaHome"` - VMTypes map[string]string `json:"vmTypes"` // since Lima v0.14.2 + VMTypes []string `json:"vmTypes"` // since Lima v0.14.2 + VMTypesEx map[string]DriverExt `json:"vmTypesEx"` GuestAgents map[limayaml.Arch]GuestAgent `json:"guestAgents"` // since Lima v1.1.0 } +type DriverExt struct { + Location string `json:"location"` +} type GuestAgent struct { Location string `json:"location"` // since Lima v1.1.0 } @@ -42,10 +46,24 @@ func New() (*LimaInfo, error) { if err != nil { return nil, err } + + reg := registry.List() + if len(reg) == 0 { + return nil, errors.New("no VM types found; ensure that the drivers are properly registered") + } + var vmTypesEx = make(map[string]DriverExt) + var vmTypes []string + for name, path := range reg { + vmTypesEx[name] = DriverExt{ + Location: path, + } + vmTypes = append(vmTypes, name) + } info := &LimaInfo{ Version: version.Version, DefaultTemplate: y, - VMTypes: registry.List(), + VMTypes: vmTypes, + VMTypesEx: vmTypesEx, GuestAgents: make(map[limayaml.Arch]GuestAgent), } info.Templates, err = templatestore.Templates() From bcb71ca7a3b9d9724fe0e753e8bf2d085ef85812 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 27 Jun 2025 01:14:32 +0530 Subject: [PATCH 48/49] refactor(image-downloader): move code to limactl from vz & qemu Signed-off-by: Ansuman Sahoo --- pkg/driver/external/server/server.go | 6 ++--- pkg/driver/qemu/qemu.go | 37 +------------------------- pkg/driver/vz/disk.go | 39 +--------------------------- pkg/driverutil/instance.go | 2 +- pkg/instance/start.go | 37 ++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 79 deletions(-) diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index b81e7597e82..6dbc065ae69 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -167,7 +167,7 @@ func Stop(extDriver *registry.ExternalDriver) error { return fmt.Errorf("external driver %s is not running", extDriver.Name) } - extDriver.Logger.Infof("Stopping external driver %s", extDriver.Name) + extDriver.Logger.Debugf("Stopping external driver %s", extDriver.Name) if extDriver.CancelFunc != nil { extDriver.CancelFunc() } @@ -180,7 +180,7 @@ func Stop(extDriver *registry.ExternalDriver) error { extDriver.Ctx = nil extDriver.CancelFunc = nil - extDriver.Logger.Infof("External driver %s stopped successfully", extDriver.Name) + extDriver.Logger.Debugf("External driver %s stopped successfully", extDriver.Name) return nil } @@ -189,8 +189,6 @@ func StopAllExternalDrivers() { if driver.Command != nil && driver.Command.Process != nil { if err := Stop(driver); err != nil { logrus.Errorf("Failed to stop external driver %s: %v", name, err) - } else { - logrus.Infof("External driver %s stopped successfully", name) } } delete(registry.ExternalDrivers, name) diff --git a/pkg/driver/qemu/qemu.go b/pkg/driver/qemu/qemu.go index 44360a4eda9..7f447d64bd9 100644 --- a/pkg/driver/qemu/qemu.go +++ b/pkg/driver/qemu/qemu.go @@ -94,42 +94,7 @@ func EnsureDisk(ctx context.Context, cfg Config) error { } baseDisk := filepath.Join(cfg.InstanceDir, filenames.BaseDisk) - kernel := filepath.Join(cfg.InstanceDir, filenames.Kernel) - kernelCmdline := filepath.Join(cfg.InstanceDir, filenames.KernelCmdline) - initrd := filepath.Join(cfg.InstanceDir, filenames.Initrd) - if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) { - var ensuredBaseDisk bool - errs := make([]error, len(cfg.LimaYAML.Images)) - for i, f := range cfg.LimaYAML.Images { - if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *cfg.LimaYAML.Arch); err != nil { - errs[i] = err - continue - } - if f.Kernel != nil { - if _, err := fileutils.DownloadFile(ctx, kernel, f.Kernel.File, false, "the kernel", *cfg.LimaYAML.Arch); err != nil { - errs[i] = err - continue - } - if f.Kernel.Cmdline != "" { - if err := os.WriteFile(kernelCmdline, []byte(f.Kernel.Cmdline), 0o644); err != nil { - errs[i] = err - continue - } - } - } - if f.Initrd != nil { - if _, err := fileutils.DownloadFile(ctx, initrd, *f.Initrd, false, "the initrd", *cfg.LimaYAML.Arch); err != nil { - errs[i] = err - continue - } - } - ensuredBaseDisk = true - break - } - if !ensuredBaseDisk { - return fileutils.Errors(errs) - } - } + diskSize, _ := units.RAMInBytes(*cfg.LimaYAML.Disk) if diskSize == 0 { return nil diff --git a/pkg/driver/vz/disk.go b/pkg/driver/vz/disk.go index 509b5ba67ca..a6fef596060 100644 --- a/pkg/driver/vz/disk.go +++ b/pkg/driver/vz/disk.go @@ -11,7 +11,6 @@ import ( "path/filepath" "github.com/docker/go-units" - "github.com/lima-vm/lima/pkg/fileutils" "github.com/lima-vm/lima/pkg/imgutil/proxyimgutil" "github.com/lima-vm/lima/pkg/iso9660util" "github.com/lima-vm/lima/pkg/store" @@ -28,43 +27,7 @@ func EnsureDisk(ctx context.Context, inst *store.Instance) error { diskUtil := proxyimgutil.NewDiskUtil() baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk) - kernel := filepath.Join(inst.Dir, filenames.Kernel) - kernelCmdline := filepath.Join(inst.Dir, filenames.KernelCmdline) - initrd := filepath.Join(inst.Dir, filenames.Initrd) - if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) { - var ensuredBaseDisk bool - errs := make([]error, len(inst.Config.Images)) - for i, f := range inst.Config.Images { - if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *inst.Config.Arch); err != nil { - errs[i] = err - continue - } - if f.Kernel != nil { - // ensure decompress kernel because vz expects it to be decompressed - if _, err := fileutils.DownloadFile(ctx, kernel, f.Kernel.File, true, "the kernel", *inst.Config.Arch); err != nil { - errs[i] = err - continue - } - if f.Kernel.Cmdline != "" { - if err := os.WriteFile(kernelCmdline, []byte(f.Kernel.Cmdline), 0o644); err != nil { - errs[i] = err - continue - } - } - } - if f.Initrd != nil { - if _, err := fileutils.DownloadFile(ctx, initrd, *f.Initrd, false, "the initrd", *inst.Config.Arch); err != nil { - errs[i] = err - continue - } - } - ensuredBaseDisk = true - break - } - if !ensuredBaseDisk { - return fileutils.Errors(errs) - } - } + diskSize, _ := units.RAMInBytes(*inst.Config.Disk) if diskSize == 0 { return nil diff --git a/pkg/driverutil/instance.go b/pkg/driverutil/instance.go index 387dab664b6..c6c959a79f7 100644 --- a/pkg/driverutil/instance.go +++ b/pkg/driverutil/instance.go @@ -30,7 +30,7 @@ func CreateConfiguredDriver(inst *store.Instance, sshLocalPort int) (*driver.Con return nil, err } } else { - logrus.Infof("Reusing existing external driver %q instance", extDriver.Name) + logrus.Debugf("Reusing existing external driver %q instance", extDriver.Name) extDriver.InstanceName = inst.Name } diff --git a/pkg/instance/start.go b/pkg/instance/start.go index e6f1d54fbcb..24e997fdb70 100644 --- a/pkg/instance/start.go +++ b/pkg/instance/start.go @@ -108,6 +108,43 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { _, err = os.Stat(baseDisk) created := err == nil + kernel := filepath.Join(inst.Dir, filenames.Kernel) + kernelCmdline := filepath.Join(inst.Dir, filenames.KernelCmdline) + initrd := filepath.Join(inst.Dir, filenames.Initrd) + if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) { + var ensuredBaseDisk bool + errs := make([]error, len(inst.Config.Images)) + for i, f := range inst.Config.Images { + if _, err := fileutils.DownloadFile(ctx, baseDisk, f.File, true, "the image", *inst.Config.Arch); err != nil { + errs[i] = err + continue + } + if f.Kernel != nil { + if _, err := fileutils.DownloadFile(ctx, kernel, f.Kernel.File, false, "the kernel", *inst.Config.Arch); err != nil { + errs[i] = err + continue + } + if f.Kernel.Cmdline != "" { + if err := os.WriteFile(kernelCmdline, []byte(f.Kernel.Cmdline), 0o644); err != nil { + errs[i] = err + continue + } + } + } + if f.Initrd != nil { + if _, err := fileutils.DownloadFile(ctx, initrd, *f.Initrd, false, "the initrd", *inst.Config.Arch); err != nil { + errs[i] = err + continue + } + } + ensuredBaseDisk = true + break + } + if !ensuredBaseDisk { + return nil, fileutils.Errors(errs) + } + } + if err := limaDriver.CreateDisk(ctx); err != nil { return nil, err } From ca8867e5b20a35549ae0df104ef70b986f5011f5 Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Fri, 27 Jun 2025 01:15:54 +0530 Subject: [PATCH 49/49] driver(build): limactl should not depend on additional-drivers target Signed-off-by: Ansuman Sahoo --- Makefile | 16 +++++++--------- pkg/driver/qemu/qemu.go | 1 - pkg/imgutil/proxyimgutil/proxyimgutil.go | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 6069ef39b0a..6a7739505a4 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,7 @@ binaries: limactl helpers guestagents \ ################################################################################ # _output/bin .PHONY: limactl lima helpers -limactl: _output/bin/limactl$(exe) external-drivers lima +limactl: _output/bin/limactl$(exe) lima ### Listing Dependencies @@ -242,13 +242,13 @@ endif ENVS__output/bin/limactl$(exe) = CGO_ENABLED=1 GOOS="$(GOOS)" GOARCH="$(GOARCH)" CC="$(CC)" LIMACTL_DRIVER_TAGS := -ifneq (,$(findstring vz,$(EXTERNAL_DRIVERS))) +ifneq (,$(findstring vz,$(ADDITIONAL_DRIVERS))) LIMACTL_DRIVER_TAGS += external_vz endif -ifneq (,$(findstring qemu,$(EXTERNAL_DRIVERS))) +ifneq (,$(findstring qemu,$(ADDITIONAL_DRIVERS))) LIMACTL_DRIVER_TAGS += external_qemu endif -ifneq (,$(findstring wsl2,$(EXTERNAL_DRIVERS))) +ifneq (,$(findstring wsl2,$(ADDITIONAL_DRIVERS))) LIMACTL_DRIVER_TAGS += external_wsl2 endif @@ -268,18 +268,16 @@ endif DRIVER_INSTALL_DIR := _output/libexec/lima -.PHONY: external-drivers -external-drivers: -ifneq ($(EXTERNAL_DRIVERS),) +.PHONY: additional-drivers +additional-drivers: @mkdir -p $(DRIVER_INSTALL_DIR) - @for drv in $(EXTERNAL_DRIVERS); do \ + @for drv in $(ADDITIONAL_DRIVERS); do \ echo "Building $$drv as external"; \ $(GO_BUILD) -o $(DRIVER_INSTALL_DIR)/lima-driver-$$drv ./cmd/lima-driver-$$drv; \ if [ "$$drv" = "vz" ]; then \ codesign -f -v --entitlements vz.entitlements -s - $(DRIVER_INSTALL_DIR)/lima-driver-vz; \ fi; \ done -endif LIMA_CMDS = $(sort lima lima$(bat)) # $(sort ...) deduplicates the list LIMA_DEPS = $(addprefix _output/bin/,$(LIMA_CMDS)) diff --git a/pkg/driver/qemu/qemu.go b/pkg/driver/qemu/qemu.go index 7f447d64bd9..707299e65f3 100644 --- a/pkg/driver/qemu/qemu.go +++ b/pkg/driver/qemu/qemu.go @@ -28,7 +28,6 @@ import ( "github.com/sirupsen/logrus" "github.com/lima-vm/lima/pkg/fileutils" - "github.com/lima-vm/lima/pkg/imgutil/qemuimgutil" "github.com/lima-vm/lima/pkg/iso9660util" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/networks" diff --git a/pkg/imgutil/proxyimgutil/proxyimgutil.go b/pkg/imgutil/proxyimgutil/proxyimgutil.go index 7ff88abcef0..0c56ca82a45 100644 --- a/pkg/imgutil/proxyimgutil/proxyimgutil.go +++ b/pkg/imgutil/proxyimgutil/proxyimgutil.go @@ -10,7 +10,7 @@ import ( "github.com/lima-vm/lima/pkg/imgutil" "github.com/lima-vm/lima/pkg/imgutil/nativeimgutil" - "github.com/lima-vm/lima/pkg/imgutil/qemuimgutil" + "github.com/lima-vm/lima/pkg/qemuimgutil" ) // ImageDiskManager is a proxy implementation of imgutil.ImageDiskManager that uses both QEMU and native image utilities.