Skip to content

Commit

Permalink
Restore guest agent unix socket functionality
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
afbjorklund committed Nov 18, 2023
1 parent a21b5f3 commit 6dd4229
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 26 deletions.
34 changes: 22 additions & 12 deletions cmd/lima-guestagent/daemon_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/lima-vm/lima/pkg/guestagent"
"github.com/lima-vm/lima/pkg/guestagent/api/server"
"github.com/lima-vm/lima/pkg/guestagent/serialport"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/mdlayher/vsock"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand All @@ -25,26 +24,23 @@ func newDaemonCommand() *cobra.Command {
}
daemonCommand.Flags().Duration("tick", 3*time.Second, "tick for polling events")
daemonCommand.Flags().Int("vsock-port", 0, "use vsock server instead a UNIX socket")
daemonCommand.Flags().String("virtio-port", "", "use virtio server instead a UNIX socket")
return daemonCommand
}

var (
vSockPort = 0

virtioPort = "/dev/virtio-ports/" + filenames.VirtioPort
)

func daemonAction(cmd *cobra.Command, _ []string) error {
socket := "/run/lima-guestagent.sock"
tick, err := cmd.Flags().GetDuration("tick")
if err != nil {
return err
}
vSockPortOverride, err := cmd.Flags().GetInt("vsock-port")
vSockPort, err := cmd.Flags().GetInt("vsock-port")
if err != nil {
return err
}
if vSockPortOverride != 0 {
vSockPort = vSockPortOverride
virtioPort, err := cmd.Flags().GetString("virtio-port")
if err != nil {
return err
}
if tick == 0 {
return errors.New("tick must be specified")
Expand Down Expand Up @@ -72,10 +68,14 @@ func daemonAction(cmd *cobra.Command, _ []string) error {
r := mux.NewRouter()
server.AddRoutes(r, backend)
srv := &http.Server{Handler: r}
err = os.RemoveAll(socket)
if err != nil {
return err
}

var l net.Listener
if _, err := os.Stat(virtioPort); err == nil {
qemuL, err := serialport.Listen(virtioPort)
if virtioPort != "" {
qemuL, err := serialport.Listen("/dev/virtio-ports/" + virtioPort)
if err != nil {
return err
}
Expand All @@ -88,6 +88,16 @@ func daemonAction(cmd *cobra.Command, _ []string) error {
}
l = vsockL
logrus.Infof("serving the guest agent on vsock port: %d", vSockPort)
} else {
socketL, err := net.Listen("unix", socket)
if err != nil {
return err
}
if err := os.Chmod(socket, 0o777); err != nil {
return err
}
l = socketL
logrus.Infof("serving the guest agent on %q", socket)
}
return srv.Serve(l)
}
10 changes: 8 additions & 2 deletions pkg/cidata/cidata.TEMPLATE.d/boot/25-guestagent-base.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ name="lima-guestagent"
description="Forward ports to the lima-hostagent"
command=${LIMA_CIDATA_GUEST_INSTALL_PREFIX}/bin/lima-guestagent
command_args="daemon --vsock-port "${LIMA_CIDATA_VSOCK_PORT}""
command_args="daemon --vsock-port "${LIMA_CIDATA_VSOCK_PORT}" --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}""
command_background=true
pidfile="/run/lima-guestagent.pid"
EOF
Expand All @@ -40,5 +40,11 @@ else
# Remove legacy systemd service
rm -f "${LIMA_CIDATA_HOME}/.config/systemd/user/lima-guestagent.service"

sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}"
if [ "${LIMA_CIDATA_VSOCK_PORT}" != "0" ]; then
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --vsock-port "${LIMA_CIDATA_VSOCK_PORT}"
elif [ "${LIMA_CIDATA_VIRTIO_PORT}" != "" ]; then
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd --virtio-port "${LIMA_CIDATA_VIRTIO_PORT}"
else
sudo "${LIMA_CIDATA_GUEST_INSTALL_PREFIX}"/bin/lima-guestagent install-systemd
fi
fi
1 change: 1 addition & 0 deletions pkg/cidata/cidata.TEMPLATE.d/lima.env
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ LIMA_CIDATA_SKIP_DEFAULT_DEPENDENCY_RESOLUTION=
{{- end}}
LIMA_CIDATA_VMTYPE={{ .VMType }}
LIMA_CIDATA_VSOCK_PORT={{ .VSockPort }}
LIMA_CIDATA_VIRTIO_PORT={{ .VirtioPort}}
{{- if .Plain}}
LIMA_CIDATA_PLAIN=1
{{- else}}
Expand Down
3 changes: 2 additions & 1 deletion pkg/cidata/cidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func setupEnv(y *limayaml.LimaYAML, args TemplateArgs) (map[string]string, error
return env, nil
}

func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, nerdctlArchive string, vsockPort int) error {
func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, nerdctlArchive string, vsockPort int, virtioPort string) error {
if err := limayaml.Validate(*y, false); err != nil {
return err
}
Expand All @@ -135,6 +135,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort
RosettaBinFmt: *y.Rosetta.BinFmt,
VMType: *y.VMType,
VSockPort: vsockPort,
VirtioPort: virtioPort,
Plain: *y.Plain,
}

Expand Down
1 change: 1 addition & 0 deletions pkg/cidata/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type TemplateArgs struct {
SkipDefaultDependencyResolution bool
VMType string
VSockPort int
VirtioPort string
Plain bool
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type BaseDriver struct {

SSHLocalPort int
VSockPort int
VirtioPort string
}

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

func (d *BaseDriver) GuestAgentConn(_ context.Context) (net.Conn, error) {
return nil, fmt.Errorf("unimplemented")
return nil, nil
}
40 changes: 35 additions & 5 deletions pkg/hostagent/hostagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ type HostAgent struct {
eventEnc *json.Encoder
eventEncMu sync.Mutex

vSockPort int
vSockPort int
virtioPort string

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

vSockPort := 0
virtioPort := ""
if *y.VMType == limayaml.VZ {
vSockPort = 2222
} else if *y.VMType == limayaml.WSL2 {
Expand All @@ -122,9 +124,11 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
logrus.WithError(err).Error("failed to get free VSock port")
}
vSockPort = port
} else if *y.VMType == limayaml.QEMU {
virtioPort = filenames.VirtioPort
}

if err := cidata.GenerateISO9660(inst.Dir, instName, y, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort); err != nil {
if err := cidata.GenerateISO9660(inst.Dir, instName, y, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort, virtioPort); err != nil {
return nil, err
}

Expand Down Expand Up @@ -157,6 +161,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
Yaml: y,
SSHLocalPort: sshLocalPort,
VSockPort: vSockPort,
VirtioPort: virtioPort,
})

a := &HostAgent{
Expand All @@ -173,6 +178,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt
sigintCh: sigintCh,
eventEnc: json.NewEncoder(stdout),
vSockPort: vSockPort,
virtioPort: virtioPort,
}
return a, nil
}
Expand Down Expand Up @@ -528,8 +534,6 @@ func (a *HostAgent) close() error {
}

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

// Setup all socket forwards and defer their teardown
if *a.y.VMType != limayaml.WSL2 {
logrus.Debugf("Forwarding unix sockets")
Expand All @@ -541,6 +545,12 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
}
}

