VMware Cloud Community
rnaude241
Contributor
Contributor

Backup Script that removes clone older than 7 days

Hi everyone,

I am fairly new to powercli and powershell but I am trying to learn.  I have tailored a backup script that works for my environment but I'd like it to do a little more.  Right now the script keeps the cloned VMs in my inventory, I'd like for it to remove the new clones (backups) from inventory so they just sit on the "Backups" datastore.

I have added the following to try to achevie this, but I am not sure if it's correct.

"# Remove Clone from vCenter Inventory

    Get-VM –VM (Get-VM -Name $customer.MasterVM) -Name $cloneName | Remove-VM -confirm:$False"

Secondly when the script runs I'd like for it to first check the if there are any clones older then 7 days, if so delete that clone from the datastore before starting a new backup.

Here is my script, I appreciate the help from the community.

# Add the vmware snapin for powershell

Add-PSSnapin VMware.VimAutomation.Core

# Import Backup CSV

$backupinfo =  Import-Csv C:\Powershell-scripts\devbackups.csv

#Set Date format for clone names

$date = Get-Date -Format "yyyyMMdd"

#Set Date format for emails

$time = (Get-Date -f "HH:MM")

# Your vcenter server and credentials

$vcenter = "vcenter"

$username = "root"

$password = "password"

# Establish Connection

connect-viserver -server $vcenter -user $username -password $password

foreach ($customer in $backupinfo)

{

  $vm = Get-VM $customer.MasterVM

  #Send Start Email

  C:\Powershell-scripts\backupstartedemail.ps1

  # Create new snapshot for clone

  $cloneSnap = $vm | New-Snapshot -Name "Clone Snapshot"

  # Get managed object view

  $vmView = $vm | Get-View

  # Get folder managed object reference

  $cloneFolder = $vmView.parent

  # Build clone specification

  $cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec

  $cloneSpec.Snapshot = $vmView.Snapshot.CurrentSnapshot

  # Make linked disk specification

  $cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec

  $cloneSpec.Location.Datastore = (Get-Datastore -Name $customer.BackupDS | Get-View).MoRef

  $cloneSpec.Location.Transform =  [Vmware.Vim.VirtualMachineRelocateTransformation]::sparse

  $cloneName = "$vm-$date"

  # Create clone

  $vmView.CloneVM( $cloneFolder, $cloneName, $cloneSpec )

  # Write newly created VM to stdout as confirmation

  Get-VM $cloneName

  # Remove Snapshot created for clone

  Get-Snapshot -VM (Get-VM -Name $customer.MasterVM) -Name $cloneSnap | Remove-Snapshot -confirm:$False

  

    # Remove Clone from vCenter Inventory

    Get-VM –VM (Get-VM -Name $customer.MasterVM) -Name $cloneName | Remove-VM -confirm:$False

  #Send Complete Email

  C:\Powershell-scripts\backupcompletedemail.ps1

}

#Disconnect from vCentre

Disconnect-VIServer -Confirm:$false

Thank you for the help.

0 Kudos
9 Replies
LucD
Leadership
Leadership

You can use the Remove-VM cmdlet for that, with the DeletePermanently switch set to $false

Remove-VM -DeletePermanently:$false -Confirm:$false


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

0 Kudos
rnaude241
Contributor
Contributor

Thanks, however won't that just delete all VMs? How does it know to remove VMs in the datastore that are older than 7 days?

0 Kudos
LucD
Leadership
Leadership

I assumed that your script already had that logic.

I just wanted to indicate the if you change your lines

    # Remove Clone from vCenter Inventory

    Get-VM –VM (Get-VM -Name $customer.MasterVM) -Name $cloneName | Remove-VM -confirm:$False

It would remove the VM from the inventory, but keep them on the datastore.


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

0 Kudos
rnaude241
Contributor
Contributor

Thank you for the help Lucid.  I believe I have the script almost where I'd like it.  The last thing I want to change is the emailing functionality.  Right now it sends an email for every VM when it starts the process and when it finishes, so 2 emails per VM.  Can someone help/explain the commands I need to just send perhaps 2 total emails? 1 email showing the process is started and then a summary email when all the VM's are backed up?

Thanks again

0 Kudos
LucD
Leadership
Leadership

Move these lines outside the ForEach loop

#Send Complete Email

  C:\Powershell-scripts\backupcompletedemail.ps1


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

0 Kudos
rnaude241
Contributor
Contributor

Sorry my fault for not including the backupstartedemail.ps1 and backupcompletedemail.ps1  I I move those outside of the foreach loop then the emails will only send a start and finish email, but I won't have an entire summary of the foreach loop correct?

Backupstartedemail.ps1:

#Set Date format for emails

$timestart = (Get-Date -f "HH:MM")

$emailFrom = "VmwareBackups@com"

$emailTo = "me@.com"

$subject = "[$vm - Backup Started]"

$body = "Backup Details

-------------

VM Name:",$vm,"

Clone Name:","$vm-$date","

Target Datastore:", $customer.BackupDS,"

Time Started:", $timestart

$smtpServer = "smtp.com"

$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$smtp.Send($emailFrom,$emailTo,$subject,$body)

Backupcompletedemail.ps1

#Set Date format for emails

$timecomplete = (Get-Date -f "HH:MM")

$emailFrom = "VmwareBackups@.com"

$emailTo = "me.com"

$subject = "[$vm - Backup Complete]"

$body = "Backup Details

-------------

VM Name:",$vm,"

Clone Name:","$vm-$date","

Target Datastore:", $customer.Backups,"

Time Started:", $timestart,"

Time Completed:", $timecomplete

$smtpServer = "smtp.com"

$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$smtp.Send($emailFrom,$emailTo,$subject,$body)

What I am trying to achieve would be a general start email saying backups have started - this is easy, just move backupsstartedemail.ps1 outside of the foreach loop- and also 1 completed email saying all VM's in the foreach loop completed.

If I move backupscompletedemail.ps1 outside of the foreach loop there will be no data provided about the process other than it's done.

0 Kudos
LucD
Leadership
Leadership

You could collect all that information in an array inside the ForEach loop.

Then after the ForEach loop you send the email and insert the content of the array in the body of the email.

An alternative could be to send the array to a CSV file, and send that file as an attachment


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

0 Kudos
rnaude241
Contributor
Contributor

Is it is possible for you to give me an example using my powershell script?

Thanks

0 Kudos
Craig_Baltzer
Expert
Expert

You could do something like this:

# Keep all the stuff you have before your ForEach loop and insert it here

$MessageBody = ""

ForEach ($customer in $backup info) {

   $vm = Get-VM $customer.MasterVM

  $MessageBody += "VM Name: " + $vm.Name + "`n"

  $MessageBody += "Clone Name: " + $vm.Name + "-$date`n"

  $MessageBody += "Target Datastore: " + $customer.BackupDS + "`n"

  $MessageBody += "Time Started: " + (Get-Date -f "HH:MM") + "`n"

  # Keep all the backup stuff you have inside the ForEach loop and insert it here

  $MessageBody += "Time Finished: " +  (Get-Date -f "HH:MM") + "`n`n"

}

$emailFrom = "VmwareBackups@me.com"

$emailTo = "somebody@me.com"

$subject = "VM Backup Report"

$smtpServer = "smtp.me.com"

$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$smtp.Send($emailFrom,$emailTo,$subject,$MessageBody)

0 Kudos