Skip to content

Commit bf81716

Browse files
committed
fix vm status / task
1 parent 9009960 commit bf81716

File tree

7 files changed

+173
-9
lines changed

7 files changed

+173
-9
lines changed

api/qemu_type.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,40 @@ type VirtualMachineConfig struct {
242242
// Cloud-init interfaces
243243
// IPConfig
244244
}
245+
246+
type VirtualMachineRebootOption struct {
247+
TimeOut int `json:"timeout,omitempty"`
248+
}
249+
250+
type VirtualMachineResumeOption struct {
251+
NoCheck bool `json:"nocheck,omitempty"`
252+
SkipLock bool `json:"skiplock,omitempty"`
253+
}
254+
255+
type VirtualMachineStartOption struct {
256+
// override qemu's -cpu argument with the given string
257+
ForceCPU string `json:"force-cpu,omitempty"`
258+
// specifies the qemu machine type
259+
Machine string `json:"machine,omitempty"`
260+
// cluster node name
261+
MigratedFroom string `json:"migratedfrom,omitempty"`
262+
// cidr of (sub) network that is used for migration
263+
MigrationNetwork string `json:"migration_network,omitempty"`
264+
// migration traffic is ecrypted using an SSH tunnel by default.
265+
// On secure, completely private networks this can be disabled to increase performance.
266+
MigrationType string `json:"migration_type,omitempty"`
267+
SkipLock bool `json:"skiplock,omitempty"`
268+
// some command save/restore state from this location
269+
StateURI string `json:"stateuri,omitempty"`
270+
// Mapping from source to target storages. Providing only a single storage ID maps all source storages to that storage.
271+
// Providing the special value '1' will map each source storage to itself.
272+
TargetStoraage string `json:"targetstorage,omitempty"`
273+
TimeOut int `json:"timeout,omitempty"`
274+
}
275+
276+
type VirtualMachineStopOption struct {
277+
KeepActive bool `json:"keepActive,omitempty"`
278+
MigratedFrom string `json:"migratedfrom,omitempty"`
279+
SkipLock bool `json:"skiplock,omitempty"`
280+
TimeOut int `json:"timeout,omitempty"`
281+
}

proxmox/qemu.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,28 +152,28 @@ func (c *VirtualMachine) ResizeVolume(ctx context.Context, disk, size string) er
152152
return nil
153153
}
154154

