Skip to content

Commit c101817

Browse files
committed
Merge pull request #1697 from myENA/feature/49_observe_snapshot_backup_rightafter
CLOUDSTACK-4858 Honors the snapshot.backup.rightafter configuration variable Unhides snapshot.backup.rightafter from global configuration If snapshot.backup.rightafter is set to false (defaults to true), snapshots are not backed up to secondary storage. This is the same as PR #1644 applied to 4.9, as per @jburwell * pr/1697: CLOUDSTACK-4858 Honors the snapshot.backup.rightafter configuration variable Unhides snapshot.backup.rightafter from global configuration Signed-off-by: Rajani Karuturi <rajani.karuturi@accelerite.com>
2 parents c3aff8e + 1a55a93 commit c101817

File tree

7 files changed

+79
-3
lines changed

7 files changed

+79
-3
lines changed

engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@
4444
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
4545
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
4646
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
47+
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
48+
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
4749
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
50+
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
4851
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
4952
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
5053
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@@ -178,6 +181,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
178181
ClusterManager clusterManager;
179182
@Inject
180183
StorageManager storageMgr;
184+
@Inject
185+
StorageStrategyFactory _storageStrategyFactory;
181186

182187
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
183188
protected List<StoragePoolAllocator> _storagePoolAllocators;
@@ -383,6 +388,24 @@ public VolumeInfo createVolumeFromSnapshot(Volume volume, Snapshot snapshot, Use
383388
DataStoreRole dataStoreRole = getDataStoreRole(snapshot);
384389
SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
385390

391+
392+
if(snapInfo == null && dataStoreRole == DataStoreRole.Image) {
393+
// snapshot is not backed up to secondary, let's do that now.
394+
snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary);
395+
396+
if (snapInfo == null) {
397+
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId());
398+
}
399+
// We need to copy the snapshot onto secondary.
400+
SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
401+
snapshotStrategy.backupSnapshot(snapInfo);
402+
403+
// Attempt to grab it again.
404+
snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
405+
if (snapInfo == null) {
406+
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId() + " on secondary and could not create backup");
407+
}
408+
}
386409
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
387410
if (!DataStoreRole.Primary.equals(dataStoreRole)) {
388411
try {

engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public SnapshotStateMachineManagerImpl() {
4747
stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.Error);
4848
stateMachine.addTransition(Snapshot.State.BackedUp, Event.DestroyRequested, Snapshot.State.Destroying);
4949
stateMachine.addTransition(Snapshot.State.BackedUp, Event.CopyingRequested, Snapshot.State.Copying);
50+
stateMachine.addTransition(Snapshot.State.BackedUp, Event.BackupToSecondary, Snapshot.State.BackingUp);
5051
stateMachine.addTransition(Snapshot.State.Copying, Event.OperationSucceeded, Snapshot.State.BackedUp);
5152
stateMachine.addTransition(Snapshot.State.Copying, Event.OperationFailed, Snapshot.State.BackedUp);
5253
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed);

engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl;
4040
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
4141

42+
import com.cloud.configuration.Config;
4243
import com.cloud.exception.InvalidParameterValueException;
4344
import com.cloud.hypervisor.Hypervisor;
4445
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -376,8 +377,24 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
376377

377378
snapshot = result.getSnashot();
378379
DataStore primaryStore = snapshot.getDataStore();
380+
boolean backupFlag = Boolean.parseBoolean(configDao.getValue(Config.BackupSnapshotAfterTakingSnapshot.toString()));
379381

380-
SnapshotInfo backupedSnapshot = backupSnapshot(snapshot);
382+
SnapshotInfo backupedSnapshot;
383+
if(backupFlag) {
384+
backupedSnapshot = backupSnapshot(snapshot);
385+
} else {
386+
// Fake it to get the transitions to fire in the proper order
387+
s_logger.debug("skipping backup of snapshot due to configuration "+Config.BackupSnapshotAfterTakingSnapshot.toString());
388+
389+
SnapshotObject snapObj = (SnapshotObject)snapshot;
390+
try {
391+
snapObj.processEvent(Snapshot.Event.OperationNotPerformed);
392+
} catch (NoTransitionException e) {
393+
s_logger.debug("Failed to change state: " + snapshot.getId() + ": " + e.toString());
394+
throw new CloudRuntimeException(e.toString());
395+
}
396+
backupedSnapshot = snapshot;
397+
}
381398

382399
try {
383400
SnapshotInfo parent = snapshot.getParent();

server/src/com/cloud/configuration/Config.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ public enum Config {
512512
null),
513513
SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null),
514514
BackupSnapshotAfterTakingSnapshot(
515-
"Hidden",
515+
"Snapshots",
516516
SnapshotManager.class,
517517
Boolean.class,
518518
"snapshot.backup.rightafter",

server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,13 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
10191019
DataStoreRole dataStoreRole = getDataStoreRole(snapshot, _snapshotStoreDao, dataStoreMgr);
10201020

10211021
SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, dataStoreRole);
1022-
1022+
if(snapshotStoreRef == null) {
1023+
// The snapshot was not backed up to secondary. Find the snap on primary
1024+
snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
1025+
if(snapshotStoreRef == null) {
1026+
throw new CloudRuntimeException("Could not find snapshot");
1027+
}
1028+
}
10231029
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(),
10241030
null, null, snapshotStoreRef.getPhysicalSize(), volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
10251031

server/src/com/cloud/template/TemplateManagerImpl.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@
7575
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
7676
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
7777
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
78+
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
79+
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
7880
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
81+
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
7982
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
8083
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
8184
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
@@ -254,6 +257,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
254257
@Inject
255258
private SnapshotDataFactory _snapshotFactory;
256259
@Inject
260+
StorageStrategyFactory _storageStrategyFactory;
261+
@Inject
257262
private TemplateService _tmpltSvr;
258263
@Inject
259264
private DataStoreManager _dataStoreMgr;
@@ -1493,6 +1498,21 @@ public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) t
14931498
SnapshotInfo snapInfo = _snapshotFactory.getSnapshot(snapshotId, dataStoreRole);
14941499

