Skip to content

Commit bf3f567

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

File tree

4 files changed

+215
-3
lines changed

4 files changed

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

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)