CLOUDSTACK-5161 enable scaling of a vm using custom offering

Signed-off-by: Koushik Das <koushik@apache.org>
This commit is contained in:
Bharat Kumar 2013-11-28 07:53:21 +05:30 committed by Koushik Das
parent abd4a826e9
commit 68406ba29d
24 changed files with 389 additions and 89 deletions

View File

@ -72,6 +72,7 @@ public class ApiConstants {
public static final String DISPLAY_VM = "displayvm"; public static final String DISPLAY_VM = "displayvm";
public static final String DISPLAY_OFFERING = "displayoffering"; public static final String DISPLAY_OFFERING = "displayoffering";
public static final String DISPLAY_VOLUME = "displayvolume"; public static final String DISPLAY_VOLUME = "displayvolume";
public static final String CUSTOM_PARAMETERS = "customparameters";
public static final String DNS1 = "dns1"; public static final String DNS1 = "dns1";
public static final String DNS2 = "dns2"; public static final String DNS2 = "dns2";
public static final String IP6_DNS1 = "ip6dns1"; public static final String IP6_DNS1 = "ip6dns1";

View File

@ -39,6 +39,11 @@ import com.cloud.offering.ServiceOffering;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@APICommand(name = "scaleSystemVm", @APICommand(name = "scaleSystemVm",
responseObject = SystemVmResponse.class, responseObject = SystemVmResponse.class,
description = "Scale the service offering for a system vm (console proxy or secondary storage). " + "The system vm must be in a \"Stopped\" state for " description = "Scale the service offering for a system vm (console proxy or secondary storage). " + "The system vm must be in a \"Stopped\" state for "
@ -61,6 +66,11 @@ public class ScaleSystemVMCmd extends BaseAsyncCmd {
description = "the service offering ID to apply to the system vm") description = "the service offering ID to apply to the system vm")
private Long serviceOfferingId; private Long serviceOfferingId;
@Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
type = CommandType.MAP,
description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
private Map<String, String> customParameters;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -73,6 +83,21 @@ public class ScaleSystemVMCmd extends BaseAsyncCmd {
return serviceOfferingId; return serviceOfferingId;
} }
public Map<String, String> getCustomParameters() {
Map<String,String> customparameterMap = new HashMap<String, String>();
if (customParameters != null && customParameters.size() != 0) {
Collection parameterCollection = customParameters.values();
Iterator iter = parameterCollection.iterator();
while (iter.hasNext()) {
HashMap<String, String> value = (HashMap<String, String>) iter.next();
for (String key : value.keySet()) {
customparameterMap.put(key, value.get(key));
}
}
}
return customparameterMap;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -34,6 +34,11 @@ import com.cloud.offering.ServiceOffering;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@APICommand(name = "changeServiceForSystemVm", @APICommand(name = "changeServiceForSystemVm",
responseObject = SystemVmResponse.class, responseObject = SystemVmResponse.class,
description = "Changes the service offering for a system vm (console proxy or secondary storage). " + "The system vm must be in a \"Stopped\" state for " description = "Changes the service offering for a system vm (console proxy or secondary storage). " + "The system vm must be in a \"Stopped\" state for "
@ -56,6 +61,11 @@ public class UpgradeSystemVMCmd extends BaseCmd {
description = "the service offering ID to apply to the system vm") description = "the service offering ID to apply to the system vm")
private Long serviceOfferingId; private Long serviceOfferingId;
@Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
type = CommandType.MAP,
description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
private Map<String, String> customParameters;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -68,6 +78,21 @@ public class UpgradeSystemVMCmd extends BaseCmd {
return serviceOfferingId; return serviceOfferingId;
} }
public Map<String, String> getCustomParameters() {
Map<String,String> customparameterMap = new HashMap<String, String>();
if (customParameters != null && customParameters.size() !=0){
Collection parameterCollection = customParameters.values();
Iterator iter = parameterCollection.iterator();
while (iter.hasNext()) {
HashMap<String, String> value = (HashMap<String, String>) iter.next();
for (String key : value.keySet()) {
customparameterMap.put(key, value.get(key));
}
}
}
return customparameterMap;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -39,6 +39,12 @@ import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.uservm.UserVm; import com.cloud.uservm.UserVm;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class) @APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class)
public class ScaleVMCmd extends BaseAsyncCmd { public class ScaleVMCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName()); public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName());
@ -60,6 +66,11 @@ public class ScaleVMCmd extends BaseAsyncCmd {
description = "the ID of the service offering for the virtual machine") description = "the ID of the service offering for the virtual machine")
private Long serviceOfferingId; private Long serviceOfferingId;
@Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
type = CommandType.MAP,
description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
private Map<String, String> customParameters;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -72,6 +83,24 @@ public class ScaleVMCmd extends BaseAsyncCmd {
return serviceOfferingId; return serviceOfferingId;
} }
//instead of reading a map directly we are using collections.
//it is because customParameters.values() cannot be cast to a map.
//it gives a exception
public Map<String, String> getCustomParameters() {
Map<String,String> customparameterMap = new HashMap<String, String>();
if (customParameters != null && customParameters.size() !=0){
Collection parameterCollection = customParameters.values();
Iterator iter = parameterCollection.iterator();
while (iter.hasNext()) {
HashMap<String, String> value = (HashMap<String, String>) iter.next();
for (String key : value.keySet()) {
customparameterMap.put(key, value.get(key));
}
}
}
return customparameterMap;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -34,6 +34,11 @@ import com.cloud.offering.ServiceOffering;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.uservm.UserVm; import com.cloud.uservm.UserVm;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@APICommand(name = "changeServiceForVirtualMachine", responseObject = UserVmResponse.class, description = "Changes the service offering for a virtual machine. " @APICommand(name = "changeServiceForVirtualMachine", responseObject = UserVmResponse.class, description = "Changes the service offering for a virtual machine. "
+ "The virtual machine must be in a \"Stopped\" state for " + "this command to take effect.") + "The virtual machine must be in a \"Stopped\" state for " + "this command to take effect.")
public class UpgradeVMCmd extends BaseCmd { public class UpgradeVMCmd extends BaseCmd {
@ -54,6 +59,11 @@ public class UpgradeVMCmd extends BaseCmd {
description = "the service offering ID to apply to the virtual machine") description = "the service offering ID to apply to the virtual machine")
private Long serviceOfferingId; private Long serviceOfferingId;
@Parameter(name=ApiConstants.CUSTOM_PARAMETERS,
type = CommandType.MAP,
description = "name value pairs of custom parameters for cpu, memory and cpunumber. example customparameters[i].name=value")
private Map<String, String> customParameters;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -66,6 +76,21 @@ public class UpgradeVMCmd extends BaseCmd {
return serviceOfferingId; return serviceOfferingId;
} }
public Map<String, String> getCustomParameters() {
Map<String,String> customparameterMap = new HashMap<String, String>();
if (customParameters != null && customParameters.size() !=0){
Collection parameterCollection = customParameters.values();
Iterator iter = parameterCollection.iterator();
while (iter.hasNext()) {
HashMap<String, String> value = (HashMap<String, String>) iter.next();
for (String key : value.keySet()) {
customparameterMap.put(key, value.get(key));
}
}
}
return customparameterMap;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -44,15 +44,15 @@ public class ServiceOfferingResponse extends BaseResponse {
@SerializedName("cpunumber") @SerializedName("cpunumber")
@Param(description = "the number of CPU") @Param(description = "the number of CPU")
private int cpuNumber; private Integer cpuNumber;
@SerializedName("cpuspeed") @SerializedName("cpuspeed")
@Param(description = "the clock rate CPU speed in Mhz") @Param(description = "the clock rate CPU speed in Mhz")
private int cpuSpeed; private Integer cpuSpeed;
@SerializedName("memory") @SerializedName("memory")
@Param(description = "the memory in MB") @Param(description = "the memory in MB")
private int memory; private Integer memory;
@SerializedName("created") @SerializedName("created")
@Param(description = "the date this service offering was created") @Param(description = "the date this service offering was created")
@ -130,6 +130,10 @@ public class ServiceOfferingResponse extends BaseResponse {
@Param(description = "additional key/value details tied with this service offering", since = "4.2.0") @Param(description = "additional key/value details tied with this service offering", since = "4.2.0")
private Map<String, String> details; private Map<String, String> details;
@SerializedName("iscustomized")
@Param(description = "is true if the offering is customized", since = "4.3.0")
private Boolean isCustomized;
public ServiceOfferingResponse() { public ServiceOfferingResponse() {
} }
@ -185,7 +189,7 @@ public class ServiceOfferingResponse extends BaseResponse {
return cpuNumber; return cpuNumber;
} }
public void setCpuNumber(int cpuNumber) { public void setCpuNumber(Integer cpuNumber) {
this.cpuNumber = cpuNumber; this.cpuNumber = cpuNumber;
} }
@ -193,7 +197,7 @@ public class ServiceOfferingResponse extends BaseResponse {
return cpuSpeed; return cpuSpeed;
} }
public void setCpuSpeed(int cpuSpeed) { public void setCpuSpeed(Integer cpuSpeed) {
this.cpuSpeed = cpuSpeed; this.cpuSpeed = cpuSpeed;
} }
@ -201,7 +205,7 @@ public class ServiceOfferingResponse extends BaseResponse {
return memory; return memory;
} }
public void setMemory(int memory) { public void setMemory(Integer memory) {
this.memory = memory; this.memory = memory;
} }
@ -309,4 +313,9 @@ public class ServiceOfferingResponse extends BaseResponse {
this.details = details; this.details = details;
} }
public void setIscutomized(boolean iscutomized) {
this.isCustomized = iscutomized;
}
} }

