VMware Cloud Community
Nadine-K
Contributor
Contributor
Jump to solution

Comparison scheduled tasks with annotation

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

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

Reply
0 Kudos
15 Replies
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

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}}
}
}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

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!

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

Oh, I didn´t mean to confuse...  
But yes, thats what I was trying to say. 

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

Unfortunately not yet completely. The script only shows PowerOn tasks and only configured days for the daily configured tasks.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Seems to work for me

LucD_0-1633422897433.png


Not sure how your scheduled tasks are defined.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

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:

NadineK_0-1633428489760.png

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

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 = 
}
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
Nadine-K
Contributor
Contributor
Jump to solution

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
    }
  }
}

 

 

Reply
0 Kudos