diff --git a/docs/resources/virtual_environment_vm.md b/docs/resources/virtual_environment_vm.md index e7235fc6..4c87eea7 100644 --- a/docs/resources/virtual_environment_vm.md +++ b/docs/resources/virtual_environment_vm.md @@ -475,6 +475,7 @@ output "ubuntu_vm_public_key" { resource. You may use the `ignore_changes` lifecycle meta-argument to ignore changes to this attribute. - `template` - (Optional) Whether to create a template (defaults to `false`). +- `stop_on_destroy` - (Optional) Whether to stop rather than shutdown on VM destroy (defaults to `false`) - `timeout_clone` - (Optional) Timeout for cloning a VM in seconds (defaults to 1800). - `timeout_create` - (Optional) Timeout for creating a VM in seconds (defaults to diff --git a/proxmoxtf/resource/vm.go b/proxmoxtf/resource/vm.go index a1fff42d..0d265cd0 100644 --- a/proxmoxtf/resource/vm.go +++ b/proxmoxtf/resource/vm.go @@ -137,8 +137,8 @@ const ( dvResourceVirtualEnvironmentVMVGAMemory = 16 dvResourceVirtualEnvironmentVMVGAType = "std" dvResourceVirtualEnvironmentVMSCSIHardware = "virtio-scsi-pci" - - dvResourceVirtualEnvironmentVMHookScript = "" + dvResourceVirtualEnvironmentVMStopOnDestroy = false + dvResourceVirtualEnvironmentVMHookScript = "" maxResourceVirtualEnvironmentVMAudioDevices = 1 maxResourceVirtualEnvironmentVMNetworkDevices = 8 @@ -299,6 +299,7 @@ const ( mkResourceVirtualEnvironmentVMVMID = "vm_id" mkResourceVirtualEnvironmentVMSCSIHardware = "scsi_hardware" mkResourceVirtualEnvironmentVMHookScriptFileID = "hook_script_file_id" + mkResourceVirtualEnvironmentVMStopOnDestroy = "stop_on_destroy" ) // VM returns a resource that manages VMs. @@ -1576,6 +1577,12 @@ func VM() *schema.Resource { Optional: true, Default: dvResourceVirtualEnvironmentVMHookScript, }, + mkResourceVirtualEnvironmentVMStopOnDestroy: { + Type: schema.TypeBool, + Description: "Whether to stop rather than shutdown on VM destroy", + Optional: true, + Default: dvResourceVirtualEnvironmentVMStopOnDestroy, + }, }, CreateContext: vmCreate, ReadContext: vmRead, @@ -1747,6 +1754,20 @@ func vmShutdown(ctx context.Context, vmAPI *vms.Client, d *schema.ResourceData) return diag.FromErr(vmAPI.WaitForVMState(ctx, "stopped", shutdownTimeout, 1)) } +// Forcefully stop the VM, then wait for it to actually stop. +func vmStop(ctx context.Context, vmAPI *vms.Client, d *schema.ResourceData) diag.Diagnostics { + tflog.Debug(ctx, "Stopping VM") + + stopTimeout := d.Get(mkResourceVirtualEnvironmentVMTimeoutStopVM).(int) + + e := vmAPI.StopVM(ctx, stopTimeout+30) + if e != nil { + return diag.FromErr(e) + } + + return diag.FromErr(vmAPI.WaitForVMState(ctx, "stopped", stopTimeout, 1)) +} + func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { config := m.(proxmoxtf.ProviderConfiguration) @@ -6126,15 +6147,22 @@ func vmDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D vmAPI := api.Node(nodeName).VM(vmID) - // Shut down the virtual machine before deleting it. + // Stop or shut down the virtual machine before deleting it. status, err := vmAPI.GetVMStatus(ctx) if err != nil { return diag.FromErr(err) } + stop := d.Get(mkResourceVirtualEnvironmentVMStopOnDestroy).(bool) if status.Status != "stopped" { - if e := vmShutdown(ctx, vmAPI, d); e != nil { - return e + if stop { + if e := vmStop(ctx, vmAPI, d); e != nil { + return e + } + } else { + if e := vmShutdown(ctx, vmAPI, d); e != nil { + return e + } } }