VMware Cloud Community
Halukkocaman
Enthusiast
Enthusiast

Schedule Snapshot with PowerCli

Hi All,

I there any way to use PowerCli to schedule a snapshot? I'm looking to built a script to take user inputs such as Vm name, snapshot name, snapshot date, etc. to schedule a snapshot. I'm hoping to create a simple webpage to take some user inputs and pass it to script. I saw some examples that use PowerShell to create schedule task but they are all about creating a windows scheduled task. I would like to create the task as you would create in vSphere.

Thanks,

Haluk

Tags (2)
39 Replies
LucD
Leadership
Leadership

I did a post on that, see Scheduled Tasks – MethodAction for some background info.

Try like this

###############

# These are the values you should get from your webform

#

$vmName = 'MyVM'

$snapTime = Get-Date "31/10/16 23:00"

$snapName = 'Test'

$snapDescription = 'Scheduled snapshot'

$snapMemory = $false

$snapQuiesce = $true

$emailAddr = 'lucd@lucd.info'

###############

$vm = Get-VM -Name $vmName

$si = get-view ServiceInstance

$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

$spec = New-Object VMware.Vim.ScheduledTaskSpec

$spec.Name = "Snapshot",$_.VMname -join ' '

$spec.Description = "Take a snapshot of $($vm.Name)"

$spec.Enabled = $true

$spec.Notification = $emailAddr

$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler

$spec.Scheduler.runat = $snapTime

$spec.Action = New-Object VMware.Vim.MethodAction

$spec.Action.Name = "CreateSnapshot_Task"

@($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

    $arg = New-Object VMware.Vim.MethodActionArgument

    $arg.Value = $_

    $spec.Action.Argument += $arg

}

$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)


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

RajJon
Contributor
Contributor

Hate to bring up an old thread but is there a way to modify this script so that it uses the import-csv function. I would like to have the values be VMName, and Description. I am having a hard time with this one.

Reply
0 Kudos
LucD
Leadership
Leadership

You mean something like this?

It assumes a CSV with this layout

VMName,Description

VM1,Test1

VM2,Test2

###############

# These are the values you should get from your webform

#

$snapTime = Get-Date "31/10/16 23:00"

$snapName = 'Test'

$snapDescription = 'Scheduled snapshot'

$snapMemory = $false

$snapQuiesce = $true

$emailAddr = 'lucd@lucd.info'

$fileName = 'C:\Temp\snap.csv'

###############

Import-Csv -Path $fileName -UseCulture | %{

    

    $vm = Get-VM -Name $_.VMName

    

    $si = get-view ServiceInstance

    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

    

    $spec = New-Object VMware.Vim.ScheduledTaskSpec

    $spec.Name = "Snapshot",$vm.Name -join ' '

    $spec.Description = $_.Description

    $spec.Enabled = $true

    $spec.Notification = $emailAddr

    

    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler

    $spec.Scheduler.runat = $snapTime

    

    $spec.Action = New-Object VMware.Vim.MethodAction

    $spec.Action.Name = "CreateSnapshot_Task"

    

    @($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

        $arg = New-Object VMware.Vim.MethodActionArgument

        $arg.Value = $_

        $spec.Action.Argument += $arg

    }

    

    $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)

}


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

Reply
0 Kudos
RajJon
Contributor
Contributor

Wow! You sir, are a legend!

Reply
0 Kudos
OBXMAN007
Contributor
Contributor

LucD, once again, a work of art.   Took your code, added saved creds - runs great - hello from years ago.  Yes, LucD is a legend.
Reply
0 Kudos
DSHAH3
Contributor
Contributor

Hi LucD,

How can I add snaptime column in csv file? I want to make csv file look like: VMname | Snapshot name | description | date | email

*email column is working but not the rest. Please check, thanks! 

