Skip to content

Commit 25b9484

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 f9ea34c commit 25b9484

File tree

9 files changed

+91
-24
lines changed

9 files changed

+91
-24
lines changed

cmd/lima-guestagent/daemon_linux.go

+22-12
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,26 +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

31-
var (
32-
vSockPort = 0
33-
34-
virtioPort = "/dev/virtio-ports/" + filenames.VirtioPort
35-
)
36-
3731
func daemonAction(cmd *cobra.Command, _ []string) error {
32+
socket := "/run/lima-guestagent.sock"
3833
tick, err := cmd.Flags().GetDuration("tick")
3934
if err != nil {
4035
return err
4136
}
42-
vSockPortOverride, err := cmd.Flags().GetInt("vsock-port")
37+
vSockPort, err := cmd.Flags().GetInt("vsock-port")
4338
if err != nil {
4439
return err
4540
}
46-
if vSockPortOverride != 0 {
47-
vSockPort = vSockPortOverride
41+
virtioPort, err := cmd.Flags().GetString("virtio-port")
42+
if err != nil {
43+
return err
4844
}
4945
if tick == 0 {
5046
return errors.New("tick must be specified")
@@ -72,10 +68,14 @@ func daemonAction(cmd *cobra.Command, _ []string) error {
7268
r := mux.NewRouter()
7369
server.AddRoutes(r, backend)
7470
srv := &http.Server{Handler: r}
71+
err = os.RemoveAll(socket)
72+
if err != nil {
73+
return err
74+
}
7575

7676
var l net.Listener
77-
if _, err := os.Stat(virtioPort); err == nil {
78-
qemuL, err := serialport.Listen(virtioPort)
77+
if virtioPort != "" {
78+
qemuL, err := serialport.Listen("/dev/virtio-ports/" + virtioPort)
7979
if err != nil {
8080
return err
8181
}
@@ -88,6 +88,16 @@ func daemonAction(cmd *cobra.Command, _ []string) error {
8888
}
8989
l = vsockL
9090
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)
91101
}
92102
return srv.Serve(l)
93103
}

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

+2-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,5 @@ 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+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}" --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}"
4444
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

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

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

67+
ForwardUnixGuestAgent() bool
68+
6769
GuestAgentConn(_ context.Context) (net.Conn, error)
6870
}
6971

@@ -73,6 +75,7 @@ type BaseDriver struct {
7375

7476
SSHLocalPort int
7577
VSockPort int
78+
VirtioPort string
7679
}
7780

7881
var _ Driver = (*BaseDriver)(nil)
@@ -137,6 +140,10 @@ func (d *BaseDriver) ListSnapshots(_ context.Context) (string, error) {
137140
return "", fmt.Errorf("unimplemented")
138141
}
139142

143+
func (d *BaseDriver) ForwardUnixGuestAgent() bool {
144+
return d.VSockPort == 0 && d.VirtioPort == ""
145+
}
146+
140147
func (d *BaseDriver) GuestAgentConn(_ context.Context) (net.Conn, error) {
141-
return nil, fmt.Errorf("unimplemented")
148+
return nil, nil
142149
}

pkg/hostagent/hostagent.go

+32-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type HostAgent struct {
5454
eventEncMu sync.Mutex
5555

5656
vSockPort int
57+
virtioPort string
5758

5859
clientMu sync.RWMutex
5960
client guestagentclient.GuestAgentClient
@@ -114,6 +115,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
114115
}
115116

116117
vSockPort := 0
118+
virtioPort := ""
117119
if *y.VMType == limayaml.VZ {
118120
vSockPort = 2222
119121
} else if *y.VMType == limayaml.WSL2 {
@@ -122,9 +124,11 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
122124
logrus.WithError(err).Error("failed to get free VSock port")
123125
}
124126
vSockPort = port
127+
} else if *y.VMType == limayaml.QEMU {
128+
virtioPort = filenames.VirtioPort
125129
}
126130

127-
if err := cidata.GenerateISO9660(inst.Dir, instName, y, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort); err != nil {
131+
if err := cidata.GenerateISO9660(inst.Dir, instName, y, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort, virtioPort); err != nil {
128132
return nil, err
129133
}
130134

@@ -157,6 +161,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
157161
Yaml: y,
158162
SSHLocalPort: sshLocalPort,
159163
VSockPort: vSockPort,
164+
VirtioPort: virtioPort,
160165
})
161166

162167
a := &HostAgent{
@@ -173,6 +178,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
173178
sigintCh: sigintCh,
174179
eventEnc: json.NewEncoder(stdout),
175180
vSockPort: vSockPort,
181+
virtioPort: virtioPort,
176182
}
177183
return a, nil
178184
}
@@ -528,7 +534,6 @@ func (a *HostAgent) close() error {
528534
}
529535

