VMware Cloud Community
rstoker13
VMware Employee
VMware Employee

How to set reservation policy with Event Broker

I have a need to dynamically assign the reservation policy after a request has been submitted based on the type of catalog item requested and business group membership of the user. I have created vRO workflows that select the appropriate reservation policy, but I cannot get it to apply the the deployment using the "ReservationPolicyId" property or the hidden "__reservationPolicyID" property. I have attempted these properties through an output of the vRO workflow as a properties object and also using "System.getModule("com.vmware.library.vcac").addUpdatePropertyFromVirtualMachineEntity". Other properties such as setting the VM Folder, setting custom attributes or setting CPU/Mem sizes work properly. It seems to me as though this property is referenced prior to my setting it and therefore is ignored. I am using the EBS topic "Machine provisioning" with the conditions in the image below.

I look forward to your assistance! Thank you.

conditions.PNG

details.PNG

Reply
0 Kudos
10 Replies
michael_stefani
Enthusiast
Enthusiast

I'm curious about the same thing.  We're migrating from 6.2 to 7.3.  In 6.2 we had to use ASD as there was no way to change the reservation policy in the workflow stubs after submission of the request.  We're trying to determine if we can do this via the event broker or if we have to use XAAS in 7.3.  Please post if you find a solution to this via event broker or if you have to go the XAAS route.  Thanks,

Mike

Reply
0 Kudos
sbeaver
Leadership
Leadership

I am doing something like this and it appears to be working the way that I have expected.  First thing, in your blueprint make sure the approval policy value is blank.

Now I have a subscription that fires at VMPSMasterWorkflow32.Requested/PRE.  This subscription handles all the data processing that I did not need to do in the form and updates a bunch of values in the process.

Below is the code from the subscription for the reservation piece:  I have a location value that is made up of different values and I split that value into an array to work with

The value that I return is __ReservationPolicyID

var locs = location.split(" ");

if ( locs[2] != "Online" ){locs[2] = "dataCanter"};

//var blueprint = System.getContext().getParameter("__asd_composition_blueprintId");

//var component = System.getContext().getParameter("__asd_composition_componentId");

var blueprint = bluePrintID;

var component = ComponentId;

var user = System.getContext().getParameter("__asd_requestedFor");

var tenant = System.getContext().getParameter("__asd_tenantRef");

var host = vCACCAFEHostManager.getDefaultHostForTenant(tenant , true);

var reservationPolicyService = host.createReservationClient().getReservationReservationPolicyService();

var reservations = System.getModule("com.vmware.vra.reservations").getReservationsForUserAndComponent(user,tenant,host, blueprint, component);

// get reservation filtered by reservations

var reservationPolicyFilter = getReservationPolicyFilterForReservations(reservations);

var reservationPolicies = [];

if (reservationPolicyFilter) {

               reservationPolicies = reservationPolicyService.getAllReservationPolicies(reservationPolicyFilter).getContent();

}

//System.log("looking for policy with name " + locs[1] + "-" + locs[2]+ "-" + osType);

var reservationPolicyProperties = new Properties();

