vCenter

 View Only

 PowerCLI and scheduling power offs

StephenChr's profile image
StephenChr posted Jul 17, 2024 01:13 PM

Hello all;

First time poster since Broadcom took over.

One of the requirements for our VMs in AWS is to ensure consistent and proper custom attributes (Tagging, we call it, but it's not the VMWare tagging) so that we've got machines running that are supposed to be running, and any rogue systems that people stand up without proper tagging gets shut down after a week.  We stand up and deploy machines and use these custom attributes to determine product, customer, ownership and how mission critical the machine is.

I've previously attempted to use the Stop-VM cmdlet via PowerShell and even though I'm able to execute the statements at the command line and the scripts do their job, when run out of Windows Task Scheduler, everything works EXCEPT the shut down.  I get my reports, I see the debug statements in the email I receive indicating that it was told to do the shutdown, but, the VM just doesn't get shut down.

So I've changed gears to get vCenter to perform the scheduled shut down in 7+{days to Wednesday}.  So not "this coming Wednesday, but the Wednesday after 10am".

The problem I'm running into is that I'm not quite sure where things are going south with the script.

The important part is here:

	if ($AreCustomAttributesValid) {
			if ($existingShutdownTaskInfo) {
					$ShutDownStatus = "Scheduled shutdown removed (Custom Attributes are valid)."
					$existingShutdownTask = Get-View $existingShutdownTaskInfo.Entity
					$existingShutdownTask.RemoveScheduledTask() | Out-Null
			}
	} else {
			if ($isPoweredOn -and -not $existingShutdownTaskInfo) {
					$ShutDownStatus = "Shutdown scheduled for $($scheduledTime.ToString('dddd, MMMM dd, yyyy at HH:mm'))"
					$scheduledTask = New-ScheduledTask -Name "$($VM.Name) - $Site - Tag Compliance Fault" -Action (New-ScheduledTaskAction -StopVirtualMachine -VM $VM) -Trigger (New-ScheduledTaskTrigger -Once -At $scheduledTime)
					$scheduledTaskManager.CreateScheduledTask($scheduledTask.Info, $VM.ExtensionData.MoRef) | Out-Null
			} elseif (-not $isPoweredOn -and $existingShutdownTaskInfo) {
					$ShutDownStatus = "Scheduled shutdown removed (VM is powered off)"
					$existingShutdownTask = Get-View $existingShutdownTaskInfo.Entity
					$existingShutdownTask.RemoveScheduledTask() | Out-Null
			}
	}

I've got a few decision maker variables that determine what the script is supposed to do taking into consideration if the tags are set correctly, what the VMs power status is, and if there's already a scheduled task of a fixed text format is present.

All the detection steps are working.  But I'm stuck on the second IF block where the New-ScheduledTask is executing.  The script is stopping telling me that it doesn't know what -StopVirtualMachine means.

My Google-fu isn't getting me what I want.  I typically get the instructions for manual process through vCenter itself.

The actual error I'm getting is this:

New-ScheduledTaskAction : A parameter cannot be found that matches parameter name 'StopVirtualMachine'.
At C:\{path}\vmware_tag_check.ps1:76 char:125
+ ... e Fault" -Action (New-ScheduledTaskAction -StopVirtualMachine -VM $VM ...
+                                               ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-ScheduledTaskAction], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,New-ScheduledTaskAction
 
Cannot convert argument "spec", with value: "VirtualMachine-vm-81819", for "CreateScheduledTask" to type "VMware.Vim.ScheduledTaskSpec": "Cannot convert the "VirtualMachine-vm-81819" value of type "VMware.Vim.ManagedObjectReference" to type "VMware.Vim.ScheduledTaskSpec"."
At C:\{path}\vmware_tag_check.ps1:77 char:6
+ ...             $scheduledTaskManager.CreateScheduledTask($scheduledTask. ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
StephenChr's profile image
StephenChr

After discussions with an AI, we managed to work out a new routine to handle this, and it seems to have worked.

function Create-VMComplianceShutdownTask {
	param(
			[Parameter(Mandatory=$true)]
			[VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]$VM,
			
			[Parameter(Mandatory=$true)]
			[string]$Site,
			
			[Parameter(Mandatory=$true)]
			[DateTime]$ScheduledTime
	)

	try {
			$taskName = "$($VM.Name) - $Site - Tag Compliance Fault"
			
			# Create a scheduler
			$scheduler = New-Object VMware.Vim.OnceTaskScheduler
			$scheduler.RunAt = $ScheduledTime
			
			# Create the task specification
			$spec = New-Object VMware.Vim.ScheduledTaskSpec
			$spec.Name = $taskName
			$spec.Description = "Automated shutdown due to tag compliance fault"
			$spec.Enabled = $true
			$spec.Scheduler = $scheduler
			
			# Create the action to power off the VM
			$spec.Action = New-Object VMware.Vim.MethodAction
			$spec.Action.Name = "PowerOffVM_Task"
			
			# Get the ScheduledTaskManager
			$scheduledTaskManager = Get-View (Get-View ServiceInstance).Content.ScheduledTaskManager

			# Create the scheduled task
			$scheduledTaskManager.CreateScheduledTask($VM.ExtensionData.MoRef, $spec)

			return $true
	}
	catch {
			Write-Error "Failed to create scheduled task: $_"
			return $false
	}
}