Connect-VIServer tormsvdr –User cotadm61 –Password Toronto10
$snapTime = Get-Date "04/17/18 08:00"
$snapName = 'Test'
$snapDescription = 'Scheduled snapshot'
$snapMemory = $true
$snapQuiesce = $false
$fileName = 'C:\TEST\April\snapshotfile.csv'
 
Import-Csv -Path $fileName -UseCulture | %{
    $vm = Get-VM -Name $_.VMName  
    $si = get-view ServiceInstance
    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager
    $spec = New-Object VMware.Vim.ScheduledTaskSpec
    $spec.Name = "Snapshot",$vm.Name -join ' '
    $spec.Description = $_.Description
    $spec.Enabled = $true
    $spec.Notification = $_.email
    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
    $spec.Scheduler.runat = $snapTime
    $spec.Action = New-Object VMware.Vim.MethodAction
    $spec.Action.Name = "CreateSnapshot_Task"
    @($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{
 
        $arg = New-Object VMware.Vim.MethodActionArgument
 
        $arg.Value = $_
 
        $spec.Action.Argument += $arg
 
    }
    $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)
}
disconnect-viserver -confirm:$false

$snapTime = Get-Date "04/17/18 08:00"

$snapName = 'Test'

$snapDescription = 'Scheduled snapshot' 

$snapMemory = $true

$snapQuiesce = $false

$fileName = 'C:\snapshotfile.csv'

 

Import-Csv -Path $fileName -UseCulture | %{

    $vm = Get-VM -Name $_.VMName  

    $si = get-view ServiceInstance

    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

    $spec = New-Object VMware.Vim.ScheduledTaskSpec

    $spec.Name = "Snapshot",$vm.Name -join ' '

    $spec.Description = $_.Description

    $spec.Enabled = $true

    $spec.Notification = $_.email

    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler

    $spec.Scheduler.runat = $snapTime

    $spec.Action = New-Object VMware.Vim.MethodAction

    $spec.Action.Name = "CreateSnapshot_Task"

    @($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

        $arg = New-Object VMware.Vim.MethodActionArgument

        $arg.Value = $_

        $spec.Action.Argument += $arg

    }

    $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)

}

Reply
0 Kudos
LucD
Leadership
Leadership

All properties in the objects imported from a CSV are strings.

You can convert to a DateTime object with the Get-Date cmdlet.

For example:

$date = '20/04/2018 09:00'

Get-Date $date

You'll have to experiment how Get-Date interprets the string, there are differences.


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

Reply
0 Kudos
Fontaaaaaa
Contributor
Contributor

This code indeed works, thanks!

There's only a problem when you connect to multiple VIservers (in my case 8).

More often than not it will return me this error:

Exception calling "CreateObjectScheduledTask" with "2" argument(s): "The object has already been deleted or has not been completely created"

At D:\Scripts\ScheduleSnapshot.psm1:160 char:5

+     $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData ...

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : VimException

How can I adjust the code so it automatically finds the right viserver?

Btw. VMware should create some cmdlets for scheduled tasks don't you think?

Reply
0 Kudos
LucD
Leadership
Leadership

You will have to use the Server parameter on the cmdlets.

And you will have to pass the name of the vCenter.

###############

# These are the values you should get from your webform

#

$snapTime = Get-Date "31/10/16 23:00"

$snapName = 'Test'

$snapDescription = 'Scheduled snapshot'

$snapMemory = $false

$snapQuiesce = $true

$emailAddr = 'lucd@lucd.info'

$fileName = 'C:\Temp\snap.csv'

$vcName = 'MyVC'

###############