View File

@ -145,9 +145,9 @@ public interface VirtualMachineManager extends Manager {
/** /**
* @param vmInstance * @param vmInstance
* @param newServiceOfferingId * @param newServiceOffering
*/ */
void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId); void checkIfCanUpgrade(VirtualMachine vmInstance, ServiceOffering newServiceOffering);
/** /**
* @param vmId * @param vmId

View File

@ -3011,10 +3011,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
} }
@Override @Override
public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) { public void checkIfCanUpgrade(VirtualMachine vmInstance, ServiceOffering newServiceOffering) {
ServiceOfferingVO newServiceOffering = _offeringDao.findById(vmInstance.getId(), newServiceOfferingId);
if (newServiceOffering == null) { if (newServiceOffering == null) {
throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOfferingId); throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOffering.getId());
} }
// Check that the VM is stopped / running // Check that the VM is stopped / running
@ -3025,7 +3024,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
} }
// Check if the service offering being upgraded to is what the VM is already running with // Check if the service offering being upgraded to is what the VM is already running with
if (vmInstance.getServiceOfferingId() == newServiceOffering.getId()) { if (!newServiceOffering.isDynamic() && vmInstance.getServiceOfferingId() == newServiceOffering.getId()) {
if (s_logger.isInfoEnabled()) { if (s_logger.isInfoEnabled()) {
s_logger.info("Not upgrading vm " + vmInstance.toString() + " since it already has the requested " + "service offering (" + newServiceOffering.getName() + s_logger.info("Not upgrading vm " + vmInstance.toString() + " since it already has the requested " + "service offering (" + newServiceOffering.getName() +
")"); ")");
@ -3734,7 +3733,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
VMInstanceVO vm = _vmDao.findByUuid(vmUuid); VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
long newServiceofferingId = vm.getServiceOfferingId(); long newServiceofferingId = vm.getServiceOfferingId();
ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, newServiceofferingId); ServiceOffering newServiceOffering = _offeringDao.findById(vm.getId(), newServiceofferingId);
HostVO hostVo = _hostDao.findById(vm.getHostId()); HostVO hostVo = _hostDao.findById(vm.getHostId());
Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(hostVo.getClusterId()); Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(hostVo.getClusterId());

View File

@ -146,6 +146,7 @@ public class VMEntityManagerImpl implements VMEntityManager {
//FIXME: profile should work on VirtualMachineEntity //FIXME: profile should work on VirtualMachineEntity
VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm); VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm);
vmProfile.setServiceOffering(_serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()));
DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null); DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null);
if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) { if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
plan = plan =

View File

@ -30,6 +30,10 @@ import com.cloud.utils.db.GenericDao;
@Entity @Entity
@Table(name = "usage_event") @Table(name = "usage_event")
public class UsageEventVO implements UsageEvent { public class UsageEventVO implements UsageEvent {
public enum DynamicParameters {
cpuSpeed, cpuNumber, memory
};
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id") @Column(name = "id")

View File

@ -34,10 +34,6 @@ import com.cloud.vm.VirtualMachine;
@DiscriminatorValue(value = "Service") @DiscriminatorValue(value = "Service")
@PrimaryKeyJoinColumn(name = "id") @PrimaryKeyJoinColumn(name = "id")
public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering { public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering {
public enum DynamicParameters {
cpuSpeed, cpuNumber, memory
};
@Column(name = "cpu") @Column(name = "cpu")
private Integer cpu; private Integer cpu;
@ -167,6 +163,20 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
this.deploymentPlanner = deploymentPlanner; this.deploymentPlanner = deploymentPlanner;
} }
public ServiceOfferingVO(ServiceOfferingVO offering) {
super(offering.getId(), offering.getName(), offering.getDisplayText(), false, offering.getTags(), offering.isRecreatable(), offering.getUseLocalStorage(), offering.getSystemUse(), true, offering.getDomainId());
this.cpu = offering.getCpu();
this.ramSize = offering.getRamSize();
this.speed = offering.getSpeed();
this.rateMbps = offering.getRateMbps();
this.multicastRateMbps = offering.getMulticastRateMbps();
this.offerHA = offering.getOfferHA();
this.limitCpuUse = offering.getLimitCpuUse();
this.volatileVm = offering.getVolatileVm();
this.hostTag = offering.getHostTag();
this.vm_type = offering.getSystemVmType();
}
@Override @Override
public boolean getOfferHA() { public boolean getOfferHA() {
return offerHA; return offerHA;

View File

@ -17,6 +17,7 @@
package com.cloud.service.dao; package com.cloud.service.dao;
import java.util.List; import java.util.List;
import java.util.Map;
import com.cloud.service.ServiceOfferingVO; import com.cloud.service.ServiceOfferingVO;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
@ -47,5 +48,5 @@ public interface ServiceOfferingDao extends GenericDao<ServiceOfferingVO, Long>
boolean isDynamic(long serviceOfferingId); boolean isDynamic(long serviceOfferingId);
ServiceOfferingVO getcomputeOffering(long serviceOfferingId, Integer cpuCores, Integer cpuSpeed, Integer memory); ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
} }

View File

@ -25,6 +25,7 @@ import javax.ejb.Local;
import javax.inject.Inject; import javax.inject.Inject;
import javax.persistence.EntityExistsException; import javax.persistence.EntityExistsException;
import com.cloud.event.UsageEventVO;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -191,14 +192,12 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) { public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) {
ServiceOfferingVO offering = super.findById(serviceOfferingId); ServiceOfferingVO offering = super.findById(serviceOfferingId);
if (offering.isDynamic()) { if (offering.isDynamic()) {
offering.setDynamicFlag(true);
if (vmId == null) { if (vmId == null) {
throw new CloudRuntimeException("missing argument vmId"); throw new CloudRuntimeException("missing argument vmId");
} }
Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
offering.setCpu(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name()))); return getcomputeOffering(offering, dynamicOffering);
offering.setSpeed(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name())));
offering.setRamSize(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.memory.name())));
return offering;
} }
return offering; return offering;
} }
@ -207,15 +206,12 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
public ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferingId) { public ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferingId) {
ServiceOfferingVO offering = super.findByIdIncludingRemoved(serviceOfferingId); ServiceOfferingVO offering = super.findByIdIncludingRemoved(serviceOfferingId);
if (offering.isDynamic()) { if (offering.isDynamic()) {
offering.setDynamicFlag(true);
if (vmId == null) { if (vmId == null) {
throw new CloudRuntimeException("missing argument vmId"); throw new CloudRuntimeException("missing argument vmId");
} }
Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
offering.setCpu(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name()))); return getcomputeOffering(offering, dynamicOffering);
offering.setSpeed(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name())));
offering.setRamSize(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.memory.name())));
return offering;
} }
return offering; return offering;
} }
@ -227,11 +223,19 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
} }
@Override @Override
public ServiceOfferingVO getcomputeOffering(long serviceOfferingId, Integer cpuCores, Integer cpuSpeed, Integer memory) { public ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
ServiceOfferingVO offering = super.findById(serviceOfferingId); ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering);
offering.setCpu(cpuCores); dummyoffering.setDynamicFlag(true);
offering.setSpeed(cpuSpeed); if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
offering.setRamSize(memory); dummyoffering.setCpu(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name())));
return offering; }
if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
dummyoffering.setSpeed(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuSpeed.name())));
}
if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())) {
dummyoffering.setRamSize(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.memory.name())));
}
return dummyoffering;
} }
} }

View File

@ -206,6 +206,22 @@ public class DiskOfferingVO implements DiskOffering {
state = State.Active; state = State.Active;
} }
public DiskOfferingVO(long id, String name, String displayText, boolean mirrored, String tags, boolean recreatable,
boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) {
this.id = id;
type = Type.Service;
this.name = name;
this.displayText = displayText;
this.tags = tags;
this.recreatable = recreatable;
this.useLocalStorage = useLocalStorage;
this.systemUse = systemUse;
this.customized = customized;
this.domainId = domainId;
uuid = UUID.randomUUID().toString();
state = State.Active;
}
@Override @Override
public State getState() { public State getState() {
return state; return state;

View File

@ -27,9 +27,6 @@ import javax.persistence.TemporalType;
@Entity @Entity
@Table(name = "usage_vm_instance") @Table(name = "usage_vm_instance")
public class UsageVMInstanceVO { public class UsageVMInstanceVO {
public enum DynamicParameters {
cpuSpeed, cpuNumber, memory
};
@Column(name = "usage_type") @Column(name = "usage_type")
private int usageType; private int usageType;

View File

@ -79,6 +79,7 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
offeringResponse.setIopsWriteRate(offering.getIopsWriteRate()); offeringResponse.setIopsWriteRate(offering.getIopsWriteRate());
offeringResponse.setDetails(ApiDBUtils.getResourceDetails(offering.getId(), ResourceObjectType.ServiceOffering)); offeringResponse.setDetails(ApiDBUtils.getResourceDetails(offering.getId(), ResourceObjectType.ServiceOffering));
offeringResponse.setObjectName("serviceoffering"); offeringResponse.setObjectName("serviceoffering");
offeringResponse.setIscutomized(offering.isDynamic());
return offeringResponse; return offeringResponse;
} }

View File

@ -55,13 +55,13 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
private boolean systemUse; private boolean systemUse;
@Column(name = "cpu") @Column(name = "cpu")
private int cpu; private Integer cpu;
@Column(name = "speed") @Column(name = "speed")
private int speed; private Integer speed;
@Column(name = "ram_size") @Column(name = "ram_size")
private int ramSize; private Integer ramSize;
@Column(name = "nw_rate") @Column(name = "nw_rate")
private Integer rateMbps; private Integer rateMbps;
@ -184,15 +184,15 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
return sortKey; return sortKey;
} }
public int getCpu() { public Integer getCpu() {
return cpu; return cpu;
} }
public int getSpeed() { public Integer getSpeed() {
return speed; return speed;
} }
public int getRamSize() { public Integer getRamSize() {
return ramSize; return ramSize;
} }
@ -247,4 +247,8 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
public Long getIopsWriteRate() { public Long getIopsWriteRate() {
return iopsWriteRate; return iopsWriteRate;
} }
public boolean isDynamic() {
return cpu == null || speed == null || ramSize == null;
}
} }

View File

@ -27,6 +27,7 @@ import javax.ejb.Local;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import com.cloud.event.UsageEventVO;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigDepot;
@ -543,10 +544,10 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId());
if (so.isDynamic()) { if (so.isDynamic()) {
usedMemory += usedMemory +=
((Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.memory.name())) * 1024L * 1024L) / ramOvercommitRatio) * ((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.memory.name())) * 1024L * 1024L) / ramOvercommitRatio) *
clusterRamOvercommitRatio; clusterRamOvercommitRatio;
usedCpu += usedCpu +=
((Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) * ((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio; clusterCpuOvercommitRatio;
} else { } else {
usedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio; usedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio;

View File

@ -1934,6 +1934,13 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
Integer cpuSpeed = cmd.getCpuSpeed(); Integer cpuSpeed = cmd.getCpuSpeed();
Integer memory = cmd.getMemory(); Integer memory = cmd.getMemory();
//restricting the createserviceoffering to allow setting all or none of the dynamic parameters to null
if (cpuNumber == null || cpuSpeed == null || memory == null) {
if (cpuNumber !=null || cpuSpeed !=null || memory !=null) {
throw new InvalidParameterValueException("For creating a custom compute offering cpu, cpu speed and memory all should be null");
}
}
if ((cpuNumber != null) && ((cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647))) { if ((cpuNumber != null) && ((cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647))) {
throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu number value between 1 and 2147483647"); throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu number value between 1 and 2147483647");
} }

View File

@ -42,6 +42,8 @@ import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -716,6 +718,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
AccountService _accountService; AccountService _accountService;
@Inject @Inject
ConfigurationManager _configMgr; ConfigurationManager _configMgr;
@Inject
ServiceOfferingDao _offeringDao;
@Inject @Inject
DeploymentPlanningManager _dpMgr; DeploymentPlanningManager _dpMgr;
@ -3769,8 +3773,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
if (vmInstance.getHypervisorType() == HypervisorType.XenServer && vmInstance.getState().equals(State.Running)) { if (vmInstance.getHypervisorType() == HypervisorType.XenServer && vmInstance.getState().equals(State.Running)) {
throw new InvalidParameterValueException("Dynamic Scaling operation is not permitted for this hypervisor on system vm"); throw new InvalidParameterValueException("Dynamic Scaling operation is not permitted for this hypervisor on system vm");
} }
boolean result = _userVmMgr.upgradeVirtualMachine(cmd.getId(), cmd.getServiceOfferingId()); boolean result = _userVmMgr.upgradeVirtualMachine(cmd.getId(), cmd.getServiceOfferingId(), cmd.getCustomParameters());
if (result) { if(result){
VirtualMachine vm = _vmInstanceDao.findById(cmd.getId()); VirtualMachine vm = _vmInstanceDao.findById(cmd.getId());
return vm; return vm;
} else { } else {
@ -3782,11 +3786,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
public VirtualMachine upgradeSystemVM(UpgradeSystemVMCmd cmd) { public VirtualMachine upgradeSystemVM(UpgradeSystemVMCmd cmd) {
Long systemVmId = cmd.getId(); Long systemVmId = cmd.getId();
Long serviceOfferingId = cmd.getServiceOfferingId(); Long serviceOfferingId = cmd.getServiceOfferingId();
return upgradeStoppedSystemVm(systemVmId, serviceOfferingId); return upgradeStoppedSystemVm(systemVmId, serviceOfferingId, cmd.getCustomParameters());
} }
private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOfferingId) { private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOfferingId, Map<String, String> customparameters){
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
@ -3797,10 +3801,25 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
_accountMgr.checkAccess(caller, null, true, systemVm); _accountMgr.checkAccess(caller, null, true, systemVm);
// Check that the specified service offering ID is valid // Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(systemVm, serviceOfferingId); ServiceOfferingVO newServiceOffering = _offeringDao.findById(serviceOfferingId);
ServiceOfferingVO currentServiceOffering = _offeringDao.findById(systemVmId,systemVm.getServiceOfferingId());
if (newServiceOffering.isDynamic()){
newServiceOffering.setDynamicFlag(true);
_userVmMgr.validateCustomParameters(newServiceOffering, customparameters);
newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customparameters);
}
_itMgr.checkIfCanUpgrade(systemVm, newServiceOffering);
boolean result = _itMgr.upgradeVmDb(systemVmId, serviceOfferingId); boolean result = _itMgr.upgradeVmDb(systemVmId, serviceOfferingId);
if (newServiceOffering.isDynamic()) {
//save the custom values to the database.
_userVmMgr.saveCustomOfferingDetails(systemVmId, newServiceOffering);
}
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
_userVmMgr.removeCustomOfferingDetails(systemVmId);
}
if (result) { if (result) {
return _vmInstanceDao.findById(systemVmId); return _vmInstanceDao.findById(systemVmId);
} else { } else {

View File

@ -20,6 +20,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey;
@ -108,7 +110,7 @@ public interface UserVmManager extends UserVmService {
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long hostId, Map<VirtualMachineProfile.Param, Object> additionalParams) Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long hostId, Map<VirtualMachineProfile.Param, Object> additionalParams)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException;
boolean upgradeVirtualMachine(Long id, Long serviceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, boolean upgradeVirtualMachine(Long id, Long serviceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
VirtualMachineMigrationException; VirtualMachineMigrationException;
boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic); boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic);
@ -117,4 +119,12 @@ public interface UserVmManager extends UserVmService {
UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData, UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId) throws ResourceUnavailableException, InsufficientCapacityException; Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId) throws ResourceUnavailableException, InsufficientCapacityException;
//the validateCustomParameters, save and remove CustomOfferingDetils functions can be removed from the interface once we can
//find a common place for all the scaling and upgrading code of both user and systemvms.
void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering);
public void removeCustomOfferingDetails(long vmId);
} }

View File

@ -34,6 +34,7 @@ import javax.ejb.Local;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import com.cloud.event.UsageEventVO;
import com.cloud.uuididentity.UUIDManager; import com.cloud.uuididentity.UUIDManager;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -773,7 +774,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
_accountMgr.checkAccess(caller, null, true, vmInstance); _accountMgr.checkAccess(caller, null, true, vmInstance);
// Check resource limits for CPU and Memory. // Check resource limits for CPU and Memory.
Map<String,String> customParameters = cmd.getCustomParameters();
ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId); ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId);
if (newServiceOffering.isDynamic()) {
newServiceOffering.setDynamicFlag(true);
validateCustomParameters(newServiceOffering, cmd.getCustomParameters());
newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters);
}
ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
int newCpu = newServiceOffering.getCpu(); int newCpu = newServiceOffering.getCpu();
@ -789,7 +796,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
// Check that the specified service offering ID is valid // Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(vmInstance, svcOffId); _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
// remove diskAndMemory VM snapshots // remove diskAndMemory VM snapshots
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId); List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
@ -805,6 +812,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
_itMgr.upgradeVmDb(vmId, svcOffId); _itMgr.upgradeVmDb(vmId, svcOffId);
if (newServiceOffering.isDynamic()) {
//save the custom values to the database.
saveCustomOfferingDetails(vmId, newServiceOffering);
}
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
removeCustomOfferingDetails(vmId);
}
// Increment or decrement CPU and Memory count accordingly. // Increment or decrement CPU and Memory count accordingly.
if (newCpu > currentCpu) { if (newCpu > currentCpu) {
@ -818,15 +832,46 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory)); _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(currentMemory - newMemory));
} }
// Generate usage event for VM upgrade generateUsageEvent(newServiceOffering, cmd.getCustomParameters(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE);
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_UPGRADE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(),
vmInstance.getHostName(), vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), vmInstance.getHypervisorType().toString(),
VirtualMachine.class.getName(), vmInstance.getUuid());
return _vmDao.findById(vmInstance.getId()); return _vmDao.findById(vmInstance.getId());
} }
private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId) throws ResourceAllocationException { @Override
public void validateCustomParameters(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
if (customParameters.size() !=0 ) {
if (serviceOffering.getCpu() == null) {
String cpuNumber = customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name());
if ((cpuNumber == null) || (NumbersUtil.parseInt(cpuNumber, -1) <= 0 || NumbersUtil.parseInt(cpuNumber, -1) > 2147483647)) {
throw new InvalidParameterValueException("Invalid cpu cores value, specify a value between 1 and 2147483647");
}
} else if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
throw new InvalidParameterValueException("The cpu cores of this offering id:"+serviceOffering.getId()+" is not customizable. This is predefined in the template.");
}
if (serviceOffering.getSpeed() == null) {
String cpuSpeed = customParameters.get(UsageEventVO.DynamicParameters.cpuSpeed.name());
if ((cpuSpeed == null) || (NumbersUtil.parseInt(cpuSpeed, -1) <= 0 || NumbersUtil.parseInt(cpuSpeed, -1) > 2147483647 )) {
throw new InvalidParameterValueException("Invalid cpu speed value, specify a value between 1 and 2147483647");
}
} else if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
throw new InvalidParameterValueException("The cpu speed of this offering id:"+serviceOffering.getId()+" is not customizable. This is predefined in the template.");
}
if (serviceOffering.getRamSize() == null) {
String memory = customParameters.get(UsageEventVO.DynamicParameters.memory.name());
if (memory == null || (NumbersUtil.parseInt(memory, -1) < 32 || NumbersUtil.parseInt(memory, -1) > 2147483647)) {
throw new InvalidParameterValueException("Invalid memory value, specify a value between 32 and 2147483647 MB");
}
} else if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())){
throw new InvalidParameterValueException("The memory of this offering id:"+serviceOffering.getId()+" is not customizable. This is predefined in the template.");
}
} else {
throw new InvalidParameterValueException("Need to specify custom parameter values cpu, cpu speed and memory when using custom offering");
}
}
private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map<String, String> customParameters) throws ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
// Verify input parameters // Verify input parameters
@ -840,6 +885,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
// Check resource limits for CPU and Memory. // Check resource limits for CPU and Memory.
ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId); ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId);
if (newServiceOffering.isDynamic()) {
newServiceOffering.setDynamicFlag(true);
validateCustomParameters(newServiceOffering, customParameters);
newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters);
}
ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
int newCpu = newServiceOffering.getCpu(); int newCpu = newServiceOffering.getCpu();
@ -855,7 +905,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
// Check that the specified service offering ID is valid // Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(vmInstance, svcOffId); _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
// remove diskAndMemory VM snapshots // remove diskAndMemory VM snapshots
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId); List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
@ -871,6 +921,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
_itMgr.upgradeVmDb(vmId, svcOffId); _itMgr.upgradeVmDb(vmId, svcOffId);
if (newServiceOffering.isDynamic()) {
//save the custom values to the database.
saveCustomOfferingDetails(vmId, newServiceOffering);
}
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
removeCustomOfferingDetails(vmId);
}
// Increment or decrement CPU and Memory count accordingly. // Increment or decrement CPU and Memory count accordingly.
if (newCpu > currentCpu) { if (newCpu > currentCpu) {
@ -1149,20 +1206,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
Long newServiceOfferingId = cmd.getServiceOfferingId(); Long newServiceOfferingId = cmd.getServiceOfferingId();
CallContext.current().setEventDetails("Vm Id: " + vmId); CallContext.current().setEventDetails("Vm Id: " + vmId);
boolean result = upgradeVirtualMachine(vmId, newServiceOfferingId); boolean result = upgradeVirtualMachine(vmId, newServiceOfferingId,cmd.getCustomParameters());
if (result) { if(result){
UserVmVO vmInstance = _vmDao.findById(vmId); UserVmVO vmInstance = _vmDao.findById(vmId);
if (vmInstance.getState().equals(State.Stopped)) { if (vmInstance.getState().equals(State.Stopped)) {
// Generate usage event for VM upgrade // Generate usage event for VM upgrade
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_UPGRADE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), generateUsageEvent(_serviceOfferingDao.findById(newServiceOfferingId), cmd.getCustomParameters(), vmInstance, EventTypes.EVENT_VM_UPGRADE);
vmInstance.getHostName(), vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), vmInstance.getHypervisorType().toString(),
VirtualMachine.class.getName(), vmInstance.getUuid());
} }
if (vmInstance.getState().equals(State.Running)) { if (vmInstance.getState().equals(State.Running)) {
// Generate usage event for Dynamic scaling of VM // Generate usage event for Dynamic scaling of VM
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DYNAMIC_SCALE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), generateUsageEvent(_serviceOfferingDao.findById(newServiceOfferingId),cmd.getCustomParameters(), vmInstance, EventTypes.EVENT_VM_UPGRADE);
vmInstance.getHostName(), vmInstance.getServiceOfferingId(), vmInstance.getTemplateId(), vmInstance.getHypervisorType().toString(),
VirtualMachine.class.getName(), vmInstance.getUuid());
} }
return vmInstance; return vmInstance;
} else { } else {
@ -1207,24 +1260,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
@Override @Override
public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{
ManagementServerException, VirtualMachineMigrationException {
// Verify input parameters // Verify input parameters
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
if (vmInstance.getState().equals(State.Stopped)) { if (vmInstance.getState().equals(State.Stopped)) {
upgradeStoppedVirtualMachine(vmId, newServiceOfferingId); upgradeStoppedVirtualMachine(vmId, newServiceOfferingId, customParameters);
return true; return true;
} }
if (vmInstance.getState().equals(State.Running)) { if(vmInstance.getState().equals(State.Running)){
return upgradeRunningVirtualMachine(vmId, newServiceOfferingId); return upgradeRunningVirtualMachine(vmId, newServiceOfferingId, customParameters);
} }
return false; return false;
} }
private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException{
ManagementServerException, VirtualMachineMigrationException {
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
@ -1234,11 +1285,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
_accountMgr.checkAccess(caller, null, true, vmInstance); _accountMgr.checkAccess(caller, null, true, vmInstance);
// Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOfferingId);
//Check if its a scale "up" //Check if its a scale "up"
ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, newServiceOfferingId); ServiceOfferingVO newServiceOffering = (ServiceOfferingVO) _offeringDao.findById(newServiceOfferingId);
if (newServiceOffering.isDynamic()) {
newServiceOffering.setDynamicFlag(true);
validateCustomParameters(newServiceOffering, customParameters);
newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters);
}
// Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
ServiceOffering currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); ServiceOffering currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
int newCpu = newServiceOffering.getCpu(); int newCpu = newServiceOffering.getCpu();
int newMemory = newServiceOffering.getRamSize(); int newMemory = newServiceOffering.getRamSize();
@ -1304,9 +1361,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
// #3 scale the vm now // #3 scale the vm now
_itMgr.upgradeVmDb(vmId, newServiceOfferingId); _itMgr.upgradeVmDb(vmId, newServiceOfferingId);
if (newServiceOffering.isDynamic()) {
//save the custom values to the database.
saveCustomOfferingDetails(vmId, newServiceOffering);
}
vmInstance = _vmInstanceDao.findById(vmId); vmInstance = _vmInstanceDao.findById(vmId);
_itMgr.reConfigureVm(vmInstance.getUuid(), currentServiceOffering, existingHostHasCapacity); _itMgr.reConfigureVm(vmInstance.getUuid(), currentServiceOffering, existingHostHasCapacity);
success = true; success = true;
if (currentServiceOffering.isDynamic() && !newServiceOffering.isDynamic()) {
removeCustomOfferingDetails(vmId);
}
return success; return success;
} catch (InsufficientCapacityException e) { } catch (InsufficientCapacityException e) {
s_logger.warn("Received exception while scaling ", e); s_logger.warn("Received exception while scaling ", e);
@ -1319,6 +1383,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} finally { } finally {
if (!success) { if (!success) {
_itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback _itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback
if (newServiceOffering.isDynamic()) {
removeCustomOfferingDetails(vmId);
}
// Decrement CPU and Memory count accordingly. // Decrement CPU and Memory count accordingly.
if (newCpu > currentCpu) { if (newCpu > currentCpu) {
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu)); _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu));
@ -1330,10 +1397,38 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
} }
} }
return success; return success;
} }
@Override
public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering) {
//save the custom values to the database.
Map<String, String> details = _uservmDetailsDao.listDetailsKeyPairs(vmId);
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
List <UserVmDetailVO> detailList = new ArrayList<UserVmDetailVO>();
for (String key : details.keySet()) {
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, key, details.get(key));
detailList.add(detailVO);
}
_uservmDetailsDao.saveDetails(detailList);
}
@Override
public void removeCustomOfferingDetails(long vmId){
Map<String, String> details = _uservmDetailsDao.listDetailsKeyPairs(vmId);
details.remove(UsageEventVO.DynamicParameters.cpuNumber.name());
details.remove(UsageEventVO.DynamicParameters.cpuSpeed.name());
details.remove(UsageEventVO.DynamicParameters.memory.name());
List <UserVmDetailVO> detailList = new ArrayList<UserVmDetailVO>();
for (String key : details.keySet()) {
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, key, details.get(key));
detailList.add(detailVO);
}
_uservmDetailsDao.saveDetails(detailList);
}
@Override @Override
public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException { public HashMap<Long, VmStatsEntry> getVirtualMachineStatistics(long hostId, String hostName, List<Long> vmIds) throws CloudRuntimeException {
HashMap<Long, VmStatsEntry> vmStatsById = new HashMap<Long, VmStatsEntry>(); HashMap<Long, VmStatsEntry> vmStatsById = new HashMap<Long, VmStatsEntry>();
@ -2594,10 +2689,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
} }
details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.cpuNumber.toString(), cpuNumber.toString())); details.add(new UserVmDetailVO(id, UsageEventVO.DynamicParameters.cpuNumber.toString(), cpuNumber.toString()));
details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.cpuSpeed.toString(), cpuSpeed.toString())); details.add(new UserVmDetailVO(id, UsageEventVO.DynamicParameters.cpuSpeed.toString(), cpuSpeed.toString()));
details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.memory.toString(), memory.toString())); details.add(new UserVmDetailVO(id, UsageEventVO.DynamicParameters.memory.toString(), memory.toString()));
offering = _serviceOfferingDao.getcomputeOffering(serviceOffering.getId(), cpuNumber, cpuSpeed, memory); offering.setCpu(cpuNumber);
offering.setRamSize(memory);
offering.setSpeed(cpuSpeed);
offering.setDynamicFlag(true); offering.setDynamicFlag(true);
} }
if (hostName != null) { if (hostName != null) {
@ -2814,6 +2911,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}); });
} }
private void generateUsageEvent(ServiceOfferingVO serviceOffering, Map<String, String> customParameters, UserVmVO vm, String eventType){
if (!serviceOffering.isDynamic()) {
UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(),
vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(),
VirtualMachine.class.getName(), vm.getUuid());
}
else {
UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(),
vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(),
VirtualMachine.class.getName(), vm.getUuid(), customParameters);
}
}
private void validateUserData(String userData, HTTPMethod httpmethod) { private void validateUserData(String userData, HTTPMethod httpmethod) {
byte[] decodedUserData = null; byte[] decodedUserData = null;
if (userData != null) { if (userData != null) {

View File

@ -136,6 +136,8 @@ public class UserVmManagerTest {
@Mock @Mock
ServiceOfferingDao _offeringDao; ServiceOfferingDao _offeringDao;
@Mock @Mock
ServiceOfferingVO _offeringVo;
@Mock
EntityManager _entityMgr; EntityManager _entityMgr;
@Mock @Mock
ResourceLimitService _resourceLimitMgr; ResourceLimitService _resourceLimitMgr;
@ -384,12 +386,12 @@ public class UserVmManagerTest {
doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock);
doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, cmd.getServiceOfferingId()); doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo);
ServiceOffering so1 = getSvcoffering(512); ServiceOffering so1 = getSvcoffering(512);
ServiceOffering so2 = getSvcoffering(256); ServiceOffering so2 = getSvcoffering(256);
when(_entityMgr.findById(eq(ServiceOffering.class), anyLong())).thenReturn(so1); when(_offeringDao.findById(anyLong())).thenReturn((ServiceOfferingVO)so1);
when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO)so1); when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO)so1);
Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, UUID.randomUUID().toString()); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, UUID.randomUUID().toString());

View File

@ -1113,14 +1113,14 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
Map<String, String> usageDetails = _usageEventDetailsDao.findDetails(event.getId()); Map<String, String> usageDetails = _usageEventDetailsDao.findDetails(event.getId());
if (usageDetails != null && usageDetails.size() != 0) { if (usageDetails != null && usageDetails.size() != 0) {
if (usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuNumber.name()) != null) { if (usageDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()) != null) {
cpuCores = Long.parseLong(usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuNumber.name())); cpuCores = Long.parseLong(usageDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()));
} }
if (usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuSpeed.name()) != null) { if (usageDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()) != null) {
cpuSpeed = Long.parseLong(usageDetails.get(UsageVMInstanceVO.DynamicParameters.cpuSpeed.name())); cpuSpeed = Long.parseLong(usageDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()));
} }
if (usageDetails.get(UsageVMInstanceVO.DynamicParameters.memory.name()) != null) { if (usageDetails.get(UsageEventVO.DynamicParameters.memory.name()) != null) {
memory = Long.parseLong(usageDetails.get(UsageVMInstanceVO.DynamicParameters.memory.name())); memory = Long.parseLong(usageDetails.get(UsageEventVO.DynamicParameters.memory.name()));
} }
} }