Remove vCenter Scheduled Tasks with PowerCLI (Part 3)

In my most recent series on vCenter Scheduled Tasks with PowerCLI, I have provided three functions…Get-VIScheduledTasks, Get-VMScheduledSnapshots, and New-VMScheduledSnapshot. To complete the series, I have a final function Remove-VIScheduledTask. I don’t really see the need for this one, as you can easily bulk select scheduled tasks in the vCenter UI and delete them with a single click. However, in the interest of completeness, here is a rough function that will delete a vSphere scheduled task. [A more robust/efficient/complete function could be written that would accept input from the pipeline. If there is a good use case for this please leave a comment below.]

NOTE: This function requires an additional function: Get-VIScheduledTasks to find the task by name. In addition the usage example below requires Get-VMScheduledSnapshots. Both functions are available here: New vCenter Scheduled Tasks with PowerCLI (Part 1).


Function Remove-VIScheduledTask {
PARAM ([string]$taskName)
  (Get-View -Id ((Get-VIScheduledTasks -Full | ?{$_.Name -eq $taskName}).ScheduledTask)).RemoveScheduledTask()
}

Usage example:

# This example will find all VM Scheduled Snapshots which 
# are not scheduled to run again, then remove each one by name.
Get-VMScheduledSnapshots | 
?{$_.NextRunTime -eq $null} | %{ Remove-VIScheduledTask $_.Name }
Posted in Scripting, Virtualization | 2 Comments

New vCenter Scheduled Tasks with PowerCLI (Part 2)

In a recent post New vCenter Scheduled Tasks with PowerCLI (Part 1), I provided two functions that return information related to vCenter Scheduled Tasks. This was my first step towards creating a PowerShell function that I could run to create scheduled snapshot tasks. This post will cover the create scheduled snapshot function.

NOTE: This function requires two additional functions, Get-VMScheduledSnapshots and Get-VIScheduledTasks, available here: New vCenter Scheduled Tasks with PowerCLI (Part 1).


