【问题标题】:How do I get the tasks associated with vCenter objects using PowerCLI?如何使用 PowerCLI 获取与 vCenter 对象关联的任务?
【发布时间】:2021-10-24 23:42:08
【问题描述】:

我们在我们的环境中使用 vSphere 6.7。

我正在编写一个脚本来查找与我们的 vCenter 环境中的特定目标资源相关联的某些任务。但是,Get-Task 仅返回显示在 HTML5 客户端的 Recent Tasks 视图中的最近任务。我可以很好地获取与资源关联的事件,例如,我可以获取与给定数据存储文件夹关联的事件,如下所示:

Get-Folder FOLDER_NAME -Type Datastore | Get-VIEvent

但似乎没有等效的方法来获取与这些相同资源相关联的任务。 Get-Task 不像 Get-VIEvent 那样接受管道输入,并导致错误:

Get-Folder FOLDER_NAME -Type Datastore | Get-Task

输出:

Get-Task: The input object cannot be bound to any parameters for the command either
because the command does not take pipeline input or the input and its properties
do not match any of the parameters that take pipeline input.

Get-Task 也不显示任何未在 HTML5 客户端的 Recent Tasks 视图中显示的任务。

检查对象似乎没有提供任何成员让我看到针对这些资源的任务:

Get-Folder FOLDER_NAME -Type Datastore | Get-Member

输出:

   TypeName: VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreClusterImpl

Name                             MemberType Definition
----                             ---------- ----------
ConvertToVersion                 Method     T VersionedObjectInterop.ConvertToVersion[T]()
Equals                           Method     bool Equals(System.Object obj)
GetClient                        Method     VMware.VimAutomation.ViCore.Interop.V1.VIAutomation VIObjectCoreInterop.GetClient()
GetHashCode                      Method     int GetHashCode()
GetType                          Method     type GetType()
IsConvertableTo                  Method     bool VersionedObjectInterop.IsConvertableTo(type type)
LockUpdates                      Method     void ExtensionData.LockUpdates()
ToString                         Method     string ToString()
UnlockUpdates                    Method     void ExtensionData.UnlockUpdates()
CapacityGB                       Property   decimal CapacityGB {get;}
ExtensionData                    Property   System.Object ExtensionData {get;}
FreeSpaceGB                      Property   decimal FreeSpaceGB {get;}
Id                               Property   string Id {get;}
IOLatencyThresholdMillisecond    Property   System.Nullable[int] IOLatencyThresholdMillisecond {get;}
IOLoadBalanceEnabled             Property   bool IOLoadBalanceEnabled {get;}
Name                             Property   string Name {get;}
SdrsAutomationLevel              Property   VMware.VimAutomation.ViCore.Types.V1.Cluster.DrsAutomationLevel SdrsAutomationLevel {get;}
SpaceUtilizationThresholdPercent Property   System.Nullable[int] SpaceUtilizationThresholdPercent {get;}
Uid                              Property   string Uid {get;}

这不仅适用于文件夹任务,但如果它们不在 HTML5 的 Recent Tasks 视图中,我似乎根本无法枚举给定资源的 任何 任务客户。相反,在 HTML5 客户端中,我可以使用其Monitor 选项卡轻松枚举给定资源上的任务,但这无助于自动化,除非以编程方式爬过 UI(不会发生):

如何使用 PowerCLI 来查看使用 PowerCLI 以特定资源为目标的任务?

