Skip to content

CI: see if wsl2 works #1826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,47 @@ jobs:

windows:
name: "Windows tests"
runs-on: windows-2022
runs-on: windows-2022-8-cores
timeout-minutes: 30
steps:
- name: Enable WSL2
run: |
wsl --set-default-version 2
wsl --update
wsl --status
wsl --list --online
- name: Install WSL2 distro
timeout-minutes: 3
run: |
# FIXME: At least one distro has to be installed here,
# otherwise `wsl --list --verbose` (called from Lima) fails:
# https://github.com/lima-vm/lima/pull/1826#issuecomment-1729993334
# The distro image itself is not consumed by Lima.
# ------------------------------------------------------------------
# Ubuntu-22.04: gets stuck in some infinite loop during adduser
# OracleLinux_9_1: almostly silently fails, and just prints "Usage: adduser [options] LOGIN"
wsl --install -d openSUSE-Leap-15.5
wsl --list --verbose
- uses: actions/checkout@v4
with:
fetch-depth: 1
- uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Unit tests
run: go test -v ./...
- name: Make
run: make
- name: Smoke test
run: |
.\_output\bin\limactl.exe start template://experimental/wsl2
# TODO: run the full integration tests
- name: Debug
if: always()
run: type C:\Users\runneradmin\.lima\wsl2\ha.stdout.log
- name: Debug
if: always()
run: type C:\Users\runneradmin\.lima\wsl2\ha.stderr.log
- name: Unit tests
run: go test -v ./...

integration:
name: Integration tests
Expand Down
3 changes: 2 additions & 1 deletion pkg/downloader/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@ func downloadHTTP(localPath, url string, description string, expectedDigest dige
if description == "" {
description = url
}
fmt.Printf("Downloading %s\n", description)
// stderr corresponds to the progress bar output
fmt.Fprintf(os.Stderr, "Downloading %s\n", description)
}
bar.Start()
if _, err := io.Copy(multiWriter, bar.NewProxyReader(resp.Body)); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion pkg/hostagent/events/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package events
import (
"context"
"encoding/json"
"fmt"
"time"

"github.com/lima-vm/lima/pkg/logrusutil"
Expand Down Expand Up @@ -51,7 +52,7 @@ loop:
}
var ev Event
if err := json.Unmarshal([]byte(line.Text), &ev); err != nil {
return err
return fmt.Errorf("failed to unmarshal %q as %T: %w", line.Text, ev, err)
}
logrus.WithField("event", ev).Debugf("received an event")
if stop := onEvent(ev); stop {
Expand Down
4 changes: 2 additions & 2 deletions pkg/store/instance_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func GetWslStatus(instName string) (string, error) {
"--verbose",
})
if err != nil {
return "", fmt.Errorf("failed to run `wsl --list --verbose`, err: %w", err)
return "", fmt.Errorf("failed to run `wsl --list --verbose`, err: %w (out=%q)", err, string(out))
}

