Skip to content

Commit 362ef67

Browse files
committed
CLOUDSTACK-3869: make new folder structure to work with Create/Delete/Attach/Detach commands
1 parent 9a2148f commit 362ef67

5 files changed

Lines changed: 251 additions & 83 deletions

File tree

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,6 +2610,15 @@ protected StartAnswer execute(StartCommand cmd) {
26102610
s_logger.error(msg);
26112611
throw new Exception(msg);
26122612
}
2613+
2614+
DatastoreMO dsRootVolumeIsOn = getDatastoreThatRootDiskIsOn(dataStoresDetails, disks);
2615+
if(dsRootVolumeIsOn == null) {
2616+
String msg = "Unable to locate datastore details of root volume";
2617+
s_logger.error(msg);
2618+
throw new Exception(msg);
2619+
}
2620+
2621+
DatacenterMO dcMo = new DatacenterMO(hyperHost.getContext(), hyperHost.getHyperHostDatacenter());
26132622

26142623
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
26152624
if (vmMo != null) {
@@ -2657,7 +2666,7 @@ protected StartAnswer execute(StartCommand cmd) {
26572666
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + vmInternalCSName);
26582667
}
26592668
}
2660-
2669+
26612670
int totalChangeDevices = disks.length + nics.length;
26622671
DiskTO volIso = null;
26632672
if (vmSpec.getType() != VirtualMachine.Type.User) {
@@ -2823,9 +2832,18 @@ protected StartAnswer execute(StartCommand cmd) {
28232832
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid());
28242833
assert (volumeDsDetails != null);
28252834
VirtualDevice device;
2835+
2836+
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmName, volumeDsDetails.second(),
2837+
volumeTO.getPath());
2838+
device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(),
2839+
(controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
2840+
2841+
/*
28262842
datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), volumeTO.getPath());
2843+
28272844
String chainInfo = volumeTO.getChainInfo();
28282845
2846+
// chainInfo is no longer in use
28292847
if (chainInfo != null && !chainInfo.isEmpty()) {
28302848
String[] diskChain = _gson.fromJson(chainInfo, String[].class);
28312849
if (diskChain == null || diskChain.length < 1) {
@@ -2845,6 +2863,8 @@ protected StartAnswer execute(StartCommand cmd) {
28452863
device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(),
28462864
(controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
28472865
}
2866+
*/
2867+
28482868
deviceConfigSpecArray[i].setDevice(device);
28492869
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
28502870

@@ -3110,8 +3130,6 @@ else if("RemoteDisplay.vnc.keymap".equalsIgnoreCase(entry.getKey()))
31103130
return validatedDetails;
31113131
}
31123132

3113-
3114-
31153133
private NicTO[] sortNicsByDeviceId(NicTO[] nics) {
31163134

31173135
List<NicTO> listForSort = new ArrayList<NicTO>();
@@ -3181,6 +3199,21 @@ private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastor
31813199
return poolMors;
31823200
}
31833201

3202+
private DatastoreMO getDatastoreThatRootDiskIsOn(HashMap<String ,Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails,
3203+
DiskTO disks[]) {
3204+
3205+
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
3206+
for (DiskTO vol : disks) {
3207+
if (vol.getType() == Volume.Type.ROOT) {
3208+
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore();
3209+
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
3210+
}
3211+
}
3212+
3213+
if(rootDiskDataStoreDetails != null)
3214+
return rootDiskDataStoreDetails.second();
3215+
return null;
3216+
}
31843217

31853218
private String getPvlanInfo(NicTO nicTo) {
31863219
if (nicTo.getBroadcastType() == BroadcastDomainType.Pvlan) {
@@ -4277,6 +4310,9 @@ protected Answer execute(AttachVolumeCommand cmd) {
42774310
}
42784311

42794312
DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs);
4313+
VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), cmd.getVmName(),
4314+
dsMo, cmd.getVolumePath());
4315+
42804316
String datastoreVolumePath = dsMo.searchFileInSubFolders(cmd.getVolumePath() + ".vmdk", true);
42814317
assert (datastoreVolumePath != null) : "Virtual disk file must exist in specified datastore for attach/detach operations.";
42824318
if (datastoreVolumePath == null) {
@@ -4292,6 +4328,8 @@ protected Answer execute(AttachVolumeCommand cmd) {
42924328

42934329
if (cmd.isManaged()) {
42944330
handleDatastoreAndVmdkDetach(cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort());
4331+
} else {
4332+
VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, cmd.getVolumePath());
42954333
}
42964334
}
42974335

plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java

Lines changed: 125 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
// under the License.
1717
package com.cloud.storage.resource;
1818

19+
import org.apache.log4j.Logger;
20+
1921
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
22+
import com.cloud.hypervisor.vmware.mo.DatastoreFile;
2023
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
2124
import com.cloud.utils.Pair;
2225

@@ -26,6 +29,7 @@
2629
*
2730
*/
2831
public class VmwareStorageLayoutHelper {
32+
private static final Logger s_logger = Logger.getLogger(VmwareStorageLayoutHelper.class);
2933

3034
public static String[] getVmdkFilePairDatastorePath(DatastoreMO dsMo, String vmName, String vmdkName,
3135
VmwareStorageLayoutType layoutType, boolean linkedVmdk) throws Exception {
@@ -34,21 +38,21 @@ public static String[] getVmdkFilePairDatastorePath(DatastoreMO dsMo, String vmN
3438
switch(layoutType) {
3539
case VMWARE :
3640
assert(vmName != null && !vmName.isEmpty());
37-
filePair[0] = String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmName, vmdkName);
41+
filePair[0] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + ".vmdk");
3842

3943
if(linkedVmdk)
40-
filePair[1] = String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmName, vmdkName);
44+
filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-delta.vmdk");
4145
else
42-
filePair[1] = String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmName, vmdkName);
46+
filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-flat.vmdk");
4347
return filePair;
4448

4549
case CLOUDSTACK_LEGACY :
46-
filePair[0] = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
50+
filePair[0] = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + ".vmdk");
4751

4852
if(linkedVmdk)
49-
filePair[1] = String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName);
53+
filePair[1] = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-delta.vmdk");
5054
else
51-
filePair[1] = String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName);
55+
filePair[1] = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-flat.vmdk");
5256
return filePair;
5357

5458
default :
@@ -60,6 +64,83 @@ public static String[] getVmdkFilePairDatastorePath(DatastoreMO dsMo, String vmN
6064
return null;
6165
}
6266

