Good Morning, We´re shutting down our not relevant servers over night via VSphere Tasks and have set a comment as an annotation with server online times. Some servers are online at the weekend, others only during week. I need a script which reads per server its scheduledt asks with its settings like regularity (weekly on these days) and servers specific annotation. I´ve tried to play around with Brian Wuchners script but I´m struggling.
I need to combine the output of
1. (Get-View ScheduledTaskManager).ScheduledTask | %{ (Get-View $_ -Property Info).Info.scheduler }
2. Get-VIScheduledTasks | select EntityName,Action
3. get-vm |Get-Annotation -CustomAttribute "Online"
to an output like this:
ServerXY
Annotation: value of specific annotation
PowerON:
monday:true
...
sunday:false
PowerOFF:
monday:true
...
sunday:false
Does anybody have an idea?
Regars,
Nadine
Thanks, I think I know what causes this.
It looks as if your station where you run the script is configured with a German locale.
That means that
(Get-Culture).DateTimeFormat.DayNames
probably returns the German days of the week.
While the "day" properties in $sTask.Info.Scheduler use the English names.
Try replacing
((Get-Culture).DateTimeFormat.DayNames
with
([CultureInfo]::GetCultureInfo('en-US')).Datetimeformat.DayNames
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
And where can we find this script from Brian Wuchner?
I assume it contains the Get-VIScheduledTasks function, since that is not a PowerCLI cmdlet.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
This is the script which i´ve tried to modify to add the properties of the task
Function Get-VIScheduledTasks {
PARAM ( [switch]$Full )
if ($Full) {
# Note: When returning the full View of each Scheduled Task, all date times are in UTC
(Get-View ScheduledTaskManager).ScheduledTask | %{ (Get-View $_).Info }
} else {
# By default, lets only return common headers and convert all date/times to local values
(Get-View ScheduledTaskManager).ScheduledTask | %{ (Get-View $_ -Property Info).Info } |
Select-Object Name, Description, Enabled, Notification, LastModifiedUser, State, Entity,
@{N=”EntityName”;E={ (Get-View $_.Entity -Property Name).Name }},
@{N=”LastModifiedTime”;E={$_.LastModifiedTime.ToLocalTime()}},
@{N=”NextRunTime”;E={$_.NextRunTime.ToLocalTime()}},
@{N=”PrevRunTime”;E={$_.LastModifiedTime.ToLocalTime()}},
@{N=”ActionName”;E={$_.Action.Name}}
}
}
Would something like this do the trick?
Do you need more info in the result?
$schedMgr = Get-View ScheduledTaskManager
Get-VM -PipelineVariable vm |
ForEach-Object -Process {
$schedMgr.RetrieveEntityScheduledTask($vm.ExtensionData.MoRef) |
ForEach-Object -Process {
$sTask = Get-View -Id $_
if ('PowerOnVM_Task', 'PowerOffVM_Task' -contains $sTask.Info.Action.Name){
$obj = [ordered]@{
VM = $vm.Name
Annotation = $vm.Notes
TaskName = $sTask.Info.Name
Action = $sTask.Info.Action.Name.TrimEnd('VM_Task')
Frequency = $sTask.Info.Scheduler.GetType().Name
Interval = $sTask.Info.Scheduler.Interval
Hour = ''
Minute = ''
Days = ''
}
if ($sTask.Info.Scheduler -is [VMware.Vim.HourlyTaskScheduler]) {
$obj.Minute = $sTask.Info.Scheduler.Minute
}
if ($sTask.Info.Scheduler -is [VMware.Vim.DailyTaskScheduler]) {
$obj.Hour = $sTask.Info.Scheduler.Hour
}
if ($sTask.Info.Scheduler -is [VMware.Vim.WeeklyTaskScheduler]) {
$obj.Days = ((Get-Culture).DateTimeFormat.DayNames |
ForEach-Object -Process {
if($sTask.Info.Scheduler."$_"){
$_
}
}) -join '|'
}
New-Object -TypeName psobject -Property $obj
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That is really close to what I´m trying to do! That was a quick response, do you have something similar already running?
Annotation = $vm.Notes
in our case the annotation is a custom attribute, not a note. this note field is in use of our backupserver so it would be overwritten.
So this is a sample output:
VM : Servername
Annotation : Last backup: [30.09.2021 19:49:27];
TaskName : Servename PowerOn
Action : PowerOn
Frequency : WeeklyTaskScheduler
Interval : 1
Hour : 3
Minute : 50
Days :
I´ve tried to get those informations and set them to an array, but I´m not yet familiar with arrays and how to use them properly.
$data = @(
[pscustomobject]@{tasks=(Get-VIScheduledTasks |select EntityName,Action)}
[pscustomobject]@{annos=(Get-Cluster SESXIINS | Get-VM | Get-Annotation -CustomAttribute ".Verfügbarkeit")}
)
Which leads me to
PS C:\WINDOWS\system32> $tasks
EntityName Action
---------- ------
Server1 PowerOnVM_Task
Server1 ShutdownGuest
Server2 PowerOnVM_Task
Server2 ShutdownGuest
PS C:\WINDOWS\system32> $annos
AnnotatedEntity Name Value
--------------- ---- -----
Server1 Verfügbarkeit 24/7
Server2Verfügbarkeit Mo-Fr 6-22:00
Combined with yours and mine should look like
AnnotatedEntity : Server2
AnnotatedValue: Mo-Fr 6-22:00
TaskName : Servename PowerOn
Action : PowerOn
Frequency : WeeklyTaskScheduler
Interval : 1
Hour : 3
Minute : 50
Days :
TaskName : Servename PowerOff
Action : PowerOff
Frequency : WeeklyTaskScheduler
Interval : 1
Hour : 3
Minute : 50
Days :
Thank you very much in advance!
I'm confused, do you just want to replace the Notes with that Custom Attribute?
That can easily be done.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Oh, I didn´t mean to confuse...
But yes, thats what I was trying to say.
The other thing I need is to see the configured days on which these tasks are performed, if that is a weekly scheduled task. We only do have daily or weekly scheduled tasks.
Check if this works for you
$schedMgr = Get-View ScheduledTaskManager
Get-VM -PipelineVariable vm |
ForEach-Object -Process {
$schedMgr.RetrieveEntityScheduledTask($vm.ExtensionData.MoRef) |
ForEach-Object -Process {
$sTask = Get-View -Id $_
if ('PowerOnVM_Task', 'PowerOffVM_Task' -contains $sTask.Info.Action.Name){
$obj = [ordered]@{
VM = $vm.Name
Annotation = (Get-Annotation -Entity $vm -CustomAttribute ".Verfügbarkeit").Value
TaskName = $sTask.Info.Name
Action = $sTask.Info.Action.Name.TrimEnd('VM_Task')
Frequency = $sTask.Info.Scheduler.GetType().Name.TrimEnd('TaskScheduler')
Interval = $sTask.Info.Scheduler.Interval
Hour = ''
Minute = ''
Days = ''
}
if ($sTask.Info.Scheduler -is [VMware.Vim.HourlyTaskScheduler]) {
$obj.Minute = $sTask.Info.Scheduler.Minute
}
if ($sTask.Info.Scheduler -is [VMware.Vim.DailyTaskScheduler]) {
$obj.Hour = $sTask.Info.Scheduler.Hour
}
if ($sTask.Info.Scheduler -is [VMware.Vim.WeeklyTaskScheduler]) {
$obj.Days = ((Get-Culture).DateTimeFormat.DayNames |
ForEach-Object -Process {
if($sTask.Info.Scheduler."$_"){
$_
}
}) -join '|'
}
elseif($sTask.Info.Scheduler -is [VMware.Vim.DailyTaskScheduler]){
$obj.Days = (Get-Culture).DateTimeFormat.DayNames -join '|'
}
New-Object -TypeName psobject -Property $obj
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Unfortunately not yet completely. The script only shows PowerOn tasks and only configured days for the daily configured tasks.
Seems to work for me
Not sure how your scheduled tasks are defined.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Replaced
if ('PowerOnVM_Task', 'PowerOffVM_Task' -contains $sTask.Info.Action.Name){
with
if ('PowerOnVM_Task', 'ShutdownGuest' -contains $sTask.Info.Action.Name){
and its now showing the tasks for shutting down.
Are there any differences how you can configure tasks? Thats my output:
You have defined your Scheduled Tasks with Shutdown Guest and my tests were with Power Off (which I took from your original question).
That explains the difference in output.
I don't immediately see why you don't seem to get the days for the ShutdownGuest tasks.
The Scheduler property should be the same in both cases.
It would be interesting to see what is actually in the Scheduler property in your Shutdown Guest tasks.
If you could show what the following returns for such a Shutdown Guest task
$sTask.Info.Scheduler | Format-Custom
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
PS C:\WINDOWS\system32> $sTask.Info.Scheduler | Format-Custom
class WeeklyTaskScheduler
{
Sunday = False
Monday = True
Tuesday = True
Wednesday = True
Thursday = True
Friday = True
Saturday = False
Hour = 3
Minute = 45
Interval = 1
ActiveTime =
class DateTime
{
Date =
class DateTime
{
Date =
class DateTime
{
Date =
class DateTime
{
Date =
class DateTime
{
Date = 30.08.2021 00:00:00
Day = 30
DayOfWeek = Monday
DayOfYear = 242
Hour = 0
Kind = Utc
Millisecond = 0
Minute = 0
Month = 8
Second = 0
Ticks = 637658784000000000
TimeOfDay = 00:00:00
Year = 2021
DateTime = Montag, 30. August 2021 00:00:00
}
Day = 30
DayOfWeek = Monday
DayOfYear = 242
Hour = 0
Kind = Utc
Millisecond = 0
Minute = 0
Month = 8
Second = 0
Ticks = 637658784000000000
TimeOfDay =
class TimeSpan
{
Ticks = 0
Days = 0
Hours = 0
Milliseconds = 0
Minutes = 0
Seconds = 0
TotalDays = 0
TotalHours = 0
TotalMilliseconds = 0
TotalMinutes = 0
TotalSeconds = 0
}
Year = 2021
DateTime = Montag, 30. August 2021 00:00:00
}
Day = 30
DayOfWeek = Monday
DayOfYear = 242
Hour = 0
Kind = Utc
Millisecond = 0
Minute = 0
Month = 8
Second = 0
Ticks = 637658784000000000
TimeOfDay =
class TimeSpan
{
Ticks = 0
Days = 0
Hours = 0
Milliseconds = 0
Minutes = 0
Seconds = 0
TotalDays = 0
TotalHours = 0
TotalMilliseconds = 0
TotalMinutes = 0
TotalSeconds = 0
}
Year = 2021
DateTime = Montag, 30. August 2021 00:00:00
}
Day = 30
DayOfWeek = Monday
DayOfYear = 242
Hour = 0
Kind = Utc
Millisecond = 0
Minute = 0
Month = 8
Second = 0
Ticks = 637658784000000000
TimeOfDay =
class TimeSpan
{
Ticks = 0
Days = 0
Hours = 0
Milliseconds = 0
Minutes = 0
Seconds = 0
TotalDays = 0
TotalHours = 0
TotalMilliseconds = 0
TotalMinutes = 0
TotalSeconds = 0
}
Year = 2021
DateTime = Montag, 30. August 2021 00:00:00
}
Day = 30
DayOfWeek = Monday
DayOfYear = 242
Hour = 3
Kind = Utc
Millisecond = 0
Minute = 45
Month = 8
Second = 0
Ticks = 637658919000000000
TimeOfDay =
class TimeSpan
{
Ticks = 135000000000
Days = 0
Hours = 3
Milliseconds = 0
Minutes = 45
Seconds = 0
TotalDays = 0,15625
TotalHours = 3,75
TotalMilliseconds = 13500000
TotalMinutes = 225
TotalSeconds = 13500
}
Year = 2021
DateTime = Montag, 30. August 2021 03:45:00
}
ExpireTime =
}
Thanks, I think I know what causes this.
It looks as if your station where you run the script is configured with a German locale.
That means that
(Get-Culture).DateTimeFormat.DayNames
probably returns the German days of the week.
While the "day" properties in $sTask.Info.Scheduler use the English names.
Try replacing
((Get-Culture).DateTimeFormat.DayNames
with
([CultureInfo]::GetCultureInfo('en-US')).Datetimeformat.DayNames
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That works fantastic! Thank you very much, genius!
For everyone here´s the final script:
$schedMgr = Get-View ScheduledTaskManager
Get-VM -PipelineVariable vm |
ForEach-Object -Process {
$schedMgr.RetrieveEntityScheduledTask($vm.ExtensionData.MoRef) |
ForEach-Object -Process {
$sTask = Get-View -Id $_
if ('PowerOnVM_Task','ShutdownGuest' -contains $sTask.Info.Action.Name){
$obj = [ordered]@{
VM = $vm.Name
Annotation = (Get-Annotation -Entity $vm -CustomAttribute ".Online").Value
TaskName = $sTask.Info.Name
Action = $sTask.Info.Action.Name.TrimEnd('VM_Task')
Frequency = $sTask.Info.Scheduler.GetType().Name.TrimEnd('TaskScheduler')
Interval = $sTask.Info.Scheduler.Interval
Hour = ''
Minute = ''
Days = ''
}
if ($sTask.Info.Scheduler -is [VMware.Vim.HourlyTaskScheduler]) {
$obj.Minute = $sTask.Info.Scheduler.Minute
}
if ($sTask.Info.Scheduler -is [VMware.Vim.DailyTaskScheduler]) {
$obj.Hour = $sTask.Info.Scheduler.Hour
}
if ($sTask.Info.Scheduler -is [VMware.Vim.WeeklyTaskScheduler]) {
$obj.Days = (([CultureInfo]::GetCultureInfo('en-US')).DateTimeFormat.DayNames |
ForEach-Object -Process {
if($sTask.Info.Scheduler."$_"){
$_
}
}) -join '|'
}
elseif($sTask.Info.Scheduler -is [VMware.Vim.DailyTaskScheduler]){
$obj.Days = ([CultureInfo]::GetCultureInfo('en-US')).DateTimeFormat.DayNames -join '|'
}
New-Object -TypeName psobject -Property $obj
}
}
}