for each(var reservationPolicy in reservationPolicies) {

               //if (reservationPolicy.getName().indexOf(locs[1]) >= 0){

               //System.log(reservationPolicy.getName() + " / " + reservationPolicy.name);

               if (reservationPolicy.name = locs[0] + "-" + locs[2]+ "-" + osType){

                              reservationPolicyProperties.put(reservationPolicy.id, reservationPolicy.name);

                              var ReservationPolicyID = reservationPolicy.id.toString();

                              var policyReservation = reservationPolicy

                              }

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////

function getReservationPolicyFilterForReservations(reservations) {

               var query = new vCACCAFEOdataQuery();

               var queryParams = [];

               for each (var reservation in reservations) {

                              queryParams.push(vCACCAFEFilterParam.equal("id" , vCACCAFEFilterParam.string(reservation.getReservationPolicyId())));

               }

               if(queryParams.length > 1) {

                              query.addFilter([vCACCAFEFilterParam.or(queryParams)]);

               } else if(queryParams.length == 1){

                              query.addFilter(queryParams);

               } else {

                              return null;

               }

             

               return new vCACCAFEPageOdataRequest(1 , 2147483647, query);

}

//---------------------------------------------------------------------------------------->

Since we are talking about reservation Policies and reservations in general this might be worth sharing.  I actual pull the available networks from the reservation itself and use this code as the property action:

Steve Beaver
VMware Communities User Moderator
VMware vExpert 2009 - 2020
VMware NSX vExpert - 2019 - 2020
====
Co-Author of "VMware ESX Essentials in the Virtual Data Center"
(ISBN:1420070274) from Auerbach
Come check out my blog: [www.virtualizationpractice.com/blog|http://www.virtualizationpractice.com/blog/]
Come follow me on twitter http://www.twitter.com/sbeaver

**The Cloud is a journey, not a project.**
Reply
0 Kudos
tchristin
Enthusiast
Enthusiast

Hi Stephen,

I'm trying to do the same at PRE Requested event with vRO by adding property ReservationPolicyID to virtualMachineAddOrUpdateProperties but it's not working...

It still provision the VM to the ESXi cluster corresponding to the resevation that was automatically chosen at request.

I'm using vRA 7.3

Could you please give me some tips to achieve it ?

Thanks !!

Tim.

Reply
0 Kudos
sbeaver
Leadership
Leadership

What I have found so far is that this must be defined at request

Steve Beaver
VMware Communities User Moderator
VMware vExpert 2009 - 2020
VMware NSX vExpert - 2019 - 2020
====
Co-Author of "VMware ESX Essentials in the Virtual Data Center"
(ISBN:1420070274) from Auerbach
Come check out my blog: [www.virtualizationpractice.com/blog|http://www.virtualizationpractice.com/blog/]
Come follow me on twitter http://www.twitter.com/sbeaver

**The Cloud is a journey, not a project.**
Reply
0 Kudos
tchristin
Enthusiast
Enthusiast

Hi all,

I found a solution to change reservation after request and within a workflow that compute VM placement.

It must be done at the IaaS level as it appears that some properties are not updating this part.

Thanks to this old thread : Moving VMs between vRA business groups and reservations in vCO « wolowicz.info

To achieve that you need following inputs :

VariableTypeDescription
iaasHostvCAC:VCACHostIaaS Host
virtualMachineIdstringRequested machine ID
targetReservationvCACCAFE:ReservationTarget reservation to be set to machine
targetStoragevCAC:EntityTarget storage for machine disks


Here is my code :

// Look for VM

System.log("Looking for virtual machine with ID: " + virtualMachineId);

// Build IaaS query

var query = "VirtualMachineID eq guid'" + virtualMachineId + "'";

var virtualMachineEntity = vCACEntityManager.readModelEntitiesBySystemQuery(iaasHost.id, "ManagementModelEntities.svc", "VirtualMachines", query, null, null, null, null, null);

if (virtualMachineEntity == null)

{

     var errorCode = "No VM found!";

     System.error(errorCode);

       throw errorCode;

}

// Look for IaaS reservation

System.log("Looking for host reservation with ID: " + targetReservation.getId());

// Build IaaS query

var query = "HostReservationID eq guid'" + targetReservation.getId() + "'";

var reservationEntity = vCACEntityManager.readModelEntitiesBySystemQuery(iaasHost.id, "ManagementModelEntities.svc", "HostReservations", query, null, null, null, null, null);

if (reservationEntity != null)

{

     System.log("Found IaaS reservation.");

}

else

{

     System.warn("No Reservation found with name: " + targetReservation.getName());

}

//Updating host reservation

System.log("Updating host reservation...");

var hostReservation = reservationEntity[0];

var hrLinks = new Properties();

hrLinks.put("HostReservation", [hostReservation]);

var hrProperties = new Properties();

// Update IaaS VM entity

System.getModule("com.vmware.library.vcac").updateEntity(virtualMachineEntity[0], hrProperties, hrLinks);

//Updating host reservation to storage

System.log("Updating host reservation to storage...");

var rStorages = reservationEntity[0].getLink(iaasHost, "HostReservationToStorages");

var hostReservationToStorage = null;

// Execute function to find HostReservationToStorage

evalHostReservationToStorage(rStorages);

var hrtsLinks = new Properties();

hrtsLinks.put("HostReservationToStorage", [hostReservationToStorage]);

var hrtsProperties = new Properties();

// Update IaaS VM entity

System.getModule("com.vmware.library.vcac").updateEntity(virtualMachineEntity[0], hrtsProperties, hrtsLinks);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function evalHostReservationToStorage(reservStorages)

{

     for each (var rs in reservStorages)

     {

          var storage = rs.getLink(iaasHost, "HostToStorage")[0];

          var isCluster = storage.getProperty("IsStorageCluster");

          if (isCluster === true)

          {

               var children = storage.getLink(iaasHost, "Children");

               for each (var childHostTosTorage in children)

               {

                    System.debug("Child: " + childHostTosTorage.getProperty("StoragePath"));

                    if (childHostTosTorage.getProperty("StoragePath") == targetStorage.getProperty("StoragePath"))

                    {

                         System.log("Matching storage: " + storage.getProperty("StoragePath"))

                         hostReservationToStorageEntity = rs;

                    }

               }

          }

          System.debug("Storage path: " + storage.getProperty("StoragePath"));

          if (storage.getProperty("StoragePath") == targetStorage.getProperty("StoragePath"))

          {

               hostReservationToStorage = rs;

               System.log("Matching storage: " + storage.getProperty("StoragePath"))

               break;

          }

     }

}

if (hostReservationToStorage == null)

{

     var errorCode = "No host-reservation-to-storage found!";

     System.error(errorCode);

     throw errorCode;

}

else

{

     System.debug("Host reservation to storage: " + hostReservationToStorage);

}

But with this piece of code you still need to update properties related to storage and pass it to variable virtualMachineAddOrUpdateProperties for Event Broker :

  • VirtualMachine.Storage.Cluster.Name
  • VirtualMachine.Storage.Cluster.ExternalReferenceId
  • VirtualMachine.Storage.Name
  • ...

You can add ReservationPolicyID property with right value too but I don't see any effect on 7.3.

If it still not clear, just let me know.

Cheers,

Tim.

Reply
0 Kudos
DLally
Enthusiast
Enthusiast

When you say it must be done at Iaas level, what do you mean by that? 

I'm in the same boat of needing to set the __ReservationPolicyID after it is requested.  Weird thing is i cannot even get it to work with the old workflow stubs.  I haven't even tried the EBS for this part yet.

Reply
0 Kudos
AnotherPassword
Enthusiast
Enthusiast

I solved this by doing this. Hopefully it won't be like this in the future. Yes, I realize there is a snippet of code for another way to do this but I like mine for my situation.

     The net net is when a user makes some combination of selections, my custom action getReservationPolicy fires and sets reservationPolicyID just like if they user selected the policies from a dropdown in the 1st place. Remember, you CAN set reservationPolicyID with a dropdown, but you CAN'T set it using  virtualMachineAddOrUpdateProperties

    

     I am assuming that people want to use virtualMachineAddOrUpdateProperties to set the reservationPolicyId because they wan to make an intelligent placement decision based on user input, and having them select the reservation policy from a dropdown named reservationPolicyId is confusing for the end user. I originally went this route and named all my res policies something meaningful, but even then it is confusing.

     I am using custom forms. To get this setup, the 1st thing I did was to 'tag' all my reservation policies in vra with information that could be matched based on user input to determine which policy to use. Yes, you can not tag a reservation policy, but you CAN put delimited text like this in the description:

Name          Type                         Description
ResPol1     Reservation Policy    res_Datacenter:Main Street,res_Application:General Population,res_Production_State:Non-Production

If you notice, this policy then is 'tagged 'with key value pairs once you split it on commas then split on colons

res_Datacenter      Main Street

res_Application      General Population

res_Production_State     Non-Production

     These 'tags' can now be used to identify the reservation Policy based on user input  of your choice. My environment has 2 datacenters, and clusters for general population or specific app, and if general population there are clusters for production and non -production (don't ask, I only work here). The code I put below named 'ACTION getReservationPolicy code'. reservationTagFilter are the 3 properties passed to the action, and respolicyTagElements are the parsed 'tags' as properties. This action gathers those, goes through all my reservation policies and finds the policy with the matching tags.

     To implement this, 'tag' your reservation policies. Add a custom property reservationPolicyID to the vm in the blueprint or from property dictionary. Add custom property(s) from property dictionary (or just the vm in blueprint) that will be the selections the user makes for you to determine which res policy to use. Mine are  cf_prdApplicationName, cf_prdDatacenter, cf_prdFinalProductionState

Drag reservationPolicyID,cf_prdApplicationName, cf_prdDatacenter, cf_prdFinalProductionState onto a custom form.

     Make all 4 of them dropdown, for example cf_prdApplicationName, cf_prdDatacenter, cf_prdFinalProductionState dropdowns may be "app1", "app2"   "north","south"   "prod","non-prod"

reservationPolicyID is setup like this: take the 3 inputs cf_prdApplicationName, cf_prdDatacenter, cf_prdFinalProductionState and pass them to external source /actions/getReservationPolicy. It can be hidden but must be a dropdown because if it is not you can't fire the action.

Untitled.jpg

ACTION getReservationPolicy code:

=====================================================

System.log("------------ IN getReservationPolicy -----------");

reservationTagFilter = new Properties();

//cf_prdApplicationName = machineProperties.get("cf_prdApplicationName"); //get selected app, this determins all other

System.log("------------ Building reservationTagFilter -----------");

if(cf_prdApplicationName == "General Population"){

reservationTagFilter.put("res_Application",cf_prdApplicationName);

reservationTagFilter.put("res_Datacenter",cf_prdDatacenter);

reservationTagFilter.put("res_Production_State",cf_prdFinalProductionState);

}

for each(key in reservationTagFilter.keys){

System.log("Key: " + key + " --->  Value: " + reservationTagFilter.get(key))

}

System.log("------------ Step thru res policies -----------");

var host = Server.findAllForType("VCACCAFE:VCACHost")[1];

var reservationPolicies = vCACCAFEEntitiesFinder.getReservationPolicies(host);

var matchedIDs = [];

var x = 0;

var reservationPolicyProperties = new Properties();

for each(var reservationPolicy in reservationPolicies){

var respolicyTagElements = new Properties();

//System.log("============")

//"res_DC:Main Street,res_AP:General Population,res_PS:Non-Production" // gives 3 chunks of catetory:tag //eg res_DC:Main Street

var numOfRespollicyTagElements = reservationPolicy.description.split(",").length; //3

var tmpArray = reservationPolicy.description.split(",") ;

for (var i = 0;i < numOfRespollicyTagElements; i++){ //split res policy desc into key/value properties aka 'tags'

var resPolCategory = tmpArray[i].split(":")[0]

var resPolTag = tmpArray[i].split(":")[1]

respolicyTagElements.put(resPolCategory,resPolTag);

//System.log("===== " + x + " =======" + " Keys: " + respolicyTagElements.keys.length);

for each(key in respolicyTagElements.keys){

//System.log("Key: " + key + " Value: " + respolicyTagElements.get(key));

}

if(respolicyTagElements.keys.length == reservationTagFilter.keys.length){ //respolicy num keys matches filter num keys

//System.log("In matchcount")

var matchCount = 0; //step thru tag filter (from request form) and match agains reservation policy tags

//System.log("============")

for each(rtfKey in reservationTagFilter.keys){

for each(rteKey in respolicyTagElements.keys){

//System.log("rtfKey: " + rtfKey + " --> rteKey: " + rteKey);

//System.log("rtfKey: " + rtfKey.length + " --> rteKey: " + rteKey.length);

//System.log("reservationTagFilter.get(rtfKey): " + reservationTagFilter.get(rtfKey) + " --> respolicyTagElements.get(rteKey): " + respolicyTagElements.get(rteKey));

//System.log("reservationTagFilter.get(rtfKey): " + reservationTagFilter.get(rtfKey).length + " --> respolicyTagElements.get(rteKey): " + respolicyTagElements.get(rteKey).length);

if( (reservationTagFilter.get(rtfKey) == respolicyTagElements.get(rteKey)) && (rtfKey == rteKey) ){

//System.log("In keymatch")

matchCount++;

//System.log("Matchcount: " + matchCount);

}

}

}

if(matchCount == respolicyTagElements.keys.length){

matchedIDs.push(reservationPolicy.id);

System.log("MatchedIDs: " + matchedIDs);

reservationPolicyProperties.put(reservationPolicy.id,reservationPolicy.name);

}

}

}

x++;

}

System.log("Found reservation policy: " + matchedIDs);

for each(key in reservationPolicyProperties.keys){

//System.log("ResPolID: " + key + " --> ResPolName: " + prp_ReservationPolicyId_Name.get(key));

reservationPolicyProperties.put(key,reservationPolicyProperties.get(key));

}

return reservationPolicyProperties;

Reply
0 Kudos
DLally
Enthusiast
Enthusiast

I've been able to get this work in vRA 7.5.  I've got my __reservationPolicyID property linked to a custom action.  Based on user input, it allows me to filter what reservations are available to a user with more friendly text like cluster names. 

Reply
0 Kudos
tchristin
Enthusiast
Enthusiast

When you say it must be done at Iaas level, what do you mean by that?

I'm just saying that you need to do some updates in the IaaS database (you Windows SQL Server db) through API.

It's not working with updates at the EBS level with the dedicated property : virtualMachineAddOrUpdateProperties.

Reply
0 Kudos
pedjono
Enthusiast
Enthusiast

Hi DLally

Im using vRA 7.5 and Im facing the same issue..  Can you tell me how you got this too work?

Reply
0 Kudos