67+
public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmName,
68+
DatastoreMO ds, String vmdkName) throws Exception {
69+
70+
assert(ds != null);
71+
if(!ds.folderExists(String.format("[%s]", ds.getName()), vmName)) {
72+
s_logger.info("VM folder does not exist on target datastore, we will create one. vm: " + vmName + ", datastore: " + ds.getName());
73+
74+
ds.makeDirectory(String.format("[%s] %s", ds.getName(), vmName), dcMo.getMor());
75+
}
76+
77+
String[] vmdkLinkedCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName,
78+
VmwareStorageLayoutType.CLOUDSTACK_LEGACY, true);
79+
String[] vmdkFullCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName,
80+
VmwareStorageLayoutType.CLOUDSTACK_LEGACY, false);
81+
82+
String[] vmdkLinkedCloneModePair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName,
83+
VmwareStorageLayoutType.VMWARE, true);
84+
String[] vmdkFullCloneModePair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName,
85+
VmwareStorageLayoutType.VMWARE, false);
86+
87+
if(!ds.fileExists(vmdkLinkedCloneModeLegacyPair[0])) {
88+
// To protect against inconsistency caused by non-atomic datastore file management, detached disk may
89+
// be left over in its previous owner VM. We will do a fixup synchronization here by moving it to root
90+
// again
91+
//
92+
syncVolumeToRootFolder(dcMo, ds, vmdkName);
93+
}
94+
95+
if(ds.fileExists(vmdkFullCloneModeLegacyPair[1])) {
96+
s_logger.info("sync " + vmdkFullCloneModeLegacyPair[1] + "->" + vmdkFullCloneModePair[1]);
97+
98+
ds.moveDatastoreFile(vmdkFullCloneModeLegacyPair[1], dcMo.getMor(), ds.getMor(),
99+
vmdkFullCloneModePair[1], dcMo.getMor(), true);
100+
}
101+
102+
if(ds.fileExists(vmdkLinkedCloneModeLegacyPair[1])) {
103+
s_logger.info("sync " + vmdkLinkedCloneModeLegacyPair[1] + "->" + vmdkLinkedCloneModePair[1]);
104+
105+
ds.moveDatastoreFile(vmdkLinkedCloneModeLegacyPair[1], dcMo.getMor(), ds.getMor(),
106+
vmdkLinkedCloneModePair[1], dcMo.getMor(), true);
107+
}
108+
109+
s_logger.info("sync " + vmdkLinkedCloneModeLegacyPair[0] + "->" + vmdkLinkedCloneModePair[0]);
110+
ds.moveDatastoreFile(vmdkLinkedCloneModeLegacyPair[0], dcMo.getMor(), ds.getMor(),
111+
vmdkLinkedCloneModePair[0], dcMo.getMor(), true);
112+
113+
return vmdkLinkedCloneModePair[0];
114+
}
115+
116+
public static void syncVolumeToRootFolder(DatacenterMO dcMo, DatastoreMO ds, String vmdkName) throws Exception {
117+
String fileDsFullPath = ds.searchFileInSubFolders(vmdkName + ".vmdk", false);
118+
if(fileDsFullPath == null)
119+
throw new Exception("Unable to find " + vmdkName + ".vmdk in datastore: " + ds.getName());
120+
121+
DatastoreFile srcDsFile = new DatastoreFile(fileDsFullPath);
122+
String companionFilePath = srcDsFile.getCompanionPath(vmdkName + "-flat.vmdk");
123+
if(ds.fileExists(companionFilePath)) {
124+
String targetPath = getLegacyDatastorePathFromVmdkFileName(ds, vmdkName + "-flat.vmdk");
125+
126+
s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath);
127+
ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true);
128+
}
129+
130+
companionFilePath = srcDsFile.getCompanionPath(vmdkName + "-delta.vmdk");
131+
if(ds.fileExists(companionFilePath)) {
132+
String targetPath = getLegacyDatastorePathFromVmdkFileName(ds, vmdkName + "-delta.vmdk");
133+
134+
s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath);
135+
ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true);
136+
}
137+
138+
// move the identity VMDK file the last
139+
String targetPath = getLegacyDatastorePathFromVmdkFileName(ds, vmdkName + ".vmdk");
140+
s_logger.info("Fixup folder-synchronization. move " + fileDsFullPath + " -> " + targetPath);
141+
ds.moveDatastoreFile(fileDsFullPath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true);
142+
}
143+
63144
public static String getTemplateOnSecStorageFilePath(String secStorageMountPoint, String templateRelativeFolderPath,
64145
String templateName, String fileExtension) {
65146

@@ -114,13 +195,43 @@ public static Pair<String, String> decodeTemplateRelativePathAndNameFromUrl(Stri
114195
}
115196

116197
public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception {
117-
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName);
118-
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
119-
120-
volumeDatastorePath = String.format("[%s] %s-flat.vmdk", dsMo.getName(), volumeName);
121-
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
122-
123-
volumeDatastorePath = String.format("[%s] %s-delta.vmdk", dsMo.getName(), volumeName);
124-
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
198+
199+
String fileName = volumeName + ".vmdk";
200+
String fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName);
201+
if(!dsMo.fileExists(fileFullPath))
202+
fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
203+
if(fileFullPath != null) {
204+
dsMo.deleteFile(fileFullPath, dcMo.getMor(), false);
205+
} else {
206+
s_logger.warn("Unable to locate VMDK file: " + fileName);
207+
}
208+
209+
fileName = volumeName + "-flat.vmdk";
210+
fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName);
211+
if(!dsMo.fileExists(fileFullPath))
212+
fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
213+
if(fileFullPath != null) {
214+
dsMo.deleteFile(fileFullPath, dcMo.getMor(), false);
215+
} else {
216+
s_logger.warn("Unable to locate VMDK file: " + fileName);
217+
}
218+
219+
fileName = volumeName + "-delta.vmdk";
220+
fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName);
221+
if(!dsMo.fileExists(fileFullPath))
222+
fileFullPath = dsMo.searchFileInSubFolders(fileName, false);
223+
if(fileFullPath != null) {
224+
dsMo.deleteFile(fileFullPath, dcMo.getMor(), false);
225+
} else {
226+
s_logger.warn("Unable to locate VMDK file: " + fileName);
227+
}
228+
}
229+
230+
public static String getLegacyDatastorePathFromVmdkFileName(DatastoreMO dsMo, String vmdkFileName) throws Exception {
231+
return String.format("[%s] %s", dsMo.getName(), vmdkFileName);
232+
}
233+
234+
public static String getVmwareDatastorePathFromVmdkFileName(DatastoreMO dsMo, String vmName, String vmdkFileName) throws Exception {
235+
return String.format("[%s] %s/%s", dsMo.getName(), vmName, vmdkFileName);
125236
}
126237
}

0 commit comments

Comments
 (0)