【问题讨论】:

    标签: powershell powercli vcenter


    【解决方案1】:

    Luc Dekens 编写了一个脚本函数来解决您的问题。这是函数的副本,您可以使用实体参数定位特定资源。

    function Get-TaskPlus {
        <#  
        .SYNOPSIS  Returns vSphere Task information   
        .DESCRIPTION The function will return vSphere task info. The
        available parameters allow server-side filtering of the
        results
        .NOTES  Author:  Luc Dekens  
        .PARAMETER Alarm
        When specified the function returns tasks triggered by
        specified alarm
        .PARAMETER Entity
        When specified the function returns tasks for the
        specific vSphere entity
        .PARAMETER Recurse
        Is used with the Entity. The function returns tasks
        for the Entity and all it's children
        .PARAMETER State
        Specify the State of the tasks to be returned. Valid
        values are: error, queued, running and success
        .PARAMETER Start
        The start date of the tasks to retrieve
        .PARAMETER Finish
        The end date of the tasks to retrieve.
        .PARAMETER UserName
        Only return tasks that were started by a specific user
        .PARAMETER MaxSamples
        Specify the maximum number of tasks to return
        .PARAMETER Reverse
        When true, the tasks are returned newest to oldest. The
        default is oldest to newest
        .PARAMETER Server
        The vCenter instance(s) for which the tasks should
        be returned
        .PARAMETER Realtime
        A switch, when true the most recent tasks are also returned.
        .PARAMETER Details
        A switch, when true more task details are returned
        .PARAMETER Keys
        A switch, when true all the keys are returned
        .EXAMPLE
        PS> Get-TaskPlus -Start (Get-Date).AddDays(-1)
        .EXAMPLE
        PS> Get-TaskPlus -Alarm $alarm -Details
        #>
        param(
            [CmdletBinding()]
            [VMware.VimAutomation.ViCore.Impl.V1.Alarm.AlarmDefinitionImpl]$Alarm,
            [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Entity,
            [switch]$Recurse = $false,
            [VMware.Vim.TaskInfoState[]]$State,
            [DateTime]$Start,
            [DateTime]$Finish,
            [string]$UserName,
            [int]$MaxSamples = 100,
            [switch]$Reverse = $true,
            [VMware.VimAutomation.ViCore.Impl.V1.VIServerImpl[]]$Server = $global:DefaultVIServer,
            [switch]$Realtime,
            [switch]$Details,
            [switch]$Keys,
            [int]$WindowSize = 100
        )
        begin {
            function Get-TaskDetails {
                param(
                    [VMware.Vim.TaskInfo[]]$Tasks
                )
                begin {
                    $psV3 = $PSversionTable.PSVersion.Major -ge 3
                }
                process {
                    $tasks | ForEach-Object {
                        if ($psV3) {
                            $object = [ordered]@{ }
                        }
                        else {
                            $object = @{ }
                        }
                        $object.Add("Name", $_.Name)
                        $object.Add("Description", $_.Description.Message)
                        if ($Details) { $object.Add("DescriptionId", $_.DescriptionId) }
                        if ($Details) { $object.Add("Task Created", $_.QueueTime) }
                        $object.Add("Task Started", $_.StartTime)
                        if ($Details) { $object.Add("Task Ended", $_.CompleteTime) }
                        $object.Add("State", $_.State)
                        $object.Add("Result", $_.Result)
                        $object.Add("Entity", $_.EntityName)
                        $object.Add("VIServer", $VIObject.Name)
                        $object.Add("Error", $_.Error.ocalizedMessage)
                        if ($Details) {
                            $object.Add("Cancelled", (& { if ($_.Cancelled) { "Y" }else { "N" } }))
                            $object.Add("Reason", $_.Reason.GetType().Name.Replace("TaskReason", ""))
                            $object.Add("AlarmName", $_.Reason.AlarmName)
                            $object.Add("AlarmEntity", $_.Reason.EntityName)
                            $object.Add("ScheduleName", $_.Reason.Name)
                            $object.Add("User", $_.Reason.UserName)
                        }
                        if ($keys) {
                            $object.Add("Key", $_.Key)
                            $object.Add("ParentKey", $_.ParentTaskKey)
                            $object.Add("RootKey", $_.RootTaskKey)
                        }
                        New-Object PSObject -Property $object
                    }
                }
            }
            $filter = New-Object VMware.Vim.TaskFilterSpec
            if ($Alarm) {
                $filter.Alarm = $Alarm.ExtensionData.MoRef
            }
            if ($Entity) {
                $filter.Entity = New-Object VMware.Vim.TaskFilterSpecByEntity
                $filter.Entity.entity = $Entity.ExtensionData.MoRef
                if ($Recurse) {
                    $filter.Entity.Recursion = [VMware.Vim.TaskFilterSpecRecursionOption]::all
                }
                else {
                    $filter.Entity.Recursion = [VMware.Vim.TaskFilterSpecRecursionOption]::self
                }
            }
            if ($State) {
                $filter.State = $State
            }
            if ($Start -or $Finish) {
                $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
                $filter.Time.beginTime = $Start
                $filter.Time.endTime = $Finish
                $filter.Time.timeType = [vmware.vim.taskfilterspectimeoption]::startedTime
            }
            if ($UserName) {
                $userNameFilterSpec = New-Object VMware.Vim.TaskFilterSpecByUserName
                $userNameFilterSpec.UserList = $UserName
                $filter.UserName = $userNameFilterSpec
            }
            $nrTasks = 0
        }
        process {
            foreach ($viObject in $Server) {
                $si = Get-View ServiceInstance -Server $viObject
                $tskMgr = Get-View $si.Content.TaskManager -Server $viObject 
                if ($Realtime -and $tskMgr.recentTask) {
                    $tasks = Get-View $tskMgr.recentTask
                    $selectNr = [Math]::Min($tasks.Count, $MaxSamples - $nrTasks)
                    Get-TaskDetails -Tasks[0..($selectNr - 1)]
                    $nrTasks += $selectNr
                }
                $tCollector = Get-View ($tskMgr.CreateCollectorForTasks($filter))
                if ($Reverse) {
                    $tCollector.ResetCollector()
                    $taskReadOp = $tCollector.ReadPreviousTasks
                }
                else {
                    $taskReadOp = $tCollector.ReadNextTasks
                }
                do {
                    $tasks = $taskReadOp.Invoke($WindowSize)
                    if (!$tasks) { break }
                    $selectNr = [Math]::Min($tasks.Count, $MaxSamples - $nrTasks)
                    Get-TaskDetails -Tasks $tasks[0..($selectNr - 1)]
                    $nrTasks += $selectNr
                }while ($nrTasks -lt $MaxSamples)
                $tCollector.DestroyCollector()
            }
        }
    }
    

    更多信息https://www.lucd.info/2013/06/01/task-data-mining-an-improved-get-task/#more-4464

    【讨论】:

    • 你很喜欢分享这个,Luc Dekens 也是。谢谢!
    • 我给这个问题写了一个follow up 问题,因为这个函数不适用于从非库存对象中获取任务(删除$Entity 的类型约束不会引发错误,但也会返回 no结果)。我发现 LucD 写了一个类似的Get-VIEventsPlus 函数,并且使用small modification 它也会返回非库存对象的事件,其中包括任务以及@Cpt.Whale 所述。
    【解决方案2】:

    Get-VIEvent 返回各种东西——幸运的是,包括任务!您可以通过它们的类型 [VMware.Vim.TaskEvent] 或通过检查它们的 info 属性来查看它们,该属性只有任务事件具有。例如:

    $VIEvents = Get-VM $VMName | Get-VIEvent
    $VITasks  = $VIEvents | Where Info
    $VITasks | Select CreatedTime, FullFormattedMessage
    
    CreatedTime           FullFormattedMessage                 
    -----------           --------------------                 
    8/19/2021 4:39:22 PM  Task: Remove all snapshots           
    8/19/2021 4:38:04 PM  Task: Reconfigure virtual machine    
    8/19/2021 3:52:06 PM  Task: Migrate virtual machine        
    

    任务事件的Info属性中通常存储了更详细的信息,但我们必须通过专门选择该属性来扩展它:

    $VITasks.Info | select QueueTime,Name,EntityName,State
    

    不过,关于实际发生的事情的高度详细信息通常存储在其他事件类型中。例如,要查看“重新配置虚拟机”任务中发生了什么变化,我需要检查具有 ConfigChanges 属性的事件。

    这些也恰好有一个非常详细的结构,其中包含您可以解析的ConfigChangesConfigSpec 属性。我只是在这里使用预先格式化的消息,但您可以使用计算属性以 Select 显示它们,就像我获取 VM 名称一样:

    Get-VM My-Test-VM1 | Get-VIEvent | Where ConfigChanges | 
      Select -First 1 CreatedTime,@{label='VmName';expr={$_.VM.Name}},FullFormattedMessage |
      Format-List
    
    CreatedTime          : 8/19/2021 4:38:04 PM
    VmName               : My-Test-VM1
    FullFormattedMessage : Reconfigured My-Test-VM1 on My-Test-Host1 in My-Test-Datacenter1.  
                            Modified:  
                           config.hardware.device(3002).deviceInfo.summary: "ISO (ISO-DATASTORE1) RHEL7.iso" -> "Remote ATAPI"; 
                            Added:  
                            Deleted:  
    

    这些步骤适用于任何事件/任务类型,但您必须进行一些初步挖掘以找到所需数据的存储位置,以及如何以有用的方式显示它。


    无论出于何种原因,Get-Task 专门设计用于获取:

    [...]有关当前或最近任务的信息[...]

    Get-Task reference

    【讨论】:

      【解决方案3】:

      @jrmilner's answer 在这里为我工作,但它不允许我从非库存对象中获取任务,即使我将-Entity 的类型更改为[object[]]。但是,我确实发布了一个关于从非库存对象中检索事件的后续问题,但这次我能够通过修改 LucD 编写的另一个函数来find a solution,这是我在继续研究时发现的。 那么这与这个问题有什么关系?

      感谢Cpt.Whale,我了解到任务事件,虽然我获得了事件并以不同的方式将“小麦与任务”分开,但他们的回答在下面帮助了我。

      通过在我的linked answer 中对另一个问题使用修改后的Get-VIEventPlus,我可以通过检查是否在返回的事件上设置了Severity 来区分任务和事件,因为它们将在HTML5 客户端中分开,就像这样:

      $dsCluster = Get-DatastoreCluster
      
      $tasks = Get-VIEventPlus -Entity $dsCluster | Where-Object { ! $_.Severity }
      $events = Get-VIEventPlus -Entity $dsCluster | Where-Object { $_.Severity }
      

      似乎事件将设置严重性,而任务则没有。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-09
        • 2015-05-16
        • 1970-01-01
        • 2023-03-22
        相关资源
        最近更新 更多