Skip to content

Commit 40dec99

Browse files
server: Cleanup allocated snapshots / vm snapshots, and update pending ones to Error on MS start (#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 12513e1 commit 40dec99

File tree

10 files changed

+111
-5
lines changed

10 files changed

+111
-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
@@ -38,6 +38,8 @@ public interface VMSnapshotDao extends GenericDao<VMSnapshotVO, Long>, StateDao<
3838
VMSnapshotVO findByName(Long vmId, String name);
3939

4040
List<VMSnapshotVO> listByAccountId(Long accountId);
41+
4142
List<VMSnapshotVO> searchByVms(List<Long> vmIds);
43+
4244
List<VMSnapshotVO> searchRemovedByVms(List<Long> vmIds, Long batchSize);
4345
}

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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,4 +481,14 @@ public StrategyPriority canHandle(Long vmId, Long rootPoolId, boolean snapshotMe
481481
}
482482
return StrategyPriority.DEFAULT;
483483
}
484+
485+
@Override
486+
public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException {
487+
try {
488+
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
489+
} catch (NoTransitionException e) {
490+
logger.debug("Failed to change vm snapshot state with event OperationFailed");
491+
throw e;
492+
}
493+
}
484494
}

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
@@ -479,6 +479,16 @@ public boolean deleteVMSnapshotFromDB(VMSnapshot vmSnapshot, boolean unmanage) {
479479
return vmSnapshotDao.remove(vmSnapshot.getId());
480480
}
481481

482+
@Override
483+
public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException {
484+
try {
485+
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
486+
} catch (NoTransitionException e) {
487+
logger.debug("Failed to change vm snapshot state with event OperationFailed");
488+
throw e;
489+
}
490+
}
491+
482492
private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm userVm, VolumeObjectTO volumeTo) {
483493
VolumeVO volume = volumeDao.findById(volumeTo.getId());
484494
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.context.CallContext;
@@ -153,11 +158,15 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
153158
@Inject
154159
private SnapshotDao _snapshotDao;
155160
@Inject
161+
private VMSnapshotDao _vmSnapshotDao;
162+
@Inject
156163
private SnapshotService snapshotSrv;
157164
@Inject
158165
private SnapshotDataFactory snapshotFactory;
159166
@Inject
160167
private SnapshotDetailsDao _snapshotDetailsDao;
168+
@Inject
169+
private VMSnapshotService _vmSnapshotService;
161170

162171
@Inject
163172
private VolumeDataFactory volFactory;
@@ -1149,6 +1158,10 @@ protected boolean cleanupResources(AsyncJobVO job) {
11491158
return cleanupVirtualMachine(job.getInstanceId());
11501159
case Network:
11511160
return cleanupNetwork(job.getInstanceId());
1161+
case Snapshot:
1162+
return cleanupSnapshot(job.getInstanceId());
1163+
case VmSnapshot:
1164+
return cleanupVmSnapshot(job.getInstanceId());
11521165
}
11531166
} catch (Exception e) {
11541167
logger.warn("Error while cleaning up resource: [" + job.getInstanceType().toString() + "] with Id: " + job.getInstanceId(), e);
@@ -1187,7 +1200,7 @@ private boolean cleanupVirtualMachine(final long vmId) throws Exception {
11871200
return true;
11881201
}
11891202

1190-
private boolean cleanupNetwork(final long networkId) throws Exception {
1203+
private boolean cleanupNetwork(final long networkId) {
11911204
NetworkVO networkVO = networkDao.findById(networkId);
11921205
if (networkVO == null) {
11931206
logger.warn("Network not found. Skip Cleanup. NetworkId: " + networkId);
@@ -1206,6 +1219,46 @@ private boolean cleanupNetwork(final long networkId) throws Exception {
12061219
return true;
12071220
}
12081221

1222+
private boolean cleanupSnapshot(final long snapshotId) {
1223+
SnapshotVO snapshotVO = _snapshotDao.findById(snapshotId);
1224+
if (snapshotVO == null) {
1225+
logger.warn("Snapshot not found. Skip Cleanup. SnapshotId: " + snapshotId);
1226+
return true;
1227+
}
1228+
if (Snapshot.State.Allocated.equals(snapshotVO.getState())) {
1229+
_snapshotDao.remove(snapshotId);
1230+
}
1231+
if (Snapshot.State.Creating.equals(snapshotVO.getState())) {
1232+
try {
1233+
snapshotFactory.updateOperationFailed(snapshotId);
1234+
} catch (NoTransitionException e) {
1235+
snapshotVO.setState(Snapshot.State.Error);
1236+
_snapshotDao.update(snapshotVO.getId(), snapshotVO);
1237+
}
1238+
}
1239+
return true;
1240+
}
1241+
1242+
private boolean cleanupVmSnapshot(final long vmSnapshotId) {
1243+
VMSnapshotVO vmSnapshotVO = _vmSnapshotDao.findById(vmSnapshotId);
1244+
if (vmSnapshotVO == null) {
1245+
logger.warn("VM Snapshot not found. Skip Cleanup. VMSnapshotId: " + vmSnapshotId);
1246+
return true;
1247+
}
1248+
if (VMSnapshot.State.Allocated.equals(vmSnapshotVO.getState())) {
1249+
_vmSnapshotDao.remove(vmSnapshotId);
1250+
}
1251+
if (VMSnapshot.State.Creating.equals(vmSnapshotVO.getState())) {
1252+
try {
1253+
_vmSnapshotService.updateOperationFailed(vmSnapshotVO);
1254+
} catch (NoTransitionException e) {
1255+
vmSnapshotVO.setState(VMSnapshot.State.Error);
1256+
_vmSnapshotDao.update(vmSnapshotVO.getId(), vmSnapshotVO);
1257+
}
1258+
}
1259+
return true;
1260+
}
1261+
12091262
private void cleanupFailedVolumesCreatedFromSnapshots(final long volumeId) {
12101263
try {
12111264
VolumeDetailVO volumeDetail = _volumeDetailsDao.findDetail(volumeId, VolumeService.SNAPSHOT_ID);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import javax.naming.ConfigurationException;
2929

3030
import com.cloud.storage.snapshot.SnapshotManager;
31+
import com.cloud.utils.fsm.NoTransitionException;
3132
import org.apache.cloudstack.annotation.AnnotationService;
3233
import org.apache.cloudstack.annotation.dao.AnnotationDao;
3334
import org.apache.cloudstack.api.ApiConstants;
@@ -1387,6 +1388,12 @@ public boolean deleteVMSnapshotsFromDB(Long vmId, boolean unmanage) {
13871388
return true;
13881389
}
13891390

1391+
@Override
1392+
public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException {
1393+
VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshot);
1394+
strategy.updateOperationFailed(vmSnapshot);
1395+
}
1396+
13901397
@Override
13911398
public String getConfigComponentName() {
13921399
return VMSnapshotManager.class.getSimpleName();

0 commit comments

Comments
 (0)