vRO workflow: Remove virtual machine snapshots older than X days/hours.

Introduction

If you are familiar with the vRealize Orchestrator and vCenter plugin, you may know that a build-in workflow called: Remove old snapshots (Library->vCenter->Virtual Machine management->Snapshot) can be used to find and remove old snapshots. So, why do I need a new workflow? Because it is the first part of my plan to create vRealize Automation custom action o Deployments level. The second part I will publish in the vRealize Automation section will focus on how to adopt that workflow to a custom action. The built-in vRO workflow has few disadvantages. First of all, it has user interaction while snapshot removing. Therefore, I do not need it. Moreover, I cannot use it with vRA action. So, the main goals for my workflow are to be able to use it later in vRA custom action, no user interaction while processing workflow, and give people the ability to select different units to define how old snapshots I want to remove. And the last one, I want to remove snapshots only for selected virtual machine (in short, I want it to be as simple as possible). In this post, you will find how to achieve that.

Prerequisites

To start, we need to meet some prerequisites:

  • vRealize Orchestrator server – embedded or standalone.
  • vRealize Orchestrator vCenter plugin configured and connected to vCenter server.

Workflow details

Below, I explain how workflow works. If you want, you can download prepared workflow in Resources section at the end of that post.

vRA-CA-RemoveOldSnaps-1

We need some inputs to workflow:
vm(VC:VirtualMachine) – Remove snapshots only for selected virtual machine.
metric(string) – Hours/Days.
howOldSnap(number) – How old snapshots we want to remove.

vRA-CA-RemoveOldSnaps-2

Also we need to define some variables:
snapshotsArray (Array/Any) – Array that will contains all snapshots that we want to remove.
errorCode (string) – String used to throw an error.

vRA-CA-RemoveOldSnaps-3

TASK 1
The first element is a scriptable task where we check the vCenter time and time for the ESXi server that hosts our virtual machine. In general, all should be synchronized with the NTP server so, the difference should be only a few milliseconds. If the time on the host is different than on the vCenter server, it may happen that we will remove wrong snapshots (I didn’t write that part myself. All code for that task can be found in a build-in workflow that I mentioned earlier).
Inputs:
vm(VC:VirtualMachine)

try
{
    //Create object reference instance
    var instance = new VcManagedObjectReference();
    instance.type = "ServiceInstance";
    instance.value = "ServiceInstance";

    //Get ESXi host where VM is placed
    var esxiHost = vm.runtime.host;
    System.log("\n VM: "+vm.name+"\n VM ESXi Host placement: "+esxiHost.name+"\n ESXi host has state: "+esxiHost.state);

    //Get time from VC
    var instanceObject;
    var timeVC;
    instanceObject = VcPlugin.convertToVimManagedObject(esxiHost, instance);
    timeVC = instanceObject.currentTime().getTime();
    System.log("vCenter time: "+timeVC);

    //Get ESXi time
    var myHostDateTimeSystem;
    var timeHost;
    myHostDateTimeSystem = VcPlugin.convertToVimManagedObject(esxiHost , esxiHost.configManager.dateTimeSystem);
    timeHost = myHostDateTimeSystem.queryDateTime().getTime();
    System.log("ESXi time: "+timeHost);

    //Check difference
    var differenceInMinute;

    differenceInMinute = (timeHost-timeVC)/60000;
    if(differenceInMinute<0)differenceInMinute = -differenceInMinute;
    if(differenceInMinute>2)
        {
        throw("Time difference between vCenter and ESXi host is bigger than 2 minutes!");
        }
    else
        {
        System.log("Time difference in minutes between vCenter and ESXi host is: "+differenceInMinute);
        }
}

catch (errorCode)
{
	System.error(errorCode);
	throw errorCode;
}

TASK 2
The second task is responsible for searching virtual machine snapshots from the VM root snapshot list. It’s the more tricky part. Here, we also have a part where we check our time units and compare them with snapshot age. If you need different than hours or days, extend that part using simple math 🙂
Inputs:
vm(VC:VirtualMachine)
metric(string)
howOldSnap(number)
Outputs:
snapshotsArray (Array/Any)

var diff;
var now = new Date();
snapshotsArray = new Array();

//Function which puts single snapshot objects from snapshot data to snapshotsArray.
function getSnapshotsInfoOfVmFromSnapshotTree(snapshotTree,howOld,unit)
{
	System.log("\n Snapshot name: " + snapshotTree.name + "\n Description: " + snapshotTree.description + "\n Creation time: "+ snapshotTree.createTime + "\n Creation time in ms: " + snapshotTree.createTime.getTime());
	
    //Check how old is snapshot
    diff = now - snapshotTree.createTime.getTime();
	var diffHours = diff/(1000 * 60 * 60);
	var diffDays = diff/(1000 * 60 * 60 * 24);
	System.log("How old is snapshot in days: "+diffDays);
	System.log("How old is snapshot in hours: "+diffHours);

	if (unit=="Days")
		{
		System.log("Use days to compare time.");
		if (diffDays >= howOld)
			{
			System.log("I will push: '"+snapshotTree.name+"' into array.");
			snapshotsArray.push(snapshotTree)
			}
		else
			{
			System.log("Snapshot: '"+snapshotTree.name+"' is not older than: "+howOld+" days.");
			}
		}
	else if (unit=="Hours")
		{
		System.log("Use hours to compare time.");
		if (diffHours >= howOld)
			{
			System.log("I will push: '"+snapshotTree.name+"' into array.");
			snapshotsArray.push(snapshotTree)
			}
		else
			{
			System.log("Snapshot: '"+snapshotTree.name+"' is not older than: "+howOld+" hours.");
			}
		}
	else
		{
		throw("Wrong unit in function,");
		}
				
    var trees = snapshotTree.childSnapshotList;

    //Repeat function for all child snapshots
    if (trees != null) 
	{
        for (index in trees) 
			{
            if (trees[index] != null)
    	        getSnapshotsInfoOfVmFromSnapshotTree(trees[index],howOld,unit);
	        }
    }
}

try
{
    //Check if VM has a snapshot.
    if (vm.snapshot)
        {
        //Get snapshot list. rootSnapshotList is data for entire set of snapshots for VM.
        System.log("Virtual machine: "+vm.name+" has snapshots. I am getting rootSnapshotList");
        var snapshotTrees = vm.snapshot.rootSnapshotList;
        //System.log(snapshotTrees)
        
        //Get single snapshot objects from snapshot data.
        for (i in snapshotTrees) 
            {
            getSnapshotsInfoOfVmFromSnapshotTree(snapshotTrees[i],howOldSnap,metric);
            }
        }
}
catch (errorCode)
{
	System.error(errorCode);
	throw errorCode;
}

TASK 3
If we have array that contains all old snapshots, we can use it to removal.
Inputs:
vm(VC:VirtualMachine)
snapshotsArray (Array/Any)

System.log("Start removing snapshots...");

try
{
    for each (snap in snapshotsArray)
        {
        System.log("Snapshot with name "+snap.name+" will be removed.");
        //(removeChildren,Consolidate)
        var task = snap.snapshot.removeSnapshot_Task(false,true);
        //Wait for task
        var actionResult = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task);	
        System.log("Snapshot: "+snap.name+" for VM: "+vm.name+" successfully removed.");
        }
        
    System.log("All snapshots successfully removed.");
}
catch (errorCode)
{
	System.error(errorCode);
	throw errorCode;
}

Resources

Remove old snapshots for VM workflow.

Summary

Enjoy the content and stay tuned.

One thought on “vRO workflow: Remove virtual machine snapshots older than X days/hours.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s