How to add additional disks with SCSI selection – vRA Cloud / 8.x

Use Case

The customer wanted the ability for the users to dynamically add the additional disks in the request form and had a specific requirement for the disks to be distributed across additional SCSI controllers.

Challenge

vRA Cloud / 8.x provides a native OOB additional disk functionality. However, the challenge is to choose the SCSI controllers for those disks. At the time of writing, this document vRA Cloud did not have this feature exposed. Choosing the SCSI controller for your additional disks is expected to be in 8.4 release (subject to change). vRA Cloud will by default attach all the additional disks on the first controller.

Solution

UPDATED on 02/06/2021

In the vRA Cloud March release, VMware released the SCSI selection as an OOB option for the customers. You can now add the SCSI controller and unit number to a disk in the cloud template YAML. If you are using OOB action the workaround originally written is not required.

resources:
  Disk1:
    type: Cloud.vSphere.Disk
    properties:
      # depending on the size conditionally create the disk (by using the count property)
      count: '${input.diskSize1 == 0 ? 0 : 1}'
      capacityGb: '${input.diskSize1}'
      diskMount: '${input.diskMount1}'
      SCSIController: SCSI_Controller_1
      unitNumber: 1

===============================================================

The only possible solution that I could think of was running an EBS workflow after the disk addition to applying the desired configuration. The solution flow is following :

  1. Add additional disks in cloud template using data grid.
  2. Run EBS post deployment to shutdown VM
  3. Add additional controllers.
  4. Update disks to use additional controllers.
  5. Power On the VM.

Solution Details

Cloud Template for additional disks.

formatVersion: 1
inputs:
  disks:
    type: array
    title: disks
    items:
      title: disk
      type: object
      properties:
        size:
          type: integer
          title: Size
        mountPoint:
          type: string
          title: Mount Point
        vgName:
          type: string
          title: VG Name
        lvName:
          type: string
          title: LV Name
        lvSize:
          type: integer
          title: LV Size
        fsType:
          type: string
          title: FS Type
    maxItems: 15
resources:
  Cloud_Machine_1:
    type: Cloud.Machine
    properties:
      image: centos 7
      flavor: Barjinder-Small
      attachedDisks: '${map_to_object(resource.Cloud_Volume_1[*].id, "source")}'
      networks:
        - network: '${resource.Cloud_vSphere_Network_1.id}'
  Cloud_Volume_1:
    type: Cloud.Volume
    allocatePerInstance: true
    properties:
      capacityGb: '${input.disks[count.index].size}'
      count: '${length(input.disks)}'
      lvName: '${input.disks[count.index].lvName}'
      vgName: '${input.disks[count.index].vgName}'
      lvSize: '${input.disks[count.index].lvSize}'
      fsType: '${input.disks[count.index].fsType }'
      mountPoint: '${input.disks[count.index].mountPoint}'
  Cloud_vSphere_Network_1:
    type: Cloud.vSphere.Network
    properties:
      networkType: existing

Cloud Template

Request Form

Custom Form

EBS

vRO Workflow

I am storing the disk to controller mapping in a JSON in my code. In a production implementatIon, I would use resource elements, abstract the code in actions etc but this is just for a lab-based demo, so the focus is on functionality only.

//Disk distribution on controllers. 
var diskDist = {
    "permittedValues":[
        {
            "controllerKey": "1000",
            "permittedDisks":[1,2,9],
			"diskIndex":0
        },
        {
            "controllerKey": "1001",
            "permittedDisks":[3,4,10],
			"diskIndex":0
        },
        {
            "controllerKey": "1002",
            "permittedDisks":[5,6,11],
			"diskIndex":0
        },
        {
            "controllerKey": "1003",
            "permittedDisks":[7,8,12],
			"diskIndex":0
        }
    ]
}

//Find Controllers and Disks on the VC VM and push to array
var controllers = [];
var disks = []
for each (var device in vcVM.config.hardware.device){
var label = device.deviceInfo.label;
	if (label.indexOf("SCSI controller") != -1) {
		controllers.push(device);
	}
	else if(label.indexOf("Hard disk") != -1) {
		disks.push(device);
	}
}
System.log("Found Controllers : " + controllers.length );
System.log("Found DISKS : " + disks.length);

