vRealize Automation Ecosystem vRealize Orchestrator

How to use dynamic property definitions in vRA 7.2

Since vRA 7.2. was released we are seeing more and more customers with earlier vRA versions wanting to move to the new version. I was recently involved in a migration of a customer’s production environment from vRA 6.2 to 7.2 (If you haven’t heard of migration, check it out – it’s a totally awesome feature). When the migration ended successfully, the customer started browsing the catalog items and in a patient and polite tone said “I don’t see my property values”, while I could feel he was screaming “Aaaaaaaghhh!” panicking on the inside.

no-values

 

You could safely presume that the idea of a major issue right before an approaching migration deadline increased my heartbeat rate in no time. So, while my first reaction was “Ugh…”, I asked the customer if I could take a look at their 6.2. environment – it seemed they were using relationships as XML files.

category-profile-relation-62

The idea of the current example is simple – a user selects a VM Category from a list during a request, then the drop down list of network profiles gets filtered based on this category, and so does the list of networks. The network profiles bear the same name as the networks so it is easier to choose. In vRA 6 this is achieved by using long, incomprehensible and rather static (I would say boring) XML statements that only specify relationships, and those relationships can only be formed in a 1-to-1 manner. This means that in 6.2 when we choose the VM Category, only the Profile Name drop down list can be filtered, but not the Network Name. The “problem” with 7.2 after migration is that it doesn’t migrate XML code as the property value. Instead, we have to write vRO actions, which, as you may know can do anything, except maybe brewing coffee, last time I checked.

So, after overcoming the first rush of blood to my head and estimating the situation I said to the customer: “Alright, we can fix this”. Seeing a slight smile on the face of the person next to me I started working on a resolution to this problem. Firstly, I had to develop some kind of a database for my vRO actions to play with. I opened the VM Category property definition and manually entered the categories in a static list as the customer wanted them.

vm-category-72

The next problem I had to solve was the mapping between the network profiles and their respective VM Category. I could easily enter that as a static dictionary in my Javascript code in vRO, but I wanted to stick to a basic principle when coding vRO actions – keep as much of the data as possible in vRA and leave the logic to vRO. One solution could be creating another property definition as a static list featuring the relationships, but this meant the customer would have yet another set of properties to manage whenever something in their infrastructure changed, for example a network got removed. I knew that in the customer environment the relationship between VM Category and Network profiles was 1-to-many, so I implemented another approach – I filled the Description of the already migrated Network Profiles with the VM Category names. This way when the customer removes a profile, they would also remove the relationship, and vice-versa.

network-profiles-72

Next, I logged onto the vRO client, went to Design and created a new module from the Actions pane.

vro-newmodule

Then, I created a new Action and named it GetNetProfiles, which, you guessed it, could fetch the profiles based on an input called VM Category. On the Scripting tab of the Edit window I set the return type to be “Array of Strings”, because this is what a drop down list actually represents.

vro-returntype-netpr

Then I added the input parameter and called it VMCategory of type String.

vro-input-netpr

Now, the reader might already be shouting “Show me the code!”, so I will not delay this anymore.

function getNetProfiles(VMCategoryName)
{
  var host = Server.findAllForType("vCAC:vCACHost")[0];
  var netProfilesNamesList = [""];
  var model = "ManagementModelEntities.svc";
  var entitySetName = "StaticIPv4NetworkProfiles";
  var property = new Properties();
  property.put("ProfileDescription", VMCategoryName);
  var netProfiles = vCACEntityManager.readModelEntitiesByCustomFilter(host.id, model, entitySetName, property, null);
  for each (var netProfile in netProfiles)
  {
    netProfilesNamesList.push(netProfile.getProperty("StaticIPv4NetworkProfileName"));
  }
    return netProfilesNamesList;
}
if (VMCategory)
{
  return getNetProfiles(VMCategory);
}
else
{
  return ["Please, select a VM Category"];
}

So, let’s analyse the code. First, it gets a host variable that represents the default IaaS Server, i.e. your Web IaaS Service of a vRA environment. Then, we craft a property variable that will be used to filter only those Network Profiles, that have VM Category as their description. After that, we just call the vCACEntityManager class and read all Entities of Set StaticIPv4NetworkProfiles by using the aforementioned property as a filter. Finally, the names of all Network Profiles which are returned by this query get extracted and poured into an array (remember the return type we set). So, basically we wrap this into a function and call this function in the action execution, while checking if we have a selected VMCategory.

After wrapping up the script code. I created another action, this time calling it GetNetworkName, which again returns an array of String and accepts an input string called NetProfile.

vro-returntype-netname

This action returns the name of the Network Profile as the name of the network in vCenter. Remember in my case I had the Network Profile name be the same as the Network name.

if(NetProfile)
{
 return [NetProfile];
}
else
{
 return ["Please, select a network profile"];
}

Now, you might be wondering how do we attach these actions to a drop down and how do we specify the input properties. Stay with me.

When done with scripting, I navigated back to the vRA 7.2 Automation Console and went straight ahead to editing a Property Definition. I selected the property with a name of VirtualMachine.Network0.ProfileName. I set the type to String and the display name as a Dropdown. The values were set to “External values” and the script action was selected from the list of actions. This list is filtered based on the data type of the property, so don’t freak out if you don’t see all the actions here.

As the Input parameter I entered VMCategory and made sure the value is passed from the VM Category Property Definition I had created earlier.

prop72-profilename

After that, I edited the VirtualMachine.Network0.Name property and selected the GetNetworkName action while setting the ProfileName property as an input parameter.

prop72-netname

I made sure the display order is set correctly, so the request form will show all the properties one under the other.

Next, I headed to the blueprint that needs these properties and made sure that the VM Category is set as a Custom Property and Show in Request is set to Yes, i.e. checked.

blueprint72-vmcatprop

Since the properties for the profiles and networks are network properties we need to check they exist in the network configuration of the blueprint.

blueprint72-netprop

Finally, I was able to request a new VM:

req72-vmcat

req72-netpr

The number of ways this approach can be modified or optimized is infinite – for example, we can use the now recommended NetworkProfileName property which combines the Network Profile and Network Name properties into one or if the profile name differs from the network name we could create another set of a dictionary that maps these two, or you can connect to the company’s service catalog and extract the VM Categories dynamically and so on and so on. I leave it to the reader’s imagination…

More on vRA 7.2.