Merge remote-tracking branch 'origin/4.17'

This commit is contained in:
Rohit Yadav 2022-07-20 11:52:26 +05:30
commit 661956cc60
5 changed files with 134 additions and 11 deletions

View File

@ -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);

View File

@ -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));
}
}

View File

@ -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();

View File

@ -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

View File

@ -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);