//Find the number of desired controllers
var desiredControllers;
if (disks.length > 8){
	System.log( "Number of diks are more than 8, setting the number of required controllers to 4")
	desiredControllers = 4;
} else {
	desiredControllers	= Math.round(disks.length/2);
	System.log("Setting required controllers to "+desiredControllers+ " for "+  disks.length+ " disks.");
} 
//Add the controllers.
if(desiredControllers > controllers.length){
	var devConfigSpec= [];
	for (var i = (controllers.length);i<desiredControllers;i++){
	 devConfigSpec.push(System.getModule("pso.vmware.vc.diskSharing").createVirtualScsiControllerConfigSpecDynamicNoBusSharing("LSI",i));
	}
	System.log("devConfigSpec: "+ devConfigSpec.length);
	var configSpec = new VcVirtualMachineConfigSpec();
	configSpec.deviceChange = devConfigSpec;
	var task = vcVM.reconfigVM_Task(configSpec);
	System.getModule("fluffy.util").vim3WaitTaskEnd(task,true,1)
	System.log("task: "+ task.state);
}

//Reconfigure disks on the controllers 
var diskConfigSpecs = []
for (var i= 0;i<disks.length;i++){
	try{
		var diskNumber = (disks[i].deviceInfo.label).slice(10);
		//var diskNumber = (JSON.stringify(disks[i].key).slice(1));
		diskNumber = Number(diskNumber);
		//diskNumber = diskNumber+1;
		System.debug("Processing : "+diskNumber)
		var ary = diskDist.permittedValues.filter(function(e){
			return (e.permittedDisks.indexOf(diskNumber) != -1) 
		});
		
		if((ary[0].controllerKey >1000 )&& (Number(ary[0].controllerKey) != Number(disks[i].controllerKey))){
			System.log("Disk: " + disks[i].deviceInfo.label+"  Disk Controller Key: "+  disks[i].controllerKey+ " JSON COntroller Key: "+ ary[0].controllerKey);
			System.log(" Processing ARY: "+ JSON.stringify(ary));
			var diskConfigSpec = new VcVirtualDeviceConfigSpec();
			diskConfigSpec.device = new VcVirtualDisk;
			diskConfigSpec.device = disks[i];
			diskConfigSpec.device.controllerKey =  ary[0].controllerKey;
			diskConfigSpec.device.unitNumber = ary[0].diskIndex;
			diskConfigSpec.operation = VcVirtualDeviceConfigSpecOperation.edit;
			System.log("Pushing the disk config into array: "+ diskConfigSpec)
			diskConfigSpecs.push(diskConfigSpec);
			//Increase index
			for each (var item in diskDist.permittedValues){
				if(item.controllerKey == ary[0].controllerKey){
					item.diskIndex = item.diskIndex +1;
				}
			}
		}
	} catch (e){
		System.log("ERROR!: "+ e)
	}	
}
if(diskConfigSpecs.length>0){
	System.log("Updating the VM config....");
	var configSpec = new VcVirtualMachineConfigSpec();
	configSpec.deviceChange = diskConfigSpecs;
	task = vcVM.reconfigVM_Task(configSpec);
	System.getModule("fluffy.util").vim3WaitTaskEnd(task,true,1)
	System.log("task: "+ task.state);
} else {
	System.log("Skipping the VM Update. VM already has desired configuration");
}

End result

Additional controllers have been added on the VM and existing disks have been distributed on those controllers as per the desired configuration.

Author: Barjinder Singh

This Post Has 4 Comments

  1. Sonal

    Hi, I am following the same steps for add Disk using vra8.1 , but i get all disk added with the same size of the first disk. So if i have added 3 disks 1,2,3 . all disk are created with size = 1. How did you get this working?

    1. Barjinder Singh

      This solution will work for vRA Cloud at this stage but vRA 8.3 will also support this (don’t take my word as gospel till it’s in the official release notes).

  2. gary

    This looks really good however in vRA 8.3 i am trying to pull the config as you did above from the vcVM entity but i’m not sure how really – would you be able to assist with just that bit? i basically just want to dump all the config items to system log for review. thank you in advance. 🙂

  3. Rahul Kumar

    Hi, If I don’t have access to vRO, How something similar can be achieved via ABX function in vRA 8.1

    Right now, I am using disk array and problem as you know, disks are being assigned in random orders to vCenter / in guestOS.

Leave a Reply