CLOUDSTACK-5840:Migration from NFS to S3 should be done in one API

(updateCloudToUseObjectStore) instead of two APIs.
This commit is contained in:
Min Chen 2014-01-08 17:25:13 -08:00
parent 858b9b1177
commit 649d9d927f
11 changed files with 252 additions and 197 deletions

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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);

View File

@ -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");
}
}
}

View File

@ -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());
}
}
}

View File

@ -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");
}

View File

@ -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();

View File

@ -266,7 +266,7 @@ deleteImageStore=1
createSecondaryStagingStore=1
listSecondaryStagingStores=1
deleteSecondaryStagingStore=1
prepareSecondaryStorageForMigration=1
updateCloudToUseObjectStore=1
#### host commands
addHost=3

View File

@ -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);

View File

@ -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);