add cache storage

This commit is contained in:
Edison Su 2013-04-10 23:36:39 -07:00
parent dcbeea057b
commit e5bf38ed05
35 changed files with 450 additions and 280 deletions

View File

@ -20,6 +20,7 @@ import java.net.UnknownHostException;
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.CreateCacheStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
@ -47,6 +48,8 @@ public interface StorageService{
*/
StoragePool createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException,
UnknownHostException, ResourceUnavailableException;
ImageStore createCacheStore(CreateCacheStoreCmd cmd);
/**
* Delete the storage pool

View File

@ -0,0 +1,123 @@
/*
* 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.Map;
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.BaseCmd.CommandType;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.log4j.Logger;
import com.cloud.exception.DiscoveryException;
import com.cloud.storage.ImageStore;
import com.cloud.user.Account;
@APICommand(name = "createCacheStore", description="create cache store.", responseObject=ImageStoreResponse.class)
public class CreateCacheStoreCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(AddImageStoreCmd.class.getName());
private static final String s_name = "createcachestoreresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=true, description="the URL for the cache store")
private String url;
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
description="the Zone ID for the image store")
private Long zoneId;
@Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="the details for the image store")
private Map<String, String> details;
@Parameter(name=ApiConstants.SCOPE, type=CommandType.STRING,
required=false, description="the scope of the image store: zone only for now")
private String scope;
@Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING,
required=false, description="the cache store provider name")
private String providerName;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getUrl() {
return url;
}
public Long getZoneId() {
return zoneId;
}
public Map<String, String> getDetails() {
return details;
}
public String getScope() {
return this.scope;
}
public String getProviderName() {
return this.providerName;
}
/////////////////////////////////////////////////////
/////////////// 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.createCacheStore(this);
ImageStoreResponse storeResponse = null;
if (result != null ) {
storeResponse = _responseGenerator.createImageStoreResponse(result);
storeResponse.setResponseName(getCommandName());
storeResponse.setObjectName("secondarystorage");
this.setResponseObject(storeResponse);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage");
}
} catch (Exception ex) {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
}
}
}

View File

@ -16,10 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.motion;
package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
public interface DataMotionService {

View File

@ -16,10 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.motion;
package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
public interface DataMotionStrategy {

View File

@ -28,5 +28,6 @@ public interface DataStoreManager {
public DataStore getDataStore(String uuid, DataStoreRole role);
public List<DataStore> getImageStoresByScope(ZoneScope scope);
public List<DataStore> getImageStoresByProvider(String provider);
public List<DataStore> getImageCacheStores(Scope scope);
public DataStore registerDataStore(Map<String, String> params, String providerUuid);
}

View File

@ -27,7 +27,8 @@ import java.util.Set;
public interface DataStoreProvider {
public static enum DataStoreProviderType {
PRIMARY,
IMAGE
IMAGE,
ImageCache
}
public DataStoreLifeCycle getDataStoreLifeCycle();
public DataStoreDriver getDataStoreDriver();

View File

@ -27,6 +27,7 @@ public interface DataStoreProviderManager extends Manager, DataStoreProviderApiS
public DataStoreProvider getDataStoreProvider(String name);
public DataStoreProvider getDefaultPrimaryDataStoreProvider();
public DataStoreProvider getDefaultImageDataStoreProvider();
public DataStoreProvider getDefaultCacheDataStoreProvider();
public List<DataStoreProvider> getDataStoreProviders();
}

View File

@ -16,8 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.backup;
package org.apache.cloudstack.engine.subsystem.api.storage;
public interface BackupMotionService {
boolean copySnapshot(String snapshotUri, String destSnapshotUri);
public interface StorageCacheManager {
public DataStore getCacheStorage(Scope scope);
}

View File

@ -28,6 +28,8 @@ import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import com.cloud.storage.ImageStore;
@ -69,6 +71,18 @@ public class ImageStoreVO implements ImageStore {
@Column(name=GenericDao.REMOVED_COLUMN)
private Date removed;
@Column(name = "role")
@Enumerated(value = EnumType.STRING)
private DataStoreRole role;
public DataStoreRole getRole() {
return role;
}
public void setRole(DataStoreRole role) {
this.role = role;
}
public long getId() {
return this.id;

View File

@ -39,8 +39,8 @@
<module>storage</module>
<module>storage/volume</module>
<module>storage/image</module>
<module>storage/imagemotion</module>
<module>storage/backup</module>
<module>storage/datamotion</module>
<module>storage/cache</module>
<module>storage/snapshot</module>
<module>storage/integration-test</module>
<module>components-api</module>

View File

@ -1,26 +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.storage.backup;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
public interface BackupService {
public boolean backupSnapshot(SnapshotInfo snapshot, long backupStoreId);
public SnapshotOnBackupStoreInfo getSnapshot(long snapshotId);
}

View File

@ -11,8 +11,8 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-engine-storage-backup</artifactId>
<name>Apache CloudStack Engine Storage Backup Component</name>
<artifactId>cloud-engine-storage-cache</artifactId>
<name>Apache CloudStack Engine Storage Cache Component</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>

View File

@ -16,9 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.image.motion;
package org.apache.cloudstack.storage.cache.allocator;
import org.apache.cloudstack.storage.motion.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
public interface ImageMotionStrategy extends DataMotionStrategy {
public interface StorageCacheAllocator {
DataStore getCacheStore(Scope scope);
}

View File

@ -0,0 +1,51 @@
/*
* 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.storage.cache.allocator;
import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import com.cloud.storage.ScopeType;
import com.cloud.utils.exception.CloudRuntimeException;
import edu.emory.mathcs.backport.java.util.Collections;
public class StorageCacheRandomAllocator implements StorageCacheAllocator {
@Inject
DataStoreManager dataStoreMgr;
@Override
public DataStore getCacheStore(Scope scope) {
if (scope.getScopeType() != ScopeType.ZONE) {
throw new CloudRuntimeException("Can only support zone wide cache storage");
}
List<DataStore> cacheStores = dataStoreMgr.getImageCacheStores(scope);
if (cacheStores.size() <= 0) {
throw new CloudRuntimeException("Can't find cache storage in zone: " + scope.getScopeId());
}
Collections.shuffle(cacheStores);
return cacheStores.get(0);
}
}

View File

@ -0,0 +1,100 @@
/*
* 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.storage.cache.manager;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
import org.apache.cloudstack.storage.cache.allocator.StorageCacheAllocator;
import com.cloud.utils.component.Manager;
public class StorageCacheManagerImpl implements StorageCacheManager, Manager {
@Inject
List<StorageCacheAllocator> storageCacheAllocator;
@Override
public DataStore getCacheStorage(Scope scope) {
for (StorageCacheAllocator allocator : storageCacheAllocator) {
DataStore store = allocator.getCacheStore(scope);
if (store != null) {
return store;
}
}
return null;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
// TODO Auto-generated method stub
return true;
}
}

View File

@ -11,8 +11,8 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-engine-storage-imagemotion</artifactId>
<name>Apache CloudStack Engine Storage Image Motion Component</name>
<artifactId>cloud-engine-storage-datamotion</artifactId>
<name>Apache CloudStack Engine Storage Data Motion Component</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>

View File

@ -24,6 +24,7 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;

View File

@ -23,6 +23,8 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.springframework.stereotype.Component;

View File

@ -28,6 +28,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@ -37,12 +38,18 @@ import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import org.apache.cloudstack.storage.image.store.ImageStoreImpl;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.storage.ScopeType;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
@Component
public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager {
private static final Logger s_logger = Logger.getLogger(ImageStoreProviderManagerImpl.class);
@Inject
ImageStoreDao dataStoreDao;
@Inject
@ -115,4 +122,21 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager
@Override
public List<DataStore> listImageCacheStores(Scope scope) {
List<DataStore> imageStores = new ArrayList<DataStore>();
if (scope.getScopeType() != ScopeType.ZONE) {
s_logger.debug("only support zone wide image cache stores");
return imageStores;
}
SearchCriteriaService<ImageStoreVO, ImageStoreVO> sc = SearchCriteria2.create(ImageStoreVO.class);
sc.addAnd(sc.getEntity().getScope(), Op.EQ, ScopeType.ZONE);
sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, scope.getScopeId());
sc.addAnd(sc.getEntity().getRole(), Op.EQ, DataStoreRole.ImageCache);
List<ImageStoreVO> cacheStores = sc.list();
for (ImageStoreVO store : cacheStores) {
imageStores.add(getImageStore(store.getId()));
}
return imageStores;
}
}

View File

@ -1,140 +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.storage.image.motion;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.command.CopyCmd;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.endpoint.EndPointSelector;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo;
import com.cloud.agent.api.Answer;
//At least one of datastore is coming from image store or image cache store
public class DefaultImageMotionStrategy implements ImageMotionStrategy {
@Inject
EndPointSelector selector;
private class CreateTemplateContext<T> extends AsyncRpcConext<T> {
private final TemplateOnPrimaryDataStoreInfo template;
public CreateTemplateContext(AsyncCompletionCallback<T> callback, TemplateOnPrimaryDataStoreInfo template) {
super(callback);
this.template = template;
}
public TemplateOnPrimaryDataStoreInfo getTemplate() {
return this.template;
}
}
/*
@Override
public void copyTemplateAsync(String destUri, String srcUri, EndPoint ep, AsyncCompletionCallback<CommandResult> callback) {
CopyCmd copyCommand = new CopyCmd(destUri, srcUri);
CreateTemplateContext<CommandResult> context = new CreateTemplateContext<CommandResult>(callback, null);
AsyncCallbackDispatcher<DefaultImageMotionStrategy, Answer> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().copyTemplateCallBack(null, null))
.setContext(context);
ep.sendMessageAsync(copyCommand, caller);
}
public Object copyTemplateCallBack(AsyncCallbackDispatcher<DefaultImageMotionStrategy, Answer> callback, CreateTemplateContext<CommandResult> context) {
AsyncCompletionCallback<CommandResult> parentCall = context.getParentCallback();
CopyTemplateToPrimaryStorageAnswer answer = (CopyTemplateToPrimaryStorageAnswer)callback.getResult();
CommandResult result = new CommandResult();
if (!answer.getResult()) {
result.setSucess(answer.getResult());
result.setResult(answer.getDetails());
} else {
TemplateOnPrimaryDataStoreInfo templateStore = context.getTemplate();
templateStore.setPath(answer.getPath());
result.setSucess(true);
}
parentCall.complete(result);
return null;
}*/
@Override
public boolean canHandle(DataObject srcData, DataObject destData) {
/*
DataStore destStore = destData.getDataStore();
DataStore srcStore = srcData.getDataStore();
if (destStore.getRole() == DataStoreRole.Image || destStore.getRole() == DataStoreRole.ImageCache
|| srcStore.getRole() == DataStoreRole.Image
|| srcStore.getRole() == DataStoreRole.ImageCache) {
return true;
}*/
return false;
}
@Override
public Void copyAsync(DataObject srcData, DataObject destData,
AsyncCompletionCallback<CopyCommandResult> callback) {
DataStore destStore = destData.getDataStore();
DataStore srcStore = srcData.getDataStore();
EndPoint ep = selector.select(srcData, destData);
CopyCommandResult result = new CopyCommandResult("", null);
if (ep == null) {
result.setResult("can't find end point");
callback.complete(result);
return null;
}
String srcUri = srcStore.getDriver().grantAccess(srcData, ep);
String destUri = destStore.getDriver().grantAccess(destData, ep);
CopyCmd cmd = new CopyCmd(srcUri, destUri);
CreateTemplateContext<CopyCommandResult> context = new CreateTemplateContext<CopyCommandResult>(callback, null);
AsyncCallbackDispatcher<DefaultImageMotionStrategy, Answer> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().copyAsyncCallback(null, null))
.setContext(context);
ep.sendMessageAsync(cmd, caller);
return null;
}
protected Void copyAsyncCallback(AsyncCallbackDispatcher<DefaultImageMotionStrategy, Answer> callback, CreateTemplateContext<CopyCommandResult> context) {
AsyncCompletionCallback<CopyCommandResult> parentCall = context.getParentCallback();
Answer answer = (Answer)callback.getResult();
if (!answer.getResult()) {
CopyCommandResult result = new CopyCommandResult("", null);
result.setResult(answer.getDetails());
parentCall.complete(result);
} else {
CopyCmdAnswer ans = (CopyCmdAnswer)answer;
CopyCommandResult result = new CopyCommandResult(ans.getPath(), null);
parentCall.complete(result);
}
return null;
}
}

