vsphere/internal/helper/virtualmachine/virtual_machine_helper.go
func GracefulPowerOff(client *govmomi.Client, vm *object.VirtualMachine, timeout int, force bool) error {
	vprops, err := Properties(vm)
	if err != nil {
		return err
	}
	// First we attempt a guest shutdown if we have VMware tools and if the VM is
	// actually powered on (we don't expect that a graceful shutdown would
	// complete on a suspended VM, so there's really no point in trying).
	if vprops.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOn && vprops.Guest != nil && vprops.Guest.ToolsRunningStatus == string(types.VirtualMachineToolsRunningStatusGuestToolsRunning) {
		if err := ShutdownGuest(client, vm, timeout); err != nil {
			if err == errGuestShutdownTimeout && !force {
				return err
			}
		} else {
			return nil
		}
	}
	// If the guest shutdown failed (and we were allowed to proceed), or
	// conditions did not satisfy the criteria for a graceful shutdown, do a full
	// power-off of the VM.
	return PowerOff(vm)
}
func GracefulPowerOff(client *govmomi.Client, vm *object.VirtualMachine, timeout int, force bool) error {
	vprops, err := Properties(vm)
	if err != nil {
		return err
	}
	// First we attempt a guest shutdown if we have VMware tools and if the VM is
	// actually powered on (we don't expect that a graceful shutdown would
	// complete on a suspended VM, so there's really no point in trying).
	if vprops.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOn && vprops.Guest != nil && vprops.Guest.ToolsRunningStatus == string(types.VirtualMachineToolsRunningStatusGuestToolsRunning) {
		if err := ShutdownGuest(client, vm, timeout); err != nil {
			if err == errGuestShutdownTimeout && !force {
				return err
			}
		} else {
			return nil
		}
	}
	// If the guest shutdown failed (and we were allowed to proceed), or
	// conditions did not satisfy the criteria for a graceful shutdown, do a full
	// power-off of the VM.
	return PowerOff(vm)
}
// GracefulPowerOff is a meta-operation that handles powering down of virtual
// machines. A graceful shutdown is attempted first if possible (VMware tools
// is installed, and the guest state is not suspended), and then, if allowed, a
// power-off is forced if that fails.