You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/10/29 05:21:53 UTC
[2/2] git commit: updated refs/heads/master to 6be228a
CLOUDSTACK-4024:Provide a way to upgrade from existing NFS secondary
storage to S3.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/6be228a4
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/6be228a4
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/6be228a4
Branch: refs/heads/master
Commit: 6be228a438e5ce3fba831be8130c73603cb0457b
Parents: 271a7df
Author: Min Chen <mi...@citrix.com>
Authored: Mon Oct 28 21:01:31 2013 -0700
Committer: Min Chen <mi...@citrix.com>
Committed: Mon Oct 28 21:01:31 2013 -0700
----------------------------------------------------------------------
api/src/com/cloud/event/EventTypes.java | 3 +
api/src/com/cloud/storage/StorageService.java | 16 +-
.../cloudstack/api/ApiCommandJobType.java | 1 +
.../PrepareSecondaryStorageForMigrationCmd.java | 109 ++++++++
client/tomcatconf/commands.properties.in | 1 +
.../api/storage/DataStoreLifeCycle.java | 2 +
.../subsystem/api/storage/DataStoreManager.java | 3 +
.../api/storage/SnapshotDataFactory.java | 4 +
.../api/storage/TemplateDataFactory.java | 6 +
.../subsystem/api/storage/TemplateService.java | 6 +-
.../api/storage/VolumeDataFactory.java | 4 +
.../storage/datastore/db/ImageStoreDao.java | 2 +
.../datastore/db/SnapshotDataStoreDao.java | 9 +
.../datastore/db/SnapshotDataStoreVO.java | 34 ++-
.../datastore/db/TemplateDataStoreDao.java | 10 +-
.../datastore/db/TemplateDataStoreVO.java | 51 ++--
.../datastore/db/VolumeDataStoreDao.java | 2 +
.../storage/datastore/db/VolumeDataStoreVO.java | 47 ++--
.../motion/AncientDataMotionStrategy.java | 37 ++-
.../storage/image/TemplateDataFactoryImpl.java | 38 ++-
.../storage/image/TemplateServiceImpl.java | 95 ++++++-
.../manager/ImageStoreProviderManagerImpl.java | 15 +-
.../storage/image/store/TemplateObject.java | 8 +
.../snapshot/SnapshotDataFactoryImpl.java | 22 +-
.../snapshot/XenserverSnapshotStrategy.java | 57 +++--
.../storage/datastore/DataStoreManagerImpl.java | 5 +
.../image/datastore/ImageStoreHelper.java | 21 +-
.../datastore/ImageStoreProviderManager.java | 2 +
.../storage/image/db/ImageStoreDaoImpl.java | 10 +-
.../image/db/SnapshotDataStoreDaoImpl.java | 82 +++++-
.../image/db/TemplateDataStoreDaoImpl.java | 104 ++++++++
.../image/db/VolumeDataStoreDaoImpl.java | 55 +++-
.../storage/volume/VolumeDataFactoryImpl.java | 33 ++-
.../SimulatorImageStoreLifeCycleImpl.java | 36 ++-
.../CloudStackImageStoreLifeCycleImpl.java | 9 +
.../lifecycle/S3ImageStoreLifeCycleImpl.java | 12 +-
.../SampleImageStoreLifeCycleImpl.java | 9 +
.../lifecycle/SwiftImageStoreLifeCycleImpl.java | 30 ++-
...CloudStackPrimaryDataStoreLifeCycleImpl.java | 17 +-
.../SamplePrimaryDataStoreLifeCycleImpl.java | 34 ++-
.../SolidFirePrimaryDataStoreLifeCycle.java | 254 ++++++++++---------
.../com/cloud/server/ManagementServerImpl.java | 71 +++---
.../com/cloud/storage/StorageManagerImpl.java | 74 ++++--
.../com/cloud/storage/VolumeApiServiceImpl.java | 125 ++++-----
.../template/HypervisorTemplateAdapter.java | 29 ++-
.../com/cloud/template/TemplateManagerImpl.java | 91 ++++---
tools/apidoc/gen_toc.py | 1 +
47 files changed, 1238 insertions(+), 448 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index c7e7a45..d9f80eb 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -449,6 +449,9 @@ public class EventTypes {
public static final String EVENT_UCS_ASSOCIATED_PROFILE = "UCS.ASSOCIATEPROFILE";
+ // Object store migration
+ public static final String EVENT_MIGRATE_PREPARE_SECONDARY_STORAGE = "MIGRATE.PREPARE.SS";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/api/src/com/cloud/storage/StorageService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/StorageService.java b/api/src/com/cloud/storage/StorageService.java
index 1ae1d3a..cbbc1f3 100644
--- a/api/src/com/cloud/storage/StorageService.java
+++ b/api/src/com/cloud/storage/StorageService.java
@@ -22,9 +22,9 @@ import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
-import org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
import com.cloud.exception.DiscoveryException;
@@ -97,4 +97,18 @@ public interface StorageService{
ImageStore discoverImageStore(AddImageStoreCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
+ /**
+ * Prepare NFS secondary storage for object store migration
+ *
+ * @param cmd
+ * - the command specifying secondaryStorageId
+ * @return the storage pool
+ * @throws ResourceUnavailableException
+ * TODO
+ * @throws InsufficientCapacityException
+ * TODO
+ */
+ public ImageStore prepareSecondaryStorageForObjectStoreMigration(Long storeId) throws ResourceUnavailableException,
+ InsufficientCapacityException;
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/api/src/org/apache/cloudstack/api/ApiCommandJobType.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiCommandJobType.java b/api/src/org/apache/cloudstack/api/ApiCommandJobType.java
index 204fe3e..3067af8 100644
--- a/api/src/org/apache/cloudstack/api/ApiCommandJobType.java
+++ b/api/src/org/apache/cloudstack/api/ApiCommandJobType.java
@@ -28,6 +28,7 @@ public enum ApiCommandJobType {
SystemVm,
Host,
StoragePool,
+ ImageStore,
IpAddress,
PortableIpAddress,
SecurityGroup,
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/api/src/org/apache/cloudstack/api/command/admin/storage/PrepareSecondaryStorageForMigrationCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/PrepareSecondaryStorageForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/PrepareSecondaryStorageForMigrationCmd.java
new file mode 100644
index 0000000..d0c995a
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/storage/PrepareSecondaryStorageForMigrationCmd.java
@@ -0,0 +1,109 @@
+// 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.api.command.admin.storage;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ImageStoreResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.storage.ImageStore;
+import com.cloud.user.Account;
+
+@APICommand(name = "prepareSecondaryStorageForMigration", description = "Prepare a NFS secondary storage to migrate to use object store like S3", responseObject = ImageStoreResponse.class)
+public class PrepareSecondaryStorageForMigrationCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(PrepareSecondaryStorageForMigrationCmd.class.getName());
+ private static final String s_name = "preparesecondarystorageformigrationresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class,
+ required = true, description = "Secondary image store ID")
+ private Long id;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.ImageStore;
+ }
+
+ @Override
+ public Long getInstanceId() {
+ return getId();
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ Account account = CallContext.current().getCallingAccount();
+ if (account != null) {
+ return account.getId();
+ }
+
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_MIGRATE_PREPARE_SECONDARY_STORAGE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "preparing secondary storage: " + getId() + " for object store migration";
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException{
+ ImageStore result = _storageService.prepareSecondaryStorageForObjectStoreMigration(getId());
+ if (result != null){
+ ImageStoreResponse response = _responseGenerator.createImageStoreResponse(result);
+ response.setResponseName(getCommandName());
+ response.setResponseName("secondarystorage");
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to prepare secondary storage for object store migration");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 3fe0463..1503ab8 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -256,6 +256,7 @@ deleteImageStore=1
createSecondaryStagingStore=1
listSecondaryStagingStores=1
deleteSecondaryStagingStore=1
+prepareSecondaryStorageForMigration=1
#### host commands
addHost=3
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
index 1e893db..c881570 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
@@ -37,4 +37,6 @@ public interface DataStoreLifeCycle {
boolean cancelMaintain(DataStore store);
boolean deleteDataStore(DataStore store);
+
+ boolean migrateToObjectStore(DataStore store);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java
index 0884453..7fbec0a 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreManager.java
@@ -19,6 +19,7 @@
package org.apache.cloudstack.engine.subsystem.api.storage;
import java.util.List;
+
import com.cloud.storage.DataStoreRole;
public interface DataStoreManager {
@@ -37,4 +38,6 @@ public interface DataStoreManager {
DataStore getImageCacheStore(long zoneId);
List<DataStore> listImageStores();
+
+ List<DataStore> listImageCacheStores();
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java
index 0b8d1f1..d5255f4 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotDataFactory.java
@@ -18,6 +18,8 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
+import java.util.List;
+
import com.cloud.storage.DataStoreRole;
public interface SnapshotDataFactory {
@@ -26,4 +28,6 @@ public interface SnapshotDataFactory {
SnapshotInfo getSnapshot(DataObject obj, DataStore store);
SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role);
+
+ List<SnapshotInfo> listSnapshotOnCache(long snapshotId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java
index 0b78da0..801c442 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java
@@ -18,6 +18,8 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
+import java.util.List;
+
import com.cloud.storage.DataStoreRole;
public interface TemplateDataFactory {
@@ -28,4 +30,8 @@ public interface TemplateDataFactory {
TemplateInfo getTemplate(long templateId, DataStoreRole storeRole);
TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long zoneId);
+
+ TemplateInfo getReadyTemplateOnCache(long templateId);
+
+ List<TemplateInfo> listTemplateOnCache(long templateId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
index 4950597..185d254 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
@@ -36,7 +36,7 @@ public interface TemplateService {
}
public TemplateInfo getTemplate() {
- return this.template;
+ return template;
}
}
@@ -54,6 +54,8 @@ public interface TemplateService {
AsyncCallFuture<TemplateApiResult> prepareTemplateOnPrimary(TemplateInfo srcTemplate, StoragePool pool);
+ void syncTemplateToRegionStore(long templateId, DataStore store);
+
void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId);
void handleTemplateSync(DataStore store);
@@ -62,5 +64,7 @@ public interface TemplateService {
void addSystemVMTemplatesToSecondary(DataStore store);
+ void associateTemplateToZone(long templateId, Long zoneId);
+
void associateCrosszoneTemplatesToZone(long dcId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java
index 99e3b59..3de0b5b 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeDataFactory.java
@@ -18,6 +18,8 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
+import java.util.List;
+
import com.cloud.storage.DataStoreRole;
public interface VolumeDataFactory {
@@ -28,4 +30,6 @@ public interface VolumeDataFactory {
VolumeInfo getVolume(long volumeId, DataStoreRole storeRole);
VolumeInfo getVolume(long volumeId);
+
+ List<VolumeInfo> listVolumeOnCache(long volumeId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java
index f95e66c..d0f8fe8 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java
@@ -36,4 +36,6 @@ public interface ImageStoreDao extends GenericDao<ImageStoreVO, Long> {
List<ImageStoreVO> findImageCacheByScope(ZoneScope scope);
List<ImageStoreVO> listImageStores();
+
+ List<ImageStoreVO> listImageCacheStores();
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/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 e350a76..dfa03ad 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
@@ -41,4 +41,13 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
List<SnapshotDataStoreVO> listDestroyed(long storeId);
List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId);
+
+ void duplicateCacheRecordsOnRegionStore(long storeId);
+
+ // delete the snapshot entry on primary data store to make sure that next snapshot will be full snapshot
+ void deleteSnapshotRecordsOnPrimary();
+
+ List<SnapshotDataStoreVO> listOnCache(long snapshotId);
+
+ void updateStoreRoleToCache(long storeId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java
index 0fe5e08..db86c3f 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreVO.java
@@ -34,7 +34,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
import com.cloud.storage.DataStoreRole;
-import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.fsm.StateObject;
@@ -98,6 +97,7 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Column(name = "volume_id")
Long volumeId;
+ @Override
public String getInstallPath() {
return installPath;
}
@@ -108,7 +108,7 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
}
public void setDataStoreId(long storeId) {
- this.dataStoreId = storeId;
+ dataStoreId = storeId;
}
public long getSnapshotId() {
@@ -135,15 +135,16 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
lastUpdated = date;
}
+ @Override
public void setInstallPath(String installPath) {
this.installPath = installPath;
}
public SnapshotDataStoreVO(long hostId, long snapshotId) {
super();
- this.dataStoreId = hostId;
+ dataStoreId = hostId;
this.snapshotId = snapshotId;
- this.state = ObjectInDataStoreStateMachine.State.Allocated;
+ state = ObjectInDataStoreStateMachine.State.Allocated;
}
public SnapshotDataStoreVO() {
@@ -158,14 +159,16 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
return jobId;
}
+ @Override
public boolean equals(Object obj) {
if (obj instanceof SnapshotDataStoreVO) {
SnapshotDataStoreVO other = (SnapshotDataStoreVO) obj;
- return (this.snapshotId == other.getSnapshotId() && this.dataStoreId == other.getDataStoreId());
+ return (snapshotId == other.getSnapshotId() && dataStoreId == other.getDataStoreId());
}
return false;
}
+ @Override
public int hashCode() {
Long tid = new Long(snapshotId);
Long hid = new Long(dataStoreId);
@@ -192,21 +195,22 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
return -1;
}
+ @Override
public String toString() {
return new StringBuilder("SnapshotDataStore[").append(id).append("-").append(snapshotId).append("-")
.append(dataStoreId).append(installPath).append("]").toString();
}
public long getUpdatedCount() {
- return this.updatedCount;
+ return updatedCount;
}
public void incrUpdatedCount() {
- this.updatedCount++;
+ updatedCount++;
}
public void decrUpdatedCount() {
- this.updatedCount--;
+ updatedCount--;
}
public Date getUpdated() {
@@ -216,7 +220,7 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Override
public ObjectInDataStoreStateMachine.State getState() {
// TODO Auto-generated method stub
- return this.state;
+ return state;
}
public void setState(ObjectInDataStoreStateMachine.State state) {
@@ -225,7 +229,7 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Override
public long getObjectId() {
- return this.getSnapshotId();
+ return getSnapshotId();
}
public DataStoreRole getRole() {
@@ -238,7 +242,7 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Override
public State getObjectInStoreState() {
- return this.state;
+ return state;
}
public long getParentSnapshotId() {
@@ -253,12 +257,16 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
return refCnt;
}
+ public void setRefCnt(Long refCnt) {
+ this.refCnt = refCnt;
+ }
+
public void incrRefCnt() {
- this.refCnt++;
+ refCnt++;
}
public void decrRefCnt() {
- this.refCnt--;
+ refCnt--;
}
public Long getVolumeId() {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
index 9350751..93adaaf 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
@@ -18,9 +18,9 @@ package org.apache.cloudstack.storage.datastore.db;
import java.util.List;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
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.State;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
@@ -62,4 +62,12 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, DataStoreRole role);
List<TemplateDataStoreVO> listByTemplate(long templateId);
+
+ void duplicateCacheRecordsOnRegionStore(long storeId);
+
+ TemplateDataStoreVO findReadyOnCache(long templateId);
+
+ List<TemplateDataStoreVO> listOnCache(long templateId);
+
+ void updateStoreRoleToCachce(long storeId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java
index a890e4b..a3696d8 100755
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java
@@ -35,7 +35,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
-
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.fsm.StateObject;
@@ -117,17 +116,17 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
public TemplateDataStoreVO(Long hostId, long templateId) {
super();
- this.dataStoreId = hostId;
+ dataStoreId = hostId;
this.templateId = templateId;
- this.state = ObjectInDataStoreStateMachine.State.Allocated;
- this.refCnt = 0L;
+ state = ObjectInDataStoreStateMachine.State.Allocated;
+ refCnt = 0L;
}
public TemplateDataStoreVO(Long hostId, long templateId, Date lastUpdated, int downloadPercent,
Status downloadState, String localDownloadPath, String errorString, String jobId, String installPath,
String downloadUrl) {
super();
- this.dataStoreId = hostId;
+ dataStoreId = hostId;
this.templateId = templateId;
this.lastUpdated = lastUpdated;
this.downloadPercent = downloadPercent;
@@ -135,33 +134,33 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
this.localDownloadPath = localDownloadPath;
this.errorString = errorString;
this.jobId = jobId;
- this.refCnt = 0L;
+ refCnt = 0L;
this.installPath = installPath;
- this.setDownloadUrl(downloadUrl);
+ setDownloadUrl(downloadUrl);
switch (downloadState) {
case DOWNLOADED:
- this.state = ObjectInDataStoreStateMachine.State.Ready;
+ state = ObjectInDataStoreStateMachine.State.Ready;
break;
case CREATING:
case DOWNLOAD_IN_PROGRESS:
case UPLOAD_IN_PROGRESS:
- this.state = ObjectInDataStoreStateMachine.State.Creating2;
+ state = ObjectInDataStoreStateMachine.State.Creating2;
break;
case DOWNLOAD_ERROR:
case UPLOAD_ERROR:
- this.state = ObjectInDataStoreStateMachine.State.Failed;
+ state = ObjectInDataStoreStateMachine.State.Failed;
break;
case ABANDONED:
- this.state = ObjectInDataStoreStateMachine.State.Destroyed;
+ state = ObjectInDataStoreStateMachine.State.Destroyed;
break;
default:
- this.state = ObjectInDataStoreStateMachine.State.Allocated;
+ state = ObjectInDataStoreStateMachine.State.Allocated;
break;
}
}
public TemplateDataStoreVO() {
- this.refCnt = 0L;
+ refCnt = 0L;
}
@Override
@@ -175,7 +174,7 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
}
public void setDataStoreId(long storeId) {
- this.dataStoreId = storeId;
+ dataStoreId = storeId;
}
public long getTemplateId() {
@@ -224,7 +223,7 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
}
public void setLocalDownloadPath(String localPath) {
- this.localDownloadPath = localPath;
+ localDownloadPath = localPath;
}
public String getLocalDownloadPath() {
@@ -251,7 +250,7 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
public boolean equals(Object obj) {
if (obj instanceof TemplateDataStoreVO) {
TemplateDataStoreVO other = (TemplateDataStoreVO) obj;
- return (this.templateId == other.getTemplateId() && this.dataStoreId == other.getDataStoreId());
+ return (templateId == other.getTemplateId() && dataStoreId == other.getDataStoreId());
}
return false;
}
@@ -316,7 +315,7 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Override
public ObjectInDataStoreStateMachine.State getState() {
// TODO Auto-generated method stub
- return this.state;
+ return state;
}
public void setState(ObjectInDataStoreStateMachine.State state) {
@@ -324,15 +323,15 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
}
public long getUpdatedCount() {
- return this.updatedCount;
+ return updatedCount;
}
public void incrUpdatedCount() {
- this.updatedCount++;
+ updatedCount++;
}
public void decrUpdatedCount() {
- this.updatedCount--;
+ updatedCount--;
}
public Date getUpdated() {
@@ -341,12 +340,12 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Override
public long getObjectId() {
- return this.getTemplateId();
+ return getTemplateId();
}
@Override
public State getObjectInStoreState() {
- return this.state;
+ return state;
}
public DataStoreRole getDataStoreRole() {
@@ -361,12 +360,16 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
return refCnt;
}
+ public void setRefCnt(Long refCnt) {
+ this.refCnt = refCnt;
+ }
+
public void incrRefCnt() {
- this.refCnt++;
+ refCnt++;
}
public void decrRefCnt() {
- this.refCnt--;
+ refCnt--;
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java
index 698465f..00a6d2a 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreDao.java
@@ -40,4 +40,6 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId, boolean lock);
List<VolumeDataStoreVO> listDestroyed(long storeId);
+
+ void duplicateCacheRecordsOnRegionStore(long storeId);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java
index e11071b..e34d4a6 100755
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java
@@ -33,8 +33,6 @@ 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.State;
-import com.cloud.storage.Storage;
-import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.fsm.StateObject;
@@ -117,6 +115,7 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
@Column(name = "ref_cnt")
Long refCnt = 0L;
+ @Override
public String getInstallPath() {
return installPath;
}
@@ -127,7 +126,7 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
}
public void setDataStoreId(long storeId) {
- this.dataStoreId = storeId;
+ dataStoreId = storeId;
}
public long getVolumeId() {
@@ -174,6 +173,7 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
lastUpdated = date;
}
+ @Override
public void setInstallPath(String installPath) {
this.installPath = installPath;
}
@@ -192,17 +192,17 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
public VolumeDataStoreVO(long hostId, long volumeId) {
super();
- this.dataStoreId = hostId;
+ dataStoreId = hostId;
this.volumeId = volumeId;
- this.state = ObjectInDataStoreStateMachine.State.Allocated;
- this.refCnt = 0L;
+ state = ObjectInDataStoreStateMachine.State.Allocated;
+ refCnt = 0L;
}
public VolumeDataStoreVO(long hostId, long volumeId, Date lastUpdated, int downloadPercent, Status downloadState,
String localDownloadPath, String errorString, String jobId, String installPath, String downloadUrl,
String checksum) {
// super();
- this.dataStoreId = hostId;
+ dataStoreId = hostId;
this.volumeId = volumeId;
// this.zoneId = zoneId;
this.lastUpdated = lastUpdated;
@@ -212,17 +212,17 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
this.errorString = errorString;
this.jobId = jobId;
this.installPath = installPath;
- this.setDownloadUrl(downloadUrl);
+ setDownloadUrl(downloadUrl);
this.checksum = checksum;
- this.refCnt = 0L;
+ refCnt = 0L;
}
public VolumeDataStoreVO() {
- this.refCnt = 0L;
+ refCnt = 0L;
}
public void setLocalDownloadPath(String localPath) {
- this.localDownloadPath = localPath;
+ localDownloadPath = localPath;
}
public String getLocalDownloadPath() {
@@ -245,14 +245,16 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
return jobId;
}
+ @Override
public boolean equals(Object obj) {
if (obj instanceof VolumeDataStoreVO) {
VolumeDataStoreVO other = (VolumeDataStoreVO) obj;
- return (this.volumeId == other.getVolumeId() && this.dataStoreId == other.getDataStoreId());
+ return (volumeId == other.getVolumeId() && dataStoreId == other.getDataStoreId());
}
return false;
}
+ @Override
public int hashCode() {
Long tid = new Long(volumeId);
Long hid = new Long(dataStoreId);
@@ -295,21 +297,22 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
return -1;
}
+ @Override
public String toString() {
return new StringBuilder("VolumeDataStore[").append(id).append("-").append(volumeId).append("-").append(dataStoreId)
.append(installPath).append("]").toString();
}
public long getUpdatedCount() {
- return this.updatedCount;
+ return updatedCount;
}
public void incrUpdatedCount() {
- this.updatedCount++;
+ updatedCount++;
}
public void decrUpdatedCount() {
- this.updatedCount--;
+ updatedCount--;
}
public Date getUpdated() {
@@ -319,7 +322,7 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
@Override
public ObjectInDataStoreStateMachine.State getState() {
// TODO Auto-generated method stub
- return this.state;
+ return state;
}
public void setState(ObjectInDataStoreStateMachine.State state) {
@@ -328,24 +331,28 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
@Override
public long getObjectId() {
- return this.getVolumeId();
+ return getVolumeId();
}
@Override
public State getObjectInStoreState() {
- return this.state;
+ return state;
}
public Long getRefCnt() {
return refCnt;
}
+ public void setRefCnt(Long refCnt) {
+ this.refCnt = refCnt;
+ }
+
public void incrRefCnt() {
- this.refCnt++;
+ refCnt++;
}
public void decrRefCnt() {
- this.refCnt--;
+ refCnt--;
}
public String getExtractUrl() {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index d70c7c0..a451ca4 100644
--- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -22,6 +22,9 @@ import java.util.Map;
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
@@ -48,9 +51,6 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
-import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.MigrateVolumeAnswer;
@@ -65,7 +65,6 @@ import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
import com.cloud.server.ManagementService;
import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VolumeVO;
@@ -112,8 +111,9 @@ AncientDataMotionStrategy implements DataMotionStrategy {
DataTO destTO = destData.getTO();
DataStoreTO srcStoreTO = srcTO.getDataStore();
DataStoreTO destStoreTO = destTO.getDataStore();
- if (srcStoreTO instanceof NfsTO || srcStoreTO.getRole() == DataStoreRole.ImageCache ||
- (srcStoreTO instanceof PrimaryDataStoreTO && ((PrimaryDataStoreTO)srcStoreTO).getPoolType() == StoragePoolType.NetworkFilesystem)) {
+ if (srcStoreTO instanceof NfsTO || srcStoreTO.getRole() == DataStoreRole.ImageCache) {
+ //||
+ // (srcStoreTO instanceof PrimaryDataStoreTO && ((PrimaryDataStoreTO)srcStoreTO).getPoolType() == StoragePoolType.NetworkFilesystem)) {
return false;
}
@@ -185,7 +185,8 @@ AncientDataMotionStrategy implements DataMotionStrategy {
cacheMgr.deleteCacheObject(srcForCopy);
} else {
// for template, we want to leave it on cache for performance reason
- if (answer == null || !answer.getResult()) {
+ if ((answer == null || !answer.getResult()) && srcForCopy.getRefCount() < 2) {
+ // cache object created by this copy, not already there
cacheMgr.deleteCacheObject(srcForCopy);
} else {
cacheMgr.releaseCacheObject(srcForCopy);
@@ -222,6 +223,13 @@ AncientDataMotionStrategy implements DataMotionStrategy {
}
}
+ protected void releaseSnapshotCacheChain(SnapshotInfo snapshot) {
+ while (snapshot != null) {
+ cacheMgr.releaseCacheObject(snapshot);
+ snapshot = snapshot.getParent();
+ }
+ }
+
protected Answer copyVolumeFromSnapshot(DataObject snapObj, DataObject volObj) {
SnapshotInfo snapshot = (SnapshotInfo) snapObj;
StoragePool pool = (StoragePool) volObj.getDataStore();
@@ -255,7 +263,8 @@ AncientDataMotionStrategy implements DataMotionStrategy {
throw new CloudRuntimeException(basicErrMsg);
} finally {
if (!(storTO instanceof NfsTO)) {
- deleteSnapshotCacheChain((SnapshotInfo) srcData);
+ // still keep snapshot on cache which may be migrated from previous secondary storage
+ releaseSnapshotCacheChain((SnapshotInfo)srcData);
}
}
}
@@ -281,7 +290,7 @@ AncientDataMotionStrategy implements DataMotionStrategy {
if (cacheStore == null) {
// need to find a nfs or cifs image store, assuming that can't copy volume
// directly to s3
- ImageStoreEntity imageStore = (ImageStoreEntity) this.dataStoreMgr.getImageStore(destScope.getScopeId());
+ ImageStoreEntity imageStore = (ImageStoreEntity) dataStoreMgr.getImageStore(destScope.getScopeId());
if (!imageStore.getProtocol().equalsIgnoreCase("nfs") && !imageStore.getProtocol().equalsIgnoreCase("cifs")) {
s_logger.debug("can't find a nfs (or cifs) image store to satisfy the need for a staging store");
return null;
@@ -290,7 +299,7 @@ AncientDataMotionStrategy implements DataMotionStrategy {
DataObject objOnImageStore = imageStore.create(srcData);
objOnImageStore.processEvent(Event.CreateOnlyRequested);
- Answer answer = this.copyObject(srcData, objOnImageStore);
+ Answer answer = copyObject(srcData, objOnImageStore);
if (answer == null || !answer.getResult()) {
if (answer != null) {
s_logger.debug("copy to image store failed: " + answer.getDetails());
@@ -336,7 +345,7 @@ AncientDataMotionStrategy implements DataMotionStrategy {
protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) {
VolumeInfo volume = (VolumeInfo)srcData;
- StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary);
+ StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary);
MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool);
EndPoint ep = selector.select(volume.getDataStore());
MigrateVolumeAnswer answer = (MigrateVolumeAnswer) ep.sendMessage(command);
@@ -345,14 +354,14 @@ AncientDataMotionStrategy implements DataMotionStrategy {
throw new CloudRuntimeException("Failed to migrate volume " + volume + " to storage pool " + destPool);
} else {
// Update the volume details after migration.
- VolumeVO volumeVo = this.volDao.findById(volume.getId());
+ VolumeVO volumeVo = volDao.findById(volume.getId());
Long oldPoolId = volume.getPoolId();
volumeVo.setPath(answer.getVolumePath());
volumeVo.setFolder(destPool.getPath());
volumeVo.setPodId(destPool.getPodId());
volumeVo.setPoolId(destPool.getId());
volumeVo.setLastPoolId(oldPoolId);
- this.volDao.update(volume.getId(), volumeVo);
+ volDao.update(volume.getId(), volumeVo);
}
return answer;
@@ -426,7 +435,7 @@ AncientDataMotionStrategy implements DataMotionStrategy {
// clean up snapshot copied to staging
if (needCache && srcData != null) {
- cacheMgr.deleteCacheObject(srcData);
+ cacheMgr.releaseCacheObject(srcData); // reduce ref count, but keep it there on cache which is converted from previous secondary storage
}
return answer;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
index a67f08f..6369311 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
@@ -18,8 +18,14 @@
*/
package org.apache.cloudstack.storage.image;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -28,8 +34,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.image.store.TemplateObject;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.VMTemplateStoragePoolVO;
@@ -87,7 +91,7 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplate(templateId, storeRole);
DataStore store = null;
if (tmplStore != null) {
- store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), storeRole);
+ store = storeMgr.getDataStore(tmplStore.getDataStoreId(), storeRole);
}
return this.getTemplate(templateId, store);
}
@@ -97,7 +101,7 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZone(templateId, zoneId, storeRole);
DataStore store = null;
if (tmplStore != null) {
- store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), storeRole);
+ store = storeMgr.getDataStore(tmplStore.getDataStoreId(), storeRole);
}
return this.getTemplate(templateId, store);
}
@@ -113,4 +117,30 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
tmpObj.setUrl(origTmpl.getUrl());
return tmpObj;
}
+
+ @Override
+ public TemplateInfo getReadyTemplateOnCache(long templateId) {
+ TemplateDataStoreVO tmplStore = templateStoreDao.findReadyOnCache(templateId);
+ if (tmplStore != null) {
+ DataStore store = storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.ImageCache);
+ return getTemplate(templateId, store);
+ } else {
+ return null;
+ }
+
+ }
+
+ @Override
+ public List<TemplateInfo> listTemplateOnCache(long templateId) {
+ List<TemplateDataStoreVO> cacheTmpls = templateStoreDao.listOnCache(templateId);
+ List<TemplateInfo> tmplObjs = new ArrayList<TemplateInfo>();
+ for (TemplateDataStoreVO cacheTmpl : cacheTmpls) {
+ long storeId = cacheTmpl.getDataStoreId();
+ DataStore store = storeMgr.getDataStore(storeId, DataStoreRole.ImageCache);
+ TemplateInfo tmplObj = getTemplate(templateId, store);
+ tmplObjs.add(tmplObj);
+ }
+ return tmplObjs;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
index a68e40c..ce6198d 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
@@ -28,6 +28,9 @@ import java.util.Set;
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
@@ -39,6 +42,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
@@ -59,9 +63,6 @@ import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
import org.apache.cloudstack.storage.image.store.TemplateObject;
import org.apache.cloudstack.storage.to.TemplateObjectTO;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
@@ -73,8 +74,9 @@ import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.StoragePool;
+import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.StoragePool;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
@@ -128,6 +130,8 @@ public class TemplateServiceImpl implements TemplateService {
TemplateManager _tmpltMgr;
@Inject
ConfigurationDao _configDao;
+ @Inject
+ StorageCacheManager _cacheMgr;
class TemplateOpContext<T> extends AsyncRpcContext<T> {
final TemplateObject template;
@@ -466,7 +470,8 @@ public class TemplateServiceImpl implements TemplateService {
// persist entry in template_zone_ref table. zoneId can be empty for
// region-wide image store, in that case,
// we will associate the template to all the zones.
- private void associateTemplateToZone(long templateId, Long zoneId) {
+ @Override
+ public void associateTemplateToZone(long templateId, Long zoneId) {
List<Long> dcs = new ArrayList<Long>();
if (zoneId != null) {
dcs.add(zoneId);
@@ -608,6 +613,86 @@ public class TemplateServiceImpl implements TemplateService {
return copyAsync(volume, template, store);
}
+ private AsyncCallFuture<TemplateApiResult> syncToRegionStoreAsync(TemplateInfo template, DataStore store) {
+ AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>();
+ // no need to create entry on template_store_ref here, since entries are already created when prepareSecondaryStorageForMigration is invoked.
+ // But we need to set default install path so that sync can be done in the right s3 path
+ TemplateInfo templateOnStore = _templateFactory.getTemplate(template, store);
+ String installPath = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR + "/"
+ + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR
+ + template.getAccountId() + "/" + template.getId() + "/" + template.getUniqueName();
+ ((TemplateObject)templateOnStore).setInstallPath(installPath);
+ TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null,
+ (TemplateObject)templateOnStore, future);
+ AsyncCallbackDispatcher<TemplateServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
+ caller.setCallback(caller.getTarget().syncTemplateCallBack(null, null)).setContext(context);
+ _motionSrv.copyAsync(template, templateOnStore, caller);
+ return future;
+ }
+
+ protected Void syncTemplateCallBack(AsyncCallbackDispatcher<TemplateServiceImpl, CopyCommandResult> callback,
+ TemplateOpContext<TemplateApiResult> context) {
+ TemplateInfo destTemplate = context.getTemplate();
+ CopyCommandResult result = callback.getResult();
+ AsyncCallFuture<TemplateApiResult> future = context.getFuture();
+ TemplateApiResult res = new TemplateApiResult(destTemplate);
+ try {
+ if (result.isFailed()) {
+ res.setResult(result.getResult());
+ // no change to existing template_store_ref, will try to re-sync later if other call triggers this sync operation, like copy template
+ } else {
+ // this will update install path properly, next time it will not sync anymore.
+ destTemplate.processEvent(Event.OperationSuccessed, result.getAnswer());
+ }
+ future.complete(res);
+ } catch (Exception e) {
+ s_logger.debug("Failed to process sync template callback", e);
+ res.setResult(e.toString());
+ future.complete(res);
+ }
+
+ return null;
+ }
+
+ private boolean isRegionStore(DataStore store) {
+ if (store.getScope().getScopeType() == ScopeType.ZONE && store.getScope().getScopeId() == null)
+ return true;
+ else
+ return false;
+ }
+
+ // This routine is used to push templates currently on cache store, but not in region store to region store.
+ // used in migrating existing NFS secondary storage to S3.
+ @Override
+ public void syncTemplateToRegionStore(long templateId, DataStore store) {
+ if (isRegionStore(store)) {
+ // if template is on region wide object store, check if it is really downloaded there (by checking install_path). Sync template to region
+ // wide store if it is not there physically.
+ TemplateInfo tmplOnStore = _templateFactory.getTemplate(templateId, store);
+ if (tmplOnStore == null) {
+ throw new CloudRuntimeException("Cannot find an entry in template_store_ref for template " + templateId + " on region store: " + store.getName());
+ }
+ if (tmplOnStore.getInstallPath() == null || tmplOnStore.getInstallPath().length() == 0) {
+ // template is not on region store yet, sync to region store
+ TemplateInfo srcTemplate = _templateFactory.getReadyTemplateOnCache(templateId);
+ if (srcTemplate == null) {
+ throw new CloudRuntimeException("Cannot find template " + templateId + " on cache store");
+ }
+ AsyncCallFuture<TemplateApiResult> future = syncToRegionStoreAsync(srcTemplate, store);
+ try {
+ TemplateApiResult result = future.get();
+ if (result.isFailed()) {
+ throw new CloudRuntimeException("sync template from cache to region wide store failed for image store " + store.getName() + ":"
+ + result.getResult());
+ }
+ _cacheMgr.releaseCacheObject(srcTemplate); // reduce reference count for template on cache, so it can recycled by schedule
+ } catch (Exception ex) {
+ throw new CloudRuntimeException("sync template from cache to region wide store failed for image store " + store.getName());
+ }
+ }
+ }
+ }
+
@Override
public AsyncCallFuture<TemplateApiResult> copyTemplate(TemplateInfo srcTemplate, DataStore destStore) {
// generate a URL from source template ssvm to download to destination data store
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java
index 64ef78f..0991860 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java
@@ -26,6 +26,9 @@ import java.util.Map;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider;
@@ -37,8 +40,6 @@ import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import org.apache.cloudstack.storage.image.store.ImageStoreImpl;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import com.cloud.storage.ScopeType;
import com.cloud.storage.dao.VMTemplateDao;
@@ -95,6 +96,16 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager
}
@Override
+ public List<DataStore> listImageCacheStores() {
+ List<ImageStoreVO> stores = dataStoreDao.listImageCacheStores();
+ List<DataStore> imageStores = new ArrayList<DataStore>();
+ for (ImageStoreVO store : stores) {
+ imageStores.add(getImageStore(store.getId()));
+ }
+ return imageStores;
+ }
+
+ @Override
public List<DataStore> listImageStoresByScope(ZoneScope scope) {
List<ImageStoreVO> stores = dataStoreDao.findByScope(scope);
List<DataStore> imageStores = new ArrayList<DataStore>();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
index f0675f3..0a5b608 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
@@ -58,6 +58,7 @@ public class TemplateObject implements TemplateInfo {
private VMTemplateVO imageVO;
private DataStore dataStore;
private String url;
+ private String installPath; // temporarily set installPath before passing to resource for entries with empty installPath for object store migration case
@Inject
VMTemplateDao imageDao;
@Inject
@@ -293,6 +294,9 @@ public class TemplateObject implements TemplateInfo {
@Override
public String getInstallPath() {
+ if (installPath != null)
+ return installPath;
+
if (dataStore == null) {
return null;
}
@@ -300,6 +304,10 @@ public class TemplateObject implements TemplateInfo {
return obj.getInstallPath();
}
+ public void setInstallPath(String installPath) {
+ this.installPath = installPath;
+ }
+
@Override
public long getAccountId() {
return imageVO.getAccountId();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
index aafdad0..6205fe4 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
@@ -18,8 +18,13 @@
*/
package org.apache.cloudstack.storage.snapshot;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.inject.Inject;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -28,7 +33,6 @@ 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.springframework.stereotype.Component;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.SnapshotVO;
@@ -70,8 +74,22 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
if (snapshotStore == null) {
return null;
}
- DataStore store = this.storeMgr.getDataStore(snapshotStore.getDataStoreId(), role);
+ DataStore store = storeMgr.getDataStore(snapshotStore.getDataStoreId(), role);
SnapshotObject so = SnapshotObject.getSnapshotObject(snapshot, store);
return so;
}
+
+ @Override
+ public List<SnapshotInfo> listSnapshotOnCache(long snapshotId) {
+ List<SnapshotDataStoreVO> cacheSnapshots = snapshotStoreDao.listOnCache(snapshotId);
+ List<SnapshotInfo> snapObjs = new ArrayList<SnapshotInfo>();
+ for (SnapshotDataStoreVO cacheSnap : cacheSnapshots) {
+ long storeId = cacheSnap.getDataStoreId();
+ DataStore store = storeMgr.getDataStore(storeId, DataStoreRole.ImageCache);
+ SnapshotInfo tmplObj = getSnapshot(snapshotId, store);
+ snapObjs.add(tmplObj);
+ }
+ return snapObjs;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/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 15335bf..7eec5ff 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
@@ -16,17 +16,14 @@
// under the License.
package org.apache.cloudstack.storage.snapshot;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.Volume;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.snapshot.SnapshotManager;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.fsm.NoTransitionException;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
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.ObjectInDataStoreStateMachine.Event;
@@ -42,10 +39,18 @@ import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-import javax.inject.Inject;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.Volume;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
@Component
public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
@@ -71,7 +76,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
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(
+ SnapshotDataStoreVO parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(
parentSnapshot.getId(), DataStoreRole.Image);
if (parentSnapshotOnBackupStore != null && parentSnapshotOnBackupStore.getState() == State.Ready) {
DataStore store = dataStoreMgr.getDataStore(parentSnapshotOnBackupStore.getDataStoreId(),
@@ -93,7 +98,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
s_logger.debug("Failed to change state: " + snapshot.getId() + ": " + e.toString());
throw new CloudRuntimeException(e.toString());
}
- return this.snapshotDataFactory.getSnapshot(snapObj.getId(), store);
+ return snapshotDataFactory.getSnapshot(snapObj.getId(), store);
} else {
s_logger.debug("parent snapshot hasn't been backed up yet");
}
@@ -111,7 +116,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
int i;
SnapshotDataStoreVO parentSnapshotOnBackupStore = null;
for (i = 1; i < deltaSnap; i++) {
- parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(parentSnapshot.getId(),
+ parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(parentSnapshot.getId(),
DataStoreRole.Image);
if (parentSnapshotOnBackupStore == null) {
break;
@@ -122,7 +127,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
break;
}
- parentSnapshotOnBackupStore = this.snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image);
+ parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image);
}
if (i >= deltaSnap) {
fullBackup = true;
@@ -130,7 +135,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
}
snapshot.addPayload(fullBackup);
- return this.snapshotSvr.backupSnapshot(snapshot);
+ return snapshotSvr.backupSnapshot(snapshot);
}
protected boolean deleteSnapshotChain(SnapshotInfo snapshot) {
@@ -164,7 +169,15 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
}
}
if (!deleted) {
- boolean r = this.snapshotSvr.deleteSnapshot(snapshot);
+ boolean r = snapshotSvr.deleteSnapshot(snapshot);
+ if (r) {
+ // delete snapshot in cache if there is
+ List<SnapshotInfo> cacheSnaps = snapshotDataFactory.listSnapshotOnCache(snapshot.getId());
+ for (SnapshotInfo cacheSnap : cacheSnaps) {
+ s_logger.debug("Delete snapshot " + snapshot.getId() + " from image cache store: " + cacheSnap.getDataStore().getName());
+ cacheSnap.delete();
+ }
+ }
if (!resultIsSet) {
result = r;
resultIsSet = true;
@@ -200,7 +213,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
// first mark the snapshot as destroyed, so that ui can't see it, but we
// may not destroy the snapshot on the storage, as other snapshots may
// depend on it.
- SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image);
+ SnapshotInfo snapshotOnImage = snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image);
if (snapshotOnImage == null) {
s_logger.debug("Can't find snapshot on backup storage, delete it in db");
snapshotDao.remove(snapshotId);
@@ -273,7 +286,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
snapshot = result.getSnashot();
DataStore primaryStore = snapshot.getDataStore();
- SnapshotInfo backupedSnapshot = this.backupSnapshot(snapshot);
+ SnapshotInfo backupedSnapshot = backupSnapshot(snapshot);
try {
SnapshotInfo parent = snapshot.getParent();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java
index a9263a9..88061aa 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataStoreManagerImpl.java
@@ -107,6 +107,11 @@ public class DataStoreManagerImpl implements DataStoreManager {
return imageDataStoreMgr.listImageStores();
}
+ @Override
+ public List<DataStore> listImageCacheStores() {
+ return imageDataStoreMgr.listImageCacheStores();
+ }
+
public void setPrimaryStoreMgr(PrimaryDataStoreProviderManager primaryStoreMgr) {
this.primaryStoreMgr = primaryStoreMgr;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java
index a641146..e2c48ea 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java
@@ -24,11 +24,14 @@ import java.util.UUID;
import javax.inject.Inject;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
-import org.springframework.stereotype.Component;
+import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
@@ -40,6 +43,8 @@ public class ImageStoreHelper {
ImageStoreDao imageStoreDao;
@Inject
ImageStoreDetailsDao imageStoreDetailsDao;
+ @Inject
+ SnapshotDataStoreDao snapshotStoreDao;
public ImageStoreVO createImageStore(Map<String, Object> params) {
ImageStoreVO store = imageStoreDao.findByName((String) params.get("name"));
@@ -115,4 +120,18 @@ public class ImageStoreHelper {
imageStoreDao.remove(id);
return true;
}
+
+ /**
+ * Convert current NFS secondary storage to Staging store to be ready to migrate to S3 object store.
+ * @param store NFS image store.
+ * @return true if successful.
+ */
+ public boolean convertToStagingStore(DataStore store) {
+ ImageStoreVO nfsStore = imageStoreDao.findById(store.getId());
+ nfsStore.setRole(DataStoreRole.ImageCache);
+ imageStoreDao.update(store.getId(), nfsStore);
+ // clear snapshot entry on primary store to make next snapshot become full snapshot
+ snapshotStoreDao.deleteSnapshotRecordsOnPrimary();
+ return true;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java
index be66cc5..8afb3d9 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreProviderManager.java
@@ -32,6 +32,8 @@ public interface ImageStoreProviderManager {
List<DataStore> listImageStores();
+ List<DataStore> listImageCacheStores();
+
List<DataStore> listImageStoresByScope(ZoneScope scope);
List<DataStore> listImageStoreByProvider(String provider);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java
index b9ef9c3..13a7f47 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java
@@ -23,10 +23,11 @@ import java.util.Map;
import javax.naming.ConfigurationException;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
-import org.springframework.stereotype.Component;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
@@ -118,4 +119,11 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
return listBy(sc);
}
+ @Override
+ public List<ImageStoreVO> listImageCacheStores() {
+ SearchCriteria<ImageStoreVO> sc = createSearchCriteria();
+ sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache);
+ return listBy(sc);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6be228a4/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 48416a2..ee00dd5 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
@@ -25,23 +25,23 @@ import java.util.Map;
import javax.naming.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
-import com.cloud.utils.db.DB;
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;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
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.TransactionLegacy;
import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.db.UpdateBuilder;
@Component
@@ -54,7 +54,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
private SearchBuilder<SnapshotDataStoreVO> snapshotSearch;
private SearchBuilder<SnapshotDataStoreVO> storeSnapshotSearch;
private SearchBuilder<SnapshotDataStoreVO> snapshotIdSearch;
- private String parentSearch = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where store_id = ? " +
+ 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";
@@ -171,6 +171,16 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
}
@Override
+ public void deleteSnapshotRecordsOnPrimary() {
+ SearchCriteria<SnapshotDataStoreVO> sc = storeSearch.create();
+ sc.setParameters("store_role", DataStoreRole.Primary);
+ TransactionLegacy txn = TransactionLegacy.currentTxn();
+ txn.start();
+ remove(sc);
+ txn.commit();
+ }
+
+ @Override
public SnapshotDataStoreVO findByStoreSnapshot(DataStoreRole role, long storeId, long snapshotId) {
SearchCriteria<SnapshotDataStoreVO> sc = storeSnapshotSearch.create();
sc.setParameters("store_id", storeId);
@@ -195,7 +205,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
long sid = rs.getLong(1);
String rl = rs.getString(2);
long snid = rs.getLong(3);
- return this.findByStoreSnapshot(role, sid, snid);
+ return findByStoreSnapshot(role, sid, snid);
}
} catch (SQLException e) {
s_logger.debug("Failed to find parent snapshot: " + e.toString());
@@ -236,4 +246,64 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
sc.setParameters("ref_cnt", 0);
return listBy(sc);
}
+
+ @Override
+ public void duplicateCacheRecordsOnRegionStore(long storeId) {
+ // find all records on image cache
+ SearchCriteria<SnapshotDataStoreVO> sc = storeSnapshotSearch.create();
+ sc.setParameters("store_role", DataStoreRole.ImageCache);
+ sc.setParameters("destroyed", false);
+ List<SnapshotDataStoreVO> snapshots = listBy(sc);
+ // create an entry for each record, but with empty install path since the content is not yet on region-wide store yet
+ if (snapshots != null) {
+ s_logger.info("Duplicate " + snapshots.size() + " snapshot cache store records to region store");
+ for (SnapshotDataStoreVO snap : snapshots) {
+ SnapshotDataStoreVO snapStore = findByStoreSnapshot(DataStoreRole.Image, storeId, snap.getSnapshotId());
+ if (snapStore != null) {
+ s_logger.info("There is already entry for snapshot " + snap.getSnapshotId() + " on region store " + storeId);
+ continue;
+ }
+ s_logger.info("Persisting an entry for snapshot " + snap.getSnapshotId() + " on region store " + storeId);
+ SnapshotDataStoreVO ss = new SnapshotDataStoreVO();
+ ss.setSnapshotId(snap.getSnapshotId());
+ ss.setDataStoreId(storeId);
+ ss.setRole(DataStoreRole.Image);
+ ss.setVolumeId(snap.getVolumeId());
+ ss.setParentSnapshotId(snap.getParentSnapshotId());
+ ss.setState(snap.getState());
+ ss.setSize(snap.getSize());
+ ss.setPhysicalSize(snap.getPhysicalSize());
+ ss.setRefCnt(snap.getRefCnt());
+ persist(ss);
+ // increase ref_cnt so that this will not be recycled before the content is pushed to region-wide store
+ snap.incrRefCnt();
+ update(snap.getId(), snap);
+ }
+ }
+
+ }
+
+ @Override
+ public List<SnapshotDataStoreVO> listOnCache(long snapshotId) {
+ SearchCriteria<SnapshotDataStoreVO> sc = storeSnapshotSearch.create();
+ sc.setParameters("snapshot_id", snapshotId);
+ sc.setParameters("store_role", DataStoreRole.ImageCache);
+ return search(sc, null);
+ }
+
+ @Override
+ public void updateStoreRoleToCache(long storeId) {
+ SearchCriteria<SnapshotDataStoreVO> sc = storeSearch.create();
+ sc.setParameters("store_id", storeId);
+ sc.setParameters("destroyed", false);
+ List<SnapshotDataStoreVO> snaps = listBy(sc);
+ if (snaps != null) {
+ s_logger.info("Update to cache store role for " + snaps.size() + " entries in snapshot_store_ref");
+ for (SnapshotDataStoreVO snap : snaps) {
+ snap.setRole(DataStoreRole.ImageCache);
+ update(snap.getId(), snap);
+ }
+ }
+ }
+
}