From 649d9d927fc42271e6851a50d552655645a6e0d1 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Wed, 8 Jan 2014 17:25:13 -0800 Subject: [PATCH] CLOUDSTACK-5840:Migration from NFS to S3 should be done in one API (updateCloudToUseObjectStore) instead of two APIs. --- api/src/com/cloud/storage/StorageService.java | 10 +- .../admin/host/AddSecondaryStorageCmd.java | 22 +-- .../admin/storage/AddImageStoreCmd.java | 10 +- .../api/command/admin/storage/AddS3Cmd.java | 46 +++--- ...repareSecondaryStorageForMigrationCmd.java | 110 -------------- .../UpdateCloudToUseObjectStoreCmd.java | 142 ++++++++++++++++++ .../api/command/admin/swift/AddSwiftCmd.java | 23 +-- .../test/AddSecondaryStorageCmdTest.java | 12 +- client/tomcatconf/commands.properties.in | 2 +- .../cloud/server/ManagementServerImpl.java | 12 +- .../com/cloud/storage/StorageManagerImpl.java | 60 ++++++-- 11 files changed, 252 insertions(+), 197 deletions(-) delete mode 100644 api/src/org/apache/cloudstack/api/command/admin/storage/PrepareSecondaryStorageForMigrationCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java diff --git a/api/src/com/cloud/storage/StorageService.java b/api/src/com/cloud/storage/StorageService.java index ac3c385695f..11f03aa9292 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; } 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 61f6f49091c..b573bea3e84 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"); } 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 5dcedff2392..5e5bd3dcde5 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"); } 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 e665b7d0d24..32897e4d59d 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 getDetails() { - Map dm = new HashMap(); - 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 dm = new HashMap(); + 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); 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 a57f2dfeffc..00000000000 --- 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"); - } - } -} 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 00000000000..983a01c7fbe --- /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 getDetails() { + Map detailsMap = null; + if (details != null && !details.isEmpty()) { + detailsMap = new HashMap(); + Collection props = details.values(); + Iterator iter = props.iterator(); + while (iter.hasNext()) { + HashMap detail = (HashMap) 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 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()); + } + } +} 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 3b684f41a63..173c95e2c0d 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 getDetails() { - Map dm = new HashMap(); - 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 dm = new HashMap(); + 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"); } 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 d0b2d85f8d5..d68cfb4ca67 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(); diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 189d087d9f4..c5ac7fd67af 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 diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 168d83d4360..28cc1fd7003 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 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); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index d73b2cc95c4..4fda2dd1e41 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 discoverers) { - this._discoverers = discoverers; + _discoverers = discoverers; } protected SearchBuilder 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 params = new HashMap(); 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 imgStores = _imageStoreDao.listImageStores(); + List nfsStores = new ArrayList(); + 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);