4 Replies Latest reply on May 30, 2018 10:01 AM by omrsafetyo

    Suggestions?  Custom Action for determining next available SCSI Bus and Unit Number for new drive

    omrsafetyo Novice

      I wrote a custom Action to get the next available SCSI BUS/Unit Number combo.


      I have VMs that have multiple SCSI controllers.  Some of those controllers have only RDM or physical drives connected.  Others have only flat files connected.  I think this is likely standard, but a controller only has 16 available unit numbers, 0-15.


      My goal was to loop through the current controllers, find one that does not have RDMs, check to see if there is an available Unit Number, and then return the Bus number and Unit number.  This is to be used inside a workflow that will add a disk to a VM.  My goal there is to have the user provide as little input as possible about the the drive they want - just the VM name, the drive letter, and the size of the drive they want.  The drive letter will be assigned in the VM via a Powershell script using a Powershell Host.  I also have a workflow that enumerates the current datastores a VM is in, and finds the best available datastore (datastore that has enough free space with reserve to house the new drive) out of the current datastores - and if the current datastores don't meet that need, it will enumerate all DSs in the DS cluster/StoragePod and find the best match there.


      This is the code for the action for the SCSI Bus and Unit number, and I'm looking for feedback as to what I can change or improve:

      var MAX_UNIT_NUMBER = 15;
      var vmname = vm.name;
      Server.log("Finding next available SCSI Bus and Unit number for " + vm.name );
      var busNumbers = {};
      var devices = vm.config.hardware.device;
      if ( devices = null )  {
          return null;
      // enumerate all the controller devices, and generate an associative array with key = busNumber
      for ( var i in devices )  {
          if ( devices[i] instanceof VcVirtualBusLogicController || devices[i] instanceof VcVirtualLsiLogicController
          || devices[i] instanceof VcParaVirtualSCSIController || devices[i] instanceof VcVirtualLsiLogicSASController )  {
              scsiControllerKey = devices[i].key;
              bus = devices[i];
              busNumber = devices[i].busNumber;
              Server.log( "SCSI controller found. (Key: " + scsiControllerKey + ") Bus Number: " + busNumber );
      busNumbers[scsiControllerKey] = busNumber;
      controllers: for (var key in busNumbers) {
          // this is an array of Unit Numbers that are in use on a particular controller.
          var usedUnitNumbers = [];
          for (var i in devices) {
              if ((devices[i] instanceof VcVirtualDisk) && (devices[i].controllerKey == key)) {
                  var disk = devices[i];
                  var type = disk.backing.compatibilityMode
                  if ( type == 'physicalMode' ) {
                      // we aren't interested in the RDM SCSI Bus - skip this iteration of controllers
                      Server.log("Controller " + key + " has RDMs attached - skipping.");
                      continue controllers;
                  var unitNumber = disk.unitNumber;
                  Server.log("Found virtual disk at unitNumber " + unitNumber);
          // if we made it here, it has disks that are not physicalMode
          var nextUnitNumber = Math.max.apply(Math,usedUnitNumbers) + 1;
          if (nextUnitNumber > MAX_UNIT_NUMBER) {
              Server.log("All units are occupied on Bus " + busNumber);
              nextUnitNumber = null;
           var busNumber = busNumbers[key];
          // we have a controller we can use, and we have available units.  
          // Return the Bus number and the next Unit number
          Server.log(busNumber + ":" + nextUnitNumber);
          BusAndUnit = new Properties();
          return BusAndUnit;