1616// under the License.
1717package com .cloud .storage .resource ;
1818
19+ import org .apache .log4j .Logger ;
20+
1921import com .cloud .hypervisor .vmware .mo .DatacenterMO ;
22+ import com .cloud .hypervisor .vmware .mo .DatastoreFile ;
2023import com .cloud .hypervisor .vmware .mo .DatastoreMO ;
2124import com .cloud .utils .Pair ;
2225
2629 *
2730 */
2831public 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