// if needed, forward the guest agent unix socket
d := a.driver.(*driver.BaseDriver)
forwardUnix := d.VSockPort == 0 && d.VirtioPort == ""
localUnix := filepath.Join(a.instDir, filenames.GuestAgentSock)
remoteUnix := "/run/lima-guestagent.sock"

a.onClose = append(a.onClose, func() error {
logrus.Debugf("Stop forwarding unix sockets")
var errs []error
Expand All @@ -553,9 +563,19 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
}
}
}
if forwardUnix {
if err := forwardSSH(context.Background(), a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbCancel, false); err != nil {
errs = append(errs, err)
}
}
return errors.Join(errs...)
})
for {
if a.client == nil || !isGuestAgentSocketAccessible(ctx, a.client) {
if forwardUnix {
_ = forwardSSH(ctx, a.sshConfig, a.sshLocalPort, localUnix, remoteUnix, verbForward, false)
}
}
client, err := a.getOrCreateClient(ctx)
if err == nil {
if err := a.processGuestAgentEvents(ctx, client); err != nil {
Expand Down Expand Up @@ -590,8 +610,18 @@ func (a *HostAgent) getOrCreateClient(ctx context.Context) (guestagentclient.Gue
return a.client, err
}

func (a *HostAgent) createClient(ctx context.Context) (guestagentclient.GuestAgentClient, error) {
func (a *HostAgent) createConnection(ctx context.Context) (net.Conn, error) {
conn, err := a.driver.GuestAgentConn(ctx)
// default to forwarded sock
if conn == nil && err == nil {
var d net.Dialer
conn, err = d.DialContext(ctx, "unix", filepath.Join(a.instDir, filenames.GuestAgentSock))
}
return conn, err
}

func (a *HostAgent) createClient(ctx context.Context) (guestagentclient.GuestAgentClient, error) {
conn, err := a.createConnection(ctx)
if err != nil {
return nil, err
}
Expand Down
24 changes: 20 additions & 4 deletions pkg/hostagent/requirements.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"time"

"github.com/lima-vm/lima/pkg/limayaml"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/lima-vm/sshocker/pkg/ssh"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -136,7 +135,7 @@ Also see "/var/log/cloud-init-output.log" in the guest.
A possible workaround is to run "lima-guestagent install-systemd" in the guest.
`, a.vSockPort),
})
} else {
} else if a.virtioPort != "" {
req = append(req, requirement{
description: "the guest agent to be running",
script: fmt.Sprintf(`#!/bin/bash
Expand All @@ -146,12 +145,29 @@ if ! timeout 30s bash -c "until sudo fuser \"${sock}\" || sudo lsof \"${sock}\";
echo >&2 "lima-guestagent is not installed yet"
exit 1
fi
`, filenames.VirtioPort),
`, a.virtioPort),
debugHint: fmt.Sprintf(`The guest agent with serialport /dev/virtio-ports/%s does not seem running.
Make sure that you are using an officially supported image.
Also see "/var/log/cloud-init-output.log" in the guest.
A possible workaround is to run "lima-guestagent install-systemd" in the guest.
`, filenames.VirtioPort),
`, a.virtioPort),
})
} else {
req = append(req, requirement{
description: "the guest agent to be running",
script: `#!/bin/bash
set -eux -o pipefail
sock="/run/lima-guestagent.sock"
if ! timeout 30s bash -c "until [ -S \"${sock}\" ]; do sleep 3; done"; then
echo >&2 "lima-guestagent is not installed yet"
exit 1
fi
`,
debugHint: `The guest agent (/run/lima-guestagent.sock) does not seem running.
Make sure that you are using an officially supported image.
Also see "/var/log/cloud-init-output.log" in the guest.
A possible workaround is to run "lima-guestagent install-systemd" in the guest.
`,
})
}
return req
Expand Down
4 changes: 3 additions & 1 deletion website/content/en/docs/dev/Internals/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ VNC:

Guest agent:

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

Host agent:
- `ha.pid`: hostagent PID
Expand Down

0 comments on commit 6dd4229

Please sign in to comment.