Skip to content

Commit 6dd4229

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 a21b5f3 commit 6dd4229

File tree

9 files changed

+94
-26
lines changed

9 files changed

+94
-26
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

+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

+2-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ type BaseDriver struct {
7373

7474
SSHLocalPort int
7575
VSockPort int
76+
VirtioPort string
7677
}
7778

7879
var _ Driver = (*BaseDriver)(nil)
@@ -138,5 +139,5 @@ func (d *BaseDriver) ListSnapshots(_ context.Context) (string, error) {
138139
}
139140

140141
func (d *BaseDriver) GuestAgentConn(_ context.Context) (net.Conn, error) {
141-
return nil, fmt.Errorf("unimplemented")
142+
return nil, nil
142143
}

pkg/hostagent/hostagent.go

+35-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
@@ -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,8 +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)
532-
533537
// Setup all socket forwards and defer their teardown
534538
if *a.y.VMType != limayaml.WSL2 {
535539
logrus.Debugf("Forwarding unix sockets")
@@ -541,6 +545,12 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
541545
}
542546
}
543547

548+
// if needed, forward the guest agent unix socket
549+
d := a.driver.(*driver.BaseDriver)
550+
forwardUnix := d.VSockPort == 0 && d.VirtioPort == ""
551+
localUnix := filepath.Join(a.instDir, filenames.GuestAgentSock)
552+
remoteUnix := "/run/lima-guestagent.sock"
553+
544554
a.onClose = append(a.onClose, func() error {
545555
logrus.Debugf("Stop forwarding unix sockets")
546556
var errs []error
@@ -553,9 +563,19 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
553563
}
554564
}
555565
}
566+
if forwardUnix {
567+
if err := forwardSSH(context.Background(), a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbCancel, false); err != nil {
568+
errs = append(errs, err)
569+
}
570+
}
556571
return errors.Join(errs...)
557572
})
558573
for {
574+
if a.client == nil || !isGuestAgentSocketAccessible(ctx, a.client) {
575+
if forwardUnix {
576+
_ = forwardSSH(ctx, a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbForward, false)
577+
}
578+
}
559579
client, err := a.getOrCreateClient(ctx)
560580
if err == nil {
561581
if err := a.processGuestAgentEvents(ctx, client); err != nil {
@@ -590,8 +610,18 @@ func (a *HostAgent) getOrCreateClient(ctx context.Context) (guestagentclient.Gue
590610
return a.client, err
591611
}
592612

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

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)