Skip to content

Commit e9c7776

Browse files
sureshanapartidhslove
authored andcommitted
server: Cleanup allocated snapshots / vm snapshots, and update pending ones to Error on MS start (apache#8452)
* Remove allocated snapshots / vm snapshots on start * Check and Cleanup snapshots / vm snapshots on MS start * rebase fixes * Update volume state (from Snapshotting) on MS start when its snapshot job not finished and snapshot in Creating state
1 parent 17d8f46 commit e9c7776

File tree

10 files changed

+113
-5
lines changed

10 files changed

+113
-5
lines changed

api/src/main/java/com/cloud/vm/snapshot/VMSnapshotService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.List;
2121

22+
import com.cloud.utils.fsm.NoTransitionException;
2223
import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd;
2324

2425
import com.cloud.exception.ConcurrentOperationException;
@@ -53,4 +54,6 @@ UserVm revertToSnapshot(Long vmSnapshotId) throws InsufficientServerCapacityExce
5354
* @param id vm id
5455
*/
5556
boolean deleteVMSnapshotsFromDB(Long vmId, boolean unmanage);
57+
58+
void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException;
5659
}

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222

2323
import com.cloud.storage.DataStoreRole;
24+
import com.cloud.utils.fsm.NoTransitionException;
2425

