From ff7ef985f1f6af6ac5b0179002109d30c9ab3512 Mon Sep 17 00:00:00 2001 From: punith-cloudbyte Date: Fri, 27 Feb 2015 15:50:25 +0530 Subject: [PATCH] NFS support for VMware-managed storage Signed-off-by: Mike Tutkowski --- .../vmware/resource/VmwareResource.java | 2 +- .../resource/VmwareStorageProcessor.java | 61 +++++++++++++------ .../ElastistorPrimaryDataStoreDriver.java | 33 +++++----- .../datastore/util/ElastistorUtil.java | 13 +++- 4 files changed, 71 insertions(+), 38 deletions(-) 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 b1a438019d1..7bf779c6745 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -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), 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 e601bb44052..c569a506e46 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -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 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> 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 iqns) throws Exception { diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java index 770dcb969fd..2ea0a594e1e 100644 --- a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java @@ -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 getCapabilities() { - // TODO Auto-generated method stub - return null; - } + Map mapCapabilities = new HashMap(); - @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; } } diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java index 7e1a5cb3f87..564ba8ef296 100644 --- a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java @@ -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"); }