Skip to content

Commit b06e66c

Browse files
author
Mike Tutkowski
committed
CLOUDSTACK-6170
1 parent bbaec7b commit b06e66c

21 files changed

Lines changed: 638 additions & 66 deletions

File tree

api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.cloudstack.api.BaseCmd;
2828
import org.apache.cloudstack.api.Parameter;
2929
import org.apache.cloudstack.api.ServerApiException;
30+
import org.apache.cloudstack.api.BaseCmd.CommandType;
3031
import org.apache.cloudstack.api.response.DomainResponse;
3132
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
3233

@@ -117,6 +118,21 @@ public class CreateServiceOfferingCmd extends BaseCmd {
117118
@Parameter(name = ApiConstants.IOPS_WRITE_RATE, type = CommandType.LONG, required = false, description = "io requests write rate of the disk offering")
118119
private Long iopsWriteRate;
119120

121+
@Parameter(name = ApiConstants.CUSTOMIZED_IOPS, type = CommandType.BOOLEAN, required = false, description = "whether compute offering iops is custom or not")
122+
private Boolean customizedIops;
123+
124+
@Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, required = false, description = "min iops of the compute offering")
125+
private Long minIops;
126+
127+
@Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, required = false, description = "max iops of the compute offering")
128+
private Long maxIops;
129+
130+
@Parameter(name = ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE,
131+
type = CommandType.INTEGER,
132+
required = false,
133+
description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)")
134+
private Integer hypervisorSnapshotReserve;
135+
120136
/////////////////////////////////////////////////////
121137
/////////////////// Accessors ///////////////////////
122138
/////////////////////////////////////////////////////
@@ -215,6 +231,22 @@ public Long getIopsWriteRate() {
215231
return iopsWriteRate;
216232
}
217233

234+
public Boolean isCustomizedIops() {
235+
return customizedIops;
236+
}
237+
238+
public Long getMinIops() {
239+
return minIops;
240+
}
241+
242+
public Long getMaxIops() {
243+
return maxIops;
244+
}
245+
246+
public Integer getHypervisorSnapshotReserve() {
247+
return hypervisorSnapshotReserve;
248+
}
249+
218250
/////////////////////////////////////////////////////
219251
/////////////// API Implementation///////////////////
220252
/////////////////////////////////////////////////////

core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,25 @@
1616
// under the License.
1717
package org.apache.cloudstack.storage.to;
1818

19+
import java.util.Map;
20+
1921
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
2022

2123
import com.cloud.agent.api.to.DataStoreTO;
2224
import com.cloud.storage.DataStoreRole;
2325
import com.cloud.storage.Storage.StoragePoolType;
2426