530536
func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
531-
// TODO: use vSock (when QEMU for macOS gets support for vSock)
532537

533538
// Setup all socket forwards and defer their teardown
534539
if *a.y.VMType != limayaml.WSL2 {
@@ -541,6 +546,9 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
541546
}
542547
}
543548

549+
localUnix := filepath.Join(a.instDir, filenames.GuestAgentSock)
550+
remoteUnix := "/run/lima-guestagent.sock"
551+
544552
a.onClose = append(a.onClose, func() error {
545553
logrus.Debugf("Stop forwarding unix sockets")
546554
var errs []error
@@ -553,9 +561,20 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
553561
}
554562
}
555563
}
564+
if a.driver.ForwardUnixGuestAgent() {
565+
if err := forwardSSH(context.Background(), a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbCancel, false); err != nil {
566+
errs = append(errs, err)
567+
}
568+
}
569+
556570
return errors.Join(errs...)
557571
})
558572
for {
573+
if a.client == nil || !isGuestAgentSocketAccessible(ctx, a.client) {
574+
if a.driver.ForwardUnixGuestAgent() {
575+
_ = forwardSSH(ctx, a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbForward, false)
576+
}
577+
}
559578
client, err := a.getOrCreateClient(ctx)
560579
if err == nil {
561580
if err := a.processGuestAgentEvents(ctx, client); err != nil {
@@ -590,8 +609,18 @@ func (a *HostAgent) getOrCreateClient(ctx context.Context) (guestagentclient.Gue
590609
return a.client, err
591610
}
592611

593-
func (a *HostAgent) createClient(ctx context.Context) (guestagentclient.GuestAgentClient, error) {
612+
func (a *HostAgent) createConnection(ctx context.Context) (net.Conn, error) {
594613
conn, err := a.driver.GuestAgentConn(ctx)
614+
// default to forwarded sock
615+
if conn == nil && err == nil {
616+
var d net.Dialer
617+
conn, err = d.DialContext(ctx, "unix", filepath.Join(a.instDir, filenames.GuestAgentSock))
618+
}
619+
return conn, err
620+
}
621+
622+
func (a *HostAgent) createClient(ctx context.Context) (guestagentclient.GuestAgentClient, error) {
623+
conn, err := a.createConnection(ctx)
595624
if err != nil {
596625
return nil, err
597626
}

pkg/hostagent/requirements.go

+20-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"time"
77

88
"github.com/lima-vm/lima/pkg/limayaml"
9-
"github.com/lima-vm/lima/pkg/store/filenames"
109
"github.com/lima-vm/sshocker/pkg/ssh"
1110
"github.com/sirupsen/logrus"
1211
)
@@ -136,7 +135,7 @@ Also see "/var/log/cloud-init-output.log" in the guest.
136135
A possible workaround is to run "lima-guestagent install-systemd" in the guest.
137136
`, a.vSockPort),
138137
})
139-
} else {
138+
} else if a.virtioPort != "" {
140139
req = append(req, requirement{
141140
description: "the guest agent to be running",
142141
script: fmt.Sprintf(`#!/bin/bash
@@ -146,12 +145,29 @@ if ! timeout 30s bash -c "until sudo fuser \"${sock}\" || sudo lsof \"${sock}\";
146145
echo >&2 "lima-guestagent is not installed yet"
147146
exit 1
148147
fi
149-
`, filenames.VirtioPort),
148+
`, a.virtioPort),
150149
debugHint: fmt.Sprintf(`The guest agent with serialport /dev/virtio-ports/%s does not seem running.
151150
Make sure that you are using an officially supported image.
152151
Also see "/var/log/cloud-init-output.log" in the guest.
153152
A possible workaround is to run "lima-guestagent install-systemd" in the guest.
154-
`, filenames.VirtioPort),
153+
`, a.virtioPort),
154+
})
155+
} else {
156+
req = append(req, requirement{
157+
description: "the guest agent to be running",
158+
script: `#!/bin/bash
159+
set -eux -o pipefail
160+
sock="/run/lima-guestagent.sock"
161+
if ! timeout 30s bash -c "until [ -S \"${sock}\" ]; do sleep 3; done"; then
162+
echo >&2 "lima-guestagent is not installed yet"
163+
exit 1
164+
fi
165+
`,
166+
debugHint: `The guest agent (/run/lima-guestagent.sock) does not seem running.
167+
Make sure that you are using an officially supported image.
168+
Also see "/var/log/cloud-init-output.log" in the guest.
169+
A possible workaround is to run "lima-guestagent install-systemd" in the guest.
170+
`,
155171
})
156172
}
157173
return req

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)