Scheduled Tasks – MethodAction

With the introduction of vSPhere the types of Tasks you can select when you create a new Scheduled Task has increased. This is a very useful feature that allows you to schedule for example your (s)vMotions, your Snapshots, your Imports and Exports and so on.

Schedule-Task-Listbox

In the PowerCLI Community there was a recent question on how these Scheduled Tasks can be created from PowerShell (see relocate vm’s from csv file and create schedule task in VC).

Being able to create a Scheduled Task for a svMotion for several guests from a PowerShell script, instead of clicking away in the vSphere Client, would be another step on the path of vSphere automation.

The current PowerCLI 4 (build 162509) unfortunately has no cmdlets for Scheduled Tasks. But the SDK contains the CreateScheduledTask method that can be used for this purpose.

The key parameter to this method is the ScheduledTaskSpec object. In the action property of this object you specify which type of action you want the scheduled task to take. If we want to schedule a Task, we will have to select the MethodAction extension object.

But then it looks as if we’re stuck. The SDK Reference doesn’t say which are the accepted values for the name property in the MethodAction object.

Luckily, with a bit of reverse engineering and with the help of Fiddler (see my The Onyx alternative ? post), I was able to get the accepted values for the name property.

In fact the set up is quite straightforward, the name property holds the name of the SDK method that performs the type of task requested. And the argument property, which is an array, will hold all the parameters that go with the called method.

An example.

We want to “Migrate a virtual machine” and move the VM to another datastore.

This is a svMotion.

That means we need the RelocateVM_Task method.

This method requires 2 parameters.

RelocateVM_Task

We will have to pass those parameters for the method in the argument array in the MethodAction object. Schematically, the MethodAction object will look like this

MethodAction-Properties

MethodAction name values

The following table shows which SDK method corresponds with which Task. With the name of the SDK method you can find the parameters that need to go in the MethodAction.argument property.

Task MethodAction.name
Add a host AddStandaloneHost_Task
Change resource settings of Resource Pool or Virtual Machine UpdateConfig
Change the power state of a virtual machine ResetVM_Task
Check compliance for a profile CheckProfileCompliance_Task
Clone a virtual machine CloneVM_Task
Create a virtual machine CreateVM_Task
Deploy a virtual machine CloneVM_Task
Make a snapshot of a virtual machine CreateSnapshot_Task
Migrate a virtual machine RelocateVM_Task

Note1: The import and export a virtual machine tasks do not use the MethodAction. They use CreateTaskAction and the TaskTypeId is respectively com.vmware.converter.Import and com.vmware.converter.Export

Note2: The Scan and Remediate tasks also use CreateTaskAction. The TaskTypeId is respectively com.vmware.vcIntegrity.ScanTask and com.vmware.vcIntegrity.RemediateTask

The script

The Virtual Machine names come from a CSV file with 1 column and with the header VMname.

The script looks like this:

