I want to know hoe to override the placement values chosen by vRA when requesting the creation of VMs from a blueprint. Currently, I'm using VRA appliance 6.1.1.0 Build 2216936.
On vRA web console I have successfully created reservations, blueprints and services. I also created a custom vRO workflow, named "Placement Override". In addition, I ran "Assign a state change workflow to a blueprint and its virtual machines" predefined workflow to invoke my "Placement Override" workflow after the Requested phase and before the BuildingMachine phase for one ore more VMs. As a result, the “ExternalWFStubs.BuildingMachine" property was successfully set to the ID of "Placement Override" workflow.
My use case is as follows:
1) From vRA web console, the administrator selects a blueprint from the Service catalog and clicks Request button to request a new VM to be created.
2) My "Placement Override" vRO workflow is invoked, performs some processing and determines several values to be used for each VM requested, such as:
- Virtual Machine name
- Host
- Datastore
- Number of CPUs
- Amount of memory
- Amount of storage
3) I want to be able to override the vRA properties mentioned above for the provisioned VM(s) with the values determined by my vRO workflow. Any examples will be appreciated. Thank you in advance.
Is this something that you want to define programmatically, based on some kind of condition about the machine?
All of these options can be exposed at request time (well, mostly).
Can you explain to me the use case of having this determined by Orchestrator rather than the requester/approver?
Grant
Yes, I want to modify those VM properties programmatically (e.g. Javascript code). The business logic of my custom workflow is as follows:
- it calls a third party appliance controlling the vCentre (e.g. VMTurbo Operations Manager), using REST API, and gets a placement decision from it;
- it compares the third party results (VM settings above) with vRA ones;
- if the VM settings are different, I want to override the vRA ones before the VM gets created.
Hope it helps.
This will be a pretty tough one, the placement decision is all part of the internal app logic.
Thinking through it a bit (bear with me as this isn't something that I've considered before), what you could do is create a Reservation Policy that contains a Reservation from each cluster. All Reservations are set with a priority of 2.
At request time, you query VMturbo, and based on the placement choice make an API call to the associated Reservation to increase it's priority. Provisioning completes, you make the same API call to the same Reservation to move it back to 2.
It seems feasible from a logic process, but don't ask me to write it for you
Day 2 movements will be a problem for you also. You will need to update the reservations in use by a machine if VMturbo decides to relocate them.
Grant
Well, from what I've found out so far, knowing what to set (e.g. VM parameters names) and how to do it (call the right API functions, in proper order, to do the mappings or change properties) is the most challenging part. As a first step, I was able to override the VM name. Before outlining the solution I cam up with, let me briefly describe my workflow and the input/output variables + workflow attributes:
- because I ran "Assign a state change workflow to a blueprint and its virtual machine" to attach "Placement Override" as an end user workflow, I already have access to the following IN parameters:
Parameter Type
vCACVm vCAC:VirtualMachine
vCentreVm VC:VirtualMachine
virtualMachineEntity vCAC:Entity
vCACHost vCAC:VCACHost
vCACVmProperties Properties
- The main workflow contains an inner one, that makes a REST API call to VMTurbo appliance to get back the placement values, such as: Virtual Machine Name, Host Name and Storage Name. It stores these values as output string attributes in "Placement Override" workflow. Let's name these attributes as follows: vmName, hostName, storageName
- After successfully getting the placement values from VMTurbo, I call a script to override the VM settings, as follows:
System.log("Trying to override VM name, host and storage...");
var modelProperties = new Properties();
modelProperties.put("VirtualMachineName", vmName);
modelProperties.put("VMDNSName", vmName);
modelProperties.put("VMTotalMemoryMB", "3072");
modelProperties.put("VMCPUs", "2");
//modelProperties.put("VirtualMachine.Disk0.Storage", storageName); --- Note this is commented out !!!
//modelProperties.put("VirtualMachine.Storage.Name", storageName); -- Note this is commented out !!!
var hostId = virtualMachineEntity.hostId;
var modelName = virtualMachineEntity.modelName;
var entitySetName = virtualMachineEntity.entitySetName;
var entityIdString = virtualMachineEntity.keyString;
System.log("Host Id = " + hostId + ", model name = " + modelName + ", entitySetName = " + entitySetName + "entity ID = " + entityIdString);
var actionResult = System.getModule("com.vmware.library.vcac").updateVCACEntity(hostId, modelName, entitySetName, entityIdString, modelProperties, null, null) ; // model links and headers are NULL
That works fine and the VM name is properly updated. However, if I add the commented out properties (see the notes above) to override the Storage values, the script ends with a NullPointerException.
Also, the values for the VM memory in MB and CPUs (whcih are hardcoded above to 3072 and 2 respectively) show up correctly in vRA web admin (when I go to Items tab and select the newly created VM) but the vSphere client shows the original ones, that were set on vRA web console when I placed the Request (2048 and 1, respectively). So, it seems I need to do more than just setting them as VM properties.
It seems that changing the host name and storage is more challenging than the VM name. I think it involves changing the links and/or headers properties (notice they are passed as null parameters to updateVCACEntity() function) but I couldn't figure out all the pieces, for now. Any help/suggestions will be greatly appreciated.
Thanks in advance,
Alex
This may help, it's possible that there's a warning present for those values that is being escalated to a failure.
https://communities.vmware.com/thread/527999?start=0&tstart=0
May also help, as it's about making sure the storage name you enter is available inside vRA as a resource to provision against.
edit: neither of these answer the problem of the CPU/Memory settings being incorrect. You seem to be updating the reference values for the model, but not at the point where a clonespec(or vm request if this isn't a clone workflow) is being created. So you see the updated variables, but they're not the values that were used to actually create the provisioning action.
The sticking point for you is the host placement. vRA doesn't determine host placement up front as a property:
Grant
PS. Is this within a single cluster or across clusters?
Grant
In the end I managed to set both the ESX host and the data store too. Shortly, the vRO script looks like this:
var vCACMachineEntity = vCACVm.getEntity();
var vCACMachineEntityProperties = vCACMachineEntity.getLink(vCACHost, "VirtualMachineProperties");
System.log("Setting the VM storage to: " + storageName);
addUpdatePropertyFromVirtualMachineEntity(vCACHost, vCACMachineEntity, "VirtualMachine.Disk0.Storage", storageName);
addUpdatePropertyFromVirtualMachineEntity(vCACHost, vCACMachineEntity, "VirtualMachine.Storage.Name", storageName);
System.log("Successfully set the VM storage to: " + storageName);
System.log("Setting the ESX host to: " + hostName);
addUpdatePropertyFromVirtualMachineEntity(vCACHost, vCACMachineEntity, "VirtualMachine.Admin.HostSelectionPolicy", "EXACT_MATCH");
addUpdatePropertyFromVirtualMachineEntity(vCACHost, vCACMachineEntity, "VirtualMachine.Admin.ForceHost", hostName);
System.log("Successfully set the VM host to: " + hostName);
// Adds or updates a property for the input Virtual Machine entity that belongs to the input vCAC Host
function addUpdatePropertyFromVirtualMachineEntity(vCACHost, virtualMachineEntity, propertyName, propertyValue) {
var propertyIsHidden = false;
propertyIsRuntime = false;
propertyIsEncrypted = false;
doNotUpdate = false;
System.getModule("com.vmware.library.vcac").addUpdatePropertyFromVirtualMachineEntity(vCACHost,
virtualMachineEntity,
propertyName,
propertyValue,
propertyIsHidden,
propertyIsRuntime,
propertyIsEncrypted,
doNotUpdate);
}
where:
vCACVm = vCAC:VirtualMachine instance
vCACHost = vCAC:VCACHost instance
storageName = String value
hostName = String value
One important aspect: the ESX Host related properties were added in vRA 6.2 release.
A question to axxel07
Did you add the new workflow in Building Machine stage? And do you mean to say that by just saving the model entity properties, vRA changed the configuration data and provisioned the VM using the new properties?
That's correct, the new workflow was added at BuildingMachine stage. And yes, the VM was provisioned using the new values for: name, data storage and host (physical machine). Again, to override the host you have to use vRA 6.2 version (at least) and the DRS has to be turned OFF for the vCenter cluster or it can be turned ON but not set to Automatic. More details about the host properties can be found at:
vRealize Automation 6.2 Documentation Center
Hope it helps,
Alex