From e6c15eccc6fd2076afb2f521e28f27976abba892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 19 Aug 2023 03:48:37 +0200 Subject: [PATCH] feat(vm): pool update support (#505) * feat(vm): pool update support This commit removed the ForceNew flag from the VM resource's `pool_id` argument and implements pool update: * if the VM was part of a pool, it is removed from it, * if the new `pool_id` value is non-empty, the VM is added to that new pool. * fix: use `types.CustomCommaSeparatedList` in `PoolUpdateRequestBody` datatype, minor error fix --------- Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> --- proxmox/pools/pool_types.go | 9 +++++++ proxmoxtf/resource/vm.go | 51 ++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/proxmox/pools/pool_types.go b/proxmox/pools/pool_types.go index 625934ef..7fa12a31 100644 --- a/proxmox/pools/pool_types.go +++ b/proxmox/pools/pool_types.go @@ -6,6 +6,8 @@ package pools +import "github.com/bpg/terraform-provider-proxmox/internal/types" + // PoolCreateRequestBody contains the data for a pool create request. type PoolCreateRequestBody struct { Comment *string `json:"comment,omitempty" url:"comment,omitempty"` @@ -45,5 +47,12 @@ type PoolListResponseData struct { // PoolUpdateRequestBody contains the data for an pool update request. type PoolUpdateRequestBody struct { + // The pool's comment Comment *string `json:"comment,omitempty" url:"comment,omitempty"` + // If this is set to 1, VMs and datastores will be removed from the pool instead of added. + Delete *types.CustomBool `json:"delete,omitempty" url:"delete,omitempty,int"` + // The list of virtual machines to add or delete. + VMs *types.CustomCommaSeparatedList `json:"vms,omitempty" url:"vms,omitempty,comma"` + // The list of datastores to add or delete. + Storage *types.CustomCommaSeparatedList `json:"storage,omitempty" url:"storage,omitempty,comma"` } diff --git a/proxmoxtf/resource/vm.go b/proxmoxtf/resource/vm.go index 25c8fc9c..64e7cd40 100644 --- a/proxmoxtf/resource/vm.go +++ b/proxmoxtf/resource/vm.go @@ -17,6 +17,7 @@ import ( "time" "unicode" + "github.com/google/go-cmp/cmp" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -27,6 +28,7 @@ import ( "github.com/bpg/terraform-provider-proxmox/internal/types" "github.com/bpg/terraform-provider-proxmox/proxmox/cluster" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms" + "github.com/bpg/terraform-provider-proxmox/proxmox/pools" "github.com/bpg/terraform-provider-proxmox/proxmoxtf" "github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator" "github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure" @@ -1212,7 +1214,6 @@ func VM() *schema.Resource { Type: schema.TypeString, Description: "The ID of the pool to assign the virtual machine to", Optional: true, - ForceNew: true, Default: dvResourceVirtualEnvironmentVMPoolID, }, mkResourceVirtualEnvironmentVMSerialDevice: { @@ -4782,6 +4783,49 @@ func vmReadPrimitiveValues( return diags } +// vmUpdatePool moves the VM to the pool it is supposed to be in if the pool ID changed. +func vmUpdatePool( + ctx context.Context, + d *schema.ResourceData, + api *pools.Client, + vmID int, +) error { + oldPoolValue, newPoolValue := d.GetChange(mkResourceVirtualEnvironmentVMPoolID) + if cmp.Equal(newPoolValue, oldPoolValue) { + return nil + } + + oldPool := oldPoolValue.(string) + newPool := newPoolValue.(string) + vmList := (types.CustomCommaSeparatedList)([]string{strconv.Itoa(vmID)}) + + tflog.Debug(ctx, fmt.Sprintf("Moving VM %d from pool '%s' to pool '%s'", vmID, oldPool, newPool)) + + if oldPool != "" { + trueValue := types.CustomBool(true) + poolUpdate := &pools.PoolUpdateRequestBody{ + VMs: &vmList, + Delete: &trueValue, + } + + err := api.UpdatePool(ctx, oldPool, poolUpdate) + if err != nil { + return fmt.Errorf("while removing VM %d from pool %s: %w", vmID, oldPool, err) + } + } + + if newPool != "" { + poolUpdate := &pools.PoolUpdateRequestBody{VMs: &vmList} + + err := api.UpdatePool(ctx, newPool, poolUpdate) + if err != nil { + return fmt.Errorf("while adding VM %d to pool %s: %w", vmID, newPool, err) + } + } + + return nil +} + func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { config := m.(proxmoxtf.ProviderConfiguration) @@ -4798,6 +4842,11 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D return diag.FromErr(e) } + e = vmUpdatePool(ctx, d, api.Pool(), vmID) + if e != nil { + return diag.FromErr(e) + } + vmAPI := api.Node(nodeName).VM(vmID) updateBody := &vms.UpdateRequestBody{