Repository: cloudstack
Updated Branches:
  refs/heads/vmware-disk-controllers 06d4458d0 -> a4cc987a6


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a4cc987a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
----------------------------------------------------------------------
diff --git 
a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java 
b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 5f180e1..35878d6 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -55,12 +55,15 @@ import com.vmware.vim25.OptionValue;
 import com.vmware.vim25.OvfCreateDescriptorParams;
 import com.vmware.vim25.OvfCreateDescriptorResult;
 import com.vmware.vim25.OvfFile;
+import com.vmware.vim25.ParaVirtualSCSIController;
 import com.vmware.vim25.PropertyFilterSpec;
 import com.vmware.vim25.PropertySpec;
 import com.vmware.vim25.TraversalSpec;
+import com.vmware.vim25.VirtualBusLogicController;
 import com.vmware.vim25.VirtualCdrom;
 import com.vmware.vim25.VirtualCdromIsoBackingInfo;
 import com.vmware.vim25.VirtualCdromRemotePassthroughBackingInfo;
+import com.vmware.vim25.VirtualController;
 import com.vmware.vim25.VirtualDevice;
 import com.vmware.vim25.VirtualDeviceBackingInfo;
 import com.vmware.vim25.VirtualDeviceConfigSpec;
@@ -80,6 +83,7 @@ import 
com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
 import com.vmware.vim25.VirtualHardwareOption;
 import com.vmware.vim25.VirtualIDEController;
 import com.vmware.vim25.VirtualLsiLogicController;
+import com.vmware.vim25.VirtualLsiLogicSASController;
 import com.vmware.vim25.VirtualMachineCloneSpec;
 import com.vmware.vim25.VirtualMachineConfigInfo;
 import com.vmware.vim25.VirtualMachineConfigOption;
@@ -97,7 +101,6 @@ import 
com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
 import com.vmware.vim25.VirtualMachineRuntimeInfo;
 import com.vmware.vim25.VirtualMachineSnapshotInfo;
 import com.vmware.vim25.VirtualMachineSnapshotTree;
-import com.vmware.vim25.VirtualPCIController;
 import com.vmware.vim25.VirtualSCSIController;
 import com.vmware.vim25.VirtualSCSISharing;
 
