diff --git a/proxmox/cluster/cluster.go b/proxmox/cluster/cluster.go index b3de0db1..00193fe3 100644 --- a/proxmox/cluster/cluster.go +++ b/proxmox/cluster/cluster.go @@ -94,3 +94,47 @@ func (c *Client) GetVMID(ctx context.Context) (*int, error) { return nil, errors.New("unable to determine the next available VM identifier") } + +// GetClusterResources retrieves current resources for cluster. +func (c *Client) GetClusterResources(ctx context.Context, resourceType string) ([]*ResourcesListResponseData, error) { + reqBody := &ResourcesListRequestBody{ + Type: resourceType, + } + resBody := &ResourcesListBody{} + + err := c.DoRequest(ctx, http.MethodGet, "cluster/resources", reqBody, resBody) + if err != nil { + return nil, fmt.Errorf("failed to get resources list of type (\"%s\") for cluster: %w", resourceType, err) + } + + if resBody.Data == nil { + return nil, api.ErrNoDataObjectInResponse + } + + return resBody.Data, nil +} + +// GetClusterResourcesVM retrieves current VM resources for cluster. +func (c *Client) GetClusterResourcesVM(ctx context.Context) ([]*ResourcesListResponseData, error) { + return c.GetClusterResources(ctx, "vm") +} + +// GetVMNodeName gets node for specified vmID. +func (c *Client) GetVMNodeName(ctx context.Context, vmID int) (*string, error) { + allClusterVM, err := c.GetClusterResourcesVM(ctx) + if err != nil { + return nil, err + } + + if allClusterVM == nil { + return nil, api.ErrNoDataObjectInResponse + } + + for _, v := range allClusterVM { + if v.VMID == vmID { + return &v.NodeName, nil + } + } + + return nil, errors.New("unable to determine node name for VM identifier") +} diff --git a/proxmox/cluster/cluster_types.go b/proxmox/cluster/cluster_types.go index c77cf6d5..23e49d7d 100644 --- a/proxmox/cluster/cluster_types.go +++ b/proxmox/cluster/cluster_types.go @@ -19,3 +19,37 @@ type NextIDRequestBody struct { type NextIDResponseBody struct { Data *types.CustomInt `json:"data,omitempty"` } + +// ResourcesListBody contains the body from a cluste resource list response. +type ResourcesListBody struct { + Data []*ResourcesListResponseData `json:"data,omitempty"` +} + +// ResourcesListRequestBody contains the body params to cluster resource list request. +type ResourcesListRequestBody struct { + Type string `json:"type" url:"type"` +} + +// ResourcesListResponseData contains the data from a cluster resource list body response. +type ResourcesListResponseData struct { + Type string `json:"type"` + ID string `json:"id"` + CgroupMode int `json:"cgroup-mode,omitempty"` + Content int `json:"content,omitempty"` + CPU float64 `json:"cpu,omitempty"` + Disk int `json:"disk,omitempty"` + HaState string `json:"hastate,omitempty"` + Level string `json:"level,omitempty"` + MaxCPU float64 `json:"maxcpu,omitempty"` + MaxDisk int `json:"maxdisk,omitempty"` + MaxMem int `json:"maxmem,omitempty"` + Mem int `json:"mem,omitempty"` + Name string `json:"name,omitempty"` + NodeName string `json:"node,omitempty"` + PluginType string `json:"plugintype,omitempty"` + PoolName string `json:"poolname,omitempty"` + Status string `json:"status,omitempty"` + Storage string `json:"storage,omitempty"` + Uptime int `json:"uptime,omitempty"` + VMID int `json:"vmid,omitempty"` +} diff --git a/proxmoxtf/resource/vm.go b/proxmoxtf/resource/vm.go index cff73416..d4114d99 100644 --- a/proxmoxtf/resource/vm.go +++ b/proxmoxtf/resource/vm.go @@ -3035,12 +3035,25 @@ func vmRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Dia return diag.FromErr(err) } - nodeName := d.Get(mkResourceVirtualEnvironmentVMNodeName).(string) vmID, err := strconv.Atoi(d.Id()) if err != nil { return diag.FromErr(err) } + vmNodeName, err := api.Cluster().GetVMNodeName(ctx, vmID) + if err != nil { + return diag.FromErr(err) + } + + if vmNodeName != d.Get(mkResourceVirtualEnvironmentVMNodeName) { + err = d.Set(mkResourceVirtualEnvironmentVMNodeName, vmNodeName) + if err != nil { + return diag.FromErr(err) + } + } + + nodeName := d.Get(mkResourceVirtualEnvironmentVMNodeName).(string) + vmAPI := api.Node(nodeName).VM(vmID) // Retrieve the entire configuration in order to compare it to the state.