Skip to content

Commit 632d824

Browse files
committed
<fix>[storage]: when the snapshot group creation fails, delete the successfully created snapshots
Resolves: ZSV-9792 Change-Id: I6b65736e646e7163777a7872667077756771726d
1 parent 40382ed commit 632d824

File tree

4 files changed

+83
-12
lines changed

4 files changed

+83
-12
lines changed

plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ public void beforeTakeLiveSnapshotsOnVolumes(CreateVolumesSnapshotOverlayInnerMs
742742
logger.info(String.format("take snapshots for volumes[%s] on %s",
743743
msg.getLockedVolumeUuids(), getClass().getCanonicalName()));
744744

745+
List<VolumeSnapshotInventory> inventories = Collections.synchronizedList(new ArrayList<>());
745746
ErrorCodeList errList = new ErrorCodeList();
746747
new While<>(cephStructs).all((struct, whileCompletion) -> {
747748
VolumeSnapshotVO vo = Q.New(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.uuid, struct.getResourceUuid()).find();
@@ -779,6 +780,7 @@ public void run(MessageReply reply) {
779780
dbf.update(vo);
780781

781782
struct.getVolumeSnapshotStruct().setCurrent(treply.getInventory());
783+
inventories.add(treply.getInventory());
782784
whileCompletion.done();
783785
}
784786
});
@@ -787,6 +789,17 @@ public void run(MessageReply reply) {
787789
public void done(ErrorCodeList errorCodeList) {
788790
if (!errList.getCauses().isEmpty()) {
789791
completion.fail(errList.getCauses().get(0));
792+
793+
inventories.forEach(snapshot -> {
794+
VolumeSnapshotDeletionMsg msg = new VolumeSnapshotDeletionMsg();
795+
msg.setSnapshotUuid(snapshot.getUuid());
796+
msg.setTreeUuid(snapshot.getTreeUuid());
797+
msg.setVolumeUuid(snapshot.getVolumeUuid());
798+
msg.setScope(DeleteVolumeSnapshotScope.Single.toString());
799+
msg.setDirection(DeleteVolumeSnapshotDirection.Commit.toString());
800+
bus.makeTargetServiceIdByResourceUuid(msg, VolumeSnapshotConstant.SERVICE_ID, snapshot.getUuid());
801+
bus.send(msg);
802+
});
790803
return;
791804
}
792805
completion.success();

storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageFactory.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ public void beforeTakeLiveSnapshotsOnVolumes(CreateVolumesSnapshotOverlayInnerMs
537537
logger.info(String.format("take snapshots for volumes[%s] on %s",
538538
msg.getLockedVolumeUuids(), getClass().getCanonicalName()));
539539

540+
List<VolumeSnapshotInventory> inventories = Collections.synchronizedList(new ArrayList<>());
540541
ErrorCodeList errList = new ErrorCodeList();
541542
new While<>(storageSnapshots).all((struct, whileCompletion) -> {
542543
VolumeSnapshotVO vo = Q.New(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.uuid, struct.getResourceUuid()).find();
@@ -574,6 +575,7 @@ public void run(MessageReply reply) {
574575
dbf.update(vo);
575576

576577
struct.getVolumeSnapshotStruct().setCurrent(treply.getInventory());
578+
inventories.add(treply.getInventory());
577579
whileCompletion.done();
578580
}
579581
});
@@ -582,6 +584,18 @@ public void run(MessageReply reply) {
582584
public void done(ErrorCodeList errorCodeList) {
583585
if (!errList.getCauses().isEmpty()) {
584586
completion.fail(errList.getCauses().get(0));
587+
588+
inventories.forEach(snapshot -> {
589+
VolumeSnapshotDeletionMsg msg = new VolumeSnapshotDeletionMsg();
590+
msg.setSnapshotUuid(snapshot.getUuid());
591+
msg.setTreeUuid(snapshot.getTreeUuid());
592+
msg.setVolumeUuid(snapshot.getVolumeUuid());
593+
msg.setScope(DeleteVolumeSnapshotScope.Single.toString());
594+
msg.setDirection(DeleteVolumeSnapshotDirection.Commit.toString());
595+
bus.makeTargetServiceIdByResourceUuid(msg, VolumeSnapshotConstant.SERVICE_ID, snapshot.getUuid());
596+
bus.send(msg);
597+
});
598+
585599
return;
586600
}
587601
completion.success();

storage/src/main/java/org/zstack/storage/snapshot/VolumeSnapshotApiInterceptor.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import javax.persistence.Tuple;
3232
import java.util.Arrays;
3333
import java.util.List;
34+
import java.util.Set;
3435
import java.util.stream.Collectors;
3536

3637

@@ -74,6 +75,8 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti
7475
validate((APIBatchDeleteVolumeSnapshotMsg) msg);
7576
} else if (msg instanceof APIRevertVmFromSnapshotGroupMsg) {
7677
validate((APIRevertVmFromSnapshotGroupMsg) msg);
78+
} else if (msg instanceof APIDeleteVolumeSnapshotGroupMsg) {
79+
validate((APIDeleteVolumeSnapshotGroupMsg) msg);
7780
}
7881

7982
setServiceId(msg);
@@ -217,4 +220,29 @@ private void validate(APIBatchDeleteVolumeSnapshotMsg msg) {
217220
throw new ApiMessageInterceptionException(operr("can not find volume uuid for snapshosts[uuid: %s]", msg.getUuids()));
218221
}
219222
}
223+
224+
private void validate(APIDeleteVolumeSnapshotGroupMsg msg) {
225+
VolumeSnapshotGroupVO groupVO = dbf.findByUuid(msg.getUuid(), VolumeSnapshotGroupVO.class);
226+
// 获取当前虚拟机所有内存快照
227+
// 检测内存快照是否完整
228+
// 1 完整 允许删除
229+
// 2 不完整 不允许删除
230+
List<VolumeSnapshotGroupVO> groups = Q.New(VolumeSnapshotGroupVO.class)
231+
.eq(VolumeSnapshotGroupVO_.vmInstanceUuid, groupVO.getVmInstanceUuid())
232+
.orderByAsc(VolumeSnapshotGroupVO_.createDate)
233+
.list();
234+
235+
final String[] ungroupUuid = new String[1];
236+
groups.forEach(group -> {
237+
Set<VolumeSnapshotGroupRefVO> volumeSnapshotRefs = group.getVolumeSnapshotRefs();
238+
volumeSnapshotRefs.forEach(ref -> {
239+
if (ref.isSnapshotDeleted()) {
240+
ungroupUuid[0] = group.getUuid();
241+
}
242+
});
243+
});
244+
if (ungroupUuid[0] != null) {
245+
throw new ApiMessageInterceptionException(argerr("volume snapshot group[uuid:%s] is not complete, cannot delete volume snapshot group", ungroupUuid[0]));
246+
}
247+
}
220248
}

storage/src/main/java/org/zstack/storage/snapshot/VolumeSnapshotTreeBase.java

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,21 +2088,37 @@ private void ungroupAfterDeleted(List<VolumeSnapshotInventory> snapshots) {
20882088
List<String> uuids = snapshots.stream().map(VolumeSnapshotInventory::getUuid).collect(Collectors.toList());
20892089
SQL.New(VolumeSnapshotGroupRefVO.class).in(VolumeSnapshotGroupRefVO_.volumeSnapshotUuid, uuids)
20902090
.set(VolumeSnapshotGroupRefVO_.snapshotDeleted, true).update();
2091-
if (currentRoot.getVolumeType().equals(VolumeType.Root.toString())) {
2092-
List<String> groupUuids = new ArrayList<>();
2093-
for (VolumeSnapshotInventory snapshot : snapshots) {
2094-
String groupUuid = snapshot.getGroupUuid();
2095-
if (groupUuid != null) {
2096-
logger.debug(String.format("root volume snapshot[uuid:%s, name:%s] has been deleted, " +
2097-
"ungroup snapshot group[uuid:%s]", snapshot.getUuid(), snapshot.getName(), groupUuid));
2098-
groupUuids.add(groupUuid);
2099-
}
21002091

2101-
}
2092+
List<String> groupUuids = snapshots.stream().map(VolumeSnapshotInventory::getGroupUuid).filter(Objects::nonNull).collect(Collectors.toList());
2093+
if (groupUuids.isEmpty()) {
2094+
return;
2095+
}
2096+
2097+
List<VolumeSnapshotGroupVO> groupVOs = Q.New(VolumeSnapshotGroupVO.class).in(VolumeSnapshotGroupVO_.uuid, groupUuids).list();
2098+
groupVOs.forEach(groupVO -> {
2099+
new RunInQueue(String.format("ungroup-volumeSnapshotGroup-%s", groupVO.getUuid()), thdf, 1)
2100+
.name("ungroup-volumeSnapshotGroup-in-queue").asyncBackup(null)
2101+
.run(chain -> ungroupAfterDeleted(groupVO, new NoErrorCompletion(chain) {
2102+
@Override
2103+
public void done() {
2104+
chain.next();
2105+
}
2106+
})
2107+
);
2108+
});
2109+
}
21022110

2103-
groupUuids.forEach(groupUuid -> vidm.deleteArchiveVmInstanceResourceMetadataGroup(groupUuid));
2104-
dbf.removeByPrimaryKeys(groupUuids, VolumeSnapshotGroupVO.class);
2111+
private void ungroupAfterDeleted(VolumeSnapshotGroupVO groupVO, NoErrorCompletion completion) {
2112+
if (!groupVO.getVolumeSnapshotRefs().stream().allMatch(VolumeSnapshotGroupRefVO::isSnapshotDeleted)) {
2113+
logger.debug(String.format("skipping ungroup operation for snapshot group[uuid:%s]: " +
2114+
"no group meet deletion criteria (due to remaining volume snapshots).", groupVO.getUuid()));
2115+
completion.done();
2116+
return;
21052117
}
2118+
logger.debug(String.format("snapshot group[uuid:%s] all volume snapshot has been deleted, delete snapshot group", groupVO.getUuid()));
2119+
vidm.deleteArchiveVmInstanceResourceMetadataGroup(groupVO.getUuid());
2120+
dbf.removeByPrimaryKey(groupVO.getUuid(), VolumeSnapshotGroupVO.class);
2121+
completion.done();
21062122
}
21072123

21082124
private List<VolumeSnapshotBackupStorageDeletionMsg> makeVolumeSnapshotBackupStorageDeletionMsg(List<String> bsUuids) {

0 commit comments

Comments
 (0)