Updated Branches: refs/heads/master 66b853789 -> bced4c7e8
Add support for hypervisor snapshots to CloudStack-managed storage (for XenServer and VMware) Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/bced4c7e Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/bced4c7e Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/bced4c7e Branch: refs/heads/master Commit: bced4c7e8ba791ebcd5a8117cf30445388233d68 Parents: 66b8537 Author: Mike Tutkowski <mike.tutkow...@solidfire.com> Authored: Wed Oct 2 00:07:48 2013 -0600 Committer: Mike Tutkowski <mike.tutkow...@solidfire.com> Committed: Fri Oct 4 15:41:20 2013 -0600 ---------------------------------------------------------------------- .../cloud/agent/api/AttachVolumeCommand.java | 8 +- .../api/agent/test/AttachVolumeAnswerTest.java | 2 +- .../api/agent/test/AttachVolumeCommandTest.java | 2 +- .../vmware/manager/VmwareHostService.java | 6 +- .../vmware/resource/VmwareResource.java | 66 +++++++------- .../VmwareSecondaryStorageResourceHandler.java | 9 +- .../resource/VmwareStorageProcessor.java | 43 +++++++--- .../xen/resource/CitrixResourceBase.java | 90 ++++++++++---------- .../xen/resource/XenServerStorageProcessor.java | 14 ++- .../driver/SolidfirePrimaryDataStoreDriver.java | 4 +- .../storage/datastore/util/SolidFireUtil.java | 22 +++-- .../com/cloud/storage/VolumeApiServiceImpl.java | 13 ++- 12 files changed, 172 insertions(+), 107 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/core/src/com/cloud/agent/api/AttachVolumeCommand.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/AttachVolumeCommand.java b/core/src/com/cloud/agent/api/AttachVolumeCommand.java index 49b2a70..e927619 100644 --- a/core/src/com/cloud/agent/api/AttachVolumeCommand.java +++ b/core/src/com/cloud/agent/api/AttachVolumeCommand.java @@ -25,6 +25,7 @@ public class AttachVolumeCommand extends Command { private StoragePoolType pooltype; private String volumePath; private String volumeName; + private Long volumeSize; private Long deviceId; private String chainInfo; private String poolUuid; @@ -45,13 +46,14 @@ public class AttachVolumeCommand extends Command { public AttachVolumeCommand(boolean attach, boolean managed, String vmName, StoragePoolType pooltype, String volumePath, String volumeName, - Long deviceId, String chainInfo) { + Long volumeSize, Long deviceId, String chainInfo) { this.attach = attach; this._managed = managed; this.vmName = vmName; this.pooltype = pooltype; this.volumePath = volumePath; this.volumeName = volumeName; + this.volumeSize = volumeSize; this.deviceId = deviceId; this.chainInfo = chainInfo; } @@ -85,6 +87,10 @@ public class AttachVolumeCommand extends Command { return volumeName; } + public Long getVolumeSize() { + return volumeSize; + } + public Long getDeviceId() { return deviceId; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeAnswerTest.java ---------------------------------------------------------------------- diff --git a/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeAnswerTest.java b/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeAnswerTest.java index 0b2bb1f..5262d3b 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeAnswerTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeAnswerTest.java @@ -27,7 +27,7 @@ import com.cloud.storage.Storage.StoragePoolType; public class AttachVolumeAnswerTest { AttachVolumeCommand avc = new AttachVolumeCommand(true, false, "vmname", - StoragePoolType.Filesystem, "vPath", "vName", + StoragePoolType.Filesystem, "vPath", "vName", 1073741824L, 123456789L, "chainInfo"); AttachVolumeAnswer ava1 = new AttachVolumeAnswer(avc); String results = ""; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeCommandTest.java ---------------------------------------------------------------------- diff --git a/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeCommandTest.java index 6f413c0..1c5caca 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/AttachVolumeCommandTest.java @@ -26,7 +26,7 @@ import com.cloud.storage.Storage.StoragePoolType; public class AttachVolumeCommandTest { AttachVolumeCommand avc = new AttachVolumeCommand(true, false, "vmname", - StoragePoolType.Filesystem, "vPath", "vName", + StoragePoolType.Filesystem, "vPath", "vName", 1073741824L, 123456789L, "chainInfo"); @Test http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java index 2b44071..d0147d1 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java @@ -17,6 +17,7 @@ package com.cloud.hypervisor.vmware.manager; import com.cloud.agent.api.Command; +import com.cloud.hypervisor.vmware.mo.DatastoreMO; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.vmware.vim25.ManagedObjectReference; @@ -28,7 +29,8 @@ public interface VmwareHostService { String getWorkerName(VmwareContext context, Command cmd, int workerSequence); - ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, - String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception; + ManagedObjectReference getVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber, + String iqn, String initiatorChapName, String initiatorChapSecret, String mutualChapName, String mutualChapSecret) throws Exception; + void createVmdk(Command cmd, DatastoreMO dsMo, String volumeDatastorePath, Long volumeSize) throws Exception; void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 83dcc58..6b3731ce 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -4439,7 +4439,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return str.replace('/', '-'); } - private String trimIqn(String iqn) { + public static String trimIqn(String iqn) { String[] tmp = iqn.split("/"); if (tmp.length != 3) { @@ -4454,36 +4454,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } @Override - public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, - String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception { + public void createVmdk(Command cmd, DatastoreMO dsMo, String vmdkDatastorePath, Long volumeSize) throws Exception { VmwareContext context = getServiceContext(); VmwareHypervisorHost hyperHost = getHyperHost(context); - ManagedObjectReference morDs = createVmfsDatastore(hyperHost, getDatastoreName(iqn), - storageHost, storagePort, trimIqn(iqn), - initiatorUsername, initiatorPassword, - targetUsername, targetPassword); + String dummyVmName = getWorkerName(context, cmd, 0); - DatastoreMO dsMo = new DatastoreMO(context, morDs); + VirtualMachineMO vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName); - String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); - - if (!dsMo.fileExists(volumeDatastorePath)) { - String dummyVmName = getWorkerName(context, cmd, 0); - - VirtualMachineMO vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName); - - if (vmMo == null) { - throw new Exception("Unable to create a dummy VM for volume creation"); - } - - vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dsMo.getSummary().getFreeSpace()), - morDs, vmMo.getScsiDeviceControllerKey()); - vmMo.detachDisk(volumeDatastorePath, false); - vmMo.destroy(); + if (vmMo == null) { + throw new Exception("Unable to create a dummy VM for volume creation"); } - return morDs; + Long volumeSizeToUse = volumeSize < dsMo.getSummary().getFreeSpace() ? volumeSize : dsMo.getSummary().getFreeSpace(); + + vmMo.createDisk(vmdkDatastorePath, getMBsFromBytes(volumeSizeToUse), dsMo.getMor(), vmMo.getScsiDeviceControllerKey()); + vmMo.detachDisk(vmdkDatastorePath, false); + vmMo.destroy(); } @Override @@ -4516,9 +4503,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference morDs = null; if (cmd.getAttach() && cmd.isManaged()) { - morDs = handleDatastoreAndVmdkAttach(cmd, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort(), - cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), - cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); + morDs = getVmfsDatastore(hyperHost, getDatastoreName(cmd.get_iScsiName()), cmd.getStorageHost(), cmd.getStoragePort(), trimIqn(cmd.get_iScsiName()), + cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); + + DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs); + + String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); + + if (!dsMo.fileExists(volumeDatastorePath)) { + createVmdk(cmd, dsMo, VmwareResource.getDatastoreName(cmd.get_iScsiName()), cmd.getVolumeSize()); + } } else { morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid()); @@ -4531,10 +4525,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs); - VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), cmd.getVmName(), - dsMo, cmd.getVolumePath()); - - String datastoreVolumePath = dsMo.searchFileInSubFolders(cmd.getVolumePath() + ".vmdk", true); + + String datastoreVolumePath = null; + + if (cmd.isManaged()) { + datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk"); + } + else { + VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), cmd.getVmName(), dsMo, cmd.getVolumePath()); + + datastoreVolumePath = dsMo.searchFileInSubFolders(cmd.getVolumePath() + ".vmdk", true); + } + assert (datastoreVolumePath != null) : "Virtual disk file must exist in specified datastore for attach/detach operations."; if (datastoreVolumePath == null) { throw new CloudRuntimeException("Unable to find file " + cmd.getVolumePath() + ".vmdk in datastore " + dsMo.getName()); @@ -4687,7 +4689,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - private ManagedObjectReference createVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, + public ManagedObjectReference getVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber, String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception { VmwareContext context = getServiceContext(); ManagedObjectReference morCluster = hyperHost.getHyperHostCluster(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java index 2c302ab..c84813f 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java @@ -37,6 +37,7 @@ import com.cloud.hypervisor.vmware.manager.VmwareStorageManager; import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl; import com.cloud.hypervisor.vmware.manager.VmwareStorageMount; import com.cloud.hypervisor.vmware.mo.ClusterMO; +import com.cloud.hypervisor.vmware.mo.DatastoreMO; import com.cloud.hypervisor.vmware.mo.HostMO; import com.cloud.hypervisor.vmware.mo.VmwareHostType; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; @@ -347,8 +348,12 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe return true; } - public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, - String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception { + public ManagedObjectReference getVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber, + String iqn, String initiatorChapName, String initiatorChapSecret, String mutualChapName, String mutualChapSecret) throws Exception { + throw new OperationNotSupportedException(); + } + + public void createVmdk(Command cmd, DatastoreMO dsMo, String volumeDatastorePath, Long volumeSize) throws Exception { throw new OperationNotSupportedException(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java index a14c403..34bfe18 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -1191,8 +1191,16 @@ public class VmwareStorageProcessor implements StorageProcessor { ManagedObjectReference morDs = null; if (isAttach && isManaged) { - morDs = hostService.handleDatastoreAndVmdkAttach(cmd, iScsiName, storageHost, storagePort, - initiatorUsername, initiatorPassword, targetUsername, targetPassword); + morDs = hostService.getVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort, + VmwareResource.trimIqn(iScsiName), initiatorUsername, initiatorPassword, targetUsername, targetPassword); + + DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs); + + String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); + + if (!dsMo.fileExists(volumeDatastorePath)) { + hostService.createVmdk(cmd, dsMo, VmwareResource.getDatastoreName(iScsiName), volumeTO.getSize()); + } } else { morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid()); @@ -1207,24 +1215,35 @@ public class VmwareStorageProcessor implements StorageProcessor { DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs); String datastoreVolumePath; - if(isAttach) { - if(!isManaged) - datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, - dsMo, volumeTO.getPath()); - else + if (isAttach) { + if (isManaged) { datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk"); - } else { - datastoreVolumePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, volumeTO.getPath() + ".vmdk"); - if(!dsMo.fileExists(datastoreVolumePath)) - datastoreVolumePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, volumeTO.getPath() + ".vmdk"); + } + else { + datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, dsMo, volumeTO.getPath()); + } + } + else { + if (isManaged) { + datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk"); + } + else { + datastoreVolumePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, volumeTO.getPath() + ".vmdk"); + + if (!dsMo.fileExists(datastoreVolumePath)) { + datastoreVolumePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, volumeTO.getPath() + ".vmdk"); + } + } } disk.setVdiUuid(datastoreVolumePath); AttachAnswer answer = new AttachAnswer(disk); + if (isAttach) { vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); - } else { + } + else { vmMo.removeAllSnapshots(); vmMo.detachDisk(datastoreVolumePath, false); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 6b81c25..92fbab2 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -5348,7 +5348,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (pool.getType() == StoragePoolType.NetworkFilesystem) { getNfsSR(conn, pool); } else if (pool.getType() == StoragePoolType.IscsiLUN) { - getIscsiSR(conn, pool.getUuid(), pool.getHost(), pool.getPath(), null, null, new Boolean[1]); + getIscsiSR(conn, pool.getUuid(), pool.getHost(), pool.getPath(), null, null); } else if (pool.getType() == StoragePoolType.PreSetup) { } else { return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported."); @@ -6166,17 +6166,27 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } protected VDI getVDIbyUuid(Connection conn, String uuid) { + return getVDIbyUuid(conn, uuid, true); + } + + protected VDI getVDIbyUuid(Connection conn, String uuid, boolean throwExceptionIfNotFound) { try { return VDI.getByUuid(conn, uuid); } catch (Exception e) { - String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); - s_logger.debug(msg); - throw new CloudRuntimeException(msg, e); + if (throwExceptionIfNotFound) { + String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); + + s_logger.debug(msg); + + throw new CloudRuntimeException(msg, e); + } + + return null; } } protected SR getIscsiSR(Connection conn, String srNameLabel, String target, String path, - String chapInitiatorUsername, String chapInitiatorPassword, Boolean[] created) { + String chapInitiatorUsername, String chapInitiatorPassword) { synchronized (srNameLabel.intern()) { Map<String, String> deviceConfig = new HashMap<String, String>(); try { @@ -6280,8 +6290,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe { sr = SR.create(conn, host, deviceConfig, new Long(0), srNameLabel, srNameLabel, type, "user", true, smConfig); - - created[0] = true; // note that the SR was created (as opposed to introduced) } else { sr = SR.introduce(conn, pooluuid, srNameLabel, srNameLabel, type, "user", true, smConfig); @@ -6459,54 +6467,41 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - protected VDI handleSrAndVdiAttach(String iqn, String storageHostName, - String chapInitiatorName, String chapInitiatorPassword) throws Types.XenAPIException, XmlRpcException { + protected VDI createVdi(SR sr, String vdiNameLabel, Long volumeSize) throws Types.XenAPIException, XmlRpcException { VDI vdi = null; Connection conn = getConnection(); - Boolean[] created = { false }; - - SR sr = getIscsiSR(conn, iqn, - storageHostName, iqn, - chapInitiatorName, chapInitiatorPassword, created); - - // if created[0] is true, this means the SR was actually created...as opposed to introduced - if (created[0]) { - VDI.Record vdir = new VDI.Record(); - - vdir.nameLabel = iqn; - vdir.SR = sr; - vdir.type = Types.VdiType.USER; + VDI.Record vdir = new VDI.Record(); - long totalSpace = sr.getPhysicalSize(conn); - long unavailableSpace = sr.getPhysicalUtilisation(conn); + vdir.nameLabel = vdiNameLabel; + vdir.SR = sr; + vdir.type = Types.VdiType.USER; - vdir.virtualSize = totalSpace - unavailableSpace; + long totalSrSpace = sr.getPhysicalSize(conn); + long unavailableSrSpace = sr.getPhysicalUtilisation(conn); + long availableSrSpace = totalSrSpace - unavailableSrSpace; - if (vdir.virtualSize < 0) { - throw new CloudRuntimeException("VDI virtual size cannot be less than 0."); - } + if (availableSrSpace < volumeSize) { + throw new CloudRuntimeException("Available space for SR cannot be less than " + volumeSize + "."); + } - long maxNumberOfTries = (totalSpace / unavailableSpace >= 1) ? (totalSpace / unavailableSpace) : 1; - long tryNumber = 0; + vdir.virtualSize = volumeSize; - while (tryNumber <= maxNumberOfTries) { - try { - vdi = VDI.create(conn, vdir); + long maxNumberOfTries = (totalSrSpace / unavailableSrSpace >= 1) ? (totalSrSpace / unavailableSrSpace) : 1; + long tryNumber = 0; - break; - } - catch (Exception ex) { - tryNumber++; + while (tryNumber <= maxNumberOfTries) { + try { + vdi = VDI.create(conn, vdir); - vdir.virtualSize -= unavailableSpace; - } + break; } + catch (Exception ex) { + tryNumber++; - } - else { - vdi = sr.getVDIs(conn).iterator().next(); + vdir.virtualSize -= unavailableSrSpace; + } } return vdi; @@ -6534,12 +6529,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } try { - // Look up the VDI VDI vdi = null; if (cmd.getAttach() && cmd.isManaged()) { - vdi = handleSrAndVdiAttach(cmd.get_iScsiName(), cmd.getStorageHost(), - cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword()); + SR sr = getIscsiSR(conn, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.get_iScsiName(), + cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword()); + + vdi = getVDIbyUuid(conn, cmd.getVolumePath(), false); + + if (vdi == null) { + vdi = createVdi(sr, cmd.get_iScsiName(), cmd.getVolumeSize()); + } } else { vdi = getVDIbyUuid(conn, cmd.getVolumePath()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java index 5da0571..2d4c86e 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java @@ -167,12 +167,20 @@ public class XenServerStorageProcessor implements StorageProcessor { try { Connection conn = this.hypervisorResource.getConnection(); - // Look up the VDI + VDI vdi = null; if (cmd.isManaged()) { - vdi = this.hypervisorResource.handleSrAndVdiAttach(cmd.get_iScsiName(), cmd.getStorageHost(), - cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword()); + SR sr = this.hypervisorResource.getIscsiSR(conn, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.get_iScsiName(), + cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword()); + + vdi = this.hypervisorResource.getVDIbyUuid(conn, data.getPath(), false); + + if (vdi == null) { + VolumeObjectTO volume = (VolumeObjectTO)data; + + vdi = this.hypervisorResource.createVdi(sr, cmd.get_iScsiName(), volume.getSize()); + } } else { vdi = this.hypervisorResource.mount(conn, null, null, data.getPath()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java ---------------------------------------------------------------------- diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java index c73e409..8046b6c 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java @@ -277,8 +277,10 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { iops = new Iops(volumeInfo.getMinIops(), volumeInfo.getMaxIops(), getDefaultBurstIops(storagePoolId, volumeInfo.getMaxIops())); } + long volumeSize = volumeInfo.getSize() * 2; // in reality, use a multiplier that's at cluster-level scope + long sfVolumeId = SolidFireUtil.createSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, - getSolidFireVolumeName(volumeInfo.getName()), sfAccountId, volumeInfo.getSize(), true, + getSolidFireVolumeName(volumeInfo.getName()), sfAccountId, volumeSize, true, volumeInfo.getSize().toString(), iops.getMinIops(), iops.getMaxIops(), iops.getBurstIops()); return SolidFireUtil.getSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java ---------------------------------------------------------------------- diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java index ac11272..6659f98 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java @@ -78,13 +78,13 @@ public class SolidFireUtil public static final String USE_MUTUAL_CHAP_FOR_VMWARE = "useMutualChapForVMware"; public static long createSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, - String strSfVolumeName, long lSfAccountId, long lTotalSize, boolean bEnable512e, + String strSfVolumeName, long lSfAccountId, long lTotalSize, boolean bEnable512e, final String strCloudStackVolumeSize, long lMinIops, long lMaxIops, long lBurstIops) { final Gson gson = new GsonBuilder().create(); VolumeToCreate volumeToCreate = new VolumeToCreate(strSfVolumeName, lSfAccountId, lTotalSize, bEnable512e, - lMinIops, lMaxIops, lBurstIops); + strCloudStackVolumeSize, lMinIops, lMaxIops, lBurstIops); String strVolumeToCreateJson = gson.toJson(volumeToCreate); @@ -443,10 +443,10 @@ public class SolidFireUtil private final VolumeToCreateParams params; private VolumeToCreate(final String strVolumeName, final long lAccountId, final long lTotalSize, - final boolean bEnable512e, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) + final boolean bEnable512e, final String strCloudStackVolumeSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) { params = new VolumeToCreateParams(strVolumeName, lAccountId, lTotalSize, bEnable512e, - lMinIOPS, lMaxIOPS, lBurstIOPS); + strCloudStackVolumeSize, lMinIOPS, lMaxIOPS, lBurstIOPS); } private static final class VolumeToCreateParams @@ -456,18 +456,30 @@ public class SolidFireUtil private final long totalSize; private final boolean enable512e; private final VolumeToCreateParamsQoS qos; + private final VolumeToCreateParamsAttributes attributes; private VolumeToCreateParams(final String strVolumeName, final long lAccountId, final long lTotalSize, - final boolean bEnable512e, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) + final boolean bEnable512e, final String strCloudStackVolumeSize, final long lMinIOPS, final long lMaxIOPS, final long lBurstIOPS) { name = strVolumeName; accountID = lAccountId; totalSize = lTotalSize; enable512e = bEnable512e; + attributes = new VolumeToCreateParamsAttributes(strCloudStackVolumeSize); qos = new VolumeToCreateParamsQoS(lMinIOPS, lMaxIOPS, lBurstIOPS); } + private static final class VolumeToCreateParamsAttributes + { + private final String CloudStackVolumeSize; + + private VolumeToCreateParamsAttributes(final String strCloudStackVolumeSize) + { + CloudStackVolumeSize = strCloudStackVolumeSize; + } + } + private static final class VolumeToCreateParamsQoS { private final long minIOPS; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bced4c7e/server/src/com/cloud/storage/VolumeApiServiceImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index faff10f..5161ca5 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -1047,8 +1047,17 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic HypervisorType rootDiskHyperType = vm.getHypervisorType(); HypervisorType dataDiskHyperType = _volsDao.getHypervisorType(volume.getId()); - if (dataDiskHyperType != HypervisorType.None && rootDiskHyperType != dataDiskHyperType) { - throw new InvalidParameterValueException("Can't attach a volume created by: " + dataDiskHyperType + " to a " + rootDiskHyperType + " vm"); + + VolumeVO dataDiskVol = _volsDao.findById(volume.getId()); + StoragePoolVO dataDiskStoragePool = _storagePoolDao.findById(dataDiskVol.getPoolId()); + + // managed storage can be used for different types of hypervisors + // only perform this check if the volume's storage pool is not null and not managed + if (dataDiskStoragePool != null && !dataDiskStoragePool.isManaged()) { + if (dataDiskHyperType != HypervisorType.None && rootDiskHyperType != dataDiskHyperType) { + throw new InvalidParameterValueException("Can't attach a volume created by: " + dataDiskHyperType + + " to a " + rootDiskHyperType + " vm"); + } } deviceId = getDeviceId(vmId, deviceId);