Task
19 Comments

    simbol

    Hi all,

    I`m struggling with my Script to schedule a Snapshot-remove. Is this even possible via script? In the other hand, create a scheduled snapshot create task works fine.

    thanks a lot

    $vm = Get-VM -Name “test”
    $si = get-view ServiceInstance
    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager
    $spec = New-Object VMware.Vim.ScheduledTaskSpec
    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
    # Validate datetime value and convert to UTC
    try { $castRunTime = ([datetime]$runTime).ToUniversalTime() } catch { “Unable to convert runtime parameter to date time value”; break }
    if ( [datetime]$runTime -lt (Get-Date) ) { “Single run tasks can not be scheduled to run in the past. Please adjust start time and try again.”; break }
    $spec.Scheduler.RunAt = $castRunTime
    $spec.Name = $snapName
    $spec.Enabled = $true
    $spec.Action = New-Object VMware.Vim.MethodAction
    $spec.Action.Name = “RemoveSnapshot_Task”
    @($snapName) | %{

    $arg = New-Object VMware.Vim.MethodActionArgument

    $arg.Value = $_

    $spec.Action.Argument += $arg

    }

    $scheduledTaskManager.CreateObjectScheduledTask($vm.MoRef,$spec)

    —————————-

    ESXi Version 6.5

    Error Output:

    Exception calling “CreateObjectScheduledTask” with “2” argument(s): ”
    Required parameter obj is missing
    while parsing call information for method CreateObjectScheduledTask
    at line 1, column 171
    while parsing SOAP body
    at line 1, column 64
    while parsing SOAP envelope
    at line 1, column 0
    while parsing HTTP request for method createObjectScheduledTask
    on object of type vim.scheduler.ScheduledTaskManager
    at line 1, column 0″
    At line:1 char:1
    + $scheduledTaskManager.CreateObjectScheduledTask($vm.MoRef, $spec)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException

    marius

    I made an extensive use of scripts based on the srcipts in this page ant they solved a lot of problems for me.
    So, many thanks, LucD!
    Let ma ask for an additional improvement: while migrating a VM can I specify that I want to change the disk format from thin to thick or from thick to thin?
    Regards and thanks again

      LucD

      Hi Marius,
      In theory that is possible, you can define the complete VirtualMachineRelocateSpec object (1st argument) in the Scheduled Task.
      But since converting the disk type needs to be done per disk, you will need to target VMs with the same number of VMDK and the DeviceId, which you also need to specify, needs to be the same on all VMs.

    Bobby

    Hi Luc,

    Thank you for the wonderful and helpful script. I got a question, anyway we can add a status report of this migration to where it will export to a CSV file, perhaps ending on c:\Temp\report.csv/txt?
    If like Provisioned size (MB) same from the source?
    VMname, disk count mounted? etc.

    Thanks,

      LucD

      Hi Bobby,
      These MethodAction tasks just call one method, there is no script involved.
      And we would need a script to add more functionality, like writing to a log.
      You can schedule a script as well, although on VCSA systems this is a bit more tricky, due to the fact that a VCSA is to be considered a ‘black box’.

      The easiest way, without voiding the support on your VCSA, would be to use an external scheduler.

    Jo

    Hi Luc,
    great article, as always!

    As Ryan asked years ago, how can we check if the task already exists and in case remove/edit it?

    Thanks

      Jo

      Nevermind, I did it.
      I found this https://www.eehelp.com/question/reconfigure-the-scheduled-task/, which wasn’t working. However, I’ve adapted it and found a way to make it working. Here the extra code:

      # Check if the task already exists
      $scheduledTaskManager.RetrieveEntityScheduledTask($vm.MoRef) | %{
      $t = (Get-View ScheduledTaskManager).ScheduledTask | %{ (Get-View $_).Info } | Where-Object {$_.Name -eq $spec.Name}
      $scheduledTask = Get-View -Id $_ | Where-Object {$t.Name -eq $spec.Name}
      }

      # If the task already exists then update it, otherwise create it
      if($scheduledTask){
      $scheduledTask.ReconfigureScheduledTask($spec)
      }
      else{
      $scheduledTaskManager.CreateScheduledTask($vm.MoRef, $Spec)
      }

    Marius

    Great code!
    I tested it and it works fine for powered off VMs.
    My only trouble is: it looks that VMware.Vim.VirtualMachineRelocateSpec always creates a task to change either datastore and host; if I don’t specify anything the current host is kept.
    If the VM is powered on the task attempts to change the host instead of changing the datastore.
    How can I specify that I want to change only the datastore?
    Regards
    marius

      LucD

      In the $arg1.Value you are in fact creating the VirtualMachineRelocateSpec object. In the script I used datastore, pool and host.
      Did you already try by just entering the datastore ?

    Marius

    Excellent and useful script!
    Still valid many years later…
    My only concern is that when I review the scheduled task created with the script I see that “Change both host and datastore” is selected, while I want only to change the datastore.
    How can I specify that I want to change only the datastore?
    Regards

    Anastasia

    Hi, i try to use your script to migrate 2 VMs to another datastore but i get error

    PowerCLI C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> c:\vmC
    ne_migrate.ps1

    Type Value
    —- —–
    ScheduledTask schedule-1
    Exception calling “CreateScheduledTask” with “2” argument(s): ”
    Required parameter entity is missing
    while parsing call information for method CreateScheduledTask
    at line 1, column 218
    while parsing SOAP body
    at line 1, column 207
    while parsing SOAP envelope
    at line 1, column 38
    while parsing HTTP request for method create
    on object of type vim.scheduler.ScheduledTaskManager
    at line 1, column 0″
    At C:\vmClone_migrate.ps1:34 char:1
    + $scheduledTaskManager.CreateScheduledTask($vm.MoRef, $spec)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException

    Only one task for first VM from CSV created.

    $csvName = “C:\Test0.csv”
    $tgtDatastore = “internal_1_old”
    $startTime = [Datetime]”05/08/2015 19:00″
    $startInterval = 1

    $si = get-view ServiceInstance
    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

    $offset = 0
    Import-Csv $csvName | % {
    $vm = Get-View -ViewType VirtualMachine -Filter @{“Name”=$_.VMname}

    $spec = New-Object VMware.Vim.ScheduledTaskSpec
    $spec.Name = “svMotion ” + $_.VMname
    $spec.Description = “Migrate ” + $_.VMname + ” to ” + $tgtDatastore
    $spec.Enabled = $true
    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
    $spec.Scheduler.runat = $startTime.AddMinutes($offset)
    $offset += $startInterval
    $spec.Action = New-Object VMware.Vim.MethodAction
    $spec.Action.Name = “RelocateVM_Task”

    $arg1 = New-Object VMware.Vim.MethodActionArgument
    $arg1.Value = New-Object VMware.Vim.VirtualMachineRelocateSpec
    $arg1.Value.datastore = (Get-Datastore $tgtDatastore | Get-View).MoRef
    $arg1.Value.pool = $vm.ResourcePool
    $arg1.Value.host = $vm.Runtime.Host

    $spec.Action.Argument += $arg1
    $arg2 = New-Object VMware.Vim.MethodActionArgument
    $arg2.Value = [VMware.Vim.VirtualMachineMovePriority]”defaultPriority”
    $spec.Action.Argument += $arg2

    $scheduledTaskManager.CreateScheduledTask($vm.MoRef, $spec)
    }

    Thank you

    Werner

    Excellent script!

    Got an error at first:

    Object reference not set to an instance of an object.

    If you get that as well; make the CSV inport file like so:

    VMname

    and so on

    Thanks Luc for this great script!

    Michael

    Hello,
    I would like to use this script to convert Think to Thin disks. How can I do this? I am running ESXi v5 and thank you.

    Andrew Berk

    I cannot get this script to work, I get the following error:

    Exception calling “CreateScheduledTask” with “2” argument(s): ”
    Error processing attribute “type” with value “vm”

    while parsing MoRef for ManagedObject of type vim.ManagedEntity
    at line 1, column 320

    while parsing call information for method CreateScheduledTask
    at line 1, column 218

    while parsing SOAP body
    at line 1, column 207

    while parsing SOAP envelope
    at line 1, column 38

    while parsing HTTP request for method create
    on object of type vim.scheduler.ScheduledTaskManager
    at line 1, column 0″
    At line:34 char:42
    + $scheduledTaskManager.CreateScheduledTask <<<< ($vm.ExtensionData.Moref.Value, $spec)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Luis B

    @Jeff C.

    I was getting this error too when I found something out. The time that’s entered in the script is in UTC time!! So make sure you’re accounting for that in the time settings of the script. So if you want it to execute 5 minutes from now add 8 hours and 5 minutes from now and enter that time in the script.

    Ryan

    Luc, how would you check if the task already exists and if so reconfigure the existing task? Or, delete the existing and create a new one?

    Jeff C.

    @Jeff C.
    I figured it out. I had entered the time format incorrectly (9:30 vs 09:30). And as always, great script Luc!

      LucD

      Hi Jeff, thanks for figuring it out.
      The SDK API can be picky about their parameters sometimes 😉

    Jeff C.

    Luc, Looks like this is some great code… I am having trouble with it though. Geting this error. Any thoughts?

    Exception calling “CreateScheduledTask” with “2” argument(s): “A specified para
    meter was not correct.

    Powercli 4.1 build 264274
    vcenter 4.1

    Thanks as always,

    Jeff

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.