Skip to content

Commit 8404fce

Browse files
committed
driver(external): complete client grpc implementation and one server function
Signed-off-by: Ansuman Sahoo <[email protected]>
1 parent 71c9629 commit 8404fce

File tree

5 files changed

+524
-81
lines changed

5 files changed

+524
-81
lines changed

pkg/driver/external/client/client.go

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -63,54 +63,3 @@ func NewDriverClient(stdin io.WriteCloser, stdout io.ReadCloser, logger *logrus.
6363
logger: logger,
6464
}, nil
6565
}
66-
67-
type PipeConn struct {
68-
Reader io.Reader
69-
Writer io.Writer
70-
}
71-
72-
func (p *PipeConn) Read(b []byte) (n int, err error) {
73-
return p.Reader.Read(b)
74-
}
75-
76-
func (p *PipeConn) Write(b []byte) (n int, err error) {
77-
return p.Writer.Write(b)
78-
}
79-
80-
func (p *PipeConn) Close() error {
81-
var err error
82-
if closer, ok := p.Reader.(io.Closer); ok {
83-
err = closer.Close()
84-
}
85-
if closer, ok := p.Writer.(io.Closer); ok {
86-
if closeErr := closer.Close(); closeErr != nil && err == nil {
87-
err = closeErr
88-
}
89-
}
90-
return err
91-
}
92-
93-
func (p *PipeConn) LocalAddr() net.Addr {
94-
return pipeAddr{}
95-
}
96-
97-
func (p *PipeConn) RemoteAddr() net.Addr {
98-
return pipeAddr{}
99-
}
100-
101-
func (p *PipeConn) SetDeadline(t time.Time) error {
102-
return nil
103-
}
104-
105-
func (p *PipeConn) SetReadDeadline(t time.Time) error {
106-
return nil
107-
}
108-
109-
func (p *PipeConn) SetWriteDeadline(t time.Time) error {
110-
return nil
111-
}
112-
113-
type pipeAddr struct{}
114-
115-
func (pipeAddr) Network() string { return "pipe" }
116-
func (pipeAddr) String() string { return "pipe" }

