Skip to content

Commit 96ba8a8

Browse files
committed
Restore guest agent unix socket functionality
Make both vsock and virtio explicit, instead of hardcoding internal filenames in the agents. Fallback to to the unix. Signed-off-by: Anders F Björklund <[email protected]>
1 parent bfd7471 commit 96ba8a8

File tree

8 files changed

+81
-18
lines changed

8 files changed

+81
-18
lines changed

cmd/lima-guestagent/daemon_linux.go

+22-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/lima-vm/lima/pkg/guestagent"
1212
"github.com/lima-vm/lima/pkg/guestagent/api/server"
1313
"github.com/lima-vm/lima/pkg/guestagent/serialport"
14-
"github.com/lima-vm/lima/pkg/store/filenames"
1514
"github.com/mdlayher/vsock"
1615
"github.com/sirupsen/logrus"
1716
"github.com/spf13/cobra"
@@ -25,21 +24,23 @@ func newDaemonCommand() *cobra.Command {
2524
}
2625
daemonCommand.Flags().Duration("tick", 3*time.Second, "tick for polling events")
2726
daemonCommand.Flags().Int("vsock-port", 0, "use vsock server instead a UNIX socket")
27+
daemonCommand.Flags().String("virtio-port", "", "use virtio server instead a UNIX socket")
2828
return daemonCommand
2929
}
3030

3131
func daemonAction(cmd *cobra.Command, _ []string) error {
32+
socket := "/run/lima-guestagent.sock"
3233
tick, err := cmd.Flags().GetDuration("tick")
3334
if err != nil {
3435
return err
3536
}
36-
vSockPortOverride, err := cmd.Flags().GetInt("vsock-port")
37+
vSockPort, err := cmd.Flags().GetInt("vsock-port")
3738
if err != nil {
3839
return err
3940
}
40-
vSockPort := 0
41-
if vSockPortOverride != 0 {
42-
vSockPort = vSockPortOverride
41+
virtioPort, err := cmd.Flags().GetString("virtio-port")
42+
if err != nil {
43+
return err
4344
}
4445
if tick == 0 {
4546
return errors.New("tick must be specified")
@@ -67,11 +68,14 @@ func daemonAction(cmd *cobra.Command, _ []string) error {
6768
r := mux.NewRouter()
6869
server.AddRoutes(r, backend)
6970
srv := &http.Server{Handler: r}
71+
err = os.RemoveAll(socket)
72+
if err != nil {
73+
return err
74+
}
7075

7176
var l net.Listener
72-
virtioPort := "/dev/virtio-ports/" + filenames.VirtioPort
73-
if _, err := os.Stat(virtioPort); err == nil {
74-
qemuL, err := serialport.Listen(virtioPort)
77+
if virtioPort != "" {
78+
qemuL, err := serialport.Listen("/dev/virtio-ports/" + virtioPort)
7579
if err != nil {
7680
return err
7781
}
@@ -84,6 +88,16 @@ func daemonAction(cmd *cobra.Command, _ []string) error {
8488
}
8589
l = vsockL
8690
logrus.Infof("serving the guest agent on vsock port: %d", vSockPort)
91+
} else {
92+
socketL, err := net.Listen("unix", socket)
93+
if err != nil {
94+
return err
95+
}
96+
if err := os.Chmod(socket, 0o777); err != nil {
97+
return err
98+
}
99+
l = socketL
100+
logrus.Infof("serving the guest agent on %q", socket)
87101
}
88102
return srv.Serve(l)
89103
}

pkg/cidata/cidata.TEMPLATE.d/boot/25-guestagent-base.sh

+8-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ name="lima-guestagent"
2828
description="Forward ports to the lima-hostagent"
2929
3030
command=${LIMA_CIDATA_GUEST_INSTALL_PREFIX}/bin/lima-guestagent
31-
command_args="daemon --vsock-port "${LIMA_CIDATA_VSOCK_PORT}""
31+
command_args="daemon --vsock-port "${LIMA_CIDATA_VSOCK_PORT}" --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}""
3232
command_background=true
3333
pidfile="/run/lima-guestagent.pid"
3434
EOF
@@ -40,5 +40,11 @@ else
4040
# Remove legacy systemd service
4141
rm -f "${LIMA_CIDATA_HOME}/.config/systemd/user/lima-guestagent.service"
4242

43-
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}"
43+
if [ "${LIMA_CIDATA_VSOCK_PORT}" != "0" ]; then
44+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}"
45+
elif [ "${LIMA_CIDATA_VIRTIO_PORT}" != "" ]; then
46+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}"
47+
else
48+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd
49+
fi
4450
fi

pkg/cidata/cidata.TEMPLATE.d/lima.env

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ LIMA_CIDATA_SKIP_DEFAULT_DEPENDENCY_RESOLUTION=
4141
{{- end}}
4242
LIMA_CIDATA_VMTYPE={{ .VMType }}
4343
LIMA_CIDATA_VSOCK_PORT={{ .VSockPort }}
44+
LIMA_CIDATA_VIRTIO_PORT={{ .VirtioPort}}
4445
{{- if .Plain}}
4546
LIMA_CIDATA_PLAIN=1
4647
{{- else}}

pkg/cidata/cidata.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func setupEnv(y *limayaml.LimaYAML, args TemplateArgs) (map[string]string, error
110110
return env, nil
111111
}
112112

113-
func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, nerdctlArchive string, vsockPort int) error {
113+
func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, nerdctlArchive string, vsockPort int, virtioPort string) error {
114114
if err := limayaml.Validate(*y, false); err != nil {
115115
return err
116116
}
@@ -135,6 +135,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort
135135
RosettaBinFmt: *y.Rosetta.BinFmt,
136136
VMType: *y.VMType,
137137
VSockPort: vsockPort,
138+
VirtioPort: virtioPort,
138139
Plain: *y.Plain,
139140
}
140141

