Skip to content

Commit

Permalink
Perform guest shutdown if possible when destroy VM
Browse files Browse the repository at this point in the history
Signed-off-by: Zhongcheng Lao <zhongchengl@vmware.com>
  • Loading branch information
laozc committed Aug 1, 2023
1 parent 8263c4c commit dc62f79
Show file tree
Hide file tree
Showing 47 changed files with 4,667 additions and 149 deletions.
10 changes: 10 additions & 0 deletions apis/v1alpha3/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ import (
)

// Convert_v1beta1_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec is an autogenerated conversion function.
//
//nolint:golint,revive,stylecheck
func Convert_v1beta1_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(in *v1beta1.VirtualMachineCloneSpec, out *VirtualMachineCloneSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VirtualMachineCloneSpec_To_v1alpha3_VirtualMachineCloneSpec(in, out, s)
}

// Convert_v1beta1_VSphereVMStatus_To_v1alpha3_VSphereVMStatus is an autogenerated conversion function.
//
//nolint:golint,revive,stylecheck
func Convert_v1beta1_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(in *v1beta1.VSphereVMStatus, out *VSphereVMStatus, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereVMStatus_To_v1alpha3_VSphereVMStatus(in, out, s)
Expand All @@ -41,3 +43,11 @@ func Convert_v1beta1_VSphereClusterStatus_To_v1alpha3_VSphereClusterStatus(in *v
func Convert_v1beta1_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(in *v1beta1.VSphereClusterSpec, out *VSphereClusterSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereClusterSpec_To_v1alpha3_VSphereClusterSpec(in, out, s)
}

func Convert_v1beta1_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(in *v1beta1.VSphereMachineSpec, out *VSphereMachineSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereMachineSpec_To_v1alpha3_VSphereMachineSpec(in, out, s)
}

func Convert_v1beta1_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(in *v1beta1.VSphereVMSpec, out *VSphereVMSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereVMSpec_To_v1alpha3_VSphereVMSpec(in, out, s)
}
2 changes: 2 additions & 0 deletions apis/v1alpha3/vspheremachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func (src *VSphereMachine) ConvertTo(dstRaw conversion.Hub) error {

dst.Spec.AdditionalDisksGiB = restored.Spec.AdditionalDisksGiB
dst.Spec.TagIDs = restored.Spec.TagIDs
dst.Spec.PowerOffMode = restored.Spec.PowerOffMode
dst.Spec.GuestSoftPowerOffTimeout = restored.Spec.GuestSoftPowerOffTimeout
for i := range dst.Spec.Network.Devices {
dst.Spec.Network.Devices[i].AddressesFromPools = restored.Spec.Network.Devices[i].AddressesFromPools
dst.Spec.Network.Devices[i].DHCP4Overrides = restored.Spec.Network.Devices[i].DHCP4Overrides
Expand Down
2 changes: 2 additions & 0 deletions apis/v1alpha3/vspheremachinetemplate_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func (src *VSphereMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
}
dst.Spec.Template.Spec.TagIDs = restored.Spec.Template.Spec.TagIDs
dst.Spec.Template.Spec.AdditionalDisksGiB = restored.Spec.Template.Spec.AdditionalDisksGiB
dst.Spec.Template.Spec.PowerOffMode = restored.Spec.Template.Spec.PowerOffMode
dst.Spec.Template.Spec.GuestSoftPowerOffTimeout = restored.Spec.Template.Spec.GuestSoftPowerOffTimeout
for i := range dst.Spec.Template.Spec.Network.Devices {
dst.Spec.Template.Spec.Network.Devices[i].AddressesFromPools = restored.Spec.Template.Spec.Network.Devices[i].AddressesFromPools
dst.Spec.Template.Spec.Network.Devices[i].DHCP4Overrides = restored.Spec.Template.Spec.Network.Devices[i].DHCP4Overrides
Expand Down
2 changes: 2 additions & 0 deletions apis/v1alpha3/vspherevm_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ func (src *VSphereVM) ConvertTo(dstRaw conversion.Hub) error {
}
dst.Spec.TagIDs = restored.Spec.TagIDs
dst.Spec.AdditionalDisksGiB = restored.Spec.AdditionalDisksGiB
dst.Spec.PowerOffMode = restored.Spec.PowerOffMode
dst.Spec.GuestSoftPowerOffTimeout = restored.Spec.GuestSoftPowerOffTimeout
dst.Status.Host = restored.Status.Host
for i := range dst.Spec.Network.Devices {
dst.Spec.Network.Devices[i].AddressesFromPools = restored.Spec.Network.Devices[i].AddressesFromPools
Expand Down
34 changes: 14 additions & 20 deletions apis/v1alpha3/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions apis/v1alpha4/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
)

// Convert_v1beta1_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec is an autogenerated conversion function.
//
//nolint:golint,revive,stylecheck
func Convert_v1beta1_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(in *v1beta1.VirtualMachineCloneSpec, out *VirtualMachineCloneSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VirtualMachineCloneSpec_To_v1alpha4_VirtualMachineCloneSpec(in, out, s)
Expand All @@ -39,3 +40,11 @@ func Convert_v1beta1_VSphereClusterStatus_To_v1alpha4_VSphereClusterStatus(in *v
func Convert_v1beta1_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(in *v1beta1.VSphereClusterSpec, out *VSphereClusterSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereClusterSpec_To_v1alpha4_VSphereClusterSpec(in, out, s)
}

func Convert_v1beta1_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(in *v1beta1.VSphereMachineSpec, out *VSphereMachineSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereMachineSpec_To_v1alpha4_VSphereMachineSpec(in, out, s)
}

func Convert_v1beta1_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(in *v1beta1.VSphereVMSpec, out *VSphereVMSpec, s conversion.Scope) error {
return autoConvert_v1beta1_VSphereVMSpec_To_v1alpha4_VSphereVMSpec(in, out, s)
}
2 changes: 2 additions & 0 deletions apis/v1alpha4/vspheremachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func (src *VSphereMachine) ConvertTo(dstRaw conversion.Hub) error {

dst.Spec.AdditionalDisksGiB = restored.Spec.AdditionalDisksGiB
dst.Spec.TagIDs = restored.Spec.TagIDs
dst.Spec.PowerOffMode = restored.Spec.PowerOffMode
dst.Spec.GuestSoftPowerOffTimeout = restored.Spec.GuestSoftPowerOffTimeout
for i := range dst.Spec.Network.Devices {
dst.Spec.Network.Devices[i].AddressesFromPools = restored.Spec.Network.Devices[i].AddressesFromPools
dst.Spec.Network.Devices[i].DHCP4Overrides = restored.Spec.Network.Devices[i].DHCP4Overrides
Expand Down
2 changes: 2 additions & 0 deletions apis/v1alpha4/vspheremachinetemplate_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func (src *VSphereMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
}
dst.Spec.Template.Spec.TagIDs = restored.Spec.Template.Spec.TagIDs
dst.Spec.Template.Spec.AdditionalDisksGiB = restored.Spec.Template.Spec.AdditionalDisksGiB
dst.Spec.Template.Spec.PowerOffMode = restored.Spec.Template.Spec.PowerOffMode
dst.Spec.Template.Spec.GuestSoftPowerOffTimeout = restored.Spec.Template.Spec.GuestSoftPowerOffTimeout
for i := range dst.Spec.Template.Spec.Network.Devices {
dst.Spec.Template.Spec.Network.Devices[i].AddressesFromPools = restored.Spec.Template.Spec.Network.Devices[i].AddressesFromPools
dst.Spec.Template.Spec.Network.Devices[i].DHCP4Overrides = restored.Spec.Template.Spec.Network.Devices[i].DHCP4Overrides
Expand Down
2 changes: 2 additions & 0 deletions apis/v1alpha4/vspherevm_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ func (src *VSphereVM) ConvertTo(dstRaw conversion.Hub) error {
}
dst.Spec.TagIDs = restored.Spec.TagIDs
dst.Spec.AdditionalDisksGiB = restored.Spec.AdditionalDisksGiB
dst.Spec.PowerOffMode = restored.Spec.PowerOffMode
dst.Spec.GuestSoftPowerOffTimeout = restored.Spec.GuestSoftPowerOffTimeout
dst.Status.Host = restored.Status.Host
for i := range dst.Spec.Network.Devices {
dst.Spec.Network.Devices[i].AddressesFromPools = restored.Spec.Network.Devices[i].AddressesFromPools
Expand Down
34 changes: 14 additions & 20 deletions apis/v1alpha4/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions apis/v1beta1/condition_consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,17 @@ const (
// cannot be found.
IPAddressClaimNotFoundReason = "IPAddressClaimNotFound"
)

const (
// GuestSoftPowerOffSucceededCondition documents the status of performing guest initiated
// graceful shutdown.
GuestSoftPowerOffSucceededCondition clusterv1.ConditionType = "GuestSoftPowerOffSucceeded"

// GuestSoftPowerOffInProgressReason (Severity=Info) documents that the guest receives
// a graceful shutdown request.
GuestSoftPowerOffInProgressReason = "GuestSoftPowerOffInProgress"

// GuestSoftPowerOffFailedReason (Severity=Warning) documents that the graceful
// shutdown request fails.
GuestSoftPowerOffFailedReason = "GuestSoftPowerOffFailed"
)
28 changes: 28 additions & 0 deletions apis/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,34 @@ const (
Windows OS = "Windows"
)

// VirtualMachinePowerOpMode represents the various power operation modes
// when powering off or suspending a VM.
// +kubebuilder:validation:Enum=hard;soft;trySoft
type VirtualMachinePowerOpMode string

const (
// VirtualMachinePowerOpModeHard indicates to halt a VM when powering it
// off or when suspending a VM to not involve the guest.
VirtualMachinePowerOpModeHard VirtualMachinePowerOpMode = "hard"

// VirtualMachinePowerOpModeSoft indicates to ask VM Tools running
// inside of a VM's guest to shutdown the guest gracefully when powering
// off a VM or when suspending a VM to allow the guest to participate.
//
// If this mode is set on a VM whose guest does not have VM Tools or if
// VM Tools is present but the operation fails, the VM may never realize
// the desired power state. This can prevent a VM from being deleted as well
// as many other unexpected issues. It is recommended to use trySoft
// instead.
VirtualMachinePowerOpModeSoft VirtualMachinePowerOpMode = "soft"

// VirtualMachinePowerOpModeTrySoft indicates to first attempt a Soft
// operation and fall back to hard if VM Tools is not present in the guest,
// if the soft operation fails, or if the VM is not in the desired power
// state within the configured timeout (default 5m).
VirtualMachinePowerOpModeTrySoft VirtualMachinePowerOpMode = "trySoft"
)

// VirtualMachineCloneSpec is information used to clone a virtual machine.
type VirtualMachineCloneSpec struct {
// Template is the name or inventory path of the template used to clone
Expand Down
27 changes: 27 additions & 0 deletions apis/v1beta1/vspheremachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ type VSphereMachineSpec struct {
// FailureDomain is the failure domain unique identifier this Machine should be attached to, as defined in Cluster API.
// For this infrastructure provider, the name is equivalent to the name of the VSphereDeploymentZone.
FailureDomain *string `json:"failureDomain,omitempty"`

// PowerOffMode describes the desired behavior when powering off a VM.
//
// There are three, supported power off modes: hard, soft, and
// trySoft. The first mode, hard, is the equivalent of a physical
// system's power cord being ripped from the wall. The soft mode
// requires the VM's guest to have VM Tools installed and attempts to
// gracefully shut down the VM. Its variant, trySoft, first attempts
// a graceful shutdown, and if that fails or the VM is not in a powered off
// state after reaching the GuestSoftPowerOffTimeout, the VM is halted.
//
// If omitted, the mode defaults to hard.
//
// +optional
// +kubebuilder:default=hard
PowerOffMode VirtualMachinePowerOpMode `json:"powerOffMode,omitempty"`

// GuestSoftPowerOffTimeout sets the wait timeout for shutdown in the VM guest.
// The VM will be powered off forcibly after the timeout if the VM is still
// up and running when the PowerOffMode is set to trySoft.
//
// This parameter only applies when the PowerOffMode is set to trySoft.
//
// If omitted, the timeout defaults to 5 minutes.
//
// +optional
GuestSoftPowerOffTimeout *metav1.Duration `json:"guestSoftPowerOffTimeout,omitempty"`
}

// VSphereMachineStatus defines the observed state of VSphereMachine
Expand Down
Loading

0 comments on commit dc62f79

Please sign in to comment.