VMware Cloud Community
rkrichevskiy
Enthusiast
Enthusiast
Jump to solution

Convert Catalog resource to Virtual Machine

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.

1 Solution

Accepted Solutions
Burke-
VMware Employee
VMware Employee
Jump to solution

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...)

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you!

Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator
for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter

View solution in original post

11 Replies
qc4vmware
Virtuoso
Virtuoso
Jump to solution

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;

rkrichevskiy
Enthusiast
Enthusiast
Jump to solution

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:

  1. provide vCACCAFE:CatalogResource as input param.
  2. Get vCACCAFE:CatalogResource name prop.
  3. Pass VM name string to "Get virtual Machines by name" as criteria to match.
  4. Check for too-many or null array elements in the response.
  5. Grab a match and set it as output.

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)?

Burke-
VMware Employee
VMware Employee
Jump to solution

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...)

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you!

Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator
for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter
qc4vmware
Virtuoso
Virtuoso
Jump to solution

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 Smiley Wink

0 Kudos
Burke-
VMware Employee
VMware Employee
Jump to solution

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.

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you!

Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator
for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter
rkrichevskiy
Enthusiast
Enthusiast
Jump to solution

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.

qc4vmware
Virtuoso
Virtuoso
Jump to solution

How often do you teach your master class?  I'd love to attend one or are they available online?

0 Kudos
BillStreet00
Enthusiast
Enthusiast
Jump to solution

Has anyone tried to convert a string to a Vc:SdkConnection? 

0 Kudos
tschoergez
Leadership
Leadership
Jump to solution

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)

0 Kudos
BillStreet00
Enthusiast
Enthusiast
Jump to solution

Since I only have one vCenter at this time I went with var allConnections = VcPlugin.allSdkConnections[0].

0 Kudos
sivakumarss
Enthusiast
Enthusiast
Jump to solution

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

0 Kudos