Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,7 @@ public class ApiConstants {
public static final String ROUTER_CHECK_TYPE = "checktype";
public static final String LAST_UPDATED = "lastupdated";
public static final String PERFORM_FRESH_CHECKS = "performfreshchecks";
public static final String CACHE_MODE = "cachemode";

public enum HostDetails {
all, capacity, events, stats, min;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ public class CreateDiskOfferingCmd extends BaseCmd {
description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)")
private Integer hypervisorSnapshotReserve;

@Parameter(name = ApiConstants.CACHE_MODE,
type = CommandType.STRING,
required = false,
description = "the cache mode to use for this disk offering. none, writeback or writethrough",
since = "4.14")
private String cacheMode;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -262,6 +269,10 @@ public Integer getHypervisorSnapshotReserve() {
return hypervisorSnapshotReserve;
}

public String getCacheMode() {
return cacheMode;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ public class CreateServiceOfferingCmd extends BaseCmd {
since = "4.4")
private Integer hypervisorSnapshotReserve;

@Parameter(name = ApiConstants.CACHE_MODE,
type = CommandType.STRING,
required = false,
description = "the cache mode to use for this disk offering. none, writeback or writethrough",
since = "4.14")
private String cacheMode;

// Introduce 4 new optional paramaters to work custom compute offerings
@Parameter(name = ApiConstants.CUSTOMIZED,
type = CommandType.BOOLEAN,
Expand Down Expand Up @@ -377,6 +384,10 @@ public Integer getHypervisorSnapshotReserve() {
return hypervisorSnapshotReserve;
}

public String getCacheMode() {
return cacheMode;
}

/**
* If customized parameter is true, then cpuNumber, memory and cpuSpeed must be null
* Check if the optional params min/max CPU/Memory have been specified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ public class ServiceOfferingResponse extends BaseResponse {
@Param(description = "is true if the offering is customized", since = "4.3.0")
private Boolean isCustomized;

@SerializedName("cacheMode")
@Param(description = "the cache mode to use for this disk offering. none, writeback or writethrough", since = "4.14")
private String cacheMode;

public ServiceOfferingResponse() {
}

Expand Down Expand Up @@ -448,4 +452,7 @@ public void setIscutomized(boolean iscutomized) {

}

public void setCacheMode(String cacheMode) {
this.cacheMode = cacheMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ protected synchronized String attachOrDetachDisk(final Connect conn, final boole
final Long bytesReadRate, final Long bytesReadRateMax, final Long bytesReadRateMaxLength,
final Long bytesWriteRate, final Long bytesWriteRateMax, final Long bytesWriteRateMaxLength,
final Long iopsReadRate, final Long iopsReadRateMax, final Long iopsReadRateMaxLength,
final Long iopsWriteRate, final Long iopsWriteRateMax, final Long iopsWriteRateMaxLength) throws LibvirtException, InternalErrorException {
final Long iopsWriteRate, final Long iopsWriteRateMax, final Long iopsWriteRateMaxLength, final String cacheMode) throws LibvirtException, InternalErrorException {
List<DiskDef> disks = null;
Domain dm = null;
DiskDef diskdef = null;
Expand Down Expand Up @@ -1281,6 +1281,9 @@ protected synchronized String attachOrDetachDisk(final Connect conn, final boole
if ((iopsWriteRateMaxLength != null) && (iopsWriteRateMaxLength > 0)) {
diskdef.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
}
if(cacheMode != null) {
diskdef.setCacheMode(DiskDef.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
}
}

final String xml = diskdef.toString();
Expand All @@ -1305,12 +1308,13 @@ public Answer attachVolume(final AttachCommand cmd) {
storagePoolMgr.connectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath(), disk.getDetails());

final KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());
final String volCacheMode = vol.getCacheMode() == null ? null : vol.getCacheMode().toString();

attachOrDetachDisk(conn, true, vmName, phyDisk, disk.getDiskSeq().intValue(), serial,
vol.getBytesReadRate(), vol.getBytesReadRateMax(), vol.getBytesReadRateMaxLength(),
vol.getBytesWriteRate(), vol.getBytesWriteRateMax(), vol.getBytesWriteRateMaxLength(),
vol.getIopsReadRate(), vol.getIopsReadRateMax(), vol.getIopsReadRateMaxLength(),
vol.getIopsWriteRate(), vol.getIopsWriteRateMax(), vol.getIopsWriteRateMaxLength());
vol.getIopsWriteRate(), vol.getIopsWriteRateMax(), vol.getIopsWriteRateMaxLength(), volCacheMode);

return new AttachAnswer(disk);
} catch (final LibvirtException e) {
Expand All @@ -1334,12 +1338,13 @@ public Answer dettachVolume(final DettachCommand cmd) {
final Connect conn = LibvirtConnection.getConnectionByVmName(vmName);

final KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());
final String volCacheMode = vol.getCacheMode() == null ? null : vol.getCacheMode().toString();

attachOrDetachDisk(conn, false, vmName, phyDisk, disk.getDiskSeq().intValue(), serial,
vol.getBytesReadRate(), vol.getBytesReadRateMax(), vol.getBytesReadRateMaxLength(),
vol.getBytesWriteRate(), vol.getBytesWriteRateMax(), vol.getBytesWriteRateMaxLength(),
vol.getIopsReadRate(), vol.getIopsReadRateMax(), vol.getIopsReadRateMaxLength(),
vol.getIopsWriteRate(), vol.getIopsWriteRateMax(), vol.getIopsWriteRateMaxLength());
vol.getIopsWriteRate(), vol.getIopsWriteRateMax(), vol.getIopsWriteRateMaxLength(), volCacheMode);

storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public ServiceOfferingResponse newServiceOfferingResponse(ServiceOfferingJoinVO
offeringResponse.setDetails(ApiDBUtils.getResourceDetails(offering.getId(), ResourceObjectType.ServiceOffering));
offeringResponse.setObjectName("serviceoffering");
offeringResponse.setIscutomized(offering.isDynamic());
offeringResponse.setCacheMode(offering.getCacheMode());

return offeringResponse;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
@Column(name = "deployment_planner")
private String deploymentPlanner;

@Column(name = "cache_mode")
String cacheMode;

public ServiceOfferingJoinVO() {
}

Expand Down Expand Up @@ -349,4 +352,8 @@ public Long getIopsWriteRate() {
public boolean isDynamic() {
return cpu == null || speed == null || ramSize == null;
}

public String getCacheMode() {
return cacheMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
import com.cloud.vm.dao.NicIpAliasVO;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.common.base.Enums;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
Expand Down Expand Up @@ -2318,6 +2319,9 @@ public ServiceOffering createServiceOffering(final CreateServiceOfferingCmd cmd)
}
}

// check if cache_mode parameter is valid
validateCacheMode(cmd.getCacheMode());

final Boolean offerHA = cmd.isOfferHa();

boolean localStorageRequired = false;
Expand Down Expand Up @@ -2398,7 +2402,7 @@ public ServiceOffering createServiceOffering(final CreateServiceOfferingCmd cmd)
cmd.getBytesWriteRate(), cmd.getBytesWriteRateMax(), cmd.getBytesWriteRateMaxLength(),
cmd.getIopsReadRate(), cmd.getIopsReadRateMax(), cmd.getIopsReadRateMaxLength(),
cmd.getIopsWriteRate(), cmd.getIopsWriteRateMax(), cmd.getIopsWriteRateMaxLength(),
cmd.getHypervisorSnapshotReserve());
cmd.getHypervisorSnapshotReserve(), cmd.getCacheMode());
}

protected ServiceOfferingVO createServiceOffering(final long userId, final boolean isSystem, final VirtualMachine.Type vmType,
Expand All @@ -2409,7 +2413,7 @@ protected ServiceOfferingVO createServiceOffering(final long userId, final boole
Long bytesWriteRate, Long bytesWriteRateMax, Long bytesWriteRateMaxLength,
Long iopsReadRate, Long iopsReadRateMax, Long iopsReadRateMaxLength,
Long iopsWriteRate, Long iopsWriteRateMax, Long iopsWriteRateMaxLength,
final Integer hypervisorSnapshotReserve) {
final Integer hypervisorSnapshotReserve, String cacheMode) {
// Filter child domains when both parent and child domains are present
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);

Expand Down Expand Up @@ -2506,6 +2510,9 @@ protected ServiceOfferingVO createServiceOffering(final long userId, final boole
if (iopsWriteRateMaxLength != null && iopsWriteRateMaxLength > 0) {
offering.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
}
if(cacheMode != null) {
offering.setCacheMode(DiskOffering.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
}

if (hypervisorSnapshotReserve != null && hypervisorSnapshotReserve < 0) {
throw new InvalidParameterValueException("If provided, Hypervisor Snapshot Reserve must be greater than or equal to 0.");
Expand Down Expand Up @@ -2764,7 +2771,7 @@ protected DiskOfferingVO createDiskOffering(final Long userId, final List<Long>
Long bytesWriteRate, Long bytesWriteRateMax, Long bytesWriteRateMaxLength,
Long iopsReadRate, Long iopsReadRateMax, Long iopsReadRateMaxLength,
Long iopsWriteRate, Long iopsWriteRateMax, Long iopsWriteRateMaxLength,
final Integer hypervisorSnapshotReserve) {
final Integer hypervisorSnapshotReserve, String cacheMode) {
long diskSize = 0;// special case for custom disk offerings
if (numGibibytes != null && numGibibytes <= 0) {
throw new InvalidParameterValueException("Please specify a disk size of at least 1 Gb.");
Expand Down Expand Up @@ -2870,6 +2877,9 @@ protected DiskOfferingVO createDiskOffering(final Long userId, final List<Long>
if (iopsWriteRateMaxLength != null && iopsWriteRateMaxLength > 0) {
newDiskOffering.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
}
if (cacheMode != null) {
newDiskOffering.setCacheMode(DiskOffering.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
}

if (hypervisorSnapshotReserve != null && hypervisorSnapshotReserve < 0) {
throw new InvalidParameterValueException("If provided, Hypervisor Snapshot Reserve must be greater than or equal to 0.");
Expand Down Expand Up @@ -2936,6 +2946,9 @@ public DiskOffering createDiskOffering(final CreateDiskOfferingCmd cmd) {
throw new InvalidParameterValueException("Disksize is not allowed for a customized disk offering");
}

// check if cache_mode parameter is valid
validateCacheMode(cmd.getCacheMode());

boolean localStorageRequired = false;
final String storageType = cmd.getStorageType();
if (storageType != null) {
Expand All @@ -2962,13 +2975,14 @@ public DiskOffering createDiskOffering(final CreateDiskOfferingCmd cmd) {
final Long iopsWriteRateMax = cmd.getIopsWriteRateMax();
final Long iopsWriteRateMaxLength = cmd.getIopsWriteRateMaxLength();
final Integer hypervisorSnapshotReserve = cmd.getHypervisorSnapshotReserve();
final String cacheMode = cmd.getCacheMode();

final Long userId = CallContext.current().getCallingUserId();
return createDiskOffering(userId, domainIds, zoneIds, name, description, provisioningType, numGibibytes, tags, isCustomized,
localStorageRequired, isDisplayOfferingEnabled, isCustomizedIops, minIops,
maxIops, bytesReadRate, bytesReadRateMax, bytesReadRateMaxLength, bytesWriteRate, bytesWriteRateMax, bytesWriteRateMaxLength,
iopsReadRate, iopsReadRateMax, iopsReadRateMaxLength, iopsWriteRate, iopsWriteRateMax, iopsWriteRateMaxLength,
hypervisorSnapshotReserve);
hypervisorSnapshotReserve, cacheMode);
}

@Override
Expand Down Expand Up @@ -6232,6 +6246,15 @@ private List<Long> filterChildSubDomains(final List<Long> domainIds) {
return filteredDomainIds;
}

protected void validateCacheMode(String cacheMode){
if(cacheMode != null &&
!Enums.getIfPresent(DiskOffering.DiskCacheMode.class,
cacheMode.toUpperCase()).isPresent()) {
throw new InvalidParameterValueException(String.format("Invalid cache mode (%s). Please specify one of the following " +
"valid cache mode parameters: none, writeback or writethrough", cacheMode));
}
}

public List<SecurityChecker> getSecChecker() {
return _secChecker;
}
Expand Down
72 changes: 72 additions & 0 deletions test/integration/smoke/test_disk_offerings.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,78 @@ def test_05_create_burst_type_disk_offering(self):
)
return

@attr(tags=["advanced", "basic", "eip", "sg", "advancedns", "smoke"], required_hardware="false")
def test_06_create_disk_offering_with_cache_mode_type(self):
"""Test to create disk offering with each one of the valid cache mode types : none, writeback and writethrough

# Validate the following:
# 1. createDiskOfferings should return valid info for new offering
# 2. The Cloud Database contains the valid information
"""
cache_mode_types=["none", "writeback", "writethrough"]
for i in range(3):
disk_offering = DiskOffering.create(
self.apiclient,
self.services["disk_offering"],
cacheMode=cache_mode_types[i]
)
self.cleanup.append(disk_offering)

self.debug("Created Disk offering with valid cacheMode param with ID: %s" % disk_offering.id)

list_disk_response = list_disk_offering(
self.apiclient,
id=disk_offering.id
)
self.assertEqual(
isinstance(list_disk_response, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
len(list_disk_response),
0,
"Check Disk offering is created"
)
disk_response = list_disk_response[0]

self.assertEqual(
disk_response.displaytext,
self.services["disk_offering"]["displaytext"],
"Check server id in createServiceOffering"
)
self.assertEqual(
disk_response.name,
self.services["disk_offering"]["name"],
"Check name in createServiceOffering"
)
self.assertEqual(
disk_response.cacheMode,
cache_mode_types[i],
"Check cacheMode in createServiceOffering"
)

return

@attr(tags=["advanced", "basic", "eip", "sg", "advancedns", "smoke"], required_hardware="false")
def test_07_create_disk_offering_with_invalid_cache_mode_type(self):
"""Test to create disk offering with invalid cacheMode type

# Validate the following:
# 1. createDiskOfferings should return valid info for new offering
# 2. The Cloud Database contains the valid information
"""

with self.assertRaises(Exception):
disk_offering = DiskOffering.create(
self.apiclient,
self.services["disk_offering"],
cacheMode="invalid_cache_mode_type"
)


return

class TestDiskOfferings(cloudstackTestCase):

def setUp(self):
Expand Down
Loading