Skip to content

Commit 4966c11

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 b136264 commit 4966c11

File tree

8 files changed

+81
-16
lines changed

8 files changed

+81
-16
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
@@ -35,7 +35,7 @@ name="lima-guestagent"
3535
description="Forward ports to the lima-hostagent"
3636
3737
command=${LIMA_CIDATA_GUEST_INSTALL_PREFIX}/bin/lima-guestagent
38-
command_args="daemon --vsock-port "${LIMA_CIDATA_VSOCK_PORT}""
38+
command_args="daemon --vsock-port "${LIMA_CIDATA_VSOCK_PORT}" --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}""
3939
command_background=true
4040
pidfile="/run/lima-guestagent.pid"
4141
EOF
@@ -47,5 +47,11 @@ else
4747
# Remove legacy systemd service
4848
rm -f "${LIMA_CIDATA_HOME}/.config/systemd/user/lima-guestagent.service"
4949

50-
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}"
50+
if [ "${LIMA_CIDATA_VSOCK_PORT}" != "0" ]; then
51+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}"
52+
elif [ "${LIMA_CIDATA_VIRTIO_PORT}" != "" ]; then
53+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}"
54+
else
55+
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd
56+
fi
5157
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-3
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
@@ -561,6 +567,9 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
561567
}
562568
}
563569

570+
localUnix := filepath.Join(a.instDir, filenames.GuestAgentSock)
571+
remoteUnix := "/run/lima-guestagent.sock"
572+
564573
a.onClose = append(a.onClose, func() error {
565574
logrus.Debugf("Stop forwarding unix sockets")
566575
var errs []error
@@ -573,9 +582,19 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
573582
}
574583
}
575584
}
585+
if a.driver.ForwardGuestAgent() {
586+
if err := forwardSSH(context.Background(), a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbCancel, false); err != nil {
587+
errs = append(errs, err)
588+
}
589+
}
576590
return errors.Join(errs...)
577591
})
578592
for {
593+
if a.client == nil || !isGuestAgentSocketAccessible(ctx, a.client) {
594+
if a.driver.ForwardGuestAgent() {
595+
_ = forwardSSH(ctx, a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbForward, false)
596+
}
597+
}
579598
client, err := a.getOrCreateClient(ctx)
580599
if err == nil {
581600
if err := a.processGuestAgentEvents(ctx, client); err != nil {
@@ -610,8 +629,18 @@ func (a *HostAgent) getOrCreateClient(ctx context.Context) (guestagentclient.Gue
610629
return a.client, err
611630
}
612631

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

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)