|
53 | 53 | import org.apache.cloudstack.framework.config.ConfigDepot; |
54 | 54 | import org.apache.cloudstack.framework.config.ConfigKey; |
55 | 55 | import org.apache.cloudstack.framework.config.Configurable; |
| 56 | +import org.apache.cloudstack.framework.jobs.AsyncJobManager; |
| 57 | +import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; |
56 | 58 | import org.apache.cloudstack.storage.command.CommandResult; |
57 | 59 | import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; |
58 | 60 | import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; |
|
63 | 65 | import com.cloud.agent.api.to.DiskTO; |
64 | 66 | import com.cloud.agent.api.to.VirtualMachineTO; |
65 | 67 | import com.cloud.agent.manager.allocator.PodAllocator; |
| 68 | +import com.cloud.cluster.ClusterManager; |
66 | 69 | import com.cloud.configuration.Resource.ResourceType; |
67 | 70 | import com.cloud.dc.DataCenter; |
68 | 71 | import com.cloud.dc.Pod; |
|
116 | 119 | import com.cloud.vm.VirtualMachine.State; |
117 | 120 | import com.cloud.vm.VirtualMachineProfile; |
118 | 121 | import com.cloud.vm.VirtualMachineProfileImpl; |
| 122 | +import com.cloud.vm.VmWorkAttachVolume; |
| 123 | +import com.cloud.vm.VmWorkMigrateVolume; |
| 124 | +import com.cloud.vm.VmWorkSerializer; |
| 125 | +import com.cloud.vm.VmWorkTakeVolumeSnapshot; |
119 | 126 | import com.cloud.vm.dao.UserVmDao; |
120 | 127 |
|
121 | 128 | public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrationService, Configurable { |
@@ -155,6 +162,10 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati |
155 | 162 | SnapshotService _snapshotSrv; |
156 | 163 | @Inject |
157 | 164 | protected UserVmDao _userVmDao; |
| 165 | + @Inject |
| 166 | + protected AsyncJobManager _jobMgr; |
| 167 | + @Inject |
| 168 | + ClusterManager clusterManager; |
158 | 169 |
|
159 | 170 | private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine; |
160 | 171 | protected List<StoragePoolAllocator> _storagePoolAllocators; |
@@ -1342,9 +1353,71 @@ public boolean configure(String name, Map<String, Object> params) throws Configu |
1342 | 1353 | return true; |
1343 | 1354 | } |
1344 | 1355 |
|
| 1356 | + private void cleanupVolumeDuringAttachFailure(Long volumeId) { |
| 1357 | + VolumeVO volume = _volsDao.findById(volumeId); |
| 1358 | + if (volume == null) { |
| 1359 | + return; |
| 1360 | + } |
| 1361 | + |
| 1362 | + if (volume.getState().equals(Volume.State.Creating)) { |
| 1363 | + s_logger.debug("Remove volume: " + volume.getId() + ", as it's leftover from last mgt server stop"); |
| 1364 | + _volsDao.remove(volume.getId()); |
| 1365 | + } |
| 1366 | + } |
| 1367 | + |
| 1368 | + private void cleanupVolumeDuringMigrationFailure(Long volumeId, Long destPoolId) { |
| 1369 | + StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destPoolId, DataStoreRole.Primary); |
| 1370 | + if (destPool == null) { |
| 1371 | + return; |
| 1372 | + } |
| 1373 | + |
| 1374 | + VolumeVO volume = _volsDao.findById(volumeId); |
| 1375 | + if (volume.getState() == Volume.State.Migrating) { |
| 1376 | + VolumeVO duplicateVol = _volsDao.findByPoolIdName(destPoolId, volume.getName()); |
| 1377 | + if (duplicateVol != null) { |
| 1378 | + s_logger.debug("Remove volume " + duplicateVol.getId() + " on storage pool " + destPoolId); |
| 1379 | + _volsDao.remove(duplicateVol.getId()); |
| 1380 | + } |
| 1381 | + |
| 1382 | + s_logger.debug("change volume state to ready from migrating in case migration failure for vol: " + volumeId); |
| 1383 | + volume.setState(Volume.State.Ready); |
| 1384 | + _volsDao.update(volumeId, volume); |
| 1385 | + } |
| 1386 | + |
| 1387 | + } |
| 1388 | + |
| 1389 | + private void cleanupVolumeDuringSnapshotFailure(Long volumeId, Long snapshotId) { |
| 1390 | + _snapshotSrv.cleanupVolumeDuringSnapshotFailure(volumeId, snapshotId); |
| 1391 | + VolumeVO volume = _volsDao.findById(volumeId); |
| 1392 | + if (volume.getState() == Volume.State.Snapshotting) { |
| 1393 | + s_logger.debug("change volume state back to Ready: " + volume.getId()); |
| 1394 | + volume.setState(Volume.State.Ready); |
| 1395 | + _volsDao.update(volume.getId(), volume); |
| 1396 | + } |
| 1397 | + } |
| 1398 | + |
1345 | 1399 | @Override |
1346 | | - public boolean start() { |
1347 | | - return true; |
| 1400 | + public void cleanupStorageJobs() { |
| 1401 | + //clean up failure jobs related to volume |
| 1402 | + List<AsyncJobVO> jobs = _jobMgr.findFailureAsyncJobs(VmWorkAttachVolume.class.getName(), |
| 1403 | + VmWorkMigrateVolume.class.getName(), VmWorkTakeVolumeSnapshot.class.getName()); |
| 1404 | + |
| 1405 | + for (AsyncJobVO job : jobs) { |
| 1406 | + try { |
| 1407 | + if (job.getCmd().equalsIgnoreCase(VmWorkAttachVolume.class.getName())) { |
| 1408 | + VmWorkAttachVolume work = VmWorkSerializer.deserialize(VmWorkAttachVolume.class, job.getCmdInfo()); |
| 1409 | + cleanupVolumeDuringAttachFailure(work.getVolumeId()); |
| 1410 | + } else if (job.getCmd().equalsIgnoreCase(VmWorkMigrateVolume.class.getName())) { |
| 1411 | + VmWorkMigrateVolume work = VmWorkSerializer.deserialize(VmWorkMigrateVolume.class, job.getCmdInfo()); |
| 1412 | + cleanupVolumeDuringMigrationFailure(work.getVolumeId(), work.getDestPoolId()); |
| 1413 | + } else if (job.getCmd().equalsIgnoreCase(VmWorkTakeVolumeSnapshot.class.getName())) { |
| 1414 | + VmWorkTakeVolumeSnapshot work = VmWorkSerializer.deserialize(VmWorkTakeVolumeSnapshot.class, job.getCmdInfo()); |
| 1415 | + cleanupVolumeDuringSnapshotFailure(work.getVolumeId(), work.getSnapshotId()); |
| 1416 | + } |
| 1417 | + } catch (Exception e) { |
| 1418 | + s_logger.debug("clean up job failure, will continue", e); |
| 1419 | + } |
| 1420 | + } |
1348 | 1421 | } |
1349 | 1422 |
|
1350 | 1423 | @Override |
|
0 commit comments