I am getting accustomed with vRA types and wanted to get a hint on object conversion approach. Is there a simple way to convert from vCACCAFE:CatalogResource type to VC:VirtualMachine? Preferably without using findAllForType and looping through to find a match.
I see that vCAC resource catalog object has property resourceData which may have useful references to identify vc:virtualmachine. But I am not quite sure how to retrieve details like vm id.
Wow, what timing! I am teaching a vRO Master class this week and a question about CatalogResource came up yesterday so I was playing with this object yesterday. After seeing this post, I did a bit more testing and adjustments to my code to fit your request. I've cleaned up the code to a point where you can use this as an action:
Input: vraVm (vCACCAFE:CatalogResource)
Output: VC:VirtualMachine
Script:
var data = vraVm.resourceData; // vCACCAFELiteralMap
// Retrieve the vCenter instanceUuid from the resourceData:
var vcID = data.get("endpointExternalReferenceId").value;
// Get all SDKConnections (just in case we have more than one vCenter
var vcConns = VcPlugin.allSdkConnections;
for each (conn in vcConns){
// Make sure we set "vc" to the vCenter connection that matches the resourceData endpointExternalReferenceId
if (conn.about.instanceUuid == vcID){
var vc = conn;
}
}
if (vc){
// Retreive the Managed Object Reference (MoRef) stored in the EXTERNAL_REFERENCE_ID of the resourceData
var vmMoRef = data.get("EXTERNAL_REFERENCE_ID").value;
// Preferred method:
var managedObject = new VcManagedObjectReference();
managedObject.type = "VirtualMachine";
managedObject.value = vmMoRef;
var vm = VcPlugin.convertToVimManagedObject(vc , managedObject);
// alternate method:
//var XPath = "xpath:id='"+vmMoRef+"'";
// Now, find the vm in our vCenter that has the matching MoRef:
//var vm = vc.getAllVirtualMachines(null, XPath)[0];
if (vm){
System.debug("Success! Found VM: "+vm.name);
return vm;
}else{
System.warn("Warning! VM NOT FOUND with moref "+vmMoRef);
}
}else{
System.warn("Warning! vCenter Connection not found with ID: " + vcID);
}
Hope this helps !
Here's an example of the output I get:
[2017-05-10 09:09:55.471] [D] Testing - External Reference: vm-494
[2017-05-10 09:09:55.536] [D] Success! Found VM: dev-015
I'm attaching a package that has this script as an Action, a workflow that uses the action, and a test workflow that I used to discover how to extract the data.
NOTE: July 11th, 2017 - Attached package now includes a test workflow that gets the VC:VirtualMachines from a Deployment (vCACCAFE:CatalogResource object - same as the children! kinda silly, but there it is...)
I don't know if things have changed in version 7.x as we have not yet updated we are still on 6.2.5 but I struggled with this for a while. One way you can do it is to first get the vCAC:VirtualMachine then from there get the vCenter VM. The catalog resource has a property in getProviderBinding().getBindingId() . The binding ID = vCAC:VirtualMachine.virtualMachineID. The only way I have been able to look this up is by looping which you are trying to avoid. If you simply look up the vCACVm by name which generally match then you can look up the vCenterVm by the uuid. This code will get the vCACVm from the catalog resource.
var bindingID = catalogResource.getProviderBinding().getBindingId();
var vCACVms = Server.findAllForType("vCAC:VirtualMachine");
var matches = [];
for each (var vCACVm in vCACVms) {
if (vCACVm.virtualMachineID === bindingID) {
System.log("Resolved vCAC VM: " + vCACVm.virtualMachineName);
matches.push(vCACVm);
}
}
System.log(matches.length + " match bindingID: " + bindingID);
if (matches.length > 1 ) throw "Too many matches for bindingID: " + bindingID + ", there can be only one!";
return matches[0];
Once you have that you can get the vCenterVm from the vCACVm like this:
var sdkConnections = VcPlugin.allSdkConnections;
var vCenterVm = null;
for each (var sdkConnection in sdkConnections) {
try {
vCenterVm = sdkConnection.searchIndex.findByUuid(null, vCACVm.vmUniqueID, true, true);
} catch(e) {
System.log("Unable to find VM by instance UUID :"+vCACVm.vmUniqueID+", for SDK connection " + sdkConnection.name + ", will fallback to search by BIOS UUID, reason : " + e);
try {
vCenterVm = sdkConnection.searchIndex.findByUuid(null, vCACVm.vmUniqueID, true, false);
} catch(e) {
System.log("Unable to find VM by BIOS UUID :"+vCACVm.vmUniqueID+", for SDK connection " + sdkConnection.name + ", reason : " + e);
}
}
if (vCenterVm != null) {
System.log("Resolved vCenter VM " + vCenterVm.name);
break;
}
}
return vCenterVm;
Thanks qc! I'll keep these snippets for future reference to see if this approach provides any search performance improvement. Basically this is my primary concern - how fast these loop search routines will run. Right now the environment is pretty much bare and looping through a handful of entries is ok. But as environment grows this approach may no longer be feasible.
What I already have is a conversion using VM name strings. I admit that your example sounds more robust in terms of finding exact match by IDs rather than VM names. For what its worth here is what I got - I used OOTB workflow "Get virtual Machines by name" to base the routine on. So the sequence is:
Which leads me to a follow up question, of course if you have any feedback to offer. I noticed that there are areas where vRA plugins present overlapping information, i.e. VM entries for our examples to convert from vRA VM object to vCenter VM. In your experience with vRO/vRA integration, is it preferred to use objects from vCAC (vRealize Automation Center Infrastructure Administration plug-in for vRealize Orchestrator) or vCACCAFE (vRealize Automation plug-in for vRealize Orchestrator)?
Wow, what timing! I am teaching a vRO Master class this week and a question about CatalogResource came up yesterday so I was playing with this object yesterday. After seeing this post, I did a bit more testing and adjustments to my code to fit your request. I've cleaned up the code to a point where you can use this as an action:
Input: vraVm (vCACCAFE:CatalogResource)
Output: VC:VirtualMachine
Script:
var data = vraVm.resourceData; // vCACCAFELiteralMap
// Retrieve the vCenter instanceUuid from the resourceData:
var vcID = data.get("endpointExternalReferenceId").value;
// Get all SDKConnections (just in case we have more than one vCenter
var vcConns = VcPlugin.allSdkConnections;
for each (conn in vcConns){
// Make sure we set "vc" to the vCenter connection that matches the resourceData endpointExternalReferenceId
if (conn.about.instanceUuid == vcID){
var vc = conn;
}
}
if (vc){
// Retreive the Managed Object Reference (MoRef) stored in the EXTERNAL_REFERENCE_ID of the resourceData
var vmMoRef = data.get("EXTERNAL_REFERENCE_ID").value;
// Preferred method:
var managedObject = new VcManagedObjectReference();
managedObject.type = "VirtualMachine";
managedObject.value = vmMoRef;
var vm = VcPlugin.convertToVimManagedObject(vc , managedObject);
// alternate method:
//var XPath = "xpath:id='"+vmMoRef+"'";
// Now, find the vm in our vCenter that has the matching MoRef:
//var vm = vc.getAllVirtualMachines(null, XPath)[0];
if (vm){
System.debug("Success! Found VM: "+vm.name);
return vm;
}else{
System.warn("Warning! VM NOT FOUND with moref "+vmMoRef);
}
}else{
System.warn("Warning! vCenter Connection not found with ID: " + vcID);
}
Hope this helps !
Here's an example of the output I get:
[2017-05-10 09:09:55.471] [D] Testing - External Reference: vm-494
[2017-05-10 09:09:55.536] [D] Success! Found VM: dev-015
I'm attaching a package that has this script as an Action, a workflow that uses the action, and a test workflow that I used to discover how to extract the data.
NOTE: July 11th, 2017 - Attached package now includes a test workflow that gets the VC:VirtualMachines from a Deployment (vCACCAFE:CatalogResource object - same as the children! kinda silly, but there it is...)
Much better than my method! Will this work for both vRA 6 and 7? I guess I can just try it but I figured I'd ask
Honestly, I have no Idea Paul... I no longer keep any vRA 6 environments around. That code was created/tested in vRA 7.2 and 7.3 GA.
This is great, Burke! I see now how to properly access values returned by the resourceData. This does exactly what I needed and will be a very helpful example. I appreciate your help with this.
How often do you teach your master class? I'd love to attend one or are they available online?
Has anyone tried to convert a string to a Vc:SdkConnection?
How does your string look like?
You have to "search" for it in the inventory.
Get all sdkConnections using
var allConnections = VcPlugin.allSdkConnections;
then you can loop through and compare e.g. name or url or instanceUuid to your string (depending what's in the string)
Since I only have one vCenter at this time I went with var allConnections = VcPlugin.allSdkConnections[0].
Now is there a method to do the reverse?
My requirement is to capture all VM information per Vsphere vcenter. If the VM is provisioned using VRA then I should get some information from that.
So, any method to convert VcVM to CatalogResource? Thanks