Skip to content

Commit 25f1552

Browse files
committed
Merge release branch 4.9 to master
This closes #1644 * 4.9: CLOUDSTACK-4858 Honors the snapshot.backup.rightafter configuration variable Unhides snapshot.backup.rightafter from global configuration
2 parents e303baa + c101817 commit 25f1552

7 files changed

Lines changed: 79 additions & 3 deletions

File tree

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;
@@ -188,6 +191,8 @@ public enum UserVmCloneType {
188191
StorageManager storageMgr;
189192
@Inject
190193
protected UserVmCloneSettingDao _vmCloneSettingDao;
194+
@Inject
195+
StorageStrategyFactory _storageStrategyFactory;
191196

192197
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
193198
protected List<StoragePoolAllocator> _storagePoolAllocators;
@@ -393,6 +398,24 @@ public VolumeInfo createVolumeFromSnapshot(Volume volume, Snapshot snapshot, Use
393398
DataStoreRole dataStoreRole = getDataStoreRole(snapshot);
394399
SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
395400

401+
402+
if(snapInfo == null && dataStoreRole == DataStoreRole.Image) {
403+
// snapshot is not backed up to secondary, let's do that now.
404+
snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary);
405+
406+
if (snapInfo == null) {
407+
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId());
408+
}
409+
// We need to copy the snapshot onto secondary.
410+
SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
411+
snapshotStrategy.backupSnapshot(snapInfo);
412+
413+
// Attempt to grab it again.
414+
snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
415+
if (snapInfo == null) {
416+
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId() + " on secondary and could not create backup");
417+
}
418+
}
396419
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
397420
if (!DataStoreRole.Primary.equals(dataStoreRole)) {
398421
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;
@@ -382,8 +383,24 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
382383

383384
snapshot = result.getSnapshot();
384385
DataStore primaryStore = snapshot.getDataStore();
386+
boolean backupFlag = Boolean.parseBoolean(configDao.getValue(Config.BackupSnapshotAfterTakingSnapshot.toString()));
385387

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

388405
try {
389406
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
@@ -511,7 +511,7 @@ public enum Config {
511511
null),
512512
SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null),
513513
BackupSnapshotAfterTakingSnapshot(
514-
"Hidden",
514+
"Snapshots",
515515
SnapshotManager.class,
516516
Boolean.class,
517517
"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
@@ -1095,7 +1095,13 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
10951095
DataStoreRole dataStoreRole = getDataStoreRole(snapshot, _snapshotStoreDao, dataStoreMgr);
10961096

10971097
SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, dataStoreRole);
1098-
1098+
if(snapshotStoreRef == null) {
1099+
// The snapshot was not backed up to secondary. Find the snap on primary
1100+
snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
1101+
if(snapshotStoreRef == null) {
1102+
throw new CloudRuntimeException("Could not find snapshot");
1103+
}
1104+
}
10991105
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(),
11001106
null, null, snapshotStoreRef.getPhysicalSize(), volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
11011107

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;
@@ -255,6 +258,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
255258
@Inject
256259
private SnapshotDataFactory _snapshotFactory;
257260
@Inject
261+
StorageStrategyFactory _storageStrategyFactory;
262+
@Inject
258263
private TemplateService _tmpltSvr;
259264
@Inject
260265
private DataStoreManager _dataStoreMgr;
@@ -1496,6 +1501,21 @@ public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) t
14961501
SnapshotInfo snapInfo = _snapshotFactory.getSnapshot(snapshotId, dataStoreRole);
14971502

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

15011521
if (snapStore != null) {

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
7070
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
7171
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
72+
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
7273
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
7374
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
7475
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@@ -165,6 +166,9 @@ public class TemplateManagerImplTest {
165166
@Inject
166167
VMTemplateDetailsDao tmpltDetailsDao;
167168

169+
@Inject
170+
StorageStrategyFactory storageStrategyFactory;
171+
168172
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
169173
AtomicInteger ai = new AtomicInteger(0);
170174
public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
@@ -457,6 +461,11 @@ public VMTemplateDao vmTemplateDao() {
457461
return Mockito.mock(VMTemplateDao.class);
458462
}
459463

464+
@Bean
465+
public StorageStrategyFactory storageStrategyFactory() {
466+
return Mockito.mock(StorageStrategyFactory.class);
467+
}
468+
460469
@Bean
461470
public VMTemplatePoolDao vmTemplatePoolDao() {
462471
return Mockito.mock(VMTemplatePoolDao.class);

0 commit comments

Comments
 (0)