mirror of https://github.com/apache/cloudstack.git
Add support for hypervisor snapshots to CloudStack-managed storage (for XenServer and VMware)
This commit is contained in:
parent
66b853789c
commit
bced4c7e8b
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = "";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
VDI.Record vdir = new VDI.Record();
|
||||
|
||||
SR sr = getIscsiSR(conn, iqn,
|
||||
storageHostName, iqn,
|
||||
chapInitiatorName, chapInitiatorPassword, created);
|
||||
vdir.nameLabel = vdiNameLabel;
|
||||
vdir.SR = sr;
|
||||
vdir.type = Types.VdiType.USER;
|
||||
|
||||
// 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;
|
||||
|
||||
long totalSpace = sr.getPhysicalSize(conn);
|
||||
long unavailableSpace = sr.getPhysicalUtilisation(conn);
|
||||
|
||||
vdir.virtualSize = totalSpace - unavailableSpace;
|
||||
|
||||
if (vdir.virtualSize < 0) {
|
||||
throw new CloudRuntimeException("VDI virtual size cannot be less than 0.");
|
||||
}
|
||||
|
||||
long maxNumberOfTries = (totalSpace / unavailableSpace >= 1) ? (totalSpace / unavailableSpace) : 1;
|
||||
long tryNumber = 0;
|
||||
|
||||
while (tryNumber <= maxNumberOfTries) {
|
||||
try {
|
||||
vdi = VDI.create(conn, vdir);
|
||||
|
||||
break;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
tryNumber++;
|
||||
|
||||
vdir.virtualSize -= unavailableSpace;
|
||||
}
|
||||
}
|
||||
long totalSrSpace = sr.getPhysicalSize(conn);
|
||||
long unavailableSrSpace = sr.getPhysicalUtilisation(conn);
|
||||
long availableSrSpace = totalSrSpace - unavailableSrSpace;
|
||||
|
||||
if (availableSrSpace < volumeSize) {
|
||||
throw new CloudRuntimeException("Available space for SR cannot be less than " + volumeSize + ".");
|
||||
}
|
||||
else {
|
||||
vdi = sr.getVDIs(conn).iterator().next();
|
||||
|
||||
vdir.virtualSize = volumeSize;
|
||||
|
||||
long maxNumberOfTries = (totalSrSpace / unavailableSrSpace >= 1) ? (totalSrSpace / unavailableSrSpace) : 1;
|
||||
long tryNumber = 0;
|
||||
|
||||
while (tryNumber <= maxNumberOfTries) {
|
||||
try {
|
||||
vdi = VDI.create(conn, vdir);
|
||||
|
||||
break;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
tryNumber++;
|
||||
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue