You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by de...@apache.org on 2014/05/08 08:49:42 UTC

git commit: updated refs/heads/master to 245b7f4

Repository: cloudstack
Updated Branches:
  refs/heads/master b8adb96ae -> 245b7f4c3


CLOUDSTACK-6510: Fix gson serialization exception in storage migration. Gson couldn't serialize
a map with volume and storagepool objects for logging. Fixed by using volume and storage pool
ids instead of objects in the map.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/245b7f4c
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/245b7f4c
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/245b7f4c

Branch: refs/heads/master
Commit: 245b7f4c39ab8bdb656b733afc4cfc55782d36eb
Parents: b8adb96
Author: Devdeep Singh <de...@gmail.com>
Authored: Mon May 5 16:59:39 2014 +0530
Committer: Devdeep Singh <de...@gmail.com>
Committed: Thu May 8 12:23:46 2014 +0530

----------------------------------------------------------------------
 .../src/com/cloud/vm/VirtualMachineManager.java |  3 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 61 ++++++++++++--------
 .../com/cloud/vm/VmWorkMigrateWithStorage.java  |  9 +--
 .../cloud/vm/VirtualMachineManagerImplTest.java | 10 ++--
 server/src/com/cloud/vm/UserVmManagerImpl.java  |  4 +-
 5 files changed, 48 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/245b7f4c/engine/api/src/com/cloud/vm/VirtualMachineManager.java
----------------------------------------------------------------------
diff --git a/engine/api/src/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/com/cloud/vm/VirtualMachineManager.java
index f070210..b1e5258 100644
--- a/engine/api/src/com/cloud/vm/VirtualMachineManager.java
+++ b/engine/api/src/com/cloud/vm/VirtualMachineManager.java
@@ -39,7 +39,6 @@ import com.cloud.network.Network;
 import com.cloud.offering.DiskOfferingInfo;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.storage.StoragePool;
-import com.cloud.storage.Volume;
 import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.utils.component.Manager;
 import com.cloud.utils.fsm.NoTransitionException;
