Updated Branches: refs/heads/4.2 5519492e3 -> a2ba2358d
CLOUDSTACK-2630: fix delta snashpt Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a2ba2358 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a2ba2358 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a2ba2358 Branch: refs/heads/4.2 Commit: a2ba2358d8562e0928c7cb7559d9cf4e42759fe6 Parents: 5519492 Author: Edison Su <[email protected]> Authored: Sat Jul 20 13:04:29 2013 -0700 Committer: Edison Su <[email protected]> Committed: Sat Jul 20 13:05:24 2013 -0700 ---------------------------------------------------------------------- client/pom.xml | 1 + .../datastore/db/SnapshotDataStoreDao.java | 1 + .../datastore/db/SnapshotDataStoreVO.java | 11 +++++ .../cloudstack/storage/to/SnapshotObjectTO.java | 5 +- .../storage/snapshot/SnapshotObject.java | 29 ++++++------ .../storage/snapshot/SnapshotServiceImpl.java | 4 ++ .../snapshot/XenserverSnapshotStrategy.java | 49 ++++++++++++++++---- .../datastore/ObjectInDataStoreManagerImpl.java | 11 +++++ .../image/db/SnapshotDataStoreDaoImpl.java | 36 +++++++++++++- .../CloudStackPrimaryDataStoreDriverImpl.java | 1 + setup/db/db/schema-410to420.sql | 1 + 11 files changed, 122 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/client/pom.xml ---------------------------------------------------------------------- diff --git a/client/pom.xml b/client/pom.xml index 32ab94a..d25576a 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -329,6 +329,7 @@ <artifactId>maven-jetty-plugin</artifactId> <version>6.1.26</version> <configuration> + <scanIntervalSeconds>0</scanIntervalSeconds> <stopPort>9966</stopPort> <stopKey>stop-jetty</stopKey> <connectors> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java index 01f0220..d129fe7 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java @@ -33,6 +33,7 @@ public interface SnapshotDataStoreDao extends GenericDao<SnapshotDataStoreVO, Lo void deletePrimaryRecordsForStore(long id); SnapshotDataStoreVO findByStoreSnapshot(DataStoreRole role, long storeId, long snapshotId); + SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId); SnapshotDataStoreVO findBySnapshot(long snapshotId, DataStoreRole role); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java index 929b2c8..300df1e 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java @@ -95,6 +95,9 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa @Column(name = "ref_cnt") Long refCnt = 0L; + @Column(name = "volume_id") + Long volumeId; + public String getInstallPath() { return installPath; } @@ -257,4 +260,12 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa public void decrRefCnt() { this.refCnt--; } + + public Long getVolumeId() { + return volumeId; + } + + public void setVolumeId(Long volumeId) { + this.volumeId = volumeId; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java index 1115aec..4754dcf 100644 --- a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java +++ b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java @@ -42,8 +42,9 @@ public class SnapshotObjectTO implements DataTO { this.setId(snapshot.getId()); this.volume = (VolumeObjectTO) snapshot.getBaseVolume().getTO(); this.setVmName(snapshot.getBaseVolume().getAttachedVmName()); - if (snapshot.getParent() != null) { - this.parentSnapshotPath = snapshot.getParent().getPath(); + SnapshotInfo parentSnapshot = snapshot.getParent(); + if (parentSnapshot != null) { + this.parentSnapshotPath = parentSnapshot.getPath(); } this.dataStore = snapshot.getDataStore().getTO(); this.setName(snapshot.getName()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java ---------------------------------------------------------------------- diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java index 1cba96e..2fc576b 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java @@ -22,12 +22,7 @@ import java.util.Date; import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; -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.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.*; import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; @@ -92,18 +87,18 @@ public class SnapshotObject implements SnapshotInfo { @Override public SnapshotInfo getParent() { + SnapshotDataStoreVO snapStoreVO = this.snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), this.store.getId(), this.snapshot.getId()); - if (snapStoreVO == null) { - return null; - } - - long parentId = snapStoreVO.getParentSnapshotId(); - if (parentId == 0) { - return null; + Long parentId = null; + if (snapStoreVO != null) { + parentId = snapStoreVO.getParentSnapshotId(); + if (parentId != null && parentId != 0) { + return this.snapshotFactory.getSnapshot(parentId, store); + } } - return this.snapshotFactory.getSnapshot(parentId, store); + return null; } @Override @@ -181,7 +176,11 @@ public class SnapshotObject implements SnapshotInfo { @Override public String getPath() { - return this.objectInStoreMgr.findObject(this, getDataStore()).getInstallPath(); + DataObjectInStore objectInStore = this.objectInStoreMgr.findObject(this, getDataStore()); + if (objectInStore != null) { + return objectInStore.getInstallPath(); + } + return null; } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java index 3d7d4f2..81036d0 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java @@ -199,6 +199,7 @@ public class SnapshotServiceImpl implements SnapshotService { s_logger.debug("Failed to take snapshot: " + snapshot.getId(), e); try { snapshot.processEvent(Snapshot.Event.OperationFailed); + snapshot.processEvent(Event.OperationFailed); } catch (NoTransitionException e1) { s_logger.debug("Failed to change state for event: OperationFailed", e); } @@ -237,6 +238,9 @@ public class SnapshotServiceImpl implements SnapshotService { // find the image store where the parent snapshot backup is located SnapshotDataStoreVO parentSnapshotOnBackupStore = _snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image); + if (parentSnapshotOnBackupStore == null) { + return dataStoreMgr.getImageStore(snapshot.getDataCenterId()); + } return dataStoreMgr.getDataStore(parentSnapshotOnBackupStore.getDataStoreId(), parentSnapshotOnBackupStore.getRole()); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/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 92af8c2..e30972d 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 @@ -18,13 +18,9 @@ package org.apache.cloudstack.storage.snapshot; import javax.inject.Inject; -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.*; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; -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.SnapshotService; import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; @@ -65,7 +61,8 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { @Override public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) { SnapshotInfo parentSnapshot = snapshot.getParent(); - if (parentSnapshot != null && parentSnapshot.getPath().equalsIgnoreCase(snapshot.getPath())) { + + if (parentSnapshot != null && snapshot.getPath().equalsIgnoreCase(parentSnapshot.getPath())) { s_logger.debug("backup an empty snapshot"); // don't need to backup this snapshot SnapshotDataStoreVO parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot( @@ -79,6 +76,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { SnapshotObjectTO snapTO = new SnapshotObjectTO(); snapTO.setPath(parentSnapshotOnBackupStore.getInstallPath()); + CreateObjectAnswer createSnapshotAnswer = new CreateObjectAnswer(snapTO); snapshotOnImageStore.processEvent(Event.OperationSuccessed, createSnapshotAnswer); @@ -109,7 +107,9 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { for (i = 1; i < deltaSnap; i++) { parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image); - + if (parentSnapshotOnBackupStore == null) { + break; + } Long prevBackupId = parentSnapshotOnBackupStore.getParentSnapshotId(); if (prevBackupId == 0) { @@ -193,8 +193,39 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { @Override public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) { - snapshot = snapshotSvr.takeSnapshot(snapshot).getSnashot(); - return this.backupSnapshot(snapshot); + SnapshotResult result = snapshotSvr.takeSnapshot(snapshot); + if (result.isFailed()) { + s_logger.debug("Failed to take snapshot: " + result.getResult()); + throw new CloudRuntimeException(result.getResult()); + } + snapshot = result.getSnashot(); + DataStore primaryStore = snapshot.getDataStore(); + + SnapshotInfo backupedSnapshot = this.backupSnapshot(snapshot); + try { + SnapshotInfo parent = snapshot.getParent(); + if (backupedSnapshot != null && parent != null) { + Long parentSnapshotId = parent.getId(); + while (parentSnapshotId != null && parentSnapshotId != 0L) { + SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(),primaryStore.getId(), parentSnapshotId); + if (snapshotDataStoreVO != null) { + parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId(); + snapshotStoreDao.remove(snapshotDataStoreVO.getId()); + } else { + parentSnapshotId = null; + } + } + SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), + snapshot.getId()); + if (snapshotDataStoreVO != null) { + snapshotDataStoreVO.setParentSnapshotId(0L); + snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO); + } + } + } catch (Exception e) { + s_logger.debug("Failed to clean up snapshots on primary storage", e); + } + return backupedSnapshot; } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java index 427609e..c673776 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java @@ -107,10 +107,16 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { VMTemplateStoragePoolVO vo = new VMTemplateStoragePoolVO(dataStore.getId(), obj.getId()); vo = templatePoolDao.persist(vo); } else if (obj.getType() == DataObjectType.SNAPSHOT) { + SnapshotInfo snapshotInfo = (SnapshotInfo)obj; SnapshotDataStoreVO ss = new SnapshotDataStoreVO(); ss.setSnapshotId(obj.getId()); ss.setDataStoreId(dataStore.getId()); ss.setRole(dataStore.getRole()); + ss.setVolumeId(snapshotInfo.getVolumeId()); + SnapshotDataStoreVO snapshotDataStoreVO = snapshotDataStoreDao.findParent(dataStore.getRole(), dataStore.getId(),snapshotInfo.getVolumeId()); + if (snapshotDataStoreVO != null) { + ss.setParentSnapshotId(snapshotDataStoreVO.getSnapshotId()); + } ss.setState(ObjectInDataStoreStateMachine.State.Allocated); ss = snapshotDataStoreDao.persist(ss); } @@ -148,6 +154,11 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { ss.setDataStoreId(dataStore.getId()); ss.setRole(dataStore.getRole()); ss.setRole(dataStore.getRole()); + ss.setVolumeId(snapshot.getVolumeId()); + SnapshotDataStoreVO snapshotDataStoreVO = snapshotDataStoreDao.findParent(dataStore.getRole(), dataStore.getId(),snapshot.getVolumeId()); + if (snapshotDataStoreVO != null) { + ss.setParentSnapshotId(snapshotDataStoreVO.getSnapshotId()); + } ss.setInstallPath(TemplateConstants.DEFAULT_SNAPSHOT_ROOT_DIR + "/" + snapshotDao.findById(obj.getId()).getAccountId() + "/" + snapshot.getVolumeId()); ss.setState(ObjectInDataStoreStateMachine.State.Allocated); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/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 a198004..f5e7421 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 @@ -16,6 +16,9 @@ // under the License. package org.apache.cloudstack.storage.image.db; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Date; import java.util.List; import java.util.Map; @@ -47,6 +50,12 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO private SearchBuilder<SnapshotDataStoreVO> destroyedSearch; private SearchBuilder<SnapshotDataStoreVO> snapshotSearch; private SearchBuilder<SnapshotDataStoreVO> storeSnapshotSearch; + private 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"; + + @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { @@ -146,7 +155,32 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO sc.setParameters("store_id", storeId); sc.setParameters("snapshot_id", snapshotId); sc.setParameters("store_role", role); - return findOneIncludingRemovedBy(sc); + return findOneBy(sc); + } + + @Override + public SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId) { + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + pstmt = txn.prepareStatement(parentSearch); + pstmt.setLong(1, storeId); + pstmt.setString(2, role.toString()); + pstmt.setLong(3, volumeId); + rs = pstmt.executeQuery(); + while (rs.next()) { + long sid = rs.getLong(1); + String rl = rs.getString(2); + long snid = rs.getLong(3); + return this.findByStoreSnapshot(role, sid, snid); + } + } catch (SQLException e) { + s_logger.debug("Failed to find parent snapshot: " + e.toString()); + } finally { + txn.close(); + } + return null; } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java ---------------------------------------------------------------------- diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index a233407..9ea91b5 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -155,6 +155,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri try { DataTO snapshotTO = snapshot.getTO(); + CreateObjectCommand cmd = new CreateObjectCommand(snapshotTO); EndPoint ep = this.epSelector.select(snapshot); Answer answer = ep.sendMessage(cmd); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a2ba2358/setup/db/db/schema-410to420.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index b4a3cd5..3668618 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -198,6 +198,7 @@ CREATE TABLE `cloud`.`snapshot_store_ref` ( `update_count` bigint unsigned, `ref_cnt` bigint unsigned, `updated` datetime, + `volume_id` bigint unsigned, PRIMARY KEY (`id`), INDEX `i_snapshot_store_ref__store_id`(`store_id`), CONSTRAINT `fk_snapshot_store_ref__snapshot_id` FOREIGN KEY `fk_snapshot_store_ref__snapshot_id` (`snapshot_id`) REFERENCES `snapshots` (`id`),