155-
func (c *VirtualMachine) Start(ctx context.Context) error {
155+
func (c *VirtualMachine) Start(ctx context.Context, option api.VirtualMachineStartOption) error {
156156
path := fmt.Sprintf("/nodes/%s/qemu/%d/status/start", c.Node, c.VM.VMID)
157157
var upid string
158-
if err := c.restclient.Post(ctx, path, nil, &upid); err != nil {
158+
if err := c.restclient.Post(ctx, path, option, &upid); err != nil {
159159
return err
160160
}
161161
return c.service.EnsureTaskDone(ctx, c.Node, upid)
162162
}
163163

164-
func (c *VirtualMachine) Stop(ctx context.Context) error {
164+
func (c *VirtualMachine) Stop(ctx context.Context, option api.VirtualMachineStopOption) error {
165165
path := fmt.Sprintf("/nodes/%s/qemu/%d/status/stop", c.Node, c.VM.VMID)
166166
var upid string
167-
if err := c.restclient.Post(ctx, path, nil, &upid); err != nil {
167+
if err := c.restclient.Post(ctx, path, option, &upid); err != nil {
168168
return err
169169
}
170170
return c.service.EnsureTaskDone(ctx, c.Node, upid)
171171
}
172172

173-
func (c *VirtualMachine) Resume(ctx context.Context) error {
173+
func (c *VirtualMachine) Resume(ctx context.Context, option api.VirtualMachineResumeOption) error {
174174
path := fmt.Sprintf("/nodes/%s/qemu/%d/status/resume", c.Node, c.VM.VMID)
175175
var upid string
176-
if err := c.restclient.Post(ctx, path, nil, &upid); err != nil {
176+
if err := c.restclient.Post(ctx, path, option, &upid); err != nil {
177177
return err
178178
}
179179
return c.service.EnsureTaskDone(ctx, c.Node, upid)

proxmox/qemu_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package proxmox
2+
3+
import (
4+
"context"
5+
6+
"github.com/sp-yduck/proxmox-go/api"
7+
)
8+
9+
func (s *TestSuite) TestVirtualMachine() {
10+
_, testVM := s.getTestVirtualMachine()
11+
vm, err := s.service.VirtualMachine(context.TODO(), testVM.VM.VMID)
12+
if err != nil {
13+
s.T().Fatalf("failed to get vm(vmid=%d): %v", testVM.VM.VMID, err)
14+
}
15+
s.Assert().Equal(*vm, *testVM)
16+
}
17+
18+
func (s *TestSuite) TestStop() {
19+
_, testVM := s.getTestVirtualMachine()
20+
if err := testVM.Stop(context.TODO(), api.VirtualMachineStopOption{}); err != nil {
21+
s.T().Fatalf("failed to stop vm: %v", err)
22+
}
23+
}
24+
25+
func (s *TestSuite) getTestNode() *api.Node {
26+
nodes, err := s.service.restclient.GetNodes(context.TODO())
27+
if err != nil {
28+
s.T().Fatalf("failed to get nodes: %v", err)
29+
}
30+
return nodes[0]
31+
}
32+
33+
func (s *TestSuite) getTestVirtualMachine() (*api.Node, *VirtualMachine) {
34+
node := s.getTestNode()
35+
vms, err := s.service.restclient.GetVirtualMachines(context.TODO(), node.Node)
36+
if err != nil {
37+
s.T().Fatalf("failed to get vms: %v", err)
38+
}
39+
vm, err := s.service.VirtualMachine(context.TODO(), vms[0].VMID)
40+
if err != nil {
41+
s.T().Fatalf("failed to get vm: %v", err)
42+
}
43+
return node, vm
44+
}

proxmox/suite_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package proxmox
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/suite"
8+
)
9+
10+
type TestSuite struct {
11+
suite.Suite
12+
service Service
13+
}
14+
15+
func (s *TestSuite) SetupSuite() {
16+
url := os.Getenv("PROXMOX_URL")
17+
user := os.Getenv("PROXMOX_USERNAME")
18+
password := os.Getenv("PROXMOX_PASSWORD")
19+
tokeid := os.Getenv("PROXMOX_TOKENID")
20+
secret := os.Getenv("PROXMOX_SECRET")
21+
if url == "" {
22+
s.T().Fatal("url must not be empty")
23+
}
24+
25+
authConfig := AuthConfig{
26+
Username: user,
27+
Password: password,
28+
TokenID: tokeid,
29+
Secret: secret,
30+
}
31+
32+
service, err := NewService(url, authConfig, true)
33+
if err != nil {
34+
s.T().Fatalf("failed to create new service: %v", err)
35+
}
36+
s.service = *service
37+
}
38+
39+
func TestSuiteIntegration(t *testing.T) {
40+
suite.Run(t, new(TestSuite))
41+
}

proxmox/task.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ const (
1616
func (s *Service) MustGetTask(ctx context.Context, node string, upid string) (*api.Task, error) {
1717
for i := 0; i < 10; i++ {
1818
task, err := s.restclient.GetTask(ctx, node, upid)
19-
if rest.IsNotFound(err) {
20-
time.Sleep(time.Second * 1)
21-
continue
19+
if err != nil {
20+
if rest.IsNotFound(err) {
21+
time.Sleep(time.Second * 1)
22+
continue
23+
}
24+
return nil, err
2225
}
2326
return task, nil
2427
}

proxmox/task_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package proxmox
2+
3+
import (
4+
"context"
5+
6+
"github.com/sp-yduck/proxmox-go/api"
7+
)
8+
9+
func (s *TestSuite) TestMustGetTask() {
10+
testNode, testTask := s.getTestTask()
11+
task, err := s.service.MustGetTask(context.TODO(), testNode.Node, testTask.UPID)
12+
if err != nil {
13+
s.T().Fatalf("failed to get task: %v", err)
14+
}
15+
s.Assert().Equal(*task, *testTask)
16+
}
17+
18+
func (s *TestSuite) TestEnsureTaskDone() {
19+
testNode, testTask := s.getTestTask()
20+
err := s.service.EnsureTaskDone(context.TODO(), testNode.Node, testTask.UPID)
21+
if err != nil {
22+
s.T().Fatalf("failed to get task: %v", err)
23+
}
24+
}
25+
26+
func (s *TestSuite) getTestTask() (*api.Node, *api.Task) {
27+
node := s.getTestNode()
28+
tasks, err := s.service.restclient.GetTasks(context.TODO(), node.Node)
29+
if err != nil {
30+
s.T().Fatalf("failed to get tasks: %v", err)
31+
}
32+
return node, tasks[0]
33+
}

rest/errors.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@ func (e *Error) Error() string {
2222
}
2323

2424
func IsNotFound(err error) bool {
25+
if err == nil {
26+
return false
27+
}
2528
return err.Error() == NotFound
2629
}
2730

2831
func IsNotAuthorized(err error) bool {
32+
if err == nil {
33+
return false
34+
}
2935
return err.Error() == NotAuthorized
3036
}

0 commit comments

Comments
 (0)