2526
public interface SnapshotDataFactory {
2627
SnapshotInfo getSnapshot(long snapshotId, DataStore store);
@@ -42,4 +43,6 @@ public interface SnapshotDataFactory {
4243
List<SnapshotInfo> listSnapshotOnCache(long snapshotId);
4344

4445
SnapshotInfo getReadySnapshotOnCache(long snapshotId);
46+
47+
void updateOperationFailed(long snapshotId) throws NoTransitionException;
4548
}

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/VMSnapshotStrategy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.cloudstack.engine.subsystem.api.storage;
2020

21+
import com.cloud.utils.fsm.NoTransitionException;
2122
import com.cloud.vm.snapshot.VMSnapshot;
2223

2324
public interface VMSnapshotStrategy {
@@ -44,4 +45,6 @@ public interface VMSnapshotStrategy {
4445
* @return true if vm snapshot removed from DB, false if not.
4546
*/
4647
boolean deleteVMSnapshotFromDB(VMSnapshot vmSnapshot, boolean unmanage);
48+
49+
void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException;
4750
}

engine/components-api/src/main/java/com/cloud/vm/snapshot/VMSnapshotManager.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,4 @@ public interface VMSnapshotManager extends VMSnapshotService, Manager {
5454
boolean hasActiveVMSnapshotTasks(Long vmId);
5555

5656
RestoreVMSnapshotCommand createRestoreCommand(UserVmVO userVm, List<VMSnapshotVO> vmSnapshotVOs);
57-
5857
}

engine/schema/src/main/java/com/cloud/vm/snapshot/dao/VMSnapshotDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public interface VMSnapshotDao extends GenericDao<VMSnapshotVO, Long>, StateDao<
4242
VMSnapshotVO findByName(Long vmId, String name);
4343

4444
List<VMSnapshotVO> listByAccountId(Long accountId);
45+
4546
List<VMSnapshotVO> searchByVms(List<Long> vmIds);
47+
4648
List<VMSnapshotVO> searchRemovedByVms(List<Long> vmIds, Long batchSize);
4749
}

engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,16 @@
2323

2424
import javax.inject.Inject;
2525

26+
import com.cloud.storage.Snapshot;
27+
import com.cloud.storage.Volume;
28+
import com.cloud.utils.fsm.NoTransitionException;
2629
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
2730
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
2831
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
32+
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
2933
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
3034
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
35+
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
3136
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
3237
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
3338
import org.apache.commons.collections.CollectionUtils;
@@ -73,7 +78,7 @@ public List<SnapshotInfo> getSnapshotsForVolumeAndStoreRole(long volumeId, DataS
7378
for (SnapshotDataStoreVO snapshotDataStoreVO : allSnapshotsFromVolumeAndDataStore) {
7479
DataStore store = storeMgr.getDataStore(snapshotDataStoreVO.getDataStoreId(), role);
7580
SnapshotVO snapshot = snapshotDao.findById(snapshotDataStoreVO.getSnapshotId());
76-
if (snapshot == null){ //snapshot may have been removed;
81+
if (snapshot == null) { //snapshot may have been removed;
7782
continue;
7883
}
7984
SnapshotObject info = SnapshotObject.getSnapshotObject(snapshot, store);
@@ -107,8 +112,6 @@ public List<SnapshotInfo> getSnapshots(long snapshotId, Long zoneId) {
107112
return infos;
108113
}
109114

110-
111-
112115
@Override
113116
public SnapshotInfo getSnapshot(long snapshotId, long storeId, DataStoreRole role) {
114117
SnapshotVO snapshot = snapshotDao.findById(snapshotId);
@@ -202,4 +205,17 @@ public List<SnapshotInfo> listSnapshotOnCache(long snapshotId) {
202205
return snapObjs;
203206
}
204207

208+
@Override
209+
public void updateOperationFailed(long snapshotId) throws NoTransitionException {
210+
List<SnapshotDataStoreVO> snapshotStoreRefs = snapshotStoreDao.findBySnapshotId(snapshotId);
211+
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
212+
SnapshotInfo snapshotInfo = getSnapshot(snapshotStoreRef.getSnapshotId(), snapshotStoreRef.getDataStoreId(), snapshotStoreRef.getRole());
213+
if (snapshotInfo != null) {
214+
VolumeInfo volumeInfo = snapshotInfo.getBaseVolume();
215+
volumeInfo.stateTransit(Volume.Event.OperationFailed);
216+
((SnapshotObject)snapshotInfo).processEvent(Snapshot.Event.OperationFailed);
217+
snapshotInfo.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
218+
}
219+
}
220+
}
205221
}

engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ public StrategyPriority canHandle(Long vmId, Long rootPoolId, boolean snapshotMe
500500
return StrategyPriority.DEFAULT;
501501
}
502502

503+
@Override
503504
private boolean vmHasKvmDiskOnlySnapshot(UserVm vm) {
504505
if (!Hypervisor.HypervisorType.KVM.equals(vm.getHypervisorType())) {
505506
return false;
@@ -514,4 +515,14 @@ private boolean vmHasKvmDiskOnlySnapshot(UserVm vm) {
514515

515516
return false;
516517
}
518+
519+
@Override
520+
public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException {
521+
try {
522+
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
523+
} catch (NoTransitionException e) {
524+
logger.debug("Failed to change vm snapshot state with event OperationFailed");
525+
throw e;
526+
}
527+
}
517528
}

engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/ScaleIOVMSnapshotStrategy.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,16 @@ public boolean deleteVMSnapshotFromDB(VMSnapshot vmSnapshot, boolean unmanage) {
488488
return vmSnapshotDao.remove(vmSnapshot.getId());
489489
}
490490

491+
@Override
492+
public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException {
493+
try {
494+
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
495+
} catch (NoTransitionException e) {
496+
logger.debug("Failed to change vm snapshot state with event OperationFailed");
497+
throw e;
498+
}
499+
}
500+
491501
private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm userVm, VolumeObjectTO volumeTo) {
492502
VolumeVO volume = volumeDao.findById(volumeTo.getId());
493503
Long diskOfferingId = volume.getDiskOfferingId();

framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
import javax.inject.Inject;
3636
import javax.naming.ConfigurationException;
3737

38+
import com.cloud.storage.SnapshotVO;
39+
import com.cloud.vm.snapshot.VMSnapshot;
40+
import com.cloud.vm.snapshot.VMSnapshotService;
41+
import com.cloud.vm.snapshot.VMSnapshotVO;
42+
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
3843
import org.apache.cloudstack.api.ApiCommandResourceType;
3944
import org.apache.cloudstack.api.ApiErrorCode;
4045
import org.apache.cloudstack.command.ReconcileCommandService;
@@ -155,11 +160,15 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
155160
@Inject
156161
private SnapshotDao _snapshotDao;
157162
@Inject
163+
private VMSnapshotDao _vmSnapshotDao;
164+
@Inject
158165
private SnapshotService snapshotSrv;
159166
@Inject
160167
private SnapshotDataFactory snapshotFactory;
161168
@Inject
162169
private SnapshotDetailsDao _snapshotDetailsDao;
170+
@Inject
171+
private VMSnapshotService _vmSnapshotService;
163172

164173
@Inject
165174
private VolumeDataFactory volFactory;
@@ -1186,6 +1195,10 @@ protected boolean cleanupResources(AsyncJobVO job) {
11861195
return cleanupVirtualMachine(job.getInstanceId());
11871196
case Network:
11881197
return cleanupNetwork(job.getInstanceId());
1198+
case Snapshot:
1199+
return cleanupSnapshot(job.getInstanceId());
1200+
case VmSnapshot:
1201+
return cleanupVmSnapshot(job.getInstanceId());
11891202
}
11901203
} catch (Exception e) {
11911204
logger.warn("Error while cleaning up resource: [" + job.getInstanceType().toString() + "] with Id: " + job.getInstanceId(), e);
@@ -1253,7 +1266,7 @@ private boolean cleanupVirtualMachine(final long vmId) throws Exception {
12531266
return true;
12541267
}
12551268

1256-
private boolean cleanupNetwork(final long networkId) throws Exception {
1269+
private boolean cleanupNetwork(final long networkId) {
12571270
NetworkVO networkVO = networkDao.findById(networkId);
12581271
if (networkVO == null) {
12591272
logger.warn("Network not found. Skip Cleanup. NetworkId: " + networkId);
@@ -1272,6 +1285,46 @@ private boolean cleanupNetwork(final long networkId) throws Exception {
12721285
return true;
12731286
}
12741287

1288+
private boolean cleanupSnapshot(final long snapshotId) {
1289+
SnapshotVO snapshotVO = _snapshotDao.findById(snapshotId);
1290+
if (snapshotVO == null) {
1291+
logger.warn("Snapshot not found. Skip Cleanup. SnapshotId: " + snapshotId);
1292+
return true;
1293+
}
1294+
if (Snapshot.State.Allocated.equals(snapshotVO.getState())) {
1295+
_snapshotDao.remove(snapshotId);
1296+
}
1297+
if (Snapshot.State.Creating.equals(snapshotVO.getState())) {
1298+
try {
1299+
snapshotFactory.updateOperationFailed(snapshotId);
1300+
} catch (NoTransitionException e) {
1301+
snapshotVO.setState(Snapshot.State.Error);
1302+
_snapshotDao.update(snapshotVO.getId(), snapshotVO);
1303+
}
1304+
}
1305+
return true;
1306+
}
1307+
1308+
private boolean cleanupVmSnapshot(final long vmSnapshotId) {
1309+
VMSnapshotVO vmSnapshotVO = _vmSnapshotDao.findById(vmSnapshotId);
1310+
if (vmSnapshotVO == null) {
1311+
logger.warn("VM Snapshot not found. Skip Cleanup. VMSnapshotId: " + vmSnapshotId);
1312+
return true;
1313+
}
1314+
if (VMSnapshot.State.Allocated.equals(vmSnapshotVO.getState())) {
1315+
_vmSnapshotDao.remove(vmSnapshotId);
1316+
}
1317+
if (VMSnapshot.State.Creating.equals(vmSnapshotVO.getState())) {
1318+
try {
1319+
_vmSnapshotService.updateOperationFailed(vmSnapshotVO);
1320+
} catch (NoTransitionException e) {
1321+
vmSnapshotVO.setState(VMSnapshot.State.Error);
1322+
_vmSnapshotDao.update(vmSnapshotVO.getId(), vmSnapshotVO);
1323+
}
1324+
}
1325+
return true;
1326+
}
1327+
12751328
private void cleanupFailedVolumesCreatedFromSnapshots(final long volumeId) {
12761329
try {
12771330
VolumeDetailVO volumeDetail = _volumeDetailsDao.findDetail(volumeId, VolumeService.SNAPSHOT_ID);

server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import javax.inject.Inject;
2828
import javax.naming.ConfigurationException;
2929

30+
import com.cloud.storage.snapshot.SnapshotManager;
31+
import com.cloud.utils.fsm.NoTransitionException;
3032
import org.apache.cloudstack.annotation.AnnotationService;
3133
import org.apache.cloudstack.annotation.dao.AnnotationDao;
3234
import org.apache.cloudstack.api.ApiConstants;
@@ -1399,6 +1401,12 @@ public boolean deleteVMSnapshotsFromDB(Long vmId, boolean unmanage) {
13991401
return true;
14001402
}
14011403

1404+
@Override
1405+
public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException {
1406+
VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshot);
1407+
strategy.updateOperationFailed(vmSnapshot);
1408+
}
1409+
14021410
@Override
14031411
public String getConfigComponentName() {
14041412
return VMSnapshotManager.class.getSimpleName();

0 commit comments

Comments
 (0)