Skip to content

Commit e78f38c

Browse files
committed
Support for Virt driver
This is a driver based on libvirt.org, for remote hypervisors. The libvirt functions are in a plugin, to minimize dependencies. Currently only shows version. Signed-off-by: Anders F Björklund <[email protected]>
1 parent bfd7471 commit e78f38c

File tree

16 files changed

+261
-3
lines changed

16 files changed

+261
-3
lines changed

Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ config GUESTAGENT_ARCH_RISCV64
3030
help
3131
Build lima-guestagent for "riscv64" Arch
3232
default y
33+
34+
config PLUGIN_VIRT
35+
bool "plugin for vmType virt"
36+
help
37+
Build plugin for virt (requires libvirt)
38+
default y

Makefile

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ endif
3838
endif
3939
endif
4040

41+
-include .config
42+
43+
ifneq ($(CONFIG_PLUGIN_VIRT),y)
44+
GO_BUILDTAGS += no_virt
45+
endif
46+
4147
PACKAGE := github.com/lima-vm/lima
4248

4349
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
@@ -77,15 +83,18 @@ menuconfig: Kconfig
7783
.config: config.mk
7884
cp $^ $@
7985

80-
-include .config
81-
8286
HELPERS = \
8387
_output/bin/nerdctl.lima \
8488
_output/bin/apptainer.lima \
8589
_output/bin/docker.lima \
8690
_output/bin/podman.lima \
8791
_output/bin/kubectl.lima
8892

93+
ifeq ($(CONFIG_PLUGIN_VIRT),y)
94+
PLUGINS += \
95+
_output/lib/lima/plugin/virt.so
96+
endif
97+
8998
ifeq ($(CONFIG_GUESTAGENT_OS_LINUX),y)
9099
ifeq ($(CONFIG_GUESTAGENT_ARCH_X8664),y)
91100
GUESTAGENT += \
@@ -112,6 +121,7 @@ binaries: clean \
112121
_output/bin/limactl$(exe) \
113122
codesign \
114123
$(HELPERS) \
124+
$(PLUGINS) \
115125
$(GUESTAGENT)
116126
cp -aL examples _output/share/lima/templates
117127
ifneq ($(GOOS),windows)
@@ -188,6 +198,12 @@ _output/share/lima/lima-guestagent.Linux-riscv64:
188198
GOOS=linux GOARCH=riscv64 CGO_ENABLED=0 $(GO_BUILD) -o $@ ./cmd/lima-guestagent
189199
chmod 644 $@
190200

201+
plugins: $(PLUGINS)
202+
203+
.PHONY: _output/lib/lima/plugin/virt.so
204+
_output/lib/lima/plugin/virt.so:
205+
CGO_ENABLED=1 $(GO_BUILD) -buildmode=plugin -o $@ ./pkg/virt/plugin
206+
191207
.PHONY: manpages
192208
manpages: _output/bin/limactl$(exe)
193209
@mkdir -p _output/share/man/man1

config.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ CONFIG_GUESTAGENT_ARCH_X8664=y
33
CONFIG_GUESTAGENT_ARCH_AARCH64=y
44
CONFIG_GUESTAGENT_ARCH_ARMV7L=y
55
CONFIG_GUESTAGENT_ARCH_RISCV64=y
6+
CONFIG_PLUGIN_VIRT=y

examples/experimental/virt.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# A template to run ubuntu using vmType: virt instead of qemu (Default)
2+
vmType: "virt"
3+
4+
images:
5+
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"
6+
arch: "x86_64"
7+
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"
8+
arch: "aarch64"
9+
10+
mounts:
11+
- location: "~"
12+
- location: "/tmp/lima"
13+
writable: true

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ require (
4848
k8s.io/client-go v0.28.4
4949
)
5050

51+
// pkg/virt/plugin
52+
require libvirt.org/go/libvirt v1.9008.0
53+
5154
require google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
5255

