Skip to content

Commit f95e8b0

Browse files
committed
registry for drivers and expose plugin info in CLI
Signed-off-by: Ansuman Sahoo <[email protected]>
1 parent b94e2fc commit f95e8b0

File tree

4 files changed

+214
-3
lines changed

4 files changed

+214
-3
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/limainfo/limainfo.go

Lines changed: 23 additions & 3 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"
@@ -22,10 +22,15 @@ type LimaInfo struct {
2222
Templates []templatestore.Template `json:"templates"`
2323
DefaultTemplate *limayaml.LimaYAML `json:"defaultTemplate"`
2424
LimaHome string `json:"limaHome"`
25-
VMTypes []string `json:"vmTypes"` // since Lima v0.14.2
25+
VMTypes []string `json:"vmTypes"` // since Lima v0.14.2
26+
VMTypesEx map[string]DriverExt `json:"vmTypesEx"`
2627
GuestAgents map[limayaml.Arch]GuestAgent `json:"guestAgents"` // since Lima v1.1.0
2728
}
2829

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

pkg/usrlocalsharelima/usrlocalsharelima.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,11 @@ func chooseGABinary(candidates []string) (string, error) {
165165
return entries[0], nil
166166
}
167167
}
168+
169+
func Prefix() (string, error) {
170+
dir, err := Dir()
171+
if err != nil {
172+
return "", err
173+
}
174+
return filepath.Dir(filepath.Dir(dir)), nil
175+
}

0 commit comments

Comments
 (0)