mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
add table lock on snapshot, during taking snapshot
Conflicts: engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
This commit is contained in:
parent
b5f7e307a1
commit
a82b179878
@ -18,6 +18,8 @@ package org.apache.cloudstack.storage.test;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.cloud.event.ActionEventUtils;
|
||||||
|
import com.cloud.event.dao.EventDaoImpl;
|
||||||
import org.apache.cloudstack.acl.APIChecker;
|
import org.apache.cloudstack.acl.APIChecker;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||||
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
||||||
@ -107,7 +109,7 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
|
|||||||
VMSnapshotDaoImpl.class, OCFS2ManagerImpl.class, ClusterDetailsDaoImpl.class, SecondaryStorageVmDaoImpl.class,
|
VMSnapshotDaoImpl.class, OCFS2ManagerImpl.class, ClusterDetailsDaoImpl.class, SecondaryStorageVmDaoImpl.class,
|
||||||
ConsoleProxyDaoImpl.class, StoragePoolWorkDaoImpl.class, StorageCacheManagerImpl.class, UserDaoImpl.class,
|
ConsoleProxyDaoImpl.class, StoragePoolWorkDaoImpl.class, StorageCacheManagerImpl.class, UserDaoImpl.class,
|
||||||
DataCenterDaoImpl.class, StoragePoolDetailsDaoImpl.class, DomainDaoImpl.class, DownloadMonitorImpl.class,
|
DataCenterDaoImpl.class, StoragePoolDetailsDaoImpl.class, DomainDaoImpl.class, DownloadMonitorImpl.class,
|
||||||
AccountDaoImpl.class }, includeFilters = { @Filter(value = Library.class, type = FilterType.CUSTOM) },
|
AccountDaoImpl.class, ActionEventUtils.class, EventDaoImpl.class}, includeFilters = { @Filter(value = Library.class, type = FilterType.CUSTOM) },
|
||||||
useDefaultFilters = false)
|
useDefaultFilters = false)
|
||||||
public class ChildTestConfiguration extends TestConfiguration {
|
public class ChildTestConfiguration extends TestConfiguration {
|
||||||
|
|
||||||
|
|||||||
@ -28,23 +28,30 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||||
|
import org.apache.cloudstack.storage.snapshot.SnapshotObject;
|
||||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||||
|
|
||||||
public class MockStorageMotionStrategy implements DataMotionStrategy {
|
public class MockStorageMotionStrategy implements DataMotionStrategy {
|
||||||
|
|
||||||
|
boolean success = true;
|
||||||
@Override
|
@Override
|
||||||
public boolean canHandle(DataObject srcData, DataObject destData) {
|
public boolean canHandle(DataObject srcData, DataObject destData) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void makeBackupSnapshotSucceed(boolean success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
|
public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
|
||||||
return true;
|
return true;
|
||||||
@ -54,9 +61,19 @@ public class MockStorageMotionStrategy implements DataMotionStrategy {
|
|||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
CopyCmdAnswer answer = null;
|
CopyCmdAnswer answer = null;
|
||||||
DataTO data = null;
|
DataTO data = null;
|
||||||
|
if (!success) {
|
||||||
|
CopyCommandResult result = new CopyCommandResult(null, null);
|
||||||
|
result.setResult("Failed");
|
||||||
|
callback.complete(result);
|
||||||
|
}
|
||||||
if (destData.getType() == DataObjectType.SNAPSHOT) {
|
if (destData.getType() == DataObjectType.SNAPSHOT) {
|
||||||
|
SnapshotInfo srcSnapshot = (SnapshotInfo)srcData;
|
||||||
|
|
||||||
SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
|
SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
|
||||||
newSnapshot.setPath(UUID.randomUUID().toString());
|
newSnapshot.setPath(UUID.randomUUID().toString());
|
||||||
|
if (srcSnapshot.getParent() != null) {
|
||||||
|
newSnapshot.setParentSnapshotPath(srcSnapshot.getParent().getPath());
|
||||||
|
}
|
||||||
data = newSnapshot;
|
data = newSnapshot;
|
||||||
} else if (destData.getType() == DataObjectType.TEMPLATE) {
|
} else if (destData.getType() == DataObjectType.TEMPLATE) {
|
||||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||||
|
|||||||
@ -18,18 +18,37 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cloudstack.storage.test;
|
package org.apache.cloudstack.storage.test;
|
||||||
|
|
||||||
|
import com.cloud.cluster.LockMasterListener;
|
||||||
|
import com.cloud.dc.ClusterVO;
|
||||||
|
import com.cloud.dc.DataCenter;
|
||||||
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.dc.HostPodVO;
|
||||||
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
|
import com.cloud.org.Cluster;
|
||||||
|
import com.cloud.org.Managed;
|
||||||
|
import com.cloud.storage.CreateSnapshotPayload;
|
||||||
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.storage.ScopeType;
|
import com.cloud.storage.ScopeType;
|
||||||
import com.cloud.storage.Snapshot;
|
import com.cloud.storage.Snapshot;
|
||||||
|
import com.cloud.storage.SnapshotPolicyVO;
|
||||||
import com.cloud.storage.SnapshotVO;
|
import com.cloud.storage.SnapshotVO;
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.StoragePoolStatus;
|
import com.cloud.storage.StoragePoolStatus;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.dao.SnapshotDao;
|
import com.cloud.storage.dao.SnapshotDao;
|
||||||
|
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
import com.cloud.user.AccountManager;
|
||||||
|
import com.cloud.user.User;
|
||||||
|
import com.cloud.utils.DateUtil;
|
||||||
import com.cloud.utils.component.ComponentContext;
|
import com.cloud.utils.component.ComponentContext;
|
||||||
import com.cloud.utils.db.DB;
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.Merovingian2;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||||
@ -45,10 +64,14 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||||
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
|
import org.apache.cloudstack.storage.volume.VolumeObject;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -59,7 +82,9 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@ -70,6 +95,9 @@ import java.util.concurrent.Executors;
|
|||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(locations = { "classpath:/fakeDriverTestContext.xml" })
|
@ContextConfiguration(locations = { "classpath:/fakeDriverTestContext.xml" })
|
||||||
public class SnapshotTestWithFakeData {
|
public class SnapshotTestWithFakeData {
|
||||||
@ -93,31 +121,106 @@ public class SnapshotTestWithFakeData {
|
|||||||
VolumeService volumeService;
|
VolumeService volumeService;
|
||||||
@Inject
|
@Inject
|
||||||
VolumeDataFactory volumeDataFactory;
|
VolumeDataFactory volumeDataFactory;
|
||||||
|
@Inject
|
||||||
|
DataCenterDao dcDao;
|
||||||
|
Long dcId;
|
||||||
|
@Inject
|
||||||
|
HostPodDao podDao;
|
||||||
|
Long podId;
|
||||||
|
@Inject
|
||||||
|
ClusterDao clusterDao;
|
||||||
|
Long clusterId;
|
||||||
|
@Inject
|
||||||
|
ImageStoreDao imageStoreDao;
|
||||||
|
ImageStoreVO imageStore;
|
||||||
|
@Inject
|
||||||
|
AccountManager accountManager;
|
||||||
|
LockMasterListener lockMasterListener;
|
||||||
VolumeInfo vol = null;
|
VolumeInfo vol = null;
|
||||||
FakePrimaryDataStoreDriver driver = new FakePrimaryDataStoreDriver();
|
FakePrimaryDataStoreDriver driver = new FakePrimaryDataStoreDriver();
|
||||||
|
@Inject
|
||||||
|
MockStorageMotionStrategy mockStorageMotionStrategy;
|
||||||
|
Merovingian2 _lockMaster;
|
||||||
|
@Inject
|
||||||
|
SnapshotPolicyDao snapshotPolicyDao;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
Mockito.when(primaryDataStoreProvider.configure(Mockito.anyMap())).thenReturn(true);
|
// create data center
|
||||||
|
|
||||||
|
DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null,
|
||||||
|
"10.0.0.1/24", null, null, DataCenter.NetworkType.Basic, null, null, true, true, null, null);
|
||||||
|
dc = dcDao.persist(dc);
|
||||||
|
dcId = dc.getId();
|
||||||
|
// create pod
|
||||||
|
|
||||||
|
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "10.223.0.1",
|
||||||
|
"10.233.2.2/25", 8, "test");
|
||||||
|
pod = podDao.persist(pod);
|
||||||
|
podId = pod.getId();
|
||||||
|
// create xen cluster
|
||||||
|
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||||
|
cluster.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString());
|
||||||
|
cluster.setClusterType(Cluster.ClusterType.CloudManaged);
|
||||||
|
cluster.setManagedState(Managed.ManagedState.Managed);
|
||||||
|
cluster = clusterDao.persist(cluster);
|
||||||
|
clusterId = cluster.getId();
|
||||||
|
|
||||||
|
imageStore = new ImageStoreVO();
|
||||||
|
imageStore.setName(UUID.randomUUID().toString());
|
||||||
|
imageStore.setDataCenterId(dcId);
|
||||||
|
imageStore.setProviderName(DataStoreProvider.NFS_IMAGE);
|
||||||
|
imageStore.setRole(DataStoreRole.Image);
|
||||||
|
imageStore.setUrl(UUID.randomUUID().toString());
|
||||||
|
imageStore.setUuid(UUID.randomUUID().toString());
|
||||||
|
imageStore.setProtocol("nfs");
|
||||||
|
imageStore = imageStoreDao.persist(imageStore);
|
||||||
|
|
||||||
|
when(primaryDataStoreProvider.configure(Mockito.anyMap())).thenReturn(true);
|
||||||
Set<DataStoreProvider.DataStoreProviderType> types = new HashSet<DataStoreProvider.DataStoreProviderType>();
|
Set<DataStoreProvider.DataStoreProviderType> types = new HashSet<DataStoreProvider.DataStoreProviderType>();
|
||||||
types.add(DataStoreProvider.DataStoreProviderType.PRIMARY);
|
types.add(DataStoreProvider.DataStoreProviderType.PRIMARY);
|
||||||
|
|
||||||
Mockito.when(primaryDataStoreProvider.getTypes()).thenReturn(types);
|
when(primaryDataStoreProvider.getTypes()).thenReturn(types);
|
||||||
Mockito.when(primaryDataStoreProvider.getName()).thenReturn(DataStoreProvider.DEFAULT_PRIMARY);
|
when(primaryDataStoreProvider.getName()).thenReturn(DataStoreProvider.DEFAULT_PRIMARY);
|
||||||
Mockito.when(primaryDataStoreProvider.getDataStoreDriver()).thenReturn(driver);
|
when(primaryDataStoreProvider.getDataStoreDriver()).thenReturn(driver);
|
||||||
|
User user = mock(User.class);
|
||||||
|
when(user.getId()).thenReturn(1L);
|
||||||
|
Account account = mock(Account.class);
|
||||||
|
when(account.getId()).thenReturn(1L);
|
||||||
|
when(accountManager.getSystemAccount()).thenReturn(account);
|
||||||
|
when(accountManager.getSystemUser()).thenReturn(user);
|
||||||
|
|
||||||
|
if(Merovingian2.getLockMaster() == null) {
|
||||||
|
_lockMaster = Merovingian2.createLockMaster(1234);
|
||||||
|
} else {
|
||||||
|
_lockMaster = Merovingian2.getLockMaster();
|
||||||
|
}
|
||||||
|
_lockMaster.cleanupThisServer();
|
||||||
ComponentContext.initComponentsLifeCycle();
|
ComponentContext.initComponentsLifeCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
_lockMaster.cleanupThisServer();
|
||||||
|
}
|
||||||
private SnapshotVO createSnapshotInDb() {
|
private SnapshotVO createSnapshotInDb() {
|
||||||
Snapshot.Type snapshotType = Snapshot.Type.MANUAL;
|
Snapshot.Type snapshotType = Snapshot.Type.RECURRING;
|
||||||
SnapshotVO snapshotVO = new SnapshotVO(1, 2, 1, 1L, 1L, UUID.randomUUID()
|
SnapshotVO snapshotVO = new SnapshotVO(dcId, 2, 1, 1L, 1L, UUID.randomUUID()
|
||||||
|
.toString(), (short) snapshotType.ordinal(), snapshotType.name(), 100,
|
||||||
|
Hypervisor.HypervisorType.XenServer);
|
||||||
|
return this.snapshotDao.persist(snapshotVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SnapshotVO createSnapshotInDb(Long volumeId) {
|
||||||
|
Snapshot.Type snapshotType = Snapshot.Type.DAILY;
|
||||||
|
SnapshotVO snapshotVO = new SnapshotVO(dcId, 2, 1, volumeId, 1L, UUID.randomUUID()
|
||||||
.toString(), (short) snapshotType.ordinal(), snapshotType.name(), 100,
|
.toString(), (short) snapshotType.ordinal(), snapshotType.name(), 100,
|
||||||
Hypervisor.HypervisorType.XenServer);
|
Hypervisor.HypervisorType.XenServer);
|
||||||
return this.snapshotDao.persist(snapshotVO);
|
return this.snapshotDao.persist(snapshotVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VolumeInfo createVolume(Long templateId, DataStore store) {
|
private VolumeInfo createVolume(Long templateId, DataStore store) {
|
||||||
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), 1L, 1L, 1L, 1L, 1000, 0L, 0L, "");
|
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
|
||||||
;
|
;
|
||||||
volume.setPoolId(store.getId());
|
volume.setPoolId(store.getId());
|
||||||
|
|
||||||
@ -129,8 +232,8 @@ public class SnapshotTestWithFakeData {
|
|||||||
}
|
}
|
||||||
private DataStore createDataStore() throws URISyntaxException {
|
private DataStore createDataStore() throws URISyntaxException {
|
||||||
StoragePoolVO pool = new StoragePoolVO();
|
StoragePoolVO pool = new StoragePoolVO();
|
||||||
pool.setClusterId(1L);
|
pool.setClusterId(clusterId);
|
||||||
pool.setDataCenterId(1);
|
pool.setDataCenterId(dcId);
|
||||||
URI uri = new URI("nfs://jfkdkf/fjdkfj");
|
URI uri = new URI("nfs://jfkdkf/fjdkfj");
|
||||||
pool.setHostAddress(uri.getHost());
|
pool.setHostAddress(uri.getHost());
|
||||||
pool.setPath(uri.getPath());
|
pool.setPath(uri.getPath());
|
||||||
@ -139,14 +242,14 @@ public class SnapshotTestWithFakeData {
|
|||||||
pool.setUuid(UUID.randomUUID().toString());
|
pool.setUuid(UUID.randomUUID().toString());
|
||||||
pool.setStatus(StoragePoolStatus.Up);
|
pool.setStatus(StoragePoolStatus.Up);
|
||||||
pool.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
|
pool.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
|
||||||
pool.setPodId(1L);
|
pool.setPodId(podId);
|
||||||
pool.setScope(ScopeType.CLUSTER);
|
pool.setScope(ScopeType.CLUSTER);
|
||||||
pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY);
|
pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY);
|
||||||
pool = this.primaryDataStoreDao.persist(pool);
|
pool = this.primaryDataStoreDao.persist(pool);
|
||||||
DataStore store = this.dataStoreManager.getPrimaryDataStore(pool.getId());
|
DataStore store = this.dataStoreManager.getPrimaryDataStore(pool.getId());
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
@Test
|
//@Test
|
||||||
public void testTakeSnapshot() throws URISyntaxException {
|
public void testTakeSnapshot() throws URISyntaxException {
|
||||||
SnapshotVO snapshotVO = createSnapshotInDb();
|
SnapshotVO snapshotVO = createSnapshotInDb();
|
||||||
DataStore store = createDataStore();
|
DataStore store = createDataStore();
|
||||||
@ -167,7 +270,7 @@ public class SnapshotTestWithFakeData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
//@Test
|
||||||
public void testTakeSnapshotWithFailed() throws URISyntaxException {
|
public void testTakeSnapshotWithFailed() throws URISyntaxException {
|
||||||
SnapshotVO snapshotVO = createSnapshotInDb();
|
SnapshotVO snapshotVO = createSnapshotInDb();
|
||||||
DataStore store = null;
|
DataStore store = null;
|
||||||
@ -188,7 +291,7 @@ public class SnapshotTestWithFakeData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
//@Test
|
||||||
public void testTakeSnapshotFromVolume() throws URISyntaxException {
|
public void testTakeSnapshotFromVolume() throws URISyntaxException {
|
||||||
DataStore store = createDataStore();
|
DataStore store = createDataStore();
|
||||||
FakePrimaryDataStoreDriver dataStoreDriver = (FakePrimaryDataStoreDriver)store.getDriver();
|
FakePrimaryDataStoreDriver dataStoreDriver = (FakePrimaryDataStoreDriver)store.getDriver();
|
||||||
@ -200,32 +303,57 @@ public class SnapshotTestWithFakeData {
|
|||||||
Assert.assertTrue(result == null);
|
Assert.assertTrue(result == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected SnapshotPolicyVO createSnapshotPolicy(Long volId) {
|
||||||
|
SnapshotPolicyVO policyVO = new SnapshotPolicyVO(volId, "jfkd", "fdfd", DateUtil.IntervalType.DAILY, 8);
|
||||||
|
policyVO = snapshotPolicyDao.persist(policyVO);
|
||||||
|
return policyVO;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConcurrentSnapshot() throws URISyntaxException, InterruptedException, ExecutionException {
|
public void testConcurrentSnapshot() throws URISyntaxException, InterruptedException, ExecutionException {
|
||||||
DataStore store = createDataStore();
|
DataStore store = createDataStore();
|
||||||
FakePrimaryDataStoreDriver dataStoreDriver = (FakePrimaryDataStoreDriver)store.getDriver();
|
final FakePrimaryDataStoreDriver dataStoreDriver = (FakePrimaryDataStoreDriver)store.getDriver();
|
||||||
dataStoreDriver.makeTakeSnapshotSucceed(true);
|
dataStoreDriver.makeTakeSnapshotSucceed(true);
|
||||||
final VolumeInfo volumeInfo = createVolume(1L, store);
|
final VolumeInfo volumeInfo = createVolume(1L, store);
|
||||||
Assert.assertTrue(volumeInfo.getState() == Volume.State.Ready);
|
Assert.assertTrue(volumeInfo.getState() == Volume.State.Ready);
|
||||||
vol = volumeInfo;
|
vol = volumeInfo;
|
||||||
|
// final SnapshotPolicyVO policyVO = createSnapshotPolicy(vol.getId());
|
||||||
|
|
||||||
|
|
||||||
ExecutorService pool = Executors.newFixedThreadPool(2);
|
ExecutorService pool = Executors.newFixedThreadPool(2);
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Future<Boolean> future = null;
|
List<Future<Boolean>> future = new ArrayList<Future<Boolean>>();
|
||||||
for(int i = 0; i < 1; i++) {
|
for(int i = 0; i < 12; i++) {
|
||||||
future = pool.submit(new Callable<Boolean>() {
|
final int cnt = i;
|
||||||
|
Future<Boolean> task = pool.submit(new Callable<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean call() throws Exception {
|
public Boolean call() throws Exception {
|
||||||
boolean r = false;
|
boolean r = true;
|
||||||
try {
|
try {
|
||||||
|
SnapshotVO snapshotVO = createSnapshotInDb(vol.getId());
|
||||||
|
VolumeObject volumeObject = (VolumeObject)vol;
|
||||||
|
Account account = mock(Account.class);
|
||||||
|
when(account.getId()).thenReturn(1L);
|
||||||
|
CreateSnapshotPayload createSnapshotPayload = mock(CreateSnapshotPayload.class);
|
||||||
|
when(createSnapshotPayload.getAccount()).thenReturn(account);
|
||||||
|
when(createSnapshotPayload.getSnapshotId()).thenReturn(snapshotVO.getId());
|
||||||
|
when(createSnapshotPayload.getSnapshotPolicyId()).thenReturn(0L);
|
||||||
|
volumeObject.addPayload(createSnapshotPayload);
|
||||||
|
if (cnt > 8) {
|
||||||
|
mockStorageMotionStrategy.makeBackupSnapshotSucceed(false);
|
||||||
|
}
|
||||||
SnapshotInfo newSnapshot = volumeService.takeSnapshot(vol);
|
SnapshotInfo newSnapshot = volumeService.takeSnapshot(vol);
|
||||||
Assert.assertTrue(newSnapshot != null);
|
if (newSnapshot == null) {
|
||||||
|
r = false;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
r = false;
|
r = false;
|
||||||
}
|
}
|
||||||
return true;
|
return r;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Assert.assertTrue(task.get());
|
||||||
}
|
}
|
||||||
future.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,5 +86,6 @@
|
|||||||
<bean id='SnapshotManagerImpl' class='com.cloud.storage.snapshot.SnapshotManagerImpl'/>
|
<bean id='SnapshotManagerImpl' class='com.cloud.storage.snapshot.SnapshotManagerImpl'/>
|
||||||
<bean id='SnapshotPolicyDao' class='com.cloud.storage.dao.SnapshotPolicyDaoImpl'/>
|
<bean id='SnapshotPolicyDao' class='com.cloud.storage.dao.SnapshotPolicyDaoImpl'/>
|
||||||
<bean id='SnapshotScheduleDao' class='com.cloud.storage.dao.SnapshotScheduleDaoImpl' />
|
<bean id='SnapshotScheduleDao' class='com.cloud.storage.dao.SnapshotScheduleDaoImpl' />
|
||||||
|
<bean id='UserContextInitializer' class='com.cloud.user.UserContextInitializer' />
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package org.apache.cloudstack.storage.snapshot;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.*;
|
import org.apache.cloudstack.engine.subsystem.api.storage.*;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||||
@ -189,7 +190,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
|
|
||||||
if (!Snapshot.State.BackedUp.equals(snapshotVO.getState())) {
|
if (!Snapshot.State.BackedUp.equals(snapshotVO.getState())) {
|
||||||
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId
|
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId
|
||||||
+ " due to it is not in BackedUp Status");
|
+ " due to it is in " + snapshotVO.getState() + " Status");
|
||||||
}
|
}
|
||||||
|
|
||||||
// first mark the snapshot as destroyed, so that ui can't see it, but we
|
// first mark the snapshot as destroyed, so that ui can't see it, but we
|
||||||
@ -235,7 +236,14 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@DB
|
||||||
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
|
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
|
||||||
|
SnapshotVO snapshotVO = snapshotDao.acquireInLockTable(snapshot.getId());
|
||||||
|
if (snapshotVO == null) {
|
||||||
|
throw new CloudRuntimeException("Failed to get lock on snapshot:" + snapshot.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
SnapshotResult result = snapshotSvr.takeSnapshot(snapshot);
|
SnapshotResult result = snapshotSvr.takeSnapshot(snapshot);
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
s_logger.debug("Failed to take snapshot: " + result.getResult());
|
s_logger.debug("Failed to take snapshot: " + result.getResult());
|
||||||
@ -245,6 +253,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
DataStore primaryStore = snapshot.getDataStore();
|
DataStore primaryStore = snapshot.getDataStore();
|
||||||
|
|
||||||
SnapshotInfo backupedSnapshot = this.backupSnapshot(snapshot);
|
SnapshotInfo backupedSnapshot = this.backupSnapshot(snapshot);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SnapshotInfo parent = snapshot.getParent();
|
SnapshotInfo parent = snapshot.getParent();
|
||||||
if (backupedSnapshot != null && parent != null) {
|
if (backupedSnapshot != null && parent != null) {
|
||||||
@ -269,6 +278,11 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
s_logger.debug("Failed to clean up snapshots on primary storage", e);
|
s_logger.debug("Failed to clean up snapshots on primary storage", e);
|
||||||
}
|
}
|
||||||
return backupedSnapshot;
|
return backupedSnapshot;
|
||||||
|
} finally {
|
||||||
|
if (snapshotVO != null) {
|
||||||
|
snapshotDao.releaseFromLockTable(snapshot.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -25,7 +25,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import com.cloud.utils.db.SearchCriteria2;
|
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||||
@ -179,6 +180,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@DB
|
||||||
public SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId) {
|
public SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId) {
|
||||||
Transaction txn = Transaction.currentTxn();
|
Transaction txn = Transaction.currentTxn();
|
||||||
PreparedStatement pstmt = null;
|
PreparedStatement pstmt = null;
|
||||||
@ -197,8 +199,6 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
s_logger.debug("Failed to find parent snapshot: " + e.toString());
|
s_logger.debug("Failed to find parent snapshot: " + e.toString());
|
||||||
} finally {
|
|
||||||
txn.close();
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1292,8 +1292,10 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
@Override
|
@Override
|
||||||
public SnapshotInfo takeSnapshot(VolumeInfo volume) {
|
public SnapshotInfo takeSnapshot(VolumeInfo volume) {
|
||||||
VolumeObject vol = (VolumeObject) volume;
|
VolumeObject vol = (VolumeObject) volume;
|
||||||
vol.stateTransit(Volume.Event.SnapshotRequested);
|
boolean result = vol.stateTransit(Volume.Event.SnapshotRequested);
|
||||||
|
if (!result) {
|
||||||
|
s_logger.debug("Failed to transit state");
|
||||||
|
}
|
||||||
SnapshotInfo snapshot = null;
|
SnapshotInfo snapshot = null;
|
||||||
try {
|
try {
|
||||||
snapshot = snapshotMgr.takeSnapshot(volume);
|
snapshot = snapshotMgr.takeSnapshot(volume);
|
||||||
|
|||||||
@ -459,7 +459,9 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
while (snaps.size() > maxSnaps && snaps.size() > 1) {
|
while (snaps.size() > maxSnaps && snaps.size() > 1) {
|
||||||
SnapshotVO oldestSnapshot = snaps.get(0);
|
SnapshotVO oldestSnapshot = snaps.get(0);
|
||||||
long oldSnapId = oldestSnapshot.getId();
|
long oldSnapId = oldestSnapshot.getId();
|
||||||
|
if (policy != null) {
|
||||||
s_logger.debug("Max snaps: " + policy.getMaxSnaps() + " exceeded for snapshot policy with Id: " + policyId + ". Deleting oldest snapshot: " + oldSnapId);
|
s_logger.debug("Max snaps: " + policy.getMaxSnaps() + " exceeded for snapshot policy with Id: " + policyId + ". Deleting oldest snapshot: " + oldSnapId);
|
||||||
|
}
|
||||||
if(deleteSnapshot(oldSnapId)){
|
if(deleteSnapshot(oldSnapId)){
|
||||||
//log Snapshot delete event
|
//log Snapshot delete event
|
||||||
ActionEventUtils.onCompletedActionEvent(User.UID_SYSTEM, oldestSnapshot.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_SNAPSHOT_DELETE, "Successfully deleted oldest snapshot: " + oldSnapId, 0);
|
ActionEventUtils.onCompletedActionEvent(User.UID_SYSTEM, oldestSnapshot.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_SNAPSHOT_DELETE, "Successfully deleted oldest snapshot: " + oldSnapId, 0);
|
||||||
@ -997,6 +999,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@DB
|
||||||
public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException {
|
public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException {
|
||||||
CreateSnapshotPayload payload = (CreateSnapshotPayload)volume.getpayload();
|
CreateSnapshotPayload payload = (CreateSnapshotPayload)volume.getpayload();
|
||||||
Long snapshotId = payload.getSnapshotId();
|
Long snapshotId = payload.getSnapshotId();
|
||||||
@ -1015,15 +1018,17 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
if (!processed) {
|
if (!processed) {
|
||||||
throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId);
|
throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
|
postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
|
||||||
|
|
||||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
|
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
|
||||||
snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
|
snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
|
||||||
volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
|
volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
|
||||||
|
|
||||||
|
|
||||||
_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
|
_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("post process snapshot failed", e);
|
||||||
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
s_logger.debug("Failed to create snapshot", e);
|
s_logger.debug("Failed to create snapshot", e);
|
||||||
if (backup) {
|
if (backup) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user