5356
require (

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5Ohx
418418
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
419419
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
420420
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
421+
libvirt.org/go/libvirt v1.9008.0 h1:LLpjuSQm9gChnx7I/44SLLg/eyvTnJpcMAFmKot65Zc=
422+
libvirt.org/go/libvirt v1.9008.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
421423
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
422424
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
423425
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=

pkg/driverutil/driverutil.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ package driverutil
22

33
import (
44
"github.com/lima-vm/lima/pkg/limayaml"
5+
"github.com/lima-vm/lima/pkg/virt"
56
"github.com/lima-vm/lima/pkg/vz"
67
"github.com/lima-vm/lima/pkg/wsl2"
78
)
89

910
// Drivers returns the available drivers.
1011
func Drivers() []string {
1112
drivers := []string{limayaml.QEMU}
13+
if virt.Enabled {
14+
drivers = append(drivers, limayaml.VIRT)
15+
}
1216
if vz.Enabled {
1317
drivers = append(drivers, limayaml.VZ)
1418
}

pkg/driverutil/instance.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import (
44
"github.com/lima-vm/lima/pkg/driver"
55
"github.com/lima-vm/lima/pkg/limayaml"
66
"github.com/lima-vm/lima/pkg/qemu"
7+
"github.com/lima-vm/lima/pkg/virt"
78
"github.com/lima-vm/lima/pkg/vz"
89
"github.com/lima-vm/lima/pkg/wsl2"
910
)
1011

1112
func CreateTargetDriverInstance(base *driver.BaseDriver) driver.Driver {
1213
limaDriver := base.Yaml.VMType
14+
if *limaDriver == limayaml.VIRT {
15+
return virt.New(base)
16+
}
1317
if *limaDriver == limayaml.VZ {
1418
return vz.New(base)
1519
}

pkg/limayaml/defaults.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,8 @@ func NewArch(arch string) Arch {
848848

849849
func NewVMType(driver string) VMType {
850850
switch driver {
851+
case "virt":
852+
return VIRT
851853
case "vz":
852854
return VZ
853855
case "qemu":

pkg/limayaml/limayaml.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ const (
6262
WSLMount MountType = "wsl2"
6363

6464
QEMU VMType = "qemu"
65+
VIRT VMType = "virt"
6566
VZ VMType = "vz"
6667
WSL2 VMType = "wsl2"
6768
)

pkg/limayaml/validate.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ func Validate(y LimaYAML, warn bool) error {
6161
if !IsNativeArch(*y.Arch) {
6262
return fmt.Errorf("field `arch` must be %q for VZ; got %q", NewArch(runtime.GOARCH), *y.Arch)
6363
}
64+
case VIRT:
65+
// NOP
6466
default:
65-
return fmt.Errorf("field `vmType` must be %q, %q, %q; got %q", QEMU, VZ, WSL2, *y.VMType)
67+
return fmt.Errorf("field `vmType` must be %q, %q, %q, %q; got %q", QEMU, VIRT, VZ, WSL2, *y.VMType)
6668
}
6769

6870
if len(y.Images) == 0 {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package usrlocalliblima
2+
3+
import (
4+
"io/fs"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
func Dir() (string, error) {
10+
self, err := os.Executable()
11+
if err != nil {
12+
return "", err
13+
}
14+
selfSt, err := os.Stat(self)
15+
if err != nil {
16+
return "", err
17+
}
18+
if selfSt.Mode()&fs.ModeSymlink != 0 {
19+
self, err = os.Readlink(self)
20+
if err != nil {
21+
return "", err
22+
}
23+
}
24+
25+
// self: /usr/local/bin/limactl
26+
selfDir := filepath.Dir(self)
27+
selfDirDir := filepath.Dir(selfDir)
28+
libLimaDir := filepath.Join(selfDirDir, "lib", "lima")
29+
if _, err := os.Stat(libLimaDir); err == nil {
30+
return libLimaDir, nil
31+
} else {
32+
return "", err
33+
}
34+
}

pkg/virt/disk.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package virt
2+
3+
import (
4+
"errors"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/docker/go-units"
9+
"github.com/lima-vm/lima/pkg/driver"
10+
"github.com/lima-vm/lima/pkg/fileutils"
11+
"github.com/lima-vm/lima/pkg/iso9660util"
12+
"github.com/lima-vm/lima/pkg/store/filenames"
13+
)
14+
15+
func EnsureDisk(driver *driver.BaseDriver) error {
16+
diffDisk := filepath.Join(driver.Instance.Dir, filenames.DiffDisk)
17+
if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) {
18+
// disk is already ensured
19+
return err
20+
}
21+
22+
baseDisk := filepath.Join(driver.Instance.Dir, filenames.BaseDisk)
23+
if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) {
24+
var ensuredBaseDisk bool
25+
errs := make([]error, len(driver.Yaml.Images))
26+
for i, f := range driver.Yaml.Images {
27+
if _, err := fileutils.DownloadFile(baseDisk, f.File, true, "the image", *driver.Yaml.Arch); err != nil {
28+
errs[i] = err
29+
continue
30+
}
31+
ensuredBaseDisk = true
32+
break
33+
}
34+
if !ensuredBaseDisk {
35+
return fileutils.Errors(errs)
36+
}
37+
}
38+
diskSize, _ := units.RAMInBytes(*driver.Yaml.Disk)
39+
if diskSize == 0 {
40+
return nil
41+
}
42+
isBaseDiskISO, err := iso9660util.IsISO9660(baseDisk)
43+
if err != nil {
44+
return err
45+
}
46+
_ = isBaseDiskISO
47+
// TODO
48+
return nil
49+
}

pkg/virt/plugin/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package main
2+
3+
import (
4+
"libvirt.org/go/libvirt"
5+
)
6+
7+
var VERSION uint32 = libvirt.VERSION_NUMBER
8+
9+
func Version() (uint32, error) { return libvirt.GetVersion() }

pkg/virt/virt_driver_others.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//go:build windows || no_virt
2+
3+
package virt
4+
5+
import (
6+
"context"
7+
"errors"
8+
9+
"github.com/lima-vm/lima/pkg/driver"
10+
)
11+
12+
var ErrUnsupported = errors.New("vm driver 'virt' is not supported")
13+
14+
const Enabled = false
15+
16+
type LimaVirtDriver struct {
17+
*driver.BaseDriver
18+
}
19+
20+
func New(driver *driver.BaseDriver) *LimaVirtDriver {
21+
return &LimaVirtDriver{
22+
BaseDriver: driver,
23+
}
24+
}
25+
26+
func (l *LimaVirtDriver) Validate() error {
27+
return ErrUnsupported
28+
}
29+
30+
func (l *LimaVirtDriver) CreateDisk() error {
31+
return ErrUnsupported
32+
}
33+
34+
func (l *LimaVirtDriver) Start(_ context.Context) (chan error, error) {
35+
return nil, ErrUnsupported
36+
}
37+
38+
func (l *LimaVirtDriver) Stop(_ context.Context) error {
39+
return ErrUnsupported
40+
}

pkg/virt/virt_driver_unix.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//go:build !windows && !no_virt
2+
3+
package virt
4+
5+
import (
6+
"context"
7+
"errors"
8+
"path/filepath"
9+
"plugin"
10+
11+
"github.com/lima-vm/lima/pkg/driver"
12+
"github.com/lima-vm/lima/pkg/usrlocalliblima"
13+
"github.com/sirupsen/logrus"
14+
)
15+
16+
const Enabled = true
17+
18+
type LimaVirtDriver struct {
19+
*driver.BaseDriver
20+
21+
virtPlugin *plugin.Plugin
22+
}
23+
24+
func New(driver *driver.BaseDriver) *LimaVirtDriver {
25+
return &LimaVirtDriver{
26+
BaseDriver: driver,
27+
}
28+
}
29+
30+
func (l *LimaVirtDriver) Validate() error {
31+
dir, err := usrlocalliblima.Dir()
32+
if err != nil {
33+
return err
34+
}
35+
p, err := plugin.Open(filepath.Join(dir, "plugin/virt.so"))
36+
if err != nil {
37+
return err
38+
}
39+
40+
// test variable
41+
v, err := p.Lookup("VERSION")
42+
if err != nil {
43+
return err
44+
}
45+
n := *v.(*uint32)
46+
logrus.Infof("VERSION: %d", n)
47+
// test function
48+
f, err := p.Lookup("Version")
49+
if err != nil {
50+
return err
51+
}
52+
n, err = f.(func() (uint32, error))()
53+
if err != nil {
54+
return err
55+
}
56+
logrus.Infof("Version: %d", n)
57+
58+
l.virtPlugin = p
59+
return nil
60+
}
61+
62+
func (l *LimaVirtDriver) CreateDisk() error {
63+
return EnsureDisk(l.BaseDriver)
64+
}
65+
66+
func (l *LimaVirtDriver) Start(_ context.Context) (chan error, error) {
67+
return nil, errors.New("TODO")
68+
}
69+
70+
func (l *LimaVirtDriver) Stop(_ context.Context) error {
71+
return nil
72+
}

0 commit comments

Comments
 (0)