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 2014/01/09 02:42:19 UTC
[1/2] git commit: updated refs/heads/master to 649d9d9
Updated Branches:
refs/heads/master fefe82618 -> 649d9d927
CLOUDSTACK-5813: With S3 as secondary storage, snapshot taken in one
zone cannot be used to create volume in another zone. zoneId parameter
in createVolumeCmd is not observed.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/858b9b11
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/858b9b11
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/858b9b11
Branch: refs/heads/master
Commit: 858b9b11778a687e6579d7ae2e9f6fbf512cd197
Parents: fefe826
Author: Min Chen <mi...@citrix.com>
Authored: Wed Jan 8 17:15:04 2014 -0800
Committer: Min Chen <mi...@citrix.com>
Committed: Wed Jan 8 17:15:04 2014 -0800
----------------------------------------------------------------------
.../motion/AncientDataMotionStrategy.java | 17 ++++++++++-------
.../com/cloud/storage/VolumeApiServiceImpl.java | 19 ++++++++++++-------
2 files changed, 22 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/858b9b11/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 99f5714..fa1dce4 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
@@ -23,6 +23,9 @@ import java.util.Map;
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@@ -45,8 +48,6 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.MigrateVolumeAnswer;
@@ -192,9 +193,9 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
}
- protected DataObject cacheSnapshotChain(SnapshotInfo snapshot) {
+ protected DataObject cacheSnapshotChain(SnapshotInfo snapshot, Scope scope) {
DataObject leafData = null;
- DataStore store = cacheMgr.getCacheStorage(snapshot.getDataStore().getScope());
+ DataStore store = cacheMgr.getCacheStorage(scope);
while (snapshot != null) {
DataObject cacheData = cacheMgr.createCacheObject(snapshot, store);
if (leafData == null) {
@@ -205,6 +206,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
return leafData;
}
+
protected void deleteSnapshotCacheChain(SnapshotInfo snapshot) {
while (snapshot != null) {
cacheMgr.deleteCacheObject(snapshot);
@@ -229,7 +231,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
DataObject srcData = snapObj;
try {
if (!(storTO instanceof NfsTO)) {
- srcData = cacheSnapshotChain(snapshot);
+ // cache snapshot to zone-wide staging store for the volume to be created
+ srcData = cacheSnapshotChain(snapshot, new ZoneScope(pool.getDataCenterId()));
}
String value = configDao.getValue(Config.CreateVolumeFromSnapshotWait.toString());
@@ -438,8 +441,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
boolean needCache = false;
if (needCacheStorage(srcData, destData)) {
needCache = true;
- SnapshotInfo snapshot = (SnapshotInfo)srcData;
- srcData = cacheSnapshotChain(snapshot);
+ SnapshotInfo snapshot = (SnapshotInfo) srcData;
+ srcData = cacheSnapshotChain(snapshot, snapshot.getDataStore().getScope());
}
EndPoint ep = null;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/858b9b11/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 4de635c..e1d1c7c 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -26,6 +26,8 @@ import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
+import org.apache.log4j.Logger;
+
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
@@ -44,6 +46,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@@ -72,7 +75,6 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
-import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@@ -120,7 +122,6 @@ import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.StoragePoolWorkDao;
-import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
@@ -130,7 +131,6 @@ import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotApiService;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.snapshot.SnapshotScheduler;
-import com.cloud.storage.upload.UploadMonitor;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
@@ -317,9 +317,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Inject
SnapshotApiService snapshotMgr;
@Inject
- UploadMonitor _uploadMonitor;
- @Inject
- UploadDao _uploadDao;
+ SnapshotService snapshotSrv;
@Inject
UUIDManager _uuidMgr;
@@ -604,7 +602,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
diskOfferingId = snapshotCheck.getDiskOfferingId();
diskOffering = _diskOfferingDao.findById(diskOfferingId);
- zoneId = snapshotCheck.getDataCenterId();
+ if (zoneId == null) {
+ // if zoneId is not provided, we default to create volume in the same zone as the snapshot zone.
+ zoneId = snapshotCheck.getDataCenterId();
+ }
size = snapshotCheck.getSize(); // ; disk offering is used for tags
// purposes
@@ -767,11 +768,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
protected VolumeVO createVolumeFromSnapshot(VolumeVO volume, long snapshotId, Long vmId) throws StorageUnavailableException {
VolumeInfo createdVolume = null;
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
+ long snapshotVolId = snapshot.getVolumeId();
UserVmVO vm = null;
if (vmId != null) {
vm = _userVmDao.findById(vmId);
}
+
+ // sync old snapshots to region store if necessary
+
createdVolume = _volumeMgr.createVolumeFromSnapshot(volume, snapshot, vm);
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(),
[2/2] git commit: updated refs/heads/master to 649d9d9
Posted by mc...@apache.org.
CLOUDSTACK-5840:Migration from NFS to S3 should be done in one API
(updateCloudToUseObjectStore) instead of two APIs.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/649d9d92
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/649d9d92
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/649d9d92
Branch: refs/heads/master
Commit: 649d9d927fc42271e6851a50d552655645a6e0d1
Parents: 858b9b1
Author: Min Chen <mi...@citrix.com>
Authored: Wed Jan 8 17:25:13 2014 -0800
Committer: Min Chen <mi...@citrix.com>
Committed: Wed Jan 8 17:25:13 2014 -0800
----------------------------------------------------------------------
api/src/com/cloud/storage/StorageService.java | 10 +-
.../admin/host/AddSecondaryStorageCmd.java | 22 ++-
.../command/admin/storage/AddImageStoreCmd.java | 10 +-
.../api/command/admin/storage/AddS3Cmd.java | 46 +++---
.../PrepareSecondaryStorageForMigrationCmd.java | 110 --------------
.../storage/UpdateCloudToUseObjectStoreCmd.java | 142 +++++++++++++++++++
.../api/command/admin/swift/AddSwiftCmd.java | 23 +--
.../test/AddSecondaryStorageCmdTest.java | 12 +-
client/tomcatconf/commands.properties.in | 2 +-
.../com/cloud/server/ManagementServerImpl.java | 12 +-
.../com/cloud/storage/StorageManagerImpl.java | 60 ++++++--
11 files changed, 252 insertions(+), 197 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/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 ac3c385..11f03aa 100644
--- a/api/src/com/cloud/storage/StorageService.java
+++ b/api/src/com/cloud/storage/StorageService.java
@@ -17,8 +17,8 @@
package com.cloud.storage;
import java.net.UnknownHostException;
+import java.util.Map;
-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;
@@ -92,7 +92,8 @@ public interface StorageService {
boolean deleteSecondaryStagingStore(DeleteSecondaryStagingStoreCmd cmd);
- ImageStore discoverImageStore(AddImageStoreCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
+ public ImageStore discoverImageStore(String name, String url, String providerName, Long dcId, Map details) throws IllegalArgumentException, DiscoveryException,
+ InvalidParameterValueException;
/**
* Prepare NFS secondary storage for object store migration
@@ -105,6 +106,9 @@ public interface StorageService {
* @throws InsufficientCapacityException
* TODO
*/
- public ImageStore prepareSecondaryStorageForObjectStoreMigration(Long storeId) throws ResourceUnavailableException, InsufficientCapacityException;
+ public ImageStore migrateToObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException,
+ InvalidParameterValueException;
+ public ImageStore prepareSecondaryStorageForObjectStoreMigration(Long storeId) throws ResourceUnavailableException,
+ InsufficientCapacityException;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
index 61f6f49..b573bea 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java
@@ -24,7 +24,6 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
@@ -74,20 +73,15 @@ public class AddSecondaryStorageCmd extends BaseCmd {
}
@Override
- public void execute() {
- AddImageStoreCmd cmd = new AddImageStoreCmd();
- cmd.setUrl(this.getUrl());
- cmd.setZoneId(this.getZoneId());
- cmd.setProviderName("NFS");
-
- try {
- ImageStore result = _storageService.discoverImageStore(cmd);
+ public void execute(){
+ try{
+ ImageStore result = _storageService.discoverImageStore(null, getUrl(), "NFS", getZoneId(), null);
ImageStoreResponse storeResponse = null;
- if (result != null) {
- storeResponse = _responseGenerator.createImageStoreResponse(result);
- storeResponse.setResponseName(getCommandName());
- storeResponse.setObjectName("secondarystorage");
- this.setResponseObject(storeResponse);
+ if (result != null ) {
+ storeResponse = _responseGenerator.createImageStoreResponse(result);
+ storeResponse.setResponseName(getCommandName());
+ storeResponse.setObjectName("secondarystorage");
+ setResponseObject(storeResponse);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
index 5dcedff..5e5bd3d 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java
@@ -95,7 +95,7 @@ public class AddImageStoreCmd extends BaseCmd {
}
public String getProviderName() {
- return this.providerName;
+ return providerName;
}
public void setUrl(String url) {
@@ -129,15 +129,15 @@ public class AddImageStoreCmd extends BaseCmd {
}
@Override
- public void execute() {
- try {
- ImageStore result = _storageService.discoverImageStore(this);
+ public void execute(){
+ try{
+ ImageStore result = _storageService.discoverImageStore(getName(), getUrl(), getProviderName(), getZoneId(), getDetails());
ImageStoreResponse storeResponse = null;
if (result != null) {
storeResponse = _responseGenerator.createImageStoreResponse(result);
storeResponse.setResponseName(getCommandName());
storeResponse.setObjectName("imagestore");
- this.setResponseObject(storeResponse);
+ setResponseObject(storeResponse);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java
index e665b7d..32897e4 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java
@@ -86,33 +86,27 @@ public final class AddS3Cmd extends BaseCmd {
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
- AddImageStoreCmd cmd = new AddImageStoreCmd() {
- @Override
- public Map<String, String> getDetails() {
- Map<String, String> dm = new HashMap<String, String>();
- dm.put(ApiConstants.S3_ACCESS_KEY, getAccessKey());
- dm.put(ApiConstants.S3_SECRET_KEY, getSecretKey());
- dm.put(ApiConstants.S3_END_POINT, getEndPoint());
- dm.put(ApiConstants.S3_BUCKET_NAME, getBucketName());
- if (getHttpsFlag() != null) {
- dm.put(ApiConstants.S3_HTTPS_FLAG, getHttpsFlag().toString());
- }
- if (getConnectionTimeout() != null) {
- dm.put(ApiConstants.S3_CONNECTION_TIMEOUT, getConnectionTimeout().toString());
- }
- if (getMaxErrorRetry() != null) {
- dm.put(ApiConstants.S3_MAX_ERROR_RETRY, getMaxErrorRetry().toString());
- }
- if (getSocketTimeout() != null) {
- dm.put(ApiConstants.S3_SOCKET_TIMEOUT, getSocketTimeout().toString());
- }
- return dm;
- }
- };
- cmd.setProviderName("S3");
+ Map<String, String> dm = new HashMap<String, String>();
+ dm.put(ApiConstants.S3_ACCESS_KEY, getAccessKey());
+ dm.put(ApiConstants.S3_SECRET_KEY, getSecretKey());
+ dm.put(ApiConstants.S3_END_POINT, getEndPoint());
+ dm.put(ApiConstants.S3_BUCKET_NAME, getBucketName());
+ if (getHttpsFlag() != null) {
+ dm.put(ApiConstants.S3_HTTPS_FLAG, getHttpsFlag().toString());
+ }
+ if (getConnectionTimeout() != null) {
+ dm.put(ApiConstants.S3_CONNECTION_TIMEOUT, getConnectionTimeout().toString());
+ }
+ if (getMaxErrorRetry() != null) {
+ dm.put(ApiConstants.S3_MAX_ERROR_RETRY, getMaxErrorRetry().toString());
+ }
+ if (getSocketTimeout() != null) {
+ dm.put(ApiConstants.S3_SOCKET_TIMEOUT, getSocketTimeout().toString());
+ }
+
- try {
- ImageStore result = _storageService.discoverImageStore(cmd);
+ try{
+ ImageStore result = _storageService.discoverImageStore(null, null, "S3", null, dm);
ImageStoreResponse storeResponse = null;
if (result != null) {
storeResponse = _responseGenerator.createImageStoreResponse(result);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/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
deleted file mode 100644
index a57f2df..0000000
--- a/api/src/org/apache/cloudstack/api/command/admin/storage/PrepareSecondaryStorageForMigrationCmd.java
+++ /dev/null
@@ -1,110 +0,0 @@
-// 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/649d9d92/api/src/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java
new file mode 100644
index 0000000..983a01c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java
@@ -0,0 +1,142 @@
+// 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 java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ImageStoreResponse;
+
+import com.cloud.exception.DiscoveryException;
+import com.cloud.storage.ImageStore;
+import com.cloud.user.Account;
+
+@APICommand(name = "updateCloudToUseObjectStore", description = "Migrate current NFS secondary storages to use object store.", responseObject = ImageStoreResponse.class, since = "4.3.0")
+public class UpdateCloudToUseObjectStoreCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(UpdateCloudToUseObjectStoreCmd.class.getName());
+ private static final String s_name = "updatecloudtouseobjectstoreresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name for the image store")
+ private String name;
+
+ @Parameter(name=ApiConstants.URL, type=CommandType.STRING, description="the URL for the image store")
+ private String url;
+
+ @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING,
+ required=true, description="the image store provider name")
+ private String providerName;
+
+ @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="the details for the image store. Example: details[0].key=accesskey&details[0].value=s389ddssaa&details[1].key=secretkey&details[1].value=8dshfsss")
+ private Map details;
+
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public String getUrl() {
+ return url;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Map<String, String> getDetails() {
+ Map<String, String> detailsMap = null;
+ if (details != null && !details.isEmpty()) {
+ detailsMap = new HashMap<String, String>();
+ Collection<?> props = details.values();
+ Iterator<?> iter = props.iterator();
+ while (iter.hasNext()) {
+ HashMap<String, String> detail = (HashMap<String, String>) iter.next();
+ String key = detail.get("key");
+ String value = detail.get("value");
+ detailsMap.put(key, value);
+ }
+ }
+ return detailsMap;
+ }
+
+ public String getProviderName() {
+ return providerName;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+
+ public void setProviderName(String providerName) {
+ this.providerName = providerName;
+ }
+
+ public void setDetails(Map<String, String> details) {
+ this.details = details;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ try{
+ ImageStore result = _storageService.migrateToObjectStore(getName(), getUrl(), getProviderName(), getDetails());
+ ImageStoreResponse storeResponse = null;
+ if (result != null ) {
+ storeResponse = _responseGenerator.createImageStoreResponse(result);
+ storeResponse.setResponseName(getCommandName());
+ storeResponse.setObjectName("imagestore");
+ setResponseObject(storeResponse);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
+ }
+ } catch (DiscoveryException ex) {
+ s_logger.warn("Exception: ", ex);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java b/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
index 3b684f4..173c95e 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java
@@ -27,7 +27,6 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import com.cloud.exception.DiscoveryException;
@@ -91,27 +90,19 @@ public class AddSwiftCmd extends BaseCmd {
@Override
public void execute() {
- AddImageStoreCmd cmd = new AddImageStoreCmd() {
- @Override
- public Map<String, String> getDetails() {
- Map<String, String> dm = new HashMap<String, String>();
- dm.put(ApiConstants.ACCOUNT, getAccount());
- dm.put(ApiConstants.USERNAME, getUsername());
- dm.put(ApiConstants.KEY, getKey());
- return dm;
- }
- };
- cmd.setProviderName("Swift");
- cmd.setUrl(this.getUrl());
+ Map<String, String> dm = new HashMap<String, String>();
+ dm.put(ApiConstants.ACCOUNT, getAccount());
+ dm.put(ApiConstants.USERNAME, getUsername());
+ dm.put(ApiConstants.KEY, getKey());
- try {
- ImageStore result = _storageService.discoverImageStore(cmd);
+ try{
+ ImageStore result = _storageService.discoverImageStore(null, getUrl(), "Swift", null, dm);
ImageStoreResponse storeResponse = null;
if (result != null) {
storeResponse = _responseGenerator.createImageStoreResponse(result);
storeResponse.setResponseName(getCommandName());
storeResponse.setObjectName("secondarystorage");
- this.setResponseObject(storeResponse);
+ setResponseObject(storeResponse);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Swift secondary storage");
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java
----------------------------------------------------------------------
diff --git a/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java
index d0b2d85..d68cfb4 100644
--- a/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java
+++ b/api/test/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java
@@ -16,6 +16,12 @@
// under the License.
package org.apache.cloudstack.api.command.test;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+
+import java.util.Map;
+
import junit.framework.Assert;
import junit.framework.TestCase;
@@ -56,7 +62,8 @@ public class AddSecondaryStorageCmdTest extends TestCase {
ImageStore store = Mockito.mock(ImageStore.class);
- Mockito.when(resourceService.discoverImageStore(addImageStoreCmd)).thenReturn(store);
+ Mockito.when(resourceService.discoverImageStore(anyString(), anyString(), anyString(), anyLong(), (Map)anyObject()))
+ .thenReturn(store);
ResponseGenerator responseGenerator = Mockito.mock(ResponseGenerator.class);
addImageStoreCmd._responseGenerator = responseGenerator;
@@ -83,7 +90,8 @@ public class AddSecondaryStorageCmdTest extends TestCase {
StorageService resourceService = Mockito.mock(StorageService.class);
addImageStoreCmd._storageService = resourceService;
- Mockito.when(resourceService.discoverImageStore(addImageStoreCmd)).thenReturn(null);
+ Mockito.when(resourceService.discoverImageStore(anyString(), anyString(), anyString(), anyLong(), (Map)anyObject()))
+ .thenReturn(null);
try {
addImageStoreCmd.execute();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 189d087..c5ac7fd 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -266,7 +266,7 @@ deleteImageStore=1
createSecondaryStagingStore=1
listSecondaryStagingStores=1
deleteSecondaryStagingStore=1
-prepareSecondaryStorageForMigration=1
+updateCloudToUseObjectStore=1
#### host commands
addHost=3
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 168d83d..28cc1fd 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -42,9 +42,6 @@ import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.cloud.service.ServiceOfferingVO;
-import com.cloud.service.dao.ServiceOfferingDao;
-import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
@@ -166,7 +163,7 @@ import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStore
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStorageProvidersCmd;
import org.apache.cloudstack.api.command.admin.storage.PreparePrimaryStorageForMaintenanceCmd;
-import org.apache.cloudstack.api.command.admin.storage.PrepareSecondaryStorageForMigrationCmd;
+import org.apache.cloudstack.api.command.admin.storage.UpdateCloudToUseObjectStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd;
import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd;
@@ -444,6 +441,7 @@ import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationSer
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
@@ -535,6 +533,8 @@ import com.cloud.projects.ProjectManager;
import com.cloud.resource.ResourceManager;
import com.cloud.server.ResourceTag.ResourceObjectType;
import com.cloud.server.auth.UserAuthenticator;
+import com.cloud.service.ServiceOfferingVO;
+import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSCategoryVO;
@@ -752,7 +752,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
public void setPlanners(List<DeploymentPlanner> planners) {
- this._planners = planners;
+ _planners = planners;
}
@Inject
@@ -2842,7 +2842,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(CreateSecondaryStagingStoreCmd.class);
cmdList.add(ListSecondaryStagingStoresCmd.class);
cmdList.add(DeleteSecondaryStagingStoreCmd.class);
- cmdList.add(PrepareSecondaryStorageForMigrationCmd.class);
+ cmdList.add(UpdateCloudToUseObjectStoreCmd.class);
cmdList.add(CreateApplicationLoadBalancerCmd.class);
cmdList.add(ListApplicationLoadBalancersCmd.class);
cmdList.add(DeleteApplicationLoadBalancerCmd.class);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/649d9d92/server/src/com/cloud/storage/StorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index d73b2cc..4fda2dd 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -41,7 +41,9 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import org.apache.cloudstack.api.command.admin.storage.AddImageStoreCmd;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
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;
@@ -84,8 +86,6 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@@ -269,7 +269,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
}
public void setDiscoverers(List<StoragePoolDiscoverer> discoverers) {
- this._discoverers = discoverers;
+ _discoverers = discoverers;
}
protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch;
@@ -1634,8 +1634,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
}
@Override
- public ImageStore discoverImageStore(AddImageStoreCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
- String providerName = cmd.getProviderName();
+ public ImageStore discoverImageStore(String name, String url, String providerName, Long dcId, Map details) throws IllegalArgumentException, DiscoveryException,
+ InvalidParameterValueException {
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
if (storeProvider == null) {
@@ -1646,16 +1646,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
providerName = storeProvider.getName(); // ignored passed provider name and use default image store provider name
}
- Long dcId = cmd.getZoneId();
- Map details = cmd.getDetails();
ScopeType scopeType = ScopeType.ZONE;
if (dcId == null) {
scopeType = ScopeType.REGION;
}
- String name = cmd.getName();
if (name == null) {
- name = cmd.getUrl();
+ name = url;
}
ImageStoreVO imageStore = _imageStoreDao.findByName(name);
if (imageStore != null) {
@@ -1694,8 +1691,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
Map<String, Object> params = new HashMap<String, Object>();
params.put("zoneId", dcId);
- params.put("url", cmd.getUrl());
- params.put("name", cmd.getName());
+ params.put("url", url);
+ params.put("name", name);
params.put("details", details);
params.put("scope", scopeType);
params.put("providerName", storeProvider.getName());
@@ -1706,8 +1703,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
try {
store = lifeCycle.initialize(params);
} catch (Exception e) {
- s_logger.debug("Failed to add data store: "+e.getMessage(), e);
- throw new CloudRuntimeException("Failed to add data store: "+e.getMessage(), e);
+ s_logger.debug("Failed to add data store: " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e);
}
if (((ImageStoreProvider)storeProvider).needDownloadSysTemplate()) {
@@ -1730,6 +1727,41 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
return (ImageStore)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Image);
}
+ @Override
+ public ImageStore migrateToObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException,
+ InvalidParameterValueException {
+ // check if current cloud is ready to migrate, we only support cloud with only NFS secondary storages
+ List<ImageStoreVO> imgStores = _imageStoreDao.listImageStores();
+ List<ImageStoreVO> nfsStores = new ArrayList<ImageStoreVO>();
+ if (imgStores != null && imgStores.size() > 0) {
+ for (ImageStoreVO store : imgStores) {
+ if (!store.getProviderName().equals(DataStoreProvider.NFS_IMAGE)) {
+ throw new InvalidParameterValueException("We only support migrate NFS secondary storage to use object store!");
+ } else {
+ nfsStores.add(store);
+ }
+ }
+ }
+ // convert all NFS secondary storage to staging store
+ if (nfsStores != null && nfsStores.size() > 0) {
+ for (ImageStoreVO store : nfsStores) {
+ long storeId = store.getId();
+
+ _accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), store.getDataCenterId());
+
+ DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(store.getProviderName());
+ DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
+ DataStore secStore = dataStoreMgr.getDataStore(storeId, DataStoreRole.Image);
+ lifeCycle.migrateToObjectStore(secStore);
+ // update store_role in template_store_ref and snapshot_store_ref to ImageCache
+ _templateStoreDao.updateStoreRoleToCachce(storeId);
+ _snapshotStoreDao.updateStoreRoleToCache(storeId);
+ }
+ }
+ // add object store
+ return discoverImageStore(name, url, providerName, null, details);
+ }
+
private void duplicateCacheStoreRecordsToRegionStore(long storeId) {
_templateStoreDao.duplicateCacheRecordsOnRegionStore(storeId);
_snapshotStoreDao.duplicateCacheRecordsOnRegionStore(storeId);