10 Replies Latest reply on Oct 16, 2019 7:38 PM by pedjono

    How to set reservation policy with Event Broker

    rstoker13 Enthusiast
    VMware Employees

      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

        • 1. Re: How to set reservation policy with Event Broker
          michael_stefani 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

          • 2. Re: How to set reservation policy with Event Broker
            sbeaver Guru
            vExpertUser Moderators

            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:

             

             

             

            • 3. Re: How to set reservation policy with Event Broker
              tchristin Novice

              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.

              • 4. Re: How to set reservation policy with Event Broker
                sbeaver Guru
                vExpertUser Moderators

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

                • 5. Re: How to set reservation policy with Event Broker
                  tchristin Novice

                  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.

                  • 6. Re: How to set reservation policy with Event Broker
                    DLally 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.

                    • 7. Re: How to set reservation policy with Event Broker
                      AnotherPassword Novice

                      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;

                      • 8. Re: How to set reservation policy with Event Broker
                        DLally 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. 

                         

                         

                         

                        • 9. Re: How to set reservation policy with Event Broker
                          tchristin Novice

                          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.

                          • 10. Re: How to set reservation policy with Event Broker
                            pedjono Novice

                            Hi DLally

                             

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