14951500
if (dataStoreRole == DataStoreRole.Image) {
1501+
if (snapInfo == null) {
1502+
snapInfo = _snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
1503+
if(snapInfo == null) {
1504+
throw new CloudRuntimeException("Cannot find snapshot "+snapshotId);
1505+
}
1506+
// We need to copy the snapshot onto secondary.
1507+
SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
1508+
snapshotStrategy.backupSnapshot(snapInfo);
1509+
1510+
// Attempt to grab it again.
1511+
snapInfo = _snapshotFactory.getSnapshot(snapshotId, dataStoreRole);
1512+
if(snapInfo == null) {
1513+
throw new CloudRuntimeException("Cannot find snapshot " + snapshotId + " on secondary and could not create backup");
1514+
}
1515+
}
14961516
DataStore snapStore = snapInfo.getDataStore();
14971517

14981518
if (snapStore != null) {

server/test/com/cloud/template/TemplateManagerImplTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
6969
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
7070
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
71+
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
7172
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
7273
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
7374
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@@ -161,6 +162,9 @@ public class TemplateManagerImplTest {
161162
@Inject
162163
SnapshotDao snapshotDao;
163164

165+
@Inject
166+
StorageStrategyFactory storageStrategyFactory;
167+
164168
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
165169
AtomicInteger ai = new AtomicInteger(0);
166170
public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
@@ -453,6 +457,11 @@ public VMTemplateDao vmTemplateDao() {
453457
return Mockito.mock(VMTemplateDao.class);
454458
}
455459

460+
@Bean
461+
public StorageStrategyFactory storageStrategyFactory() {
462+
return Mockito.mock(StorageStrategyFactory.class);
463+
}
464+
456465
@Bean
457466
public VMTemplatePoolDao vmTemplatePoolDao() {
458467
return Mockito.mock(VMTemplatePoolDao.class);

0 commit comments

Comments
 (0)