blob: 7ba9f697b4653f9c01cb135c0534d0dff6070130 [file] [log] [blame]
/*
* 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.browser;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.UnsupportedAnswer;
import com.cloud.api.query.dao.ImageStoreJoinDao;
import com.cloud.api.query.vo.ImageStoreJoinVO;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.admin.storage.DownloadImageStoreObjectCmd;
import org.apache.cloudstack.api.command.admin.storage.ListImageStoreObjectsCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolObjectsCmd;
import org.apache.cloudstack.api.response.ListResponse;
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.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StorageBrowserImplTest {
@Mock
ImageStoreJoinDao imageStoreJoinDao;
@Mock
DataStoreManager dataStoreMgr;
@Mock
TemplateDataStoreDao templateDataStoreDao;
@Mock
SnapshotDataStoreDao snapshotDataStoreDao;
@Mock
SnapshotDao snapshotDao;
@Mock
EndPointSelector endPointSelector;
@Mock
VMTemplatePoolDao templatePoolDao;
@Mock
VMTemplateDao templateDao;
@Mock
VolumeDao volumeDao;
@Mock
VolumeDataStoreDao volumeDataStoreDao;
@InjectMocks
@Spy
private StorageBrowserImpl storageBrowser;
private AutoCloseable closeable;
@Before
public void setUp() throws Exception {
closeable = MockitoAnnotations.openMocks(this);
}
@After
public void tearDown() throws Exception {
closeable.close();
}
@Test
public void testGetPathVolumeMapForPrimaryDSNoVolumes() {
List<String> paths = List.of("volume1", "volume2");
Mockito.when(volumeDao.listByPoolIdAndPaths(1, paths)).thenReturn(null);
Map<String, VolumeVO> result = storageBrowser.getPathVolumeMapForPrimaryDS(1L, paths);
Assert.assertTrue(result.isEmpty());
}
@Test
public void testGetPathVolumeMapForPrimaryDS() {
List<String> paths = List.of("volume1", "volume2");
VolumeVO volume = Mockito.mock(VolumeVO.class);
Mockito.when(volume.getPath()).thenReturn("volume1");
Mockito.when(volumeDao.listByPoolIdAndPaths(1, paths)).thenReturn(List.of(volume));
Map<String, VolumeVO> result = storageBrowser.getPathVolumeMapForPrimaryDS(1L, paths);
Assert.assertEquals(1, result.size());
Assert.assertEquals(volume, result.get("volume1"));
}
@Test
public void testGetPathTemplateMapForPrimaryDSNoTemplates() {
List<String> paths = List.of("template1", "template2");
Mockito.when(templatePoolDao.listByPoolIdAndInstallPath(1L, paths)).thenReturn(null);
Map<String, VMTemplateVO> result = storageBrowser.getPathTemplateMapForPrimaryDS(1L, paths);
Assert.assertTrue(result.isEmpty());
}
@Test
public void testGetPathTemplateMapForPrimaryDS() {
List<String> paths = List.of("template1", "template2");
VMTemplateStoragePoolVO templatePool = Mockito.mock(VMTemplateStoragePoolVO.class);
Mockito.when(templatePool.getTemplateId()).thenReturn(5L);
Mockito.when(templatePool.getInstallPath()).thenReturn("template1");
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
Mockito.when(template.getId()).thenReturn(5L);
Mockito.when(templateDao.listByIds(List.of(5L))).thenReturn(List.of(template));
List<VMTemplateStoragePoolVO> templateStoragePoolList = List.of(templatePool);
Mockito.when(templatePoolDao.listByPoolIdAndInstallPath(1L, paths)).thenReturn(templateStoragePoolList);
Map<String, VMTemplateVO> result = storageBrowser.getPathTemplateMapForPrimaryDS(1L, paths);
Assert.assertEquals(1L, result.size());
Assert.assertEquals(template, result.get("template1"));
}
@Test
public void testGetFormattedPaths() {
List<String> paths = List.of("/path/to/file", "/path/to/file/", "path/to/file", "path/to/file/");
List<String> expectedFormattedPaths = List.of("path/to/file", "path/to/file", "path/to/file", "path/to/file");
List<String> formattedPaths = storageBrowser.getFormattedPaths(paths);
Assert.assertEquals(expectedFormattedPaths, formattedPaths);
}
@Test
public void testListImageStore() {
ListImageStoreObjectsCmd cmd = Mockito.mock(ListImageStoreObjectsCmd.class);
Long imageStoreId = 1L;
String path = "path/to/image/store";
Mockito.when(cmd.getStoreId()).thenReturn(imageStoreId);
Mockito.when(cmd.getPath()).thenReturn(path);
Mockito.when(cmd.getStartIndex()).thenReturn(0L);
Mockito.when(cmd.getPageSizeVal()).thenReturn(10L);
ImageStoreJoinVO imageStore = Mockito.mock(ImageStoreJoinVO.class);
Mockito.when(imageStoreJoinDao.findById(imageStoreId)).thenReturn(imageStore);
DataStore dataStore = Mockito.mock(DataStore.class);
Mockito.when(dataStoreMgr.getDataStore(imageStoreId, imageStore.getRole())).thenReturn(dataStore);
ListDataStoreObjectsAnswer answer = Mockito.mock(ListDataStoreObjectsAnswer.class);
Mockito.doReturn(answer).when(storageBrowser).listObjectsInStore(dataStore, path, 0, 10);
ListResponse<DataStoreObjectResponse> response = storageBrowser.listImageStoreObjects(cmd);
Assert.assertNotNull(response);
}
@Test
public void testListPrimaryStore() {
ListStoragePoolObjectsCmd cmd = Mockito.mock(ListStoragePoolObjectsCmd.class);
Long storeId = 1L;
String path = "path/to/primary/store";
Mockito.when(cmd.getStoreId()).thenReturn(storeId);
Mockito.when(cmd.getPath()).thenReturn(path);
Mockito.when(cmd.getStartIndex()).thenReturn(0L);
Mockito.when(cmd.getPageSizeVal()).thenReturn(10L);
DataStore dataStore = Mockito.mock(DataStore.class);
Mockito.when(dataStoreMgr.getDataStore(storeId, DataStoreRole.Primary)).thenReturn(dataStore);
ListDataStoreObjectsAnswer answer = Mockito.mock(ListDataStoreObjectsAnswer.class);
Mockito.doReturn(answer).when(storageBrowser).listObjectsInStore(dataStore, path, 0, 10);
ListResponse<DataStoreObjectResponse> response = storageBrowser.listPrimaryStoreObjects(cmd);
Assert.assertNotNull(response);
Assert.assertEquals(answer.getPaths().size(), response.getResponses().size());
}
@Test
public void testGetCommands() {
List<Class<?>> expectedCmdList = new ArrayList<>();
expectedCmdList.add(ListImageStoreObjectsCmd.class);
expectedCmdList.add(ListStoragePoolObjectsCmd.class);
expectedCmdList.add(DownloadImageStoreObjectCmd.class);
List<Class<?>> cmdList = storageBrowser.getCommands();
Assert.assertNotNull(cmdList);
Assert.assertEquals(expectedCmdList, cmdList);
}
@Test
public void testListObjectsInStoreNoEndpoint() {
DataStore dataStore = Mockito.mock(DataStore.class);
String path = "path/to/store";
int startIndex = 0;
int pageSize = 10;
Mockito.when(endPointSelector.select(dataStore)).thenReturn(null);
try {
storageBrowser.listObjectsInStore(dataStore, path, startIndex, pageSize);
} catch (CloudRuntimeException exception) {
Assert.assertEquals("No remote endpoint to send command", exception.getMessage());
}
}
@Test
public void testListObjectsInStoreBadCommand() {
DataStore dataStore = Mockito.mock(DataStore.class);
String path = "path/to/store";
int startIndex = 0;
int pageSize = 10;
EndPoint ep = Mockito.mock(EndPoint.class);
Mockito.when(endPointSelector.select(dataStore)).thenReturn(ep);
Answer answer = Mockito.mock(UnsupportedAnswer.class);
Mockito.when(ep.sendMessage(Mockito.any())).thenReturn(answer);
try {
storageBrowser.listObjectsInStore(dataStore, path, startIndex, pageSize);
} catch (CloudRuntimeException exception) {
Assert.assertEquals("Failed to list datastore objects", exception.getMessage());
}
}
@Test
public void testListObjectsInStorePathDoesNotExist() {
DataStore dataStore = Mockito.mock(DataStore.class);
String path = "path/to/store";
int startIndex = 0;
int pageSize = 10;
EndPoint ep = Mockito.mock(EndPoint.class);
Mockito.when(endPointSelector.select(dataStore)).thenReturn(ep);
ListDataStoreObjectsAnswer answer = Mockito.mock(ListDataStoreObjectsAnswer.class);
Mockito.when(ep.sendMessage(Mockito.any())).thenReturn(answer);
Mockito.when(answer.getResult()).thenReturn(true);
Mockito.when(answer.isPathExists()).thenReturn(false);
Mockito.when(dataStore.getUuid()).thenReturn("uuid");
try {
storageBrowser.listObjectsInStore(dataStore, path, startIndex, pageSize);
} catch (IllegalArgumentException exception) {
Assert.assertEquals("Path " + path + " doesn't exist in store: " + dataStore.getUuid(), exception.getMessage());
}
}
@Test
public void testListObjectsInStore() {
DataStore dataStore = Mockito.mock(DataStore.class);
String path = "path/to/store";
int startIndex = 0;
int pageSize = 10;
EndPoint ep = Mockito.mock(EndPoint.class);
Mockito.when(endPointSelector.select(dataStore)).thenReturn(ep);
ListDataStoreObjectsAnswer answer = Mockito.mock(ListDataStoreObjectsAnswer.class);
Mockito.when(ep.sendMessage(Mockito.any())).thenReturn(answer);
Mockito.when(answer.getResult()).thenReturn(true);
Mockito.when(answer.isPathExists()).thenReturn(true);
Assert.assertEquals(answer, storageBrowser.listObjectsInStore(dataStore, path, startIndex, pageSize));
}
@Test
public void testGetPathTemplateMapForSecondaryDS() {
long dataStoreId = 1L;
List<String> paths = List.of("/path1", "/path2");
TemplateDataStoreVO templateDataStore1 = Mockito.mock(TemplateDataStoreVO.class);
Mockito.when(templateDataStore1.getInstallPath()).thenReturn("/path1");
Mockito.when(templateDataStore1.getTemplateId()).thenReturn(1L);
TemplateDataStoreVO templateDataStore2 = Mockito.mock(TemplateDataStoreVO.class);
Mockito.when(templateDataStore2.getInstallPath()).thenReturn("/path2");
Mockito.when(templateDataStore2.getTemplateId()).thenReturn(2L);
List<TemplateDataStoreVO> templateList = List.of(templateDataStore1, templateDataStore2);
VMTemplateVO template1 = Mockito.mock(VMTemplateVO.class);
Mockito.when(template1.getId()).thenReturn(1L);
VMTemplateVO template2 = Mockito.mock(VMTemplateVO.class);
Mockito.when(template2.getId()).thenReturn(2L);
List<VMTemplateVO> templates = List.of(template1, template2);
Mockito.when(templateDataStoreDao.listByStoreIdAndInstallPaths(dataStoreId, paths)).thenReturn(templateList);
Mockito.when(templateDao.listByIds(List.of(1L, 2L))).thenReturn(templates);
Map<String, VMTemplateVO> expectedPathTemplateMap = new HashMap<>();
expectedPathTemplateMap.put("/path1", template1);
expectedPathTemplateMap.put("/path2", template2);
Map<String, VMTemplateVO> actualPathTemplateMap = storageBrowser.getPathTemplateMapForSecondaryDS(dataStoreId, paths);
Assert.assertEquals(expectedPathTemplateMap, actualPathTemplateMap);
}
@Test
public void testGetPathSnapshotMapForSecondaryDS() {
long dataStoreId = 1L;
List<String> paths = List.of("/path1", "/path2");
SnapshotDataStoreVO snapshotDataStore1 = Mockito.mock(SnapshotDataStoreVO.class);
Mockito.when(snapshotDataStore1.getInstallPath()).thenReturn("/path1");
Mockito.when(snapshotDataStore1.getSnapshotId()).thenReturn(1L);
SnapshotDataStoreVO snapshotDataStore2 = Mockito.mock(SnapshotDataStoreVO.class);
Mockito.when(snapshotDataStore2.getInstallPath()).thenReturn("/path2");
Mockito.when(snapshotDataStore2.getSnapshotId()).thenReturn(2L);
List<SnapshotDataStoreVO> snapshotDataStoreList = List.of(snapshotDataStore1, snapshotDataStore2);
SnapshotVO snapshot1 = Mockito.mock(SnapshotVO.class);
Mockito.when(snapshot1.getId()).thenReturn(1L);
SnapshotVO snapshot2 = Mockito.mock(SnapshotVO.class);
Mockito.when(snapshot2.getId()).thenReturn(2L);
List<SnapshotVO> snapshots = List.of(snapshot1, snapshot2);
Mockito.when(snapshotDataStoreDao.listByStoreAndInstallPaths(dataStoreId, DataStoreRole.Image, paths)).thenReturn(snapshotDataStoreList);
Mockito.when(snapshotDao.listByIds(new Long[]{1L, 2L})).thenReturn(snapshots);
Map<String, SnapshotVO> expectedSnapshotPathMap = new HashMap<>();
expectedSnapshotPathMap.put("/path1", snapshot1);
expectedSnapshotPathMap.put("/path2", snapshot2);
Map<String, SnapshotVO> snapshotPathMap = storageBrowser.getPathSnapshotMapForSecondaryDS(dataStoreId, paths);
Assert.assertEquals(expectedSnapshotPathMap, snapshotPathMap);
}
@Test
public void testGetPathSnapshotMapForPrimaryDS() {
long dataStoreId = 1L;
List<String> paths = List.of("path1", "path2");
List<String> absPaths = List.of("/mnt/path1", "/mnt/path2");
SnapshotDataStoreVO snapshotDataStore1 = Mockito.mock(SnapshotDataStoreVO.class);
Mockito.when(snapshotDataStore1.getInstallPath()).thenReturn("/mnt/path1");
Mockito.when(snapshotDataStore1.getSnapshotId()).thenReturn(1L);
SnapshotDataStoreVO snapshotDataStore2 = Mockito.mock(SnapshotDataStoreVO.class);
Mockito.when(snapshotDataStore2.getInstallPath()).thenReturn("/mnt/path2");
Mockito.when(snapshotDataStore2.getSnapshotId()).thenReturn(2L);
List<SnapshotDataStoreVO> snapshotDataStoreList = List.of(snapshotDataStore1, snapshotDataStore2);
SnapshotVO snapshot1 = Mockito.mock(SnapshotVO.class);
Mockito.when(snapshot1.getId()).thenReturn(1L);
SnapshotVO snapshot2 = Mockito.mock(SnapshotVO.class);
Mockito.when(snapshot2.getId()).thenReturn(2L);
List<SnapshotVO> snapshots = List.of(snapshot1, snapshot2);
Mockito.when(snapshotDataStoreDao.listByStoreAndInstallPaths(dataStoreId, DataStoreRole.Primary, absPaths)).thenReturn(snapshotDataStoreList);
Mockito.when(snapshotDao.listByIds(new Long[]{1L, 2L})).thenReturn(snapshots);
Map<String, SnapshotVO> expectedSnapshotPathMap = new HashMap<>();
expectedSnapshotPathMap.put("path1", snapshot1);
expectedSnapshotPathMap.put("path2", snapshot2);
Map<String, SnapshotVO> snapshotPathMap = storageBrowser.getPathSnapshotMapForPrimaryDS(dataStoreId, paths, absPaths);
Assert.assertEquals(expectedSnapshotPathMap, snapshotPathMap);
}
@Test
public void testGetResponse() {
ListDataStoreObjectsAnswer answer = Mockito.mock(ListDataStoreObjectsAnswer.class);
Mockito.when(answer.getPaths()).thenReturn(List.of("/path1", "/path2"));
Mockito.when(answer.getAbsPaths()).thenReturn(List.of("/path1", "/path2"));
Mockito.when(answer.getNames()).thenReturn(List.of("name1", "name2"));
Mockito.when(answer.getIsDirs()).thenReturn(List.of(true, false));
Mockito.when(answer.getSizes()).thenReturn(List.of(100L, 200L));
Mockito.when(answer.getLastModified()).thenReturn(List.of((new Date()).getTime(), (new Date()).getTime()));
List<String> paths = List.of("path1", "path2");
List<String> absPaths = List.of("/path1", "/path2");
Map<String, SnapshotVO> pathSnapshotMap = new HashMap<>();
pathSnapshotMap.put("path1", Mockito.mock(SnapshotVO.class));
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
Map<String, VMTemplateVO> pathTemplateMap = new HashMap<>();
pathTemplateMap.put("path2", template);
Mockito.when(template.getFormat()).thenReturn(Storage.ImageFormat.ISO);
Map<String, VolumeVO> pathVolumeMap = new HashMap<>();
pathVolumeMap.put("path1", Mockito.mock(VolumeVO.class));
DataStore dataStore = Mockito.mock(DataStore.class);
Mockito.when(dataStore.getRole()).thenReturn(DataStoreRole.Primary);
Mockito.when(dataStore.getId()).thenReturn(1L);
Mockito.doReturn(pathTemplateMap).when(storageBrowser).getPathTemplateMapForPrimaryDS(1L, paths);
Mockito.doReturn(pathSnapshotMap).when(storageBrowser).getPathSnapshotMapForPrimaryDS(1L, paths, absPaths);
Mockito.doReturn(pathVolumeMap).when(storageBrowser).getPathVolumeMapForPrimaryDS(1L, paths);
ListResponse<DataStoreObjectResponse> response = storageBrowser.getResponse(dataStore, answer);
Assert.assertEquals(2, response.getResponses().size());
Assert.assertEquals("name1", response.getResponses().get(0).getName());
Assert.assertEquals(true, response.getResponses().get(0).isDirectory());
Assert.assertEquals(100L, response.getResponses().get(0).getSize());
Assert.assertNotNull(response.getResponses().get(0).getLastUpdated());
Assert.assertEquals("name2", response.getResponses().get(1).getName());
Assert.assertEquals(false, response.getResponses().get(1).isDirectory());
Assert.assertEquals(200L, response.getResponses().get(1).getSize());
Assert.assertNotNull(response.getResponses().get(1).getLastUpdated());
}
}