1818
1919import java .util .ArrayList ;
2020import java .util .Collections ;
21+ import java .util .Comparator ;
2122import java .util .Date ;
2223import java .util .HashMap ;
2324import java .util .List ;
@@ -738,12 +739,19 @@ private void postCreateSnapshot(Long volumeId, Long snapshotId, Long policyId, L
738739 postCreateRecurringSnapshotForPolicy (userId , volumeId , snapshotId , policyId );
739740 }
740741
741- if (HypervisorType .KVM .equals (snapshot .getHypervisorType ()) && kvmIncrementalSnapshot .valueIn (clusterId )) {
742- endChainIfNeeded (snapshotId , snapshot .getDataCenterId ());
742+ if (HypervisorType .KVM .equals (snapshot .getHypervisorType ())) {
743+ if (kvmIncrementalSnapshot .valueIn (clusterId )){
744+ endCurrentChainIfNeeded (snapshotId , snapshot .getDataCenterId ());
745+ } else {
746+ endLastChainIfNeeded (clusterId , volumeId );
747+ }
743748 }
744749 }
745750
746- private void endChainIfNeeded (Long snapshotId , Long zoneId ) {
751+ /**
752+ * Will mark this snapshot as the end of the chain if it has reached the value of snapshot.delta.max.
753+ * */
754+ private void endCurrentChainIfNeeded (Long snapshotId , Long zoneId ) {
747755 SnapshotDataStoreVO snapshotDataStoreVo = _snapshotStoreDao .findOneBySnapshotId (snapshotId , zoneId );
748756 int chainSize = 1 ;
749757 while (snapshotDataStoreVo .getParentSnapshotId () > 0 ) {
@@ -759,6 +767,36 @@ private void endChainIfNeeded(Long snapshotId, Long zoneId) {
759767 }
760768 }
761769
770+ /**
771+ * This method ends the last snapshot chain if the current snapshot being taken is not incremental anymore.
772+ * This is needed when a user has a chain of snapshots with kvm.incremental.snapshot = true, then sets the configuration as false and takes a new snapshot.
773+ * Ending the last snapshot chain prevents future inconsistencies if the user sets kvm.incremental.snapshot = true again.
774+ * <br></br>
775+ * <b>This method should only be called when kvm.incremental.snapshot = false and for volumes in KVM</b>
776+ * */
777+ protected void endLastChainIfNeeded (long clusterId , long volumeId ) {
778+ if (kvmIncrementalSnapshot .valueIn (clusterId )) {
779+ return ;
780+ }
781+
782+ List <SnapshotDataStoreVO > volumeSnapshots = _snapshotStoreDao .listReadyByVolumeId (volumeId );
783+ volumeSnapshots .sort (Comparator .comparing (SnapshotDataStoreVO ::getCreated ));
784+ Collections .reverse (volumeSnapshots );
785+
786+ SnapshotDataStoreVO snapshotDataStoreVO ;
787+ for (int i = 1 ; i < volumeSnapshots .size (); i ++) {
788+ snapshotDataStoreVO = volumeSnapshots .get (i );
789+ if (snapshotDataStoreVO .getKvmCheckpointPath () != null ) {
790+ if (!snapshotDataStoreVO .isEndOfChain ()) {
791+ logger .debug ("Found snapshot reference [{}] that used to belong to a now dead snapshot chain. Will mark it as end of chain." , snapshotDataStoreVO );
792+ snapshotDataStoreVO .setEndOfChain (true );
793+ _snapshotStoreDao .update (snapshotDataStoreVO .getId (), snapshotDataStoreVO );
794+ }
795+ return ;
796+ }
797+ }
798+ }
799+
762800 private void postCreateRecurringSnapshotForPolicy (long userId , long volumeId , long snapshotId , long policyId ) {
763801 // Use count query
764802 SnapshotVO spstVO = _snapshotDao .findById (snapshotId );
0 commit comments