pkg/cidata/template.go

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ type TemplateArgs struct {
8181
SkipDefaultDependencyResolution bool
8282
VMType string
8383
VSockPort int
84+
VirtioPort string
8485
Plain bool
8586
}
8687

pkg/driver/driver.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ type Driver interface {
6464

6565
ListSnapshots(_ context.Context) (string, error)
6666

67+
// ForwardGuestAgent returns if the guest agent sock needs forwarding by host agent.
68+
ForwardGuestAgent() bool
69+
70+
// GuestAgentConn returns the guest agent connection, or nil (if forwarded by ssh).
6771
GuestAgentConn(_ context.Context) (net.Conn, error)
6872
}
6973

@@ -73,6 +77,7 @@ type BaseDriver struct {
7377

7478
SSHLocalPort int
7579
VSockPort int
80+
VirtioPort string
7681
}
7782

7883
var _ Driver = (*BaseDriver)(nil)
@@ -137,6 +142,12 @@ func (d *BaseDriver) ListSnapshots(_ context.Context) (string, error) {
137142
return "", fmt.Errorf("unimplemented")
138143
}
139144

145+
func (d *BaseDriver) ForwardGuestAgent() bool {
146+
// if driver is not providing, use host agent
147+
return d.VSockPort == 0 && d.VirtioPort == ""
148+
}
149+
140150
func (d *BaseDriver) GuestAgentConn(_ context.Context) (net.Conn, error) {
141-
return nil, fmt.Errorf("unimplemented")
151+
// use the unix socket forwarded by host agent
152+
return nil, nil
142153
}

pkg/hostagent/hostagent.go

+32-5
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ type HostAgent struct {
5353
eventEnc *json.Encoder
5454
eventEncMu sync.Mutex
5555

56-
vSockPort int
56+
vSockPort int
57+
virtioPort string
5758

5859
clientMu sync.RWMutex
5960
client guestagentclient.GuestAgentClient
@@ -117,6 +118,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
117118
}
118119

119120
vSockPort := 0
121+
virtioPort := ""
120122
if *y.VMType == limayaml.VZ {
121123
vSockPort = 2222
122124
} else if *y.VMType == limayaml.WSL2 {
@@ -125,9 +127,11 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
125127
logrus.WithError(err).Error("failed to get free VSock port")
126128
}
127129
vSockPort = port
130+
} else if *y.VMType == limayaml.QEMU {
131+
virtioPort = filenames.VirtioPort
128132
}
129133