Import-Csv -Path $fileName -UseCulture | %{

   

    $vm = Get-VM -Name $_.VMName -Server $vcName

   

    $si = Get-View ServiceInstance -Server $vcName

    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $vcName

   

    $spec = New-Object VMware.Vim.ScheduledTaskSpec

    $spec.Name = "Snapshot",$vm.Name -join ' '

    $spec.Description = $_.Description

    $spec.Enabled = $true

    $spec.Notification = $emailAddr

   

    $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler

    $spec.Scheduler.runat = $snapTime

   

    $spec.Action = New-Object VMware.Vim.MethodAction

    $spec.Action.Name = "CreateSnapshot_Task"

   

    @($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

        $arg = New-Object VMware.Vim.MethodActionArgument

        $arg.Value = $_

        $spec.Action.Argument += $arg

    }

   

    $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)

}


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

Fontaaaaaa
Contributor
Contributor

Awesome. that works!

to prevent having to use the -Server argument on the Get-VM cmdlet, I changed the code to:

https://pastebin.com/aSPm5jCw

Reply
0 Kudos
LucD
Leadership
Leadership

Before you do the Connect-VIServer, you might want to check the DefaultVIServerMode setting with the Get-PowerCLIConfiguration cmdlet.

To make sure it is set to 'multiple'


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

Reply
0 Kudos
Fontaaaaaa
Contributor
Contributor

I am making sure of that Smiley Happy

$CurrentPowerCLIConfig = Get-PowerCLIConfiguration -Scope Session

    if ($CurrentPowerCLIConfig.DefaultVIServerMode -ne "Multiple") {

        Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false | Out-Null

    }

sebskc
Contributor
Contributor

Hi LucD,

Slightly stuck with one thing, below works perfectly but I wish to change from single task execution to reocurring event, once a month.

Doing so, changing "$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler" to "$spec.Scheduler = New-Object VMware.Vim.MonthlyByWeekdayTaskScheduler" although, I'm unable to ajdust parameters like offset, day and time.

Any hints please? For example, willing to task occur second Tuesday, every 1 month at 6:00am.

Reply
0 Kudos
LucD
Leadership
Leadership

Try like this

$spec = New-Object VMware.Vim.ScheduledTaskSpec

$spec.Scheduler = New-Object VMware.Vim.MonthlyByWeekdayTaskScheduler

$spec.Scheduler.Offset = [VMware.Vim.WeekOfMonth]::second

$spec.Scheduler.Weekday = [VMware.Vim.DayOfWeek]::tuesday

$spec.Scheduler.Hour = 6


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

Reply
0 Kudos
sebskc
Contributor
Contributor

Thanks LucD unfortunately, receiving  below. Definitely doing something wrong, although I'm lost.

pastedImage_0.png

Here is full script:

###############

# These are the values you should get from your webform

#

$vmName = 'servername'

$snapTime = Get-Date "10/11/18 23:00"

$snapName = 'Test'

$snapDescription = 'Scheduled snapshot'

$snapMemory = $false

$snapQuiesce = $true

$emailAddr = 'xxx@xxx.com'

###############

$vm = Get-VM -Name $vmName

$si = get-view ServiceInstance

$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

$spec = New-Object VMware.Vim.ScheduledTaskSpec

$spec.Scheduler = New-Object VMware.Vim.MonthlyByWeekdayTaskScheduler

$spec.Scheduler.Offset = [VMware.Vim.WeekOfMonth]::second

$spec.Scheduler.Weekday = [VMware.Vim.DayOfWeek]::tuesday

$spec.Scheduler.Hour = 6

$spec.Name = "Snapshot",$_.VMname -join ' '

$spec.Description = "Take a snapshot of $($vm.Name)"

$spec.Enabled = $true

$spec.Notification = $emailAddr

$spec.Action = New-Object VMware.Vim.MethodAction

$spec.Action.Name = "CreateSnapshot_Task"

@($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

    $arg = New-Object VMware.Vim.MethodActionArgument

    $arg.Value = $_

    $spec.Action.Argument += $arg

}

$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)

Reply
0 Kudos
LucD
Leadership
Leadership

Oops, the Interval property needs to be explicitly set (I assumed it would take the default, which is 1).

Try with this version

###############

# These are the values you should get from your webform

#

