mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
Merge remote-tracking branch 'origin/4.17'
This commit is contained in:
commit
661956cc60
@ -36,6 +36,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
||||
@ -79,6 +80,8 @@ public class SnapshotServiceImpl implements SnapshotService {
|
||||
StorageCacheManager _cacheMgr;
|
||||
@Inject
|
||||
private SnapshotDetailsDao _snapshotDetailsDao;
|
||||
@Inject
|
||||
VolumeDataFactory volFactory;
|
||||
|
||||
static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
|
||||
final SnapshotInfo snapshot;
|
||||
@ -428,11 +431,15 @@ public class SnapshotServiceImpl implements SnapshotService {
|
||||
|
||||
@Override
|
||||
public boolean revertSnapshot(SnapshotInfo snapshot) {
|
||||
PrimaryDataStore store = null;
|
||||
SnapshotInfo snapshotOnPrimaryStore = _snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary);
|
||||
if (snapshotOnPrimaryStore == null) {
|
||||
throw new CloudRuntimeException("Cannot find an entry for snapshot " + snapshot.getId() + " on primary storage pools");
|
||||
s_logger.warn("Cannot find an entry for snapshot " + snapshot.getId() + " on primary storage pools, searching with volume's primary storage pool");
|
||||
VolumeInfo volumeInfo = volFactory.getVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
|
||||
store = (PrimaryDataStore)volumeInfo.getDataStore();
|
||||
} else {
|
||||
store = (PrimaryDataStore)snapshotOnPrimaryStore.getDataStore();
|
||||
}
|
||||
PrimaryDataStore store = (PrimaryDataStore)snapshotOnPrimaryStore.getDataStore();
|
||||
|
||||
AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
|
||||
RevertSnapshotContext<CommandResult> context = new RevertSnapshotContext<CommandResult>(null, snapshot, future);
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cloudstack.storage.snapshot;
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||
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.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
||||
import org.apache.cloudstack.storage.command.CommandResult;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({SnapshotServiceImpl.class})
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
public class SnapshotServiceImplTest {
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private SnapshotServiceImpl snapshotService = new SnapshotServiceImpl();
|
||||
|
||||
@Mock
|
||||
VolumeDataFactory volFactory;
|
||||
|
||||
@Mock
|
||||
SnapshotDataFactory _snapshotFactory;
|
||||
|
||||
@Mock
|
||||
AsyncCallFuture<SnapshotResult> futureMock;
|
||||
|
||||
@Mock
|
||||
AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller;
|
||||
|
||||
@Before
|
||||
public void testSetUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevertSnapshotWithNoPrimaryStorageEntry() throws Exception {
|
||||
SnapshotInfo snapshot = Mockito.mock(SnapshotInfo.class);
|
||||
VolumeInfo volumeInfo = Mockito.mock(VolumeInfo.class);
|
||||
|
||||
Mockito.when(snapshot.getId()).thenReturn(1L);
|
||||
Mockito.when(snapshot.getVolumeId()).thenReturn(1L);
|
||||
Mockito.when(_snapshotFactory.getSnapshot(1L, DataStoreRole.Primary)).thenReturn(null);
|
||||
Mockito.when(volFactory.getVolume(1L, DataStoreRole.Primary)).thenReturn(volumeInfo);
|
||||
|
||||
PrimaryDataStore store = Mockito.mock(PrimaryDataStore.class);
|
||||
Mockito.when(volumeInfo.getDataStore()).thenReturn(store);
|
||||
|
||||
PrimaryDataStoreDriver driver = Mockito.mock(PrimaryDataStoreDriver.class);
|
||||
Mockito.when(store.getDriver()).thenReturn(driver);
|
||||
Mockito.doNothing().when(driver).revertSnapshot(snapshot, null, caller);
|
||||
|
||||
SnapshotResult result = Mockito.mock(SnapshotResult.class);
|
||||
PowerMockito.whenNew(AsyncCallFuture.class).withNoArguments().thenReturn(futureMock);
|
||||
Mockito.when(futureMock.get()).thenReturn(result);
|
||||
Mockito.when(result.isFailed()).thenReturn(false);
|
||||
|
||||
Assert.assertEquals(true, snapshotService.revertSnapshot(snapshot));
|
||||
}
|
||||
|
||||
}
|
||||
@ -178,11 +178,13 @@ public class LibvirtRevertSnapshotCommandWrapper extends CommandWrapper<RevertSn
|
||||
* and the snapshot path from the primary storage.
|
||||
*/
|
||||
protected Pair<String, SnapshotObjectTO> getSnapshot(SnapshotObjectTO snapshotOnPrimaryStorage, SnapshotObjectTO snapshotOnSecondaryStorage,
|
||||
KVMStoragePool kvmStoragePoolPrimary, KVMStoragePool kvmStoragePoolSecondary){
|
||||
String snapshotPath = snapshotOnPrimaryStorage.getPath();
|
||||
|
||||
if (Files.exists(Paths.get(snapshotPath))) {
|
||||
return new Pair<>(snapshotPath, snapshotOnPrimaryStorage);
|
||||
KVMStoragePool kvmStoragePoolPrimary, KVMStoragePool kvmStoragePoolSecondary) {
|
||||
String snapshotPath = null;
|
||||
if (snapshotOnPrimaryStorage != null) {
|
||||
snapshotPath = snapshotOnPrimaryStorage.getPath();
|
||||
if (Files.exists(Paths.get(snapshotPath))) {
|
||||
return new Pair<>(snapshotPath, snapshotOnPrimaryStorage);
|
||||
}
|
||||
}
|
||||
|
||||
if (kvmStoragePoolSecondary == null) {
|
||||
@ -190,8 +192,10 @@ public class LibvirtRevertSnapshotCommandWrapper extends CommandWrapper<RevertSn
|
||||
snapshotOnSecondaryStorage, snapshotOnSecondaryStorage.getVolume()));
|
||||
}
|
||||
|
||||
s_logger.trace(String.format("Snapshot [%s] does not exists on primary storage [%s], searching snapshot [%s] on secondary storage [%s].", snapshotOnPrimaryStorage,
|
||||
kvmStoragePoolPrimary, snapshotOnSecondaryStorage, kvmStoragePoolSecondary));
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace(String.format("Snapshot does not exists on primary storage [%s], searching snapshot [%s] on secondary storage [%s].",
|
||||
kvmStoragePoolPrimary, snapshotOnSecondaryStorage, kvmStoragePoolSecondary));
|
||||
}
|
||||
|
||||
String snapshotPathOnSecondaryStorage = snapshotOnSecondaryStorage.getPath();
|
||||
|
||||
|
||||
@ -1536,6 +1536,7 @@ public class DateraPrimaryDataStoreDriver implements PrimaryDataStoreDriver {
|
||||
|
||||
/**
|
||||
* Revert snapshot for a volume
|
||||
*
|
||||
* @param snapshotInfo Information about volume snapshot
|
||||
* @param snapshotOnPrimaryStore Not used
|
||||
* @throws CloudRuntimeException
|
||||
|
||||
@ -41,6 +41,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StorageAction;
|
||||
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.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
@ -121,6 +122,8 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
||||
TemplateManager templateManager;
|
||||
@Inject
|
||||
TemplateDataFactory templateDataFactory;
|
||||
@Inject
|
||||
VolumeDataFactory volFactory;
|
||||
|
||||
@Override
|
||||
public DataTO getTO(DataObject data) {
|
||||
@ -379,11 +382,21 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
||||
|
||||
@Override
|
||||
public void revertSnapshot(SnapshotInfo snapshot, SnapshotInfo snapshotOnPrimaryStore, AsyncCompletionCallback<CommandResult> callback) {
|
||||
RevertSnapshotCommand cmd = new RevertSnapshotCommand((SnapshotObjectTO)snapshot.getTO(), (SnapshotObjectTO)snapshotOnPrimaryStore.getTO());
|
||||
SnapshotObjectTO dataOnPrimaryStorage = null;
|
||||
if (snapshotOnPrimaryStore != null) {
|
||||
dataOnPrimaryStorage = (SnapshotObjectTO)snapshotOnPrimaryStore.getTO();
|
||||
}
|
||||
RevertSnapshotCommand cmd = new RevertSnapshotCommand((SnapshotObjectTO)snapshot.getTO(), dataOnPrimaryStorage);
|
||||
|
||||
CommandResult result = new CommandResult();
|
||||
try {
|
||||
EndPoint ep = epSelector.select(snapshotOnPrimaryStore);
|
||||
EndPoint ep = null;
|
||||
if (snapshotOnPrimaryStore != null) {
|
||||
ep = epSelector.select(snapshotOnPrimaryStore);
|
||||
} else {
|
||||
VolumeInfo volumeInfo = volFactory.getVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
|
||||
ep = epSelector.select(volumeInfo);
|
||||
}
|
||||
if ( ep == null ){
|
||||
String errMsg = "No remote endpoint to send RevertSnapshotCommand, check if host or ssvm is down?";
|
||||
s_logger.error(errMsg);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user