NFS support for VMware-managed storage

Signed-off-by: Mike Tutkowski <mike.tutkowski@solidfire.com>
This commit is contained in:
punith-cloudbyte 2015-02-27 15:50:25 +05:30 committed by Mike Tutkowski
parent 8e5fefc66c
commit ff7ef985f1
4 changed files with 71 additions and 38 deletions

View File

@ -2360,7 +2360,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// if the datastore is not present, we need to discover the iSCSI device that will support it,
// create the datastore, and create a VMDK file in the datastore
if (morDatastore == null) {
morDatastore = _storageProcessor.prepareManagedStorage(context, hyperHost, iScsiName,
morDatastore = _storageProcessor.prepareManagedStorage(context, hyperHost, null, iScsiName,
details.get(DiskTO.STORAGE_HOST), Integer.parseInt(details.get(DiskTO.STORAGE_PORT)),
volumeTO.getVolumeType() == Volume.Type.ROOT ? volumeTO.getName() : null,
details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),

View File

@ -105,6 +105,7 @@ import com.cloud.vm.VirtualMachine.PowerState;
public class VmwareStorageProcessor implements StorageProcessor {
private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
private static final int DEFAULT_NFS_PORT = 2049;
private VmwareHostService hostService;
private boolean _fullCloneFlag;
@ -297,8 +298,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
final ManagedObjectReference morDs;
if (managed) {
morDs = prepareManagedDatastore(context, hyperHost, managedStoragePoolName, storageHost, storagePort,
chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
morDs = prepareManagedDatastore(context, hyperHost, null, managedStoragePoolName, storageHost, storagePort,
chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
}
else {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, storageUuid);
@ -1306,17 +1307,22 @@ public class VmwareStorageProcessor implements StorageProcessor {
vmName = vmMo.getName();
ManagedObjectReference morDs = null;
String diskUuid = volumeTO.getUuid().replace("-", "");
if (isAttach && isManaged) {
Map<String, String> details = disk.getDetails();
morDs = prepareManagedStorage(context, hyperHost, iScsiName, storageHost, storagePort, null,
details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET),
volumeTO.getSize(), cmd);
morDs = prepareManagedStorage(context, hyperHost, diskUuid, iScsiName, storageHost, storagePort, null,
details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET),
volumeTO.getSize(), cmd);
}
else {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid());
if (storagePort == DEFAULT_NFS_PORT) {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(diskUuid) : primaryStore.getUuid());
} else {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid());
}
}
if (morDs == null) {
@ -1357,7 +1363,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
vmMo.detachDisk(datastoreVolumePath, false);
if (isManaged) {
handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
handleDatastoreAndVmdkDetachManaged(diskUuid, iScsiName, storageHost, storagePort);
} else {
VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath());
}
@ -1721,11 +1727,24 @@ public class VmwareStorageProcessor implements StorageProcessor {
return getVmfsDatastore(context, hyperHost, datastoreName, storageHost, storagePort, trimIqn(iScsiName), null, null, null, null);
}
private ManagedObjectReference prepareManagedDatastore(VmwareContext context, VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret) throws Exception {
return getVmfsDatastore(context, hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
trimIqn(iScsiName), chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
private ManagedObjectReference prepareManagedDatastore(VmwareContext context, VmwareHypervisorHost hyperHost, String diskUuid, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret) throws Exception {
if (storagePort == DEFAULT_NFS_PORT) {
s_logger.info("creating the NFS datastore with the following configuration - storageHost: " + storageHost + ", storagePort: " + storagePort +
", exportpath: " + iScsiName + "and diskUuid : " + diskUuid);
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
ClusterMO cluster = new ClusterMO(context, morCluster);
List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
HostMO host = new HostMO(context, lstHosts.get(0).first());
HostDatastoreSystemMO hostDatastoreSystem = host.getHostDatastoreSystemMO();
return hostDatastoreSystem.createNfsDatastore(storageHost, storagePort, iScsiName, diskUuid);
} else {
return getVmfsDatastore(context, hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
trimIqn(iScsiName), chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
}
}
private ManagedObjectReference getVmfsDatastore(VmwareContext context, VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber,
@ -2006,10 +2025,11 @@ public class VmwareStorageProcessor implements StorageProcessor {
return tmp[1].trim();
}
public ManagedObjectReference prepareManagedStorage(VmwareContext context, VmwareHypervisorHost hyperHost, String iScsiName,
public ManagedObjectReference prepareManagedStorage(VmwareContext context, VmwareHypervisorHost hyperHost, String diskUuid, String iScsiName,
String storageHost, int storagePort, String volumeName, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception {
ManagedObjectReference morDs = prepareManagedDatastore(context, hyperHost, iScsiName, storageHost, storagePort,
ManagedObjectReference morDs = prepareManagedDatastore(context, hyperHost, diskUuid, iScsiName, storageHost, storagePort,
chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs);
@ -2030,8 +2050,15 @@ public class VmwareStorageProcessor implements StorageProcessor {
removeVmfsDatastore(hyperHost, datastoreName, storageHost, storagePort, trimIqn(iqn));
}
private void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception {
handleDatastoreAndVmdkDetach(VmwareResource.getDatastoreName(iqn), iqn, storageHost, storagePort);
private void handleDatastoreAndVmdkDetachManaged(String diskUuid, String iqn, String storageHost, int storagePort) throws Exception {
if (storagePort == DEFAULT_NFS_PORT) {
VmwareContext context = hostService.getServiceContext(null);
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
// for managed NFS datastore
hyperHost.unmountDatastore(diskUuid);
} else {
handleDatastoreAndVmdkDetach(VmwareResource.getDatastoreName(iqn), iqn, storageHost, storagePort);
}
}
private void removeManagedTargetsFromCluster(List<String> iqns) throws Exception {

View File

@ -19,22 +19,24 @@
package org.apache.cloudstack.storage.datastore.driver;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.util.ElastistorUtil;
@ -46,7 +48,6 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
import com.cloud.host.Host;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.ResizeVolumePayload;
import com.cloud.storage.Storage.StoragePoolType;
@ -176,7 +177,7 @@ public class ElastistorPrimaryDataStoreDriver extends CloudStackPrimaryDataStore
_volumeDao.update(volume.getId(), volume);
// create new volume details for the volume
updateVolumeDetails(volume, esvolume);
//updateVolumeDetails(volume, esvolume);
long capacityBytes = storagePool.getCapacityBytes();
long usedBytes = storagePool.getUsedBytes();
@ -373,9 +374,14 @@ public class ElastistorPrimaryDataStoreDriver extends CloudStackPrimaryDataStore
throw new CloudRuntimeException("elastistor volume snapshot failed");
}else{
s_logger.info("elastistor volume snapshot succesfull");
result = new CreateCmdResult(null, null);
result.setSuccess(answer.getResult());
result.setAnswer(answer);
snapshotTO.setPath(answer.getDetails());
CreateObjectAnswer createObjectAnswer = new CreateObjectAnswer(snapshotTO);
result = new CreateCmdResult(null, createObjectAnswer);
result.setResult(null);
}
}
catch (Throwable e) {
@ -393,20 +399,11 @@ public class ElastistorPrimaryDataStoreDriver extends CloudStackPrimaryDataStore
@Override
public Map<String, String> getCapabilities() {
// TODO Auto-generated method stub
return null;
}
Map<String, String> mapCapabilities = new HashMap<String, String>();
@Override
public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore) {
// TODO Auto-generated method stub
return false;
}
@Override
public void revokeAccess(DataObject dataObject, Host host, DataStore dataStore) {
// TODO Auto-generated method stub
mapCapabilities.put(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString(), Boolean.TRUE.toString());
return mapCapabilities;
}
}

View File

@ -113,6 +113,8 @@ public class ElastistorUtil {
public static final String REST_PARAM_AUTHNETWORK = "authnetwork";
public static final String REST_PARAM_MAPUSERSTOROOT = "mapuserstoroot";
public static final String REST_PARAM_STORAGEID = "storageid";
public static final String REST_PARAM_TPCONTROL = "tpcontrol";
public static final String REST_PARAM_IOPSCONTROL = "iopscontrol";
/**
* Constants related to elastistor which are persisted in cloudstack
@ -165,6 +167,8 @@ public class ElastistorUtil {
private static final String ES_AUTHNETWORK_VAL = "all";
private static final String ES_MAPUSERSTOROOT_VAL = "yes";
private static final String ES_SYNC_VAL = "always";
private static final String ES_TPCONTROL_VAL = "false";
private static final String ES_IOPSCONTROL_VAL = "true";
/**
* Private constructor s.t. its never instantiated.
@ -338,7 +342,8 @@ public class ElastistorUtil {
String qosgroupid;
String VolumeName = volumeName;
String totaliops = String.valueOf(capacityIops);
String totalthroughput = String.valueOf(capacityIops * 4);
//String totalthroughput = String.valueOf(capacityIops * 4);
String totalthroughput = "0";
String quotasize = convertCapacityBytes(capacityBytes);
@ -367,6 +372,10 @@ public class ElastistorUtil {
addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid);
if (null != ElastistorUtil.ES_GRACEALLOWED_VAL)
addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL);
if (null != ElastistorUtil.ES_IOPSCONTROL_VAL)
addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IOPSCONTROL, ElastistorUtil.ES_IOPSCONTROL_VAL);
if (null != ElastistorUtil.ES_TPCONTROL_VAL)
addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TPCONTROL, ElastistorUtil.ES_TPCONTROL_VAL);
AddQosGroupCmdResponse addQosGroupCmdResponse = (AddQosGroupCmdResponse) getElastistorRestClient().executeCommand(addQosGroupCmd);
@ -2423,7 +2432,7 @@ public class ElastistorUtil {
CreateStorageSnapshotCmdResponse snapshotCmdResponse = (CreateStorageSnapshotCmdResponse) getElastistorRestClient().executeCommand(snapshotCmd);
if(snapshotCmdResponse.getStorageSnapshot().getId() != null){
return new Answer(null, true, "snapshot succesfully taken");
return new Answer(null, true, snapshotCmdResponse.getStorageSnapshot().getId());
}else{
return new Answer(null, false, "snapshot failed");
}