From 7095ea2b5e497620c8c879517565046e3b46e493 Mon Sep 17 00:00:00 2001 From: Bharat Kumar Date: Wed, 6 Nov 2013 21:42:44 +0530 Subject: [PATCH] CLOUDSTACK-4738 Dynamic compute offering. Signed-off-by: Koushik Das --- .../com/cloud/offering/ServiceOffering.java | 8 +- api/src/com/cloud/vm/UserVmService.java | 33 ++-- .../apache/cloudstack/api/ApiConstants.java | 1 + .../offering/CreateServiceOfferingCmd.java | 23 ++- .../api/command/user/vm/DeployVMCmd.java | 34 +++- .../service/VolumeOrchestrationService.java | 2 +- .../service/api/OrchestrationService.java | 4 +- .../src/com/cloud/event/UsageEventUtils.java | 16 ++ .../cloud/vm/VirtualMachineManagerImpl.java | 8 +- .../orchestration/CloudOrchestrator.java | 7 +- .../orchestration/VolumeOrchestrator.java | 6 +- ...spring-engine-schema-core-daos-context.xml | 1 + .../com/cloud/event/UsageEventDetailsVO.java | 72 ++++++++ .../com/cloud/event/dao/UsageEventDao.java | 3 + .../cloud/event/dao/UsageEventDaoImpl.java | 9 +- .../cloud/event/dao/UsageEventDetailsDao.java | 33 ++++ .../event/dao/UsageEventDetailsDaoImpl.java | 104 ++++++++++++ .../com/cloud/service/ServiceOfferingVO.java | 43 +++-- .../cloud/service/dao/ServiceOfferingDao.java | 5 + .../service/dao/ServiceOfferingDaoImpl.java | 52 +++++- .../implicitplanner/ImplicitPlannerTest.java | 3 +- .../BaremetalPxeManagerImpl.java | 2 +- .../impl/UserConcentratedAllocator.java | 2 +- .../com/cloud/api/query/QueryManagerImpl.java | 2 +- .../cloud/capacity/CapacityManagerImpl.java | 25 +-- .../ConfigurationManagerImpl.java | 24 +-- .../VirtualNetworkApplianceManagerImpl.java | 2 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 158 ++++++++++++------ .../cloud/capacity/CapacityManagerTest.java | 2 +- .../test/com/cloud/vm/UserVmManagerTest.java | 2 +- .../CreateNetworkOfferingTest.java | 12 ++ .../service/ServiceOfferingVOTest.java | 49 ++++++ .../test/resources/createNetworkOffering.xml | 4 +- setup/db/db/schema-421to430.sql | 10 ++ 34 files changed, 618 insertions(+), 143 deletions(-) create mode 100644 engine/schema/src/com/cloud/event/UsageEventDetailsVO.java create mode 100644 engine/schema/src/com/cloud/event/dao/UsageEventDetailsDao.java create mode 100644 engine/schema/src/com/cloud/event/dao/UsageEventDetailsDaoImpl.java create mode 100644 server/test/org/apache/cloudstack/service/ServiceOfferingVOTest.java diff --git a/api/src/com/cloud/offering/ServiceOffering.java b/api/src/com/cloud/offering/ServiceOffering.java index 9f7bf8e1315..e4c65cdaf0c 100755 --- a/api/src/com/cloud/offering/ServiceOffering.java +++ b/api/src/com/cloud/offering/ServiceOffering.java @@ -61,17 +61,17 @@ public interface ServiceOffering extends DiskOffering, InfrastructureEntity, Int /** * @return # of cpu. */ - int getCpu(); + Integer getCpu(); /** * @return speed in mhz */ - int getSpeed(); + Integer getSpeed(); /** * @return ram size in megabytes */ - int getRamSize(); + Integer getRamSize(); /** * @return Does this service plan offer HA? @@ -117,4 +117,6 @@ public interface ServiceOffering extends DiskOffering, InfrastructureEntity, Int String getSystemVmType(); String getDeploymentPlanner(); + + boolean isDynamic(); } diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java index 0b142e83b72..6fc8b54cfa1 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -136,6 +136,7 @@ public interface UserVmService { * Creates a Basic Zone User VM in the database and returns the VM to the * caller. * + * * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -181,13 +182,15 @@ public interface UserVmService { * @param displayVm * - Boolean flag whether to the display the vm to the end user or not * @param affinityGroupIdList - * * @param accountName * - an optional account for the virtual machine. Must be used * with domainId * @param domainId * - an optional domainId for the virtual machine. If the account * parameter is used, domainId must also be used + * @param cpuSpeed + * @param memory + * @param cpuNumber * @return UserVm object if successful. * * @throws InsufficientCapacityException @@ -201,15 +204,16 @@ public interface UserVmService { * @throws InsufficientResourcesException */ UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList, Account owner, String hostName, - String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, - HTTPMethod httpmethod, String userData, String sshKeyPair, Map requestedIps, - IpAddresses defaultIp, Boolean displayVm, String keyboard, List affinityGroupIdList) + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + HTTPMethod httpmethod, String userData, String sshKeyPair, Map requestedIps, + IpAddresses defaultIp, Boolean displayVm, String keyboard, List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdisksize) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; /** * Creates a User VM in Advanced Zone (Security Group feature is enabled) in * the database and returns the VM to the caller. * + * * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -257,13 +261,15 @@ public interface UserVmService { * @param displayVm * - Boolean flag whether to the display the vm to the end user or not * @param affinityGroupIdList - * * @param accountName * - an optional account for the virtual machine. Must be used * with domainId * @param domainId * - an optional domainId for the virtual machine. If the account * parameter is used, domainId must also be used + * @param CpuSpeed + * @param memory + * @param cpuNumber * @return UserVm object if successful. * * @throws InsufficientCapacityException @@ -277,14 +283,15 @@ public interface UserVmService { * @throws InsufficientResourcesException */ UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, List securityGroupIdList, - Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData, String sshKeyPair, - Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List affinityGroupIdList) + Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData, String sshKeyPair, + Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdisksize) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; /** * Creates a User VM in Advanced Zone (Security Group feature is disabled) * in the database and returns the VM to the caller. * + * * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -329,15 +336,17 @@ public interface UserVmService { * @param displayVm * - Boolean flag whether to the display the vm to the end user or not * @param affinityGroupIdList - * * @param accountName * - an optional account for the virtual machine. Must be used * with domainId * @param domainId * - an optional domainId for the virtual machine. If the account * parameter is used, domainId must also be used + * @param cpuSpeed + * @param memory + * @param cpuNumber * @return UserVm object if successful. - * + * * @throws InsufficientCapacityException * if there is insufficient capacity to deploy the VM. * @throws ConcurrentOperationException @@ -349,9 +358,9 @@ public interface UserVmService { * @throws InsufficientResourcesException */ UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner, String hostName, - String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, - HTTPMethod httpmethod, String userData, String sshKeyPair, Map requestedIps, - IpAddresses defaultIps, Boolean displayVm, String keyboard, List affinityGroupIdList) + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + HTTPMethod httpmethod, String userData, String sshKeyPair, Map requestedIps, + IpAddresses defaultIps, Boolean displayVm, String keyboard, List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootdkisksize) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 8ab6c5e252e..20e848db287 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -61,6 +61,7 @@ public class ApiConstants { public static final String DEVICE_ID = "deviceid"; public static final String DISK_OFFERING_ID = "diskofferingid"; public static final String DISK_SIZE = "disksize"; + public static final String ROOT_DISK_SIZE = "rootdisksize"; public static final String DISPLAY_NAME = "displayname"; public static final String DISPLAY_NETWORK = "displaynetwork"; public static final String DISPLAY_NIC = "displaynic"; diff --git a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index decac29ae6b..63f19cc7057 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -41,17 +41,17 @@ public class CreateServiceOfferingCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.CPU_NUMBER, type=CommandType.LONG, required=true, description="the CPU number of the service offering") - private Long cpuNumber; + @Parameter(name=ApiConstants.CPU_NUMBER, type=CommandType.INTEGER, required=false, description="the CPU number of the service offering") + private Integer cpuNumber; - @Parameter(name=ApiConstants.CPU_SPEED, type=CommandType.LONG, required=true, description="the CPU speed of the service offering in MHz.") - private Long cpuSpeed; + @Parameter(name=ApiConstants.CPU_SPEED, type=CommandType.INTEGER, required=false, description="the CPU speed of the service offering in MHz.") + private Integer cpuSpeed; @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the service offering") private String displayText; - @Parameter(name=ApiConstants.MEMORY, type=CommandType.LONG, required=true, description="the total memory of the service offering in MB") - private Long memory; + @Parameter(name=ApiConstants.MEMORY, type=CommandType.INTEGER, required=false, description="the total memory of the service offering in MB") + private Integer memory; @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the service offering") private String serviceOfferingName; @@ -109,11 +109,11 @@ public class CreateServiceOfferingCmd extends BaseCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Long getCpuNumber() { + public Integer getCpuNumber() { return cpuNumber; } - public Long getCpuSpeed() { + public Integer getCpuSpeed() { return cpuSpeed; } @@ -121,7 +121,7 @@ public class CreateServiceOfferingCmd extends BaseCmd { return displayText; } - public Long getMemory() { + public Integer getMemory() { return memory; } @@ -173,6 +173,11 @@ public class CreateServiceOfferingCmd extends BaseCmd { return deploymentPlanner; } + public boolean getCustomized() { + return (cpuNumber == null || memory == null || cpuSpeed == null); + } + + public Map getDetails() { if (details == null || details.isEmpty()) { return null; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index 8a6cea79091..3643f91de6c 100755 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -188,6 +188,18 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { @Parameter(name=ApiConstants.DISPLAY_VM, type=CommandType.BOOLEAN, since="4.2", description="an optional field, whether to the display the vm to the end user or not.") private Boolean displayVm; + @Parameter(name=ApiConstants.CPU_SPEED, type = CommandType.INTEGER, since="4.3", description = "optional field to specify the cpu speed when using dynamic compute offering.") + private Integer cpuSpeed; + + @Parameter(name=ApiConstants.MEMORY, type = CommandType.INTEGER, since="4.3", description = "optional field to specify the memory when using dynamic compute offering") + private Integer memory; + + @Parameter(name=ApiConstants.CPU_NUMBER, type=CommandType.INTEGER, since="4.3", description = "optional field to specify the number of cpu cores when using dynamic offering.") + private Integer cpuNumber; + + @Parameter(name=ApiConstants.ROOT_DISK_SIZE, type=CommandType.LONG, since="4.3", description = "optional field to specify the number of cpu cores when using dynamic offering.") + private Long rootdisksize; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -227,6 +239,22 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { return displayVm; } + public Integer getMemory() { + return memory; + } + + public Integer getCpuSpeed() { + return cpuSpeed; + } + + public Integer getCpuNumber() { + return cpuNumber; + } + + public Long getRootdisksize() { + return rootdisksize; + } + public List getSecurityGroupIdList() { if (securityGroupNameList != null && securityGroupIdList != null) { throw new InvalidParameterValueException("securitygroupids parameter is mutually exclusive with securitygroupnames parameter"); @@ -495,19 +523,19 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { throw new InvalidParameterValueException("Can't specify network Ids in Basic zone"); } else { vm = _userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(), owner, name, - displayName, diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList()); + displayName, diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize); } } else { if (zone.isSecurityGroupEnabled()) { vm = _userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, getNetworkIds(), getSecurityGroupIdList(), - owner, name, displayName, diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList()); + owner, name, displayName, diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize ); } else { if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) { throw new InvalidParameterValueException("Can't create vm with security groups; security group feature is not enabled per zone"); } vm = _userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, getNetworkIds(), owner, name, displayName, - diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList()); + diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList(), cpuSpeed, memory, cpuNumber, rootdisksize); } } diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index a773ac42a3a..ad957d5ac8f 100644 --- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -86,7 +86,7 @@ public interface VolumeOrchestrationService { boolean canVmRestartOnAnotherServer(long vmId); - DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, VirtualMachineTemplate template, VirtualMachine vm, Account owner); + DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, Long rootDisksize, VirtualMachineTemplate template, VirtualMachine vm, Account owner); String getVmNameFromVolumeId(long volumeId); diff --git a/engine/api/src/org/apache/cloudstack/engine/service/api/OrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/service/api/OrchestrationService.java index 64ef063d096..8c582276ade 100755 --- a/engine/api/src/org/apache/cloudstack/engine/service/api/OrchestrationService.java +++ b/engine/api/src/org/apache/cloudstack/engine/service/api/OrchestrationService.java @@ -55,6 +55,7 @@ public interface OrchestrationService { * @param computeTags tags for the compute * @param rootDiskTags tags for the root disk * @param networks networks that this VM should join + * @param rootDiskSize size the root disk in case of templates. * @return VirtualMachineEntity */ @POST @@ -73,7 +74,8 @@ public interface OrchestrationService { @QueryParam("compute-tags") List computeTags, @QueryParam("root-disk-tags") List rootDiskTags, @QueryParam("network-nic-map") Map networkNicMap, - @QueryParam("deploymentplan") DeploymentPlan plan + @QueryParam("deploymentplan") DeploymentPlan plan, + @QueryParam("root-disk-size") Long rootDiskSize ) throws InsufficientCapacityException; @POST diff --git a/engine/components-api/src/com/cloud/event/UsageEventUtils.java b/engine/components-api/src/com/cloud/event/UsageEventUtils.java index b44ed3280db..a4be4dd58c6 100644 --- a/engine/components-api/src/com/cloud/event/UsageEventUtils.java +++ b/engine/components-api/src/com/cloud/event/UsageEventUtils.java @@ -25,6 +25,7 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.event.dao.UsageEventDetailsDao; import org.apache.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -38,6 +39,8 @@ import com.cloud.event.dao.UsageEventDao; import com.cloud.user.Account; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; public class UsageEventUtils { @@ -103,6 +106,19 @@ public class UsageEventUtils { publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, + String resourceName, Long offeringId, Long templateId, String resourceType, + String entityType, String entityUUID, Map details) { + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType, details); + publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } + + private static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, String resourceType, Map details) { + UsageEventVO usageEvent = new UsageEventVO(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType); + _usageEventDao.persist(usageEvent); + _usageEventDao.saveDetails(usageEvent.getId(), details); + } + public static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, Long size) { _usageEventDao.persist( new UsageEventVO(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size)); } diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index b74b4c55bac..555a58faaa9 100755 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -356,7 +356,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } else if (template.getFormat() == ImageFormat.BAREMETAL) { // Do nothing } else { - volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOffering.first(), template, vmFinal, owner); + volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOffering.first(), rootDiskOffering.second(), template, vmFinal, owner); } for (Map.Entry offering : dataDiskOfferingsFinal.entrySet()) { @@ -674,7 +674,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac ItWorkVO work = start.third(); VMInstanceVO startedVm = null; - ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); + ServiceOfferingVO offering = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()); VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, vm.getTemplateId()); if (s_logger.isDebugEnabled()) { @@ -2771,7 +2771,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) { - ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId); + ServiceOfferingVO newServiceOffering = _offeringDao.findById(vmInstance.getId(), newServiceOfferingId); if (newServiceOffering == null) { throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOfferingId); } @@ -2793,7 +2793,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac newServiceOffering.getName() + ")"); } - ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); + ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); // Check that the service offering being upgraded to has the same Guest IP type as the VM's current service offering // NOTE: With the new network refactoring in 2.2, we shouldn't need the check for same guest IP type anymore. diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java index 2fd10b66e32..5dd15ce0bb4 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java @@ -164,7 +164,7 @@ public class CloudOrchestrator implements OrchestrationService { Long diskSize, List computeTags, List rootDiskTags, - Map networkNicMap, DeploymentPlan plan) throws InsufficientCapacityException { + Map networkNicMap, DeploymentPlan plan, Long rootDiskSize) throws InsufficientCapacityException { // VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks, vmEntityManager); @@ -191,8 +191,9 @@ public class CloudOrchestrator implements OrchestrationService { Pair rootDiskOffering = new Pair(null, null); LinkedHashMap dataDiskOfferings = new LinkedHashMap(); - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); + ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); rootDiskOffering.first(offering); + rootDiskOffering.second(rootDiskSize); if(vm.getDiskOfferingId() != null){ DiskOfferingVO diskOffering = _diskOfferingDao.findById(vm.getDiskOfferingId()); @@ -238,7 +239,7 @@ public class CloudOrchestrator implements OrchestrationService { VMInstanceVO vm = _vmDao.findByUuid(id); Pair rootDiskOffering = new Pair(null, null); - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); + ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); rootDiskOffering.first(offering); LinkedHashMap dataDiskOfferings = new LinkedHashMap(); diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index ab626c86354..f839d6cf343 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -586,11 +586,13 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } @Override - public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, VirtualMachineTemplate template, VirtualMachine vm, Account owner) { + public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, Long rootDisksize, VirtualMachineTemplate template, VirtualMachine vm, Account owner) { assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really...."; Long size = _tmpltMgr.getTemplateSize(template.getId(), vm.getDataCenterId()); - + if (rootDisksize != null) { + size = (rootDisksize * 1024 * 1024 * 1024); + } VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 98ef018d791..a64e5c06e7c 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -263,6 +263,7 @@ + diff --git a/engine/schema/src/com/cloud/event/UsageEventDetailsVO.java b/engine/schema/src/com/cloud/event/UsageEventDetailsVO.java new file mode 100644 index 00000000000..d6d118b220f --- /dev/null +++ b/engine/schema/src/com/cloud/event/UsageEventDetailsVO.java @@ -0,0 +1,72 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.event; + + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="usage_event_details") +public class UsageEventDetailsVO { + + @Id + @Column(name="id") + long id; + + @Column(name = "usage_event_id", nullable = false) + long usageEventId; + + @Column(name = "name", nullable = false) + String key; + + @Column(name = "value") + String value; + + public UsageEventDetailsVO() { + } + + + public UsageEventDetailsVO(long usageEventId, String key, String value) { + this.key = key; + this.value = value; + this.usageEventId = usageEventId; + } + + public long getId() { + return id; + } + + public void setUsageEventId(long usageEventId) { + this.usageEventId = usageEventId; + } + + public long getUsageEventId() { + return usageEventId; + } + + public String getKey() { + return this.key; + } + + public String getValue() { + return this.value; + } + + } diff --git a/engine/schema/src/com/cloud/event/dao/UsageEventDao.java b/engine/schema/src/com/cloud/event/dao/UsageEventDao.java index 01979e18ea3..dc6f8242de0 100644 --- a/engine/schema/src/com/cloud/event/dao/UsageEventDao.java +++ b/engine/schema/src/com/cloud/event/dao/UsageEventDao.java @@ -18,6 +18,7 @@ package com.cloud.event.dao; import java.util.Date; import java.util.List; +import java.util.Map; import com.cloud.event.UsageEventVO; import com.cloud.utils.db.GenericDao; @@ -32,4 +33,6 @@ public interface UsageEventDao extends GenericDao { List listDirectIpEvents(Date startDate, Date endDate, long zoneId); + void saveDetails(long eventId, Map details); + } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/event/dao/UsageEventDaoImpl.java b/engine/schema/src/com/cloud/event/dao/UsageEventDaoImpl.java index 43339038c53..370afbafa4b 100644 --- a/engine/schema/src/com/cloud/event/dao/UsageEventDaoImpl.java +++ b/engine/schema/src/com/cloud/event/dao/UsageEventDaoImpl.java @@ -20,9 +20,11 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.TimeZone; import javax.ejb.Local; +import javax.inject.Inject; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -51,7 +53,7 @@ public class UsageEventDaoImpl extends GenericDaoBase implem private static final String COPY_ALL_EVENTS = "INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) " + "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id <= ?"; private static final String MAX_EVENT = "select max(id) from cloud.usage_event where created <= ?"; - + @Inject protected UsageEventDetailsDao usageEventDetailsDao; public UsageEventDaoImpl () { latestEventsSearch = createSearchBuilder(); @@ -184,4 +186,9 @@ public class UsageEventDaoImpl extends GenericDaoBase implem return listBy(sc, filter); } + @Override + public void saveDetails(long eventId, Map details) { + usageEventDetailsDao.persist(eventId, details); + } + } diff --git a/engine/schema/src/com/cloud/event/dao/UsageEventDetailsDao.java b/engine/schema/src/com/cloud/event/dao/UsageEventDetailsDao.java new file mode 100644 index 00000000000..fb9c0e27b09 --- /dev/null +++ b/engine/schema/src/com/cloud/event/dao/UsageEventDetailsDao.java @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.event.dao; +import java.util.Map; + +import com.cloud.event.UsageEventDetailsVO; +import com.cloud.utils.db.GenericDao; + + +public interface UsageEventDetailsDao extends GenericDao { + Map findDetails(long eventId); + + void persist(long eventId, Map details); + + UsageEventDetailsVO findDetail(long eventId, String key); + + void deleteDetails(long eventId); +} diff --git a/engine/schema/src/com/cloud/event/dao/UsageEventDetailsDaoImpl.java b/engine/schema/src/com/cloud/event/dao/UsageEventDetailsDaoImpl.java new file mode 100644 index 00000000000..a4382c47a3c --- /dev/null +++ b/engine/schema/src/com/cloud/event/dao/UsageEventDetailsDaoImpl.java @@ -0,0 +1,104 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.event.dao; + +import com.cloud.event.UsageEventDetailsVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.TransactionLegacy; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +@Local(value={UsageEventDetailsDao.class}) +public class UsageEventDetailsDaoImpl extends GenericDaoBase implements UsageEventDetailsDao { + public static final Logger s_logger = Logger.getLogger(UsageEventDetailsDaoImpl.class.getName()); + + protected final SearchBuilder EventDetailsSearch; + protected final SearchBuilder DetailSearch; + + public UsageEventDetailsDaoImpl() { + + EventDetailsSearch =createSearchBuilder(); + EventDetailsSearch.and("eventId", EventDetailsSearch.entity().getUsageEventId(), SearchCriteria.Op.EQ); + EventDetailsSearch.done(); + + DetailSearch = createSearchBuilder(); + DetailSearch.and("eventId", DetailSearch.entity().getUsageEventId(), SearchCriteria.Op.EQ); + DetailSearch.and("key", DetailSearch.entity().getKey(), SearchCriteria.Op.EQ); + DetailSearch.done(); + + + } + + @Override + public void deleteDetails(long eventId) { + SearchCriteria sc = EventDetailsSearch.create(); + sc.setParameters("eventId", eventId); + + List results = search(sc, null); + for (UsageEventDetailsVO result : results) { + remove(result.getId()); + } + } + + @Override + public UsageEventDetailsVO findDetail(long eventId, String key) { + SearchCriteria sc = DetailSearch.create(); + sc.setParameters("eventId", eventId); + sc.setParameters("key", key); + + return findOneBy(sc); + } + + @Override + public Map findDetails(long eventId) { + SearchCriteria sc = EventDetailsSearch.create(); + sc.setParameters("eventId", eventId); + + List results = search(sc, null); + Map details = new HashMap(results.size()); + for (UsageEventDetailsVO result : results) { + details.put(result.getKey(), result.getValue()); + } + + return details; + } + + @Override + public void persist(long eventId, Map details) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + txn.start(); + SearchCriteria sc = EventDetailsSearch.create(); + sc.setParameters("eventId", eventId); + expunge(sc); + + for (Map.Entry detail : details.entrySet()) { + UsageEventDetailsVO vo = new UsageEventDetailsVO(eventId, detail.getKey(), detail.getValue()); + persist(vo); + } + txn.commit(); + } + + +} diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java index 9a262c540b7..1e89addb519 100755 --- a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java +++ b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java @@ -18,12 +18,7 @@ package com.cloud.service; import java.util.Map; -import javax.persistence.Column; -import javax.persistence.DiscriminatorValue; -import javax.persistence.Entity; -import javax.persistence.PrimaryKeyJoinColumn; -import javax.persistence.Table; -import javax.persistence.Transient; +import javax.persistence.*; import com.cloud.offering.ServiceOffering; import com.cloud.storage.DiskOfferingVO; @@ -34,14 +29,18 @@ import com.cloud.vm.VirtualMachine; @DiscriminatorValue(value="Service") @PrimaryKeyJoinColumn(name="id") public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering { + public enum DynamicParameters { + cpuSpeed, cpuNumber, memory + }; + @Column(name="cpu") - private int cpu; + private Integer cpu; @Column(name="speed") - private int speed; + private Integer speed; @Column(name="ram_size") - private int ramSize; + private Integer ramSize; @Column(name="nw_rate") private Integer rateMbps; @@ -83,7 +82,8 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering super(); } - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, boolean defaultUse) { + public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, String displayText, + boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, boolean defaultUse) { super(name, displayText, false, tags, recreatable, useLocalStorage, systemUse, true); this.cpu = cpu; this.ramSize = ramSize; @@ -97,7 +97,8 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase(); } - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId) { + public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse, + boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId) { super(name, displayText, false, tags, recreatable, useLocalStorage, systemUse, true, domainId); this.cpu = cpu; this.ramSize = ramSize; @@ -110,12 +111,14 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase(); } - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, String hostTag) { - this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId); + public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitResourceUse, + boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, String hostTag) { + this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, displayText, useLocalStorage, recreatable, tags, systemUse, + vm_type, domainId); this.hostTag = hostTag; } - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, + public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, String hostTag, String deploymentPlanner) { @@ -159,7 +162,7 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering } @Override - public int getCpu() { + public Integer getCpu() { return cpu; } @@ -176,12 +179,12 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering } @Override - public int getSpeed() { + public Integer getSpeed() { return speed; } @Override - public int getRamSize() { + public Integer getRamSize() { return ramSize; } @@ -252,4 +255,10 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering public void setDetails(Map details) { this.details = details; } + + public boolean isDynamic() { + return cpu == null || speed == null || ramSize == null; + } + + } diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java index 7da72088431..c5c4cff62c0 100644 --- a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java +++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDao.java @@ -17,6 +17,7 @@ package com.cloud.service.dao; import java.util.List; +import java.util.Map; import com.cloud.service.ServiceOfferingVO; import com.cloud.utils.db.GenericDao; @@ -33,4 +34,8 @@ public interface ServiceOfferingDao extends GenericDao ServiceOfferingVO persistDeafultServiceOffering(ServiceOfferingVO offering); void loadDetails(ServiceOfferingVO serviceOffering); void saveDetails(ServiceOfferingVO serviceOffering); + ServiceOfferingVO findById(Long vmId, long serviceOfferingId); + ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferingId); + boolean isDynamic(long serviceOfferingId); + ServiceOfferingVO getcomputeOffering(long serviceOfferingId, Integer cpuCores, Integer cpuSpeed, Integer memory); } diff --git a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java index f807f0df565..917eaefb445 100644 --- a/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java +++ b/engine/schema/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java @@ -25,6 +25,9 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.persistence.EntityExistsException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.dao.UserVmDetailsDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -41,13 +44,14 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase UniqueNameSearch; protected final SearchBuilder ServiceOfferingsByDomainIdSearch; protected final SearchBuilder SystemServiceOffering; protected final SearchBuilder ServiceOfferingsByKeywordSearch; protected final SearchBuilder PublicServiceOfferingSearch; - + public ServiceOfferingDaoImpl() { super(); @@ -134,7 +138,7 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase findPublicServiceOfferings(){ SearchCriteria sc = PublicServiceOfferingSearch.create(); sc.setParameters("system", false); - return listBy(sc); + return listBy(sc); } @Override @DB @@ -180,4 +184,48 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); + offering.setCpu(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name()))); + offering.setSpeed(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name()))); + offering.setRamSize(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.memory.name()))); + return offering; + } + return offering; + } + + public ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferingId) { + ServiceOfferingVO offering = super.findByIdIncludingRemoved(serviceOfferingId); + if (offering.isDynamic()) { + if (vmId == null) { + throw new CloudRuntimeException("missing argument vmId"); + } + Map dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); + offering.setCpu(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name()))); + offering.setSpeed(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name()))); + offering.setRamSize(Integer.parseInt(dynamicOffering.get(ServiceOfferingVO.DynamicParameters.memory.name()))); + return offering; + + } + return offering; + } + + public boolean isDynamic(long serviceOfferingId) { + ServiceOfferingVO offering = super.findById(serviceOfferingId); + return offering.getCpu() == null || offering.getSpeed() == null || offering.getRamSize() == null; + } + + public ServiceOfferingVO getcomputeOffering(long serviceOfferingId, Integer cpuCores, Integer cpuSpeed, Integer memory) { + ServiceOfferingVO offering = super.findById(serviceOfferingId); + offering.setCpu(cpuCores); + offering.setSpeed(cpuSpeed); + offering.setRamSize(memory); + return offering; + } } diff --git a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java index f1fa71c3c56..24368ee3d9c 100644 --- a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java +++ b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.implicitplanner; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -34,6 +35,7 @@ import java.util.UUID; import javax.inject.Inject; +import com.cloud.hypervisor.Hypervisor; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -163,7 +165,6 @@ public class ImplicitPlannerTest { acct.setId(accountId); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); - CallContext.register(user, acct); } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java index ef6ec312d13..9618e6bb47f 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java @@ -187,7 +187,7 @@ public class BaremetalPxeManagerImpl extends ManagerBase implements BaremetalPxe UserVmVO vm = (UserVmVO) profile.getVirtualMachine(); _vmDao.loadDetails(vm); - String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText(); + String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText(); String zoneName = _dcDao.findById(vm.getDataCenterId()).getName(); NicVO nvo = _nicDao.findById(nic.getId()); VmDataCommand cmd = new VmDataCommand(nvo.getIp4Address(), vm.getInstanceName(), _ntwkModel.getExecuteInSeqNtwkElmtCmd()); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java index 0da2c925d3b..3f1994e0d8e 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java @@ -260,7 +260,7 @@ public class UserConcentratedAllocator extends AdapterBase implements PodAllocat } } - so = _offeringDao.findById(vm.getServiceOfferingId()); + so = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()); if (capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) { usedCapacity += so.getRamSize() * 1024L * 1024L; diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index f34e60efc96..29346419eac 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -2431,7 +2431,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { _accountMgr.checkAccess(caller, null, true, vmInstance); - ServiceOfferingVO offering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); + ServiceOfferingVO offering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId()); // Only return offerings with the same Guest IP type and storage diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 1c5f189237f..a9b9ae410d6 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -60,7 +60,6 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.offering.ServiceOffering; -import com.cloud.org.Cluster; import com.cloud.org.Grouping.AllocationState; import com.cloud.resource.ResourceListener; import com.cloud.resource.ResourceManager; @@ -81,7 +80,6 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; -import com.cloud.utils.db.TransactionCallback; import com.cloud.utils.db.TransactionCallbackNoReturn; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.fsm.StateListener; @@ -174,7 +172,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @DB @Override public boolean releaseVmCapacity(VirtualMachine vm, final boolean moveFromReserved, final boolean moveToReservered, final Long hostId) { - final ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); + final ServiceOfferingVO svo = _offeringsDao.findById(vm.getId(), vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); Long clusterId = null; @@ -270,7 +268,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, final float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue()); final float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue()); - final ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); + final ServiceOfferingVO svo = _offeringsDao.findById(vm.getId(), vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); @@ -549,16 +547,23 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, Float cpuOvercommitRatio = 1f; Float ramOvercommitRatio = 1f; for (VMInstanceVO vm : vms) { - UserVmDetailVO vmDetailCpu = _userVmDetailsDao.findDetail(vm.getId(), "cpuOvercommitRatio"); - UserVmDetailVO vmDetailRam = _userVmDetailsDao.findDetail(vm.getId(),"memoryOvercommitRatio"); + Map vmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); + String vmDetailCpu = vmDetails.get("cpuOvercommitRatio"); + String vmDetailRam = vmDetails.get("memoryOvercommitRatio"); if (vmDetailCpu != null ) { //if vmDetail_cpu is not null it means it is running in a overcommited cluster. - cpuOvercommitRatio = Float.parseFloat(vmDetailCpu.getValue()); - ramOvercommitRatio = Float.parseFloat(vmDetailRam.getValue()); + cpuOvercommitRatio = Float.parseFloat(vmDetailCpu); + ramOvercommitRatio = Float.parseFloat(vmDetailRam); } ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); - usedMemory += ((so.getRamSize() * 1024L * 1024L)/ramOvercommitRatio)*clusterRamOvercommitRatio; - usedCpu += ((so.getCpu() * so.getSpeed())/cpuOvercommitRatio)*clusterCpuOvercommitRatio; + if (so.isDynamic()) { + usedMemory += ((Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.memory.name())) * 1024L * 1024L)/ramOvercommitRatio)*clusterRamOvercommitRatio; + usedCpu += ((Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(ServiceOfferingVO.DynamicParameters.cpuSpeed.name())))/cpuOvercommitRatio)*clusterCpuOvercommitRatio; + } + else { + usedMemory += ((so.getRamSize() * 1024L * 1024L)/ramOvercommitRatio)*clusterRamOvercommitRatio; + usedCpu += ((so.getCpu() * so.getSpeed())/cpuOvercommitRatio)*clusterCpuOvercommitRatio; + } } List vmsByLastHostId = _vmDao.listByLastHostId(host.getId()); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index a31d06f4e67..e4bbe8e5bf7 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -206,7 +206,8 @@ import com.cloud.vm.dao.NicIpAliasVO; import com.cloud.vm.dao.NicSecondaryIpDao; @Local(value = { ConfigurationManager.class, ConfigurationService.class }) -public class ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService { +public class + ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService { public static final Logger s_logger = Logger.getLogger(ConfigurationManagerImpl.class); @Inject @@ -1995,20 +1996,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati + ": specify the display text that has non-zero length"); } - Long cpuNumber = cmd.getCpuNumber(); - if ((cpuNumber == null) || (cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647)) { + Integer cpuNumber = cmd.getCpuNumber(); + Integer cpuSpeed = cmd.getCpuSpeed(); + Integer memory = cmd.getMemory(); + boolean customized = cmd.getCustomized(); + + 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"); } - - Long cpuSpeed = cmd.getCpuSpeed(); - if ((cpuSpeed == null) || (cpuSpeed.intValue() <= 0) || (cpuSpeed.intValue() > 2147483647)) { + if ((cpuSpeed != null) && ((cpuSpeed.intValue() < 0) || (cpuSpeed.intValue() > 2147483647))) { throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu speed value between 1 and 2147483647"); } - - Long memory = cmd.getMemory(); - if ((memory == null) || (memory.intValue() < 32) || (memory.intValue() > 2147483647)) { + if (( memory != null ) && ((memory.intValue() < 32) || (memory.intValue() > 2147483647))) { throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the memory value between 32 and 2147483647 MB"); } @@ -2074,21 +2075,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), - cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(), + cpuNumber, memory, cpuSpeed, cmd.getDisplayText(), localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner(), cmd.getDetails(), cmd.getBytesReadRate(), cmd.getBytesWriteRate(), cmd.getIopsReadRate(), cmd.getIopsWriteRate()); } protected ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_type, - String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, + String name, Integer cpu, Integer ramSize, Integer speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner, Map details, Long bytesReadRate, Long bytesWriteRate, Long iopsReadRate, Long iopsWriteRate) { tags = StringUtils.cleanupTags(tags); ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type, domainId, hostTag, deploymentPlanner); - if ((bytesReadRate != null) && (bytesReadRate > 0)) offering.setBytesReadRate(bytesReadRate); if ((bytesWriteRate != null) && (bytesWriteRate > 0)) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 9b35a4b0fbd..fb75cb76822 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -3433,7 +3433,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } private void createVmDataCommand(VirtualRouter router, UserVm vm, NicVO nic, String publicKey, Commands cmds) { - String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText(); + String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText(); String zoneName = _dcDao.findById(router.getDataCenterId()).getName(); cmds.addCommand("vmdata", generateVmDataCommand(router, nic.getIp4Address(), vm.getUserData(), serviceOffering, zoneName, nic.getIp4Address(), diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 9e699623307..52fda38ffd5 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -80,8 +80,6 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.TemplateObjectTO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -220,7 +218,6 @@ import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountService; -import com.cloud.user.AccountVO; import com.cloud.user.ResourceLimitService; import com.cloud.user.SSHKeyPair; import com.cloud.user.SSHKeyPairVO; @@ -246,7 +243,6 @@ import com.cloud.utils.db.Filter; import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.TransactionCallback; import com.cloud.utils.db.TransactionCallbackNoReturn; import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.Transaction; @@ -445,6 +441,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir VolumeService _volService; @Inject VolumeDataFactory volFactory; + @Inject + UserVmDetailsDao _uservmDetailsDao; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -791,7 +789,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Check resource limits for CPU and Memory. ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId); - ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); + ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); int newCpu = newServiceOffering.getCpu(); int newMemory = newServiceOffering.getRamSize(); @@ -859,7 +857,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Check resource limits for CPU and Memory. ServiceOfferingVO newServiceOffering = _offeringDao.findById(svcOffId); - ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); + ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); int newCpu = newServiceOffering.getCpu(); int newMemory = newServiceOffering.getRamSize(); @@ -1256,7 +1254,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir //Check if its a scale "up" ServiceOffering newServiceOffering = _entityMgr.findById(ServiceOffering.class, newServiceOfferingId); - ServiceOffering currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); + ServiceOffering currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); int newCpu = newServiceOffering.getCpu(); int newMemory = newServiceOffering.getRamSize(); int newSpeed = newServiceOffering.getSpeed(); @@ -1442,7 +1440,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } // Get serviceOffering for Virtual Machine - ServiceOfferingVO serviceOffering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); + ServiceOfferingVO serviceOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); // First check that the maximum number of UserVMs, CPU and Memory limit for the given // accountId will not be exceeded @@ -1721,7 +1719,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); // Get serviceOffering for Virtual Machine - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); + ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); // Update Resource Count for the given account resourceCountDecrement(vm.getAccountId(), new Long(offering.getCpu()), @@ -1831,7 +1829,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir ha = vm.isHaEnabled(); } - ServiceOffering offering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); + ServiceOffering offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); if (!offering.getOfferHA() && ha) { throw new InvalidParameterValueException( "Can't enable ha for the vm as it's created from the Service offering having HA disabled"); @@ -1939,7 +1937,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // If the VM is Volatile in nature, on reboot discard the VM's root disk and create a new root disk for it: by calling restoreVM long serviceOfferingId = vmInstance.getServiceOfferingId(); - ServiceOfferingVO offering = _serviceOfferingDao.findById(serviceOfferingId); + ServiceOfferingVO offering = _serviceOfferingDao.findById(vmInstance.getId(), serviceOfferingId); if(offering != null && offering.getRemoved() == null) { if(offering.getVolatileVm()){ return restoreVMInternal(caller, vmInstance, null); @@ -2189,10 +2187,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true) public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList, Account owner, - String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, - HypervisorType hypervisor, HTTPMethod httpmethod, String userData, String sshKeyPair, - Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, - List affinityGroupIdList) + String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, + HypervisorType hypervisor, HTTPMethod httpmethod, String userData, String sshKeyPair, + Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, + List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); @@ -2243,17 +2241,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, securityGroupIdList, group, httpmethod, userData, sshKeyPair, hypervisor, - caller, requestedIps, defaultIps, displayVm, keyboard, affinityGroupIdList); + caller, requestedIps, defaultIps, displayVm, keyboard, affinityGroupIdList, cpuSpeed , memory, cpuNumber, rootDiskSize); } @Override @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true) public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, - List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, - Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData, - String sshKeyPair, Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, - List affinityGroupIdList) throws InsufficientCapacityException, ConcurrentOperationException, + List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, + Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData, + String sshKeyPair, Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, + List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); @@ -2361,15 +2359,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, securityGroupIdList, group, httpmethod, userData, sshKeyPair, hypervisor, - caller, requestedIps, defaultIps, displayVm, keyboard, affinityGroupIdList); + caller, requestedIps, defaultIps, displayVm, keyboard, affinityGroupIdList, cpuSpeed, memory, cpuNumber, rootDiskSize); } @Override @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true) public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner, String hostName, - String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, - HTTPMethod httpmethod, String userData, String sshKeyPair, Map requestedIps, - IpAddresses defaultIps, Boolean displayvm, String keyboard, List affinityGroupIdList) + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + HTTPMethod httpmethod, String userData, String sshKeyPair, Map requestedIps, + IpAddresses defaultIps, Boolean displayvm, String keyboard, List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); @@ -2456,7 +2454,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException( "Can't create vm of hypervisor type " + hypervisor + " in vpc network"); - + } } @@ -2476,7 +2474,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, null, group, httpmethod, userData, sshKeyPair, hypervisor, caller, requestedIps, - defaultIps, displayvm, keyboard, affinityGroupIdList); + defaultIps, displayvm, keyboard, affinityGroupIdList, cpuSpeed, memory, cpuNumber, rootDiskSize); } @@ -2491,7 +2489,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate tmplt, String hostName, String displayName, Account owner, Long diskOfferingId, Long diskSize, List networkList, List securityGroupIdList, String group, HTTPMethod httpmethod, String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map requestedIps, - IpAddresses defaultIps, Boolean isDisplayVmEnabled, String keyboard, List affinityGroupIdList) + IpAddresses defaultIps, Boolean isDisplayVmEnabled, String keyboard, List affinityGroupIdList, Integer cpuSpeed, Integer memory, Integer cpuNumber, Long rootDiskSize) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { _accountMgr.checkAccess(caller, null, true, owner); @@ -2504,7 +2502,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (template != null) { _templateDao.loadDetails(template); } - + long accountId = owner.getId(); assert !(requestedIps != null && (defaultIps.getIp4Address() != null || defaultIps.getIp6Address() != null)) : "requestedIp list and defaultNetworkIp should never be specified together"; @@ -2531,7 +2529,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } ServiceOfferingVO offering = _serviceOfferingDao.findById(serviceOffering.getId()); - // check if account/domain is with in resource limits to create a new vm boolean isIso = Storage.ImageFormat.ISO == template.getFormat(); // For baremetal, size can be null @@ -2543,7 +2540,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (diskOfferingId != null) { size += _diskOfferingDao.findById(diskOfferingId).getDiskSize(); } - resourceLimitCheck(owner, new Long(offering.getCpu()), new Long(offering.getRamSize())); + if (!offering.isDynamic()) { + resourceLimitCheck(owner, new Long(offering.getCpu()), new Long(offering.getRamSize())); + } + else { + resourceLimitCheck(owner, new Long(cpuSpeed), new Long(memory)); + } _resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, (isIso || diskOfferingId == null ? 1 : 2)); _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, new Long (size)); @@ -2732,6 +2734,36 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir long id = _vmDao.getNextInSequence(Long.class, "id"); + List details = new ArrayList(); + if (offering.isDynamic()) { + //insert the custom value of dynamic parameters + if (offering.getCpu() == null) { + if ((cpuNumber != null) && ((cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647))) { + throw new InvalidParameterValueException("Invalid CPU number value, specify a value between 1 and 2147483647"); + } + } + + if (offering.getSpeed() == null) { + if ((cpuSpeed != null) && ((cpuSpeed.intValue() <= 0) || (cpuSpeed.intValue() > 2147483647))) { + throw new InvalidParameterValueException("Invalid CPU speed value, specify a value between 1 and 2147483647"); + } + } + + if (offering.getRamSize() == null) { + if ((memory != null) && ((memory.intValue() < 32) || (memory.intValue() > 2147483647))) { + throw new InvalidParameterValueException("Invalid memory value, specify a value between 32 and 2147483647 MB"); + } + } + + details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.cpuNumber.toString(), cpuNumber.toString())); + details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.cpuSpeed.toString(), cpuSpeed.toString())); + details.add(new UserVmDetailVO(id, ServiceOfferingVO.DynamicParameters.memory.toString(), memory.toString())); + offering = _serviceOfferingDao.getcomputeOffering(serviceOffering.getId(), cpuNumber, cpuSpeed, memory); + } + if (hostName != null) { + // Check is hostName is RFC compliant + checkNameForRFCCompliance(hostName); + } String instanceName = null; @@ -2801,7 +2833,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir UserVmVO vm = commitUserVm(zone, template, hostName, displayName, owner, diskOfferingId, diskSize, userData, hypervisor, caller, isDisplayVmEnabled, keyboard, accountId, offering, isIso, sshPublicKey, - networkNicMap, id, instanceName, uuidName, hypervisorType); + networkNicMap, id, instanceName, uuidName, hypervisorType, rootDiskSize, details); // Assign instance to the group try { @@ -2835,7 +2867,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir final HypervisorType hypervisor, final Account caller, final Boolean isDisplayVmEnabled, final String keyboard, final long accountId, final ServiceOfferingVO offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, final long id, final String instanceName, final String uuidName, - final HypervisorType hypervisorType) throws InsufficientCapacityException { + final HypervisorType hypervisorType, final Long rootDiskSize,final List vmdetails) throws InsufficientCapacityException { return Transaction.execute(new TransactionCallbackWithException() { @Override public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCapacityException { @@ -2849,14 +2881,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (sshPublicKey != null) { vm.setDetail("SSH.PublicKey", sshPublicKey); } - + if (keyboard != null && !keyboard.isEmpty()) vm.setDetail(VmDetailConstants.KEYBOARD, keyboard); - + if (isIso) { vm.setIsoId(template.getId()); } - + if(isDisplayVmEnabled != null){ if(!_accountMgr.isRootAdmin(caller.getType())){ throw new PermissionDeniedException( "Cannot update parameter displayvm, only admin permitted "); @@ -2865,7 +2897,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir }else { vm.setDisplayVm(true); } - + // If hypervisor is vSphere, check for clone type setting. if (hypervisorType.equals(HypervisorType.VMware)) { // retrieve clone flag. @@ -2878,13 +2910,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir UserVmCloneSettingVO vmCloneSettingVO = new UserVmCloneSettingVO(id, cloneType.toString()); _vmCloneSettingDao.persist(vmCloneSettingVO); } - + long guestOSId = template.getGuestOSId(); GuestOSVO guestOS = _guestOSDao.findById(guestOSId); long guestOSCategoryId = guestOS.getCategoryId(); GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId); - - + + // If hypervisor is vSphere and OS is OS X, set special settings. if (hypervisorType.equals(HypervisorType.VMware)) { if (guestOS.getDisplayName().toLowerCase().contains("apple mac os")){ @@ -2894,28 +2926,33 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir s_logger.info("guestOS is OSX : overwrite root disk controller to scsi, use smc and efi"); } } - + Map details = template.getDetails(); if ( details != null && !details.isEmpty() ) { vm.details.putAll(details); } _vmDao.persist(vm); + if (vmdetails != null && vmdetails.size() >0) { + for (UserVmDetailVO detail : vmdetails) { + vm.setDetail(detail.getName(), detail.getValue()); + } + } _vmDao.saveDetails(vm); - + s_logger.debug("Allocating in the DB for vm"); DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); - + List computeTags = new ArrayList(); computeTags.add(offering.getHostTag()); - + List rootDiskTags = new ArrayList(); rootDiskTags.add(offering.getTags()); - + if(isIso){ VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), Long.toString(owner.getAccountId()), vm.getIsoId().toString(), hostName, displayName, hypervisor.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan); }else { - VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachine(vm.getUuid(), Long.toString(owner.getAccountId()), Long.toString(template.getId()), hostName, displayName, hypervisor.name(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan); + VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachine(vm.getUuid(), Long.toString(owner.getAccountId()), Long.toString(template.getId()), hostName, displayName, hypervisor.name(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan, rootDiskSize); } @@ -2924,10 +2961,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir s_logger.debug("Successfully allocated DB entry for " + vm); } CallContext.current().setEventDetails("Vm Id: " + vm.getId()); - - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), - vm.getHostName(), offering.getId(), template.getId(), hypervisorType.toString(), - VirtualMachine.class.getName(), vm.getUuid()); + + if (!offering.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), + vm.getHostName(), offering.getId(), template.getId(), hypervisorType.toString(), + VirtualMachine.class.getName(), vm.getUuid()); + } + else { + HashMap vmdetailsMap = new HashMap(); + for (UserVmDetailVO vmdetail :vmdetails) { + vmdetailsMap.put(vmdetail.getName(), vmdetail.getValue()); + } + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), + vm.getHostName(), offering.getId(), template.getId(), hypervisorType.toString(), + VirtualMachine.class.getName(), vm.getUuid(), vmdetailsMap); + } //Update Resource Count for the given account resourceCountIncrement(accountId, new Long(offering.getCpu()), @@ -3401,7 +3449,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); // Get serviceOffering for Virtual Machine - ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()); + ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()); String plannerName = offering.getDeploymentPlanner(); if (plannerName == null) { if (vm.getHypervisorType() == HypervisorType.BareMetal) { @@ -3477,7 +3525,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (vmState != State.Error) { // Get serviceOffering for Virtual Machine - ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()); + ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()); //Update Resource Count for the given account resourceCountDecrement(vm.getAccountId(), new Long(offering.getCpu()), @@ -3913,7 +3961,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir private boolean isVMUsingLocalStorage(VMInstanceVO vm) { boolean usesLocalStorage = false; - ServiceOfferingVO svcOffering = _serviceOfferingDao.findById(vm + ServiceOfferingVO svcOffering = _serviceOfferingDao.findById(vm.getId(), vm .getServiceOfferingId()); if (svcOffering.getUseLocalStorage()) { usesLocalStorage = true; @@ -4129,7 +4177,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } // Checks for implicitly dedicated hosts - ServiceOfferingVO deployPlanner = _offeringDao.findById(vm.getServiceOfferingId()); + ServiceOfferingVO deployPlanner = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()); if(deployPlanner.getDeploymentPlanner() != null && deployPlanner.getDeploymentPlanner().equals("ImplicitDedicationPlanner")) { //VM is deployed using implicit planner long accountOfVm = vm.getAccountId(); @@ -4153,7 +4201,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir //If vm is deployed using preferred implicit planner, check if all vms on destination host must be //using implicit planner and must belong to same account for (VMInstanceVO vmsDest : vmsOnDest) { - ServiceOfferingVO destPlanner = _offeringDao.findById(vmsDest.getServiceOfferingId()); + ServiceOfferingVO destPlanner = _offeringDao.findById(vm.getId(), vmsDest.getServiceOfferingId()); if (!((destPlanner.getDeploymentPlanner() != null && destPlanner.getDeploymentPlanner().equals("ImplicitDedicationPlanner")) && vmsDest.getAccountId()==accountOfVm)) { msg = "VM of account " + accountOfVm + " with preffered implicit deployment planner being migrated to host " + destHost.getName() + @@ -4494,7 +4542,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir DataCenterVO zone = _dcDao.findById(vm.getDataCenterId()); // Get serviceOffering and Volumes for Virtual Machine - final ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()); + final ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()); final List volumes = _volsDao.findByInstance(cmd.getVmId()); //Remove vm from instance group diff --git a/server/test/com/cloud/capacity/CapacityManagerTest.java b/server/test/com/cloud/capacity/CapacityManagerTest.java index 3faa32f0f6d..300e6b50a65 100644 --- a/server/test/com/cloud/capacity/CapacityManagerTest.java +++ b/server/test/com/cloud/capacity/CapacityManagerTest.java @@ -57,7 +57,7 @@ public class CapacityManagerTest { capMgr=setUp(); when(vm.getHostId()).thenReturn(1l); when(vm.getServiceOfferingId()).thenReturn(2l); - when(SOfferingDao.findById(anyLong())).thenReturn(svo); + when(SOfferingDao.findById(anyLong(), anyLong())).thenReturn(svo); when(CDao.findByHostIdType(anyLong(), eq(Capacity.CAPACITY_TYPE_CPU))).thenReturn(cvo_cpu); when(CDao.findByHostIdType(anyLong(), eq(Capacity.CAPACITY_TYPE_MEMORY))).thenReturn(cvo_ram); when(cvo_cpu.getUsedCapacity()).thenReturn(500l); diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index df676d31594..0a3ed3c93b9 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -367,7 +367,7 @@ public class UserVmManagerTest { ServiceOffering so2 = getSvcoffering(256); when(_entityMgr.findById(eq(ServiceOffering.class), anyLong())).thenReturn(so1); - when(_offeringDao.findByIdIncludingRemoved(anyLong())).thenReturn((ServiceOfferingVO) so1); + when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO) so1); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, UUID.randomUUID().toString()); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); diff --git a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java index f2ebf67acf9..47e509f140c 100644 --- a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java +++ b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java @@ -24,6 +24,9 @@ import java.util.Set; import javax.inject.Inject; +import com.cloud.event.dao.UsageEventDao; +import com.cloud.event.dao.UsageEventDetailsDao; +import com.cloud.vm.dao.UserVmDetailsDao; import junit.framework.TestCase; import org.junit.After; @@ -78,6 +81,15 @@ public class CreateNetworkOfferingTest extends TestCase{ @Inject VpcManager vpcMgr; + @Inject + UserVmDetailsDao userVmDetailsDao; + + @Inject + UsageEventDao UsageEventDao; + + @Inject + UsageEventDetailsDao usageEventDetailsDao; + @Override @Before public void setUp() { diff --git a/server/test/org/apache/cloudstack/service/ServiceOfferingVOTest.java b/server/test/org/apache/cloudstack/service/ServiceOfferingVOTest.java new file mode 100644 index 00000000000..38425c6874c --- /dev/null +++ b/server/test/org/apache/cloudstack/service/ServiceOfferingVOTest.java @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.service; + +import com.cloud.service.ServiceOfferingVO; +import com.cloud.vm.VirtualMachine; +import org.junit.Before; +import org.junit.Test; +import org.junit.Assert; +import org.mockito.MockitoAnnotations; + +public class ServiceOfferingVOTest { + ServiceOfferingVO offeringCustom; + ServiceOfferingVO offering; + + + @Before + public void setup(){ + MockitoAnnotations.initMocks(this); + offeringCustom = new ServiceOfferingVO("custom", null, null, 500, 10, 10, false, "custom", false, false, "", false, VirtualMachine.Type.User, false); + offering = new ServiceOfferingVO("normal", 1, 1000, 500, 10, 10, false, "normal", false, false, "", false, VirtualMachine.Type.User, false); + } + + // Test restoreVm when VM state not in running/stopped case + @Test + public void isDynamic() { + Assert.assertTrue(offeringCustom.isDynamic()); + } + + @Test + public void notDynamic() { + Assert.assertTrue(!offering.isDynamic()); + } + +} \ No newline at end of file diff --git a/server/test/resources/createNetworkOffering.xml b/server/test/resources/createNetworkOffering.xml index 9d684ba12bb..c6228dab707 100644 --- a/server/test/resources/createNetworkOffering.xml +++ b/server/test/resources/createNetworkOffering.xml @@ -43,5 +43,7 @@ - + + + diff --git a/setup/db/db/schema-421to430.sql b/setup/db/db/schema-421to430.sql index 980650dce17..2dd998b2361 100644 --- a/setup/db/db/schema-421to430.sql +++ b/setup/db/db/schema-421to430.sql @@ -579,3 +579,13 @@ insert into cloud.monitoring_services(id, service, process_name, service_name, s insert into cloud.monitoring_services(id, service, process_name, service_name, service_path, pidfile, isDefault) values(2,'dhcp','dnsmasq','dnsmasq','/etc/init.d/dnsmasq','/var/run/dnsmasq/dnsmasq.pid',false); insert into cloud.monitoring_services(id, service, process_name, service_name, service_path, pidfile, isDefault) values(3,'loadbalancing','haproxy','haproxy','/etc/init.d/haproxy','/var/run/haproxy.pid',false); insert into cloud.monitoring_services(id, service, process_name, service_name, service_path, pidfile, isDefault) values(4,'webserver','apache2','apache2','/etc/init.d/apache2','/var/run/apache2.pid', true); +ALTER TABLE `cloud`.`service_offering` CHANGE COLUMN `cpu` `cpu` INT(10) UNSIGNED NULL COMMENT '# of cores' , CHANGE COLUMN `speed` `speed` INT(10) UNSIGNED NULL COMMENT 'speed per core in mhz' , CHANGE COLUMN `ram_size` `ram_size` BIGINT(20) UNSIGNED NULL ; + +CREATE TABLE `cloud`.`usage_event_details` ( + `id` bigint unsigned NOT NULL auto_increment, + `usage_event_id` bigint unsigned NOT NULL COMMENT 'usage event id', + `name` varchar(255) NOT NULL, + `value` varchar(1024) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_usage_event_details__usage_event_id` FOREIGN KEY `fk_usage_event_details__usage_event_id`(`usage_event_id`) REFERENCES `usage_event`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8;