Skip to content

Commit 9b373ed

Browse files
committed
add WriteFile
1 parent 5c1d940 commit 9b373ed

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

proxmox/websocket.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package proxmox
22

33
import (
44
"context"
5+
"encoding/base64"
56
"fmt"
67
"regexp"
78
"strconv"
89
"strings"
10+
"time"
911

1012
"github.com/pkg/errors"
1113

@@ -19,7 +21,8 @@ const (
1921
)
2022

2123
type VNCWebSocketClient struct {
22-
conn *websocket.Conn
24+
conn *websocket.Conn
25+
ticker *time.Ticker
2326
}
2427

2528
func (s *Service) NewNodeVNCWebSocketConnection(ctx context.Context, nodeName string) (*VNCWebSocketClient, error) {
@@ -32,11 +35,22 @@ func (s *Service) NewNodeVNCWebSocketConnection(ctx context.Context, nodeName st
3235
return nil, err
3336
}
3437

35-
return &VNCWebSocketClient{conn: conn}, nil
38+
ticker := time.NewTicker(30 * time.Second)
39+
go func() {
40+
for {
41+
select {
42+
case <-ticker.C:
43+
conn.WriteMessage(websocket.BinaryMessage, []byte("2"))
44+
}
45+
}
46+
}()
47+
48+
return &VNCWebSocketClient{conn: conn, ticker: ticker}, nil
3649
}
3750

3851
func (c *VNCWebSocketClient) Close() {
3952
c.conn.Close()
53+
c.ticker.Stop()
4054
}
4155

4256
func (c *VNCWebSocketClient) Write(cmd string) error {
@@ -49,6 +63,38 @@ func (c *VNCWebSocketClient) Write(cmd string) error {
4963
return c.sendFinMessage()
5064
}
5165

66+
func (c *VNCWebSocketClient) WriteFile(ctx context.Context, content, path string) error {
67+
c.Exec(ctx, fmt.Sprintf("rm %s", path))
68+
if _, _, err := c.Exec(ctx, fmt.Sprintf("touch %s", path)); err != nil {
69+
return err
70+
}
71+
chunks := chunkString(content, 3000)
72+
for _, chunk := range chunks {
73+
b64chunk := base64.StdEncoding.EncodeToString([]byte(chunk))
74+
_, _, err := c.Exec(ctx, fmt.Sprintf("echo %s | base64 -d >> %s", b64chunk, path))
75+
if err != nil {
76+
return err
77+
}
78+
}
79+
return nil
80+
}
81+
82+
func chunkString(s string, chunkSize int) []string {
83+
var chunks []string
84+
runes := []rune(s)
85+
if len(runes) == 0 {
86+
return []string{s}
87+
}
88+
for i := 0; i < len(runes); i += chunkSize {
89+
nn := i + chunkSize
90+
if nn > len(runes) {
91+
nn = len(runes)
92+
}
93+
chunks = append(chunks, string(runes[i:nn]))
94+
}
95+
return chunks
96+
}
97+
5298
func (c *VNCWebSocketClient) sendFinMessage() error {
5399
b := []byte(fmt.Sprintf(`echo "%s$?"%s`, finMessage, "\n"))
54100
bheader := []byte(fmt.Sprintf("0:%d:", len(b)))

proxmox/websocket_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ func (s *TestSuite) TestExec() {
4343
s.T().Logf("exec command : %s : %d", out, code)
4444
}
4545

46+
func (s *TestSuite) TestWriteFile() {
47+
testNode := s.getTestNode()
48+
client, err := s.service.NewNodeVNCWebSocketConnection(context.TODO(), testNode.Node)
49+
if err != nil {
50+
s.T().Fatalf("failed to create new vnc client: %v", err)
51+
}
52+
defer client.Close()
53+
54+
ctx, _ := context.WithTimeout(context.TODO(), 15*time.Second)
55+
err = client.WriteFile(ctx, "this is a file content", "~/test-write-file.txt")
56+
if err != nil {
57+
s.T().Fatalf("failed to exec command: %v", err)
58+
}
59+
}
60+
4661
func TestParseFinMessage(t *testing.T) {
4762
testMsg := " daf" + finMessage + "123\n"
4863
if parseFinMessage(testMsg) == "" {

0 commit comments

Comments
 (0)