diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java index d10c63bb3dd..b3564885447 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java @@ -16,8 +16,11 @@ // under the License. package com.cloud.storage.resource; +import java.util.Arrays; import java.util.List; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; import org.apache.log4j.Logger; import com.cloud.hypervisor.vmware.mo.DatacenterMO; @@ -32,32 +35,49 @@ import com.cloud.utils.Pair; * To provide helper methods to handle storage layout in one place * */ -public class VmwareStorageLayoutHelper { +public class VmwareStorageLayoutHelper implements Configurable { private static final Logger s_logger = Logger.getLogger(VmwareStorageLayoutHelper.class); + static final ConfigKey VsphereLinkedCloneExtensions = new ConfigKey("Hidden", String.class, + "vsphere.linked.clone.extensions", "delta.vmdk,sesparse.vmdk", + "Comma separated list of linked clone disk formats allowed to handle storage in VMware", true); + + public static String[] getVmdkFilePairDatastorePath(DatastoreMO dsMo, String vmName, String vmdkName, VmwareStorageLayoutType layoutType, boolean linkedVmdk) throws Exception { - String[] filePair = new String[2]; + int i = 0; + String[] vSphereLinkedCloneExtensions = VsphereLinkedCloneExtensions.value().trim().split("\\s*,\\s*"); + String[] fileNames; + if (linkedVmdk) + fileNames = new String[vSphereLinkedCloneExtensions.length + 1]; + else + fileNames = new String[2]; + switch (layoutType) { case VMWARE: assert (vmName != null && !vmName.isEmpty()); - filePair[0] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + ".vmdk"); + fileNames[i] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + ".vmdk"); - if (linkedVmdk) - filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-delta.vmdk"); + if (linkedVmdk) { + for (int j=0 ; j < vSphereLinkedCloneExtensions.length; j++) { + fileNames[++i] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, String.format("%s-%s",vmdkName, vSphereLinkedCloneExtensions[j])); + } + } else - filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-flat.vmdk"); - return filePair; + fileNames[i+1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-flat.vmdk"); + return fileNames; case CLOUDSTACK_LEGACY: - filePair[0] = getDatastorePathBaseFolderFromVmdkFileName(dsMo, vmdkName + ".vmdk"); + fileNames[i] = getDatastorePathBaseFolderFromVmdkFileName(dsMo, vmdkName + ".vmdk"); - if (linkedVmdk) - filePair[1] = getDatastorePathBaseFolderFromVmdkFileName(dsMo, vmdkName + "-delta.vmdk"); - else - filePair[1] = getDatastorePathBaseFolderFromVmdkFileName(dsMo, vmdkName + "-flat.vmdk"); - return filePair; + if (linkedVmdk) { + for (int j=0 ; j < vSphereLinkedCloneExtensions.length; j++) { + fileNames[++i] = getDatastorePathBaseFolderFromVmdkFileName(dsMo, String.format("%s-%s",vmdkName, vSphereLinkedCloneExtensions[j])); + } + } else + fileNames[i+1] = getDatastorePathBaseFolderFromVmdkFileName(dsMo, vmdkName + "-flat.vmdk"); + return fileNames; default: assert (false); @@ -71,26 +91,37 @@ public class VmwareStorageLayoutHelper { public static String[] getVmdkFilePairManagedDatastorePath(DatastoreMO dsMo, String vmName, String vmdkName, VmwareStorageLayoutType layoutType, boolean linkedVmdk) throws Exception { - String[] filePair = new String[2]; + int i = 0; + String[] vSphereLinkedCloneExtensions = VsphereLinkedCloneExtensions.value().trim().split("\\s*,\\s*"); + String[] fileNames; + if (linkedVmdk) + fileNames = new String[vSphereLinkedCloneExtensions.length + 1]; + else + fileNames = new String[2]; + switch (layoutType) { case VMWARE: assert (vmName != null && !vmName.isEmpty()); - filePair[0] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + ".vmdk"); + fileNames[i] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + ".vmdk"); - if (linkedVmdk) - filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-delta.vmdk"); - else - filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-flat.vmdk"); - return filePair; + if (linkedVmdk) { + for (int j=0 ; j < vSphereLinkedCloneExtensions.length; j++) { + fileNames[++i] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, String.format("%s-%s",vmdkName, vSphereLinkedCloneExtensions[j])); + } + } else + fileNames[i+1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-flat.vmdk"); + return fileNames; case CLOUDSTACK_LEGACY: - filePair[0] = getDeprecatedLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + ".vmdk"); + fileNames[i] = getDeprecatedLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + ".vmdk"); - if (linkedVmdk) - filePair[1] = getDeprecatedLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-delta.vmdk"); - else - filePair[1] = getDeprecatedLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-flat.vmdk"); - return filePair; + if (linkedVmdk) { + for (int j=0 ; j < vSphereLinkedCloneExtensions.length; j++) { + fileNames[++i] = getDeprecatedLegacyDatastorePathFromVmdkFileName(dsMo, String.format("%s-%s",vmdkName, vSphereLinkedCloneExtensions[j])); + } + } else + fileNames[i+1] = getDeprecatedLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-flat.vmdk"); + return fileNames; default: assert (false); @@ -156,16 +187,20 @@ public class VmwareStorageLayoutHelper { syncVolumeToRootFolder(dcMo, ds, vmdkName, vmName, excludeFolders); } - if (ds.fileExists(vmdkFullCloneModeLegacyPair[1])) { - s_logger.info("sync " + vmdkFullCloneModeLegacyPair[1] + "->" + vmdkFullCloneModePair[1]); + for (int i=1; i" + vmdkFullCloneModePair[i]); - ds.moveDatastoreFile(vmdkFullCloneModeLegacyPair[1], dcMo.getMor(), ds.getMor(), vmdkFullCloneModePair[1], dcMo.getMor(), true); + ds.moveDatastoreFile(vmdkFullCloneModeLegacyPair[i], dcMo.getMor(), ds.getMor(), vmdkFullCloneModePair[i], dcMo.getMor(), true); + } } - if (ds.fileExists(vmdkLinkedCloneModeLegacyPair[1])) { - s_logger.info("sync " + vmdkLinkedCloneModeLegacyPair[1] + "->" + vmdkLinkedCloneModePair[1]); + for (int i=1; i" + vmdkLinkedCloneModePair[i]); - ds.moveDatastoreFile(vmdkLinkedCloneModeLegacyPair[1], dcMo.getMor(), ds.getMor(), vmdkLinkedCloneModePair[1], dcMo.getMor(), true); + ds.moveDatastoreFile(vmdkLinkedCloneModeLegacyPair[i], dcMo.getMor(), ds.getMor(), vmdkLinkedCloneModePair[i], dcMo.getMor(), true); + } } if (ds.fileExists(vmdkLinkedCloneModeLegacyPair[0])) { @@ -192,20 +227,18 @@ public class VmwareStorageLayoutHelper { } DatastoreFile srcDsFile = new DatastoreFile(fileDsFullPath); - String companionFilePath = srcDsFile.getCompanionPath(vmdkName + "-flat.vmdk"); - if (ds.fileExists(companionFilePath)) { - String targetPath = getDatastorePathBaseFolderFromVmdkFileName(ds, vmdkName + "-flat.vmdk"); - s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath); - ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true); - } + List vSphereFileExtensions = Arrays.asList(VsphereLinkedCloneExtensions.value().trim().split("\\s*,\\s*")); + // add flat file format to the above list + vSphereFileExtensions.add("flat.vmdk"); + for (String linkedCloneExtension : vSphereFileExtensions) { + String companionFilePath = srcDsFile.getCompanionPath(String.format("%s-%s",vmdkName, linkedCloneExtension)); + if (ds.fileExists(companionFilePath)) { + String targetPath = getDatastorePathBaseFolderFromVmdkFileName(ds, String.format("%s-%s",vmdkName, linkedCloneExtension)); - companionFilePath = srcDsFile.getCompanionPath(vmdkName + "-delta.vmdk"); - if (ds.fileExists(companionFilePath)) { - String targetPath = getDatastorePathBaseFolderFromVmdkFileName(ds, vmdkName + "-delta.vmdk"); - - s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath); - ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true); + s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath); + ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true); + } } // move the identity VMDK file the last @@ -234,18 +267,16 @@ public class VmwareStorageLayoutHelper { s_logger.info("Move " + file.getPath() + " -> " + targetFile.getPath()); dsMo.moveDatastoreFile(file.getPath(), dcMo.getMor(), dsMo.getMor(), targetFile.getPath(), dcMo.getMor(), true); - String pairSrcFilePath = file.getCompanionPath(file.getFileBaseName() + "-flat.vmdk"); - String pairTargetFilePath = targetFile.getCompanionPath(file.getFileBaseName() + "-flat.vmdk"); - if (dsMo.fileExists(pairSrcFilePath)) { - s_logger.info("Move " + pairSrcFilePath + " -> " + pairTargetFilePath); - dsMo.moveDatastoreFile(pairSrcFilePath, dcMo.getMor(), dsMo.getMor(), pairTargetFilePath, dcMo.getMor(), true); - } - - pairSrcFilePath = file.getCompanionPath(file.getFileBaseName() + "-delta.vmdk"); - pairTargetFilePath = targetFile.getCompanionPath(file.getFileBaseName() + "-delta.vmdk"); - if (dsMo.fileExists(pairSrcFilePath)) { - s_logger.info("Move " + pairSrcFilePath + " -> " + pairTargetFilePath); - dsMo.moveDatastoreFile(pairSrcFilePath, dcMo.getMor(), dsMo.getMor(), pairTargetFilePath, dcMo.getMor(), true); + List vSphereFileExtensions = Arrays.asList(VsphereLinkedCloneExtensions.value().trim().split("\\s*,\\s*")); + // add flat file format to the above list + vSphereFileExtensions.add("flat.vmdk"); + for (String linkedCloneExtension : vSphereFileExtensions) { + String pairSrcFilePath = file.getCompanionPath(String.format("%s-%s", file.getFileBaseName(), linkedCloneExtension)); + String pairTargetFilePath = targetFile.getCompanionPath(String.format("%s-%s", file.getFileBaseName(), linkedCloneExtension)); + if (dsMo.fileExists(pairSrcFilePath)) { + s_logger.info("Move " + pairSrcFilePath + " -> " + pairTargetFilePath); + dsMo.moveDatastoreFile(pairSrcFilePath, dcMo.getMor(), dsMo.getMor(), pairTargetFilePath, dcMo.getMor(), true); + } } } } else { @@ -322,24 +353,17 @@ public class VmwareStorageLayoutHelper { s_logger.warn("Unable to locate VMDK file: " + fileName); } - fileName = volumeName + "-flat.vmdk"; - fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); - if (!dsMo.fileExists(fileFullPath)) - fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders); - if (fileFullPath != null) { - dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders); - } else { - s_logger.warn("Unable to locate VMDK file: " + fileName); - } - - fileName = volumeName + "-delta.vmdk"; - fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); - if (!dsMo.fileExists(fileFullPath)) - fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders); - if (fileFullPath != null) { - dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders); - } else { - s_logger.warn("Unable to locate VMDK file: " + fileName); + List vSphereFileExtensions = Arrays.asList(VsphereLinkedCloneExtensions.value().trim().split("\\s*,\\s*")); + vSphereFileExtensions.add("flat.vmdk"); + for (String linkedCloneExtension : vSphereFileExtensions) { + fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, String.format("%s-%s", volumeName, linkedCloneExtension)); + if (!dsMo.fileExists(fileFullPath)) + fileFullPath = dsMo.searchFileInSubFolders(String.format("%s-%s", volumeName, linkedCloneExtension), false, excludeFolders); + if (fileFullPath != null) { + dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders); + } else { + s_logger.warn("Unable to locate VMDK file: " + String.format("%s-%s", volumeName, linkedCloneExtension)); + } } } @@ -364,4 +388,14 @@ public class VmwareStorageLayoutHelper { public static String getVmwareDatastorePathFromVmdkFileName(DatastoreMO dsMo, String vmName, String vmdkFileName) throws Exception { return String.format("[%s] %s/%s", dsMo.getName(), vmName, vmdkFileName); } + + @Override + public String getConfigComponentName() { + return VmwareStorageLayoutHelper.class.getSimpleName(); + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[] {VsphereLinkedCloneExtensions}; + } } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 22d0a92aea6..e1c16589692 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -671,7 +671,9 @@ public class VmwareStorageProcessor implements StorageProcessor { 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); + for (int i=1; i