@@ -113,7 +112,7 @@ public interface VirtualMachineManager extends Manager {
 
     void migrate(String vmUuid, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException;
 
-    void migrateWithStorage(String vmUuid, long srcId, long destId, Map<Volume, StoragePool> volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException;
+    void migrateWithStorage(String vmUuid, long srcId, long destId, Map<Long, Long> volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException;
 
     void reboot(String vmUuid, Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/245b7f4c/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index e15d287..8ca7d1e 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -26,6 +26,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -1963,24 +1964,26 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-    private Map<Volume, StoragePool> getPoolListForVolumesForMigration(VirtualMachineProfile profile, Host host, Map<Volume, StoragePool> volumeToPool) {
+    private Map<Volume, StoragePool> getPoolListForVolumesForMigration(VirtualMachineProfile profile, Host host, Map<Long, Long> volumeToPool) {
         List<VolumeVO> allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId());
+        Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<Volume, StoragePool> ();
         for (VolumeVO volume : allVolumes) {
-            StoragePool pool = volumeToPool.get(volume);
-            DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
+            Long poolId = volumeToPool.get(Long.valueOf(volume.getId()));
+            StoragePoolVO pool = _storagePoolDao.findById(poolId);
             StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId());
+            DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
             if (pool != null) {
                 // Check if pool is accessible from the destination host and disk offering with which the volume was
                 // created is compliant with the pool type.
                 if (_poolHostDao.findByPoolHost(pool.getId(), host.getId()) == null || pool.isLocal() != diskOffering.getUseLocalStorage()) {
                     // Cannot find a pool for the volume. Throw an exception.
                     throw new CloudRuntimeException("Cannot migrate volume " + volume + " to storage pool " + pool + " while migrating vm to host " + host +
-                            ". Either the pool is not accessible from the " + "host or because of the offering with which the volume is created it cannot be placed on " +
+                            ". Either the pool is not accessible from the host or because of the offering with which the volume is created it cannot be placed on " +
                             "the given pool.");
                 } else if (pool.getId() == currentPool.getId()) {
-                    // If the pool to migrate too is the same as current pool, remove the volume from the list of
-                    // volumes to be migrated.
-                    volumeToPool.remove(volume);
+                    // If the pool to migrate too is the same as current pool, the volume doesn't need to be migrated.
+                } else {
+                    volumeToPoolObjectMap.put(volume, pool);
                 }
             } else {
                 // Find a suitable pool for the volume. Call the storage pool allocator to find the list of pools.
@@ -1989,23 +1992,33 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 ExcludeList avoid = new ExcludeList();
                 boolean currentPoolAvailable = false;
 
+                List<StoragePool> poolList = new ArrayList<StoragePool>();
                 for (StoragePoolAllocator allocator : _storagePoolAllocators) {
-                    List<StoragePool> poolList = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL);
-                    if (poolList != null && !poolList.isEmpty()) {
-                        // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the
-                        // volume to a pool only if it is required; that is the current pool on which the volume resides
-                        // is not available on the destination host.
-                        if (poolList.contains(currentPool)) {
+                    List<StoragePool> poolListFromAllocator = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL);
+                    if (poolListFromAllocator != null && !poolListFromAllocator.isEmpty()) {
+                        poolList.addAll(poolListFromAllocator);
+                    }
+                }
+
+                if (poolList != null && !poolList.isEmpty()) {
+                    // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the
+                    // volume to a pool only if it is required; that is the current pool on which the volume resides
+                    // is not available on the destination host.
+                    Iterator<StoragePool> iter = poolList.iterator();
+                    while (iter.hasNext()) {
+                        if (currentPool.getId() == iter.next().getId()) {
                             currentPoolAvailable = true;
-                        } else {
-                            volumeToPool.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid()));
+                            break;
                         }
+                    }
 
-                        break;
+                    if (!currentPoolAvailable) {
+                        volumeToPoolObjectMap.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid()));
                     }
                 }
 
-                if (!currentPoolAvailable && !volumeToPool.containsKey(volume)) {
+
+                if (!currentPoolAvailable && !volumeToPoolObjectMap.containsKey(volume)) {
                     // Cannot find a pool for the volume. Throw an exception.
                     throw new CloudRuntimeException("Cannot find a storage pool which is available for volume " + volume + " while migrating virtual machine " +
                             profile.getVirtualMachine() + " to host " + host);
@@ -2013,7 +2026,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             }
         }
 
-        return volumeToPool;
+        return volumeToPoolObjectMap;
     }
 
     private <T extends VMInstanceVO> void moveVmToMigratingState(T vm, Long hostId, ItWorkVO work) throws ConcurrentOperationException {
@@ -2043,7 +2056,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     @Override
-    public void migrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map<Volume, StoragePool> volumeToPool)
+    public void migrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map<Long, Long> volumeToPool)
             throws ResourceUnavailableException, ConcurrentOperationException {
 
         AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
@@ -2087,7 +2100,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-    private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map<Volume, StoragePool> volumeToPool) throws ResourceUnavailableException,
+    private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map<Long, Long> volumeToPool) throws ResourceUnavailableException,
     ConcurrentOperationException {
 
         VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
@@ -2103,11 +2116,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         // Create a map of which volume should go in which storage pool.
         VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
-        volumeToPool = getPoolListForVolumesForMigration(profile, destHost, volumeToPool);
+        Map<Volume, StoragePool> volumeToPoolMap = getPoolListForVolumesForMigration(profile, destHost, volumeToPool);
 
         // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating
         // a vm and not migrating a vm with storage.
-        if (volumeToPool.isEmpty()) {
+        if (volumeToPoolMap == null || volumeToPoolMap.isEmpty()) {
             throw new InvalidParameterValueException("Migration of the vm " + vm + "from host " + srcHost + " to destination host " + destHost +
                     " doesn't involve migrating the volumes.");
         }
@@ -2137,7 +2150,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         boolean migrated = false;
         try {
             // Migrate the vm and its volume.
-            volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool);
+            volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPoolMap);
 
             // Put the vm back to running state.
             moveVmOutofMigratingStateOnSuccess(vm, destHost.getId(), work);
@@ -4717,7 +4730,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     public Outcome<VirtualMachine> migrateVmWithStorageThroughJobQueue(
             final String vmUuid, final long srcHostId, final long destHostId,
-            final Map<Volume, StoragePool> volumeToPool) {
+            final Map<Long, Long> volumeToPool) {
 
         final CallContext context = CallContext.current();
         final User user = context.getCallingUser();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/245b7f4c/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java b/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java
index ee30c74..52fe9f2 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java
@@ -18,18 +18,15 @@ package com.cloud.vm;
 
 import java.util.Map;
 
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.Volume;
-
 public class VmWorkMigrateWithStorage extends VmWork {
     private static final long serialVersionUID = -5626053872453569165L;
 
     long srcHostId;
     long destHostId;
-    Map<Volume, StoragePool> volumeToPool;
+    Map<Long, Long> volumeToPool;
 
     public VmWorkMigrateWithStorage(long userId, long accountId, long vmId, String handlerName, long srcHostId,
-            long destHostId, Map<Volume, StoragePool> volumeToPool) {
+            long destHostId, Map<Long, Long> volumeToPool) {
 
         super(userId, accountId, vmId, handlerName);
 
@@ -46,7 +43,7 @@ public class VmWorkMigrateWithStorage extends VmWork {
         return destHostId;
     }
 
-    public Map<Volume, StoragePool> getVolumeToPool() {
+    public Map<Long, Long> getVolumeToPool() {
         return volumeToPool;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/245b7f4c/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java
index f6422f4..ae07455 100644
--- a/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java
+++ b/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java
@@ -89,9 +89,7 @@ import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.Storage.ProvisioningType;
 import com.cloud.storage.DiskOfferingVO;
-import com.cloud.storage.StoragePool;
 import com.cloud.storage.StoragePoolHostVO;
-import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.user.Account;
@@ -197,7 +195,7 @@ public class VirtualMachineManagerImplTest {
     @Mock
     HostVO _destHostMock;
     @Mock
-    Map<Volume, StoragePool> _volumeToPoolMock;
+    Map<Long, Long> _volumeToPoolMock;
     @Mock
     EntityManager _entityMgr;
     @Mock
@@ -356,11 +354,13 @@ public class VirtualMachineManagerImplTest {
         // Mock the disk offering and pool objects for a volume.
         when(_volumeMock.getDiskOfferingId()).thenReturn(5L);
         when(_volumeMock.getPoolId()).thenReturn(200L);
+        when(_volumeMock.getId()).thenReturn(5L);
         when(_diskOfferingDao.findById(anyLong())).thenReturn(_diskOfferingMock);
-        when(_storagePoolDao.findById(anyLong())).thenReturn(_srcStoragePoolMock);
+        when(_storagePoolDao.findById(200L)).thenReturn(_srcStoragePoolMock);
+        when(_storagePoolDao.findById(201L)).thenReturn(_destStoragePoolMock);
 
         // Mock the volume to pool mapping.
-        when(_volumeToPoolMock.get(_volumeMock)).thenReturn(_destStoragePoolMock);
+        when(_volumeToPoolMock.get(5L)).thenReturn(201L);
         when(_destStoragePoolMock.getId()).thenReturn(201L);
         when(_srcStoragePoolMock.getId()).thenReturn(200L);
         when(_destStoragePoolMock.isLocal()).thenReturn(false);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/245b7f4c/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 5da1875..d323e98 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -4092,7 +4092,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         }
 
         List<VolumeVO> vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId());
-        Map<Volume, StoragePool> volToPoolObjectMap = new HashMap<Volume, StoragePool>();
+        Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
         if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId().equals(srcHost.getClusterId())) {
             if (volumeToPool.isEmpty()) {
                 // If the destination host is in the same cluster and volumes do not have to be migrated across pools
@@ -4116,7 +4116,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                     if (!vmVolumes.contains(volume)) {
                         throw new InvalidParameterValueException("There volume " + volume + " doesn't belong to " + "the virtual machine " + vm + " that has to be migrated");
                     }
-                    volToPoolObjectMap.put(volume, pool);
+                    volToPoolObjectMap.put(Long.valueOf(volume.getId()), Long.valueOf(pool.getId()));
                 }
             }
         }