4040import javax .inject .Inject ;
4141import javax .naming .ConfigurationException ;
4242
43- import com .cloud .deployasis .dao .UserVmDeployAsIsDetailsDao ;
4443import org .apache .cloudstack .affinity .dao .AffinityGroupVMMapDao ;
4544import org .apache .cloudstack .api .ApiConstants ;
4645import org .apache .cloudstack .api .command .admin .vm .MigrateVMCmd ;
142141import com .cloud .deploy .DeploymentPlanner ;
143142import com .cloud .deploy .DeploymentPlanner .ExcludeList ;
144143import com .cloud .deploy .DeploymentPlanningManager ;
144+ import com .cloud .deployasis .dao .UserVmDeployAsIsDetailsDao ;
145145import com .cloud .event .EventTypes ;
146146import com .cloud .event .UsageEventUtils ;
147147import com .cloud .event .UsageEventVO ;
@@ -2210,23 +2210,17 @@ private void orchestrateStorageMigration(final String vmUuid, final StoragePool
22102210 }
22112211 }
22122212
2213- private Answer [] attemptHypervisorMigration (StoragePool destPool , VMInstanceVO vm ) {
2213+ private Answer [] attemptHypervisorMigration (StoragePool destPool , VMInstanceVO vm , Long hostId ) {
2214+ if (hostId == null ) {
2215+ return null ;
2216+ }
22142217 final HypervisorGuru hvGuru = _hvGuruMgr .getGuru (vm .getHypervisorType ());
22152218 // OfflineVmwareMigration: in case of vmware call vcenter to do it for us.
22162219 // OfflineVmwareMigration: should we check the proximity of source and destination
22172220 // OfflineVmwareMigration: if we are in the same cluster/datacentre/pool or whatever?
22182221 // OfflineVmwareMigration: we are checking on success to optionally delete an old vm if we are not
22192222 List <Command > commandsToSend = hvGuru .finalizeMigrate (vm , destPool );
22202223
2221- Long hostId = vm .getHostId ();
2222- // OfflineVmwareMigration: probably this is null when vm is stopped
2223- if (hostId == null ) {
2224- hostId = vm .getLastHostId ();
2225- if (s_logger .isDebugEnabled ()) {
2226- s_logger .debug (String .format ("host id is null, using last host id %d" , hostId ) );
2227- }
2228- }
2229-
22302224 if (CollectionUtils .isNotEmpty (commandsToSend )) {
22312225 Commands commandsContainer = new Commands (Command .OnError .Stop );
22322226 commandsContainer .addCommands (commandsToSend );
@@ -2241,7 +2235,7 @@ private Answer[] attemptHypervisorMigration(StoragePool destPool, VMInstanceVO v
22412235 return null ;
22422236 }
22432237
2244- private void afterHypervisorMigrationCleanup (StoragePool destPool , VMInstanceVO vm , HostVO srcHost , Long srcClusterId , Answer [] hypervisorMigrationResults ) throws InsufficientCapacityException {
2238+ private void afterHypervisorMigrationCleanup (StoragePool destPool , VMInstanceVO vm , Long srcClusterId , Answer [] hypervisorMigrationResults ) throws InsufficientCapacityException {
22452239 boolean isDebugEnabled = s_logger .isDebugEnabled ();
22462240 if (isDebugEnabled ) {
22472241 String msg = String .format ("cleaning up after hypervisor pool migration volumes for VM %s(%s) to pool %s(%s)" , vm .getInstanceName (), vm .getUuid (), destPool .getName (), destPool .getUuid ());
@@ -2250,18 +2244,23 @@ private void afterHypervisorMigrationCleanup(StoragePool destPool, VMInstanceVO
22502244 setDestinationPoolAndReallocateNetwork (destPool , vm );
22512245 // OfflineVmwareMigration: don't set this to null or have another way to address the command; twice migrating will lead to an NPE
22522246 Long destPodId = destPool .getPodId ();
2253- Long vmPodId = vm . getPodIdToDeployIn ();
2254- if (destPodId == null || ! destPodId .equals (vmPodId )) {
2247+
2248+ if (destPodId == null || !destPodId .equals (vm . getPodIdToDeployIn () )) {
22552249 if (isDebugEnabled ) {
22562250 String msg = String .format ("resetting lasHost for VM %s(%s) as pod (%s) is no good." , vm .getInstanceName (), vm .getUuid (), destPodId );
22572251 s_logger .debug (msg );
22582252 }
2259-
22602253 vm .setLastHostId (null );
22612254 vm .setPodIdToDeployIn (destPodId );
22622255 // OfflineVmwareMigration: a consecutive migration will fail probably (no host not pod)
2263- }// else keep last host set for this vm
2264- markVolumesInPool (vm ,destPool , hypervisorMigrationResults );
2256+ } else if (srcClusterId != null && destPool .getClusterId () != null && !srcClusterId .equals (destPool .getClusterId ())) {
2257+ if (isDebugEnabled ) {
2258+ String msg = String .format ("resetting lasHost for VM %s(%s) as cluster changed" , vm .getInstanceName (), vm .getUuid ());
2259+ s_logger .debug (msg );
2260+ }
2261+ vm .setLastHostId (null );
2262+ } // else keep last host set for this vm
2263+ markVolumesInPool (vm , destPool , hypervisorMigrationResults );
22652264 // OfflineVmwareMigration: deal with answers, if (hypervisorMigrationResults.length > 0)
22662265 // OfflineVmwareMigration: iterate over the volumes for data updates
22672266 }
@@ -2295,23 +2294,60 @@ private void markVolumesInPool(VMInstanceVO vm, StoragePool destPool, Answer[] h
22952294 }
22962295 }
22972296
2297+ private Pair <Long , Long > findClusterAndHostIdForVm (VMInstanceVO vm ) {
2298+ Long hostId = vm .getHostId ();
2299+ Long clusterId = null ;
2300+ // OfflineVmwareMigration: probably this is null when vm is stopped
2301+ if (hostId == null ) {
2302+ hostId = vm .getLastHostId ();
2303+ if (s_logger .isDebugEnabled ()) {
2304+ s_logger .debug (String .format ("host id is null, using last host id %d" , hostId ) );
2305+ }
2306+ }
2307+ if (hostId == null ) {
2308+ List <VolumeVO > volumes = _volsDao .findByInstanceAndType (vm .getId (), Type .ROOT );
2309+ if (CollectionUtils .isNotEmpty (volumes )) {
2310+ for (VolumeVO rootVolume : volumes ) {
2311+ if (rootVolume .getPoolId () != null ) {
2312+ StoragePoolVO pool = _storagePoolDao .findById (rootVolume .getPoolId ());
2313+ if (pool != null && pool .getClusterId () != null ) {
2314+ clusterId = pool .getClusterId ();
2315+ List <HostVO > hosts = _hostDao .findHypervisorHostInCluster (pool .getClusterId ());
2316+ if (CollectionUtils .isNotEmpty (hosts )) {
2317+ hostId = hosts .get (0 ).getId ();
2318+ break ;
2319+ }
2320+ }
2321+ }
2322+ }
2323+ }
2324+ }
2325+ if (clusterId == null && hostId != null ) {
2326+ HostVO host = _hostDao .findById (hostId );
2327+ if (host != null ) {
2328+ clusterId = host .getClusterId ();
2329+ }
2330+ }
2331+ return new Pair <>(clusterId , hostId );
2332+ }
2333+
22982334 private void migrateThroughHypervisorOrStorage (StoragePool destPool , VMInstanceVO vm ) throws StorageUnavailableException , InsufficientCapacityException {
22992335 final VirtualMachineProfile profile = new VirtualMachineProfileImpl (vm );
2300- final Long srchostId = vm . getHostId () != null ? vm . getHostId () : vm . getLastHostId ( );
2301- final HostVO srcHost = _hostDao . findById ( srchostId );
2302- final Long srcClusterId = srcHost . getClusterId ();
2303- Answer [] hypervisorMigrationResults = attemptHypervisorMigration (destPool , vm );
2336+ Pair < Long , Long > vmClusterAndHost = findClusterAndHostIdForVm ( vm );
2337+ final Long sourceClusterId = vmClusterAndHost . first ( );
2338+ final Long sourceHostId = vmClusterAndHost . second ();
2339+ Answer [] hypervisorMigrationResults = attemptHypervisorMigration (destPool , vm , sourceHostId );
23042340 boolean migrationResult = false ;
23052341 if (hypervisorMigrationResults == null ) {
23062342 // OfflineVmwareMigration: if the HypervisorGuru can't do it, let the volume manager take care of it.
23072343 migrationResult = volumeMgr .storageMigration (profile , destPool );
23082344 if (migrationResult ) {
2309- afterStorageMigrationCleanup (destPool , vm , srcHost , srcClusterId );
2345+ afterStorageMigrationCleanup (destPool , vm , sourceHostId , sourceClusterId );
23102346 } else {
23112347 s_logger .debug ("Storage migration failed" );
23122348 }
23132349 } else {
2314- afterHypervisorMigrationCleanup (destPool , vm , srcHost , srcClusterId , hypervisorMigrationResults );
2350+ afterHypervisorMigrationCleanup (destPool , vm , sourceClusterId , hypervisorMigrationResults );
23152351 }
23162352 }
23172353
@@ -2366,7 +2402,7 @@ static boolean matches(List<String> volumeTags, List<String> storagePoolTags) {
23662402 }
23672403
23682404
2369- private void afterStorageMigrationCleanup (StoragePool destPool , VMInstanceVO vm , HostVO srcHost , Long srcClusterId ) throws InsufficientCapacityException {
2405+ private void afterStorageMigrationCleanup (StoragePool destPool , VMInstanceVO vm , Long srcHostId , Long srcClusterId ) throws InsufficientCapacityException {
23702406 setDestinationPoolAndReallocateNetwork (destPool , vm );
23712407
23722408 //when start the vm next time, don;'t look at last_host_id, only choose the host based on volume/storage pool
@@ -2376,7 +2412,7 @@ private void afterStorageMigrationCleanup(StoragePool destPool, VMInstanceVO vm,
23762412 // If VM was cold migrated between clusters belonging to two different VMware DCs,
23772413 // unregister the VM from the source host and cleanup the associated VM files.
23782414 if (vm .getHypervisorType ().equals (HypervisorType .VMware )) {
2379- afterStorageMigrationVmwareVMcleanup (destPool , vm , srcHost , srcClusterId );
2415+ afterStorageMigrationVmwareVMCleanup (destPool , vm , srcHostId , srcClusterId );
23802416 }
23812417 }
23822418
@@ -2394,14 +2430,14 @@ private void setDestinationPoolAndReallocateNetwork(StoragePool destPool, VMInst
23942430 }
23952431 }
23962432
2397- private void afterStorageMigrationVmwareVMcleanup (StoragePool destPool , VMInstanceVO vm , HostVO srcHost , Long srcClusterId ) {
2433+ private void afterStorageMigrationVmwareVMCleanup (StoragePool destPool , VMInstanceVO vm , Long srcHostId , Long srcClusterId ) {
23982434 // OfflineVmwareMigration: this should only happen on storage migration, else the guru would already have issued the command
23992435 final Long destClusterId = destPool .getClusterId ();
2400- if (srcClusterId != null && destClusterId != null && ! srcClusterId .equals (destClusterId )) {
2436+ if (srcHostId != null && srcClusterId != null && destClusterId != null && ! srcClusterId .equals (destClusterId )) {
24012437 final String srcDcName = _clusterDetailsDao .getVmwareDcName (srcClusterId );
24022438 final String destDcName = _clusterDetailsDao .getVmwareDcName (destClusterId );
24032439 if (srcDcName != null && destDcName != null && !srcDcName .equals (destDcName )) {
2404- removeStaleVmFromSource (vm , srcHost );
2440+ removeStaleVmFromSource (vm , _hostDao . findById ( srcHostId ) );
24052441 }
24062442 }
24072443 }
0 commit comments