如何使用 PowerCLI 获取与 vCenter 对象关联的任务?
How do I get the tasks associated with vCenter objects using PowerCLI?
我们在我们的环境中使用 vSphere 6.7。
我正在编写一个脚本来查找与我们的 vCenter 环境中的特定目标资源关联的某些任务。但是,Get-Task
只有 returns 个最近的任务显示在 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 客户端的 16=] 视图。相反,在 HTML5 客户端中,我可以使用它的 Monitor
选项卡轻松地枚举给定资源上的任务,但这对自动化没有帮助,除非以编程方式在 UI 中爬行(不是正在发生):
如何使用 PowerCLI 查看针对使用 PowerCLI 的特定资源的任务?
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
Get-VIEvent
returns 各种各样的东西 - 幸运的是,包括任务!您可以通过类型 [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
不过,关于实际发生的事情的高度详细信息通常存储在其他事件类型中。例如,要查看 'Reconfigure virtual machine' 任务中发生了什么变化,我需要检查具有 ConfigChanges
属性.
的事件
这些也恰好具有非常详细的结构,其中包含您可以解析的 ConfigChanges
和 ConfigSpec
属性。我只是在此处使用预先格式化的消息,但您可以使用计算属性以 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:
这些步骤适用于任何 event/task 类型,但您必须进行一些初步挖掘以找到存储所需数据的位置,以及如何以有用的方式显示数据。
无论出于何种原因,Get-Task
专门设计用于仅获取:
[...]information about the current or recent tasks[...]
worked for me here, but it does not let me get tasks from non-inventory objects, even if I change the type of -Entity
to an [object[]]
. However, I did post a follow up question about retrieving events from non-inventory objects, but this time I was able to 通过修改 LucD 编写的另一个函数,我在继续研究时发现了这个函数。 那么这和这个问题有什么关系呢?
感谢 ,我了解到任务 是 事件,当我获取事件并以不同的方式将“小麦与任务”分开时,他们的回答在下面帮助了我。
通过在我的 中使用修改后的 Get-VIEventPlus
到另一个问题,我可以区分任务和事件,因为它们在 HTML5 客户端中通过检查是否 Severity
在返回的事件上设置如下:
$dsCluster = Get-DatastoreCluster
$tasks = Get-VIEventPlus -Entity $dsCluster | Where-Object { ! $_.Severity }
$events = Get-VIEventPlus -Entity $dsCluster | Where-Object { $_.Severity }
似乎事件将设置严重性,而任务则不会。
我们在我们的环境中使用 vSphere 6.7。
我正在编写一个脚本来查找与我们的 vCenter 环境中的特定目标资源关联的某些任务。但是,Get-Task
只有 returns 个最近的任务显示在 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 客户端的 16=] 视图。相反,在 HTML5 客户端中,我可以使用它的 Monitor
选项卡轻松地枚举给定资源上的任务,但这对自动化没有帮助,除非以编程方式在 UI 中爬行(不是正在发生):
如何使用 PowerCLI 查看针对使用 PowerCLI 的特定资源的任务?
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
Get-VIEvent
returns 各种各样的东西 - 幸运的是,包括任务!您可以通过类型 [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
不过,关于实际发生的事情的高度详细信息通常存储在其他事件类型中。例如,要查看 'Reconfigure virtual machine' 任务中发生了什么变化,我需要检查具有 ConfigChanges
属性.
这些也恰好具有非常详细的结构,其中包含您可以解析的 ConfigChanges
和 ConfigSpec
属性。我只是在此处使用预先格式化的消息,但您可以使用计算属性以 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:
这些步骤适用于任何 event/task 类型,但您必须进行一些初步挖掘以找到存储所需数据的位置,以及如何以有用的方式显示数据。
无论出于何种原因,Get-Task
专门设计用于仅获取:
[...]information about the current or recent tasks[...]
-Entity
to an [object[]]
. However, I did post a follow up question about retrieving events from non-inventory objects, but this time I was able to
感谢
通过在我的 Get-VIEventPlus
到另一个问题,我可以区分任务和事件,因为它们在 HTML5 客户端中通过检查是否 Severity
在返回的事件上设置如下:
$dsCluster = Get-DatastoreCluster
$tasks = Get-VIEventPlus -Entity $dsCluster | Where-Object { ! $_.Severity }
$events = Get-VIEventPlus -Entity $dsCluster | Where-Object { $_.Severity }
似乎事件将设置严重性,而任务则不会。