$vmName = 'servername'

$snapTime = Get-Date "10/11/18 23:00"

$snapName = 'Test'

$snapDescription = 'Scheduled snapshot'

$snapMemory = $false

$snapQuiesce = $true

$emailAddr = 'xxx@xxx.com'

###############

$vm = Get-VM -Name $vmName

$si = get-view ServiceInstance

$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

$spec = New-Object VMware.Vim.ScheduledTaskSpec

$spec.Scheduler = New-Object VMware.Vim.MonthlyByWeekdayTaskScheduler

$spec.Scheduler.Offset = [VMware.Vim.WeekOfMonth]::second

$spec.Scheduler.Weekday = [VMware.Vim.DayOfWeek]::tuesday

$spec.Scheduler.Hour = 6

$spec.Scheduler.Interval = 1

$spec.Name = "Snapshot",$_.VMname -join ' '

$spec.Description = "Take a snapshot of $($vm.Name)"

$spec.Enabled = $true

$spec.Notification = $emailAddr

$spec.Action = New-Object VMware.Vim.MethodAction

$spec.Action.Name = "CreateSnapshot_Task"

@($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

    $arg = New-Object VMware.Vim.MethodActionArgument

    $arg.Value = $_

    $spec.Action.Argument += $arg

}

$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)


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

sebskc
Contributor
Contributor

Works now perfectly, thank you!

Reply
0 Kudos
LauraLeigh
Contributor
Contributor

I am trying to add some user input to the script as follows:

###############

# These are the values you should get from your webform

$Vcenter= Read-Host -Prompt "Which Vcenter is the machine located on?"

$vmName = Read-Host -Prompt "Snapshot of VM"

$date = Read-Host -Prompt "When would you like this to be taken (DD/MM/YY 23:00 Format)"

$Owner = Read-Host -Prompt "Who are you?"

$requester = Read-Host -Prompt "Email Address of Requester"

$SR = Read-Host -Prompt "What is the SR number?"

$snapTime = Get-Date "$date"

$snapName = "Snapshot of $vmName by $owner on $date per SR $SR"

$snapDescription = "Snapshot of $vmName by $owner on $date Per SR $SR"

$snapMemory = $false

$snapQuiesce = $true

$emailAddr = @("Myemailaddress@somewhere.com", "$requester")

###############

#Add VMWare Snapin & connect to vcenter

Add-PSSnapin VMware.VimAutomation.Core

Connect-VIServer -server $Vcenter

$vm = Get-VM -Name $vmName

$si = get-view ServiceInstance

$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager

$spec = New-Object VMware.Vim.ScheduledTaskSpec

$spec.Name = "Snapshot",$_.VMname -join ' '

$spec.Description = "Take a snapshot of $($vm.Name)"

$spec.Enabled = $true

$spec.Notification = $emailAddr

$spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler

$spec.Scheduler.runat = $snapTime

$spec.Action = New-Object VMware.Vim.MethodAction

$spec.Action.Name = "CreateSnapshot_Task"

@($snapName,$snapDescription,$snapMemory,$snapQuiesce) | %{

    $arg = New-Object VMware.Vim.MethodActionArgument

    $arg.Value = $_

    $spec.Action.Argument += $arg

}

$scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)

but I get the following error. I'm pretty new to scripting, so can someone please help me?:

Cannot convert argument "obj", with value: "System.Object[]", for

"CreateObjectScheduledTask" to type "VMware.Vim.ManagedObjectReference": "Cannot convert

the "System.Object[]" value of type "System.Object[]" to type

"VMware.Vim.ManagedObjectReference"."

At \\MyServer\Folder1\Folder2\ScheduleSnapshots.ps1:43 char:1

+ $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoR ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodException

    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Reply
0 Kudos
LucD
Leadership
Leadership

Could it be that Get-VM -Name $vmName returns more than 1 VM?


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

Reply
0 Kudos