Adding a vNIC to a virtual machine in vRealize Automation Center

I was asked the other day to add 2 nics to a virtual machine. 1 nic had to be an adapter type of E1000 and the other had to be a VMXNET3. The reason behind this was because the VM was being built by PXE and until VMtools was installed as part of the build, the VMXNET3 adapter wouldn’t have been recognised by the build process. I thought that I could just specify the custom properties “VMware.Network.Type”, however this is a global property and applies to all vm nics added at request time and you cannot change the apadter type after you have added a NIC to the vm. So I had to add the additional vNIC at the Machine Provisioned vRA stub workflow stage. I also needed to match the virtual wire that was submitted at request time. That was the challenge and this was how I went around it.

First of all I had to get the virtual wire requested. In this post, I am going to use an example of ‘virtual-wire-001’. I then had to find that virtual wire on the logical switch, or in old ESX terms, the dvSwitch. To do this, I got he host the VM was allocated on, searched for this host in the clusters available, then got the dvSwitch so I could get the dvPortGroup object type.

// get host that is running VM
var vmHost = vcVm.runtime.host.name;

// example name for the virtual wire to look for.
var vNic1Network = "virtual-wire-001 ";

// prepare sdk connection
var sdk = Server.findAllForType("VC:SdkConnection");

// loop through SDK connections
for (var con=0; con < sdk.length; con++){

    // create object of allClusterComputeResources
    var clusters = sdk[con].getAllClusterComputeResources();

     // loop through Clusters in allClusterComputeResources

     for each (var cluster in clusters){
    
        // loop through all hosts in cluster
        for each (var host in cluster.host){
        
            // match vm host to host in cluster
            if (vmHost == host.name){
            
                // get object for cluster
                var vmCluster = clusters;

                // get network object in cluster and match on network name requested
                for each (var dvPortGroup in cluster.network){
                
                    if (dvPortGroup.name.indexOf(vNic1Network) = -1){
                        System.log("Found dvPortGroup object to connect the vNIC to: " + dvPortGroup)};
                        break;
                }
            }
        }
    }
}

What this gave me was a dvPortGroup object that I could use to connect the vNIC to on the virtual machine. Next was to create the vNIC on the virtual machine. Initially, I found this next bit tricky to get my head round, but once I understood the code, it opens up a lot of configuration options not just for adding a vNIC, but also adding other virtual machine configuration specifications:


// creating a config spec
var configSpec = new VcVirtualMachineConfigSpec();
var deviceConfigSpecs = new Array();
var deviceConfigSpec;

// create operation for device config spec
var deviceConfigSpec = new VcVirtualDeviceConfigSpec();
deviceConfigSpec.operation = VcVirtualDeviceConfigSpecOperation.add;

// Create connect info for dvPortgroup
var connectInfo = new VcVirtualDeviceConnectInfo();
connectInfo.allowGuestControl = true;
connectInfo.connected = true;
connectInfo.startConnected = true;

// Create Network BackingInfo
var dvsPortConnection = new VcDistributedVirtualSwitchPortConnection();
var dvSwitch = VcPlugin.convertToVimManagedObject(dvPortGroup, dvPortGroup.config.distributedVirtualSwitch);
dvsPortConnection.switchUuid = dvSwitch.uuid;
dvsPortConnection.portgroupKey = dvPortGroup.key;

var netBackingInfo = new VcVirtualEthernetCardDistributedVirtualPortBackingInfo() ;
netBackingInfo.port = dvsPortConnection;

// Create VirtualNetwork
var vNetwork = new VcVirtualVmxnet3();
vNetwork.backing = netBackingInfo;
vNetwork.unitNumber = 0;
vNetwork.addressType = "Generated";
vNetwork.wakeOnLanEnabled = true;
vNetwork.connectable = connectInfo;

// Creating devicespecs configured in vNetwork object
deviceConfigSpec.device = vNetwork;
deviceConfigSpecs[0] = deviceConfigSpec;

// List of devices
configSpec.deviceChange = deviceConfigSpecs;

// Launch the reconfigVM task
vcVmTask = vcVm.reconfigVM_Task( configSpec );

The key areas in this script are as follows:

// List of devices
configSpec.deviceChange = deviceConfigSpecs;

// Launch the reconfigVM task
vcVmTask = vcVm.reconfigVM_Task( configSpec );

This creates an object that is used to submit the configuration specifications

var configSpec = new VcVirtualMachineConfigSpec();

We then build up this object with various configuration objects that are required. Things like connection information, dvsPortConnection, adapter type settings. Here’s each bit in more info.

For the connection settings, these are quite obvious.

var connectInfo = new VcVirtualDeviceConnectInfo();
connectInfo.allowGuestControl = true;
connectInfo.connected = true;
connectInfo.startConnected = true;

We are basically telling the NIC to be connected at start up and connected by default.

The next was to create the dvsPortConnection settings. Here is where we pass the dvPortGroup object found in the cluster the virtual machine was allocated in.

var dvsPortConnection = new VcDistributedVirtualSwitchPortConnection();
var dvSwitch = VcPlugin.convertToVimManagedObject(dvPortGroup, dvPortGroup.config.distributedVirtualSwitch);
dvsPortConnection.switchUuid = dvSwitch.uuid;
dvsPortConnection.portgroupKey = dvPortGroup.key;

You need to pass in the dvPortGroup object to get the uuid and the key for the dvSiwtch. These values are effectively required to know how to ‘attach’ the vNIC to the dvswitch. If you don’t have these settings, the portgroup will be blank and you will get an invalid backing message, and hence no network connectivity. Once you create this object, you need to add this to the VcVirtualEthernetCardDistributedVirtualPortBackingInfo() object

var netBackingInfo = new VcVirtualEthernetCardDistributedVirtualPortBackingInfo() ;
netBackingInfo.port = dvsPortConnection;

The next section is required to create the VcVirtualVmxnet3 settings. There are different object types for different vNICs. As I needed the vmxnet3 vNIC, I used the VcVirtualVmxnet3() object type. You also have VcVirtualE1000, VcVirtualE1000e, VcVirtualVmxnet2 etc.

var vNetwork = new VcVirtualVmxnet3();
vNetwork.backing = netBackingInfo;
vNetwork.unitNumber = 0;
vNetwork.addressType = "Generated";
vNetwork.wakeOnLanEnabled = true;
vNetwork.connectable = connectInfo;

What we are doing now is adding some of the previously created objects to the VcVirtualVmxnet3 object, for example the netBackingInfo, connectInfo etc. This is making up the profile of the vNIC.

Once we have created the vNIC profile, we just need to execute the object on the vNIC.

// Creating devicespecs configured in vNetwork object
deviceConfigSpec.device = vNetwork;
deviceConfigSpecs[0] = deviceConfigSpec;

// List of devices
configSpec.deviceChange = deviceConfigSpecs;

// Launch the reconfigVM task
vcVmTask = vcVm.reconfigVM_Task( configSpec );

In my vRO workflow, the vcVm is the VC:VirtualMachine object passed in to the stub workflow.

Here’s a look at the workflow:

Screen Shot 2015-02-17 at 20.35.50 1

and here are the input parameters:

Screen Shot 2015-02-17 at 20.36.54

Hope this helps

Advertisements

2 comments

  1. i realize this is a year out but would it be at all possible to provide this workflow as a .workflow file? There are a couple of nuances eluding me. Thank you for your time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s