Function New-VMScheduledSnapshot {
PARAM (
  [string]$vmName,
  [string]$runTime,
  [string]$notifyEmail=$null,
  [string]$taskName="$vmName Scheduled Snapshot"
)

# Verify we found a single VM
$vm = (get-view -viewtype virtualmachine -property Name -Filter @{"Name"="^$($vmName)$"}).MoRef
if (($vm | Measure-Object).Count -ne 1 ) { "Unable to locate a specific VM $vmName"; break }

# Validate datetime value and convert to UTC
try { $castRunTime = ([datetime]$runTime).ToUniversalTime() } catch { "Unable to convert runtime parameter to date time value"; break }
if ( [datetime]$runTime -lt (Get-Date) ) { "Single run tasks can not be scheduled to run in the past.  Please adjust start time and try again."; break }

# Verify the scheduled task name is not already in use
if ( (Get-VIScheduledTasks | ?{$_.Name -eq $taskName } | Measure-Object).Count -eq 1 ) { "Task Name `"$taskName`" already exists.  Please try again and specify the taskname parameter"; break }

$spec = New-Object VMware.Vim.ScheduledTaskSpec
$spec.name = $taskName
$spec.description = "Snapshot of $vmName scheduled for $runTime"
$spec.enabled = $true
if ( $notifyEmail ) {$spec.notification = $notifyEmail}
($spec.scheduler = New-Object VMware.Vim.OnceTaskScheduler).runAt = $castRunTime
($spec.action = New-Object VMware.Vim.MethodAction).Name = "CreateSnapshot_Task"
$spec.action.argument = New-Object VMware.Vim.MethodActionArgument[] (4)
($spec.action.argument[0] = New-Object VMware.Vim.MethodActionArgument).Value = "$vmName scheduled snapshot"
($spec.action.argument[1] = New-Object VMware.Vim.MethodActionArgument).Value = "Snapshot created using $taskName"
($spec.action.argument[2] = New-Object VMware.Vim.MethodActionArgument).Value = $false # Snapshot memory
($spec.action.argument[3] = New-Object VMware.Vim.MethodActionArgument).Value = $false # quiesce guest file system (requires VMware Tools)

[Void](Get-View -Id 'ScheduledTaskManager-ScheduledTaskManager').CreateScheduledTask($vm, $spec)
Get-VMScheduledSnapshots | ?{$_.Name -eq $taskName }
}
# Create a snapshot of the VM test002 at 9:40AM on 3/2/13
New-VMScheduledSnapshot test002 "3/2/13 9:40AM"

# Create a snapshot and send an email notification
New-VMScheduledSnapshot test002 "3/2/13 9:40AM" myemail@mydomain.com

# Use all of the options and name the parameters
New-VMScheduledSnapshot -vmname 'test001' -runtime '3/2/13 9:40am' -notifyemail 'myemail@mydomain.com' -taskname 'My scheduled task of test001'

I hope someone finds this function useful.

Posted in Scripting, Virtualization | 11 Comments

Get vCenter Scheduled Tasks with PowerCLI (Part 1)

I work with a lot of scheduled tasks. Typically, these tasks run powershell scripts from the Windows Task Scheduler. However, when working with simple VMware tasks (like creating snapshots right before a maintenance window) I like to use the Scheduled Tasks feature from right inside vCenter. The other day I thought it would be interesting if I had a PowerShell function that I could run to create these snapshot tasks. The first step in this process is to figure out what tasks we already have…and understand where some of these properties are located using PowerCLI.

The following two functions can be used to get information on Scheduled Tasks inside vCenter. The first function Get-VIScheduledTasks will simply return a list of all scheduled tasks that exist in a vCenter environment. I picked out a handful of properties that I figured would be needed and return those by default, casting the date/time values into local time. If you need all of the properties (the native .Net view of the Scheduled Task Info objects) you can include the parameter -Full and all of the properties will be returned.


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

This next function calls above function, but only returns the tasks whose action is “CreateSnapshot_Task”


Function Get-VMScheduledSnapshots {
  Get-VIScheduledTasks | ?{$_.ActionName -eq 'CreateSnapshot_Task'} |
    Select-Object @{N="VMName";E={$_.EntityName}}, Name, NextRunTime, Notification
}

Sample usage would be:

# To find all tasks that failed to execute last run
Get-VIScheduledTasks | ?{$_.State -ne 'success'}

# To find all snapshots that are not scheduled to run again:
Get-VMScheduledSnapshots | ?{$_.NextRunTime -eq $null}

I hope you find these functions useful. Be sure to check out the next post – on creating scheduled snapshots with PowerCLI!

Posted in Scripting, Virtualization | 10 Comments

Compare two CSV files to trend mailbox growth

I had an interesting request the other day. A co-worker had two CSV files containing mailbox information from the same Exchange server, but from different parts of the day. He wanted to know if there was any way to find which users had the most growth in their mailbox size.

Here is an example of how to get mailbox size for all users on the same Exchange server:

Get-MailboxStatistics -Server EXCHANGE01 | 
Select-Object -Property DisplayName, 
@{N="SizeMB";E={$_.TotalItemSize.Value.ToMB()}}, Identity | 
Export-Csv file2.csv -NoTypeInformation

The first thought that came to mind had involved Group-Object and Measure-Object. I threw something together that got the job done, but decided to clean it up a bit and thought I’d share it here.


Import-Csv file1.csv, file2.csv | Group-Object -Property Identity | %{
      $thisDetail = $_ | Select-Object -ExpandProperty Group| Measure-Object SizeMB -Maximum -Minimum
      New-Object psobject -Property @{
            DisplayName = [string]($_.Group[0].DisplayName)
            GrowthMB = [float]($thisDetail.Maximum - $thisDetail.Minimum)
      } | Select DisplayName, GrowthMB
} | Sort-Object GrowthMB -Descending | Select-Object -First 10

Hope someone else finds this helpful!

Posted in Messaging, Scripting | Leave a comment

PowerCLI checks for vSphere Datastores

Over the last couple of days, I have posted a handful of PowerCLI scripts to check a vSphere environment. These checks have looked at general cluster level reporting, networking and virtual machines. Today I’m posting a couple of checks that look at datastores. I hope you find these checks useful.

In my environment, local disks contain the text boot or local. The following code will return a list of non-shared datastores that do not follow this naming convention. This could indicate local disk that doesn’t follow a standard naming convention.


Get-View -ViewType Datastore -Property Name, Summary |
?{$_.Summary.MultipleHostAccess -eq $false -And $_.Name -notmatch "boot|local"} |
Select Name, @{N="Datastore Type";E={$_.Summary.Type}}, 
@{N="Capacity (GB)";E={[math]::round( $_.Summary.Capacity/1GB , 0)}} |
Sort-Object Name

The following script will return a list of datastores reporting as not accessible. I’ve seen this happen after removing datastores from hosts where array based snapshots had been previously presented. Typically an HBA re-scan will clear up this issue.


Get-View -ViewType Datastore -Property Name, Summary |
?{$_.Summary.Accessible -eq $false} | 
Select-Object name, @{N="Datastore Type";E={$_.Summary.Type}},
@{N="Capacity (GB)";E={[math]::round( $_.Summary.Capacity/1GB , 0)}} | 
Sort-Object Name

I try to keep the VMFS block size and version consistent on all shared storage in my environment. The following code will show VMFS datastores if inconsistent block sizes or VMFS versions are not using the most common configuration detected in the environment.


$vmfsDs = Get-View -ViewType Datastore -Property Name, Summary, Info, Host | 
?{$_.Summary.Type -eq 'VMFS' -and $_.Summary.MultipleHostAccess -eq $true} | 
Select-Object Name, @{N="VMFS Version";E={$_.Info.Vmfs.Version}}, 
@{N="Block Size (MB)";E={$_.Info.Vmfs.BlockSizeMB}},
@{N="Host Count";E={@($_.Host).Count}}

if ( ($vmfsDs | Select-Object -Property "Block Size (MB)" -Unique | Measure-Object).Count -gt 1 -or
  ($vmfsDs | Select-Object -Property "VMFS Version" -Unique | Measure-Object).Count -gt 1) { 
  $standardVmfsBlockSize = (($vmfsDs | Group-Object -Property "Block Size (MB)") | Sort-Object Count -Descending | Select-Object -First 1).Name
  $standardVmfsVersion = (($vmfsDs | Group-Object -Property "VMFS Version") | Sort-Object Count -Descending | Select-Object -First 1).Name
  $vmfsDs | ?{$_."Block Size (MB)" -ne $standardVmfsBlockSize -or $_."VMFS Version" -ne $standardVmfsVersion } |
  Sort-Object Name 
}

I hope someone else finds these checks useful.

Posted in Scripting, Virtualization | Leave a comment