This is an automated email from the ASF dual-hosted git repository.

rafael pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 21c0225  Fix the problem at #1740 when it loads all snapshots in the 
primary storage (#2808)
21c0225 is described below

commit 21c0225921a4b9dd8ba2fb823629ab7b6a23ee34
Author: Rafael Weingärtner <[email protected]>
AuthorDate: Fri Aug 17 08:33:25 2018 -0300

    Fix the problem at #1740 when it loads all snapshots in the primary storage 
(#2808)
    
    * Fix the problem at #1740 when it loads all snapshots in the primary 
storage
    
    While checking a problem with @mike-tutkowski at PR #1740, we noticed that 
the method 
`org.apache.cloudstack.storage.snapshot.SnapshotDataFactoryImpl.getSnapshots(long,
 DataStoreRole)` was not loading the snapshots in `snapshot_store_ref` table 
according to their storage role. Instead, it would return a list of all 
snapshots (even if they are not in the storage role sent as a parameter) saying 
that they are in the storage that was sent as parameter.
    
    * Add unit test
---
 .../storage/datastore/db/SnapshotDataStoreDao.java |   7 +-
 .../storage/snapshot/SnapshotDataFactoryImpl.java  |  23 +++--
 .../snapshot/SnapshotDataFactoryImplTest.java      | 110 +++++++++++++++++++++
 .../storage/image/db/SnapshotDataStoreDaoImpl.java | 100 ++++++++++---------
 4 files changed, 182 insertions(+), 58 deletions(-)

diff --git 
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
 
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
index 20cff56..50f311a 100644
--- 
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
+++ 
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
@@ -26,7 +26,7 @@ import com.cloud.utils.db.GenericDao;
 import com.cloud.utils.fsm.StateDao;
 
 public interface SnapshotDataStoreDao extends GenericDao<SnapshotDataStoreVO, 
Long>,
-        StateDao<ObjectInDataStoreStateMachine.State, 
ObjectInDataStoreStateMachine.Event, DataObjectInStore> {
+StateDao<ObjectInDataStoreStateMachine.State, 
ObjectInDataStoreStateMachine.Event, DataObjectInStore> {
 
     List<SnapshotDataStoreVO> listByStoreId(long id, DataStoreRole role);
 
@@ -63,5 +63,10 @@ public interface SnapshotDataStoreDao extends 
GenericDao<SnapshotDataStoreVO, Lo
 
     SnapshotDataStoreVO findByVolume(long volumeId, DataStoreRole role);
 
+    /**
+     * List all snapshots in 'snapshot_store_ref' by volume and data store 
role. Therefore, it is possible to list all snapshots that are in the primary 
storage or in the secondary storage.
+     */
+    List<SnapshotDataStoreVO> listAllByVolumeAndDataStore(long volumeId, 
DataStoreRole role);
+
     List<SnapshotDataStoreVO> 
listByState(ObjectInDataStoreStateMachine.State... states);
 }
diff --git 
a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
 
b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
index ad58f42..11d61df 100644
--- 
a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
+++ 
b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
@@ -28,9 +28,9 @@ 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.SnapshotDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
+import org.apache.commons.collections.CollectionUtils;
 
 import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.SnapshotVO;
@@ -38,14 +38,13 @@ import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.utils.exception.CloudRuntimeException;
 
 public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
+
     @Inject
-    SnapshotDao snapshotDao;
-    @Inject
-    SnapshotDataStoreDao snapshotStoreDao;
+    private SnapshotDao snapshotDao;
     @Inject
-    DataStoreManager storeMgr;
+    private SnapshotDataStoreDao snapshotStoreDao;
     @Inject
-    VolumeDataFactory volumeFactory;
+    private DataStoreManager storeMgr;
 
     @Override
     public SnapshotInfo getSnapshot(long snapshotId, DataStore store) {
@@ -66,16 +65,16 @@ public class SnapshotDataFactoryImpl implements 
SnapshotDataFactory {
 
     @Override
     public List<SnapshotInfo> getSnapshots(long volumeId, DataStoreRole role) {
-
-        SnapshotDataStoreVO snapshotStore = 
snapshotStoreDao.findByVolume(volumeId, role);
-        if (snapshotStore == null) {
+        List<SnapshotDataStoreVO> allSnapshotsFromVolumeAndDataStore = 
snapshotStoreDao.listAllByVolumeAndDataStore(volumeId, role);
+        if (CollectionUtils.isEmpty(allSnapshotsFromVolumeAndDataStore)) {
             return new ArrayList<>();
         }
-        DataStore store = 
storeMgr.getDataStore(snapshotStore.getDataStoreId(), role);
-        List<SnapshotVO> volSnapShots = snapshotDao.listByVolumeId(volumeId);
         List<SnapshotInfo> infos = new ArrayList<>();
-        for(SnapshotVO snapshot: volSnapShots) {
+        for (SnapshotDataStoreVO snapshotDataStoreVO : 
allSnapshotsFromVolumeAndDataStore) {
+            DataStore store = 
storeMgr.getDataStore(snapshotDataStoreVO.getDataStoreId(), role);
+            SnapshotVO snapshot = 
snapshotDao.findById(snapshotDataStoreVO.getSnapshotId());
             SnapshotObject info = SnapshotObject.getSnapshotObject(snapshot, 
store);
+
             infos.add(info);
         }
         return infos;
diff --git 
a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java
 
b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java
new file mode 100644
index 0000000..aad339b
--- /dev/null
+++ 
b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImplTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+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.SnapshotInfo;
+import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.utils.component.ComponentContext;
+
+@RunWith(PowerMockRunner.class)
+public class SnapshotDataFactoryImplTest {
+
+    @Spy
+    @InjectMocks
+    private SnapshotDataFactoryImpl snapshotDataFactoryImpl = new 
SnapshotDataFactoryImpl();
+
+    @Mock
+    private SnapshotDataStoreDao snapshotStoreDaoMock;
+    @Mock
+    private DataStoreManager dataStoreManagerMock;
+    @Mock
+    private SnapshotDao snapshotDaoMock;
+
+    private long volumeMockId = 1;
+
+    @Test
+    public void 
getSnapshotsByVolumeAndDataStoreTestNoSnapshotDataStoreVOFound() {
+        Mockito.doReturn(new 
ArrayList<>()).when(snapshotStoreDaoMock).listAllByVolumeAndDataStore(volumeMockId,
 DataStoreRole.Primary);
+
+        List<SnapshotInfo> snapshots = 
snapshotDataFactoryImpl.getSnapshots(volumeMockId, DataStoreRole.Primary);
+
+        Assert.assertTrue(snapshots.isEmpty());
+    }
+
+    @Test
+    @PrepareForTest({ComponentContext.class})
+    public void getSnapshotsByVolumeAndDataStoreTest() {
+        PowerMockito.mockStatic(ComponentContext.class);
+        
PowerMockito.when(ComponentContext.inject(SnapshotObject.class)).thenReturn(new 
SnapshotObject());
+
+        SnapshotDataStoreVO snapshotDataStoreVoMock = 
Mockito.mock(SnapshotDataStoreVO.class);
+        
Mockito.doReturn(volumeMockId).when(snapshotDataStoreVoMock).getVolumeId();
+
+        long snapshotId = 1223;
+        long dataStoreId = 34567;
+        
Mockito.doReturn(snapshotId).when(snapshotDataStoreVoMock).getSnapshotId();
+        
Mockito.doReturn(dataStoreId).when(snapshotDataStoreVoMock).getDataStoreId();
+
+        SnapshotVO snapshotVoMock  = Mockito.mock(SnapshotVO.class);
+        Mockito.doReturn(snapshotId).when(snapshotVoMock).getId();
+
+        DataStoreRole dataStoreRole = DataStoreRole.Primary;
+        DataStore dataStoreMock = Mockito.mock(DataStore.class);
+        Mockito.doReturn(dataStoreId).when(dataStoreMock).getId();
+        Mockito.doReturn(dataStoreRole).when(dataStoreMock).getRole();
+
+        List<SnapshotDataStoreVO> snapshotDataStoreVOs = new ArrayList<>();
+        snapshotDataStoreVOs.add(snapshotDataStoreVoMock);
+
+        
Mockito.doReturn(snapshotDataStoreVOs).when(snapshotStoreDaoMock).listAllByVolumeAndDataStore(volumeMockId,
 dataStoreRole);
+        
Mockito.doReturn(dataStoreMock).when(dataStoreManagerMock).getDataStore(dataStoreId,
 dataStoreRole);
+        
Mockito.doReturn(snapshotVoMock).when(snapshotDaoMock).findById(snapshotId);
+
+        List<SnapshotInfo> snapshots = 
snapshotDataFactoryImpl.getSnapshots(volumeMockId, dataStoreRole);
+
+        Assert.assertEquals(1, snapshots.size());
+
+        SnapshotInfo snapshotInfo = snapshots.get(0);
+        Assert.assertEquals(dataStoreMock, snapshotInfo.getDataStore());
+        Assert.assertEquals(snapshotVoMock, 
((SnapshotObject)snapshotInfo).getSnapshotVO());
+
+        PowerMockito.verifyStatic();
+        ComponentContext.inject(SnapshotObject.class);
+    }
+}
diff --git 
a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
 
b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
index c3e48b9..6ca6b23 100644
--- 
a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
+++ 
b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
@@ -16,14 +16,17 @@
 // under the License.
 package org.apache.cloudstack.storage.image.db;
 
-import com.cloud.storage.DataStoreRole;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
-import com.cloud.utils.db.SearchCriteria.Op;
-import com.cloud.utils.db.TransactionLegacy;
-import com.cloud.utils.db.UpdateBuilder;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
 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.Event;
@@ -33,19 +36,18 @@ import 
org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.dao.SnapshotDao;
-import javax.inject.Inject;
-import com.cloud.hypervisor.Hypervisor;
-import java.util.ArrayList;
+import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
-import javax.naming.ConfigurationException;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.UpdateBuilder;
 
 @Component
 public class SnapshotDataStoreDaoImpl extends 
GenericDaoBase<SnapshotDataStoreVO, Long> implements SnapshotDataStoreDao {
@@ -176,33 +178,33 @@ public class SnapshotDataStoreDaoImpl extends 
GenericDaoBase<SnapshotDataStoreVO
             if (dbVol != null) {
                 StringBuilder str = new StringBuilder("Unable to update 
").append(dataObj.toString());
                 str.append(": DB Data={id=")
-                    .append(dbVol.getId())
-                    .append("; state=")
-                    .append(dbVol.getState())
-                    .append("; updatecount=")
-                    .append(dbVol.getUpdatedCount())
-                    .append(";updatedTime=")
-                    .append(dbVol.getUpdated());
+                .append(dbVol.getId())
+                .append("; state=")
+                .append(dbVol.getState())
+                .append("; updatecount=")
+                .append(dbVol.getUpdatedCount())
+                .append(";updatedTime=")
+                .append(dbVol.getUpdated());
                 str.append(": New Data={id=")
-                    .append(dataObj.getId())
-                    .append("; state=")
-                    .append(nextState)
-                    .append("; event=")
-                    .append(event)
-                    .append("; updatecount=")
-                    .append(dataObj.getUpdatedCount())
-                    .append("; updatedTime=")
-                    .append(dataObj.getUpdated());
+                .append(dataObj.getId())
+                .append("; state=")
+                .append(nextState)
+                .append("; event=")
+                .append(event)
+                .append("; updatecount=")
+                .append(dataObj.getUpdatedCount())
+                .append("; updatedTime=")
+                .append(dataObj.getUpdated());
                 str.append(": stale Data={id=")
-                    .append(dataObj.getId())
-                    .append("; state=")
-                    .append(currentState)
-                    .append("; event=")
-                    .append(event)
-                    .append("; updatecount=")
-                    .append(oldUpdated)
-                    .append("; updatedTime=")
-                    .append(oldUpdatedTime);
+                .append(dataObj.getId())
+                .append("; state=")
+                .append(currentState)
+                .append("; event=")
+                .append(event)
+                .append("; updatecount=")
+                .append(oldUpdated)
+                .append("; updatedTime=")
+                .append(oldUpdatedTime);
             } else {
                 s_logger.debug("Unable to update objectIndatastore: id=" + 
dataObj.getId() + ", as there is no such object exists in the database 
anymore");
             }
@@ -254,7 +256,7 @@ public class SnapshotDataStoreDaoImpl extends 
GenericDaoBase<SnapshotDataStoreVO
         TransactionLegacy txn = TransactionLegacy.currentTxn();
         try (
                 PreparedStatement pstmt = 
txn.prepareStatement(findLatestSnapshot);
-            ){
+                ){
             pstmt.setString(1, role.toString());
             pstmt.setLong(2, volumeId);
             try (ResultSet rs = pstmt.executeQuery();) {
@@ -275,7 +277,7 @@ public class SnapshotDataStoreDaoImpl extends 
GenericDaoBase<SnapshotDataStoreVO
         TransactionLegacy txn = TransactionLegacy.currentTxn();
         try (
                 PreparedStatement pstmt = 
txn.prepareStatement(findOldestSnapshot);
-            ){
+                ){
             pstmt.setString(1, role.toString());
             pstmt.setLong(2, volumeId);
             try (ResultSet rs = pstmt.executeQuery();) {
@@ -319,6 +321,14 @@ public class SnapshotDataStoreDaoImpl extends 
GenericDaoBase<SnapshotDataStoreVO
     }
 
     @Override
+    public List<SnapshotDataStoreVO> listAllByVolumeAndDataStore(long 
volumeId, DataStoreRole role) {
+        SearchCriteria<SnapshotDataStoreVO> sc = volumeSearch.create();
+        sc.setParameters("volume_id", volumeId);
+        sc.setParameters("store_role", role);
+        return listBy(sc);
+    }
+
+    @Override
     public SnapshotDataStoreVO findByVolume(long volumeId, DataStoreRole role) 
{
         SearchCriteria<SnapshotDataStoreVO> sc = volumeSearch.create();
         sc.setParameters("volume_id", volumeId);

Reply via email to