From a53a116b96f0b549bd05428de2912c4caa0a05c1 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Wed, 13 Mar 2024 21:30:19 +0300 Subject: [PATCH 01/31] vzdump api call --- types.go | 26 ++++++++++++++++++++++++++ virtual_machine.go | 13 +++++++++++++ 2 files changed, 39 insertions(+) diff --git a/types.go b/types.go index c646411..8299267 100644 --- a/types.go +++ b/types.go @@ -1242,3 +1242,29 @@ type FirewallIPSet struct { Digest string `json:"digest,omitempty"` Comment string `json:"comment,omitempty"` } + +type ( + ModeType = string + CompressType = string +) + +const ( + ModeSnapshot = ModeType("snapshot") + ModeSuspend = ModeType("suspend") + ModeStop = ModeType("stop") + + CompressZero = CompressType("0") + CompressOne = CompressType("1") + CompressGzip = CompressType("gzip") + CompressLzo = CompressType("lzo") + CompressZstd = CompressType("zstd") +) + +type VirtualMachineBackupOptions struct { + VMID uint64 `json:"vmid"` + Storage string `json:"storage,omitempty"` + Remove int `json:"remove,omitempty"` + Mode ModeType `json:"mode,omitempty"` + Compress CompressType `json:"compess,omitempty"` + Notes string `json:"notes,omitempty"` +} diff --git a/virtual_machine.go b/virtual_machine.go index 3e379d8..47d8fcd 100644 --- a/virtual_machine.go +++ b/virtual_machine.go @@ -643,3 +643,16 @@ func (v *VirtualMachine) ConvertToTemplate(ctx context.Context) (task *Task, err } return NewTask(upid, v.client), nil } + +func (v *VirtualMachine) Vzdump(ctx context.Context, params *VirtualMachineBackupOptions) (task *Task, err error) { + var upid UPID + + if params == nil { + params = &VirtualMachineBackupOptions{} + } + + if err = v.client.Post(ctx, fmt.Sprintf("/nodes/%s/vzdump", v.Node), params, &upid); err != nil { + return nil, err + } + return NewTask(upid, v.client), nil +} From 9ec5fe0b8b40b46b049ee87d4bcb573f1199f231 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Wed, 13 Mar 2024 21:41:17 +0300 Subject: [PATCH 02/31] struct tag fix --- types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types.go b/types.go index 8299267..3fcd26b 100644 --- a/types.go +++ b/types.go @@ -1265,6 +1265,6 @@ type VirtualMachineBackupOptions struct { Storage string `json:"storage,omitempty"` Remove int `json:"remove,omitempty"` Mode ModeType `json:"mode,omitempty"` - Compress CompressType `json:"compess,omitempty"` + Compress CompressType `json:"compress,omitempty"` Notes string `json:"notes,omitempty"` } From 50b62d3800ab195f14c82fb3a9de7d9fc3cc01ef Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Fri, 15 Mar 2024 13:40:34 +0300 Subject: [PATCH 03/31] replace vzdump method based on proxmox ve api --- nodes.go | 13 +++++++++++++ types.go | 2 +- virtual_machine.go | 13 ------------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/nodes.go b/nodes.go index 8080ac9..73dff3b 100644 --- a/nodes.go +++ b/nodes.go @@ -276,3 +276,16 @@ func (n *Node) GetCustomCertificates(ctx context.Context) (certs *NodeCertificat err = n.client.Get(ctx, fmt.Sprintf("/nodes/%s/certificates/info", n.Name), &certs) return } + +func (n *Node) Vzdump(ctx context.Context, params *VirtualMachineBackupOptions) (task *Task, err error) { + var upid UPID + + if params == nil { + return nil, fmt.Errorf("empty params") + } + + if err = n.client.Post(ctx, fmt.Sprintf("/nodes/%s/vzdump", n.Name), params, &upid); err != nil { + return nil, err + } + return NewTask(upid, n.client), nil +} diff --git a/types.go b/types.go index 3fcd26b..a04667f 100644 --- a/types.go +++ b/types.go @@ -1262,7 +1262,7 @@ const ( type VirtualMachineBackupOptions struct { VMID uint64 `json:"vmid"` - Storage string `json:"storage,omitempty"` + Storage string `json:"storage"` Remove int `json:"remove,omitempty"` Mode ModeType `json:"mode,omitempty"` Compress CompressType `json:"compress,omitempty"` diff --git a/virtual_machine.go b/virtual_machine.go index 47d8fcd..3e379d8 100644 --- a/virtual_machine.go +++ b/virtual_machine.go @@ -643,16 +643,3 @@ func (v *VirtualMachine) ConvertToTemplate(ctx context.Context) (task *Task, err } return NewTask(upid, v.client), nil } - -func (v *VirtualMachine) Vzdump(ctx context.Context, params *VirtualMachineBackupOptions) (task *Task, err error) { - var upid UPID - - if params == nil { - params = &VirtualMachineBackupOptions{} - } - - if err = v.client.Post(ctx, fmt.Sprintf("/nodes/%s/vzdump", v.Node), params, &upid); err != nil { - return nil, err - } - return NewTask(upid, v.client), nil -} From ff0cfcef2aeb5e9caaba8eb6b6ac395d26ec3cfb Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 16 Mar 2024 01:27:17 +0300 Subject: [PATCH 04/31] review comment fixes --- nodes.go | 2 +- types.go | 63 +++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/nodes.go b/nodes.go index 73dff3b..cb7ba15 100644 --- a/nodes.go +++ b/nodes.go @@ -281,7 +281,7 @@ func (n *Node) Vzdump(ctx context.Context, params *VirtualMachineBackupOptions) var upid UPID if params == nil { - return nil, fmt.Errorf("empty params") + params = &VirtualMachineBackupOptions{} } if err = n.client.Post(ctx, fmt.Sprintf("/nodes/%s/vzdump", n.Name), params, &upid); err != nil { diff --git a/types.go b/types.go index a04667f..0d02b4e 100644 --- a/types.go +++ b/types.go @@ -1244,27 +1244,56 @@ type FirewallIPSet struct { } type ( - ModeType = string - CompressType = string + VirtualMachineBackupMode = string + VirtualMachineBackupCompress = string + VirtualMachineBackupNotificationPolicy = string ) const ( - ModeSnapshot = ModeType("snapshot") - ModeSuspend = ModeType("suspend") - ModeStop = ModeType("stop") - - CompressZero = CompressType("0") - CompressOne = CompressType("1") - CompressGzip = CompressType("gzip") - CompressLzo = CompressType("lzo") - CompressZstd = CompressType("zstd") + VirtualMachineBackupModeSnapshot = VirtualMachineBackupMode("snapshot") + VirtualMachineBackupModeSuspend = VirtualMachineBackupMode("suspend") + VirtualMachineBackupModeStop = VirtualMachineBackupMode("stop") + + VirtualMachineBackupCompressZero = VirtualMachineBackupCompress("0") + VirtualMachineBackupCompressOne = VirtualMachineBackupCompress("1") + VirtualMachineBackupCompressGzip = VirtualMachineBackupCompress("gzip") + VirtualMachineBackupCompressLzo = VirtualMachineBackupCompress("lzo") + VirtualMachineBackupCompressZstd = VirtualMachineBackupCompress("zstd") + + VirtualMachineBackupNotificationPolicyAlways = VirtualMachineBackupNotificationPolicy("always") + VirtualMachineBackupNotificationPolicyFailure = VirtualMachineBackupNotificationPolicy("failure") + VirtualMachineBackupNotificationPolicyNever = VirtualMachineBackupNotificationPolicy("never") ) type VirtualMachineBackupOptions struct { - VMID uint64 `json:"vmid"` - Storage string `json:"storage"` - Remove int `json:"remove,omitempty"` - Mode ModeType `json:"mode,omitempty"` - Compress CompressType `json:"compress,omitempty"` - Notes string `json:"notes,omitempty"` + All bool `json:"all,omitempty"` + BwLimit uint `json:"bwlimit,omitempty"` + Compress VirtualMachineBackupCompress `json:"compress,omitempty"` + DumpDir string `json:"dumpDir,omitempty"` + Exclude string `json:"exclude,omitempty"` + ExcludePath []string `json:"exclude-path,omitempty"` + IoNice uint `json:"ionice,omitempty"` + LockWait uint `json:"lockwait,omitempty"` + MailTo string `json:"mailto,omitempty"` + Mode VirtualMachineBackupMode `json:"mode,omitempty"` + Node string `json:"node,omitempty"` + NotesTemplate string `json:"notes-template,omitempty"` + NotificationPolicy VirtualMachineBackupNotificationPolicy `json:"notification-policy,omitempty"` + NotificationTarget string `json:"notification-target,omitempty"` + Performance string `json:"performance,omitempty"` + Pigz int `json:"pigz,omitempty"` + Pool string `json:"pool,omitempty"` + Protected string `json:"protected,omitempty"` + PruneBackups string `json:"prune-backups,omitempty"` + Quiet bool `json:"quiet,omitempty"` + Remove bool `json:"remove,omitempty"` + Script string `json:"script,omitempty"` + StdExcludes bool `json:"stdexcludes,omitempty"` + StdOut bool `json:"stdout,omitempty"` + Stop bool `json:"stop,omitempty"` + StopWait uint `json:"stopwait,omitempty"` + Storage string `json:"storage,omitempty"` + TmpDir string `json:"tmpdir,omitempty"` + VMID uint64 `json:"vmid,omitempty"` + Zstd uint `json:"zstd,omitempty"` } From 375c1b53994dde2fdd5ba999bf9a63e9bdf1f418 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 30 Mar 2024 16:10:05 +0300 Subject: [PATCH 05/31] cluster tasks api call --- cluster.go | 10 ++++++++++ types.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cluster.go b/cluster.go index a3da92c..c8c3f64 100644 --- a/cluster.go +++ b/cluster.go @@ -49,3 +49,13 @@ func (cl *Cluster) Resources(ctx context.Context, filters ...string) (rs Cluster return rs, cl.client.Get(ctx, u.String(), &rs) } + +func (cl *Cluster) Tasks(ctx context.Context) (Tasks, error) { + var tasks Tasks + + if err := cl.client.Get(ctx, "/cluster/tasks", &tasks); err != nil { + return nil, err + } + + return tasks, nil +} diff --git a/types.go b/types.go index 63f9651..8c0059b 100644 --- a/types.go +++ b/types.go @@ -580,7 +580,7 @@ type VirtualMachineMoveDiskOptions struct { type UPID string -type Tasks []*Tasks +type Tasks []*Task type Task struct { client *Client UPID UPID From 6e5c7e34535bfabed0d863030f3b535ab5faa528 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 30 Mar 2024 16:27:43 +0300 Subject: [PATCH 06/31] add client instance to cluster task --- cluster.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cluster.go b/cluster.go index c8c3f64..244e701 100644 --- a/cluster.go +++ b/cluster.go @@ -57,5 +57,9 @@ func (cl *Cluster) Tasks(ctx context.Context) (Tasks, error) { return nil, err } + for index := range tasks { + tasks[index].client = cl.client + } + return tasks, nil } From 0187fca48e9b489f3f33a2d4a558b185ea18ae77 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 4 May 2024 01:04:53 +0300 Subject: [PATCH 07/31] update firewall options --- types.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/types.go b/types.go index 4209f16..3e5e21b 100644 --- a/types.go +++ b/types.go @@ -980,16 +980,16 @@ type FirewallNodeOption struct { } type FirewallVirtualMachineOption struct { - Enable bool `json:"enable,omitempty"` - Dhcp bool `json:"dhcp,omitempty"` - Ipfilter bool `json:"ipfilter,omitempty"` - LogLevelIn string `json:"log_level_in,omitempty"` - LogLevelOut string `json:"log_level_out,omitempty"` - Macfilter bool `json:"macfilter,omitempty"` - Ntp bool `json:"ntp,omitempty"` - PolicyIn string `json:"policy_in,omitempty"` - PolicyOut string `json:"policy_out,omitempty"` - Radv bool `json:"radv,omitempty"` + Enable *bool `json:"enable,omitempty"` + Dhcp *bool `json:"dhcp,omitempty"` + IpFilter *bool `json:"ipfilter,omitempty"` + LogLevelIn *string `json:"log_level_in,omitempty"` + LogLevelOut *string `json:"log_level_out,omitempty"` + MacFilter *bool `json:"macfilter,omitempty"` + Ndp *bool `json:"ndp,omitempty"` + PolicyIn *string `json:"policy_in,omitempty"` + PolicyOut *string `json:"policy_out,omitempty"` + Radv *bool `json:"radv,omitempty"` } type Snapshot struct { From 551e941e35504d9f38f5976a891df1c5b3e95fe9 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 4 May 2024 01:59:13 +0300 Subject: [PATCH 08/31] update field types --- types.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/types.go b/types.go index 3e5e21b..1b58dd6 100644 --- a/types.go +++ b/types.go @@ -980,16 +980,16 @@ type FirewallNodeOption struct { } type FirewallVirtualMachineOption struct { - Enable *bool `json:"enable,omitempty"` - Dhcp *bool `json:"dhcp,omitempty"` - IpFilter *bool `json:"ipfilter,omitempty"` - LogLevelIn *string `json:"log_level_in,omitempty"` - LogLevelOut *string `json:"log_level_out,omitempty"` - MacFilter *bool `json:"macfilter,omitempty"` - Ndp *bool `json:"ndp,omitempty"` - PolicyIn *string `json:"policy_in,omitempty"` - PolicyOut *string `json:"policy_out,omitempty"` - Radv *bool `json:"radv,omitempty"` + Enable *IntOrBool `json:"enable,omitempty"` + Dhcp *IntOrBool `json:"dhcp,omitempty"` + IpFilter *IntOrBool `json:"ipfilter,omitempty"` + LogLevelIn *string `json:"log_level_in,omitempty"` + LogLevelOut *string `json:"log_level_out,omitempty"` + MacFilter *IntOrBool `json:"macfilter,omitempty"` + Ndp *IntOrBool `json:"ndp,omitempty"` + PolicyIn *string `json:"policy_in,omitempty"` + PolicyOut *string `json:"policy_out,omitempty"` + Radv *IntOrBool `json:"radv,omitempty"` } type Snapshot struct { From 4875d865f4bfe1de6bf8de51d8b33928c1657e9b Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 4 May 2024 02:13:20 +0300 Subject: [PATCH 09/31] update field types --- types.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/types.go b/types.go index 1b58dd6..d8e26e2 100644 --- a/types.go +++ b/types.go @@ -980,16 +980,16 @@ type FirewallNodeOption struct { } type FirewallVirtualMachineOption struct { - Enable *IntOrBool `json:"enable,omitempty"` - Dhcp *IntOrBool `json:"dhcp,omitempty"` - IpFilter *IntOrBool `json:"ipfilter,omitempty"` - LogLevelIn *string `json:"log_level_in,omitempty"` - LogLevelOut *string `json:"log_level_out,omitempty"` - MacFilter *IntOrBool `json:"macfilter,omitempty"` - Ndp *IntOrBool `json:"ndp,omitempty"` - PolicyIn *string `json:"policy_in,omitempty"` - PolicyOut *string `json:"policy_out,omitempty"` - Radv *IntOrBool `json:"radv,omitempty"` + Enable *int `json:"enable,omitempty"` + Dhcp *int `json:"dhcp,omitempty"` + IpFilter *int `json:"ipfilter,omitempty"` + LogLevelIn *string `json:"log_level_in,omitempty"` + LogLevelOut *string `json:"log_level_out,omitempty"` + MacFilter *int `json:"macfilter,omitempty"` + Ndp *int `json:"ndp,omitempty"` + PolicyIn *string `json:"policy_in,omitempty"` + PolicyOut *string `json:"policy_out,omitempty"` + Radv *int `json:"radv,omitempty"` } type Snapshot struct { From 202a4a62acba10c7d92c8f76b546a11cd1dcc47d Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 4 May 2024 17:16:33 +0300 Subject: [PATCH 10/31] change firewall get option func --- virtual_machine.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/virtual_machine.go b/virtual_machine.go index 4915f72..b40af0c 100644 --- a/virtual_machine.go +++ b/virtual_machine.go @@ -569,9 +569,14 @@ func (v *VirtualMachine) AgentSetUserPassword(ctx context.Context, password stri return v.client.Post(ctx, fmt.Sprintf("/nodes/%s/qemu/%d/agent/set-user-password", v.Node, v.VMID), map[string]string{"password": password, "username": username}, nil) } -func (v *VirtualMachine) FirewallOptionGet(ctx context.Context) (firewallOption *FirewallVirtualMachineOption, err error) { - err = v.client.Get(ctx, fmt.Sprintf("/nodes/%s/qemu/%d/firewall/options", v.Node, v.VMID), firewallOption) - return +func (v *VirtualMachine) FirewallOptionGet(ctx context.Context) (*FirewallVirtualMachineOption, error) { + firewallOption := FirewallVirtualMachineOption{} + + if err := v.client.Get(ctx, fmt.Sprintf("/nodes/%s/qemu/%d/firewall/options", v.Node, v.VMID), &firewallOption); err != nil { + return nil, err + } + + return &firewallOption, nil } func (v *VirtualMachine) FirewallOptionSet(ctx context.Context, firewallOption *FirewallVirtualMachineOption) error { From 21bfc4ac90210564514e0a5156991ab7dd7f29a5 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Sat, 4 May 2024 18:04:03 +0300 Subject: [PATCH 11/31] change for common types --- types.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/types.go b/types.go index d8e26e2..1b58dd6 100644 --- a/types.go +++ b/types.go @@ -980,16 +980,16 @@ type FirewallNodeOption struct { } type FirewallVirtualMachineOption struct { - Enable *int `json:"enable,omitempty"` - Dhcp *int `json:"dhcp,omitempty"` - IpFilter *int `json:"ipfilter,omitempty"` - LogLevelIn *string `json:"log_level_in,omitempty"` - LogLevelOut *string `json:"log_level_out,omitempty"` - MacFilter *int `json:"macfilter,omitempty"` - Ndp *int `json:"ndp,omitempty"` - PolicyIn *string `json:"policy_in,omitempty"` - PolicyOut *string `json:"policy_out,omitempty"` - Radv *int `json:"radv,omitempty"` + Enable *IntOrBool `json:"enable,omitempty"` + Dhcp *IntOrBool `json:"dhcp,omitempty"` + IpFilter *IntOrBool `json:"ipfilter,omitempty"` + LogLevelIn *string `json:"log_level_in,omitempty"` + LogLevelOut *string `json:"log_level_out,omitempty"` + MacFilter *IntOrBool `json:"macfilter,omitempty"` + Ndp *IntOrBool `json:"ndp,omitempty"` + PolicyIn *string `json:"policy_in,omitempty"` + PolicyOut *string `json:"policy_out,omitempty"` + Radv *IntOrBool `json:"radv,omitempty"` } type Snapshot struct { From ca5f6731666ba359e219c46ba4ee9a0d81b393cf Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 14:02:17 +0300 Subject: [PATCH 12/31] create ha group --- cluster_ha.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ types.go | 20 ++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 cluster_ha.go diff --git a/cluster_ha.go b/cluster_ha.go new file mode 100644 index 0000000..ed0b15e --- /dev/null +++ b/cluster_ha.go @@ -0,0 +1,45 @@ +package proxmox + +import ( + "context" + "fmt" + "strings" +) + +func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfiguration) error { + if groupConfiguration == nil { + return fmt.Errorf("empty ha group configuration") + } + + haGroupConfiguration := struct { + Nodes string `json:"nodes"` + HAGroupConfiguration + }{ + HAGroupConfiguration: HAGroupConfiguration{ + Group: groupConfiguration.Group, + Comment: groupConfiguration.Comment, + NoFailback: groupConfiguration.NoFailback, + Restricted: groupConfiguration.Restricted, + Type: HATypeGroup, + }, + } + + var nodes []string + for _, haNode := range groupConfiguration.HaNodes { + if haNode.Priority != nil { + nodes = append(nodes, + fmt.Sprintf("%s:%d", haNode.Node, haNode.Priority)) + } else { + nodes = append(nodes, + haNode.Node) + } + } + + haGroupConfiguration.Nodes = strings.Join(nodes, ",") + + if err := cl.client.Post(ctx, "cluster/ha/groups", &haGroupConfiguration, nil); err != nil { + return err + } + + return nil +} diff --git a/types.go b/types.go index 4209f16..eb4b957 100644 --- a/types.go +++ b/types.go @@ -1476,3 +1476,23 @@ type VzdumpConfig struct { IPConfig8 string `json:"ipconfig8,omitempty"` IPConfig9 string `json:"ipconfig9,omitempty"` } + +type HAType = string + +const ( + HATypeGroup = HAType("group") +) + +type HANodes struct { + Node string + Priority *uint +} + +type HAGroupConfiguration struct { + Group string `json:"group"` + HaNodes []HANodes + Comment *string `json:"comment"` + NoFailback *int `json:"nofailback"` + Restricted *int `json:"restricted"` + Type HAType `json:"type"` +} From 5df326d5ba3243218b1168c5c20abee53ed527b0 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 14:14:19 +0300 Subject: [PATCH 13/31] update path --- cluster_ha.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cluster_ha.go b/cluster_ha.go index ed0b15e..71146c3 100644 --- a/cluster_ha.go +++ b/cluster_ha.go @@ -28,7 +28,7 @@ func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfi for _, haNode := range groupConfiguration.HaNodes { if haNode.Priority != nil { nodes = append(nodes, - fmt.Sprintf("%s:%d", haNode.Node, haNode.Priority)) + fmt.Sprintf("%s:%d", haNode.Node, *haNode.Priority)) } else { nodes = append(nodes, haNode.Node) @@ -37,7 +37,7 @@ func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfi haGroupConfiguration.Nodes = strings.Join(nodes, ",") - if err := cl.client.Post(ctx, "cluster/ha/groups", &haGroupConfiguration, nil); err != nil { + if err := cl.client.Post(ctx, "/cluster/ha/groups", &haGroupConfiguration, nil); err != nil { return err } From 037f9da9d22f6c32122d0d5178b6acd66322e88a Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 14:17:04 +0300 Subject: [PATCH 14/31] small schema changes --- cluster_ha.go | 20 +++++++++++--------- types.go | 10 +++++----- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/cluster_ha.go b/cluster_ha.go index 71146c3..81cbdd8 100644 --- a/cluster_ha.go +++ b/cluster_ha.go @@ -12,16 +12,18 @@ func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfi } haGroupConfiguration := struct { - Nodes string `json:"nodes"` - HAGroupConfiguration + Nodes string `json:"nodes"` + Group string `json:"group"` + Comment *string `json:"comment"` + NoFailback *int `json:"nofailback"` + Restricted *int `json:"restricted"` + Type HAType `json:"type"` }{ - HAGroupConfiguration: HAGroupConfiguration{ - Group: groupConfiguration.Group, - Comment: groupConfiguration.Comment, - NoFailback: groupConfiguration.NoFailback, - Restricted: groupConfiguration.Restricted, - Type: HATypeGroup, - }, + Group: groupConfiguration.Group, + Comment: groupConfiguration.Comment, + NoFailback: groupConfiguration.NoFailback, + Restricted: groupConfiguration.Restricted, + Type: HATypeGroup, } var nodes []string diff --git a/types.go b/types.go index eb4b957..8077d5e 100644 --- a/types.go +++ b/types.go @@ -1489,10 +1489,10 @@ type HANodes struct { } type HAGroupConfiguration struct { - Group string `json:"group"` + Group string HaNodes []HANodes - Comment *string `json:"comment"` - NoFailback *int `json:"nofailback"` - Restricted *int `json:"restricted"` - Type HAType `json:"type"` + Comment *string + NoFailback *int + Restricted *int + Type HAType } From b925facca1d1dee0e7d9746ea5bc9b4487017e78 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 14:39:04 +0300 Subject: [PATCH 15/31] small changes --- cluster_ha.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cluster_ha.go b/cluster_ha.go index 81cbdd8..afcc024 100644 --- a/cluster_ha.go +++ b/cluster_ha.go @@ -14,10 +14,10 @@ func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfi haGroupConfiguration := struct { Nodes string `json:"nodes"` Group string `json:"group"` - Comment *string `json:"comment"` - NoFailback *int `json:"nofailback"` - Restricted *int `json:"restricted"` - Type HAType `json:"type"` + Comment *string `json:"comment,omitempty"` + NoFailback *int `json:"nofailback,omitempty"` + Restricted *int `json:"restricted,omitempty"` + Type HAType `json:"type,omitempty"` }{ Group: groupConfiguration.Group, Comment: groupConfiguration.Comment, From bf9f1e84b4c9802e5c4e22a3adf3fe01b8ac1e37 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 14:48:39 +0300 Subject: [PATCH 16/31] drop unused field --- types.go | 1 - 1 file changed, 1 deletion(-) diff --git a/types.go b/types.go index 8077d5e..186c2ce 100644 --- a/types.go +++ b/types.go @@ -1494,5 +1494,4 @@ type HAGroupConfiguration struct { Comment *string NoFailback *int Restricted *int - Type HAType } From ebaa0e87ce16944e43be04475c816ea7b5516382 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 15:49:40 +0300 Subject: [PATCH 17/31] get ha groups --- cluster_ha.go | 94 ++++++++++++++++++++++++++++++++++++++++++++------- util.go | 5 +++ 2 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 util.go diff --git a/cluster_ha.go b/cluster_ha.go index afcc024..af4b59c 100644 --- a/cluster_ha.go +++ b/cluster_ha.go @@ -3,22 +3,30 @@ package proxmox import ( "context" "fmt" + "strconv" "strings" ) -func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfiguration) error { +const ( + PrioritySeparator = ":" + NodeSeparator = "," +) + +type haGroupConfiguration struct { + Nodes string `json:"nodes"` + Group string `json:"group"` + Comment *string `json:"comment,omitempty"` + NoFailback *int `json:"nofailback,omitempty"` + Restricted *int `json:"restricted,omitempty"` + Type HAType `json:"type,omitempty"` +} + +func (cl *Cluster) HAGroupCreate(ctx context.Context, groupConfiguration *HAGroupConfiguration) error { if groupConfiguration == nil { return fmt.Errorf("empty ha group configuration") } - haGroupConfiguration := struct { - Nodes string `json:"nodes"` - Group string `json:"group"` - Comment *string `json:"comment,omitempty"` - NoFailback *int `json:"nofailback,omitempty"` - Restricted *int `json:"restricted,omitempty"` - Type HAType `json:"type,omitempty"` - }{ + haGroupCfg := haGroupConfiguration{ Group: groupConfiguration.Group, Comment: groupConfiguration.Comment, NoFailback: groupConfiguration.NoFailback, @@ -30,18 +38,80 @@ func (cl *Cluster) HAGroup(ctx context.Context, groupConfiguration *HAGroupConfi for _, haNode := range groupConfiguration.HaNodes { if haNode.Priority != nil { nodes = append(nodes, - fmt.Sprintf("%s:%d", haNode.Node, *haNode.Priority)) + fmt.Sprintf("%s%s%d", haNode.Node, PrioritySeparator, *haNode.Priority)) } else { nodes = append(nodes, haNode.Node) } } - haGroupConfiguration.Nodes = strings.Join(nodes, ",") + haGroupCfg.Nodes = strings.Join(nodes, NodeSeparator) - if err := cl.client.Post(ctx, "/cluster/ha/groups", &haGroupConfiguration, nil); err != nil { + if err := cl.client.Post(ctx, "/cluster/ha/groups", &haGroupCfg, nil); err != nil { return err } return nil } + +func (cl *Cluster) HAGroups(ctx context.Context) ([]HAGroupConfiguration, error) { + var haConfigurations []haGroupConfiguration + if err := cl.client.Get(ctx, "/cluster/ha/groups", &haConfigurations); err != nil { + return nil, err + } + + haGroupConfigurations := make([]HAGroupConfiguration, 0, len(haConfigurations)) + + for _, groupCfg := range haConfigurations { + haNodes, err := prepareHANodeList(groupCfg.Nodes) + if err != nil { + return nil, fmt.Errorf("prepare ha node list : %w", err) + } + + haGroupConfigurations = append(haGroupConfigurations, HAGroupConfiguration{ + Group: groupCfg.Group, + HaNodes: haNodes, + Comment: groupCfg.Comment, + NoFailback: groupCfg.NoFailback, + Restricted: groupCfg.Restricted, + }) + } + + return haGroupConfigurations, nil +} + +func prepareHANodeList(haNodeStr string) ([]HANodes, error) { + nodeStrs := strings.Split(haNodeStr, NodeSeparator) + + haNodes := make([]HANodes, 0, len(nodeStrs)) + + for _, nodeStr := range nodeStrs { + haNode, err := splitToHANode(nodeStr) + if err != nil { + return nil, fmt.Errorf("split node string : %w", err) + } + + haNodes = append(haNodes, haNode) + } + + return haNodes, nil +} + +func splitToHANode(haNodeStr string) (HANodes, error) { + haNodeParts := strings.Split(haNodeStr, PrioritySeparator) + + haNode := HANodes{ + Node: haNodeParts[0], + } + + if len(haNodeParts) > 1 { + priority, err := strconv.ParseUint(haNodeParts[1], 10, 32) + if err != nil { + return HANodes{}, fmt.Errorf("cannot parse priority : %w", err) + } + + haNode.Priority = AsPtr[uint](uint(priority)) + } + + return haNode, nil +} diff --git a/util.go b/util.go new file mode 100644 index 0000000..1d3100f --- /dev/null +++ b/util.go @@ -0,0 +1,5 @@ +package proxmox + +func AsPtr[T any](input T) *T { + return &input +} From ca43383dd260ff98d933dcb2340b799cf92d4b09 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 15:53:01 +0300 Subject: [PATCH 18/31] ha group delete --- cluster_ha.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cluster_ha.go b/cluster_ha.go index af4b59c..adfca34 100644 --- a/cluster_ha.go +++ b/cluster_ha.go @@ -54,6 +54,10 @@ func (cl *Cluster) HAGroupCreate(ctx context.Context, groupConfiguration *HAGrou return nil } +func (cl *Cluster) HAGroupDelete(ctx context.Context, groupName string) error { + return cl.client.Delete(ctx, fmt.Sprintf("/cluster/ha/groups/%s", groupName), nil) +} + func (cl *Cluster) HAGroups(ctx context.Context) ([]HAGroupConfiguration, error) { var haConfigurations []haGroupConfiguration if err := cl.client.Get(ctx, "/cluster/ha/groups", &haConfigurations); err != nil { From d522b894417a448f11e707c5ead4dcb37a537012 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Mon, 13 May 2024 15:59:51 +0300 Subject: [PATCH 19/31] change types --- cluster_ha.go | 12 ++++++------ types.go | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cluster_ha.go b/cluster_ha.go index adfca34..a81a1c3 100644 --- a/cluster_ha.go +++ b/cluster_ha.go @@ -13,12 +13,12 @@ const ( ) type haGroupConfiguration struct { - Nodes string `json:"nodes"` - Group string `json:"group"` - Comment *string `json:"comment,omitempty"` - NoFailback *int `json:"nofailback,omitempty"` - Restricted *int `json:"restricted,omitempty"` - Type HAType `json:"type,omitempty"` + Nodes string `json:"nodes"` + Group string `json:"group"` + Comment *string `json:"comment,omitempty"` + NoFailback *IntOrBool `json:"nofailback,omitempty"` + Restricted *IntOrBool `json:"restricted,omitempty"` + Type HAType `json:"type,omitempty"` } func (cl *Cluster) HAGroupCreate(ctx context.Context, groupConfiguration *HAGroupConfiguration) error { diff --git a/types.go b/types.go index 186c2ce..b7b4aef 100644 --- a/types.go +++ b/types.go @@ -1492,6 +1492,6 @@ type HAGroupConfiguration struct { Group string HaNodes []HANodes Comment *string - NoFailback *int - Restricted *int + NoFailback *IntOrBool + Restricted *IntOrBool } From 0c1b737bdf347791ad0e54bd09708ab89b86433f Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Tue, 14 May 2024 12:59:33 +0300 Subject: [PATCH 20/31] change task saved type --- types.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/types.go b/types.go index 4209f16..960d997 100644 --- a/types.go +++ b/types.go @@ -589,10 +589,10 @@ type Task struct { User string Status string Node string - PID uint64 `json:",omitempty"` - PStart uint64 `json:",omitempty"` - Saved string `json:",omitempty"` - ExitStatus string `json:",omitempty"` + PID uint64 `json:",omitempty"` + PStart uint64 `json:",omitempty"` + Saved StringOrInt `json:",omitempty"` + ExitStatus string `json:",omitempty"` IsCompleted bool IsRunning bool IsFailed bool From 46586b7a63e84e041fe09007a9457ab0ce4dd92f Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Fri, 31 May 2024 13:36:53 +0300 Subject: [PATCH 21/31] cluster ha resources --- cluster_ha_resources.go | 13 +++++++++++++ types.go | 20 +++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 cluster_ha_resources.go diff --git a/cluster_ha_resources.go b/cluster_ha_resources.go new file mode 100644 index 0000000..2a82149 --- /dev/null +++ b/cluster_ha_resources.go @@ -0,0 +1,13 @@ +package proxmox + +import ( + "context" +) + +func (cl *Cluster) HAResourceCreate(ctx context.Context, haResource HAResource) error { + if err := cl.client.Post(ctx, "/cluster/ha/resources", &haResource, nil); err != nil { + return err + } + + return nil +} diff --git a/types.go b/types.go index 276fc6b..c1df946 100644 --- a/types.go +++ b/types.go @@ -1477,10 +1477,19 @@ type VzdumpConfig struct { IPConfig9 string `json:"ipconfig9,omitempty"` } -type HAType = string +type ( + HAType string + HAResourceState string +) const ( HATypeGroup = HAType("group") + + HAResourceStateStarted = HAResourceState("started") + HAResourceStateStopped = HAResourceState("stopped") + HAResourceStateEnabled = HAResourceState("enabled") + HAResourceStateDisabled = HAResourceState("disabled") + HAResourceStateIgnored = HAResourceState("ignored") ) type HANodes struct { @@ -1495,3 +1504,12 @@ type HAGroupConfiguration struct { NoFailback *IntOrBool Restricted *IntOrBool } + +type HAResource struct { + ID int `json:"sid"` + Group *string `json:"group"` + Comment *string `json:"comment"` + MaxRelocate *uint `json:"max_relocate"` + MaxRestart *uint `json:"max_restart"` + State *HAResourceState `json:"state"` +} From 55ea2aba827411d77dc46386c8d94d864cdc5212 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Tue, 4 Jun 2024 17:23:51 +0300 Subject: [PATCH 22/31] omitempty instruction --- types.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/types.go b/types.go index c1df946..a49861e 100644 --- a/types.go +++ b/types.go @@ -1508,8 +1508,8 @@ type HAGroupConfiguration struct { type HAResource struct { ID int `json:"sid"` Group *string `json:"group"` - Comment *string `json:"comment"` - MaxRelocate *uint `json:"max_relocate"` - MaxRestart *uint `json:"max_restart"` - State *HAResourceState `json:"state"` + Comment *string `json:"commentm,omitempty"` + MaxRelocate *uint `json:"max_relocate,omitempty"` + MaxRestart *uint `json:"max_restart,omitempty"` + State *HAResourceState `json:"state,omitempty"` } From dfe5e577c9f8058fb1c64102bd9da407cd87be06 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Tue, 4 Jun 2024 17:27:46 +0300 Subject: [PATCH 23/31] json tag name fix --- types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types.go b/types.go index a49861e..12bb216 100644 --- a/types.go +++ b/types.go @@ -1508,7 +1508,7 @@ type HAGroupConfiguration struct { type HAResource struct { ID int `json:"sid"` Group *string `json:"group"` - Comment *string `json:"commentm,omitempty"` + Comment *string `json:"comment,omitempty"` MaxRelocate *uint `json:"max_relocate,omitempty"` MaxRestart *uint `json:"max_restart,omitempty"` State *HAResourceState `json:"state,omitempty"` From 581006ac2ac60c185f0cc0c1ac6cd76fcefbce8f Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Tue, 4 Jun 2024 17:41:00 +0300 Subject: [PATCH 24/31] cluster ha resource delete --- cluster_ha_resources.go | 9 +++++++++ types.go | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/cluster_ha_resources.go b/cluster_ha_resources.go index 2a82149..2222570 100644 --- a/cluster_ha_resources.go +++ b/cluster_ha_resources.go @@ -2,6 +2,7 @@ package proxmox import ( "context" + "fmt" ) func (cl *Cluster) HAResourceCreate(ctx context.Context, haResource HAResource) error { @@ -11,3 +12,11 @@ func (cl *Cluster) HAResourceCreate(ctx context.Context, haResource HAResource) return nil } + +func (cl *Cluster) HAResourceDelete(ctx context.Context, sid SID) error { + if err := cl.client.Delete(ctx, fmt.Sprintf("/cluster/ha/resources/%s:%d", sid.Type, sid.ID), nil); err != nil { + return err + } + + return nil +} diff --git a/types.go b/types.go index 12bb216..09fb418 100644 --- a/types.go +++ b/types.go @@ -1480,6 +1480,7 @@ type VzdumpConfig struct { type ( HAType string HAResourceState string + HAResourceType string ) const ( @@ -1490,6 +1491,8 @@ const ( HAResourceStateEnabled = HAResourceState("enabled") HAResourceStateDisabled = HAResourceState("disabled") HAResourceStateIgnored = HAResourceState("ignored") + + HAResourceTypeVm = HAResourceType("vm") ) type HANodes struct { @@ -1505,6 +1508,11 @@ type HAGroupConfiguration struct { Restricted *IntOrBool } +type SID struct { + Type HAResourceType + ID int +} + type HAResource struct { ID int `json:"sid"` Group *string `json:"group"` From 6246749958db2e0fb33813d18720b64b67526bbd Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Tue, 18 Jun 2024 02:18:29 +0300 Subject: [PATCH 25/31] move opt --- types.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/types.go b/types.go index 276fc6b..c44cb20 100644 --- a/types.go +++ b/types.go @@ -939,6 +939,7 @@ type FirewallSecurityGroup struct { Comment string `json:"comment,omitempty"` Rules []*FirewallRule `json:"rules,omitempty"` } + type FirewallRule struct { Type string `json:"type,omitempty"` Action string `json:"action,omitempty"` @@ -954,6 +955,8 @@ type FirewallRule struct { Proto string `json:"proto,omitempty"` Source string `json:"source,omitempty"` Sport string `json:"sport,omitempty"` + + MoveTo *int `json:"moveto,omitempty"` // Other fields will be ignored when used } func (r *FirewallRule) IsEnable() bool { From e37fc12e7e1877fb20d09abd1ddf1c572fb76fbf Mon Sep 17 00:00:00 2001 From: Veniamin Stepanov Date: Thu, 4 Jul 2024 16:59:03 +0300 Subject: [PATCH 26/31] feat: generalize http client --- options.go | 7 +++++++ proxmox.go | 14 +++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/options.go b/options.go index bc36c3c..70c4055 100644 --- a/options.go +++ b/options.go @@ -1,6 +1,7 @@ package proxmox import ( + "crypto/tls" "fmt" "net/http" ) @@ -59,3 +60,9 @@ func WithLogger(logger LeveledLoggerInterface) Option { c.log = logger } } + +func WithTLSConfig(config *tls.Config) Option { + return func(c *Client) { + c.tlsConfig = config + } +} diff --git a/proxmox.go b/proxmox.go index 4b5bc22..96c556d 100644 --- a/proxmox.go +++ b/proxmox.go @@ -52,8 +52,13 @@ func MakeTag(v string) string { return fmt.Sprintf(TagFormat, v) } +type doer interface { + Do(req *http.Request) (*http.Response, error) +} + type Client struct { - httpClient *http.Client + httpClient doer + tlsConfig *tls.Config userAgent string baseURL string token string @@ -298,16 +303,11 @@ func (c *Client) VNCWebSocket(path string, vnc *VNC) (chan string, chan string, path = strings.Replace(c.baseURL, "https://", "wss://", 1) + path } - var tlsConfig *tls.Config - transport := c.httpClient.Transport.(*http.Transport) - if transport != nil { - tlsConfig = transport.TLSClientConfig - } c.log.Debugf("connecting to websocket: %s", path) dialer := &websocket.Dialer{ Proxy: http.ProxyFromEnvironment, HandshakeTimeout: 30 * time.Second, - TLSClientConfig: tlsConfig, + TLSClientConfig: c.tlsConfig, } dialerHeaders := http.Header{} From c174489449a3587630a5ce1c82b53acde0486ab1 Mon Sep 17 00:00:00 2001 From: Veniamin Stepanov Date: Thu, 4 Jul 2024 17:25:08 +0300 Subject: [PATCH 27/31] feat: change type of http client for option --- options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options.go b/options.go index 70c4055..f71deb8 100644 --- a/options.go +++ b/options.go @@ -13,7 +13,7 @@ func WithClient(client *http.Client) Option { return WithHTTPClient(client) } -func WithHTTPClient(client *http.Client) Option { +func WithHTTPClient(client doer) Option { return func(c *Client) { c.httpClient = client } From 0d48950b18b1e33c51530e3b33dff93c7998c83d Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Fri, 25 Oct 2024 11:57:56 +0300 Subject: [PATCH 28/31] ha resource get & list --- cluster_ha_resources.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/cluster_ha_resources.go b/cluster_ha_resources.go index 2222570..4b79843 100644 --- a/cluster_ha_resources.go +++ b/cluster_ha_resources.go @@ -5,7 +5,7 @@ import ( "fmt" ) -func (cl *Cluster) HAResourceCreate(ctx context.Context, haResource HAResource) error { +func (cl *Cluster) CreateHAResource(ctx context.Context, haResource HAResource) error { if err := cl.client.Post(ctx, "/cluster/ha/resources", &haResource, nil); err != nil { return err } @@ -13,10 +13,28 @@ func (cl *Cluster) HAResourceCreate(ctx context.Context, haResource HAResource) return nil } -func (cl *Cluster) HAResourceDelete(ctx context.Context, sid SID) error { +func (cl *Cluster) DeleteHAResource(ctx context.Context, sid SID) error { if err := cl.client.Delete(ctx, fmt.Sprintf("/cluster/ha/resources/%s:%d", sid.Type, sid.ID), nil); err != nil { return err } return nil } + +func (cl *Cluster) GetHAResource(ctx context.Context, sid SID) (HAResource, error) { + var haResource HAResource + if err := cl.client.Get(ctx, fmt.Sprintf("/cluster/ha/resources/%s:%d", sid.Type, sid.ID), &haResource); err != nil { + return haResource, err + } + + return haResource, nil +} + +func (cl *Cluster) ListHAResources(ctx context.Context, resourceType HAResourceType) ([]SID, error) { + var haResources []SID + if err := cl.client.Get(ctx, fmt.Sprintf("/cluster/ha/resources?type=%s", resourceType), &haResources); err != nil { + return nil, err + } + + return haResources, nil +} From 5bea9b4e2548833a6ea6324002d44536d5962f3d Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Fri, 25 Oct 2024 12:05:31 +0300 Subject: [PATCH 29/31] ha resource get & list --- cluster_ha_resources.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cluster_ha_resources.go b/cluster_ha_resources.go index 4b79843..817f559 100644 --- a/cluster_ha_resources.go +++ b/cluster_ha_resources.go @@ -30,8 +30,8 @@ func (cl *Cluster) GetHAResource(ctx context.Context, sid SID) (HAResource, erro return haResource, nil } -func (cl *Cluster) ListHAResources(ctx context.Context, resourceType HAResourceType) ([]SID, error) { - var haResources []SID +func (cl *Cluster) ListHAResources(ctx context.Context, resourceType HAResourceType) ([]HAResource, error) { + var haResources []HAResource if err := cl.client.Get(ctx, fmt.Sprintf("/cluster/ha/resources?type=%s", resourceType), &haResources); err != nil { return nil, err } From eea99582bd203616d66ed268bd2c4465090af50b Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Fri, 25 Oct 2024 13:07:47 +0300 Subject: [PATCH 30/31] change files --- cluster_ha_resources.go | 43 ++++++++++++++++++++++++++++++++++++++++- types.go | 9 +++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/cluster_ha_resources.go b/cluster_ha_resources.go index 817f559..eb61c52 100644 --- a/cluster_ha_resources.go +++ b/cluster_ha_resources.go @@ -2,7 +2,10 @@ package proxmox import ( "context" + "errors" "fmt" + "strconv" + "strings" ) func (cl *Cluster) CreateHAResource(ctx context.Context, haResource HAResource) error { @@ -31,10 +34,48 @@ func (cl *Cluster) GetHAResource(ctx context.Context, sid SID) (HAResource, erro } func (cl *Cluster) ListHAResources(ctx context.Context, resourceType HAResourceType) ([]HAResource, error) { - var haResources []HAResource + var haResources []haResource if err := cl.client.Get(ctx, fmt.Sprintf("/cluster/ha/resources?type=%s", resourceType), &haResources); err != nil { return nil, err } + return fillHAResources(haResources) +} + +func fillHAResources(resources []haResource) ([]HAResource, error) { + haResources := make([]HAResource, 0, len(resources)) + for _, resource := range resources { + sid, err := parseSid(resource.Sid) + if err != nil { + return nil, fmt.Errorf("parse sid: %w", err) + } + + haResources = append(haResources, HAResource{ + ID: sid.ID, + Group: &resource.Group, + Comment: &resource.Comment, + MaxRelocate: &resource.MaxRelocate, + MaxRestart: &resource.MaxRestart, + State: &resource.State, + }) + } + return haResources, nil } + +func parseSid(sid string) (SID, error) { + sidParts := strings.Split(sid, ":") + if len(sidParts) != 2 { + return SID{}, errors.New("invalid sid parts count") + } + + vmid, err := strconv.Atoi(sidParts[1]) + if err != nil { + return SID{}, fmt.Errorf("parse sid vmid: %w", err) + } + + return SID{ + Type: HAResourceType(sidParts[0]), + ID: vmid, + }, nil +} diff --git a/types.go b/types.go index 405047e..63b5a25 100644 --- a/types.go +++ b/types.go @@ -1516,6 +1516,15 @@ type SID struct { ID int } +type haResource struct { + Group string `json:"group"` + Sid string `json:"sid"` + State HAResourceState `json:"state"` + Comment string `json:"comment"` + MaxRestart uint `json:"max_restart"` + MaxRelocate uint `json:"max_relocate"` +} + type HAResource struct { ID int `json:"sid"` Group *string `json:"group"` From 9a7a104d54198d7e41b888bec97de585a078e674 Mon Sep 17 00:00:00 2001 From: Pivnoy Date: Fri, 25 Oct 2024 17:42:58 +0300 Subject: [PATCH 31/31] fix --- cluster_ha_resources.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cluster_ha_resources.go b/cluster_ha_resources.go index eb61c52..f5d2340 100644 --- a/cluster_ha_resources.go +++ b/cluster_ha_resources.go @@ -52,11 +52,11 @@ func fillHAResources(resources []haResource) ([]HAResource, error) { haResources = append(haResources, HAResource{ ID: sid.ID, - Group: &resource.Group, - Comment: &resource.Comment, - MaxRelocate: &resource.MaxRelocate, - MaxRestart: &resource.MaxRestart, - State: &resource.State, + Group: AsPtr(resource.Group), + Comment: AsPtr(resource.Comment), + MaxRelocate: AsPtr(resource.MaxRelocate), + MaxRestart: AsPtr(resource.MaxRestart), + State: AsPtr(resource.State), }) }