Friday, 25 May 2018

vRealize Automation - More VM Expiration Notifications

I have been working with a customer who have mentioned concern around VMs suddenly turning themselves off if users forget the VM has a lease or don't regularly use vRA.  This to me is a question of good operating procedures and user education - but Rome wasn't built in a day, so what can we do to help...

The first article I came across was from VMware which seems to provide an out of the box method of notifying users, which is great...
but my problem is that if we want to provide more than one notification (i.e., "You have 5 days to go" and then "Last warning - your VM's going to be shut down if you don't extend the lease" type approach)... 

What I did was write a vRO workflow to find the expiration date from the vCAC:VirtualMachine and check whether it was * number of days ahead of the current date in order to trigger an email to send a custom warning.  My main issue was that the vCAC:VirtualMachine date object is in a format of string like 2018-05-25T10:15:11:254 - which I needed to convert into a vRO Date Object.

I first created an action to take the string of the vCAC Date Object and convert it to a date object.  I couldn't find a better way to do it other than splitting the string, so it looks like this:

//Input  dateString - String
//Output Date
var tempSplit = new Array();
tempSplit = dateString.split("-");
var year = tempSplit[0];
var month = tempSplit[1];
month = month -1;
var dayTime = tempSplit[2];
tempSplit = dayTime.split("T");
var day = tempSplit[0];
tempSplit = tempSplit[1].split(":");
var hour = tempSplit[0];
var minute = tempSplit[1];
tempSplit = tempSplit[2].split(".");
var second = tempSplit[0];
//Return Date Object
return (new Date(year,month,day,hour,minute,second));

From which, I can use the action to convert the date string to a vRO date and use an 'if' statement to filter VMs with a relevant date into the three separate arrays

var vcacVms = Server.findAllForType("vCAC:VirtualMachine");

//Get future dates
var now = new Date();
var dayPlus1 = new Date();
dayPlus1.setDate(dayPlus1.getDate() + 1); 
var dayPlus3 = new Date();
dayPlus3.setDate(dayPlus3.getDate() + 3); 
var dayPlus5 = new Date();
dayPlus5.setDate(dayPlus5.getDate() + 5); 

//Define arrays
var vms5Day = new Array();
var vms3Day = new Array();
var vms1Day = new Array();

//Loop all VMs to idenfity expiration times
for each (var vcacVm in vcacVms) {
System.log (vcacVm.displayName);
var vmExpires =  vcacVm.expires
System.log (vmExpires)
if (vmExpires != null) {
vmExpires = vmExpires.toString();
var dateObj = System.getModule("com.vmware.sjw").convertVraDateStringToDateObject(vmExpires);
if ((dateObj < dayPlus5) && (dateObj > dayPlus3)) {
System.log (vcacVm.displayName + " has 5 days until expiration");
if ((dateObj < dayPlus3) && (dateObj >dayPlus1)) {
System.log (vcacVm.displayName + " has 3 days until expiration");
if ((dateObj < dayPlus1) && (dateObj > now)) {
System.log (vcacVm.displayName + " has 1 days until expiration");

From the three separate arrays, I had three separate tasks for each array (mainly to be able to separate out other actions should we need them in the future)...   This was done using the new EmailMessage(); functionality with HTLM content stored in the WF attributes (mailBody)...  An example is below:

for each (var vm3Day in vms3Day) 
{ var displayName = vm3Day.displayName;
  var expiration = vm3Day.expires;
  var notes = vm3Day.notes;
if (notes == null) {
notes = "No details supplied at provisioning time"}
var messageContent = mailBody
messageContent = messageContent.replace ("{{vmName}}",displayName)
messageContent = messageContent.replace ("{{expirationDate}}",expiration)
messageContent = messageContent.replace ("{{details}}",notes)

//Get Catalog Resource from vCAC VM and get mail address from user reference
var cafeVm = System.getModule("com.vmware.sjw").getCatalogResourceOfVM(vm3Day,"arm")
var owners = new Array();
owners = cafeVm.owners;
var mailAddress = owners[0].getRef();

//Send email 
var message = new EmailMessage() ; 
message.subject = "Warning - less than 3 day on VM " + displayName  + " lease." ; 
message.toAddress = mailAddress ; 

N.B., the action referred in the above 'getCatalogResourceOfVM' info can be found here:

I don't think it's ideal, but it works!