if len(out) == 0 {
Expand Down Expand Up @@ -94,7 +94,7 @@ func getWslSSHAddress(instName string) (string, error) {
cmd := exec.Command("wsl.exe", "-d", distroName, "bash", "-c", `hostname -I | cut -d ' ' -f1`)
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("failed to get hostname for instance %s, err: %w", instName, err)
return "", fmt.Errorf("failed to get hostname for instance %s, err: %w (out=%q)", instName, err, string(out))
}

return strings.TrimSpace(string(out)), nil
Expand Down
4 changes: 3 additions & 1 deletion pkg/windows/process_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ func GetProcessCommandLine(name string) ([]string, error) {
}

var outJSON CommandLineJSON
json.Unmarshal([]byte(out), &outJSON)
if err = json.Unmarshal([]byte(out), &outJSON); err != nil {
return nil, fmt.Errorf("failed to unmarshal %q as %T: %w", out, outJSON, err)
}

var ret []string
for _, s := range outJSON {
Expand Down
11 changes: 6 additions & 5 deletions pkg/wsl2/lima-init.TEMPLATE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set -eu; \
export LOG_FILE=/var/log/lima-init.log; \
exec > >(tee \$LOG_FILE) 2>&1; \
export LIMA_CIDATA_MNT="$(/usr/bin/wslpath '{{.CIDataPath}}')"; \
exec "\$LIMA_CIDATA_MNT/boot.sh";
#!/bin/bash
set -eu
export LOG_FILE=/var/log/lima-init.log
exec > >(tee $LOG_FILE) 2>&1
export LIMA_CIDATA_MNT="$(/usr/bin/wslpath '{{.CIDataPath}}')"
exec "$LIMA_CIDATA_MNT/boot.sh"
53 changes: 37 additions & 16 deletions pkg/wsl2/vm_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"context"
_ "embed"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/lima-vm/lima/pkg/executil"
"github.com/lima-vm/lima/pkg/store"
Expand All @@ -20,13 +20,14 @@ import (

// startVM calls WSL to start a VM.
func startVM(ctx context.Context, distroName string) error {
_, err := executil.RunUTF16leCommand([]string{
out, err := executil.RunUTF16leCommand([]string{
"wsl.exe",
"--distribution",
distroName,
}, executil.WithContext(&ctx))
if err != nil {
return err
return fmt.Errorf("failed to run `wsl.exe --distribution %s`: %w (out=%q)",
distroName, err, string(out))
}
return nil
}
Expand All @@ -35,28 +36,30 @@ func startVM(ctx context.Context, distroName string) error {
func initVM(ctx context.Context, instanceDir, distroName string) error {
baseDisk := filepath.Join(instanceDir, filenames.BaseDisk)
logrus.Infof("Importing distro from %q to %q", baseDisk, instanceDir)
_, err := executil.RunUTF16leCommand([]string{
out, err := executil.RunUTF16leCommand([]string{
"wsl.exe",
"--import",
distroName,
instanceDir,
baseDisk,
}, executil.WithContext(&ctx))
if err != nil {
return err
return fmt.Errorf("failed to run `wsl.exe --import %s %s %s`: %w (out=%q)",
distroName, instanceDir, baseDisk, err, string(out))
}
return nil
}

// stopVM calls WSL to stop a running VM.
func stopVM(ctx context.Context, distroName string) error {
_, err := executil.RunUTF16leCommand([]string{
out, err := executil.RunUTF16leCommand([]string{
"wsl.exe",
"--terminate",
distroName,
}, executil.WithContext(&ctx))
if err != nil {
return err
return fmt.Errorf("failed to run `wsl.exe --terminate %s`: %w (out=%q)",
distroName, err, string(out))
}
return nil
}
Expand All @@ -70,11 +73,27 @@ func provisionVM(ctx context.Context, instanceDir, instanceName, distroName stri
m := map[string]string{
"CIDataPath": ciDataPath,
}
out, err := textutil.ExecuteTemplate(limaBoot, m)
limaBootB, err := textutil.ExecuteTemplate(limaBoot, m)
if err != nil {
return fmt.Errorf("failed to construct wsl boot.sh script: %w", err)
}
outString := strings.Replace(string(out), `\r\n`, `\n`, -1)
limaBootFile, err := os.CreateTemp("", "lima-wsl2-boot-*.sh")
if err != nil {
return err
}
if _, err = limaBootFile.Write(limaBootB); err != nil {
return err
}
limaBootFilePathOnWindows := limaBootFile.Name()
if err = limaBootFile.Close(); err != nil {
return err
}
defer os.RemoveAll(limaBootFilePathOnWindows)
limaBootFilePathOnLinuxB, err := exec.Command("wsl.exe", "wslpath", "-u", limaBootFilePathOnWindows).Output()
if err != nil {
return err
}
limaBootFilePathOnLinux := string(limaBootFilePathOnLinuxB)

go func() {
cmd := exec.CommandContext(
Expand All @@ -83,13 +102,14 @@ func provisionVM(ctx context.Context, instanceDir, instanceName, distroName stri
"-d",
distroName,
"bash",
"-c",
outString,
limaBootFilePathOnLinux,
)
if _, err := cmd.CombinedOutput(); err != nil {
out, err := cmd.CombinedOutput()
logrus.Infof("%v: %q", cmd.Args, string(out))
if err != nil {
*errCh <- fmt.Errorf(
"error running wslCommand that executes boot.sh: %w, "+
"check /var/log/lima-init.log for more details", err)
"error running wslCommand that executes boot.sh (%v): %w, "+
"check /var/log/lima-init.log for more details (out=%q)", cmd.Args, err, string(out))
}

for {
Expand Down Expand Up @@ -130,13 +150,14 @@ func keepAlive(ctx context.Context, distroName string, errCh *chan error) {
// unregisterVM calls WSL to unregister a VM.
func unregisterVM(ctx context.Context, distroName string) error {
logrus.Info("Unregistering WSL2 VM")
_, err := executil.RunUTF16leCommand([]string{
out, err := executil.RunUTF16leCommand([]string{
"wsl.exe",
"--unregister",
distroName,
}, executil.WithContext(&ctx))
if err != nil {
return err
return fmt.Errorf("failed to run `wsl.exe --unregister %s`: %w (out=%q)",
distroName, err, string(out))
}
return nil
}