mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-6170
This commit is contained in:
parent
bbaec7bae8
commit
b06e66c50a
@ -27,6 +27,7 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||||||
import org.apache.cloudstack.api.BaseCmd;
|
import org.apache.cloudstack.api.BaseCmd;
|
||||||
import org.apache.cloudstack.api.Parameter;
|
import org.apache.cloudstack.api.Parameter;
|
||||||
import org.apache.cloudstack.api.ServerApiException;
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||||
import org.apache.cloudstack.api.response.DomainResponse;
|
import org.apache.cloudstack.api.response.DomainResponse;
|
||||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||||
|
|
||||||
@ -117,6 +118,21 @@ public class CreateServiceOfferingCmd extends BaseCmd {
|
|||||||
@Parameter(name = ApiConstants.IOPS_WRITE_RATE, type = CommandType.LONG, required = false, description = "io requests write rate of the disk offering")
|
@Parameter(name = ApiConstants.IOPS_WRITE_RATE, type = CommandType.LONG, required = false, description = "io requests write rate of the disk offering")
|
||||||
private Long iopsWriteRate;
|
private Long iopsWriteRate;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.CUSTOMIZED_IOPS, type = CommandType.BOOLEAN, required = false, description = "whether compute offering iops is custom or not")
|
||||||
|
private Boolean customizedIops;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, required = false, description = "min iops of the compute offering")
|
||||||
|
private Long minIops;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, required = false, description = "max iops of the compute offering")
|
||||||
|
private Long maxIops;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE,
|
||||||
|
type = CommandType.INTEGER,
|
||||||
|
required = false,
|
||||||
|
description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)")
|
||||||
|
private Integer hypervisorSnapshotReserve;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -215,6 +231,22 @@ public class CreateServiceOfferingCmd extends BaseCmd {
|
|||||||
return iopsWriteRate;
|
return iopsWriteRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isCustomizedIops() {
|
||||||
|
return customizedIops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getMinIops() {
|
||||||
|
return minIops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getMaxIops() {
|
||||||
|
return maxIops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHypervisorSnapshotReserve() {
|
||||||
|
return hypervisorSnapshotReserve;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.storage.to;
|
package org.apache.cloudstack.storage.to;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.DataStoreTO;
|
import com.cloud.agent.api.to.DataStoreTO;
|
||||||
@ -23,6 +25,16 @@ import com.cloud.storage.DataStoreRole;
|
|||||||
import com.cloud.storage.Storage.StoragePoolType;
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
|
||||||
public class PrimaryDataStoreTO implements DataStoreTO {
|
public class PrimaryDataStoreTO implements DataStoreTO {
|
||||||
|
public static final String MANAGED = PrimaryDataStore.MANAGED;
|
||||||
|
public static final String STORAGE_HOST = PrimaryDataStore.STORAGE_HOST;
|
||||||
|
public static final String MANAGED_STORE_TARGET = PrimaryDataStore.MANAGED_STORE_TARGET;
|
||||||
|
public static final String MANAGED_STORE_TARGET_ROOT_VOLUME = PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME;
|
||||||
|
public static final String CHAP_INITIATOR_USERNAME = PrimaryDataStore.CHAP_INITIATOR_USERNAME;
|
||||||
|
public static final String CHAP_INITIATOR_SECRET = PrimaryDataStore.CHAP_INITIATOR_SECRET;
|
||||||
|
public static final String CHAP_TARGET_USERNAME = PrimaryDataStore.CHAP_TARGET_USERNAME;
|
||||||
|
public static final String CHAP_TARGET_SECRET = PrimaryDataStore.CHAP_TARGET_SECRET;
|
||||||
|
public static final String VOLUME_SIZE = PrimaryDataStore.VOLUME_SIZE;
|
||||||
|
|
||||||
private final String uuid;
|
private final String uuid;
|
||||||
private final String name;
|
private final String name;
|
||||||
private String type;
|
private String type;
|
||||||
@ -32,6 +44,7 @@ public class PrimaryDataStoreTO implements DataStoreTO {
|
|||||||
private String path;
|
private String path;
|
||||||
private int port;
|
private int port;
|
||||||
private final String url;
|
private final String url;
|
||||||
|
private Map<String, String> details;
|
||||||
|
|
||||||
public PrimaryDataStoreTO(PrimaryDataStore dataStore) {
|
public PrimaryDataStoreTO(PrimaryDataStore dataStore) {
|
||||||
this.uuid = dataStore.getUuid();
|
this.uuid = dataStore.getUuid();
|
||||||
@ -42,6 +55,7 @@ public class PrimaryDataStoreTO implements DataStoreTO {
|
|||||||
this.setPath(dataStore.getPath());
|
this.setPath(dataStore.getPath());
|
||||||
this.setPort(dataStore.getPort());
|
this.setPort(dataStore.getPort());
|
||||||
this.url = dataStore.getUri();
|
this.url = dataStore.getUri();
|
||||||
|
this.details = dataStore.getDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
@ -58,6 +72,10 @@ public class PrimaryDataStoreTO implements DataStoreTO {
|
|||||||
return this.url;
|
return this.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getDetails() {
|
||||||
|
return this.details;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,8 @@ import com.cloud.agent.api.to.VirtualMachineTO;
|
|||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
|
|
||||||
public interface DataMotionService {
|
public interface DataMotionService {
|
||||||
|
void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
|
||||||
|
|
||||||
void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
|
void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
|
||||||
|
|
||||||
void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
|
void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
|
||||||
|
|||||||
@ -30,6 +30,8 @@ public interface DataMotionStrategy {
|
|||||||
|
|
||||||
StrategyPriority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
|
StrategyPriority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
|
||||||
|
|
||||||
|
Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
|
||||||
|
|
||||||
Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
|
Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
|
||||||
|
|
||||||
Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
|
Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
||||||
|
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
@ -25,6 +27,16 @@ import com.cloud.storage.Storage.StoragePoolType;
|
|||||||
import com.cloud.storage.StoragePool;
|
import com.cloud.storage.StoragePool;
|
||||||
|
|
||||||
public interface PrimaryDataStoreInfo extends StoragePool {
|
public interface PrimaryDataStoreInfo extends StoragePool {
|
||||||
|
static final String MANAGED = "managed";
|
||||||
|
static final String STORAGE_HOST= "storageHost";
|
||||||
|
static final String MANAGED_STORE_TARGET = "managedStoreTarget";
|
||||||
|
static final String MANAGED_STORE_TARGET_ROOT_VOLUME = "managedStoreTargetRootVolume";
|
||||||
|
static final String CHAP_INITIATOR_USERNAME = "chapInitiatorUsername";
|
||||||
|
static final String CHAP_INITIATOR_SECRET = "chapInitiatorSecret";
|
||||||
|
static final String CHAP_TARGET_USERNAME = "chapTargetUsername";
|
||||||
|
static final String CHAP_TARGET_SECRET = "chapTargetSecret";
|
||||||
|
static final String VOLUME_SIZE = "volumeSize";
|
||||||
|
|
||||||
boolean isHypervisorSupported(HypervisorType hypervisor);
|
boolean isHypervisorSupported(HypervisorType hypervisor);
|
||||||
|
|
||||||
boolean isLocalStorageSupported();
|
boolean isLocalStorageSupported();
|
||||||
@ -37,5 +49,11 @@ public interface PrimaryDataStoreInfo extends StoragePool {
|
|||||||
@Override
|
@Override
|
||||||
StoragePoolType getPoolType();
|
StoragePoolType getPoolType();
|
||||||
|
|
||||||
|
boolean isManaged();
|
||||||
|
|
||||||
|
void setDetails(Map<String, String> details);
|
||||||
|
|
||||||
|
Map<String, String> getDetails();
|
||||||
|
|
||||||
PrimaryDataStoreLifeCycle getLifeCycle();
|
PrimaryDataStoreLifeCycle getLifeCycle();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,11 @@ public interface VolumeService {
|
|||||||
|
|
||||||
VolumeEntity getVolumeEntity(long volumeId);
|
VolumeEntity getVolumeEntity(long volumeId);
|
||||||
|
|
||||||
AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template);
|
AsyncCallFuture<VolumeApiResult> createManagedStorageAndVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId,
|
||||||
|
TemplateInfo srcTemplateInfo, long destHostId);
|
||||||
|
|
||||||
|
AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId,
|
||||||
|
TemplateInfo template);
|
||||||
|
|
||||||
AsyncCallFuture<VolumeApiResult> copyVolume(VolumeInfo srcVolume, DataStore destStore);
|
AsyncCallFuture<VolumeApiResult> copyVolume(VolumeInfo srcVolume, DataStore destStore);
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationSer
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
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.DataStoreManager;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||||
@ -1113,8 +1114,24 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||||||
future = volService.createVolumeAsync(volume, destPool);
|
future = volService.createVolumeAsync(volume, destPool);
|
||||||
} else {
|
} else {
|
||||||
TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image);
|
TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image);
|
||||||
|
|
||||||
|
PrimaryDataStore primaryDataStore = (PrimaryDataStore)destPool;
|
||||||
|
|
||||||
|
if (primaryDataStore.isManaged()) {
|
||||||
|
DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
|
||||||
|
HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
|
||||||
|
|
||||||
|
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
|
||||||
|
updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType);
|
||||||
|
|
||||||
|
long hostId = vm.getVirtualMachine().getHostId();
|
||||||
|
|
||||||
|
future = volService.createManagedStorageAndVolumeFromTemplateAsync(volume, destPool.getId(), templ, hostId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
|
future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VolumeApiResult result = null;
|
VolumeApiResult result = null;
|
||||||
try {
|
try {
|
||||||
result = future.get();
|
result = future.get();
|
||||||
|
|||||||
@ -46,6 +46,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
|
||||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.storage.RemoteHostEndPoint;
|
||||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
||||||
|
|
||||||
@ -94,15 +95,17 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
protected boolean needCacheStorage(DataObject srcData, DataObject destData) {
|
protected boolean needCacheStorage(DataObject srcData, DataObject destData) {
|
||||||
DataTO srcTO = srcData.getTO();
|
DataTO srcTO = srcData.getTO();
|
||||||
DataTO destTO = destData.getTO();
|
|
||||||
DataStoreTO srcStoreTO = srcTO.getDataStore();
|
DataStoreTO srcStoreTO = srcTO.getDataStore();
|
||||||
DataStoreTO destStoreTO = destTO.getDataStore();
|
|
||||||
if (srcStoreTO instanceof NfsTO || srcStoreTO.getRole() == DataStoreRole.ImageCache) {
|
if (srcStoreTO instanceof NfsTO || srcStoreTO.getRole() == DataStoreRole.ImageCache) {
|
||||||
//||
|
//||
|
||||||
// (srcStoreTO instanceof PrimaryDataStoreTO && ((PrimaryDataStoreTO)srcStoreTO).getPoolType() == StoragePoolType.NetworkFilesystem)) {
|
// (srcStoreTO instanceof PrimaryDataStoreTO && ((PrimaryDataStoreTO)srcStoreTO).getPoolType() == StoragePoolType.NetworkFilesystem)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataTO destTO = destData.getTO();
|
||||||
|
DataStoreTO destStoreTO = destTO.getDataStore();
|
||||||
|
|
||||||
if (destStoreTO instanceof NfsTO || destStoreTO.getRole() == DataStoreRole.ImageCache) {
|
if (destStoreTO instanceof NfsTO || destStoreTO.getRole() == DataStoreRole.ImageCache) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -147,7 +150,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
return selectedScope;
|
return selectedScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Answer copyObject(DataObject srcData, DataObject destData) {
|
protected Answer copyObject(DataObject srcData, DataObject destData, Host destHost) {
|
||||||
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||||
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||||
Answer answer = null;
|
Answer answer = null;
|
||||||
@ -160,7 +163,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopyCommand cmd = new CopyCommand(srcForCopy.getTO(), destData.getTO(), _primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
|
CopyCommand cmd = new CopyCommand(srcForCopy.getTO(), destData.getTO(), _primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
|
||||||
EndPoint ep = selector.select(srcForCopy, destData);
|
EndPoint ep = destHost != null ? RemoteHostEndPoint.getHypervisorHostEndPoint(destHost) : selector.select(srcForCopy, destData);
|
||||||
if (ep == null) {
|
if (ep == null) {
|
||||||
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
|
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
|
||||||
s_logger.error(errMsg);
|
s_logger.error(errMsg);
|
||||||
@ -193,6 +196,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Answer copyObject(DataObject srcData, DataObject destData) {
|
||||||
|
return copyObject(srcData, destData, null);
|
||||||
|
}
|
||||||
|
|
||||||
protected DataObject cacheSnapshotChain(SnapshotInfo snapshot, Scope scope) {
|
protected DataObject cacheSnapshotChain(SnapshotInfo snapshot, Scope scope) {
|
||||||
DataObject leafData = null;
|
DataObject leafData = null;
|
||||||
DataStore store = cacheMgr.getCacheStorage(snapshot, scope);
|
DataStore store = cacheMgr.getCacheStorage(snapshot, scope);
|
||||||
@ -392,8 +399,9 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: destHost is currently only used if the copyObject method is invoked
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
Answer answer = null;
|
Answer answer = null;
|
||||||
String errMsg = null;
|
String errMsg = null;
|
||||||
try {
|
try {
|
||||||
@ -416,7 +424,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
} else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) {
|
} else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) {
|
||||||
answer = copySnapshot(srcData, destData);
|
answer = copySnapshot(srcData, destData);
|
||||||
} else {
|
} else {
|
||||||
answer = copyObject(srcData, destData);
|
answer = copyObject(srcData, destData, destHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (answer != null && !answer.getResult()) {
|
if (answer != null && !answer.getResult()) {
|
||||||
@ -432,6 +440,11 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
return copyAsync(srcData, destData, null, callback);
|
||||||
|
}
|
||||||
|
|
||||||
@DB
|
@DB
|
||||||
protected Answer createTemplateFromSnapshot(DataObject srcData, DataObject destData) {
|
protected Answer createTemplateFromSnapshot(DataObject srcData, DataObject destData) {
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public class DataMotionServiceImpl implements DataMotionService {
|
|||||||
StorageStrategyFactory storageStrategyFactory;
|
StorageStrategyFactory storageStrategyFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
if (srcData.getDataStore() == null || destData.getDataStore() == null) {
|
if (srcData.getDataStore() == null || destData.getDataStore() == null) {
|
||||||
throw new CloudRuntimeException("can't find data store");
|
throw new CloudRuntimeException("can't find data store");
|
||||||
}
|
}
|
||||||
@ -65,7 +65,12 @@ public class DataMotionServiceImpl implements DataMotionService {
|
|||||||
destData.getType().name() + " '" + destData.getUuid() + "'");
|
destData.getType().name() + " '" + destData.getUuid() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
strategy.copyAsync(srcData, destData, callback);
|
strategy.copyAsync(srcData, destData, destHost, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
copyAsync(srcData, destData, null, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||||
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
||||||
@ -299,6 +300,20 @@ public class TemplateObject implements TemplateInfo {
|
|||||||
if (dataStore == null) {
|
if (dataStore == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// managed primary data stores should not have an install path
|
||||||
|
if (dataStore instanceof PrimaryDataStore) {
|
||||||
|
PrimaryDataStore primaryDataStore = (PrimaryDataStore)dataStore;
|
||||||
|
|
||||||
|
Map<String, String> details = primaryDataStore.getDetails();
|
||||||
|
|
||||||
|
boolean managed = details != null && Boolean.parseBoolean(details.get(PrimaryDataStore.MANAGED));
|
||||||
|
|
||||||
|
if (managed) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DataObjectInStore obj = objectInStoreMgr.findObject(this, dataStore);
|
DataObjectInStore obj = objectInStoreMgr.findObject(this, dataStore);
|
||||||
return obj.getInstallPath();
|
return obj.getInstallPath();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,11 @@ public class MockStorageMotionStrategy implements DataMotionStrategy {
|
|||||||
return StrategyPriority.HIGHEST;
|
return StrategyPriority.HIGHEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
CopyCmdAnswer answer = null;
|
CopyCmdAnswer answer = null;
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import java.io.File;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@ -67,6 +68,7 @@ import com.cloud.utils.storage.encoding.EncodingType;
|
|||||||
|
|
||||||
public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
||||||
private static final Logger s_logger = Logger.getLogger(PrimaryDataStoreImpl.class);
|
private static final Logger s_logger = Logger.getLogger(PrimaryDataStoreImpl.class);
|
||||||
|
|
||||||
protected PrimaryDataStoreDriver driver;
|
protected PrimaryDataStoreDriver driver;
|
||||||
protected StoragePoolVO pdsv;
|
protected StoragePoolVO pdsv;
|
||||||
@Inject
|
@Inject
|
||||||
@ -86,6 +88,7 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private VolumeDao volumeDao;
|
private VolumeDao volumeDao;
|
||||||
|
private Map<String, String> _details;
|
||||||
|
|
||||||
public PrimaryDataStoreImpl() {
|
public PrimaryDataStoreImpl() {
|
||||||
|
|
||||||
@ -135,6 +138,16 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
|||||||
return pdsv.getId();
|
return pdsv.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDetails(Map<String, String> details) {
|
||||||
|
_details = details;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getDetails() {
|
||||||
|
return _details;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
String path = pdsv.getPath().replaceFirst("/*", "");
|
String path = pdsv.getPath().replaceFirst("/*", "");
|
||||||
@ -222,10 +235,15 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isManaged() {
|
||||||
|
return pdsv.isManaged();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataObject create(DataObject obj) {
|
public DataObject create(DataObject obj) {
|
||||||
// create template on primary storage
|
// create template on primary storage
|
||||||
if (obj.getType() == DataObjectType.TEMPLATE) {
|
if (obj.getType() == DataObjectType.TEMPLATE && !isManaged()) {
|
||||||
try {
|
try {
|
||||||
String templateIdPoolIdString = "templateId:" + obj.getId() + "poolId:" + getId();
|
String templateIdPoolIdString = "templateId:" + obj.getId() + "poolId:" + getId();
|
||||||
VMTemplateStoragePoolVO templateStoragePoolRef;
|
VMTemplateStoragePoolVO templateStoragePoolRef;
|
||||||
|
|||||||
@ -85,7 +85,7 @@ public class DefaultHostListener implements HypervisorHostListener {
|
|||||||
poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes());
|
poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes());
|
||||||
primaryStoreDao.update(pool.getId(), poolVO);
|
primaryStoreDao.update(pool.getId(), poolVO);
|
||||||
|
|
||||||
s_logger.info("Connection established between " + pool + " host + " + hostId);
|
s_logger.info("Connection established between storage pool " + pool + " and host " + hostId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ package org.apache.cloudstack.storage.volume;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
|
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
|
||||||
@ -60,6 +62,7 @@ import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
|
|||||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.storage.ListVolumeAnswer;
|
import com.cloud.agent.api.storage.ListVolumeAnswer;
|
||||||
@ -72,6 +75,7 @@ import com.cloud.event.EventTypes;
|
|||||||
import com.cloud.event.UsageEventUtils;
|
import com.cloud.event.UsageEventUtils;
|
||||||
import com.cloud.exception.ConcurrentOperationException;
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
import com.cloud.exception.ResourceAllocationException;
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.storage.ScopeType;
|
import com.cloud.storage.ScopeType;
|
||||||
@ -122,6 +126,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
VolumeDao _volumeDao;
|
VolumeDao _volumeDao;
|
||||||
@Inject
|
@Inject
|
||||||
EndPointSelector _epSelector;
|
EndPointSelector _epSelector;
|
||||||
|
@Inject
|
||||||
|
HostDao _hostDao;
|
||||||
|
|
||||||
public VolumeServiceImpl() {
|
public VolumeServiceImpl() {
|
||||||
}
|
}
|
||||||
@ -349,6 +355,39 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ManagedCreateBaseImageContext<T> extends AsyncRpcContext<T> {
|
||||||
|
private final VolumeInfo _volumeInfo;
|
||||||
|
private final PrimaryDataStore _primaryDataStore;
|
||||||
|
private final TemplateInfo _templateInfo;
|
||||||
|
private final AsyncCallFuture<VolumeApiResult> _future;
|
||||||
|
|
||||||
|
public ManagedCreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volumeInfo,
|
||||||
|
PrimaryDataStore primaryDatastore, TemplateInfo templateInfo, AsyncCallFuture<VolumeApiResult> future) {
|
||||||
|
super(callback);
|
||||||
|
|
||||||
|
_volumeInfo = volumeInfo;
|
||||||
|
_primaryDataStore = primaryDatastore;
|
||||||
|
_templateInfo = templateInfo;
|
||||||
|
_future = future;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VolumeInfo getVolumeInfo() {
|
||||||
|
return _volumeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrimaryDataStore getPrimaryDataStore() {
|
||||||
|
return _primaryDataStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateInfo getTemplateInfo() {
|
||||||
|
return _templateInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCallFuture<VolumeApiResult> getFuture() {
|
||||||
|
return _future;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CreateBaseImageContext<T> extends AsyncRpcContext<T> {
|
class CreateBaseImageContext<T> extends AsyncRpcContext<T> {
|
||||||
private final VolumeInfo volume;
|
private final VolumeInfo volume;
|
||||||
private final PrimaryDataStore dataStore;
|
private final PrimaryDataStore dataStore;
|
||||||
@ -411,7 +450,6 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
|
|
||||||
@DB
|
@DB
|
||||||
protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture<VolumeApiResult> future) {
|
protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture<VolumeApiResult> future) {
|
||||||
|
|
||||||
DataObject templateOnPrimaryStoreObj = dataStore.create(template);
|
DataObject templateOnPrimaryStoreObj = dataStore.create(template);
|
||||||
|
|
||||||
VMTemplateStoragePoolVO templatePoolRef = _tmpltPoolDao.findByPoolTemplate(dataStore.getId(), template.getId());
|
VMTemplateStoragePoolVO templatePoolRef = _tmpltPoolDao.findByPoolTemplate(dataStore.getId(), template.getId());
|
||||||
@ -476,6 +514,37 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
|
||||||
|
ManagedCreateBaseImageContext<VolumeApiResult> context) {
|
||||||
|
CopyCommandResult result = callback.getResult();
|
||||||
|
VolumeInfo volumeInfo = context.getVolumeInfo();
|
||||||
|
VolumeApiResult res = new VolumeApiResult(volumeInfo);
|
||||||
|
|
||||||
|
if (result.isSuccess()) {
|
||||||
|
// volumeInfo.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||||
|
|
||||||
|
VolumeVO volume = volDao.findById(volumeInfo.getId());
|
||||||
|
CopyCmdAnswer answer = (CopyCmdAnswer)result.getAnswer();
|
||||||
|
TemplateObjectTO templateObjectTo = (TemplateObjectTO)answer.getNewData();
|
||||||
|
|
||||||
|
volume.setPath(templateObjectTo.getPath());
|
||||||
|
volume.setFormat(templateObjectTo.getFormat());
|
||||||
|
|
||||||
|
volDao.update(volume.getId(), volume);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
volumeInfo.processEvent(Event.DestroyRequested);
|
||||||
|
|
||||||
|
res.setResult(result.getResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncCallFuture<VolumeApiResult> future = context.getFuture();
|
||||||
|
|
||||||
|
future.complete(res);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@DB
|
@DB
|
||||||
protected Void copyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
|
protected Void copyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
|
||||||
CopyCommandResult result = callback.getResult();
|
CopyCommandResult result = callback.getResult();
|
||||||
@ -577,6 +646,91 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AsyncCallFuture<VolumeApiResult> createManagedStorageAndVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId,
|
||||||
|
TemplateInfo srcTemplateInfo, long destHostId) {
|
||||||
|
PrimaryDataStore destPrimaryDataStore = dataStoreMgr.getPrimaryDataStore(destDataStoreId);
|
||||||
|
TemplateInfo destTemplateInfo = (TemplateInfo)destPrimaryDataStore.create(srcTemplateInfo);
|
||||||
|
Host destHost = _hostDao.findById(destHostId);
|
||||||
|
|
||||||
|
if (destHost == null) {
|
||||||
|
throw new CloudRuntimeException("Destinatin host should not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// must call driver to have a volume created
|
||||||
|
AsyncCallFuture<VolumeApiResult> createVolumeFuture = createVolumeAsync(volumeInfo, destPrimaryDataStore);
|
||||||
|
|
||||||
|
VolumeApiResult createVolumeResult = createVolumeFuture.get();
|
||||||
|
|
||||||
|
if (createVolumeResult.isFailed()) {
|
||||||
|
throw new CloudRuntimeException("Creation of a volume failed: " + createVolumeResult.getResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
// refresh the volume from the DB
|
||||||
|
volumeInfo = volFactory.getVolume(volumeInfo.getId(), destPrimaryDataStore);
|
||||||
|
|
||||||
|
connectVolumeToHost(volumeInfo, destHost, destPrimaryDataStore);
|
||||||
|
|
||||||
|
ManagedCreateBaseImageContext<CreateCmdResult> context = new ManagedCreateBaseImageContext<CreateCmdResult>(null, volumeInfo,
|
||||||
|
destPrimaryDataStore, srcTemplateInfo, future);
|
||||||
|
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||||
|
caller.setCallback(caller.getTarget().managedCopyBaseImageCallback(null, null)).setContext(context);
|
||||||
|
|
||||||
|
Map<String, String> details = new HashMap<String, String>();
|
||||||
|
|
||||||
|
details.put(PrimaryDataStore.MANAGED, Boolean.TRUE.toString());
|
||||||
|
details.put(PrimaryDataStore.STORAGE_HOST, destPrimaryDataStore.getHostAddress());
|
||||||
|
// for managed storage, the storage repository (XenServer) or datastore (ESX) name is based off of the iScsiName property of a volume
|
||||||
|
details.put(PrimaryDataStore.MANAGED_STORE_TARGET, volumeInfo.get_iScsiName());
|
||||||
|
details.put(PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME, volumeInfo.getName());
|
||||||
|
details.put(PrimaryDataStore.VOLUME_SIZE, String.valueOf(volumeInfo.getSize()));
|
||||||
|
|
||||||
|
ChapInfo chapInfo = getChapInfo(volumeInfo, destPrimaryDataStore);
|
||||||
|
|
||||||
|
if (chapInfo != null) {
|
||||||
|
details.put(PrimaryDataStore.CHAP_INITIATOR_USERNAME, chapInfo.getInitiatorUsername());
|
||||||
|
details.put(PrimaryDataStore.CHAP_INITIATOR_SECRET, chapInfo.getInitiatorSecret());
|
||||||
|
details.put(PrimaryDataStore.CHAP_TARGET_USERNAME, chapInfo.getTargetUsername());
|
||||||
|
details.put(PrimaryDataStore.CHAP_TARGET_SECRET, chapInfo.getTargetSecret());
|
||||||
|
}
|
||||||
|
|
||||||
|
destPrimaryDataStore.setDetails(details);
|
||||||
|
|
||||||
|
motionSrv.copyAsync(srcTemplateInfo, destTemplateInfo, destHost, caller);
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
String errMsg = t.toString();
|
||||||
|
|
||||||
|
volumeInfo.processEvent(Event.DestroyRequested);
|
||||||
|
|
||||||
|
disconnectVolumeFromHost(volumeInfo, destHost, destPrimaryDataStore);
|
||||||
|
|
||||||
|
try {
|
||||||
|
AsyncCallFuture<VolumeApiResult> expungeVolumeFuture = expungeVolumeAsync(volumeInfo);
|
||||||
|
|
||||||
|
VolumeApiResult expungeVolumeResult = expungeVolumeFuture.get();
|
||||||
|
|
||||||
|
if (expungeVolumeResult.isFailed()) {
|
||||||
|
errMsg += " : Failed to expunge a volume that was created";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
errMsg += " : " + ex.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeApiResult result = new VolumeApiResult(volumeInfo);
|
||||||
|
|
||||||
|
result.setResult(errMsg);
|
||||||
|
|
||||||
|
future.complete(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
@DB
|
@DB
|
||||||
@Override
|
@Override
|
||||||
public AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template) {
|
public AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template) {
|
||||||
|
|||||||
@ -42,6 +42,11 @@ public class SimulatorDataMotionStrategy implements DataMotionStrategy {
|
|||||||
return StrategyPriority.HYPERVISOR;
|
return StrategyPriority.HYPERVISOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
CopyCommandResult result = new CopyCommandResult("something", null);
|
CopyCommandResult result = new CopyCommandResult("something", null);
|
||||||
|
|||||||
@ -85,6 +85,11 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy {
|
|||||||
return StrategyPriority.CANT_HANDLE;
|
return StrategyPriority.CANT_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
CopyCommandResult result = new CopyCommandResult(null, null);
|
CopyCommandResult result = new CopyCommandResult(null, null);
|
||||||
|
|||||||
@ -1869,18 +1869,23 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
return prepareManagedStorage(conn, details, null, vdiNameLabel);
|
return prepareManagedStorage(conn, details, null, vdiNameLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected VDI prepareManagedStorage(Connection conn, Map<String, String> details, String path, String vdiNameLabel) throws Exception {
|
protected SR prepareManagedSr(Connection conn, Map<String, String> details) {
|
||||||
String iScsiName = details.get(DiskTO.IQN);
|
String iScsiName = details.get(DiskTO.IQN);
|
||||||
String storageHost = details.get(DiskTO.STORAGE_HOST);
|
String storageHost = details.get(DiskTO.STORAGE_HOST);
|
||||||
String chapInitiatorUsername = details.get(DiskTO.CHAP_INITIATOR_USERNAME);
|
String chapInitiatorUsername = details.get(DiskTO.CHAP_INITIATOR_USERNAME);
|
||||||
String chapInitiatorSecret = details.get(DiskTO.CHAP_INITIATOR_SECRET);
|
String chapInitiatorSecret = details.get(DiskTO.CHAP_INITIATOR_SECRET);
|
||||||
Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE));
|
|
||||||
|
|
||||||
SR sr = getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true);
|
return getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected VDI prepareManagedStorage(Connection conn, Map<String, String> details, String path, String vdiNameLabel) throws Exception {
|
||||||
|
SR sr = prepareManagedSr(conn, details);
|
||||||
|
|
||||||
VDI vdi = getVDIbyUuid(conn, path, false);
|
VDI vdi = getVDIbyUuid(conn, path, false);
|
||||||
|
|
||||||
if (vdi == null) {
|
if (vdi == null) {
|
||||||
|
Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE));
|
||||||
|
|
||||||
vdi = createVdi(sr, vdiNameLabel, volumeSize);
|
vdi = createVdi(sr, vdiNameLabel, volumeSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,6 +59,7 @@ import org.apache.cloudstack.storage.command.ForgetObjectCmd;
|
|||||||
import org.apache.cloudstack.storage.command.IntroduceObjectAnswer;
|
import org.apache.cloudstack.storage.command.IntroduceObjectAnswer;
|
||||||
import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
|
import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
|
||||||
import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
|
import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
|
||||||
|
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
@ -887,58 +888,121 @@ public class XenServerStorageProcessor implements StorageProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
|
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
|
||||||
DataTO srcData = cmd.getSrcTO();
|
DataTO srcDataTo = cmd.getSrcTO();
|
||||||
DataTO destData = cmd.getDestTO();
|
DataTO destDataTo = cmd.getDestTO();
|
||||||
int wait = cmd.getWait();
|
int wait = cmd.getWait();
|
||||||
DataStoreTO srcStore = srcData.getDataStore();
|
DataStoreTO srcDataStoreTo = srcDataTo.getDataStore();
|
||||||
try {
|
|
||||||
if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) {
|
|
||||||
NfsTO srcImageStore = (NfsTO)srcStore;
|
|
||||||
TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData;
|
|
||||||
String storeUrl = srcImageStore.getUrl();
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ((srcDataStoreTo instanceof NfsTO) && (srcDataTo.getObjectType() == DataObjectType.TEMPLATE)) {
|
||||||
|
NfsTO srcImageStore = (NfsTO)srcDataStoreTo;
|
||||||
|
TemplateObjectTO srcTemplateObjectTo = (TemplateObjectTO)srcDataTo;
|
||||||
|
String storeUrl = srcImageStore.getUrl();
|
||||||
URI uri = new URI(storeUrl);
|
URI uri = new URI(storeUrl);
|
||||||
String tmplpath = uri.getHost() + ":" + uri.getPath() + "/" + srcData.getPath();
|
String tmplPath = uri.getHost() + ":" + uri.getPath() + "/" + srcDataTo.getPath();
|
||||||
String poolName = destData.getDataStore().getUuid();
|
DataStoreTO destDataStoreTo = destDataTo.getDataStore();
|
||||||
|
|
||||||
|
boolean managed = false;
|
||||||
|
String storageHost = null;
|
||||||
|
String managedStoragePoolName = null;
|
||||||
|
String managedStoragePoolRootVolumeName = null;
|
||||||
|
String managedStoragePoolRootVolumeSize = null;
|
||||||
|
String chapInitiatorUsername = null;
|
||||||
|
String chapInitiatorSecret = null;
|
||||||
|
|
||||||
|
if (destDataStoreTo instanceof PrimaryDataStoreTO) {
|
||||||
|
PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO)destDataStoreTo;
|
||||||
|
|
||||||
|
Map<String, String> details = destPrimaryDataStoreTo.getDetails();
|
||||||
|
|
||||||
|
if (details != null) {
|
||||||
|
managed = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
|
||||||
|
|
||||||
|
if (managed) {
|
||||||
|
storageHost = details.get(PrimaryDataStoreTO.STORAGE_HOST);
|
||||||
|
managedStoragePoolName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET);
|
||||||
|
managedStoragePoolRootVolumeName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET_ROOT_VOLUME);
|
||||||
|
managedStoragePoolRootVolumeSize = details.get(PrimaryDataStoreTO.VOLUME_SIZE);
|
||||||
|
chapInitiatorUsername = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_USERNAME);
|
||||||
|
chapInitiatorSecret = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_SECRET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connection conn = hypervisorResource.getConnection();
|
Connection conn = hypervisorResource.getConnection();
|
||||||
|
|
||||||
SR poolsr = null;
|
final SR sr;
|
||||||
Set<SR> srs = SR.getByNameLabel(conn, poolName);
|
|
||||||
|
if (managed) {
|
||||||
|
Map<String, String> details = new HashMap<String, String>();
|
||||||
|
|
||||||
|
details.put(DiskTO.STORAGE_HOST, storageHost);
|
||||||
|
details.put(DiskTO.IQN, managedStoragePoolName);
|
||||||
|
details.put(DiskTO.VOLUME_SIZE, managedStoragePoolRootVolumeSize);
|
||||||
|
details.put(DiskTO.CHAP_INITIATOR_USERNAME, chapInitiatorUsername);
|
||||||
|
details.put(DiskTO.CHAP_INITIATOR_SECRET, chapInitiatorSecret);
|
||||||
|
|
||||||
|
sr = hypervisorResource.prepareManagedSr(conn, details);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String srName = destDataStoreTo.getUuid();
|
||||||
|
Set<SR> srs = SR.getByNameLabel(conn, srName);
|
||||||
|
|
||||||
if (srs.size() != 1) {
|
if (srs.size() != 1) {
|
||||||
String msg = "There are " + srs.size() + " SRs with same name: " + poolName;
|
String msg = "There are " + srs.size() + " SRs with same name: " + srName;
|
||||||
|
|
||||||
s_logger.warn(msg);
|
s_logger.warn(msg);
|
||||||
|
|
||||||
return new CopyCmdAnswer(msg);
|
return new CopyCmdAnswer(msg);
|
||||||
} else {
|
} else {
|
||||||
poolsr = srs.iterator().next();
|
sr = srs.iterator().next();
|
||||||
}
|
}
|
||||||
String pUuid = poolsr.getUuid(conn);
|
}
|
||||||
boolean isISCSI = IsISCSI(poolsr.getType(conn));
|
|
||||||
String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait);
|
String srUuid = sr.getUuid(conn);
|
||||||
VDI tmpl = getVDIbyUuid(conn, uuid);
|
String tmplUuid = copy_vhd_from_secondarystorage(conn, tmplPath, srUuid, wait);
|
||||||
VDI snapshotvdi = tmpl.snapshot(conn, new HashMap<String, String>());
|
VDI tmplVdi = getVDIbyUuid(conn, tmplUuid);
|
||||||
String snapshotUuid = snapshotvdi.getUuid(conn);
|
|
||||||
snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName());
|
final String uuidToReturn;
|
||||||
String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI);
|
|
||||||
VDI parent = getVDIbyUuid(conn, parentuuid);
|
if (managed) {
|
||||||
Long phySize = parent.getPhysicalUtilisation(conn);
|
uuidToReturn = tmplUuid;
|
||||||
tmpl.destroy(conn);
|
|
||||||
poolsr.scan(conn);
|
tmplVdi.setNameLabel(conn, managedStoragePoolRootVolumeName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VDI snapshotVdi = tmplVdi.snapshot(conn, new HashMap<String, String>());
|
||||||
|
|
||||||
|
uuidToReturn = snapshotVdi.getUuid(conn);
|
||||||
|
|
||||||
|
snapshotVdi.setNameLabel(conn, "Template " + srcTemplateObjectTo.getName());
|
||||||
|
|
||||||
|
tmplVdi.destroy(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
sr.scan(conn);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateObjectTO newVol = new TemplateObjectTO();
|
TemplateObjectTO newVol = new TemplateObjectTO();
|
||||||
newVol.setUuid(snapshotvdi.getUuid(conn));
|
|
||||||
newVol.setPath(newVol.getUuid());
|
newVol.setUuid(uuidToReturn);
|
||||||
|
newVol.setPath(uuidToReturn);
|
||||||
newVol.setFormat(ImageFormat.VHD);
|
newVol.setFormat(ImageFormat.VHD);
|
||||||
|
|
||||||
return new CopyCmdAnswer(newVol);
|
return new CopyCmdAnswer(newVol);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString();
|
String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString();
|
||||||
|
|
||||||
s_logger.warn(msg, e);
|
s_logger.warn(msg, e);
|
||||||
|
|
||||||
return new CopyCmdAnswer(msg);
|
return new CopyCmdAnswer(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CopyCmdAnswer("not implemented yet");
|
return new CopyCmdAnswer("not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,6 +90,11 @@ public class XenServerStorageMotionStrategy implements DataMotionStrategy {
|
|||||||
return StrategyPriority.CANT_HANDLE;
|
return StrategyPriority.CANT_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
CopyCommandResult result = new CopyCommandResult(null, null);
|
CopyCommandResult result = new CopyCommandResult(null, null);
|
||||||
|
|||||||
@ -2016,15 +2016,54 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
|
|
||||||
return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), cpuNumber, memory, cpuSpeed, cmd.getDisplayText(), localStorageRequired,
|
return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), cpuNumber, memory, cpuSpeed, cmd.getDisplayText(), localStorageRequired,
|
||||||
offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner(), cmd.getDetails(),
|
offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner(), cmd.getDetails(),
|
||||||
cmd.getBytesReadRate(), cmd.getBytesWriteRate(), cmd.getIopsReadRate(), cmd.getIopsWriteRate());
|
cmd.isCustomizedIops(), cmd.getMinIops(), cmd.getMaxIops(), cmd.getBytesReadRate(), cmd.getBytesWriteRate(), cmd.getIopsReadRate(), cmd.getIopsWriteRate(),
|
||||||
|
cmd.getHypervisorSnapshotReserve());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vmType, String name, Integer cpu, Integer ramSize, Integer speed,
|
protected ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vmType, String name, Integer cpu, Integer ramSize, Integer speed,
|
||||||
String displayText, boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag,
|
String displayText, boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag,
|
||||||
Integer networkRate, String deploymentPlanner, Map<String, String> details, Long bytesReadRate, Long bytesWriteRate, Long iopsReadRate, Long iopsWriteRate) {
|
Integer networkRate, String deploymentPlanner, Map<String, String> details, Boolean isCustomizedIops, Long minIops, Long maxIops,
|
||||||
|
Long bytesReadRate, Long bytesWriteRate, Long iopsReadRate, Long iopsWriteRate, Integer hypervisorSnapshotReserve) {
|
||||||
tags = StringUtils.cleanupTags(tags);
|
tags = StringUtils.cleanupTags(tags);
|
||||||
ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired,
|
ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired,
|
||||||
false, tags, isSystem, vmType, domainId, hostTag, deploymentPlanner);
|
false, tags, isSystem, vmType, domainId, hostTag, deploymentPlanner);
|
||||||
|
|
||||||
|
if (isCustomizedIops != null) {
|
||||||
|
bytesReadRate = null;
|
||||||
|
bytesWriteRate = null;
|
||||||
|
iopsReadRate = null;
|
||||||
|
iopsWriteRate = null;
|
||||||
|
|
||||||
|
if (isCustomizedIops) {
|
||||||
|
minIops = null;
|
||||||
|
maxIops = null;
|
||||||
|
} else {
|
||||||
|
if (minIops == null && maxIops == null) {
|
||||||
|
minIops = 0L;
|
||||||
|
maxIops = 0L;
|
||||||
|
} else {
|
||||||
|
if (minIops == null || minIops <= 0) {
|
||||||
|
throw new InvalidParameterValueException("The min IOPS must be greater than 0.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxIops == null) {
|
||||||
|
maxIops = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minIops > maxIops) {
|
||||||
|
throw new InvalidParameterValueException("The min IOPS must be less than or equal to the max IOPS.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minIops = null;
|
||||||
|
maxIops = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
offering.setCustomizedIops(isCustomizedIops);
|
||||||
|
offering.setMinIops(minIops);
|
||||||
|
offering.setMaxIops(maxIops);
|
||||||
|
|
||||||
if ((bytesReadRate != null) && (bytesReadRate > 0))
|
if ((bytesReadRate != null) && (bytesReadRate > 0))
|
||||||
offering.setBytesReadRate(bytesReadRate);
|
offering.setBytesReadRate(bytesReadRate);
|
||||||
if ((bytesWriteRate != null) && (bytesWriteRate > 0))
|
if ((bytesWriteRate != null) && (bytesWriteRate > 0))
|
||||||
@ -2034,6 +2073,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
if ((iopsWriteRate != null) && (iopsWriteRate > 0))
|
if ((iopsWriteRate != null) && (iopsWriteRate > 0))
|
||||||
offering.setIopsWriteRate(iopsWriteRate);
|
offering.setIopsWriteRate(iopsWriteRate);
|
||||||
|
|
||||||
|
if (hypervisorSnapshotReserve != null && hypervisorSnapshotReserve < 0) {
|
||||||
|
throw new InvalidParameterValueException("If provided, Hypervisor Snapshot Reserve must be greater than or equal to 0.");
|
||||||
|
}
|
||||||
|
|
||||||
|
offering.setHypervisorSnapshotReserve(hypervisorSnapshotReserve);
|
||||||
|
|
||||||
if ((offering = _serviceOfferingDao.persist(offering)) != null) {
|
if ((offering = _serviceOfferingDao.persist(offering)) != null) {
|
||||||
if (details != null) {
|
if (details != null) {
|
||||||
List<ServiceOfferingDetailsVO> detailsVO = new ArrayList<ServiceOfferingDetailsVO>();
|
List<ServiceOfferingDetailsVO> detailsVO = new ArrayList<ServiceOfferingDetailsVO>();
|
||||||
|
|||||||
@ -136,6 +136,113 @@
|
|||||||
number: true
|
number: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
qosType: {
|
||||||
|
label: 'label.qos.type',
|
||||||
|
docID: 'helpDiskOfferingQoSType',
|
||||||
|
select: function(args) {
|
||||||
|
var items = [];
|
||||||
|
items.push({
|
||||||
|
id: '',
|
||||||
|
description: ''
|
||||||
|
});
|
||||||
|
items.push({
|
||||||
|
id: 'hypervisor',
|
||||||
|
description: 'hypervisor'
|
||||||
|
});
|
||||||
|
items.push({
|
||||||
|
id: 'storage',
|
||||||
|
description: 'storage'
|
||||||
|
});
|
||||||
|
args.response.success({
|
||||||
|
data: items
|
||||||
|
});
|
||||||
|
|
||||||
|
args.$select.change(function() {
|
||||||
|
var $form = $(this).closest('form');
|
||||||
|
var $isCustomizedIops = $form.find('.form-item[rel=isCustomizedIops]');
|
||||||
|
var $minIops = $form.find('.form-item[rel=minIops]');
|
||||||
|
var $maxIops = $form.find('.form-item[rel=maxIops]');
|
||||||
|
var $hypervisorSnapshotReserve = $form.find('.form-item[rel=hypervisorSnapshotReserve]');
|
||||||
|
var $diskBytesReadRate = $form.find('.form-item[rel=diskBytesReadRate]');
|
||||||
|
var $diskBytesWriteRate = $form.find('.form-item[rel=diskBytesWriteRate]');
|
||||||
|
var $diskIopsReadRate = $form.find('.form-item[rel=diskIopsReadRate]');
|
||||||
|
var $diskIopsWriteRate = $form.find('.form-item[rel=diskIopsWriteRate]');
|
||||||
|
|
||||||
|
var qosId = $(this).val();
|
||||||
|
|
||||||
|
if (qosId == 'storage') { // Storage QoS
|
||||||
|
$diskBytesReadRate.hide();
|
||||||
|
$diskBytesWriteRate.hide();
|
||||||
|
$diskIopsReadRate.hide();
|
||||||
|
$diskIopsWriteRate.hide();
|
||||||
|
|
||||||
|
$isCustomizedIops.css('display', 'inline-block');
|
||||||
|
|
||||||
|
if ($isCustomizedIops.find('input[type=checkbox]').is(':checked')) {
|
||||||
|
$minIops.hide();
|
||||||
|
$maxIops.hide();
|
||||||
|
} else {
|
||||||
|
$minIops.css('display', 'inline-block');
|
||||||
|
$maxIops.css('display', 'inline-block');
|
||||||
|
}
|
||||||
|
|
||||||
|
$hypervisorSnapshotReserve.css('display', 'inline-block');
|
||||||
|
} else if (qosId == 'hypervisor') { // Hypervisor Qos
|
||||||
|
$isCustomizedIops.hide();
|
||||||
|
$minIops.hide();
|
||||||
|
$maxIops.hide();
|
||||||
|
$hypervisorSnapshotReserve.hide();
|
||||||
|
|
||||||
|
$diskBytesReadRate.css('display', 'inline-block');
|
||||||
|
$diskBytesWriteRate.css('display', 'inline-block');
|
||||||
|
$diskIopsReadRate.css('display', 'inline-block');
|
||||||
|
$diskIopsWriteRate.css('display', 'inline-block');
|
||||||
|
} else { // No Qos
|
||||||
|
$diskBytesReadRate.hide();
|
||||||
|
$diskBytesWriteRate.hide();
|
||||||
|
$diskIopsReadRate.hide();
|
||||||
|
$diskIopsWriteRate.hide();
|
||||||
|
$isCustomizedIops.hide();
|
||||||
|
$minIops.hide();
|
||||||
|
$maxIops.hide();
|
||||||
|
$hypervisorSnapshotReserve.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isCustomizedIops: {
|
||||||
|
label: 'label.custom.disk.iops',
|
||||||
|
docID: 'helpDiskOfferingCustomDiskIops',
|
||||||
|
isBoolean: true,
|
||||||
|
isReverse: true,
|
||||||
|
isChecked: false
|
||||||
|
},
|
||||||
|
minIops: {
|
||||||
|
label: 'label.disk.iops.min',
|
||||||
|
docID: 'helpDiskOfferingDiskIopsMin',
|
||||||
|
dependsOn: 'isCustomizedIops',
|
||||||
|
validation: {
|
||||||
|
required: false,
|
||||||
|
number: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxIops: {
|
||||||
|
label: 'label.disk.iops.max',
|
||||||
|
docID: 'helpDiskOfferingDiskIopsMax',
|
||||||
|
dependsOn: 'isCustomizedIops',
|
||||||
|
validation: {
|
||||||
|
required: false,
|
||||||
|
number: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hypervisorSnapshotReserve: {
|
||||||
|
label: 'label.hypervisor.snapshot.reserve',
|
||||||
|
docID: 'helpDiskOfferingHypervisorSnapshotReserve',
|
||||||
|
validation: {
|
||||||
|
required: false,
|
||||||
|
number: true
|
||||||
|
}
|
||||||
|
},
|
||||||
diskBytesReadRate: {
|
diskBytesReadRate: {
|
||||||
label: 'label.disk.bytes.read.rate',
|
label: 'label.disk.bytes.read.rate',
|
||||||
docID: 'helpComputeOfferingDiskBytesReadRate',
|
docID: 'helpComputeOfferingDiskBytesReadRate',
|
||||||
@ -326,26 +433,59 @@
|
|||||||
networkrate: args.data.networkRate
|
networkrate: args.data.networkRate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.data.qosType == 'storage') {
|
||||||
|
var customIops = args.data.isCustomizedIops == "on";
|
||||||
|
|
||||||
|
$.extend(data, {
|
||||||
|
customizediops: customIops
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!customIops) {
|
||||||
|
if (args.data.minIops != null && args.data.minIops.length > 0) {
|
||||||
|
$.extend(data, {
|
||||||
|
miniops: args.data.minIops
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.data.maxIops != null && args.data.maxIops.length > 0) {
|
||||||
|
$.extend(data, {
|
||||||
|
maxiops: args.data.maxIops
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.data.hypervisorSnapshotReserve != null && args.data.hypervisorSnapshotReserve.length > 0) {
|
||||||
|
$.extend(data, {
|
||||||
|
hypervisorsnapshotreserve: args.data.hypervisorSnapshotReserve
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (args.data.qosType == 'hypervisor') {
|
||||||
if (args.data.diskBytesReadRate != null && args.data.diskBytesReadRate.length > 0) {
|
if (args.data.diskBytesReadRate != null && args.data.diskBytesReadRate.length > 0) {
|
||||||
$.extend(data, {
|
$.extend(data, {
|
||||||
bytesreadrate: args.data.diskBytesReadRate
|
bytesreadrate: args.data.diskBytesReadRate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.data.diskBytesWriteRate != null && args.data.diskBytesWriteRate.length > 0) {
|
if (args.data.diskBytesWriteRate != null && args.data.diskBytesWriteRate.length > 0) {
|
||||||
$.extend(data, {
|
$.extend(data, {
|
||||||
byteswriterate: args.data.diskBytesWriteRate
|
byteswriterate: args.data.diskBytesWriteRate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.data.diskIopsReadRate != null && args.data.diskIopsReadRate.length > 0) {
|
if (args.data.diskIopsReadRate != null && args.data.diskIopsReadRate.length > 0) {
|
||||||
$.extend(data, {
|
$.extend(data, {
|
||||||
iopsreadrate: args.data.diskIopsReadRate
|
iopsreadrate: args.data.diskIopsReadRate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.data.diskIopsWriteRate != null && args.data.diskIopsWriteRate.length > 0) {
|
if (args.data.diskIopsWriteRate != null && args.data.diskIopsWriteRate.length > 0) {
|
||||||
$.extend(data, {
|
$.extend(data, {
|
||||||
iopswriterate: args.data.diskIopsWriteRate
|
iopswriterate: args.data.diskIopsWriteRate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$.extend(data, {
|
$.extend(data, {
|
||||||
offerha: (args.data.offerHA == "on")
|
offerha: (args.data.offerHA == "on")
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user