CLOUDSTACK-2987 Ensure XStools to be there in template inorder to enable dynamic scaling of vm

CLOUDSTACK-3042 - handle Scaling up of vm memory/CPU based on the presence of XS tools in the template
This also takes care of updation of VM after XS tools are installed in the vm and set memory values accordingly to support dynamic scaling after stop start of VM

Signed-off-by: Abhinandan Prateek <aprateek@apache.org>
This commit is contained in:
Harikrishna Patnala 2013-06-20 11:06:12 +05:30 committed by Abhinandan Prateek
parent e420c3be8c
commit 7b6b8d7a07
28 changed files with 176 additions and 25 deletions

View File

@ -92,4 +92,6 @@ public interface VirtualMachineTemplate extends ControlledEntity, Identity, Inte
String getTemplateTag();
Map getDetails();
Boolean isDynamicallyScalable();
}

View File

@ -158,6 +158,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I
}
}
public static final String IsDynamicScalingEnabled = "enable.dynamic.scaling";
public enum Event {
CreateRequested,
StartRequested,

View File

@ -509,6 +509,7 @@ public class ApiConstants {
public static final String DEPLOYMENT_PLANNER = "deploymentplanner";
public static final String ACL_ID = "aclid";
public static final String NUMBER = "number";
public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable";
public enum HostDetails {
all, capacity, events, stats, min;

View File

@ -54,6 +54,9 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
@Parameter(name=ApiConstants.SORT_KEY, type=CommandType.INTEGER, description="sort key of the template, integer")
private Integer sortKey;
@Parameter(name = ApiConstants.IS_DYNAMICALLY_SCALABLE, type = CommandType.BOOLEAN, description = "true if template/ISO contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory")
private Boolean isDynamicallyScalable;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -89,4 +92,8 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
public Integer getSortKey() {
return sortKey;
}
public Boolean isDynamicallyScalable() {
return isDynamicallyScalable;
}
}

View File

@ -93,6 +93,9 @@ public class RegisterIsoCmd extends BaseCmd {
description="Image store uuid")
private String imageStoreUuid;
@Parameter(name = ApiConstants.IS_DYNAMICALLY_SCALABLE, type = CommandType.BOOLEAN, description = "true if iso contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory")
protected Boolean isDynamicallyScalable;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -149,6 +152,10 @@ public class RegisterIsoCmd extends BaseCmd {
return this.imageStoreUuid;
}
public Boolean isDynamicallyScalable() {
return isDynamicallyScalable == null ? false : isDynamicallyScalable;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -118,6 +118,9 @@ public class RegisterTemplateCmd extends BaseCmd {
@Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="Template details in key/value pairs.")
protected Map details;
@Parameter(name = ApiConstants.IS_DYNAMICALLY_SCALABLE, type = CommandType.BOOLEAN, description = "true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory")
protected Boolean isDynamicallyScalable;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -208,6 +211,10 @@ public class RegisterTemplateCmd extends BaseCmd {
return params;
}
public Boolean isDynamicallyScalable() {
return isDynamicallyScalable == null ? false : isDynamicallyScalable;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -67,6 +67,9 @@ public class UpdateVMCmd extends BaseCmd{
@Parameter(name=ApiConstants.DISPLAY_VM, type=CommandType.BOOLEAN, description="an optional field, whether to the display the vm to the end user or not.")
private Boolean displayVm;
@Parameter(name = ApiConstants.IS_DYNAMICALLY_SCALABLE, type = CommandType.BOOLEAN, description = "true if VM contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory")
protected Boolean isDynamicallyScalable;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -95,6 +98,10 @@ public class UpdateVMCmd extends BaseCmd{
return displayVm;
}
public Boolean isDynamicallyScalable() {
return isDynamicallyScalable;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -139,6 +139,9 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe
@SerializedName(ApiConstants.SSHKEY_ENABLED) @Param(description="true if template is sshkey enabled, false otherwise")
private Boolean sshKeyEnabled;
@SerializedName(ApiConstants.IS_DYNAMICALLY_SCALABLE) @Param(description="true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory")
private Boolean isDynamicallyScalable;
@Override
public String getObjectId() {
return this.getId();
@ -296,4 +299,8 @@ public class TemplateResponse extends BaseResponse implements ControlledEntityRe
this.sshKeyEnabled = sshKeyEnabled;
}
public void setDynamicallyScalable(boolean isDynamicallyScalable) {
this.isDynamicallyScalable = isDynamicallyScalable;
}
}

View File

@ -189,6 +189,9 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
@SerializedName(ApiConstants.DISPLAY_VM) @Param(description="an optional field whether to the display the vm to the end user or not.")
private Boolean displayVm;
@SerializedName(ApiConstants.IS_DYNAMICALLY_SCALABLE) @Param(description="true if vm contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory.")
private Boolean isDynamicallyScalable;
public UserVmResponse(){
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
nics = new LinkedHashSet<NicResponse>();
@ -432,4 +435,8 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
this.affinityGroupList.add(affinityGroup);
}
public void setDynamicallyScalable(boolean isDynamicallyScalable) {
this.isDynamicallyScalable = isDynamicallyScalable;
}
}

View File

@ -41,7 +41,7 @@ public class ScaleVmCommand extends Command {
}
public ScaleVmCommand(String vmName, int cpus,
Integer minSpeed, Integer maxSpeed, long minRam, long maxRam, boolean limitCpuUse) {
Integer minSpeed, Integer maxSpeed, long minRam, long maxRam, boolean limitCpuUse, boolean isDynamicallyScalable) {
super();
this.vmName = vmName;
this.cpus = cpus;
@ -50,6 +50,7 @@ public class ScaleVmCommand extends Command {
this.minRam = minRam;
this.maxRam = maxRam;
this.vm = new VirtualMachineTO(1L, vmName, null, cpus, minSpeed, maxSpeed, minRam, maxRam, null, null, false, limitCpuUse, null);
vm.setEnableDynamicallyScaleVm(isDynamicallyScalable);
/*vm.setName(vmName);
vm.setCpus(cpus);
vm.setRam(minRam, maxRam);*/

View File

@ -148,6 +148,9 @@ public class VMTemplateVO implements VirtualMachineTemplate, StateObject<Templat
@Transient
Map details;
@Column(name = "dynamically_scalable")
protected boolean dynamicallyScalable;
@Override
public String getUniqueName() {
return uniqueName;
@ -171,12 +174,13 @@ public class VMTemplateVO implements VirtualMachineTemplate, StateObject<Templat
this.state = TemplateState.Allocated;
}
public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, String templateTag, Map details, boolean sshKeyEnabled) {
public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, String templateTag, Map details, boolean sshKeyEnabled, boolean isDynamicallyScalable) {
this(id, name, format, isPublic, featured, isExtractable, type, url, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType, details);
this.templateTag = templateTag;
this.uuid = UUID.randomUUID().toString();
this.state = TemplateState.Allocated;
this.enableSshKey = sshKeyEnabled;
this.dynamicallyScalable = isDynamicallyScalable;
}
public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
@ -530,5 +534,13 @@ public class VMTemplateVO implements VirtualMachineTemplate, StateObject<Templat
this.updated = updated;
}
public void setDynamicallyScalable(boolean dynamicallyScalable) {
this.dynamicallyScalable = dynamicallyScalable;
}
public Boolean isDynamicallyScalable() {
return this.dynamicallyScalable;
}
}

View File

@ -146,6 +146,7 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi
@Enumerated(value=EnumType.STRING)
protected HypervisorType hypervisorType;
/*
@Column(name="tags")
protected String tags;

View File

@ -101,6 +101,12 @@ public class TemplateEntityImpl implements TemplateEntity {
return null;
}
@Override
public Boolean isDynamicallyScalable() {
// TODO Auto-generated method stub
return false;
}
@Override
public void addDetail(String name, String value) {

View File

@ -26,6 +26,7 @@ import com.cloud.storage.dao.GuestOSDao;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfileImpl;
@Local(value=HypervisorGuru.class)
public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru {

View File

@ -680,6 +680,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.uuid + " ,check your license and hypervisor version.");
}
if(!vmSpec.isEnableDynamicallyScaleVm()) {
throw new CloudRuntimeException("Unable to Scale the vm: " + vmName + "as vm does not have xs tools to support dynamic scaling");
}
// stop vm which is running on this host or is in halted state
Iterator<VM> iter = vms.iterator();
while ( iter.hasNext() ) {

View File

@ -137,6 +137,7 @@ public class XenServer56FP1Resource extends XenServer56Resource {
vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY;
vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY;
Map<String, String> details = vmSpec.getDetails();
if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) {
//scaling is allowed
vmr.memoryStaticMin = mem_128m; //128MB

View File

@ -1306,6 +1306,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setTags(tagResponses);
response.setObjectName("iso");
response.setDynamicallyScalable(result.isDynamicallyScalable());
return response;
}
@ -1520,6 +1521,7 @@ public class ApiResponseHelper implements ResponseGenerator {
templateResponse.setTags(tagResponses);
templateResponse.setObjectName("template");
templateResponse.setDynamicallyScalable(template.isDynamicallyScalable());
responses.add(templateResponse);
return responses;
}
@ -1545,6 +1547,7 @@ public class ApiResponseHelper implements ResponseGenerator {
isoResponse.setChecksum(iso.getChecksum());
isoResponse.setPasswordEnabled(false);
isoResponse.setDetails(iso.getDetails());
isoResponse.setDynamicallyScalable(iso.isDynamicallyScalable());
// add account ID and name
Account owner = ApiDBUtils.findAccountById(iso.getAccountId());
@ -1721,6 +1724,7 @@ public class ApiResponseHelper implements ResponseGenerator {
isoResponse.setPublic(iso.isPublicTemplate());
isoResponse.setChecksum(iso.getChecksum());
isoResponse.setDetails(iso.getDetails());
isoResponse.setDynamicallyScalable(iso.isDynamicallyScalable());
// TODO: implement
GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());

View File

@ -249,6 +249,11 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
}
userVmResponse.setObjectName(objectName);
if (userVm.isDynamicallyScalable() == null) {
userVmResponse.setDynamicallyScalable(false);
} else {
userVmResponse.setDynamicallyScalable(userVm.isDynamicallyScalable());
}
return userVmResponse;
}

View File

@ -391,6 +391,9 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
@Column(name="uuid")
private String uuid;
@Column(name="dynamically_scalable")
private boolean isDynamicallyScalable;
public UserVmJoinVO() {
}
@ -1717,5 +1720,13 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
return affinityGroupDescription;
}
public Boolean isDynamicallyScalable() {
return isDynamicallyScalable;
}
public void setDynamicallyScalable(boolean isDynamicallyScalable) {
this.isDynamicallyScalable = isDynamicallyScalable;
}
}

View File

@ -29,6 +29,8 @@ import com.cloud.configuration.Config;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.ConfigurationServer;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.VMTemplateVO;
import com.cloud.utils.component.AdapterBase;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
@ -37,6 +39,7 @@ import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
public abstract class HypervisorGuruBase extends AdapterBase implements HypervisorGuru {
@ -47,7 +50,6 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
@Inject NicSecondaryIpDao _nicSecIpDao;
@Inject ConfigurationServer _configServer;
protected HypervisorGuruBase() {
super();
}
@ -120,15 +122,18 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
if(detailsInVm != null) {
details.putAll(detailsInVm);
}
if (details.get(VirtualMachine.IsDynamicScalingEnabled) == null || details.get(VirtualMachine.IsDynamicScalingEnabled).isEmpty()) {
to. setEnableDynamicallyScaleVm(false);
} else {
// check if XStools/VMWare tools are present in the VM and dynamic scaling feature is enabled (per zone/global)
to.setEnableDynamicallyScaleVm(details.get(VirtualMachine.IsDynamicScalingEnabled).equals("true") && Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vm.getDataCenterId())));
}
to.setDetails(details);
// Workaround to make sure the TO has the UUID we need for Niciri integration
VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId());
to.setUuid(vmInstance.getUuid());
//
to.setEnableDynamicallyScaleVm(Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vm.getDataCenterId())));
return to;
}

View File

@ -1877,6 +1877,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
Boolean passwordEnabled = cmd.isPasswordEnabled();
Boolean bootable = cmd.isBootable();
Integer sortKey = cmd.getSortKey();
Boolean isDynamicallyScalable = cmd.isDynamicallyScalable();
Account account = UserContext.current().getCaller();
// verify that template exists
@ -1898,7 +1899,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
_accountMgr.checkAccess(account, AccessType.ModifyEntry, true, template);
boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null
&& bootable == null && sortKey == null);
&& bootable == null && sortKey == null && isDynamicallyScalable == null);
if (!updateNeeded) {
return template;
}
@ -1947,6 +1948,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
template.setBootable(bootable);
}
if (isDynamicallyScalable != null) {
template.setDynamicallyScalable(isDynamicallyScalable);
}
_templateDao.update(id, template);
return _templateDao.findById(id);

View File

@ -47,6 +47,7 @@ public class TemplateProfile {
String templateTag;
Long imageStoreId;
Map details;
Boolean isDynamicallyScalable;
public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm,
String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId,
@ -84,11 +85,12 @@ public class TemplateProfile {
public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm,
String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId,
HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, String templateTag, Map details, Boolean sshKeyEnabled,
Long imageStoreId) {
Long imageStoreId, Boolean isDynamicallyScalable) {
this(templateId, userId, name, displayText, bits, passwordEnabled, requiresHvm, url, isPublic, featured, isExtractable, format, guestOsId, zoneId,
hypervisorType, accountName, domainId, accountId, chksum, bootable, details, sshKeyEnabled);
this.templateTag = templateTag;
this.imageStoreId = imageStoreId;
this.isDynamicallyScalable = isDynamicallyScalable;
}
public Long getTemplateId() {
@ -258,4 +260,12 @@ public class TemplateProfile {
public Long getImageStoreId() {
return this.imageStoreId;
}
public Boolean IsDynamicallyScalable() {
return this.isDynamicallyScalable;
}
public void setScalabe(Boolean isDynamicallyScalabe) {
this.isDynamicallyScalable = isDynamicallyScalabe;
}
}

View File

@ -69,5 +69,5 @@ public interface TemplateAdapter extends Adapter {
public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits,
Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured,
Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType,
String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshKeyEnabled, String imageStoreUuid) throws ResourceAllocationException;
String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshKeyEnabled, String imageStoreUuid, Boolean isDynamicallyScalable) throws ResourceAllocationException;
}

View File

@ -104,14 +104,14 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType,
String accountName, Long domainId, String chksum, Boolean bootable, Map details) throws ResourceAllocationException {
return prepare(isIso, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, featured, isExtractable, format, guestOSId, zoneId, hypervisorType,
chksum, bootable, null, null, details, false, null);
chksum, bootable, null, null, details, false, null, false);
}
public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits,
Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured,
Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType,
String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshkeyEnabled,
String imageStoreUuid) throws ResourceAllocationException {
String imageStoreUuid, Boolean isDynamicallyScalable) throws ResourceAllocationException {
//Long accountId = null;
// parameters verification
@ -226,7 +226,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
Long id = _tmpltDao.getNextInSequence(Long.class, "id");
UserContext.current().setEventDetails("Id: " +id+ " name: " + name);
return new TemplateProfile(id, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic,
featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, templateOwner.getAccountName(), templateOwner.getDomainId(), templateOwner.getAccountId(), chksum, bootable, templateTag, details, sshkeyEnabled, imageStoreId);
featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, templateOwner.getAccountName(), templateOwner.getDomainId(), templateOwner.getAccountId(), chksum, bootable, templateTag, details, sshkeyEnabled, imageStoreId, isDynamicallyScalable);
}
@Override
@ -241,7 +241,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
return prepare(false, UserContext.current().getCallerUserId(), cmd.getTemplateName(), cmd.getDisplayText(),
cmd.getBits(), cmd.isPasswordEnabled(), cmd.getRequiresHvm(), cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(),
cmd.isExtractable(), cmd.getFormat(), cmd.getOsTypeId(), cmd.getZoneId(), HypervisorType.getType(cmd.getHypervisor()),
cmd.getChecksum(), true, cmd.getTemplateTag(), owner, cmd.getDetails(), cmd.isSshKeyEnabled(), cmd.getImageStoreUuid());
cmd.getChecksum(), true, cmd.getTemplateTag(), owner, cmd.getDetails(), cmd.isSshKeyEnabled(), cmd.getImageStoreUuid(), cmd.isDynamicallyScalable());
}
public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException {
@ -252,7 +252,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
return prepare(true, UserContext.current().getCallerUserId(), cmd.getIsoName(), cmd.getDisplayText(), 64, false,
true, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), cmd.isExtractable(), ImageFormat.ISO.toString(), cmd.getOsTypeId(),
cmd.getZoneId(), HypervisorType.None, cmd.getChecksum(), cmd.isBootable(), null, owner, null, false, cmd.getImageStoreUuid());
cmd.getZoneId(), HypervisorType.None, cmd.getChecksum(), cmd.isBootable(), null, owner, null, false, cmd.getImageStoreUuid(), cmd.isDynamicallyScalable());
}
protected VMTemplateVO persistTemplate(TemplateProfile profile) {
@ -261,7 +261,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
profile.getFeatured(), profile.getIsExtractable(), TemplateType.USER, profile.getUrl(), profile.getRequiresHVM(),
profile.getBits(), profile.getAccountId(), profile.getCheckSum(), profile.getDisplayText(),
profile.getPasswordEnabled(), profile.getGuestOsId(), profile.getBootable(), profile.getHypervisorType(), profile.getTemplateTag(),
profile.getDetails(), profile.getSshKeyEnabled());
profile.getDetails(), profile.getSshKeyEnabled(), profile.IsDynamicallyScalable());
template.setImageDataStoreId(profile.getImageStoreId());
if (zoneId == null || zoneId.longValue() == -1) {

View File

@ -1709,6 +1709,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
Long id = cmd.getId();
Long osTypeId = cmd.getOsTypeId();
String userData = cmd.getUserData();
Boolean isDynamicallyScalable = cmd.isDynamicallyScalable();
Account caller = UserContext.current().getCaller();
// Input validation
@ -1796,6 +1797,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
}
if (isDynamicallyScalable != null) {
UserVmDetailVO vmDetailVO = _vmDetailsDao.findDetail(vm.getId(), VirtualMachine.IsDynamicScalingEnabled);
if (vmDetailVO == null) {
vmDetailVO = new UserVmDetailVO(vm.getId(), VirtualMachine.IsDynamicScalingEnabled, isDynamicallyScalable.toString());
_vmDetailsDao.persist(vmDetailVO);
} else {
vmDetailVO.setValue(isDynamicallyScalable.toString());
_vmDetailsDao.update(vmDetailVO.getId(), vmDetailVO);
}
}
_vmDao.updateVM(id, displayName, ha, osTypeId, userData, isDisplayVmEnabled);
if (updateUserdata) {
@ -2684,6 +2696,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
owner.getDomainId(), owner.getId(), offering.getId(), userData,
hostName, diskOfferingId);
vm.setUuid(uuidName);
vm.setDetail(VirtualMachine.IsDynamicScalingEnabled, template.isDynamicallyScalable().toString());
if (sshPublicKey != null) {
vm.setDetail("SSH.PublicKey", sshPublicKey);

View File

@ -168,6 +168,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.ItWorkVO.Step;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
@ -3230,14 +3231,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Override
public VMInstanceVO reConfigureVm(VMInstanceVO vm , ServiceOffering oldServiceOffering, boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
UserVmDetailVO vmDetailVO = _uservmDetailsDao.findDetail(vm.getId(), VirtualMachine.IsDynamicScalingEnabled);
Boolean isDynamicallyScalable;
if (vmDetailVO == null) {
isDynamicallyScalable = false;
} else {
isDynamicallyScalable = (vmDetailVO.getValue()).equals("true");
}
long newServiceofferingId = vm.getServiceOfferingId();
ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newServiceofferingId);
HostVO hostVo = _hostDao.findById(vm.hostId);
HostVO hostVo = _hostDao.findById(vm.getHostId());
Float memoryOvercommitRatio = Float.parseFloat(_configServer.getConfigValue(Config.MemOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), hostVo.getClusterId()));
Float cpuOvercommitRatio = Float.parseFloat(_configServer.getConfigValue(Config.CPUOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), hostVo.getClusterId()));
long minMemory = (long) (newServiceOffering.getRamSize()/memoryOvercommitRatio);
ScaleVmCommand reconfigureCmd = new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(),
(int) (newServiceOffering.getSpeed()/cpuOvercommitRatio), newServiceOffering.getSpeed(), minMemory * 1024 * 1024, newServiceOffering.getRamSize() * 1024 * 1024, newServiceOffering.getLimitCpuUse());
(int) (newServiceOffering.getSpeed()/cpuOvercommitRatio), newServiceOffering.getSpeed(), minMemory * 1024 * 1024, newServiceOffering.getRamSize() * 1024 * 1024, newServiceOffering.getLimitCpuUse(), isDynamicallyScalable);
Long dstHostId = vm.getHostId();
ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Running, vm.getType(), vm.getId());

View File

@ -75,7 +75,7 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
import com.cloud.utils.Pair;
@ -160,12 +160,15 @@ public class VirtualMachineManagerImplTest {
ConfigurationServer _configServer;
@Mock
HostVO hostVO;
@Mock
UserVmDetailVO _vmDetailVO;
@Mock ClusterDao _clusterDao;
@Mock HostPodDao _podDao;
@Mock DataCenterDao _dcDao;
@Mock DiskOfferingDao _diskOfferingDao;
@Mock PrimaryDataStoreDao _storagePoolDao;
@Mock UserVmDetailsDao _vmDetailsDao;
@Mock StoragePoolHostDao _poolHostDao;
@Mock NetworkManager _networkMgr;
@Mock HypervisorGuruManager _hvGuruMgr;
@ -206,6 +209,7 @@ public class VirtualMachineManagerImplTest {
_vmMgr._vmSnapshotMgr = _vmSnapshotMgr;
_vmMgr._vmDao = _vmInstanceDao;
_vmMgr._configServer = _configServer;
_vmMgr._uservmDetailsDao = _vmDetailsDao;
when(_vmMock.getId()).thenReturn(314l);
when(_vmInstance.getId()).thenReturn(1L);
@ -244,14 +248,20 @@ public class VirtualMachineManagerImplTest {
DeployDestination dest = new DeployDestination(null, null, null, _host);
long l = 1L;
doReturn(3L).when(_vmInstance).getId();
when(_vmDetailsDao.findDetail(3L, VirtualMachine.IsDynamicScalingEnabled)).thenReturn(_vmDetailVO);
doReturn("true").when(_vmDetailVO).getValue();
when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance);
ServiceOfferingVO newServiceOffering = getSvcoffering(512);
when(_hostDao.findById(_vmInstance.hostId)).thenReturn(hostVO);
doReturn(1L).when(_vmInstance).getHostId();
doReturn(hostVO).when(_hostDao).findById(1L);
doReturn(1L).when(_vmInstance).getDataCenterId();
doReturn(1L).when(hostVO).getClusterId();
when(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), 1L)).thenReturn("true");
when(_configServer.getConfigValue(Config.MemOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), 1L)).thenReturn("1.0");
when(_configServer.getConfigValue(Config.CPUOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), 1L)).thenReturn("1.0");
ScaleVmCommand reconfigureCmd = new ScaleVmCommand("myVmName", newServiceOffering.getCpu(),
newServiceOffering.getSpeed(), newServiceOffering.getSpeed(), newServiceOffering.getRamSize(), newServiceOffering.getRamSize(), newServiceOffering.getLimitCpuUse());
newServiceOffering.getSpeed(), newServiceOffering.getSpeed(), newServiceOffering.getRamSize(), newServiceOffering.getRamSize(), newServiceOffering.getLimitCpuUse(), true);
Answer answer = new ScaleVmAnswer(reconfigureCmd, true, "details");
when(_agentMgr.send(2l, reconfigureCmd)).thenReturn(null);
_vmMgr.reConfigureVm(_vmInstance, getSvcoffering(256), false);

View File

@ -1518,7 +1518,8 @@ CREATE VIEW `cloud`.`user_vm_view` AS
affinity_group.id affinity_group_id,
affinity_group.uuid affinity_group_uuid,
affinity_group.name affinity_group_name,
affinity_group.description affinity_group_description
affinity_group.description affinity_group_description,
vm_details.value dynamically_scalable
from
`cloud`.`user_vm`
@ -1579,10 +1580,13 @@ CREATE VIEW `cloud`.`user_vm_view` AS
`cloud`.`async_job` ON async_job.instance_id = vm_instance.id
and async_job.instance_type = 'VirtualMachine'
and async_job.job_status = 0
left join
`cloud`.`affinity_group_vm_map` ON vm_instance.id = affinity_group_vm_map.instance_id
left join
`cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id;
left join
`cloud`.`affinity_group_vm_map` ON vm_instance.id = affinity_group_vm_map.instance_id
left join
`cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id
left join
`cloud`.`user_vm_details` vm_details ON vm_details.vm_id = vm_instance.id
and vm_details.name = 'enable.dynamic.scaling';
DROP VIEW IF EXISTS `cloud`.`volume_view`;
CREATE VIEW `cloud`.`volume_view` AS
@ -1884,3 +1888,4 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'execute.in.sequence.hypervisor.commands', 'false', 'If set to true, StartCommand, StopCommand, CopyVolumeCommand, CreateCommand will be synchronized on the agent side. If set to false, these commands become asynchronous. Default value is false.');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'execute.in.sequence.network.element.commands', 'false', 'If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side. If set to false, these commands become asynchronous. Default value is false.');
ALTER TABLE `cloud`.`vm_template` ADD COLUMN `dynamically_scalable` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory';