Reply to Message

View discussion in a popup

Replying to:
ssheikhgpo
Contributor
Contributor

Scheduled task for cross-site vMotion

I am trying to write a script that would create a scheduled task for a cross-site vMotion. I can create that scheduled task through the GUI and it works. The environment is 3 linked 7.0 sites. From PowerShell there are connected VISessions to all three VC servers.   

When trying to do it through the script below, If I make sure sure that $scheduledTaskManager instance is from the VC where the VM is currently located then it throws errors for objects that are on the destination site. Errors like:

Exception calling "CreateScheduledTask" with "2" argument(s): "The object 'vim.ResourcePool:resgroup-1002' has already been deleted or has not been completely created"
At C:\Scripts\MigrateTo-IMDC\Create-VMMoveScheduledTask.ps1:123 char:12
+ return ($scheduledTaskManager.CreateScheduledTask($vmView.MoRef, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException

If I remove the resource pool then it complains about the datastore:

Exception calling "CreateScheduledTask" with "2" argument(s): "The object 'vim.Datastore:datastore-1411' has already been deleted or has not been completely created"
At C:\Scripts\MigrateTo-IMDC\Create-VMMoveScheduledTask.ps1:123 char:5
+ $scheduledTaskManager.CreateScheduledTask($vmView.MoRef, $spec)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException

If I remove the datastore then it complains about the destination Host. And so on.

If I let $scheduledTaskManager enumerate ScheduledTaskManagers from all 3 sites then it cant find the VM:

Exception calling "CreateScheduledTask" with "2" argument(s): "The object 'vim.VirtualMachine:vm-107863' has already been deleted or has not been completely created"
At C:\Scripts\MigrateTo-IMDC\Create-VMMoveScheduledTask.ps1:123 char:12
+ return ($scheduledTaskManager.CreateScheduledTask($vmView.MoRef, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException

 

My script is as follows. Any help would be much appreciated.

function Create-VMMoveScheduledTask {
    Param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]
        $VM,

        [Alias("Folder")]
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [VMware.VimAutomation.ViCore.Types.V1.Inventory.Folder]
        $DestinationFolder,

        [Alias("VMHost")]
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]
        $DestinationHost,

        [Alias("Datastore")]
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]
        $DestinationDatastore,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        # Array of Hashes. Keys = MACAddress. Values = PortGroup (object).
        [ValidateScript({
            if ($_.keys | Where-Object {$_ -notmatch "^[a-fA-F0-9]{2}([:-]?[a-fA-F0-9]{2}){5}$"}) {return $false}
            if ($_.values | Where-Object {!($_ -is [VMware.VimAutomation.Vds.Types.V1.VDPortgroup])}) {return $false}
            return $true;
        })]
      $vNICPortGroups,

        [
Alias("Name")]
        [Parameter(Mandatory = $true)]
        [String]
        $TaskName = "Create-VMMoveScheduledTask $(Get-Date -Format G)",      

        [
Alias("Description")]
        [Parameter(Mandatory = $true)]
        [String]
        $TaskDescription = "Create-VMMoveScheduledTask $(Get-Date -Format G)",

        [Parameter(Mandatory = $true)]
        [ValidateScript({([DateTime]$_) -gt (([DateTime]::Now).AddSeconds(15)) -and ([DateTime]$_) -lt (([DateTime]::Now).AddDays(7))})]
        [DateTime]
        $StartTime,

        [Alias("Email")]
        [Parameter()]
        [ValidatePattern("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")]
        [string]
        $AlertEmail
    )

    #$si = Get-View ServiceInstance -Server ($VM.Uid -replace "^.*@(.*):.*$",'$1')
    $si = Get-View ServiceInstance
    #$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server ($VM.Uid -replace "^.*@(.*):.*$",'$1')
    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

    $vmView = $VM | Get-View

    # ScheduledTask specs
    $spec = New-Object VMware.Vim.ScheduledTaskSpec
    $spec.Name = $TaskName
    $spec.Description = $TaskDescription
    $spec.Enabled = $true
    if ($AlertEmail) {$spec.Notification = $AlertEmail}
    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
    $spec.Scheduler.runat = $StartTime
    $spec.Action = New-Object VMware.Vim.MethodAction
    $spec.Action.Name = "RelocateVM_Task"

    # vMotion specs
    $arg1 = New-Object VMware.Vim.MethodActionArgument
    $arg1.Value = New-Object VMware.Vim.VirtualMachineRelocateSpec

    # ServiceLocator for destination - we should not need this
    #$arg1.Value.service = New-Object VMware.Vim.ServiceLocator
    #$arg1.Value.service.instanceUuid = ($global:defaultviservers | Where-Object {$DestinationHost.Uid -match  $_.Name}).InstanceUuid.toUpper()

    # Destination Datastore
    $arg1.Value.datastore = $DestinationDatastore.Id

   
# Destination Host
    $arg1.Value.host = $DestinationHost.Id

    # Destination ResourcePool
    if ($DestinationHost.ParentId -match "Cluster") {
        $arg1.Value.pool = ($DestinationHost | Get-Cluster).ExtensionData.ResourcePool
    }
    else {
        $arg1.Value.pool = $DestinationHost.ExtensionData.ResourcePool
    } #

   
# Destination Folder
    $arg1.Value.folder = ($DestinationFolder | Get-View).MoRef

    # vNIC PortGroups
    $arg1.Value.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec
    $VMNICs = $VM | Get-NetworkAdapter
    $VMNICs | ForEach-Object {$i = 0} {
        $arg1.Value.deviceChange[$i] = New-Object VMware.Vim.VirtualDeviceConfigSpec
        $arg1.Value.deviceChange[$i].Operation = "edit"
        $arg1.Value.deviceChange[$i].device = $_.ExtensionData
        $arg1.Value.deviceChange[$i].device.backing = New-Object VMware.Vim.VirtualEthernetCardDistributedVirtualPortBackingInfo
        $arg1.Value.deviceChange[$i].device.backing.port = New-Object VMware.Vim.DistributedVirtualSwitchPortConnection
        $arg1.Value.deviceChange[$i].device.backing.port.SwitchUuid = ($vNICPortGroups.($_.MacAddress) | Get-VDSwitch | Get-View).Uuid
        $arg1.Value.deviceChange[$i].device.backing.port.PortgroupKey = $vNICPortGroups.($_.MacAddress).Key
        $i++
    }

    $spec.Action.Argument += $arg1

    # Set vMotion priority
    $arg2 = New-Object VMware.Vim.MethodActionArgument
    $arg2.Value = [VMware.Vim.VirtualMachineMovePriority]"defaultPriority"
    $spec.Action.Argument += $arg2

    # Create scheduledTask
    return ($scheduledTaskManager.CreateScheduledTask($vmView.MoRef, $spec))
}

 

thx.

Reply
0 Kudos