VMware Cloud Community
craigso
Enthusiast
Enthusiast

Get network profile associated with Network Adapter?

Hello!

We are trying to improve our OS provision blueprint by retrieving and presenting some additional details for selected networks. This would be things like, grabbing a friendly name from our IPAM, get number of free IPs in the range, etc.

Right now we are using the getApplicableNetworks action to populate a drop down on our blueplrint. This works great but it displays a somewhat unfriendly name. This is not a deal breaker. But what I'm trying to figure our is how I can get an associated network profile for the selected network adapter?

In my mind, I'd like to use the network adapter as an input, lookup the business group association, then look at the network profile. Our network profiles only contain one IP range. Once I have the network profile, I can use this to retrieve details on the range and then return those to display in the blueprint. Most likely will be using custom forms to do some of this work.

Am I on the right track here? Should I be thinking about this different to achieve similar results?

11 Replies
daphnissov
Immortal
Immortal

I think you're going to have to copy and then modify this action to get the results you want. I don't really see any other good way than that. At least then you have a new, single Action bundled up which encapsulates all that logic to your forms without having it fragmented across lots of smaller pieces here and there.

0 Kudos
craigso
Enthusiast
Enthusiast

I've made a bit of progress on this. But I hit a snag.

First off, I've managed to grab the network profile from the Network Adapter but doing the following:

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

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

var count = 0;

for each(var res in reservations) {

     var extensionData = res.getExtensionData();

     var keys = extensionData.keySet();

     var networks = extensionData.get("reservationNetworks");

     if(networks) {

          for each(var network in networks.getValue()) {

               var path = network.getValue().get("networkPath");

               var profile = network.getValue().get("networkProfile");

              

               System.log(path.label);

               System.log(profile.label);

          }

     }

}

}

}

Now that I have the Network Adapter and associated network profile, I'd like to l pull information about the range in the profile. Specifically name and description.

pastedImage_7.png

I believe I found some sample code to do this from: Get vCAC Network Ranges - Samples - VMware {code}

//Name: getNetworkRanges

//Description: Used to get all network ranges from a given vCAC IaaS Host

//Inputs: vcacHost [vCAC:VCACHost]

//Return Type: string

//Initialize Array or JSON

var networkRanges = [];

var netRanges = vCACEntityManager.readModelEntitiesBySystemExpandQuery(vcacHost.id,"ManagementModelEntities.svc","StaticIPv4Ranges",null,'StaticIPv4NetworkProfile/ID',null,null,null,null,null);

for each (netRange in netRanges){

//Create JSON Object

var networkRange = {};

networkRange["name"] = netRange.getProperties().get("StaticIPv4RangeName");

networkRange["rangeDescription"] = netRange.getProperties().get("IPv4RangeDescription");

networkRange["networkProfileId"] = netRange.getLink(vcacHost, "StaticIPv4NetworkProfile")[0].getProperties().get("ID");; //Gets the id from a forien key in StaticIPv4NetworkProfile

networkRange["rangeId"] = netRange.getProperties().get("ID");

networkRange["rangeState"] = netRange.getProperties().get("StaticIPv4State");

networkRange["externalId"] = netRange.getProperties().get("ExternalId");

networkRanges.push(networkRange);

}

return JSON.stringify(networkRanges,null,4)

However this errors out on line 11 with:

[2019-04-23 09:20:36.343] [E] Error in (Workflow:getNetworkRanges / Scriptable task (item1)#8) java.lang.NullPointerException

[2019-04-23 09:20:36.353] [E] Workflow execution stack:

***

item: 'getNetworkRanges/item1', state: 'failed', business state: 'null', exception: 'java.lang.NullPointerException (Workflow:getNetworkRanges / Scriptable task (item1)#8)'

workflow: 'getNetworkRanges' (56d543d8-ae41-4f2f-8467-7259aa369840)

|  'attribute': name=vcacHost type=vCACCAFE:VCACHost value=dunes://service.dunes.ch/CustomSDKObject?id='0420c0c0-0fad-49ec-9666-4383cae8e70a'&dunesName='vCACCAFE:VCACHost'

|  'no inputs'

|  'no outputs'

*** End of execution stack.

I am passing my vCAC host into vcacHost. Everything else is the same as the sample code.

pastedImage_11.png

Am I overlooking something?

0 Kudos
craigso
Enthusiast
Enthusiast

Also should note, we are running vRA 7.5.

0 Kudos
xian_
Expert
Expert

What do you have in line #8 ?

0 Kudos
craigso
Enthusiast
Enthusiast

Edited my initial response as I misunderstood your question.

Line 8 of the script I ran is line 11 posted above:

var netRanges = vCACEntityManager.readModelEntitiesBySystemExpandQuery(vcacHost.id,"ManagementModelEntities.svc","StaticIPv4Ranges",null,'StaticIPv4NetworkProfile/ID',null,null,null,null,null);

0 Kudos
xian_
Expert
Expert

The problem is that you're expecting an input of the type vCACCAFE:VCACHost. This is the vRA server, but you need the IaaS server instead, type vCAC:VCACHost. The Model Entity is running on this Windows machine.

You need to add your IaaS server to the vRO inventory (if you have not done so) by running Library/vRealize Automation/Configuration/Add the IaaS host of a vRA host workflow. Once added, re-run your code with the correct input type and select the IaaS server as input.

See the excellent series on Entities by Gavin Stephens at https://www.simplygeek.co.uk/vra-developer-master-series/

Although deprecated, the iaas-proxy-provider api should be easier to use: Get a Network Profile List Example 

craigso
Enthusiast
Enthusiast

Thank you!

I should have know, I mean its specified in the notes of the script. I changed the type and specified the correct input and it works as expected.

Thanks for the links, I'll check those out now.

0 Kudos
craigso
Enthusiast
Enthusiast

I'm happy to report I was able to re-write getApplicableNetworks to display a more friendly strings on the dropdown. Since this forum has been so helpful I'm happy to post for others to get ideas from. This is not a truly portable script as there are likely references to environmental specific resources. I'll also attach it as the formatting will likely get munched a bit.

/* Todo: If more than one IaaS host is present, select the default. var vcacHosts = Server.findAllForType("vCAC:VCACHost");

*/

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

///////////////////////////////////////////////////Functions///////////////////////////////////////////////////

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

function getNetworkRangesFromReservation() {

/* This function grabs network ranges from reservations associated with the user who called the action. It then returns an array of network range

   objects that includes details of those ranges.

  

Example returned data for one single range: (In some cases there be multiple network range objects in the array.)

   [{

      "name": "10.128.191.224/28",

  "rangeDescription": "IS_VRA_TEST3",

  "networkProfileId": "d5aa4841-3b86-49f3-9ddf-c6033db3a52c",

  "rangeId": "bfb18c99-c2d8-45fd-8a94-aa29f27ff3c9",

  "rangeState": 1,

  "externalId": "10.128.191.224/28"

  }]

*/

var networkRanges = [];

var countRanges = 0;

// Inputs: vcacHost [vCAC:VCACHost] 

// readModelEntitiesBySystemExpandQuery(String hostId, String modelName, String entitySetName, String filter, String expand, String orderBy, String select, int top, int skip, Properties headers)

var netRanges = vCACEntityManager.readModelEntitiesBySystemExpandQuery(vcacHosts[0].id,"ManagementModelEntities.svc","StaticIPv4Ranges",null,'StaticIPv4NetworkProfile/ID',null,null,null,null,null);

for each (netRange in netRanges){

// Create Object and push to array

countRanges++;

var networkRange = {};

networkRange["name"] = netRange.getProperties().get("StaticIPv4RangeName");

networkRange["rangeDescription"] = netRange.getProperties().get("IPv4RangeDescription");

networkRange["networkProfileId"] = netRange.getLink(vcacHosts[0], "StaticIPv4NetworkProfile")[0].getProperties().get("ID");; //Gets the id from a forien key in StaticIPv4NetworkProfile

networkRange["rangeId"] = netRange.getProperties().get("ID");

networkRange["rangeState"] = netRange.getProperties().get("StaticIPv4State");

networkRange["externalId"] = netRange.getProperties().get("ExternalId");

networkRanges.push(networkRange);

}

System.debug("Number of network profiles found:" + countRanges);

System.debug("Returning raw network range data:");

System.debug(JSON.stringify(networkRanges, null,' '));

return networkRanges;

}

function getExternalIdAndDescription(name){

// getExternalIdAndDescription takes in a network profile name (string) and returns am object that include range external ID and range description as defined in Netdot.

// These values are pulled from Netdot when the range is initially configured. If the details of the range get updated in netdot, simply navigate to the range in vRA

// open it. It will make the call to Netdot automatically and update the record.

// Get the network ranges from the reservation

var networkRanges = getNetworkRangesFromReservation();

System.debug("Number of ranges found: " + networkRanges.length);

System.debug("Name parameter: " + name);

for(var i = 0 ; i < networkRanges.length ; i++ ) {

// loop though the returned ranges until a match is found, then return an object containing externalId and rangeDescription. These values coorelate to values found in Netdot.

if(networkRanges[i].name == name) {

System.debug(name + " = " + networkRanges[i].externalId);

System.debug(name + " = " + networkRanges[i].rangeDescription);

/* Example of returned data:

   {

      "externalId": "10.128.191.224/28",

  "rangeDescription": "IS_VRA_TEST3"

   }

*/

return {externalId:networkRanges[i].externalId,rangeDescription:networkRanges[i].rangeDescription};

}

}

// If we fall out of the loop without a successful match throw error

throw "externalId with name: " + name + " was not found!";

}

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

////////////////////////////////////////////////   Main   /////////////////////////////////////////////////////

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

System.log("Blueprint: " + blueprint);

System.log("ComponentID: " + component);

System.log("requestedFor: " + user);

System.log("tenantRef: " + tenant);

System.log("sybtenantRef: " + subtenantId);

// Find all IaaS hosts. Change this later to add logic to select only the DEFAULT host

var vcacHosts = Server.findAllForType("vCAC:VCACHost");

System.log(vcacHosts);

// Checks if the default host is already added and returns it.

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

// Get reservations for the user

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

var count = 0;

var applicableNetworks = new Properties();

for each(var res in reservations) {

count++;

var extensionData = res.getExtensionData();

var keys = extensionData.keySet();

var networks = extensionData.get("reservationNetworks");

if(networks) {

for each(var network in networks.getValue()) {

var path = network.getValue().get("networkPath");

var profile = network.getValue().get("networkProfile");

var rangeObj = getExternalIdAndDescription(profile.label);

System.debug(JSON.stringify(rangeObj, null, ' '));

applicableNetworks.put(path.label, rangeObj.externalId + " - " + rangeObj.rangeDescription);

System.log(path.label + " - " + rangeObj.externalId + " - " + rangeObj.rangeDescription);

}

}

System.debug("Number of Reservations: " + count);

}

return applicableNetworks;

craigso
Enthusiast
Enthusiast

The last remaining todo is to handle multiple IaaS hosts if returned from:

var vcacHosts = Server.findAllForType("vCAC:VCACHost")

Ideally I just want to select the default IaaS host and use it. In our environment we only have one IaaS host, but I don't want the script to break if another one gets added in the future.

Is there a way to simply select the default? or do I need to write logic to enumerate through vcacHosts and return the default?

0 Kudos
qc4vmware
Virtuoso
Virtuoso

I've used a configuration element to set the default host.  I don't know of any way to programmatically get that.  If you tag a default vCACCAFE:VCACHost it changes the name property to "Default" and the displayName property to "Default [whatever the original name was when you added it]" so its easy to identify that.  I also use a configuration element though to hold that value as I've liked being able to easily coax my workflows to interact with the endpoints I want without needing to run the configuration workflows.  Most of the time I never have more than one of each defined but in my lab and other test environments I do occasionally.

Paul

craigso
Enthusiast
Enthusiast

Thanks for mentioning this! I started researching configuration elements after your post. This helped me solve a few other issues I was having. I haven't quite got the default IaaS server bit fixed, but I have added it to my list of things to do.

0 Kudos