pkg/driver/external/client/methods.go

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
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/pkg/driver"
16+
pb "github.com/lima-vm/lima/pkg/driver/external"
17+
"github.com/lima-vm/lima/pkg/store"
18+
)
19+
20+
func (d *DriverClient) Validate() error {
21+
d.logger.Debug("Validating driver for the given config")
22+
23+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
24+
defer cancel()
25+
26+
_, err := d.DriverSvc.Validate(ctx, &emptypb.Empty{})
27+
if err != nil {
28+
d.logger.Errorf("Validation failed: %v", err)
29+
return err
30+
}
31+
32+
d.logger.Debug("Driver validated successfully")
33+
return nil
34+
}
35+
36+
func (d *DriverClient) Initialize(ctx context.Context) error {
37+
d.logger.Debug("Initializing driver instance")
38+
39+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
40+
defer cancel()
41+
_, err := d.DriverSvc.Initialize(connCtx, &emptypb.Empty{})
42+
if err != nil {
43+
d.logger.Errorf("Initialization failed: %v", err)
44+
return err
45+
}
46+
47+
d.logger.Debug("Driver instance initialized successfully")
48+
return nil
49+
}
50+
51+
func (d *DriverClient) CreateDisk(ctx context.Context) error {
52+
d.logger.Debug("Creating disk for the instance")
53+
54+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
55+
defer cancel()
56+
_, err := d.DriverSvc.CreateDisk(connCtx, &emptypb.Empty{})
57+
if err != nil {
58+
d.logger.Errorf("Disk creation failed: %v", err)
59+
return err
60+
}
61+
62+
d.logger.Debug("Disk created successfully")
63+
return nil
64+
}
65+
66+
func (d *DriverClient) Start(ctx context.Context) (chan error, error) {
67+
d.logger.Debug("Starting driver instance")
68+
69+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
70+
defer cancel()
71+
stream, err := d.DriverSvc.Start(connCtx, &emptypb.Empty{})
72+
if err != nil {
73+
d.logger.Errorf("Failed to start driver instance: %v", err)
74+
return nil, err
75+
}
76+
77+
errCh := make(chan error, 1)
78+
go func() {
79+
for {
80+
errorStream, err := stream.Recv()
81+
if err != nil {
82+
d.logger.Errorf("Error receiving response from driver: %v", err)
83+
return
84+
}
85+
d.logger.Debugf("Received response: %v", errorStream)
86+
if !errorStream.Success {
87+
errCh <- errors.New(errorStream.Error)
88+
} else {
89+
errCh <- nil
90+
return
91+
}
92+
}
93+
}()
94+
95+
d.logger.Debug("Driver instance started successfully")
96+
return errCh, nil
97+
}
98+
99+
func (d *DriverClient) Stop(ctx context.Context) error {
100+
d.logger.Debug("Stopping driver instance")
101+
102+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
103+
defer cancel()
104+
_, err := d.DriverSvc.Stop(connCtx, &emptypb.Empty{})
105+
if err != nil {
106+
d.logger.Errorf("Failed to stop driver instance: %v", err)
107+
return err
108+
}
109+
110+
d.logger.Debug("Driver instance stopped successfully")
111+
return nil
112+
}
113+
114+
func (d *DriverClient) RunGUI() error {
115+
d.logger.Debug("Running GUI for the driver instance")
116+
117+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
118+
defer cancel()
119+
120+
_, err := d.DriverSvc.RunGUI(ctx, &emptypb.Empty{})
121+
if err != nil {
122+
d.logger.Errorf("Failed to run GUI: %v", err)
123+
return err
124+
}
125+
126+
d.logger.Debug("GUI started successfully")
127+
return nil
128+
}
129+
130+
func (d *DriverClient) ChangeDisplayPassword(ctx context.Context, password string) error {
131+
d.logger.Debug("Changing display password for the driver instance")
132+
133+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
134+
defer cancel()
135+
136+
_, err := d.DriverSvc.ChangeDisplayPassword(connCtx, &pb.ChangeDisplayPasswordRequest{
137+
Password: password,
138+
})
139+
if err != nil {
140+
d.logger.Errorf("Failed to change display password: %v", err)
141+
return err
142+
}
143+
144+
d.logger.Debug("Display password changed successfully")
145+
return nil
146+
}
147+
148+
func (d *DriverClient) GetDisplayConnection(ctx context.Context) (string, error) {
149+
d.logger.Debug("Getting display connection for the driver instance")
150+
151+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
152+
defer cancel()
153+
154+
resp, err := d.DriverSvc.GetDisplayConnection(connCtx, &emptypb.Empty{})
155+
if err != nil {
156+
d.logger.Errorf("Failed to get display connection: %v", err)
157+
return "", err
158+
}
159+
160+
d.logger.Debugf("Display connection retrieved: %s", resp.Connection)
161+
return resp.Connection, nil
162+
}
163+
164+
func (d *DriverClient) CreateSnapshot(ctx context.Context, tag string) error {
165+
d.logger.Debugf("Creating snapshot with tag: %s", tag)
166+
167+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
168+
defer cancel()
169+
170+
_, err := d.DriverSvc.CreateSnapshot(connCtx, &pb.CreateSnapshotRequest{
171+
Tag: tag,
172+
})
173+
if err != nil {
174+
d.logger.Errorf("Failed to create snapshot: %v", err)
175+
return err
176+
}
177+
178+
d.logger.Debugf("Snapshot '%s' created successfully", tag)
179+
return nil
180+
}
181+
182+
func (d *DriverClient) ApplySnapshot(ctx context.Context, tag string) error {
183+
d.logger.Debugf("Applying snapshot with tag: %s", tag)
184+
185+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
186+
defer cancel()
187+
188+
_, err := d.DriverSvc.ApplySnapshot(connCtx, &pb.ApplySnapshotRequest{
189+
Tag: tag,
190+
})
191+
if err != nil {
192+
d.logger.Errorf("Failed to apply snapshot: %v", err)
193+
return err
194+
}
195+
196+
d.logger.Debugf("Snapshot '%s' applied successfully", tag)
197+
return nil
198+
}
199+
200+
func (d *DriverClient) DeleteSnapshot(ctx context.Context, tag string) error {
201+
d.logger.Debugf("Deleting snapshot with tag: %s", tag)
202+
203+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
204+
defer cancel()
205+
206+
_, err := d.DriverSvc.DeleteSnapshot(connCtx, &pb.DeleteSnapshotRequest{
207+
Tag: tag,
208+
})
209+
if err != nil {
210+
d.logger.Errorf("Failed to delete snapshot: %v", err)
211+
return err
212+
}
213+
214+
d.logger.Debugf("Snapshot '%s' deleted successfully", tag)
215+
return nil
216+
}
217+
218+
func (d *DriverClient) ListSnapshots(ctx context.Context) (string, error) {
219+
d.logger.Debug("Listing snapshots")
220+
221+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
222+
defer cancel()
223+
224+
resp, err := d.DriverSvc.ListSnapshots(connCtx, &emptypb.Empty{})
225+
if err != nil {
226+
d.logger.Errorf("Failed to list snapshots: %v", err)
227+
return "", err
228+
}
229+
230+
d.logger.Debugf("Snapshots listed successfully: %s", resp.Snapshots)
231+
return resp.Snapshots, nil
232+
}
233+
234+
func (d *DriverClient) Register(ctx context.Context) error {
235+
d.logger.Debug("Registering driver instance")
236+
237+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
238+
defer cancel()
239+
_, err := d.DriverSvc.Register(connCtx, &emptypb.Empty{})
240+
if err != nil {
241+
d.logger.Errorf("Failed to register driver instance: %v", err)
242+
return err
243+
}
244+
245+
d.logger.Debug("Driver instance registered successfully")
246+
return nil
247+
}
248+
249+
func (d *DriverClient) Unregister(ctx context.Context) error {
250+
d.logger.Debug("Unregistering driver instance")
251+
252+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
253+
defer cancel()
254+
255+
_, err := d.DriverSvc.Unregister(connCtx, &emptypb.Empty{})
256+
if err != nil {
257+
d.logger.Errorf("Failed to unregister driver instance: %v", err)
258+
return err
259+
}
260+
261+
d.logger.Debug("Driver instance unregistered successfully")
262+
return nil
263+
}
264+
265+
func (d *DriverClient) ForwardGuestAgent() bool {
266+
d.logger.Debug("Checking if guest agent needs to be forwarded")
267+
268+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
269+
defer cancel()
270+
271+
resp, err := d.DriverSvc.ForwardGuestAgent(ctx, &emptypb.Empty{})
272+
if err != nil {
273+
d.logger.Errorf("Failed to check guest agent forwarding: %v", err)
274+
return false
275+
}
276+
277+
d.logger.Debugf("Guest agent forwarding status: %v", resp.ShouldForward)
278+
return resp.ShouldForward
279+
}
280+
281+
// NOTE: This method is might not work correctly.
282+
func (d *DriverClient) GuestAgentConn(ctx context.Context) (net.Conn, error) {
283+
d.logger.Debug("Getting guest agent connection")
284+
285+
connCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
286+
defer cancel()
287+
288+
connStream, err := d.DriverSvc.GuestAgentConn(connCtx, &emptypb.Empty{})
289+
if err != nil {
290+
d.logger.Errorf("Failed to get guest agent connection: %v", err)
291+
return nil, err
292+
}
293+
294+
return streamToConn(connStream), nil
295+
}
296+
297+
func (d *DriverClient) GetInfo() driver.Info {
298+
d.logger.Debug("Getting driver info")
299+
300+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
301+
defer cancel()
302+
303+
resp, err := d.DriverSvc.GetInfo(ctx, &emptypb.Empty{})
304+
if err != nil {
305+
d.logger.Errorf("Failed to get driver info: %v", err)
306+
return driver.Info{}
307+
}
308+
309+
var info driver.Info
310+
if err := json.Unmarshal(resp.InfoJson, &info); err != nil {
311+
d.logger.Errorf("Failed to unmarshal driver info: %v", err)
312+
return driver.Info{}
313+
}
314+
315+
d.logger.Debugf("Driver info retrieved: %+v", info)
316+
return info
317+
}
318+
319+
func (d *DriverClient) SetConfig(inst *store.Instance, sshLocalPort int) {
320+
d.logger.Debugf("Setting config for instance %s with SSH local port %d", inst.Name, sshLocalPort)
321+
322+
instJson, err := json.Marshal(inst)
323+
if err != nil {
324+
d.logger.Errorf("Failed to marshal instance config: %v", err)
325+
return
326+
}
327+
328+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
329+
defer cancel()
330+
331+
_, err = d.DriverSvc.SetConfig(ctx, &pb.SetConfigRequest{
332+
InstanceConfigJson: instJson,
333+
SshLocalPort: int64(sshLocalPort),
334+
})
335+
if err != nil {
336+
d.logger.Errorf("Failed to set config: %v", err)
337+
return
338+
}
339+
340+
d.logger.Debugf("Config set successfully for instance %s", inst.Name)
341+
}

0 commit comments

Comments
 (0)