Skip to content

Commit d16de8a

Browse files
authored
Merge pull request #3692 from unsuman/feature/driver-registry
Feature: Registry for drivers and expose driver info in CLI
2 parents 4192b7c + 6beccf5 commit d16de8a

File tree

5 files changed

+224
-24
lines changed

5 files changed

+224
-24
lines changed

cmd/limactl/start.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/lima-vm/lima/pkg/limatmpl"
2222
"github.com/lima-vm/lima/pkg/limayaml"
2323
networks "github.com/lima-vm/lima/pkg/networks/reconcile"
24+
"github.com/lima-vm/lima/pkg/registry"
2425
"github.com/lima-vm/lima/pkg/store"
2526
"github.com/lima-vm/lima/pkg/store/filenames"
2627
"github.com/lima-vm/lima/pkg/templatestore"
@@ -32,6 +33,7 @@ func registerCreateFlags(cmd *cobra.Command, commentPrefix string) {
3233
flags := cmd.Flags()
3334
flags.String("name", "", commentPrefix+"Override the instance name")
3435
flags.Bool("list-templates", false, commentPrefix+"List available templates and exit")
36+
flags.Bool("list-drivers", false, commentPrefix+"List available drivers and exit")
3537
editflags.RegisterCreate(cmd, commentPrefix)
3638
}
3739

@@ -393,6 +395,14 @@ func createStartActionCommon(cmd *cobra.Command, _ []string) (exit bool, err err
393395
_, _ = fmt.Fprintln(w, f.Name)
394396
}
395397
return true, nil
398+
} else if listDrivers, err := cmd.Flags().GetBool("list-drivers"); err != nil {
399+
return true, err
400+
} else if listDrivers {
401+
w := cmd.OutOrStdout()
402+
for k := range registry.List() {
403+
_, _ = fmt.Fprintln(w, k)
404+
}
405+
return true, nil
396406
}
397407
return false, nil
398408
}

pkg/driverutil/driverutil.go

Lines changed: 0 additions & 22 deletions
This file was deleted.

pkg/limainfo/limainfo.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99

1010
"github.com/sirupsen/logrus"
1111

12-
"github.com/lima-vm/lima/pkg/driverutil"
1312
"github.com/lima-vm/lima/pkg/limayaml"
13+
"github.com/lima-vm/lima/pkg/registry"
1414
"github.com/lima-vm/lima/pkg/store/dirnames"
1515
"github.com/lima-vm/lima/pkg/templatestore"
1616
"github.com/lima-vm/lima/pkg/usrlocalsharelima"
@@ -23,9 +23,14 @@ type LimaInfo struct {
2323
DefaultTemplate *limayaml.LimaYAML `json:"defaultTemplate"`
2424
LimaHome string `json:"limaHome"`
2525
VMTypes []string `json:"vmTypes"` // since Lima v0.14.2
26+
VMTypesEx map[string]DriverExt `json:"vmTypesEx"` // since Lima v2.0.0
2627
GuestAgents map[limayaml.Arch]GuestAgent `json:"guestAgents"` // since Lima v1.1.0
2728
}
2829

