CLOUDSTACK-6170 (VMware root-disk support for managed storage)

This commit is contained in:
Mike Tutkowski 2014-03-29 23:49:56 -06:00
parent 412af7c2e6
commit fe0c9768cf
9 changed files with 145 additions and 24 deletions

View File

@ -27,6 +27,7 @@ import com.cloud.storage.Storage.StoragePoolType;
public class PrimaryDataStoreTO implements DataStoreTO {
public static final String MANAGED = PrimaryDataStore.MANAGED;
public static final String STORAGE_HOST = PrimaryDataStore.STORAGE_HOST;
public static final String STORAGE_PORT = PrimaryDataStore.STORAGE_PORT;
public static final String MANAGED_STORE_TARGET = PrimaryDataStore.MANAGED_STORE_TARGET;
public static final String MANAGED_STORE_TARGET_ROOT_VOLUME = PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME;
public static final String CHAP_INITIATOR_USERNAME = PrimaryDataStore.CHAP_INITIATOR_USERNAME;

View File

@ -29,6 +29,7 @@ import com.cloud.storage.StoragePool;
public interface PrimaryDataStoreInfo extends StoragePool {
static final String MANAGED = "managed";
static final String STORAGE_HOST= "storageHost";
static final String STORAGE_PORT = "storagePort";
static final String MANAGED_STORE_TARGET = "managedStoreTarget";
static final String MANAGED_STORE_TARGET_ROOT_VOLUME = "managedStoreTargetRootVolume";
static final String CHAP_INITIATOR_USERNAME = "chapInitiatorUsername";

View File

@ -527,7 +527,10 @@ public class VolumeServiceImpl implements VolumeService {
TemplateObjectTO templateObjectTo = (TemplateObjectTO)answer.getNewData();
volume.setPath(templateObjectTo.getPath());
volume.setFormat(templateObjectTo.getFormat());
if (templateObjectTo.getFormat() != null) {
volume.setFormat(templateObjectTo.getFormat());
}
volDao.update(volume.getId(), volume);
}
@ -682,6 +685,7 @@ public class VolumeServiceImpl implements VolumeService {
details.put(PrimaryDataStore.MANAGED, Boolean.TRUE.toString());
details.put(PrimaryDataStore.STORAGE_HOST, destPrimaryDataStore.getHostAddress());
details.put(PrimaryDataStore.STORAGE_PORT, String.valueOf(destPrimaryDataStore.getPort()));
// for managed storage, the storage repository (XenServer) or datastore (ESX) name is based off of the iScsiName property of a volume
details.put(PrimaryDataStore.MANAGED_STORE_TARGET, volumeInfo.get_iScsiName());
details.put(PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME, volumeInfo.getName());

View File

@ -33,9 +33,14 @@ public interface VmwareHostService {
String getWorkerName(VmwareContext context, Command cmd, int workerSequence);
ManagedObjectReference prepareManagedDatastore(VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret) throws Exception;
ManagedObjectReference prepareManagedStorage(VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception;
void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception;
void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception;

View File

@ -1824,13 +1824,20 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
vmMo.ensureScsiDeviceController();
}
@Override
public ManagedObjectReference prepareManagedDatastore(VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret) throws Exception {
return getVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
VmwareResource.trimIqn(iScsiName), chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
}
@Override
public ManagedObjectReference prepareManagedStorage(VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception {
ManagedObjectReference morDs = getVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iScsiName),
storageHost, storagePort, VmwareResource.trimIqn(iScsiName), chapInitiatorUsername, chapInitiatorSecret,
chapTargetUsername, chapTargetSecret);
ManagedObjectReference morDs = prepareManagedDatastore(hyperHost, iScsiName, storageHost, storagePort,
chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
DatastoreMO dsMo = new DatastoreMO(getServiceContext(null), morDs);
@ -1908,7 +1915,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (isManaged) {
if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, dsMo.getName());
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getName());
}
else {
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");

View File

@ -314,6 +314,13 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
return _resource.getRootDir(storageUrl);
}
@Override
public ManagedObjectReference prepareManagedDatastore(VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
String chapTargetUsername, String chapTargetSecret) throws Exception {
throw new OperationNotSupportedException();
}
@Override
public ManagedObjectReference prepareManagedStorage(VmwareHypervisorHost hyperHost, String iScsiName,
String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,

View File

@ -188,44 +188,121 @@ public class VmwareStorageProcessor implements StorageProcessor {
DataTO srcData = cmd.getSrcTO();
TemplateObjectTO template = (TemplateObjectTO)srcData;
DataStoreTO srcStore = srcData.getDataStore();
if (!(srcStore instanceof NfsTO)) {
return new CopyCmdAnswer("unsupported protocol");
}
NfsTO nfsImageStore = (NfsTO)srcStore;
DataTO destData = cmd.getDestTO();
DataStoreTO destStore = destData.getDataStore();
DataStoreTO primaryStore = destStore;
String secondaryStorageUrl = nfsImageStore.getUrl();
assert (secondaryStorageUrl != null);
boolean managed = false;
String storageHost = null;
int storagePort = Integer.MIN_VALUE;
String managedStoragePoolName = null;
String managedStoragePoolRootVolumeName = null;
String chapInitiatorUsername = null;
String chapInitiatorSecret = null;
String chapTargetUsername = null;
String chapTargetSecret = null;
if (destStore instanceof PrimaryDataStoreTO) {
PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO)destStore;
Map<String, String> details = destPrimaryDataStoreTo.getDetails();
if (details != null) {
managed = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
if (managed) {
storageHost = details.get(PrimaryDataStoreTO.STORAGE_HOST);
try {
storagePort = Integer.parseInt(details.get(PrimaryDataStoreTO.STORAGE_PORT));
}
catch (Exception ex) {
storagePort = 3260;
}
managedStoragePoolName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET);
managedStoragePoolRootVolumeName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET_ROOT_VOLUME);
chapInitiatorUsername = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_USERNAME);
chapInitiatorSecret = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_SECRET);
chapTargetUsername = details.get(PrimaryDataStoreTO.CHAP_TARGET_USERNAME);
chapTargetSecret = details.get(PrimaryDataStoreTO.CHAP_TARGET_SECRET);
}
}
}
String templateUrl = secondaryStorageUrl + "/" + srcData.getPath();
Pair<String, String> templateInfo = VmwareStorageLayoutHelper.decodeTemplateRelativePathAndNameFromUrl(secondaryStorageUrl, templateUrl, template.getName());
VmwareContext context = hostService.getServiceContext(cmd);
try {
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
String templateUuidName = deriveTemplateUuidOnHost(hyperHost, primaryStore.getUuid(), templateInfo.second());
String storageUuid = managed ? managedStoragePoolName : primaryStore.getUuid();
String templateUuidName = deriveTemplateUuidOnHost(hyperHost, storageUuid, templateInfo.second());
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
DatastoreMO dsMo = null;
if (templateMo == null) {
if (s_logger.isInfoEnabled())
s_logger.info("Template " + templateInfo.second() + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
assert (morDs != null);
DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
if (s_logger.isInfoEnabled()) {
s_logger.info("Template " + templateInfo.second() + " is not setup yet. Set up template from secondary storage with uuid name: " + templateUuidName);
}
copyTemplateFromSecondaryToPrimary(hyperHost, primaryStorageDatastoreMo, secondaryStorageUrl, templateInfo.first(), templateInfo.second(),
templateUuidName);
final ManagedObjectReference morDs;
if (managed) {
morDs = hostService.prepareManagedDatastore(hyperHost, managedStoragePoolName, storageHost, storagePort,
chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
}
else {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, storageUuid);
}
assert (morDs != null);
dsMo = new DatastoreMO(context, morDs);
copyTemplateFromSecondaryToPrimary(hyperHost, dsMo, secondaryStorageUrl, templateInfo.first(), templateInfo.second(),
managed ? managedStoragePoolRootVolumeName : templateUuidName);
if (managed) {
String[] vmwareLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, managedStoragePoolRootVolumeName, managedStoragePoolRootVolumeName,
VmwareStorageLayoutType.VMWARE, false);
String[] legacyCloudStackLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, null, managedStoragePoolRootVolumeName,
VmwareStorageLayoutType.CLOUDSTACK_LEGACY, false);
dsMo.moveDatastoreFile(vmwareLayoutFilePair[0], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[0], dcMo.getMor(), true);
dsMo.moveDatastoreFile(vmwareLayoutFilePair[1], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[1], dcMo.getMor(), true);
String folderToDelete = dsMo.getDatastorePath(managedStoragePoolRootVolumeName, true);
dsMo.deleteFolder(folderToDelete, dcMo.getMor());
}
} else {
s_logger.info("Template " + templateInfo.second() + " has already been setup, skip the template setup process in primary storage");
}
TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(templateUuidName);
if (managed) {
String path = dsMo.getDatastorePath(managedStoragePoolRootVolumeName + ".vmdk");
newTemplate.setPath(path);
}
else {
newTemplate.setPath(templateUuidName);
}
return new CopyCmdAnswer(newTemplate);
} catch (Throwable e) {
if (e instanceof RemoteException) {
@ -233,7 +310,9 @@ public class VmwareStorageProcessor implements StorageProcessor {
}
String msg = "Unable to copy template to primary storage due to exception:" + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg, e);
return new CopyCmdAnswer(msg);
}
}
@ -1176,9 +1255,9 @@ public class VmwareStorageProcessor implements StorageProcessor {
Map<String, String> details = disk.getDetails();
morDs = hostService.prepareManagedStorage(hyperHost, iScsiName, storageHost, storagePort,
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);
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());
@ -1572,15 +1651,15 @@ public class VmwareStorageProcessor implements StorageProcessor {
VirtualDiskFlatVer2BackingInfo backingInfo = (VirtualDiskFlatVer2BackingInfo)virtualDisk.getBacking();
String path = backingInfo.getFileName();
path = new DatastoreFile(path).getFileBaseName();
String search = "-";
String search = "[-";
int index = path.indexOf(search);
if (index > -1) {
path = path.substring(index + search.length());
index = path.lastIndexOf(search);
String search2 = "-0]";
index = path.lastIndexOf(search2);
if (index > -1) {
path = path.substring(0, index);

View File

@ -911,7 +911,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
String chapInitiatorSecret = null;
if (destDataStoreTo instanceof PrimaryDataStoreTO) {
PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO) destDataStoreTo;
PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO)destDataStoreTo;
Map<String, String> details = destPrimaryDataStoreTo.getDetails();

View File

@ -142,6 +142,23 @@ public class DatastoreMO extends BaseMO {
return path;
}
public boolean deleteFolder(String folder, ManagedObjectReference morDc) throws Exception {
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();
ManagedObjectReference morTask = _context.getService().deleteDatastoreFileTask(morFileManager, folder, morDc);
boolean result = _context.getVimClient().waitForTask(morTask);
if (result) {
_context.waitForTaskProgressDone(morTask);
return true;
} else {
s_logger.error("VMware deleteDatastoreFile_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
}
return false;
}
public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence) throws Exception {
String datastoreName = getName();
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();