View File

@ -1,70 +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.storage.image.motion;
import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
public class ImageMotionServiceImpl implements ImageMotionService {
@Inject
List<ImageMotionStrategy> motionStrategies;
@Inject
VolumeService volumeService;
@Inject
ImageService imageService;
@Override
public boolean copyIso(String isoUri, String destIsoUri) {
// TODO Auto-generated method stub
return false;
}
@Override
public void copyTemplateAsync(TemplateInfo destTemplate, TemplateInfo srcTemplate, AsyncCompletionCallback<CommandResult> callback) {
/* ImageMotionStrategy ims = null;
for (ImageMotionStrategy strategy : motionStrategies) {
if (strategy.canHandle(srcTemplate)) {
ims = strategy;
break;
}
}
if (ims == null) {
throw new CloudRuntimeException("Can't find proper image motion strategy");
}
EndPoint ep = ims.getEndPoint(destTemplate, srcTemplate);
String srcUri = srcTemplate.getDataStore().grantAccess(srcTemplate, ep);
String destUri = destTemplate.getDataStore().grantAccess(destTemplate, ep);
ims.copyTemplateAsync(destUri, srcUri, ep, callback);*/
}
}

View File

@ -19,9 +19,9 @@
package org.apache.cloudstack.storage.test;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.motion.DataMotionStrategy;
public class MockStorageMotionStrategy implements DataMotionStrategy {

View File

@ -25,7 +25,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@ -45,23 +45,15 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.motion.DataMotionService;
import org.apache.cloudstack.storage.snapshot.SnapshotObject;
import org.apache.cloudstack.storage.snapshot.SnapshotStateMachineManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.BackupSnapshotAnswer;
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.SwiftTO;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@ -73,12 +65,9 @@ import com.cloud.storage.VolumeManager;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.vm.UserVmVO;

View File

@ -23,6 +23,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@ -31,7 +32,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.motion.DataMotionService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

View File

@ -46,6 +46,8 @@ public class DataStoreManagerImpl implements DataStoreManager {
return primaryStorMgr.getPrimaryDataStore(storeId);
} else if (role == DataStoreRole.Image) {
return imageDataStoreMgr.getImageStore(storeId);
} else if (role == DataStoreRole.ImageCache) {
return imageDataStoreMgr.getImageStore(storeId);
}
throw new CloudRuntimeException("un recognized type" + role);
}
@ -81,5 +83,8 @@ public class DataStoreManagerImpl implements DataStoreManager {
public DataStore getPrimaryDataStore(long storeId) {
return primaryStorMgr.getPrimaryDataStore(storeId);
}
@Override
public List<DataStore> getImageCacheStores(Scope scope) {
return imageDataStoreMgr.listImageCacheStores(scope);
}
}