2527
public class PrimaryDataStoreTO implements DataStoreTO {
28+
public static final String MANAGED = PrimaryDataStore.MANAGED;
29+
public static final String STORAGE_HOST = PrimaryDataStore.STORAGE_HOST;
30+
public static final String MANAGED_STORE_TARGET = PrimaryDataStore.MANAGED_STORE_TARGET;
31+
public static final String MANAGED_STORE_TARGET_ROOT_VOLUME = PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME;
32+
public static final String CHAP_INITIATOR_USERNAME = PrimaryDataStore.CHAP_INITIATOR_USERNAME;
33+
public static final String CHAP_INITIATOR_SECRET = PrimaryDataStore.CHAP_INITIATOR_SECRET;
34+
public static final String CHAP_TARGET_USERNAME = PrimaryDataStore.CHAP_TARGET_USERNAME;
35+
public static final String CHAP_TARGET_SECRET = PrimaryDataStore.CHAP_TARGET_SECRET;
36+
public static final String VOLUME_SIZE = PrimaryDataStore.VOLUME_SIZE;
37+
2638
private final String uuid;
2739
private final String name;
2840
private String type;
@@ -32,6 +44,7 @@ public class PrimaryDataStoreTO implements DataStoreTO {
3244
private String path;
3345
private int port;
3446
private final String url;
47+
private Map<String, String> details;
3548

3649
public PrimaryDataStoreTO(PrimaryDataStore dataStore) {
3750
this.uuid = dataStore.getUuid();
@@ -42,6 +55,7 @@ public PrimaryDataStoreTO(PrimaryDataStore dataStore) {
4255
this.setPath(dataStore.getPath());
4356
this.setPort(dataStore.getPort());
4457
this.url = dataStore.getUri();
58+
this.details = dataStore.getDetails();
4559
}
4660

4761
public long getId() {
@@ -58,6 +72,10 @@ public String getUrl() {
5872
return this.url;
5973
}
6074

75+
public Map<String, String> getDetails() {
76+
return this.details;
77+
}
78+
6179
public String getName() {
6280
return this.name;
6381
}

engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import com.cloud.host.Host;
2727

2828
public interface DataMotionService {
29+
void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
30+
2931
void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
3032

3133
void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);

engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataMotionStrategy.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public interface DataMotionStrategy {
3030

3131
StrategyPriority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
3232

33+
Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);
34+
3335
Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
3436

3537
Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback);

engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,25 @@
1818
*/
1919
package org.apache.cloudstack.engine.subsystem.api.storage;
2020

21+
import java.util.Map;
22+
2123
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
2224

2325
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2426
import com.cloud.storage.Storage.StoragePoolType;
2527
import com.cloud.storage.StoragePool;
2628

2729
public interface PrimaryDataStoreInfo extends StoragePool {
30+
static final String MANAGED = "managed";
31+
static final String STORAGE_HOST= "storageHost";
32+
static final String MANAGED_STORE_TARGET = "managedStoreTarget";
33+
static final String MANAGED_STORE_TARGET_ROOT_VOLUME = "managedStoreTargetRootVolume";
34+
static final String CHAP_INITIATOR_USERNAME = "chapInitiatorUsername";
35+
static final String CHAP_INITIATOR_SECRET = "chapInitiatorSecret";
36+
static final String CHAP_TARGET_USERNAME = "chapTargetUsername";
37+
static final String CHAP_TARGET_SECRET = "chapTargetSecret";
38+
static final String VOLUME_SIZE = "volumeSize";
39+
2840
boolean isHypervisorSupported(HypervisorType hypervisor);
2941

3042
boolean isLocalStorageSupported();
@@ -37,5 +49,11 @@ public interface PrimaryDataStoreInfo extends StoragePool {
3749
@Override
3850
StoragePoolType getPoolType();
3951

52+
boolean isManaged();
53+
54+
void setDetails(Map<String, String> details);
55+
56+
Map<String, String> getDetails();
57+
4058
PrimaryDataStoreLifeCycle getLifeCycle();
4159
}

engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@ public VolumeInfo getVolume() {
7878

7979
VolumeEntity getVolumeEntity(long volumeId);
8080

81-
AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template);
81+
AsyncCallFuture<VolumeApiResult> createManagedStorageAndVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId,
82+
TemplateInfo srcTemplateInfo, long destHostId);
83+
84+
AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId,
85+
TemplateInfo template);
8286

8387
AsyncCallFuture<VolumeApiResult> copyVolume(VolumeInfo srcVolume, DataStore destStore);
8488

engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
3737
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3838
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
39+
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
3940
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
4041
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
4142
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
@@ -1113,7 +1114,23 @@ private Pair<VolumeVO, DataStore> recreateVolume(VolumeVO vol, VirtualMachinePro
11131114
future = volService.createVolumeAsync(volume, destPool);
11141115
} else {
11151116
TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image);
1116-
future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
1117+
1118+
PrimaryDataStore primaryDataStore = (PrimaryDataStore)destPool;
1119+
1120+
if (primaryDataStore.isManaged()) {
1121+
DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
1122+
HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
1123+
1124+
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
1125+
updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType);
1126+
1127+
long hostId = vm.getVirtualMachine().getHostId();
1128+
1129+
future = volService.createManagedStorageAndVolumeFromTemplateAsync(volume, destPool.getId(), templ, hostId);
1130+
}
1131+
else {
1132+
future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
1133+
}
11171134
}
11181135
VolumeApiResult result = null;
11191136
try {

engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
4747
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
4848
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
49+
import org.apache.cloudstack.storage.RemoteHostEndPoint;
4950
import org.apache.cloudstack.storage.command.CopyCommand;
5051
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
5152

@@ -94,15 +95,17 @@ public StrategyPriority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host src
9495

9596
protected boolean needCacheStorage(DataObject srcData, DataObject destData) {
9697
DataTO srcTO = srcData.getTO();
97-
DataTO destTO = destData.getTO();
9898
DataStoreTO srcStoreTO = srcTO.getDataStore();
99-
DataStoreTO destStoreTO = destTO.getDataStore();
99+
100100
if (srcStoreTO instanceof NfsTO || srcStoreTO.getRole() == DataStoreRole.ImageCache) {
101101
//||
102102
// (srcStoreTO instanceof PrimaryDataStoreTO && ((PrimaryDataStoreTO)srcStoreTO).getPoolType() == StoragePoolType.NetworkFilesystem)) {
103103
return false;
104104
}
105105

106+
DataTO destTO = destData.getTO();
107+
DataStoreTO destStoreTO = destTO.getDataStore();
108+
106109
if (destStoreTO instanceof NfsTO || destStoreTO.getRole() == DataStoreRole.ImageCache) {
107110
return false;
108111
}
@@ -147,7 +150,7 @@ private Scope pickCacheScopeForCopy(DataObject srcData, DataObject destData) {
147150
return selectedScope;
148151
}
149152

150-
protected Answer copyObject(DataObject srcData, DataObject destData) {
153+
protected Answer copyObject(DataObject srcData, DataObject destData, Host destHost) {
151154
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
152155
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
153156
Answer answer = null;
@@ -160,7 +163,7 @@ protected Answer copyObject(DataObject srcData, DataObject destData) {
160163
}
161164

162165
CopyCommand cmd = new CopyCommand(srcForCopy.getTO(), destData.getTO(), _primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
163-
EndPoint ep = selector.select(srcForCopy, destData);
166+
EndPoint ep = destHost != null ? RemoteHostEndPoint.getHypervisorHostEndPoint(destHost) : selector.select(srcForCopy, destData);
164167
if (ep == null) {
165168
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
166169
s_logger.error(errMsg);
@@ -193,6 +196,10 @@ protected Answer copyObject(DataObject srcData, DataObject destData) {
193196
}
194197
}
195198

199+
protected Answer copyObject(DataObject srcData, DataObject destData) {
200+
return copyObject(srcData, destData, null);
201+
}
202+
196203
protected DataObject cacheSnapshotChain(SnapshotInfo snapshot, Scope scope) {
197204
DataObject leafData = null;
198205
DataStore store = cacheMgr.getCacheStorage(snapshot, scope);
@@ -392,8 +399,9 @@ protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) {
392399
return answer;
393400
}
394401

402+
// Note: destHost is currently only used if the copyObject method is invoked
395403
@Override
396-
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
404+
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
397405
Answer answer = null;
398406
String errMsg = null;
399407
try {
@@ -416,7 +424,7 @@ public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCa
416424
} else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) {
417425
answer = copySnapshot(srcData, destData);
418426
} else {
419-
answer = copyObject(srcData, destData);
427+
answer = copyObject(srcData, destData, destHost);
420428
}
421429

422430
if (answer != null && !answer.getResult()) {
@@ -432,6 +440,11 @@ public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCa
432440
return null;
433441
}
434442

443+
@Override
444+
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
445+
return copyAsync(srcData, destData, null, callback);
446+
}
447+
435448
@DB
436449
protected Answer createTemplateFromSnapshot(DataObject srcData, DataObject destData) {
437450

engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class DataMotionServiceImpl implements DataMotionService {
4646
StorageStrategyFactory storageStrategyFactory;
4747

4848
@Override
49-
public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
49+
public void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
5050
if (srcData.getDataStore() == null || destData.getDataStore() == null) {
5151
throw new CloudRuntimeException("can't find data store");
5252
}
@@ -65,7 +65,12 @@ public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCa
6565
destData.getType().name() + " '" + destData.getUuid() + "'");
6666
}
6767

68-
strategy.copyAsync(srcData, destData, callback);
68+
strategy.copyAsync(srcData, destData, destHost, callback);
69+
}
70+
71+
@Override
72+
public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
73+
copyAsync(srcData, destData, null, callback);
6974
}
7075

7176
@Override

engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3131
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
3232
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
33+
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
3334
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
3435
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
3536
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
@@ -299,6 +300,20 @@ public String getInstallPath() {
299300
if (dataStore == null) {
300301
return null;
301302
}
303+
304+
// managed primary data stores should not have an install path
305+
if (dataStore instanceof PrimaryDataStore) {
306+
PrimaryDataStore primaryDataStore = (PrimaryDataStore)dataStore;
307+
308+
Map<String, String> details = primaryDataStore.getDetails();
309+
310+
boolean managed = details != null && Boolean.parseBoolean(details.get(PrimaryDataStore.MANAGED));
311+
312+
if (managed) {
313+
return null;
314+
}
315+
}
316+
302317
DataObjectInStore obj = objectInStoreMgr.findObject(this, dataStore);
303318
return obj.getInstallPath();
304319
}

0 commit comments

Comments
 (0)