diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 248e76bd882..2501a78303c 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -14,6 +14,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strconv" "strings" "sync" @@ -127,15 +128,52 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt virtioPort := "" if *inst.Config.VMType == limayaml.VZ { vSockPort = 2222 + if inst.Config.GuestAgentTransportType != nil { + switch *inst.Config.GuestAgentTransportType { + case limayaml.VSOCKGA: + case limayaml.HOSTAGENTGA: + vSockPort = 0 + default: + logrus.Warnf("Ignoring invalid for %s type GA transport %s", *inst.Config.VMType, *inst.Config.GuestAgentTransportType) + } + } } else if *inst.Config.VMType == limayaml.WSL2 { port, err := freeport.VSock() if err != nil { logrus.WithError(err).Error("failed to get free VSock port") } vSockPort = port + if inst.Config.GuestAgentTransportType != nil { + switch *inst.Config.GuestAgentTransportType { + case limayaml.VSOCKGA: + // TODO support hostagent forwarder https://github.com/lima-vm/lima/issues/3386 + default: + logrus.Warnf("Ignoring invalid for %s type GA transport %s", *inst.Config.VMType, *inst.Config.GuestAgentTransportType) + } + } } else if *inst.Config.VMType == limayaml.QEMU { - // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 - virtioPort = "" // filenames.VirtioPort + if runtime.GOOS != "windows" { + // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 + virtioPort = "" + } else { + // On Windows it is a more reasonable default + virtioPort = filenames.VirtioPort + } + if inst.Config.GuestAgentTransportType != nil { + switch *inst.Config.GuestAgentTransportType { + case limayaml.VIRTIOGA: + virtioPort = filenames.VirtioPort + case limayaml.HOSTAGENTGA: + if runtime.GOOS != "windows" { + virtioPort = "" + } else { + // TODO support hostagent forwarder https://github.com/lima-vm/lima/issues/3386 + logrus.Warnf("Ignoring invalid for %s type GA transport %s", *inst.Config.VMType, *inst.Config.GuestAgentTransportType) + } + default: + logrus.Warnf("Ignoring invalid for %s type GA transport %s", *inst.Config.VMType, *inst.Config.GuestAgentTransportType) + } + } } if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { diff --git a/pkg/limayaml/limayaml.go b/pkg/limayaml/limayaml.go index b954063c06c..453eae8bc73 100644 --- a/pkg/limayaml/limayaml.go +++ b/pkg/limayaml/limayaml.go @@ -45,13 +45,14 @@ type LimaYAML struct { DNS []net.IP `yaml:"dns,omitempty" json:"dns,omitempty"` HostResolver HostResolver `yaml:"hostResolver,omitempty" json:"hostResolver,omitempty"` // `useHostResolver` was deprecated in Lima v0.8.1, removed in Lima v0.14.0. Use `hostResolver.enabled` instead. - PropagateProxyEnv *bool `yaml:"propagateProxyEnv,omitempty" json:"propagateProxyEnv,omitempty" jsonschema:"nullable"` - CACertificates CACertificates `yaml:"caCerts,omitempty" json:"caCerts,omitempty"` - Rosetta Rosetta `yaml:"rosetta,omitempty" json:"rosetta,omitempty"` - Plain *bool `yaml:"plain,omitempty" json:"plain,omitempty" jsonschema:"nullable"` - TimeZone *string `yaml:"timezone,omitempty" json:"timezone,omitempty" jsonschema:"nullable"` - NestedVirtualization *bool `yaml:"nestedVirtualization,omitempty" json:"nestedVirtualization,omitempty" jsonschema:"nullable"` - User User `yaml:"user,omitempty" json:"user,omitempty"` + PropagateProxyEnv *bool `yaml:"propagateProxyEnv,omitempty" json:"propagateProxyEnv,omitempty" jsonschema:"nullable"` + CACertificates CACertificates `yaml:"caCerts,omitempty" json:"caCerts,omitempty"` + Rosetta Rosetta `yaml:"rosetta,omitempty" json:"rosetta,omitempty"` + GuestAgentTransportType *GATransportType `yaml:"guestAgentTransportType,omitempty" json:"guestAgentTransportType,omitempty" jsonschema:"nullable"` + Plain *bool `yaml:"plain,omitempty" json:"plain,omitempty" jsonschema:"nullable"` + TimeZone *string `yaml:"timezone,omitempty" json:"timezone,omitempty" jsonschema:"nullable"` + NestedVirtualization *bool `yaml:"nestedVirtualization,omitempty" json:"nestedVirtualization,omitempty" jsonschema:"nullable"` + User User `yaml:"user,omitempty" json:"user,omitempty"` } type BaseTemplates []LocatorWithDigest @@ -62,10 +63,11 @@ type LocatorWithDigest struct { } type ( - OS = string - Arch = string - MountType = string - VMType = string + OS = string + Arch = string + MountType = string + VMType = string + GATransportType = string ) type CPUType = map[Arch]string @@ -87,6 +89,10 @@ const ( QEMU VMType = "qemu" VZ VMType = "vz" WSL2 VMType = "wsl2" + + VIRTIOGA GATransportType = "virtio-ga" + VSOCKGA GATransportType = "vsock-ga" + HOSTAGENTGA GATransportType = "hostagent-ga" ) var ( diff --git a/pkg/qemu/qemu.go b/pkg/qemu/qemu.go index f0a92c37a0d..f190bede85d 100644 --- a/pkg/qemu/qemu.go +++ b/pkg/qemu/qemu.go @@ -45,6 +45,7 @@ type Config struct { LimaYAML *limayaml.LimaYAML SSHLocalPort int SSHAddress string + VirtioGA bool } // MinimumQemuVersion is the minimum supported QEMU version. @@ -987,11 +988,13 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er args = append(args, "-chardev", fmt.Sprintf("socket,id=%s,path=%s,server=on,wait=off", qmpChardev, qmpSock)) args = append(args, "-qmp", "chardev:"+qmpChardev) - // Guest agent via serialport - guestSock := filepath.Join(cfg.InstanceDir, filenames.GuestAgentSock) - args = append(args, "-chardev", fmt.Sprintf("socket,path=%s,server=on,wait=off,id=qga0", guestSock)) - args = append(args, "-device", "virtio-serial") - args = append(args, "-device", "virtserialport,chardev=qga0,name="+filenames.VirtioPort) + if cfg.VirtioGA { + // Guest agent via serialport + guestSock := filepath.Join(cfg.InstanceDir, filenames.GuestAgentSock) + args = append(args, "-chardev", fmt.Sprintf("socket,path=%s,server=on,wait=off,id=qga0", guestSock)) + args = append(args, "-device", "virtio-serial") + args = append(args, "-device", "virtserialport,chardev=qga0,name="+filenames.VirtioPort) + } // QEMU process args = append(args, "-name", "lima-"+cfg.Name) diff --git a/pkg/qemu/qemu_driver.go b/pkg/qemu/qemu_driver.go index ec3da5390a6..64e3504d5da 100644 --- a/pkg/qemu/qemu_driver.go +++ b/pkg/qemu/qemu_driver.go @@ -77,6 +77,7 @@ func (l *LimaQemuDriver) Start(ctx context.Context) (chan error, error) { LimaYAML: l.Instance.Config, SSHLocalPort: l.SSHLocalPort, SSHAddress: l.Instance.SSHAddress, + VirtioGA: l.VirtioPort != "", } qExe, qArgs, err := Cmdline(ctx, qCfg) if err != nil { diff --git a/pkg/vz/vz_driver_darwin.go b/pkg/vz/vz_driver_darwin.go index ef50a10af4a..f6a2178a4a6 100644 --- a/pkg/vz/vz_driver_darwin.go +++ b/pkg/vz/vz_driver_darwin.go @@ -20,6 +20,7 @@ import ( "github.com/lima-vm/lima/pkg/driver" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/reflectutil" + "github.com/lima-vm/lima/pkg/store/filenames" ) var knownYamlProperties = []string{ @@ -36,6 +37,7 @@ var knownYamlProperties = []string{ "Env", "Firmware", "GuestInstallPrefix", + "GuestAgentTransportType", "HostResolver", "Images", "Memory", @@ -225,7 +227,12 @@ 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(ctx context.Context) (net.Conn, error) { + if l.VSockPort == 0 { + var d net.Dialer + dialContext, err := d.DialContext(ctx, "unix", filepath.Join(l.Instance.Dir, filenames.GuestAgentSock)) + return dialContext, err + } for _, socket := range l.machine.SocketDevices() { connect, err := socket.Connect(uint32(l.VSockPort)) if err == nil && connect.SourcePort() != 0 { diff --git a/templates/default.yaml b/templates/default.yaml index eac787d7d77..c398e8c6e0b 100644 --- a/templates/default.yaml +++ b/templates/default.yaml @@ -367,6 +367,13 @@ rosetta: # 🟢 Builtin default: false binfmt: null +# Specify communication transport to connect to GuestAgent. +# Supported values are "virtio-ga", "vsock-ga" and "hostagent-ga". +# If selected option will not be supported for VMType and Host OS a Warning will be shown and the +# default mode will be selected. +# 🟢 Builtin default: not set which results in VMType and Host OS specific behavior +guestAgentTransportType: null + # Specify the timezone name (as used by the zoneinfo database). Specify the empty string # to not set a timezone in the instance. # 🟢 Builtin default: use name from /etc/timezone or deduce from symlink target of /etc/localtime