View File

@ -161,11 +161,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
this.stateMachines.transitTo(obj, event, null,
templatePoolDao);
} catch (NoTransitionException e) {
if (event == Event.CreateOnlyRequested || event == Event.OperationSuccessed) {
s_logger.debug("allow muliple create requests");
} else {
throw e;
}
}
} else {
throw new CloudRuntimeException("Invalid data or store type: " + data.getType() + " " + data.getDataStore().getRole());

View File

@ -34,8 +34,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManag
import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -68,7 +68,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
public List<StorageProviderResponse> getPrimaryDataStoreProviders() {
List<StorageProviderResponse> providers = new ArrayList<StorageProviderResponse>();
for (DataStoreProvider provider : providerMap.values()) {
if (provider instanceof PrimaryDataStoreProvider) {
if (provider.getTypes().contains(DataStoreProviderType.PRIMARY)) {
StorageProviderResponse response = new StorageProviderResponse();
response.setName(provider.getName());
response.setType(DataStoreProvider.DataStoreProviderType.PRIMARY.toString());
@ -81,7 +81,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
public List<StorageProviderResponse> getImageDataStoreProviders() {
List<StorageProviderResponse> providers = new ArrayList<StorageProviderResponse>();
for (DataStoreProvider provider : providerMap.values()) {
if (provider instanceof ImageStoreProvider) {
if (provider.getTypes().contains(DataStoreProviderType.IMAGE)) {
StorageProviderResponse response = new StorageProviderResponse();
response.setName(provider.getName());
response.setType(DataStoreProvider.DataStoreProviderType.IMAGE.toString());
@ -90,6 +90,19 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
}
return providers;
}
public List<StorageProviderResponse> getCacheDataStoreProviders() {
List<StorageProviderResponse> providers = new ArrayList<StorageProviderResponse>();
for (DataStoreProvider provider : providerMap.values()) {
if (provider.getTypes().contains(DataStoreProviderType.ImageCache)) {
StorageProviderResponse response = new StorageProviderResponse();
response.setName(provider.getName());
response.setType(DataStoreProviderType.ImageCache.toString());
providers.add(response);
}
}
return providers;
}
@Override
public boolean configure(String name, Map<String, Object> params)
@ -125,6 +138,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
} catch(Exception e) {
s_logger.debug("configure provider failed", e);
providerMap.remove(providerName);
return false;
}
}
@ -141,6 +155,11 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
public DataStoreProvider getDefaultImageDataStoreProvider() {
return this.getDataStoreProvider("CloudStack ImageStore Provider");
}
@Override
public DataStoreProvider getDefaultCacheDataStoreProvider() {
return this.getDataStoreProvider("cloudstack image store provider");
}
@Override
public List<StorageProviderResponse> getDataStoreProviders(String type) {
@ -151,6 +170,8 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
return this.getPrimaryDataStoreProviders();
} else if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.IMAGE.toString())) {
return this.getImageDataStoreProviders();
} else if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.ImageCache.toString())) {
return this.getCacheDataStoreProviders();
} else {
throw new InvalidParameterValueException("Invalid parameter: " + type);
}

View File

@ -23,6 +23,7 @@ import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
@ -52,6 +53,7 @@ public class ImageStoreHelper {
store.setScope((ScopeType)params.get("scope"));
store.setUuid((String)params.get("uuid"));
store.setUrl((String)params.get("url"));
store.setRole(DataStoreRole.getRole((String)params.get("role")));
store = imageStoreDao.persist(store);
return store;
}
@ -68,6 +70,7 @@ public class ImageStoreHelper {
store.setScope((ScopeType)params.get("scope"));
store.setUuid((String)params.get("uuid"));
store.setUrl((String)params.get("url"));
store.setRole(DataStoreRole.getRole((String)params.get("role")));
store = imageStoreDao.persist(store);
// persist details

View File

@ -31,5 +31,6 @@ public interface ImageStoreProviderManager {
List<DataStore> listImageStores();
List<DataStore> listImageStoresByScope(ZoneScope scope);
List<DataStore> listImageStoreByProvider(String provider);
List<DataStore> listImageCacheStores(Scope scope);
boolean registerDriver(String uuid, ImageStoreDriver driver);
}

View File

@ -20,12 +20,12 @@ package org.apache.cloudstack.storage.volume;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.motion.DataMotionService;
import org.apache.cloudstack.storage.volume.VolumeServiceImpl.CreateBaseImageResult;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

View File

@ -24,6 +24,7 @@ import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
@ -40,7 +41,6 @@ import org.apache.cloudstack.storage.datastore.DataObjectManager;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
import org.apache.cloudstack.storage.motion.DataMotionService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -52,7 +52,6 @@ import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;

View File

@ -83,6 +83,7 @@ public class CloudStackImageStoreProviderImpl implements ImageStoreProvider {
public Set<DataStoreProviderType> getTypes() {
Set<DataStoreProviderType> types = new HashSet<DataStoreProviderType>();
types.add(DataStoreProviderType.IMAGE);
types.add(DataStoreProviderType.ImageCache);
return types;
}

View File

@ -42,6 +42,7 @@ import javax.naming.ConfigurationException;
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.CreateCacheStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
@ -1966,6 +1967,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
params.put("details", details);
params.put("scope", scopeType);
params.put("providerName", storeProvider.getName());
params.put("role", DataStoreRole.Image);
DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle();
DataStore store = null;
@ -2017,6 +2019,74 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
txn.commit();
return true;
}
@Override
public ImageStore createCacheStore(CreateCacheStoreCmd cmd) {
String providerName = cmd.getProviderName();
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
if (storeProvider == null) {
storeProvider = _dataStoreProviderMgr.getDefaultCacheDataStoreProvider();
if (storeProvider == null) {
throw new InvalidParameterValueException("can't find cache store provider: " + providerName);
}
}
Long dcId = cmd.getZoneId();
ScopeType scopeType = null;
String scope = cmd.getScope();
if (scope != null) {
try {
scopeType = Enum.valueOf(ScopeType.class, scope.toUpperCase());
} catch (Exception e) {
throw new InvalidParameterValueException("invalid scope" + scope);
}
if (scopeType != ScopeType.ZONE) {
throw new InvalidParameterValueException("Only zone wide cache storage is supported");
}
}
if (scopeType == ScopeType.ZONE && dcId == null) {
throw new InvalidParameterValueException("zone id can't be null, if scope is zone");
}
// Check if the zone exists in the system
DataCenterVO zone = _dcDao.findById(dcId);
if (zone == null) {
throw new InvalidParameterValueException("Can't find zone by id " + dcId);
}
Account account = UserContext.current().getCaller();
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
PermissionDeniedException ex = new PermissionDeniedException(
"Cannot perform this operation, Zone with specified id is currently disabled");
ex.addProxyObject(zone, dcId, "dcId");
throw ex;
}
Map<String, Object> params = new HashMap<String, Object>();
params.put("zoneId", dcId);
params.put("url", cmd.getUrl());
params.put("name", cmd.getUrl());
params.put("details", cmd.getDetails());
params.put("scope", scopeType);
params.put("providerName", storeProvider.getName());
params.put("role", DataStoreRole.ImageCache);
DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle();
DataStore store = null;
try {
store = lifeCycle.initialize(params);
} catch (Exception e) {
s_logger.debug("Failed to add data store", e);
throw new CloudRuntimeException("Failed to add data store", e);
}
return (ImageStore) _dataStoreMgr.getDataStore(store.getId(), DataStoreRole.ImageCache);
}
}

View File

@ -95,6 +95,7 @@ known_categories = {
'InstanceGroup': 'VM Group',
'StorageMaintenance': 'Storage Pool',
'StoragePool': 'Storage Pool',
'CacheStore': 'Storage Pool',
'StorageProvider': 'Storage Pool',
'SecurityGroup': 'Security Group',
'SSH': 'SSH',