130-
if err := cidata.GenerateISO9660(inst.Dir, instName, y, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort); err != nil {
134+
if err := cidata.GenerateISO9660(inst.Dir, instName, y, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort, virtioPort); err != nil {
131135
return nil, err
132136
}
133137

@@ -160,6 +164,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
160164
Yaml: y,
161165
SSHLocalPort: sshLocalPort,
162166
VSockPort: vSockPort,
167+
VirtioPort: virtioPort,
163168
})
164169

165170
a := &HostAgent{
@@ -176,6 +181,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
176181
sigintCh: sigintCh,
177182
eventEnc: json.NewEncoder(stdout),
178183
vSockPort: vSockPort,
184+
virtioPort: virtioPort,
179185
guestAgentAliveCh: make(chan struct{}),
180186
}
181187
return a, nil
@@ -548,8 +554,6 @@ func (a *HostAgent) close() error {
548554
}
549555

550556
func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
551-
// TODO: use vSock (when QEMU for macOS gets support for vSock)
552-
553557
// Setup all socket forwards and defer their teardown
554558
if *a.y.VMType != limayaml.WSL2 {
555559
logrus.Debugf("Forwarding unix sockets")
@@ -561,6 +565,9 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
561565
}
562566
}
563567

568+
localUnix := filepath.Join(a.instDir, filenames.GuestAgentSock)
569+
remoteUnix := "/run/lima-guestagent.sock"
570+
564571
a.onClose = append(a.onClose, func() error {
565572
logrus.Debugf("Stop forwarding unix sockets")
566573
var errs []error
@@ -573,9 +580,19 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
573580
}
574581
}
575582
}
583+
if a.driver.ForwardGuestAgent() {
584+
if err := forwardSSH(context.Background(), a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbCancel, false); err != nil {
585+
errs = append(errs, err)
586+
}
587+
}
576588
return errors.Join(errs...)
577589
})
578590
for {
591+
if a.client == nil || !isGuestAgentSocketAccessible(ctx, a.client) {
592+
if a.driver.ForwardGuestAgent() {
593+
_ = forwardSSH(ctx, a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbForward, false)
594+
}
595+
}
579596
client, err := a.getOrCreateClient(ctx)
580597
if err == nil {
581598
if err := a.processGuestAgentEvents(ctx, client); err != nil {
@@ -610,8 +627,18 @@ func (a *HostAgent) getOrCreateClient(ctx context.Context) (guestagentclient.Gue
610627
return a.client, err
611628
}
612629

613-
func (a *HostAgent) createClient(ctx context.Context) (guestagentclient.GuestAgentClient, error) {
630+
func (a *HostAgent) createConnection(ctx context.Context) (net.Conn, error) {
614631
conn, err := a.driver.GuestAgentConn(ctx)
632+
// default to forwarded sock
633+
if conn == nil && err == nil {
634+
var d net.Dialer
635+
conn, err = d.DialContext(ctx, "unix", filepath.Join(a.instDir, filenames.GuestAgentSock))
636+
}
637+
return conn, err
638+
}
639+
640+
func (a *HostAgent) createClient(ctx context.Context) (guestagentclient.GuestAgentClient, error) {
641+
conn, err := a.createConnection(ctx)
615642
if err != nil {
616643
return nil, err
617644
}

website/content/en/docs/dev/Internals/_index.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ VNC:
7272

7373
Guest agent:
7474

75-
Each drivers use their own mode of communication
75+
Each drivers use their own mode of communication
7676
- `qemu`: uses virtio-port `io.lima-vm.guest_agent.0`
7777
- `vz`: uses vsock port 2222
7878
- `wsl2`: uses free random vsock port
79+
The fallback is to use port forward over ssh port
80+
- `ga.sock`: Forwarded to `/run/lima-guestagent.sock` in the guest, via SSH
7981

8082
Host agent:
8183
- `ha.pid`: hostagent PID

0 commit comments

Comments
 (0)