You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by wi...@apache.org on 2015/01/02 15:35:59 UTC
[07/50] [abbrv] git commit: updated refs/heads/reporter to b26f3fc
CLOUDSTACK-8097: Failed to create volume snapshot after vm live migration across clusters.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/0c4128e0
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/0c4128e0
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/0c4128e0
Branch: refs/heads/reporter
Commit: 0c4128e024b519f24625ad8cd6b53ddf0137728e
Parents: 3090e4a
Author: Sanjay Tripathi <sa...@citrix.com>
Authored: Fri Dec 19 14:26:48 2014 +0530
Committer: Sanjay Tripathi <sa...@citrix.com>
Committed: Fri Dec 19 14:26:48 2014 +0530
----------------------------------------------------------------------
.../orchestration/VolumeOrchestrator.java | 16 +++++-
.../src/com/cloud/storage/dao/SnapshotDao.java | 2 +
.../com/cloud/storage/dao/SnapshotDaoImpl.java | 10 ++++
.../datastore/db/SnapshotDataStoreDao.java | 4 ++
.../snapshot/XenserverSnapshotStrategy.java | 57 +++++++++++++-------
.../image/db/SnapshotDataStoreDaoImpl.java | 47 +++++++++++++++-
6 files changed, 113 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0c4128e0/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
index 515d5ec..e04bd6d 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
@@ -58,6 +58,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
@@ -96,6 +97,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeDetailsDao;
import com.cloud.template.TemplateManager;
@@ -142,6 +144,10 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
@Inject
protected VolumeDao _volumeDao;
@Inject
+ protected SnapshotDao _snapshotDao;
+ @Inject
+ protected SnapshotDataStoreDao _snapshotDataStoreDao;
+ @Inject
protected ResourceLimitService _resourceLimitMgr;
@Inject
VolumeDetailsDao _volDetailDao;
@@ -919,8 +925,14 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
try {
VolumeApiResult result = future.get();
if (result.isFailed()) {
- s_logger.error("migrate volume failed:" + result.getResult());
- throw new StorageUnavailableException("migrate volume failed: " + result.getResult(), destPool.getId());
+ s_logger.error("Migrate volume failed:" + result.getResult());
+ throw new StorageUnavailableException("Migrate volume failed: " + result.getResult(), destPool.getId());
+ } else {
+ // update the volumeId for snapshots on secondary
+ if (!_snapshotDao.listByVolumeId(vol.getId()).isEmpty()) {
+ _snapshotDao.updateVolumeIds(vol.getId(), result.getVolume().getId());
+ _snapshotDataStoreDao.updateVolumeIds(vol.getId(), result.getVolume().getId());
+ }
}
return result.getVolume();
} catch (InterruptedException e) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0c4128e0/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java b/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java
index f55352b2..ff2e445 100644
--- a/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java
+++ b/engine/schema/src/com/cloud/storage/dao/SnapshotDao.java
@@ -57,4 +57,6 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long>, StateDao<Snap
List<SnapshotVO> listAllByStatus(Snapshot.State... status);
+ void updateVolumeIds(long oldVolId, long newVolId);
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0c4128e0/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index 204447c..84a92d7 100644
--- a/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/engine/schema/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -41,6 +41,7 @@ import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.UpdateBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@@ -326,4 +327,13 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
return true;
}
+ @Override
+ public void updateVolumeIds(long oldVolId, long newVolId) {
+ SearchCriteria<SnapshotVO> sc = VolumeIdSearch.create();
+ sc.setParameters("volumeId", oldVolId);
+ SnapshotVO snapshot = createForUpdate();
+ snapshot.setVolumeId(newVolId);
+ UpdateBuilder ub = getUpdateBuilder(snapshot);
+ update(ub, sc, null);
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0c4128e0/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
index e24c035..231b241 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
@@ -56,4 +56,8 @@ public interface SnapshotDataStoreDao extends GenericDao<SnapshotDataStoreVO, Lo
void updateStoreRoleToCache(long storeId);
SnapshotDataStoreVO findLatestSnapshotForVolume(Long volumeId, DataStoreRole role);
+
+ SnapshotDataStoreVO findOldestSnapshotForVolume(Long volumeId, DataStoreRole role);
+
+ void updateVolumeIds(long oldVolId, long newVolId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0c4128e0/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
index 90efcde..51f75bd 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
@@ -46,7 +46,9 @@ import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.DB;
@@ -68,6 +70,8 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
@Inject
SnapshotDao snapshotDao;
@Inject
+ VolumeDao volumeDao;
+ @Inject
SnapshotDataFactory snapshotDataFactory;
@Override
@@ -105,31 +109,44 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
// determine full snapshot backup or not
-
boolean fullBackup = true;
SnapshotDataStoreVO parentSnapshotOnBackupStore = snapshotStoreDao.findLatestSnapshotForVolume(snapshot.getVolumeId(), DataStoreRole.Image);
HypervisorType hypervisorType = snapshot.getBaseVolume().getHypervisorType();
if (parentSnapshotOnBackupStore != null && hypervisorType == Hypervisor.HypervisorType.XenServer) { // CS does incremental backup only for XenServer
- int _deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"),
- SnapshotManager.DELTAMAX);
- int deltaSnap = _deltaSnapshotMax;
- int i;
-
- for (i = 1; i < deltaSnap; i++) {
- Long prevBackupId = parentSnapshotOnBackupStore.getParentSnapshotId();
- if (prevBackupId == 0) {
- break;
- }
- parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image);
- if (parentSnapshotOnBackupStore == null) {
- break;
- }
- }
- if (i >= deltaSnap) {
- fullBackup = true;
- } else {
- fullBackup = false;
+ // In case of volume migration from one pool to other pool, CS should take full snapshot to avoid any issues with delta chain,
+ // to check if this is a migrated volume, compare the current pool id of volume and store_id of oldest snapshot on primary for this volume.
+ // Why oldest? Because at this point CS has two snapshot on primary entries for same volume, one with old pool_id and other one with
+ // current pool id. So, verify and if volume found to be migrated, delete snapshot entry with previous pool store_id.
+ SnapshotDataStoreVO oldestSnapshotOnPrimary = snapshotStoreDao.findOldestSnapshotForVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
+ VolumeVO volume = volumeDao.findById(snapshot.getVolumeId());
+ if (oldestSnapshotOnPrimary != null) {
+ if (oldestSnapshotOnPrimary.getDataStoreId() == volume.getPoolId()) {
+ int _deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"),
+ SnapshotManager.DELTAMAX);
+ int deltaSnap = _deltaSnapshotMax;
+ int i;
+
+ for (i = 1; i < deltaSnap; i++) {
+ Long prevBackupId = parentSnapshotOnBackupStore.getParentSnapshotId();
+ if (prevBackupId == 0) {
+ break;
+ }
+ parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image);
+ if (parentSnapshotOnBackupStore == null) {
+ break;
+ }
+ }
+
+ if (i >= deltaSnap) {
+ fullBackup = true;
+ } else {
+ fullBackup = false;
+ }
+ } else {
+ // if there is an snapshot entry for previousPool(primary storage) of migrated volume, delete it becasue CS created one more snapshot entry for current pool
+ snapshotStoreDao.remove(oldestSnapshotOnPrimary.getId());
+ }
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0c4128e0/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
index 28d6598..ea73ecd 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
@@ -54,6 +54,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
private SearchBuilder<SnapshotDataStoreVO> snapshotSearch;
private SearchBuilder<SnapshotDataStoreVO> storeSnapshotSearch;
private SearchBuilder<SnapshotDataStoreVO> snapshotIdSearch;
+ private SearchBuilder<SnapshotDataStoreVO> volumeIdSearch;
private final String parentSearch = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where store_id = ? "
+ " and store_role = ? and volume_id = ? and state = 'Ready'" + " order by created DESC " + " limit 1";
@@ -61,6 +62,10 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
" store_role = ? and volume_id = ? and state = 'Ready'" +
" order by created DESC " +
" limit 1";
+ private final String findOldestSnapshot = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where " +
+ " store_role = ? and volume_id = ? and state = 'Ready'" +
+ " order by created ASC " +
+ " limit 1";
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
@@ -110,6 +115,10 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
snapshotIdSearch.and("snapshot_id", snapshotIdSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
snapshotIdSearch.done();
+ volumeIdSearch = createSearchBuilder();
+ volumeIdSearch.and("volume_id", volumeIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
+ volumeIdSearch.done();
+
return true;
}
@@ -225,7 +234,34 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
return findByStoreSnapshot(role, sid, snid);
}
} catch (SQLException e) {
- s_logger.debug("Failed to find parent snapshot: " + e.toString());
+ s_logger.debug("Failed to find latest snapshot for volume: " + volumeId + " due to: " + e.toString());
+ } finally {
+ try {
+ if (pstmt != null)
+ pstmt.close();
+ } catch (SQLException e) {
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public SnapshotDataStoreVO findOldestSnapshotForVolume(Long volumeId, DataStoreRole role) {
+ TransactionLegacy txn = TransactionLegacy.currentTxn();
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ pstmt = txn.prepareStatement(findOldestSnapshot);
+ pstmt.setString(1, role.toString());
+ pstmt.setLong(2, volumeId);
+ rs = pstmt.executeQuery();
+ while (rs.next()) {
+ long sid = rs.getLong(1);
+ long snid = rs.getLong(3);
+ return findByStoreSnapshot(role, sid, snid);
+ }
+ } catch (SQLException e) {
+ s_logger.debug("Failed to find oldest snapshot for volume: " + volumeId + " due to: " + e.toString());
} finally {
try {
if (pstmt != null)
@@ -367,4 +403,13 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
}
}
+ @Override
+ public void updateVolumeIds(long oldVolId, long newVolId) {
+ SearchCriteria<SnapshotDataStoreVO> sc = volumeIdSearch.create();
+ sc.setParameters("volume_id", oldVolId);
+ SnapshotDataStoreVO snapshot = createForUpdate();
+ snapshot.setVolumeId(newVolId);
+ UpdateBuilder ub = getUpdateBuilder(snapshot);
+ update(ub, sc, null);
+ }
}