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
This commit is contained in:
Rajani Karuturi 2017-02-08 12:37:21 +05:30
commit 25f1552e37
7 changed files with 79 additions and 3 deletions

View File

@ -44,7 +44,10 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@ -188,6 +191,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
StorageManager storageMgr; StorageManager storageMgr;
@Inject @Inject
protected UserVmCloneSettingDao _vmCloneSettingDao; protected UserVmCloneSettingDao _vmCloneSettingDao;
@Inject
StorageStrategyFactory _storageStrategyFactory;
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine; private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
protected List<StoragePoolAllocator> _storagePoolAllocators; protected List<StoragePoolAllocator> _storagePoolAllocators;
@ -393,6 +398,24 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
DataStoreRole dataStoreRole = getDataStoreRole(snapshot); DataStoreRole dataStoreRole = getDataStoreRole(snapshot);
SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole); SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
if(snapInfo == null && dataStoreRole == DataStoreRole.Image) {
// snapshot is not backed up to secondary, let's do that now.
snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary);
if (snapInfo == null) {
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId());
}
// We need to copy the snapshot onto secondary.
SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
snapshotStrategy.backupSnapshot(snapInfo);
// Attempt to grab it again.
snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
if (snapInfo == null) {
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId() + " on secondary and could not create backup");
}
}
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary // don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
if (!DataStoreRole.Primary.equals(dataStoreRole)) { if (!DataStoreRole.Primary.equals(dataStoreRole)) {
try { try {

View File

@ -47,6 +47,7 @@ public class SnapshotStateMachineManagerImpl implements SnapshotStateMachineMana
stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.Error); stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.Error);
stateMachine.addTransition(Snapshot.State.BackedUp, Event.DestroyRequested, Snapshot.State.Destroying); stateMachine.addTransition(Snapshot.State.BackedUp, Event.DestroyRequested, Snapshot.State.Destroying);
stateMachine.addTransition(Snapshot.State.BackedUp, Event.CopyingRequested, Snapshot.State.Copying); stateMachine.addTransition(Snapshot.State.BackedUp, Event.CopyingRequested, Snapshot.State.Copying);
stateMachine.addTransition(Snapshot.State.BackedUp, Event.BackupToSecondary, Snapshot.State.BackingUp);
stateMachine.addTransition(Snapshot.State.Copying, Event.OperationSucceeded, Snapshot.State.BackedUp); stateMachine.addTransition(Snapshot.State.Copying, Event.OperationSucceeded, Snapshot.State.BackedUp);
stateMachine.addTransition(Snapshot.State.Copying, Event.OperationFailed, Snapshot.State.BackedUp); stateMachine.addTransition(Snapshot.State.Copying, Event.OperationFailed, Snapshot.State.BackedUp);
stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed); stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed);

View File