30+
type DriverExt struct {
31+
Location string `json:"location,omitempty"` // since Lima v2.0.0
32+
}
33+
2934
type GuestAgent struct {
3035
Location string `json:"location"` // since Lima v1.1.0
3136
}
@@ -42,10 +47,25 @@ func New() (*LimaInfo, error) {
4247
if err != nil {
4348
return nil, err
4449
}
50+
51+
reg := registry.List()
52+
if len(reg) == 0 {
53+
return nil, errors.New("no VM types found; ensure that the drivers are properly registered")
54+
}
55+
vmTypesEx := make(map[string]DriverExt)
56+
var vmTypes []string
57+
for name, path := range reg {
58+
vmTypesEx[name] = DriverExt{
59+
Location: path,
60+
}
61+
vmTypes = append(vmTypes, name)
62+
}
63+
4564
info := &LimaInfo{
4665
Version: version.Version,
4766
DefaultTemplate: y,
48-
VMTypes: driverutil.Drivers(),
67+
VMTypes: vmTypes,
68+
VMTypesEx: vmTypesEx,
4969
GuestAgents: make(map[limayaml.Arch]GuestAgent),
5070
}
5171
info.Templates, err = templatestore.Templates()

pkg/registry/registry.go

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// SPDX-FileCopyrightText: Copyright The Lima Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package registry
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"os"
10+
"os/exec"
11+
"path/filepath"
12+
"strings"
13+
14+
"github.com/sirupsen/logrus"
15+
16+
"github.com/lima-vm/lima/pkg/driver"
17+
"github.com/lima-vm/lima/pkg/driver/vz"
18+
"github.com/lima-vm/lima/pkg/driver/wsl2"
19+
"github.com/lima-vm/lima/pkg/limayaml"
20+
"github.com/lima-vm/lima/pkg/usrlocalsharelima"
21+
)
22+
23+
const (
24+
Internal = "internal"
25+
)
26+
27+
type ExternalDriver struct {
28+
Name string
29+
InstanceName string
30+
Command *exec.Cmd
31+
SocketPath string
32+
Path string
33+
Ctx context.Context
34+
Logger *logrus.Logger
35+
CancelFunc context.CancelFunc
36+
}
37+
38+
var (
39+
internalDrivers = make(map[string]driver.Driver)
40+
ExternalDrivers = make(map[string]*ExternalDriver)
41+
)
42+
43+
func List() map[string]string {
44+
if err := discoverDrivers(); err != nil {
45+
logrus.Warnf("Error discovering drivers: %v", err)
46+
}
47+
48+
vmTypes := make(map[string]string)
49+
for name := range internalDrivers {
50+
vmTypes[name] = Internal
51+
}
52+
for name, d := range ExternalDrivers {
53+
vmTypes[name] = d.Path
54+
}
55+
56+
// This block will be removed while merging the internal driver pull request(#3693).
57+
if len(vmTypes) == 0 {
58+
vmTypes[limayaml.QEMU] = Internal
59+
if vz.Enabled {
60+
vmTypes[limayaml.VZ] = Internal
61+
}
62+
if wsl2.Enabled {
63+
vmTypes[limayaml.WSL2] = Internal
64+
}
65+
}
66+
67+
return vmTypes
68+
}
69+
70+
func Get(name string) (*ExternalDriver, driver.Driver, bool) {
71+
if err := discoverDrivers(); err != nil {
72+
logrus.Warnf("Error discovering drivers: %v", err)
73+
}
74+
75+
internalDriver, exists := internalDrivers[name]
76+
if !exists {
77+
externalDriver, exists := ExternalDrivers[name]
78+
if exists {
79+
return externalDriver, nil, exists
80+
}
81+
}
82+
return nil, internalDriver, exists
83+
}
84+
85+
func registerExternalDriver(name, path string) {
86+
if _, exists := ExternalDrivers[name]; exists {
87+
return
88+
}
89+
90+
if _, exists := internalDrivers[name]; exists {
91+
logrus.Debugf("Driver %q is already registered as an internal driver, skipping external registration", name)
92+
return
93+
}
94+
95+
ExternalDrivers[name] = &ExternalDriver{
96+
Name: name,
97+
Path: path,
98+
Logger: logrus.New(),
99+
}
100+
}
101+
102+
func discoverDrivers() error {
103+
prefix, err := usrlocalsharelima.Prefix()
104+
if err != nil {
105+
return err
106+
}
107+
stdDriverDir := filepath.Join(prefix, "libexec", "lima")
108+
109+
logrus.Debugf("Discovering external drivers in %s", stdDriverDir)
110+
if _, err := os.Stat(stdDriverDir); err == nil {
111+
if err := discoverDriversInDir(stdDriverDir); err != nil {
112+
logrus.Warnf("Error discovering external drivers in %q: %v", stdDriverDir, err)
113+
}
114+
}
115+
116+
if driverPaths := os.Getenv("LIMA_DRIVERS_PATH"); driverPaths != "" {
117+
paths := filepath.SplitList(driverPaths)
118+
for _, path := range paths {
119+
if path == "" {
120+
continue
121+
}
122+
123+
info, err := os.Stat(path)
124+
if err != nil {
125+
logrus.Warnf("Error accessing external driver path %q: %v", path, err)
126+
continue
127+
}
128+
129+
if info.IsDir() {
130+
if err := discoverDriversInDir(path); err != nil {
131+
logrus.Warnf("Error discovering external drivers in %q: %v", path, err)
132+
}
133+
} else if isExecutable(info.Mode()) {
134+
registerDriverFile(path)
135+
}
136+
}
137+
}
138+
139+
return nil
140+
}
141+
142+
func discoverDriversInDir(dir string) error {
143+
entries, err := os.ReadDir(dir)
144+
if err != nil {
145+
return fmt.Errorf("failed to read driver directory %q: %w", dir, err)
146+
}
147+
148+
for _, entry := range entries {
149+
if entry.IsDir() {
150+
continue
151+
}
152+
153+
info, err := entry.Info()
154+
if err != nil {
155+
logrus.Warnf("Failed to get info for %q: %v", entry.Name(), err)
156+
continue
157+
}
158+
159+
if !isExecutable(info.Mode()) {
160+
continue
161+
}
162+
163+
driverPath := filepath.Join(dir, entry.Name())
164+
registerDriverFile(driverPath)
165+
}
166+
167+
return nil
168+
}
169+
170+
func registerDriverFile(path string) {
171+
base := filepath.Base(path)
172+
if !strings.HasPrefix(base, "lima-driver-") {
173+
return
174+
}
175+
176+
name := strings.TrimPrefix(base, "lima-driver-")
177+
178+
registerExternalDriver(name, path)
179+
}
180+
181+
func isExecutable(mode os.FileMode) bool {
182+
return mode&0o111 != 0
183+
}

pkg/usrlocalsharelima/usrlocalsharelima.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,12 @@ func chooseGABinary(candidates []string) (string, error) {
165165
return entries[0], nil
166166
}
167167
}
168+
169+
// Prefix returns the <PREFIX> directory, which is two levels above the lima share directory.
170+
func Prefix() (string, error) {
171+
dir, err := Dir()
172+
if err != nil {
173+
return "", err
174+
}
175+
return filepath.Dir(filepath.Dir(dir)), nil
176+
}

0 commit comments

Comments
 (0)