@@ -2849,7 +2849,8 @@ protected StartAnswer execute(StartCommand cmd) {
28492849 if (vol .getType () == Volume .Type .ISO )
28502850 continue ;
28512851
2852- controllerKey = getDiskController (vol , vmSpec , ideControllerKey , scsiControllerKey );
2852+ VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDisk (diskInfoBuilder , vol );
2853+ controllerKey = getDiskController (matchingExistingDisk , vol , vmSpec , ideControllerKey , scsiControllerKey );
28532854
28542855 VolumeObjectTO volumeTO = (VolumeObjectTO )vol .getData ();
28552856 PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO )volumeTO .getDataStore ();
@@ -2858,19 +2859,16 @@ protected StartAnswer execute(StartCommand cmd) {
28582859 VirtualDevice device ;
28592860
28602861 String [] diskChain = syncDiskChain (dcMo , vmMo , vmSpec ,
2861- vol , diskInfoBuilder ,
2862- dataStoresDetails ,
2863- (controllerKey == ideControllerKey ) ? true : false ,
2864- 0 , // currently only support bus 0
2865- (controllerKey == ideControllerKey ) ? ideUnitNumber : scsiUnitNumber );
2862+ vol , matchingExistingDisk ,
2863+ dataStoresDetails );
28662864
2867- device = VmwareHelper .prepareDiskDevice (vmMo , controllerKey ,
2865+ device = VmwareHelper .prepareDiskDevice (vmMo , null , controllerKey ,
28682866 diskChain ,
28692867 volumeDsDetails .first (),
28702868 (controllerKey == ideControllerKey ) ? ideUnitNumber ++ : scsiUnitNumber ++, i + 1 );
28712869
28722870 deviceConfigSpecArray [i ].setDevice (device );
2873- deviceConfigSpecArray [i ].setOperation (VirtualDeviceConfigSpecOperation .ADD );
2871+ deviceConfigSpecArray [i ].setOperation (VirtualDeviceConfigSpecOperation .ADD );
28742872
28752873 if (s_logger .isDebugEnabled ())
28762874 s_logger .debug ("Prepare volume at new device " + _gson .toJson (device ));
@@ -3013,55 +3011,37 @@ int getReservedCpuMHZ(VirtualMachineTO vmSpec) {
30133011
30143012 // return the finalized disk chain for startup, from top to bottom
30153013 private String [] syncDiskChain (DatacenterMO dcMo , VirtualMachineMO vmMo , VirtualMachineTO vmSpec ,
3016- DiskTO vol , VirtualMachineDiskInfoBuilder diskInfoBuilder ,
3017- HashMap <String ,Pair <ManagedObjectReference , DatastoreMO >> dataStoresDetails ,
3018- boolean ideController , int deviceBusNumber , int deviceUnitNumber ) throws Exception {
3014+ DiskTO vol , VirtualMachineDiskInfo diskInfo ,
3015+ HashMap <String ,Pair <ManagedObjectReference , DatastoreMO >> dataStoresDetails
3016+ ) throws Exception {
30193017
30203018 VolumeObjectTO volumeTO = (VolumeObjectTO )vol .getData ();
30213019 PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO )volumeTO .getDataStore ();
30223020
3023- String deviceBusName ;
3024- if (ideController )
3025- deviceBusName = String .format ("ide%d:%d" , deviceBusNumber , deviceUnitNumber );
3026- else
3027- deviceBusName = String .format ("scsi%d:%d" , deviceBusNumber , deviceUnitNumber );
3028-
30293021 Pair <ManagedObjectReference , DatastoreMO > volumeDsDetails = dataStoresDetails .get (primaryStore .getUuid ());
30303022 if (volumeDsDetails == null )
30313023 throw new Exception ("Primary datastore " + primaryStore .getUuid () + " is not mounted on host." );
30323024 DatastoreMO dsMo = volumeDsDetails .second ();
30333025
30343026 // we will honor vCenter's meta if it exists
3035- if (diskInfoBuilder != null && diskInfoBuilder . getDiskCount () > 0 ) {
3036- // we will always on-disk info from vCenter in this case
3037- VirtualMachineDiskInfo diskInfo = diskInfoBuilder . getDiskInfoByDeviceBusName ( deviceBusName );
3038- if ( diskInfo != null ) {
3039- if ( s_logger . isInfoEnabled ())
3040- s_logger . info ( "Volume " + volumeTO . getId () + " does not seem to exist on datastore. use on-disk chain: " +
3041- _gson . toJson ( diskInfo ) );
3042-
3043- return diskInfo . getDiskChain ( );
3044- } else {
3045- s_logger . warn ( "Volume " + volumeTO . getId () + " does not seem to exist on datastore. on-disk may be out of sync as well. disk device info: " + deviceBusName );
3046- }
3047- }
3027+ if (diskInfo != null ) {
3028+ // to deal with run-time upgrade to maintain the new datastore folder structure
3029+ String disks [] = diskInfo . getDiskChain ( );
3030+ for ( int i = 0 ; i < disks . length ; i ++ ) {
3031+ DatastoreFile file = new DatastoreFile ( disks [ i ]);
3032+ if ( file . getDir () != null && file . getDir (). isEmpty ()) {
3033+ s_logger . info ( "Perform run-time datastore folder upgrade. sync " + disks [ i ] + " to VM folder" );
3034+ disks [ i ] = VmwareStorageLayoutHelper . syncVolumeToVmDefaultFolder (
3035+ dcMo , vmMo . getName (), dsMo , file . getFileBaseName () );
3036+ }
3037+ }
3038+ return disks ;
3039+ }
30483040
30493041 String datastoreDiskPath = VmwareStorageLayoutHelper .syncVolumeToVmDefaultFolder (
30503042 dcMo , vmMo .getName (), dsMo , volumeTO .getPath ());
30513043 if (!dsMo .fileExists (datastoreDiskPath )) {
3052- if (s_logger .isInfoEnabled ())
3053- s_logger .info ("Volume " + volumeTO .getId () + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath );
3054-
3055- // last resort, try chain info stored in DB
3056- if (volumeTO .getChainInfo () != null ) {
3057- VirtualMachineDiskInfo diskInfo = _gson .fromJson (volumeTO .getChainInfo (), VirtualMachineDiskInfo .class );
3058- if (diskInfo != null ) {
3059- s_logger .info ("Use chain info from DB: " + volumeTO .getChainInfo ());
3060- return diskInfo .getDiskChain ();
3061- }
3062-
3063- throw new Exception ("Volume " + volumeTO .getId () + " does not seem to exist on datastore. Broken disk chain" );
3064- }
3044+ s_logger .warn ("Volume " + volumeTO .getId () + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath );
30653045 }
30663046
30673047 return new String [] { datastoreDiskPath };
@@ -3271,21 +3251,80 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi
32713251 }
32723252 }
32733253
3274- private static int getDiskController (DiskTO vol , VirtualMachineTO vmSpec , int ideControllerKey , int scsiControllerKey ) {
3254+ private VirtualMachineDiskInfo getMatchingExistingDisk (VirtualMachineDiskInfoBuilder diskInfoBuilder , DiskTO vol ) {
3255+ if (diskInfoBuilder != null ) {
3256+ VolumeObjectTO volume = (VolumeObjectTO )vol .getData ();
3257+
3258+ VirtualMachineDiskInfo diskInfo = diskInfoBuilder .getDiskInfoByBackingFileBaseName (volume .getPath ());
3259+ if (diskInfo != null ) {
3260+ s_logger .info ("Found existing disk info from volume path: " + volume .getPath ());
3261+ return diskInfo ;
3262+ } else {
3263+ String chainInfo = volume .getChainInfo ();
3264+ if (chainInfo != null ) {
3265+ VirtualMachineDiskInfo infoInChain = _gson .fromJson (chainInfo , VirtualMachineDiskInfo .class );
3266+ if (infoInChain != null ) {
3267+ String [] disks = infoInChain .getDiskChain ();
3268+ if (disks .length > 0 ) {
3269+ for (String diskPath : disks ) {
3270+ DatastoreFile file = new DatastoreFile (diskPath );
3271+ diskInfo = diskInfoBuilder .getDiskInfoByBackingFileBaseName (file .getFileBaseName ());
3272+ if (diskInfo != null ) {
3273+ s_logger .info ("Found existing disk from chain info: " + diskPath );
3274+ return diskInfo ;
3275+ }
3276+ }
3277+ }
3278+
3279+ if (diskInfo == null ) {
3280+ diskInfo = diskInfoBuilder .getDiskInfoByDeviceBusName (infoInChain .getDiskDeviceBusName ());
3281+ if (diskInfo != null ) {
3282+ s_logger .info ("Found existing disk from from chain device bus information: " + infoInChain .getDiskDeviceBusName ());
3283+ return diskInfo ;
3284+ }
3285+ }
3286+ }
3287+ }
3288+ }
3289+ }
3290+
3291+ return null ;
3292+ }
3293+
3294+ private int getDiskController (VirtualMachineDiskInfo matchingExistingDisk , DiskTO vol ,
3295+ VirtualMachineTO vmSpec , int ideControllerKey , int scsiControllerKey ) {
3296+
32753297 int controllerKey ;
3298+ if (matchingExistingDisk != null ) {
3299+ s_logger .info ("Chose disk controller based on existing information: " + matchingExistingDisk .getDiskDeviceBusName ());
3300+ if (matchingExistingDisk .getDiskDeviceBusName ().startsWith ("ide" ))
3301+ return ideControllerKey ;
3302+ else
3303+ return scsiControllerKey ;
3304+ }
32763305
32773306 if (vol .getType () == Volume .Type .ROOT ) {
3278- if (vmSpec .getDetails () != null && vmSpec .getDetails ().get (VmDetailConstants .ROOK_DISK_CONTROLLER ) != null )
3307+ Map <String , String > vmDetails = vmSpec .getDetails ();
3308+ if (vmDetails != null && vmDetails .get (VmDetailConstants .ROOK_DISK_CONTROLLER ) != null )
32793309 {
3280- if (vmSpec .getDetails ().get (VmDetailConstants .ROOK_DISK_CONTROLLER ).equalsIgnoreCase ("scsi" ))
3310+ if (vmDetails .get (VmDetailConstants .ROOK_DISK_CONTROLLER ).equalsIgnoreCase ("scsi" )) {
3311+ s_logger .info ("Chose disk controller for vol " + vol .getType () + " -> scsi, based on root disk controller settings: "
3312+ + vmDetails .get (VmDetailConstants .ROOK_DISK_CONTROLLER ));
32813313 controllerKey = scsiControllerKey ;
3282- else
3314+ }
3315+ else {
3316+ s_logger .info ("Chose disk controller for vol " + vol .getType () + " -> ide, based on root disk controller settings: "
3317+ + vmDetails .get (VmDetailConstants .ROOK_DISK_CONTROLLER ));
32833318 controllerKey = ideControllerKey ;
3319+ }
32843320 } else {
3321+ s_logger .info ("Chose disk controller for vol " + vol .getType () + " -> scsi. due to null root disk controller setting" );
32853322 controllerKey = scsiControllerKey ;
32863323 }
3324+
32873325 } else {
32883326 // DATA volume always use SCSI device
3327+ s_logger .info ("Chose disk controller for vol " + vol .getType () + " -> scsi" );
32893328 controllerKey = scsiControllerKey ;
32903329 }
32913330
@@ -3296,25 +3335,14 @@ private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO v
32963335 int ideControllerKey , int scsiControllerKey ) throws Exception {
32973336
32983337 VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo .getDiskInfoBuilder ();
3299- int controllerKey ;
3300- int ideUnitNumber = 1 ; // we always count in IDE device first
3301- int scsiUnitNumber = 0 ;
33023338
33033339 for (DiskTO vol : sortedDisks ) {
33043340 if (vol .getType () == Volume .Type .ISO )
33053341 continue ;
33063342
33073343 VolumeObjectTO volumeTO = (VolumeObjectTO )vol .getData ();
33083344
3309- controllerKey = getDiskController (vol , vmSpec , ideControllerKey , scsiControllerKey );
3310-
3311- String deviceBusName ;
3312- if (controllerKey == ideControllerKey )
3313- deviceBusName = String .format ("ide%d:%d" , 0 , ideUnitNumber ++);
3314- else
3315- deviceBusName = String .format ("scsi%d:%d" , 0 , scsiUnitNumber ++);
3316-
3317- VirtualMachineDiskInfo diskInfo = diskInfoBuilder .getDiskInfoByDeviceBusName (deviceBusName );
3345+ VirtualMachineDiskInfo diskInfo = getMatchingExistingDisk (diskInfoBuilder , vol );
33183346 assert (diskInfo != null );
33193347
33203348 String [] diskChain = diskInfo .getDiskChain ();
0 commit comments