public static VolumeSnapshotInventory valueOf(VolumeSnapshotVO vo) { VolumeSnapshotInventory inv = new VolumeSnapshotInventory(); inv.setName(vo.getName()); inv.setCreateDate(vo.getCreateDate()); inv.setDescription(vo.getDescription()); inv.setLastOpDate(vo.getLastOpDate()); inv.setParentUuid(vo.getParentUuid()); inv.setState(vo.getState().toString()); inv.setType(vo.getType()); inv.setVolumeUuid(vo.getVolumeUuid()); inv.setFormat(vo.getFormat()); inv.setUuid(vo.getUuid()); inv.setStatus(vo.getStatus().toString()); inv.setPrimaryStorageUuid(vo.getPrimaryStorageUuid()); inv.setPrimaryStorageInstallPath(vo.getPrimaryStorageInstallPath()); inv.setLatest(vo.isLatest()); inv.setSize(vo.getSize()); inv.setVolumeType(vo.getVolumeType()); inv.setTreeUuid(vo.getTreeUuid()); inv.setBackupStorageRefs(VolumeSnapshotBackupStorageRefInventory.valueOf(vo.getBackupStorageRefs())); return inv; }
@Override public String getName() { return String.format("revert-volume-%s-from-snapshot-%s", currentRoot.getVolumeUuid(), currentRoot.getUuid()); } });
public VolumeSnapshotTreeBase(VolumeSnapshotVO vo, boolean syncOnVolume) { currentRoot = vo; if (syncOnVolume) { syncSignature = String.format("volume.snapshot.volume.%s", currentRoot.getVolumeUuid()); } else { syncSignature = String.format("volume.snapshot.tree.%s", currentRoot.getTreeUuid()); } }
" and c.current = true"; TypedQuery<VolumeSnapshotTreeVO> cq = dbf.getEntityManager().createQuery(sql, VolumeSnapshotTreeVO.class); cq.setParameter("volUuid", vo.getVolumeUuid()); List<VolumeSnapshotTreeVO> rets = cq.getResultList(); DebugUtils.Assert(rets.size() < 2, "can not have more than one VolumeSnapshotTreeVO with current=1"); VolumeSnapshotTreeVO chain = rets.isEmpty() ? null : rets.get(0); final Integer maxIncrementalSnapshotNum = getMaxIncrementalSnapshotNum(vo.getVolumeUuid()); if (!CoreGlobalProperty.UNIT_TEST_ON) { if (maxIncrementalSnapshotNum <= 1) { throw new OperationFailureException(operr("Unsupported maximum snapshot number (%d) for volume [uuid:%s]", maxIncrementalSnapshotNum, vo.getVolumeUuid() )); " and s.treeUuid = :chainUuid"; TypedQuery<VolumeSnapshotVO> q = dbf.getEntityManager().createQuery(sql, VolumeSnapshotVO.class); q.setParameter("volUuid", vo.getVolumeUuid()); q.setParameter("chainUuid", chain.getUuid()); VolumeSnapshotVO latest = q.getSingleResult(); if (latest.getDistance() >= maxIncrementalSnapshotNum) { chain.setCurrent(false); dbf.getEntityManager().merge(chain); latest.setLatest(false); latest = dbf.getEntityManager().merge(latest); vo.setTreeUuid(latest.getTreeUuid()); vo.setLatest(true); vo.setParentUuid(latest.getUuid());
@Override public String getName() { return String.format("delete-volume-snapshot-%s", currentRoot.getUuid()); } });
private ErrorCode isOperationAllowed(Message msg) { if (allowedStatus.isOperationAllowed(msg.getClass().getName(), currentRoot.getStatus().toString())) { return null; } else { return err(VolumeSnapshotErrors.NOT_IN_CORRECT_STATE, "snapshot[uuid:%s, name:%s]'s status[%s] is not allowed for message[%s], allowed status%s", currentRoot.getUuid(), currentRoot.getName(), currentRoot.getStatus(), msg.getClass().getName(), allowedStatus.getStatesForOperation(msg.getClass().getName())); } }
@Transactional private VolumeSnapshotStruct newChain(VolumeSnapshotVO vo, boolean fullsnapshot) { VolumeSnapshotTreeVO chain = new VolumeSnapshotTreeVO(); chain.setCurrent(true); chain.setVolumeUuid(vo.getVolumeUuid()); chain.setUuid(Platform.getUuid()); chain = dbf.getEntityManager().merge(chain); logger.debug(String.format("created new volume snapshot tree[tree uuid:%s, volume uuid:%s, full snapshot uuid:%s]", chain.getUuid(), vo.getVolumeUuid(), vo.getUuid())); vo.setTreeUuid(chain.getUuid()); vo.setDistance(fullsnapshot ? 0 : 1); vo.setParentUuid(null); vo.setLatest(true); vo.setFullSnapshot(fullsnapshot); dbf.getEntityManager().persist(vo); dbf.getEntityManager().flush(); dbf.getEntityManager().refresh(vo); VolumeSnapshotStruct struct = new VolumeSnapshotStruct(); struct.setCurrent(VolumeSnapshotInventory.valueOf(vo)); struct.setFullSnapshot(fullsnapshot); return struct; }
private void validate(APICreateDataVolumeTemplateFromVolumeSnapshotMsg msg) { VolumeSnapshotVO vsvo = dbf.findByUuid(msg.getSnapshotUuid(), VolumeSnapshotVO.class); if (VolumeSnapshotStatus.Ready != vsvo.getStatus()) { throw new ApiMessageInterceptionException(operr("volume snapshot[uuid:%s] is not Ready, it's %s", vsvo.getUuid(), vsvo.getStatus())); } if (VolumeSnapshotState.Enabled != vsvo.getState()) { throw new ApiMessageInterceptionException(operr("volume snapshot[uuid:%s] is not Enabled, it's %s", vsvo.getUuid(), vsvo.getState())); } }
chain.setName(String.format("delete-snapshot-%s", currentRoot.getUuid())); chain.allowEmptyFlow(); tq.add(VolumeSnapshotTreeVO_.uuid, Op.EQ, currentRoot.getTreeUuid()); Boolean onCurrentTree = tq.findValue(); boolean needMerge = onCurrentTree && ancestorOfLatest && currentRoot.getPrimaryStorageUuid() != null && VolumeSnapshotConstant.HYPERVISOR_SNAPSHOT_TYPE.toString().equals(currentRoot.getType()); if (needMerge) { chain.then(new NoRollbackFlow() {
info.setPath(vo.getPrimaryStorageInstallPath()); info.setResourceRef(CollectionUtils.find(snapshotRefVOS, new Function<LocalStorageResourceRefInventory, LocalStorageResourceRefVO>() { @Override throw new CloudRuntimeException( String.format("cannot find reference of snapshot[uuid:%s, name:%s] on the local storage[uuid:%s, name:%s]", vo.getUuid(), vo.getName(), self.getUuid(), self.getName())); requiredSize += vo.getSize();
new While<>(msg.getVolumeSnapshotJobs()).all((struct, whileCompletion) -> { VolumeSnapshotVO vo = Q.New(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.uuid, struct.getResourceUuid()).find(); if (vo.getStatus().equals(VolumeSnapshotStatus.Ready)) { logger.warn(String.format("snapshot %s on volume %s is ready, no need to create again!", vo.getUuid(), vo.getVolumeUuid())); whileCompletion.done(); return;
@Override protected void scripts() { String psUuid = q(VolumeSnapshotVO.class) .select(VolumeSnapshotVO_.primaryStorageUuid) .eq(VolumeSnapshotVO_.uuid, currentRoot.getUuid()) .findValue(); if (psUuid != null) { ret.value = false; return; } // the snapshot is on neither primary storage, delete it and descendants List<String> uuids = currentLeaf.getDescendants().stream().map(VolumeSnapshotInventory::getUuid).collect(Collectors.toList()); if (!uuids.isEmpty()) { sql(VolumeSnapshotVO.class).in(VolumeSnapshotVO_.uuid, uuids).hardDelete(); } if (!q(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.treeUuid, currentRoot.getTreeUuid()).isExists()) { logger.debug(String.format("volume snapshot tree[uuid:%s] has no leaf, delete it", currentRoot.getTreeUuid())); sql(VolumeSnapshotTreeVO.class).eq(VolumeSnapshotTreeVO_.uuid, currentRoot.getTreeUuid()).hardDelete(); } ret.value = true; } }.execute();
private List<VolumeSnapshotBackupStorageDeletionMsg> makeVolumeSnapshotBackupStorageDeletionMsg(List<String> bsUuids) { List<VolumeSnapshotBackupStorageDeletionMsg> msgs = new ArrayList<VolumeSnapshotBackupStorageDeletionMsg>(); List<String> allMyBsUuids = CollectionUtils.transformToList(currentRoot.getBackupStorageRefs(), new Function<String, VolumeSnapshotBackupStorageRefVO>() { @Override public String call(VolumeSnapshotBackupStorageRefVO arg) { msg.setSnapshotUuid(currentRoot.getUuid()); msg.setBackupStorageUuids(bsUuids); bus.makeLocalServiceId(msg, VolumeSnapshotConstant.SERVICE_ID);
private void refreshVO() { VolumeSnapshotVO vo = dbf.reload(currentRoot); if (vo == null) { throw new OperationFailureException(operr("cannot find volume snapshot[uuid:%s, name:%s], it may have been deleted by previous operation", currentRoot.getUuid(), currentRoot.getName())); } currentRoot = vo; buildFullSnapshotTree(); currentLeaf = fullTree.findSnapshot(new Function<Boolean, VolumeSnapshotInventory>() { @Override public Boolean call(VolumeSnapshotInventory arg) { return arg.getUuid().equals(currentRoot.getUuid()); } }); }
@Transactional private void rollbackSnapshot(String uuid) { VolumeSnapshotVO vo = dbf.getEntityManager().find(VolumeSnapshotVO.class, uuid); dbf.getEntityManager().remove(vo); String sql = "delete from AccountResourceRefVO where resourceUuid = :vsUuid and resourceType = 'VolumeSnapshotVO'"; Query q = dbf.getEntityManager().createQuery(sql); q.setParameter("vsUuid", uuid); q.executeUpdate(); if (vo.getParentUuid() != null) { VolumeSnapshotVO parent = dbf.getEntityManager().find(VolumeSnapshotVO.class, vo.getParentUuid()); parent.setLatest(true); dbf.getEntityManager().merge(parent); } else { VolumeSnapshotTreeVO chain = dbf.getEntityManager().find(VolumeSnapshotTreeVO.class, vo.getTreeUuid()); dbf.getEntityManager().remove(chain); } }
requiredSize += vo.getSize(); m.computeIfAbsent(vo.getTreeUuid(), k -> new ArrayList<>()).add(vo);
private void buildFullSnapshotTree() { SimpleQuery<VolumeSnapshotVO> q = dbf.createQuery(VolumeSnapshotVO.class); q.add(VolumeSnapshotVO_.treeUuid, SimpleQuery.Op.EQ, currentRoot.getTreeUuid()); List<VolumeSnapshotVO> vos = q.list(); fullTree = VolumeSnapshotTree.fromVOs(vos); }
@Override public void run(final FlowTrigger trigger, Map data) { MergeVolumeSnapshotOnPrimaryStorageMsg mmsg = new MergeVolumeSnapshotOnPrimaryStorageMsg(); VolumeSnapshotInventory from = currentLeaf.getParent() == null ? currentLeaf.getInventory() : currentLeaf.getParent().getInventory(); mmsg.setFrom(from); VolumeVO vol = dbf.findByUuid(currentRoot.getVolumeUuid(), VolumeVO.class); mmsg.setTo(VolumeInventory.valueOf(vol)); mmsg.setFullRebase(currentLeaf.getParent() == null); bus.makeTargetServiceIdByResourceUuid(mmsg, PrimaryStorageConstant.SERVICE_ID, currentRoot.getPrimaryStorageUuid()); bus.send(mmsg, new CloudBusCallBack(trigger) { @Override public void run(MessageReply reply) { if (!reply.isSuccess()) { trigger.fail(reply.getError()); } else { trigger.next(); } } }); } });