@@ -1083,6 +1086,130 @@ public class VirtualMachineMO extends BaseMO {
             s_logger.trace("vCenter API trace - createDisk() 
done(successfully)");
     }
 
+    public void updateVmdkAdapter(String vmdkFileName, String newAdapterType) 
throws Exception {
+        Pair<VmdkFileDescriptor, byte[]> vmdkInfo = 
getVmdkFileInfo(vmdkFileName);
+        VmdkFileDescriptor vmdkFileDescriptor = vmdkInfo.first();
+        boolean isVmfsSparseFile = vmdkFileDescriptor.isVmfsSparseFile();
+        if (!isVmfsSparseFile) {
+            String currentAdapterType = vmdkFileDescriptor.getAdapterType();
+            if (!currentAdapterType.equalsIgnoreCase(newAdapterType)) {
+                s_logger.info("Updating adapter type to " + newAdapterType + " 
for VMDK file " + vmdkFileName);
+                Pair<DatacenterMO, String> dcInfo = getOwnerDatacenter();
+                byte[] newVmdkContent = 
vmdkFileDescriptor.changeVmdkAdapterType(vmdkInfo.second(), newAdapterType);
+                String vmdkUploadUrl = 
getContext().composeDatastoreBrowseUrl(dcInfo.first().getName(), vmdkFileName);
+                getContext().uploadResourceContent(vmdkUploadUrl, 
newVmdkContent);
+                s_logger.info("Updated VMDK file " + vmdkFileName);
+            }
+        }
+    }
+
+    public void updateAdapterTypeIfRequired(String vmdkFileName) throws 
Exception {
+        // Validate existing adapter type of VMDK file. Update it with a 
supported adapter type if validation fails.
+        Pair<VmdkFileDescriptor, byte[]> vmdkInfo = 
getVmdkFileInfo(vmdkFileName);
+        VmdkFileDescriptor vmdkFileDescriptor = vmdkInfo.first();
+
+        boolean isVmfsSparseFile = vmdkFileDescriptor.isVmfsSparseFile();
+        if (!isVmfsSparseFile) {
+            String currentAdapterTypeStr = vmdkFileDescriptor.getAdapterType();
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace("Detected adapter type  " + 
currentAdapterTypeStr + " for VMDK file " + vmdkFileName);
+            }
+            VmdkAdapterType currentAdapterType = 
VmdkAdapterType.getType(currentAdapterTypeStr);
+            if (currentAdapterType == VmdkAdapterType.none) {
+                // Value of currentAdapterType can be VmdkAdapterType.none 
only if adapter type of vmdk is set to either
+                // lsisas1068 (SAS controller) or pvscsi (Vmware Paravirtual) 
only. Valid adapter type for those controllers is lsilogic.
+                // Hence use adapter type lsilogic. Other adapter types ide, 
lsilogic, buslogic are valid and does not need to be modified.
+                VmdkAdapterType newAdapterType = VmdkAdapterType.lsilogic;
+                s_logger.debug("Updating adapter type to " + newAdapterType + 
" from " + currentAdapterTypeStr + " for VMDK file " + vmdkFileName);
+                Pair<DatacenterMO, String> dcInfo = getOwnerDatacenter();
+                byte[] newVmdkContent = 
vmdkFileDescriptor.changeVmdkAdapterType(vmdkInfo.second(), 
newAdapterType.toString());
+                String vmdkUploadUrl = 
getContext().composeDatastoreBrowseUrl(dcInfo.first().getName(), vmdkFileName);
+
+                getContext().uploadResourceContent(vmdkUploadUrl, 
newVmdkContent);
+                s_logger.debug("Updated VMDK file " + vmdkFileName);
+            }
+        }
+    }
+
+    public void attachDisk(String[] vmdkDatastorePathChain, 
ManagedObjectReference morDs, String diskController) throws Exception {
+
+        if(s_logger.isTraceEnabled())
+            s_logger.trace("vCenter API trace - attachDisk(). target MOR: " + 
_mor.getValue() + ", vmdkDatastorePath: "
+                            + new Gson().toJson(vmdkDatastorePathChain) + ", 
datastore: " + morDs.getValue());
+        int controllerKey = 0;
+        int unitNumber = 0;
+
+        if (DiskControllerType.getType(diskController) == 
DiskControllerType.ide) {
+            // IDE virtual disk cannot be added if VM is running
+            if (getPowerState() == VirtualMachinePowerState.POWERED_ON) {
+                throw new Exception("Adding a virtual disk over IDE controller 
is not supported while VM is running in VMware hypervisor. Please re-try when 
VM is not running.");
+            }
+            // Get next available unit number and controller key
+            int ideDeviceCount = getNumberOfIDEDevices();
+            if (ideDeviceCount >= VmwareHelper.MAX_IDE_CONTROLLER_COUNT * 
VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER) {
+                throw new Exception("Maximum limit of  devices supported on 
IDE controllers [" + VmwareHelper.MAX_IDE_CONTROLLER_COUNT
+                        * VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER + "] 
is reached.");
+            }
+            controllerKey = getIDEControllerKey(ideDeviceCount);
+            unitNumber = getFreeUnitNumberOnIDEController(controllerKey);
+        } else {
+            controllerKey = getScsiDiskControllerKey(diskController);
+            unitNumber = -1;
+        }
+        synchronized (_mor.getValue().intern()) {
+            VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, null, 
controllerKey, vmdkDatastorePathChain, morDs, unitNumber, 1);
+            controllerKey = newDisk.getControllerKey();
+            unitNumber = newDisk.getUnitNumber();
+            VirtualDiskFlatVer2BackingInfo backingInfo = 
(VirtualDiskFlatVer2BackingInfo)newDisk.getBacking();
+            String vmdkFileName = backingInfo.getFileName();
+            DiskControllerType diskControllerType = 
DiskControllerType.getType(diskController);
+            VmdkAdapterType vmdkAdapterType = 
VmdkAdapterType.getAdapterType(diskControllerType);
+            if (vmdkAdapterType == VmdkAdapterType.none) {
+                String message = "Failed to attach disk due to invalid vmdk 
adapter type for vmdk file [" +
+                    vmdkFileName + "] with controller : " + diskControllerType;
+                s_logger.debug(message);
+                throw new Exception(message);
+            }
+            updateVmdkAdapter(vmdkFileName, vmdkAdapterType.toString());
+            VirtualMachineConfigSpec reConfigSpec = new 
VirtualMachineConfigSpec();
+            VirtualDeviceConfigSpec deviceConfigSpec = new 
VirtualDeviceConfigSpec();
+
+            deviceConfigSpec.setDevice(newDisk);
+            
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+            reConfigSpec.getDeviceChange().add(deviceConfigSpec);
+
+            ManagedObjectReference morTask = 
_context.getService().reconfigVMTask(_mor, reConfigSpec);
+            boolean result = _context.getVimClient().waitForTask(morTask);
+
+            if (!result) {
+                if (s_logger.isTraceEnabled())
+                    s_logger.trace("vCenter API trace - attachDisk() 
done(failed)");
+                throw new Exception("Failed to attach disk due to " + 
TaskMO.getTaskFailureInfo(_context, morTask));
+            }
+
+            _context.waitForTaskProgressDone(morTask);
+        }
+
+        if(s_logger.isTraceEnabled())
+            s_logger.trace("vCenter API trace - attachDisk() 
done(successfully)");
+    }
+
+    private int getControllerBusNumber(int controllerKey) throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof VirtualController && device.getKey() == 
controllerKey) {
+                    return ((VirtualController)device).getBusNumber();
+                }
+            }
+        }
+        throw new Exception("SCSI Controller with key " + controllerKey + " is 
Not Found");
+
+    }
+
     public void attachDisk(String[] vmdkDatastorePathChain, 
ManagedObjectReference morDs) throws Exception {
 
         if (s_logger.isTraceEnabled())
@@ -1753,11 +1880,16 @@ public class VirtualMachineMO extends BaseMO {
 
     public GuestOsDescriptor getGuestOsDescriptor(String guestOsId) throws 
Exception {
         GuestOsDescriptor guestOsDescriptor = null;
-        ManagedObjectReference vmEnvironmentBrowser = 
_context.getVimClient().getMoRefProp(_mor, "environmentBrowser");
+        String guestId = guestOsId;
+        if (guestId == null) {
+            guestId = getGuestId();
+        }
+        ManagedObjectReference vmEnvironmentBrowser =
+                _context.getVimClient().getMoRefProp(_mor, 
"environmentBrowser");
         VirtualMachineConfigOption vmConfigOption = 
_context.getService().queryConfigOption(vmEnvironmentBrowser, null, null);
         List<GuestOsDescriptor> guestDescriptors = 
vmConfigOption.getGuestOSDescriptor();
         for (GuestOsDescriptor descriptor : guestDescriptors) {
-            if (guestOsId != null && 
guestOsId.equalsIgnoreCase(descriptor.getId())) {
+            if (guestId != null && 
guestId.equalsIgnoreCase(descriptor.getId())) {
                 guestOsDescriptor = descriptor;
                 break;
             }
@@ -1896,6 +2028,134 @@ public class VirtualMachineMO extends BaseMO {
         }
     }
 
+    public int getPvScsiDeviceControllerKeyNoException() throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof ParaVirtualSCSIController) {
+                    return device.getKey();
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    public int getPvScsiDeviceControllerKey() throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof ParaVirtualSCSIController) {
+                    return device.getKey();
+                }
+            }
+        }
+
+        assert (false);
+        throw new Exception("VMware Paravirtual SCSI Controller Not Found");
+    }
+
+    public void ensurePvScsiDeviceController(int requiredNumScsiControllers, 
int availableBusNum) throws Exception {
+        VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+
+        int busNum = availableBusNum;
+        while (busNum < requiredNumScsiControllers) {
+            ParaVirtualSCSIController scsiController = new 
ParaVirtualSCSIController();
+
+            scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+            scsiController.setBusNumber(busNum);
+            scsiController.setKey(busNum - 
VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
+            VirtualDeviceConfigSpec scsiControllerSpec = new 
VirtualDeviceConfigSpec();
+            scsiControllerSpec.setDevice(scsiController);
+            
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+            vmConfig.getDeviceChange().add(scsiControllerSpec);
+            busNum++;
+        }
+
+        if (configureVm(vmConfig)) {
+            throw new Exception("Unable to add Scsi controllers to the VM " + 
getName());
+        } else {
+            s_logger.info("Successfully added " + requiredNumScsiControllers + 
" SCSI controllers.");
+        }
+    }
+
+    public String getRecommendedDiskController(String guestOsId) throws 
Exception {
+        String recommendedController;
+        GuestOsDescriptor guestOsDescriptor = getGuestOsDescriptor(guestOsId);
+        recommendedController = 
VmwareHelper.getRecommendedDiskControllerFromDescriptor(guestOsDescriptor);
+        return recommendedController;
+    }
+
+    public boolean isPvScsiSupported() throws Exception {
+        int virtualHardwareVersion;
+
+        virtualHardwareVersion = getVirtualHardwareVersion();
+
+        // Check if virtual machine is using hardware version 7 or later.
+        if (virtualHardwareVersion < 7) {
+            s_logger.error("The virtual hardware version of the VM is " + 
virtualHardwareVersion
+                    + ", which doesn't support PV SCSI controller type for 
virtual harddisks. Please upgrade this VM's virtual hardware version to 7 or 
later.");
+            return false;
+        }
+        return true;
+    }
+
+    // Would be useful if there exists multiple sub types of SCSI controllers 
per VM are supported in CloudStack f
+    public int getScsiDiskControllerKey(String diskController) throws 
Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if ((DiskControllerType.getType(diskController) == 
DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof VirtualLsiLogicController) {
+                    return ((VirtualLsiLogicController)device).getKey();
+                } else if ((DiskControllerType.getType(diskController) == 
DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof VirtualLsiLogicSASController) {
+                    return ((VirtualLsiLogicSASController)device).getKey();
+                } else if ((DiskControllerType.getType(diskController) == 
DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof ParaVirtualSCSIController) {
+                    return ((ParaVirtualSCSIController)device).getKey();
+                } else if ((DiskControllerType.getType(diskController) == 
DiskControllerType.buslogic || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof VirtualBusLogicController) {
+                    return ((VirtualBusLogicController)device).getKey();
+                }
+            }
+        }
+
+        assert (false);
+        throw new Exception(diskController + " Controller Not Found");
+    }
+
+    public int getScsiDiskControllerKeyNoException(String diskController) 
throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if ((DiskControllerType.getType(diskController) == 
DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof VirtualLsiLogicController) {
+                    return ((VirtualLsiLogicController)device).getKey();
+                } else if ((DiskControllerType.getType(diskController) == 
DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof VirtualLsiLogicSASController) {
+                    return ((VirtualLsiLogicSASController)device).getKey();
+                } else if ((DiskControllerType.getType(diskController) == 
DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof ParaVirtualSCSIController) {
+                    return ((ParaVirtualSCSIController)device).getKey();
+                } else if ((DiskControllerType.getType(diskController) == 
DiskControllerType.buslogic || DiskControllerType.getType(diskController) == 
DiskControllerType.scsi)
+                        && device instanceof VirtualBusLogicController) {
+                    return ((VirtualBusLogicController)device).getKey();
+                }
+            }
+        }
+        return -1;
+    }
+
     public int getNextScsiDiskDeviceNumber() throws Exception {
         int scsiControllerKey = getScsiDeviceControllerKey();
         int deviceNumber = getNextDeviceNumber(scsiControllerKey);
@@ -1908,7 +2168,7 @@ public class VirtualMachineMO extends BaseMO {
 
         if (devices != null && devices.size() > 0) {
             for (VirtualDevice device : devices) {
-                if (device instanceof VirtualLsiLogicController) {
+                if (device instanceof VirtualSCSIController) {
                     return device.getKey();
                 }
             }
@@ -1918,12 +2178,27 @@ public class VirtualMachineMO extends BaseMO {
         throw new Exception("SCSI Controller Not Found");
     }
 
-    public int getScsiDeviceControllerKeyNoException() throws Exception {
+    public int getGenericScsiDeviceControllerKeyNoException() throws Exception 
{
         List<VirtualDevice> devices = 
_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
 
         if (devices != null && devices.size() > 0) {
             for (VirtualDevice device : devices) {
-                if (device instanceof VirtualLsiLogicController) {
+                if (device instanceof VirtualSCSIController) {
+                    return device.getKey();
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    public int getScsiDeviceControllerKeyNoException() throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+            getDynamicProperty(_mor, "config.hardware.device");
+
+        if(devices != null && devices.size() > 0) {
+            for(VirtualDevice device : devices) {
+                if(device instanceof VirtualLsiLogicController) {
                     return device.getKey();
                 }
             }
@@ -1953,6 +2228,32 @@ public class VirtualMachineMO extends BaseMO {
         }
     }
 
+    public void ensureScsiDeviceControllers(int count, int availableBusNum) 
throws Exception {
+        int scsiControllerKey = getScsiDeviceControllerKeyNoException();
+        if (scsiControllerKey < 0) {
+            VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+
+            int busNum = availableBusNum;
+            while (busNum < count) {
+            VirtualLsiLogicController scsiController = new 
VirtualLsiLogicController();
+            scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+                scsiController.setBusNumber(busNum);
+                scsiController.setKey(busNum - 
VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
+            VirtualDeviceConfigSpec scsiControllerSpec = new 
VirtualDeviceConfigSpec();
+            scsiControllerSpec.setDevice(scsiController);
+            
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+            vmConfig.getDeviceChange().add(scsiControllerSpec);
+                busNum++;
+            }
+            if (configureVm(vmConfig)) {
+                throw new Exception("Unable to add Scsi controllers to the VM 
" + getName());
+            } else {
+                s_logger.info("Successfully added " + count + " SCSI 
controllers.");
+            }
+        }
+    }
+
     // return pair of VirtualDisk and disk device bus name(ide0:0, etc)
     public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath, 
boolean matchExactly) throws Exception {
         List<VirtualDevice> devices = 
_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
@@ -2305,43 +2606,84 @@ public class VirtualMachineMO extends BaseMO {
         throw new Exception("IDE Controller Not Found");
     }
 
-    public int getNextIDEDeviceNumber() throws Exception {
-        int controllerKey = getIDEDeviceControllerKey();
-        return getNextDeviceNumber(controllerKey);
+    public int getIDEControllerKey(int ideUnitNumber) throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+            getDynamicProperty(_mor, "config.hardware.device");
+
+        int requiredIdeController = ideUnitNumber / 
VmwareHelper.MAX_IDE_CONTROLLER_COUNT;
+
+        int ideControllerCount = 0;
+        if(devices != null && devices.size() > 0) {
+            for(VirtualDevice device : devices) {
+                if(device instanceof VirtualIDEController) {
+                    if (ideControllerCount == requiredIdeController) {
+                        return ((VirtualIDEController)device).getKey();
+                    }
+                    ideControllerCount++;
+                }
+            }
+        }
+
+        assert(false);
+        throw new Exception("IDE Controller Not Found");
     }
 
-    public VirtualDevice getIsoDevice() throws Exception {
-        List<VirtualDevice> devices = 
_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
+    public int getNumberOfIDEDevices() throws Exception {
+        int ideDeviceCount = 0;
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
         if (devices != null && devices.size() > 0) {
             for (VirtualDevice device : devices) {
-                if (device instanceof VirtualCdrom) {
-                    return device;
+                if (device instanceof VirtualIDEController) {
+                    ideDeviceCount += 
((VirtualIDEController)device).getDevice().size();
                 }
             }
         }
-        return null;
+        return ideDeviceCount;
     }
 
-    public int getPCIDeviceControllerKey() throws Exception {
-        List<VirtualDevice> devices = 
_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
+    public int getFreeUnitNumberOnIDEController(int controllerKey) throws 
Exception {
+        int freeUnitNumber = 0;
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
 
+        int deviceCount = 0;
+        int ideDeviceUnitNumber = -1;
         if (devices != null && devices.size() > 0) {
             for (VirtualDevice device : devices) {
-                if (device instanceof VirtualPCIController) {
-                    return ((VirtualPCIController)device).getKey();
+                if (device instanceof VirtualDisk && (controllerKey == 
device.getControllerKey())) {
+                    deviceCount++;
+                    ideDeviceUnitNumber = device.getUnitNumber();
                 }
             }
         }
-
-        assert (false);
-        throw new Exception("PCI Controller Not Found");
+        if (deviceCount == 1) {
+            if (ideDeviceUnitNumber == 0) {
+                freeUnitNumber = 1;
+            } // else freeUnitNumber is already initialized to 0
+        } else if (deviceCount == 2) {
+            throw new Exception("IDE controller with key [" + controllerKey + 
"] already has 2 device attached. Cannot attach more than the limit of 2.");
+        }
+        return freeUnitNumber;
     }
-
-    public int getNextPCIDeviceNumber() throws Exception {
-        int controllerKey = getPCIDeviceControllerKey();
+    public int getNextIDEDeviceNumber() throws Exception {
+        int controllerKey = getIDEDeviceControllerKey();
         return getNextDeviceNumber(controllerKey);
     }
 
+    public VirtualDevice getIsoDevice() throws Exception {
+        List<VirtualDevice> devices = 
_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof VirtualCdrom) {
+                    return device;
+                }
+            }
+        }
+        return null;
+    }
+
     public int getNextDeviceNumber(int controllerKey) throws Exception {
         List<VirtualDevice> devices = 
_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
 
@@ -2596,6 +2938,9 @@ public class VirtualMachineMO extends BaseMO {
     public long getHotAddMemoryLimitInMb() throws Exception {
         return (Long)_context.getVimClient().getDynamicProperty(_mor, 
"config.hotPlugMemoryLimit");
     }
+    public String getGuestId() throws Exception {
+        return (String)_context.getVimClient().getDynamicProperty(_mor, 
"config.guestId");
+    }
 
     public int getCoresPerSocket() throws Exception {
         // number of cores per socket is 1 in case of ESXi. It's not defined 
explicitly and the property is support since vSphere API 5.0.
@@ -2672,6 +3017,135 @@ public class VirtualMachineMO extends BaseMO {
         }
         return guestOsSupportsMemoryHotAdd && 
virtualHardwareSupportsMemoryHotAdd;
     }
+    public void ensureLsiLogicSasDeviceControllers(int count, int 
availableBusNum) throws Exception {
+        int scsiControllerKey = getLsiLogicSasDeviceControllerKeyNoException();
+        if (scsiControllerKey < 0) {
+            VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+
+            int busNum = availableBusNum;
+            while (busNum < count) {
+                VirtualLsiLogicSASController scsiController = new 
VirtualLsiLogicSASController();
+                scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+                scsiController.setBusNumber(busNum);
+                scsiController.setKey(busNum - 
VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
+                VirtualDeviceConfigSpec scsiControllerSpec = new 
VirtualDeviceConfigSpec();
+                scsiControllerSpec.setDevice(scsiController);
+                
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+                vmConfig.getDeviceChange().add(scsiControllerSpec);
+                busNum++;
+            }
+            if (configureVm(vmConfig)) {
+                throw new Exception("Unable to add Scsi controller of type 
LsiLogic SAS.");
+            }
+        }
+
+    }
+
+    private int getLsiLogicSasDeviceControllerKeyNoException() throws 
Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof VirtualLsiLogicSASController) {
+                    return device.getKey();
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    public void ensureBusLogicDeviceControllers(int count, int 
availableBusNum) throws Exception {
+        int scsiControllerKey = getBusLogicDeviceControllerKeyNoException();
+        if (scsiControllerKey < 0) {
+            VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+
+            int busNum = availableBusNum;
+            while (busNum < count) {
+                VirtualBusLogicController scsiController = new 
VirtualBusLogicController();
+
+                scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+                scsiController.setBusNumber(busNum);
+                scsiController.setKey(busNum - 
VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
+                VirtualDeviceConfigSpec scsiControllerSpec = new 
VirtualDeviceConfigSpec();
+                scsiControllerSpec.setDevice(scsiController);
+                
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+                vmConfig.getDeviceChange().add(scsiControllerSpec);
+                busNum++;
+            }
+
+            if (configureVm(vmConfig)) {
+                throw new Exception("Unable to add Scsi BusLogic controllers 
to the VM " + getName());
+            } else {
+                s_logger.info("Successfully added " + count + " SCSI BusLogic 
controllers.");
+            }
+        }
+    }
+
+    private int getBusLogicDeviceControllerKeyNoException() throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof VirtualBusLogicController) {
+                    return device.getKey();
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    public Ternary<Integer, Integer, DiskControllerType> 
getScsiControllerInfo() throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
+
+        int scsiControllerCount = 0;
+        int busNum = -1;
+        DiskControllerType controllerType = DiskControllerType.lsilogic;
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof VirtualSCSIController) {
+                    scsiControllerCount++;
+                    int deviceBus = 
((VirtualSCSIController)device).getBusNumber();
+                    if (busNum < deviceBus) {
+                        busNum = deviceBus;
+                    }
+                    if (device instanceof VirtualLsiLogicController) {
+                        controllerType = DiskControllerType.lsilogic;
+                    } else if (device instanceof VirtualLsiLogicSASController) 
{
+                        controllerType = DiskControllerType.lsisas1068;
+                    } else if (device instanceof VirtualBusLogicController) {
+                        controllerType = DiskControllerType.buslogic;
+                    } else if (device instanceof ParaVirtualSCSIController) {
+                        controllerType = DiskControllerType.pvscsi;
+                    }
+                }
+            }
+        }
+
+        return new Ternary<Integer, Integer, 
DiskControllerType>(scsiControllerCount, busNum, controllerType);
+    }
+
+    public int getNumberOfVirtualDisks() throws Exception {
+        List<VirtualDevice> devices = 
(List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, 
"config.hardware.device");
+
+        s_logger.info("Counting disk devices attached to VM " + getVmName());
+        int count = 0;
+
+        if (devices != null && devices.size() > 0) {
+            for (VirtualDevice device : devices) {
+                if (device instanceof VirtualDisk) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
 
     public boolean consolidateVmDisks() throws Exception {
         ManagedObjectReference morTask = 
_context.getService().consolidateVMDisksTask(_mor);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a4cc987a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkAdapterType.java
----------------------------------------------------------------------
diff --git 
a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkAdapterType.java 
b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkAdapterType.java
new file mode 100644
index 0000000..f602c46
--- /dev/null
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkAdapterType.java
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.vmware.mo;
+
+public enum VmdkAdapterType {
+    ide,
+    lsilogic,
+    buslogic,
+    none;
+
+    public static VmdkAdapterType getAdapterType(DiskControllerType 
diskControllerType) {
+        if (diskControllerType == DiskControllerType.ide) {
+            return VmdkAdapterType.ide;
+        } else if (diskControllerType == DiskControllerType.buslogic) {
+            return VmdkAdapterType.buslogic;
+        } else if (diskControllerType == DiskControllerType.lsilogic || 
diskControllerType == DiskControllerType.pvscsi || diskControllerType == 
DiskControllerType.lsisas1068) {
+            return VmdkAdapterType.lsilogic;
+        } else {
+            return VmdkAdapterType.none;
+        }
+    }
+
+    public static VmdkAdapterType getType(String vmdkAdapterType) {
+        if (vmdkAdapterType.equalsIgnoreCase("ide")) {
+            return VmdkAdapterType.ide;
+        } else if (vmdkAdapterType.equalsIgnoreCase("lsilogic")) {
+            return VmdkAdapterType.lsilogic;
+        } else if (vmdkAdapterType.equalsIgnoreCase("buslogic")) {
+            return VmdkAdapterType.buslogic;
+        } else {
+            return VmdkAdapterType.none;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a4cc987a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java
----------------------------------------------------------------------
diff --git 
a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java 
b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java
index 8aecfdd..932c251 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java
@@ -29,6 +29,9 @@ import org.apache.log4j.Logger;
 
 public class VmdkFileDescriptor {
     private static final Logger s_logger = 
Logger.getLogger(VmdkFileDescriptor.class);
+    private static final String VMDK_PROPERTY_CREATE_TYPE = "createType";
+    private static final String VMDK_CREATE_TYPE_VMFSSPARSE = "vmfsSparse";
+    private static final String VMDK_PROPERTY_ADAPTER_TYPE = "ddb.adapterType";
 
     private Properties _properties = new Properties();
     private String _baseFileName;
@@ -84,6 +87,73 @@ public class VmdkFileDescriptor {
         return _properties.getProperty("parentFileNameHint");
     }
 
+    public boolean isVmfsSparseFile() {
+        String vmdkCreateType = 
_properties.getProperty(VMDK_PROPERTY_CREATE_TYPE);
+        if (vmdkCreateType.equalsIgnoreCase(VMDK_CREATE_TYPE_VMFSSPARSE)) {
+            return true;
+        }
+        return false;
+    }
+
+    public String getAdapterType() {
+        return _properties.getProperty(VMDK_PROPERTY_ADAPTER_TYPE);
+    }
+
+
+    public static byte[] changeVmdkAdapterType(byte[] vmdkContent, String 
newAdapterType) throws IOException {
+        assert (vmdkContent != null);
+
+        BufferedReader in = null;
+        BufferedWriter out = null;
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+        try {
+            in = new BufferedReader(new InputStreamReader(new 
ByteArrayInputStream(vmdkContent)));
+            out = new BufferedWriter(new OutputStreamWriter(bos));
+            String line;
+            while ((line = in.readLine()) != null) {
+                // ignore empty and comment lines
+                line = line.trim();
+                if (line.isEmpty()) {
+                    out.newLine();
+                    continue;
+                }
+                if (line.charAt(0) == '#') {
+                    out.write(line);
+                    out.newLine();
+                    continue;
+                }
+
+                String[] tokens = line.split("=");
+                if (tokens.length == 2) {
+                    String name = tokens[0].trim();
+                    String value = tokens[1].trim();
+                    if (value.charAt(0) == '\"')
+                        value = value.substring(1, value.length() - 1);
+
+                    if (newAdapterType != null && 
name.equals(VMDK_PROPERTY_ADAPTER_TYPE)) {
+                        out.write(name + "=\"" + newAdapterType + "\"");
+                        out.newLine();
+                    } else {
+                        out.write(line);
+                        out.newLine();
+                    }
+                } else {
+                    out.write(line);
+                    out.newLine();
+                }
+            }
+        } finally {
+            if (in != null)
+                in.close();
+            if (out != null)
+                out.close();
+        }
+
+        return bos.toByteArray();
+
+    }
+
     public static byte[] changeVmdkContentBaseInfo(byte[] vmdkContent, String 
baseFileName, String parentFileName) throws IOException {
 
         assert (vmdkContent != null);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a4cc987a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
----------------------------------------------------------------------
diff --git 
a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java 
b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
index 9727e17..fdfc254 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
@@ -23,6 +23,7 @@ import com.vmware.vim25.ObjectContent;
 import com.vmware.vim25.VirtualMachineConfigSpec;
 
 import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.utils.Pair;
 
 /**
  * Interface to consolidate ESX(i) hosts and HA/FT clusters into a common 
interface used by CloudStack Hypervisor resources
@@ -53,7 +54,8 @@ public interface VmwareHypervisorHost {
     boolean createVm(VirtualMachineConfigSpec vmSpec) throws Exception;
 
     boolean createBlankVm(String vmName, String vmInternalCSName, int 
cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int 
memoryMB,
-        int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference 
morDs, boolean snapshotDirToParent) throws Exception;
+        int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference 
morDs, boolean snapshotDirToParent,
+        Pair<String, String> controllerInfo, Boolean systemVm) throws 
Exception;
 
     void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, 
String diskOption) throws Exception;
 
@@ -81,4 +83,5 @@ public interface VmwareHypervisorHost {
     ComputeResourceSummary getHyperHostHardwareSummary() throws Exception;
 
     LicenseAssignmentManagerMO getLicenseAssignmentManager() throws Exception;
+    String getRecommendedDiskController(String guestOsId) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a4cc987a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java 
b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
index b2b1090..8379813 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
@@ -34,6 +34,7 @@ import org.apache.log4j.Logger;
 
 import com.vmware.vim25.DistributedVirtualSwitchPortConnection;
 import com.vmware.vim25.DynamicProperty;
+import com.vmware.vim25.GuestOsDescriptor;
 import com.vmware.vim25.ManagedObjectReference;
 import com.vmware.vim25.MethodFault;
 import com.vmware.vim25.ObjectContent;
@@ -62,6 +63,7 @@ import com.vmware.vim25.VirtualPCNet32;
 import com.vmware.vim25.VirtualVmxnet2;
 import com.vmware.vim25.VirtualVmxnet3;
 
+import com.cloud.hypervisor.vmware.mo.DiskControllerType;
 import com.cloud.hypervisor.vmware.mo.HostMO;
 import com.cloud.hypervisor.vmware.mo.LicenseAssignmentManagerMO;
 import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
@@ -75,6 +77,11 @@ public class VmwareHelper {
     @SuppressWarnings("unused")
     private static final Logger s_logger = 
Logger.getLogger(VmwareHelper.class);
 
+    public static final int MAX_SCSI_CONTROLLER_COUNT = 4;
+    public static final int MAX_IDE_CONTROLLER_COUNT = 2;
+    public static final int MAX_ALLOWED_DEVICES_IDE_CONTROLLER = 2;
+    public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 15;
+
     public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
         return deviceNumber == 7;
     }
@@ -705,6 +712,19 @@ public class VmwareHelper {
         return UUID.randomUUID().toString().replaceAll("-", "");
     }
 
+    public static String 
getRecommendedDiskControllerFromDescriptor(GuestOsDescriptor guestOsDescriptor) 
throws Exception {
+        String recommendedController;
+
+        recommendedController = 
guestOsDescriptor.getRecommendedDiskController();
+
+        // By-pass auto detected PVSCSI controller to use LsiLogic Parallel 
instead
+        if (DiskControllerType.getType(recommendedController) == 
DiskControllerType.pvscsi) {
+            recommendedController = DiskControllerType.lsilogic.toString();
+        }
+
+        return recommendedController;
+    }
+
     public static String trimSnapshotDeltaPostfix(String name) {
         String[] tokens = name.split("-");
         if (tokens.length > 1 && tokens[tokens.length - 
1].matches("[0-9]{6,}")) {
@@ -716,4 +736,8 @@ public class VmwareHelper {
         return name;
     }
 
+    public static boolean isControllerOsRecommended(String dataDiskController) 
{
+        return DiskControllerType.getType(dataDiskController) == 
DiskControllerType.osdefault;
+    }
+
 }

Reply via email to