@ -39,6 +39,7 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl;
import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import com.cloud.configuration.Config;
import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.InvalidParameterValueException;
import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.Hypervisor.HypervisorType;
@ -382,8 +383,24 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
snapshot = result.getSnapshot(); snapshot = result.getSnapshot();
DataStore primaryStore = snapshot.getDataStore(); DataStore primaryStore = snapshot.getDataStore();
boolean backupFlag = Boolean.parseBoolean(configDao.getValue(Config.BackupSnapshotAfterTakingSnapshot.toString()));
SnapshotInfo backupedSnapshot = backupSnapshot(snapshot); SnapshotInfo backupedSnapshot;
if(backupFlag) {
backupedSnapshot = backupSnapshot(snapshot);
} else {
// Fake it to get the transitions to fire in the proper order
s_logger.debug("skipping backup of snapshot due to configuration "+Config.BackupSnapshotAfterTakingSnapshot.toString());
SnapshotObject snapObj = (SnapshotObject)snapshot;
try {
snapObj.processEvent(Snapshot.Event.OperationNotPerformed);
} catch (NoTransitionException e) {
s_logger.debug("Failed to change state: " + snapshot.getId() + ": " + e.toString());
throw new CloudRuntimeException(e.toString());
}
backupedSnapshot = snapshot;
}
try { try {
SnapshotInfo parent = snapshot.getParent(); SnapshotInfo parent = snapshot.getParent();

View File

@ -511,7 +511,7 @@ public enum Config {
null), null),
SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null), SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null),
BackupSnapshotAfterTakingSnapshot( BackupSnapshotAfterTakingSnapshot(
"Hidden", "Snapshots",
SnapshotManager.class, SnapshotManager.class,
Boolean.class, Boolean.class,
"snapshot.backup.rightafter", "snapshot.backup.rightafter",

View File

@ -1095,7 +1095,13 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
DataStoreRole dataStoreRole = getDataStoreRole(snapshot, _snapshotStoreDao, dataStoreMgr); DataStoreRole dataStoreRole = getDataStoreRole(snapshot, _snapshotStoreDao, dataStoreMgr);
SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, dataStoreRole); SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, dataStoreRole);
if(snapshotStoreRef == null) {
// The snapshot was not backed up to secondary. Find the snap on primary
snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
if(snapshotStoreRef == null) {
throw new CloudRuntimeException("Could not find snapshot");
}
}
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(), UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(), snapshot.getDataCenterId(), snapshotId, snapshot.getName(),
null, null, snapshotStoreRef.getPhysicalSize(), volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid()); null, null, snapshotStoreRef.getPhysicalSize(), volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());

View File

@ -75,7 +75,10 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope; import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
@ -255,6 +258,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
@Inject @Inject
private SnapshotDataFactory _snapshotFactory; private SnapshotDataFactory _snapshotFactory;
@Inject @Inject
StorageStrategyFactory _storageStrategyFactory;
@Inject
private TemplateService _tmpltSvr; private TemplateService _tmpltSvr;
@Inject @Inject
private DataStoreManager _dataStoreMgr; private DataStoreManager _dataStoreMgr;
@ -1496,6 +1501,21 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
SnapshotInfo snapInfo = _snapshotFactory.getSnapshot(snapshotId, dataStoreRole); SnapshotInfo snapInfo = _snapshotFactory.getSnapshot(snapshotId, dataStoreRole);
if (dataStoreRole == DataStoreRole.Image) { if (dataStoreRole == DataStoreRole.Image) {
if (snapInfo == null) {
snapInfo = _snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
if(snapInfo == null) {
throw new CloudRuntimeException("Cannot find snapshot "+snapshotId);
}
// We need to copy the snapshot onto secondary.
SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
snapshotStrategy.backupSnapshot(snapInfo);
// Attempt to grab it again.
snapInfo = _snapshotFactory.getSnapshot(snapshotId, dataStoreRole);
if(snapInfo == null) {
throw new CloudRuntimeException("Cannot find snapshot " + snapshotId + " on secondary and could not create backup");
}
}
DataStore snapStore = snapInfo.getDataStore(); DataStore snapStore = snapInfo.getDataStore();
if (snapStore != null) { if (snapStore != null) {

View File

@ -69,6 +69,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@ -165,6 +166,9 @@ public class TemplateManagerImplTest {
@Inject @Inject
VMTemplateDetailsDao tmpltDetailsDao; VMTemplateDetailsDao tmpltDetailsDao;
@Inject
StorageStrategyFactory storageStrategyFactory;
public class CustomThreadPoolExecutor extends ThreadPoolExecutor { public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
AtomicInteger ai = new AtomicInteger(0); AtomicInteger ai = new AtomicInteger(0);
public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
@ -457,6 +461,11 @@ public class TemplateManagerImplTest {
return Mockito.mock(VMTemplateDao.class); return Mockito.mock(VMTemplateDao.class);
} }
@Bean
public StorageStrategyFactory storageStrategyFactory() {
return Mockito.mock(StorageStrategyFactory.class);
}
@Bean @Bean
public VMTemplatePoolDao vmTemplatePoolDao() { public VMTemplatePoolDao vmTemplatePoolDao() {
return Mockito.mock(VMTemplatePoolDao.class); return Mockito.mock(VMTemplatePoolDao.class);