Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/pkg/driver/external/client/methods.go
2611 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package client
5
6
import (
7
"context"
8
"encoding/json"
9
"errors"
10
"net"
11
"time"
12
13
"google.golang.org/protobuf/types/known/emptypb"
14
15
"github.com/lima-vm/lima/v2/pkg/driver"
16
pb "github.com/lima-vm/lima/v2/pkg/driver/external"
17
"github.com/lima-vm/lima/v2/pkg/limatype"
18
)
19
20
func (d *DriverClient) Validate(ctx context.Context) error {
21
d.logger.Debug("Validating driver for the given config")
22
23
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
24
defer cancel()
25
_, err := d.DriverSvc.Validate(ctx, &emptypb.Empty{})
26
if err != nil {
27
d.logger.WithError(err).Error("Validation failed")
28
return err
29
}
30
31
d.logger.Debug("Driver validated successfully")
32
return nil
33
}
34
35
func (d *DriverClient) Create(ctx context.Context) error {
36
d.logger.Debug("Initializing driver instance")
37
38
_, err := d.DriverSvc.Create(ctx, &emptypb.Empty{})
39
if err != nil {
40
d.logger.WithError(err).Error("Initialization failed")
41
return err
42
}
43
44
d.logger.Debug("Driver instance initialized successfully")
45
return nil
46
}
47
48
func (d *DriverClient) CreateDisk(ctx context.Context) error {
49
d.logger.Debug("Creating disk for the instance")
50
51
_, err := d.DriverSvc.CreateDisk(ctx, &emptypb.Empty{})
52
if err != nil {
53
d.logger.WithError(err).Error("Disk creation failed")
54
return err
55
}
56
57
d.logger.Debug("Disk created successfully")
58
return nil
59
}
60
61
// Start initiates the driver instance and receives streaming responses. It blocks until
62
// receiving the initial success response, then spawns a goroutine to consume subsequent
63
// error messages from the stream. Any errors from the driver are sent to the channel.
64
func (d *DriverClient) Start(ctx context.Context) (chan error, error) {
65
d.logger.Debug("Starting driver instance")
66
67
stream, err := d.DriverSvc.Start(ctx, &emptypb.Empty{})
68
if err != nil {
69
d.logger.WithError(err).Error("Failed to start driver instance")
70
return nil, err
71
}
72
73
// Blocking to receive an initial response to ensure Start() is initiated
74
// at the server-side.
75
initialResp, err := stream.Recv()
76
if err != nil {
77
d.logger.WithError(err).Error("Error receiving initial response from driver start")
78
return nil, err
79
}
80
if !initialResp.Success {
81
return nil, errors.New(initialResp.Error)
82
}
83
84
go func() {
85
<-ctx.Done()
86
if closeErr := stream.CloseSend(); closeErr != nil {
87
d.logger.WithError(closeErr).Warn("Failed to close stream")
88
}
89
}()
90
91
errCh := make(chan error, 1)
92
go func() {
93
for {
94
respStream, err := stream.Recv()
95
if err != nil {
96
d.logger.Infof("Error receiving response from driver: %v", err)
97
return
98
}
99
d.logger.Debugf("Received response: %v", respStream)
100
if !respStream.Success {
101
errCh <- errors.New(respStream.Error)
102
} else {
103
close(errCh)
104
return
105
}
106
}
107
}()
108
109
d.logger.Debug("Driver instance started successfully")
110
return errCh, nil
111
}
112
113
func (d *DriverClient) Stop(ctx context.Context) error {
114
d.logger.Debug("Stopping driver instance")
115
116
_, err := d.DriverSvc.Stop(ctx, &emptypb.Empty{})
117
if err != nil {
118
d.logger.WithError(err).Error("Failed to stop driver instance")
119
return err
120
}
121
122
d.logger.Debug("Driver instance stopped successfully")
123
return nil
124
}
125
126
func (d *DriverClient) Delete(ctx context.Context) error {
127
d.logger.Debug("Deleting driver instance")
128
129
_, err := d.DriverSvc.Delete(ctx, &emptypb.Empty{})
130
if err != nil {
131
d.logger.WithError(err).Error("Failed to deleted driver instance")
132
return err
133
}
134
135
d.logger.Debug("Driver instance deleted successfully")
136
return nil
137
}
138
139
func (d *DriverClient) FillConfig(_ context.Context, _ *limatype.LimaYAML, _ string) error {
140
return errors.New("pre-configured driver action not implemented in client driver")
141
}
142
143
func (d *DriverClient) RunGUI() error {
144
d.logger.Debug("Running GUI for the driver instance")
145
146
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
147
defer cancel()
148
149
_, err := d.DriverSvc.RunGUI(ctx, &emptypb.Empty{})
150
if err != nil {
151
d.logger.WithError(err).Error("Failed to run GUI")
152
return err
153
}
154
155
d.logger.Debug("GUI started successfully")
156
return nil
157
}
158
159
func (d *DriverClient) ChangeDisplayPassword(ctx context.Context, password string) error {
160
d.logger.Debug("Changing display password for the driver instance")
161
162
_, err := d.DriverSvc.ChangeDisplayPassword(ctx, &pb.ChangeDisplayPasswordRequest{
163
Password: password,
164
})
165
if err != nil {
166
d.logger.WithError(err).Error("Failed to change display password")
167
return err
168
}
169
170
d.logger.Debug("Display password changed successfully")
171
return nil
172
}
173
174
func (d *DriverClient) DisplayConnection(ctx context.Context) (string, error) {
175
d.logger.Debug("Getting display connection for the driver instance")
176
177
resp, err := d.DriverSvc.GetDisplayConnection(ctx, &emptypb.Empty{})
178
if err != nil {
179
d.logger.WithError(err).Error("Failed to get display connection")
180
return "", err
181
}
182
183
d.logger.Debugf("Display connection retrieved: %s", resp.Connection)
184
return resp.Connection, nil
185
}
186
187
func (d *DriverClient) CreateSnapshot(ctx context.Context, tag string) error {
188
d.logger.Debugf("Creating snapshot with tag: %s", tag)
189
190
_, err := d.DriverSvc.CreateSnapshot(ctx, &pb.CreateSnapshotRequest{
191
Tag: tag,
192
})
193
if err != nil {
194
d.logger.WithError(err).Error("Failed to create snapshot")
195
return err
196
}
197
198
d.logger.Debugf("Snapshot '%s' created successfully", tag)
199
return nil
200
}
201
202
func (d *DriverClient) ApplySnapshot(ctx context.Context, tag string) error {
203
d.logger.Debugf("Applying snapshot with tag: %s", tag)
204
205
_, err := d.DriverSvc.ApplySnapshot(ctx, &pb.ApplySnapshotRequest{
206
Tag: tag,
207
})
208
if err != nil {
209
d.logger.WithError(err).Error("Failed to apply snapshot")
210
return err
211
}
212
213
d.logger.Debugf("Snapshot '%s' applied successfully", tag)
214
return nil
215
}
216
217
func (d *DriverClient) DeleteSnapshot(ctx context.Context, tag string) error {
218
d.logger.Debugf("Deleting snapshot with tag: %s", tag)
219
220
_, err := d.DriverSvc.DeleteSnapshot(ctx, &pb.DeleteSnapshotRequest{
221
Tag: tag,
222
})
223
if err != nil {
224
d.logger.WithError(err).Error("Failed to delete snapshot")
225
return err
226
}
227
228
d.logger.Debugf("Snapshot '%s' deleted successfully", tag)
229
return nil
230
}
231
232
func (d *DriverClient) ListSnapshots(ctx context.Context) (string, error) {
233
d.logger.Debug("Listing snapshots")
234
235
resp, err := d.DriverSvc.ListSnapshots(ctx, &emptypb.Empty{})
236
if err != nil {
237
d.logger.WithError(err).Error("Failed to list snapshots")
238
return "", err
239
}
240
241
d.logger.Debugf("Snapshots listed successfully: %s", resp.Snapshots)
242
return resp.Snapshots, nil
243
}
244
245
func (d *DriverClient) ForwardGuestAgent() bool {
246
d.logger.Debug("Checking if guest agent needs to be forwarded")
247
248
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
249
defer cancel()
250
251
resp, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{})
252
if err != nil {
253
d.logger.WithError(err).Error("Failed to check guest agent forwarding")
254
return false
255
}
256
257
return resp.ShouldForward
258
}
259
260
func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, string, error) {
261
d.logger.Info("Getting guest agent connection")
262
_, err := d.DriverSvc.GuestAgentConn(ctx, &emptypb.Empty{})
263
if err != nil {
264
d.logger.WithError(err).Error("Failed to get guest agent connection")
265
return nil, "", err
266
}
267
268
return nil, "", nil
269
}
270
271
func (d *DriverClient) Info() driver.Info {
272
d.logger.Debug("Getting driver info")
273
274
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
275
defer cancel()
276
277
resp, err := d.DriverSvc.Info(ctx, &emptypb.Empty{})
278
if err != nil {
279
d.logger.WithError(err).Error("Failed to get driver info")
280
return driver.Info{}
281
}
282
283
var info driver.Info
284
if err := json.Unmarshal(resp.InfoJson, &info); err != nil {
285
d.logger.WithError(err).Error("Failed to unmarshal driver info")
286
return driver.Info{}
287
}
288
289
d.logger.Debugf("Driver info retrieved: %+v", info)
290
return info
291
}
292
293
func (d *DriverClient) Configure(inst *limatype.Instance) *driver.ConfiguredDriver {
294
d.logger.Debugf("Setting config for instance %s with SSH local port %d", inst.Name, inst.SSHLocalPort)
295
296
instJSON, err := inst.MarshalJSON()
297
if err != nil {
298
d.logger.WithError(err).Error("Failed to marshal instance config")
299
return nil
300
}
301
302
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
303
defer cancel()
304
305
_, err = d.DriverSvc.Configure(ctx, &pb.SetConfigRequest{
306
InstanceConfigJson: instJSON,
307
})
308
if err != nil {
309
d.logger.WithError(err).Error("Failed to set config")
310
return nil
311
}
312
313
d.logger.Debugf("Config set successfully for instance %s", inst.Name)
314
return &driver.ConfiguredDriver{
315
Driver: d,
316
}
317
}
318
319
func (d *DriverClient) InspectStatus(_ context.Context, _ *limatype.Instance) string {
320
return ""
321
}
322
323
func (d *DriverClient) SSHAddress(ctx context.Context) (string, error) {
324
d.logger.Debug("Getting SSH address for the driver instance")
325
326
resp, err := d.DriverSvc.SSHAddress(ctx, &emptypb.Empty{})
327
if err != nil {
328
d.logger.WithError(err).Error("Failed to get SSH address")
329
return "", err
330
}
331
332
d.logger.Debugf("SSH address retrieved: %s", resp.Address)
333
return resp.Address, nil
334
}
335
336
func (d *DriverClient) BootScripts() (map[string][]byte, error) {
337
d.logger.Debug("Getting boot scripts for the driver instance")
338
resp, err := d.DriverSvc.BootScripts(context.Background(), &emptypb.Empty{})
339
if err != nil {
340
d.logger.WithError(err).Error("Failed to get boot scripts")
341
return nil, err
342
}
343
344
d.logger.Debugf("Boot scripts retrieved successfully: %d scripts", len(resp.Scripts))
345
return resp.Scripts, nil
346
}
347
348
func (d *DriverClient) AdditionalSetupForSSH(ctx context.Context) error {
349
d.logger.Debug("Performing additional setup for SSH connection")
350
351
_, err := d.DriverSvc.AdditionalSetupForSSH(ctx, &emptypb.Empty{})
352
if err != nil {
353
d.logger.WithError(err).Error("Failed to perform additional setup for SSH")
354
return err
355
}
356
357
d.logger.Debug("Additional setup for SSH completed successfully")
358
return nil
359
}
360
361