Skip to content

Commit

Permalink
test: add basic tests for vfkit
Browse files Browse the repository at this point in the history
Adds a basic implementation for testing against a vfkit VM. Tests are based on the existing qemu version. It just changes the way the VM gets created/started.

Signed-off-by: Luca Stocchi <[email protected]>
  • Loading branch information
lstocchi committed Nov 26, 2024
1 parent f5d2753 commit 13e461c
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 0 deletions.
19 changes: 19 additions & 0 deletions test-vfkit/basic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package e2evfkit

import (
e2e "github.com/containers/gvisor-tap-vsock/test"
"github.com/onsi/ginkgo"
)

var _ = ginkgo.Describe("connectivity with vfkit", func() {
e2e.BasicConnectivityTests(e2e.BasicTestProps{
SshExec: sshExec,
})
})

var _ = ginkgo.Describe("dns with vfkit", func() {
e2e.BasicDNSTests(e2e.BasicTestProps{
SshExec: sshExec,
Sock: sock,
})
})
166 changes: 166 additions & 0 deletions test-vfkit/vfkit_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package e2evfkit

import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"testing"
"time"

e2e_utils "github.com/containers/gvisor-tap-vsock/test-utils"

"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
log "github.com/sirupsen/logrus"
)

func TestSuite(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "gvisor-tap-vsock suite")
}

const (
sock = "/tmp/gvproxy-api-vfkit.sock"
vfkitSock = "/tmp/vfkit.sock"
sshPort = 2222
ignitionUser = "test"
// #nosec "test" (for manual usage)
ignitionPasswordHash = "$y$j9T$TqJWt3/mKJbH0sYi6B/LD1$QjVRuUgntjTHjAdAkqhkr4F73m.Be4jBXdAaKw98sPC"
)

var (
tmpDir string
binDir string
host *exec.Cmd
client *exec.Cmd
privateKeyFile string
publicKeyFile string
ignFile string
)

func init() {
flag.StringVar(&tmpDir, "tmpDir", "../tmp", "temporary working directory")
flag.StringVar(&binDir, "bin", "../bin", "directory with compiled binaries")
privateKeyFile = filepath.Join(tmpDir, "id_test")
publicKeyFile = privateKeyFile + ".pub"
ignFile = filepath.Join(tmpDir, "test.ign")

}

var _ = ginkgo.BeforeSuite(func() {
gomega.Expect(os.MkdirAll(filepath.Join(tmpDir, "disks"), os.ModePerm)).Should(gomega.Succeed())

downloader, err := e2e_utils.NewFcosDownloader(filepath.Join(tmpDir, "disks"))
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
fcosImage, err := downloader.DownloadImage("applehv", "raw.gz")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

publicKey, err := e2e_utils.CreateSSHKeys(publicKeyFile, privateKeyFile)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

err = e2e_utils.CreateIgnition(ignFile, publicKey, ignitionUser, ignitionPasswordHash)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

outer:
for panics := 0; ; panics++ {
_ = os.Remove(sock)

// #nosec
host = exec.Command(filepath.Join(binDir, "gvproxy"), fmt.Sprintf("--listen=unix://%s", sock), fmt.Sprintf("--listen-vfkit=unixgram://%s", vfkitSock))

host.Stderr = os.Stderr
host.Stdout = os.Stdout
gomega.Expect(host.Start()).Should(gomega.Succeed())
go func() {
if err := host.Wait(); err != nil {
log.Error(err)
}
}()

for {
_, err := os.Stat(sock)
if os.IsNotExist(err) {
log.Info("waiting for socket")
time.Sleep(100 * time.Millisecond)
continue
}
_, err = os.Stat(vfkitSock)
if os.IsNotExist(err) {
log.Info("waiting for vfkit socket")
time.Sleep(100 * time.Millisecond)
continue
}
break
}

vfkitArgs := `--cpus 2 --memory 2048 --bootloader efi,variable-store=efi-variable-store,create --device virtio-blk,path=%s --ignition %s --device virtio-net,unixSocketPath=%s,mac=5a:94:ef:e4:0c:ee`
// #nosec
client = exec.Command(vfkitExecutable(), strings.Split(fmt.Sprintf(vfkitArgs, fcosImage, ignFile, vfkitSock), " ")...)
client.Stderr = os.Stderr
client.Stdout = os.Stdout
gomega.Expect(client.Start()).Should(gomega.Succeed())
go func() {
if err := client.Wait(); err != nil {
log.Error(err)
}
}()

for {
_, err := sshExec("whoami")
if err == nil {
break outer
}

log.Infof("waiting for client to connect: %v", err)
time.Sleep(time.Second)
}
}

time.Sleep(5 * time.Second)
})

func vfkitExecutable() string {
vfkitBinaries := []string{"vfkit"}
for _, binary := range vfkitBinaries {
path, err := exec.LookPath(binary)
if err == nil && path != "" {
return path
}
}

return ""
}

func sshExec(cmd ...string) ([]byte, error) {
return sshCommand(cmd...).Output()
}

func sshCommand(cmd ...string) *exec.Cmd {
sshCmd := exec.Command("ssh",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no",
"-o", "IdentitiesOnly=yes",
"-i", privateKeyFile,
"-p", strconv.Itoa(sshPort),
fmt.Sprintf("%[email protected]", ignitionUser), "--", strings.Join(cmd, " ")) // #nosec G204
return sshCmd
}

var _ = ginkgo.AfterSuite(func() {
if host != nil {
if err := host.Process.Kill(); err != nil {
log.Error(err)
}
}
if client != nil {
if err := client.Process.Kill(); err != nil {
log.Error(err)
}
}
_ = os.Remove(sock)
_ = os.Remove(vfkitSock)
})

0 comments on commit 13e461c

Please sign in to comment.