diff --git a/api/src/com/cloud/configuration/Resource.java b/api/src/com/cloud/configuration/Resource.java index 0fd51dc2f17..76f2930e615 100644 --- a/api/src/com/cloud/configuration/Resource.java +++ b/api/src/com/cloud/configuration/Resource.java @@ -38,8 +38,8 @@ public interface Resource { private ResourceOwnerType[] supportedOwners; private int ordinal; public static final long bytesToKiB = 1024; - public static final long bytesToMiB = 1024 * 1024; - public static final long bytesToGiB = 1024 * 1024 * 1024; + public static final long bytesToMiB = bytesToKiB * 1024; + public static final long bytesToGiB = bytesToMiB * 1024; ResourceType(String name, int ordinal, ResourceOwnerType... supportedOwners) { this.name = name; diff --git a/api/src/main/java/com/cloud/exception/UnavailableCommandException.java b/api/src/com/cloud/exception/UnavailableCommandException.java similarity index 100% rename from api/src/main/java/com/cloud/exception/UnavailableCommandException.java rename to api/src/com/cloud/exception/UnavailableCommandException.java diff --git a/api/src/org/apache/cloudstack/acl/RoleService.java b/api/src/org/apache/cloudstack/acl/RoleService.java index 721bef08c20..6130c62a7d4 100644 --- a/api/src/org/apache/cloudstack/acl/RoleService.java +++ b/api/src/org/apache/cloudstack/acl/RoleService.java @@ -17,38 +17,64 @@ package org.apache.cloudstack.acl; +import java.util.List; + import org.apache.cloudstack.acl.RolePermission.Permission; import org.apache.cloudstack.framework.config.ConfigKey; -import java.util.List; - public interface RoleService { ConfigKey EnableDynamicApiChecker = new ConfigKey<>("Advanced", Boolean.class, "dynamic.apichecker.enabled", "false", - "If set to true, this enables the dynamic role-based api access checker and disables the default static role-based api access checker.", - true); + "If set to true, this enables the dynamic role-based api access checker and disables the default static role-based api access checker.", true); boolean isEnabled(); - Role findRole(final Long id); - Role createRole(final String name, final RoleType roleType, final String description); - Role updateRole(final Role role, final String name, final RoleType roleType, final String description); - boolean deleteRole(final Role role); - RolePermission findRolePermission(final Long id); - RolePermission findRolePermissionByUuid(final String uuid); + /** + * Searches for a role with the given ID. If the ID is null or less than zero, this method will return null. + * This method will also return null if no role is found with the provided ID. + * Moreover, we will check if the requested role is of 'Admin' type; roles with 'Admin' type should only be visible to 'root admins'. + * Therefore, if a non-'root admin' user tries to search for an 'Admin' role, this method will return null. + */ + Role findRole(Long id); + + Role createRole(String name, RoleType roleType, String description); + + Role updateRole(Role role, String name, RoleType roleType, String description); + + boolean deleteRole(Role role); + + RolePermission findRolePermission(Long id); + + RolePermission findRolePermissionByUuid(String uuid); + + RolePermission createRolePermission(Role role, Rule rule, Permission permission, String description); - RolePermission createRolePermission(final Role role, final Rule rule, final Permission permission, final String description); /** * updateRolePermission updates the order/position of an role permission * @param role The role whose permissions needs to be re-ordered * @param newOrder The new list of ordered role permissions */ - boolean updateRolePermission(final Role role, final List newOrder); - boolean updateRolePermission(final Role role, final RolePermission rolePermission, final Permission permission); - boolean deleteRolePermission(final RolePermission rolePermission); + boolean updateRolePermission(Role role, List newOrder); + boolean updateRolePermission(Role role, RolePermission rolePermission, Permission permission); + + boolean deleteRolePermission(RolePermission rolePermission); + + /** + * List all roles configured in the database. Roles that have the type {@link RoleType#Admin} will not be shown for users that are not 'root admin'. + */ List listRoles(); - List findRolesByName(final String name); - List findRolesByType(final RoleType roleType); - List findAllPermissionsBy(final Long roleId); + + /** + * Find all roles that have the giving {@link String} as part of their name. + * If the user calling the method is not a 'root admin', roles of type {@link RoleType#Admin} wil lbe removed of the returned list. + */ + List findRolesByName(String name); + + /** + * Find all roles by {@link RoleType}. If the role type is {@link RoleType#Admin}, the calling account must be a root admin, otherwise we return an empty list. + */ + List findRolesByType(RoleType roleType); + + List findAllPermissionsBy(Long roleId); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java index 5cf870bfc06..9025e89a93c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java @@ -17,31 +17,25 @@ package org.apache.cloudstack.api.command.admin.acl; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.user.Account; -import com.google.common.base.Strings; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import org.apache.cloudstack.acl.Role; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.RoleResponse; +import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import com.cloud.user.Account; +import com.google.common.base.Strings; -@APICommand(name = ListRolesCmd.APINAME, description = "Lists dynamic roles in CloudStack", responseObject = RoleResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, - since = "4.9.0", - authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin}) +@APICommand(name = ListRolesCmd.APINAME, description = "Lists dynamic roles in CloudStack", responseObject = RoleResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.9.0", authorized = { + RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin}) public class ListRolesCmd extends BaseCmd { public static final String APINAME = "listRoles"; @@ -112,13 +106,13 @@ public class ListRolesCmd extends BaseCmd { } @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - final List roles; + public void execute() { + List roles; if (getId() != null && getId() > 0L) { roles = Collections.singletonList(roleService.findRole(getId())); - } else if (!Strings.isNullOrEmpty(getName())) { + } else if (StringUtils.isNotBlank(getName())) { roles = roleService.findRolesByName(getName()); - } else if (getRoleType() != null){ + } else if (getRoleType() != null) { roles = roleService.findRolesByType(getRoleType()); } else { roles = roleService.listRoles(); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/RoleCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/RoleCmd.java similarity index 100% rename from api/src/main/java/org/apache/cloudstack/api/command/admin/acl/RoleCmd.java rename to api/src/org/apache/cloudstack/api/command/admin/acl/RoleCmd.java diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java index 7b48a1ea8a1..18b11f10bd1 100644 --- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.EntityReference; import com.cloud.serializer.Param; import com.cloud.user.Account; -@SuppressWarnings("unused") @EntityReference(value = Account.class) public class AccountResponse extends BaseResponse implements ResourceLimitAndCountResponse { @SerializedName(ApiConstants.ID) @@ -222,7 +221,7 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou @SerializedName("secondarystoragetotal") @Param(description = "the total secondary storage space (in GiB) owned by account", since = "4.2.0") - private Long secondaryStorageTotal; + private float secondaryStorageTotal; @SerializedName("secondarystorageavailable") @Param(description = "the total secondary storage space (in GiB) available to be used for this account", since = "4.2.0") @@ -501,7 +500,7 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou } @Override - public void setSecondaryStorageTotal(Long secondaryStorageTotal) { + public void setSecondaryStorageTotal(float secondaryStorageTotal) { this.secondaryStorageTotal = secondaryStorageTotal; } diff --git a/api/src/org/apache/cloudstack/api/response/DomainResponse.java b/api/src/org/apache/cloudstack/api/response/DomainResponse.java index e848759c9e4..7e5bd970d29 100644 --- a/api/src/org/apache/cloudstack/api/response/DomainResponse.java +++ b/api/src/org/apache/cloudstack/api/response/DomainResponse.java @@ -165,7 +165,7 @@ public class DomainResponse extends BaseResponse implements ResourceLimitAndCoun private String secondaryStorageLimit; @SerializedName("secondarystoragetotal") @Param(description="the total secondary storage space (in GiB) owned by domain", since="4.2.0") - private Long secondaryStorageTotal; + private float secondaryStorageTotal; @SerializedName("secondarystorageavailable") @Param(description="the total secondary storage space (in GiB) available to be used for this domain", since="4.2.0") private String secondaryStorageAvailable; @@ -399,7 +399,7 @@ public class DomainResponse extends BaseResponse implements ResourceLimitAndCoun } @Override - public void setSecondaryStorageTotal(Long secondaryStorageTotal) { + public void setSecondaryStorageTotal(float secondaryStorageTotal) { this.secondaryStorageTotal = secondaryStorageTotal; } diff --git a/api/src/org/apache/cloudstack/api/response/ProjectResponse.java b/api/src/org/apache/cloudstack/api/response/ProjectResponse.java index 0ae9e18612e..8bfa6d94b63 100644 --- a/api/src/org/apache/cloudstack/api/response/ProjectResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ProjectResponse.java @@ -29,7 +29,6 @@ import com.cloud.projects.Project; import com.cloud.serializer.Param; @EntityReference(value = Project.class) -@SuppressWarnings("unused") public class ProjectResponse extends BaseResponse implements ResourceLimitAndCountResponse { @SerializedName(ApiConstants.ID) @@ -134,7 +133,7 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou @SerializedName("secondarystoragetotal") @Param(description = "the total secondary storage space (in GiB) owned by project", since = "4.2.0") - private Long secondaryStorageTotal; + private float secondaryStorageTotal; @SerializedName("secondarystorageavailable") @Param(description = "the total secondary storage space (in GiB) available to be used for this project", since = "4.2.0") @@ -414,7 +413,7 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou } @Override - public void setSecondaryStorageTotal(Long secondaryStorageTotal) { + public void setSecondaryStorageTotal(float secondaryStorageTotal) { this.secondaryStorageTotal = secondaryStorageTotal; } diff --git a/api/src/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java b/api/src/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java index ba97c2c83ce..f247be834cb 100644 --- a/api/src/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java @@ -54,7 +54,7 @@ public interface ResourceLimitAndCountResponse { public void setSecondaryStorageLimit(String secondaryStorageLimit); - public void setSecondaryStorageTotal(Long secondaryStorageTotal); + public void setSecondaryStorageTotal(float secondaryStorageTotal); public void setSecondaryStorageAvailable(String secondaryStorageAvailable); diff --git a/core/src/com/cloud/storage/template/IsoProcessor.java b/core/src/com/cloud/storage/template/IsoProcessor.java index 271818ccd91..4cd2f1a2a02 100644 --- a/core/src/com/cloud/storage/template/IsoProcessor.java +++ b/core/src/com/cloud/storage/template/IsoProcessor.java @@ -37,6 +37,11 @@ public class IsoProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName) { + return process(templatePath, format, templateName, 0); + } + + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) { if (format != null) { s_logger.debug("We don't handle conversion from " + format + " to ISO."); return null; diff --git a/core/src/com/cloud/storage/template/OVAProcessor.java b/core/src/com/cloud/storage/template/OVAProcessor.java index 08087bfb9c8..f29efb46b52 100644 --- a/core/src/com/cloud/storage/template/OVAProcessor.java +++ b/core/src/com/cloud/storage/template/OVAProcessor.java @@ -42,11 +42,15 @@ import com.cloud.utils.script.Script; public class OVAProcessor extends AdapterBase implements Processor { private static final Logger s_logger = Logger.getLogger(OVAProcessor.class); - StorageLayer _storage; @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + return process(templatePath, format, templateName, 0); + } + + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { if (s_logger.isInfoEnabled()) { s_logger.info("We currently don't handle conversion from " + format + " to OVA."); @@ -66,8 +70,7 @@ public class OVAProcessor extends AdapterBase implements Processor { s_logger.info("Template processing - untar OVA package. templatePath: " + templatePath + ", templateName: " + templateName); String templateFileFullPath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension(); File templateFile = new File(templateFileFullPath); - - Script command = new Script("tar", 0, s_logger); + Script command = new Script("tar", processTimeout, s_logger); command.add("--no-same-owner"); command.add("--no-same-permissions"); command.add("-xf", templateFileFullPath); diff --git a/core/src/com/cloud/storage/template/Processor.java b/core/src/com/cloud/storage/template/Processor.java index ba57563e1b6..c8ee18109a1 100644 --- a/core/src/com/cloud/storage/template/Processor.java +++ b/core/src/com/cloud/storage/template/Processor.java @@ -44,6 +44,8 @@ public interface Processor extends Adapter { */ FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException; + FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException; + public static class FormatInfo { public ImageFormat format; public long size; diff --git a/core/src/com/cloud/storage/template/QCOW2Processor.java b/core/src/com/cloud/storage/template/QCOW2Processor.java index 642d8d3cb7b..56ae078dc51 100644 --- a/core/src/com/cloud/storage/template/QCOW2Processor.java +++ b/core/src/com/cloud/storage/template/QCOW2Processor.java @@ -40,8 +40,13 @@ public class QCOW2Processor extends AdapterBase implements Processor { private StorageLayer _storage; + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + return process(templatePath, format, templateName, 0); + } + @Override - public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { s_logger.debug("We currently don't handle conversion from " + format + " to QCOW2."); return null; diff --git a/core/src/com/cloud/storage/template/RawImageProcessor.java b/core/src/com/cloud/storage/template/RawImageProcessor.java index 5645a3199a7..5fbc626f271 100644 --- a/core/src/com/cloud/storage/template/RawImageProcessor.java +++ b/core/src/com/cloud/storage/template/RawImageProcessor.java @@ -45,8 +45,13 @@ public class RawImageProcessor extends AdapterBase implements Processor { return true; } + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + return process(templatePath, format, templateName, 0); + } + @Override - public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { s_logger.debug("We currently don't handle conversion from " + format + " to raw image."); return null; diff --git a/core/src/com/cloud/storage/template/TARProcessor.java b/core/src/com/cloud/storage/template/TARProcessor.java index dfd9a0adf25..51aeb234c50 100644 --- a/core/src/com/cloud/storage/template/TARProcessor.java +++ b/core/src/com/cloud/storage/template/TARProcessor.java @@ -35,6 +35,11 @@ public class TARProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName) { + return process(templatePath, format, templateName, 0); + } + + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) { if (format != null) { s_logger.debug("We currently don't handle conversion from " + format + " to TAR."); return null; diff --git a/core/src/com/cloud/storage/template/VhdProcessor.java b/core/src/com/cloud/storage/template/VhdProcessor.java index cb13d06687b..baea7bf0db5 100644 --- a/core/src/com/cloud/storage/template/VhdProcessor.java +++ b/core/src/com/cloud/storage/template/VhdProcessor.java @@ -58,6 +58,11 @@ public class VhdProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + return process(templatePath, format, templateName, 0); + } + + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { s_logger.debug("We currently don't handle conversion from " + format + " to VHD."); return null; diff --git a/core/src/com/cloud/storage/template/VmdkProcessor.java b/core/src/com/cloud/storage/template/VmdkProcessor.java index eacabb93968..ee50b2718b7 100644 --- a/core/src/com/cloud/storage/template/VmdkProcessor.java +++ b/core/src/com/cloud/storage/template/VmdkProcessor.java @@ -44,6 +44,11 @@ public class VmdkProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException { + return process(templatePath, format, templateName, 0); + } + + @Override + public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { if (s_logger.isInfoEnabled()) { s_logger.info("We currently don't handle conversion from " + format + " to VMDK."); diff --git a/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java b/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java index 29fdd191164..965d30320a8 100644 --- a/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java @@ -51,6 +51,8 @@ public class TemplateOrVolumePostUploadCommand { private String defaultMaxAccountSecondaryStorage; + private long processTimeout; + private long accountId; private Integer nfsVersion; @@ -206,4 +208,12 @@ public class TemplateOrVolumePostUploadCommand { public void setNfsVersion(Integer nfsVersion) { this.nfsVersion = nfsVersion; } + + public void setProcessTimeout(long processTimeout) { + this.processTimeout = processTimeout; + } + + public long getProcessTimeout() { + return processTimeout; + } } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index cec2e5926c1..1b707c3979d 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -38,6 +38,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.StringUtils; import org.apache.log4j.Logger; import org.apache.cloudstack.acl.ControlledEntity.ACLType; @@ -2116,16 +2117,12 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra boolean ipv6 = false; - if (ip6Gateway != null && ip6Cidr != null) { + if (StringUtils.isNotBlank(ip6Gateway) && StringUtils.isNotBlank(ip6Cidr)) { ipv6 = true; } // Validate zone final DataCenterVO zone = _dcDao.findById(zoneId); if (zone.getNetworkType() == NetworkType.Basic) { - if (ipv6) { - throw new InvalidParameterValueException("IPv6 is not supported in Basic zone"); - } - // In Basic zone the network should have aclType=Domain, domainId=1, subdomainAccess=true if (aclType == null || aclType != ACLType.Domain) { throw new InvalidParameterValueException("Only AclType=Domain can be specified for network creation in Basic zone"); @@ -2188,6 +2185,10 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra } } + if (ipv6 && !NetUtils.isValidIp6Cidr(ip6Cidr)) { + throw new InvalidParameterValueException("Invalid IPv6 cidr specified"); + } + //TODO(VXLAN): Support VNI specified // VlanId can be specified only when network offering supports it final boolean vlanSpecified = vlanId != null; @@ -2328,7 +2329,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra userNetwork.setGateway(gateway); } - if (ip6Cidr != null && ip6Gateway != null) { + if (StringUtils.isNotBlank(ip6Gateway) && StringUtils.isNotBlank(ip6Cidr)) { userNetwork.setIp6Cidr(ip6Cidr); userNetwork.setIp6Gateway(ip6Gateway); } diff --git a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java index d4695c3ff75..c1ad254d151 100644 --- a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java +++ b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDao.java @@ -57,4 +57,16 @@ public interface ResourceCountDao extends GenericDao { Set listRowsToUpdateForDomain(long domainId, ResourceType type); long removeEntriesByOwner(long ownerId, ResourceOwnerType ownerType); -} + + /** + * Counts the number of CPU cores allocated for the given account. + * Side note: This method is not using the "resource_count" table. It is executing the actual count instead. + */ + long countCpuNumberAllocatedToAccount(long accountId); + + /** + * Counts the amount of memory allocated for the given account. + * Side note: This method is not using the "resource_count" table. It is executing the actual count instead. + */ + long countMemoryAllocatedToAccount(long accountId); +} \ No newline at end of file diff --git a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java index f7cd3cbf86f..9cc8913f8fa 100644 --- a/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java +++ b/engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java @@ -16,6 +16,9 @@ // under the License. package com.cloud.configuration.dao; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -42,6 +45,7 @@ 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 com.cloud.utils.exception.CloudRuntimeException; @Component public class ResourceCountDaoImpl extends GenericDaoBase implements ResourceCountDao { @@ -248,4 +252,41 @@ public class ResourceCountDaoImpl extends GenericDaoBase return 0; } + private String baseSqlCountComputingResourceAllocatedToAccount = "Select " + + " SUM((CASE " + + " WHEN so.%s is not null THEN so.%s " + + " ELSE CONVERT(vmd.value, UNSIGNED INTEGER) " + + " END)) as total " + + " from vm_instance vm " + + " join service_offering_view so on so.id = vm.service_offering_id " + + " left join user_vm_details vmd on vmd.vm_id = vm.id and vmd.name = '%s' " + + " where vm.type = 'User' and state not in ('Destroyed', 'Error', 'Expunging') and display_vm = true and account_id = ? "; + + @Override + public long countCpuNumberAllocatedToAccount(long accountId) { + String sqlCountCpuNumberAllocatedToAccount = String.format(baseSqlCountComputingResourceAllocatedToAccount, ResourceType.cpu, ResourceType.cpu, "cpuNumber"); + return executeSqlCountComputingResourcesForAccount(accountId, sqlCountCpuNumberAllocatedToAccount); + } + + @Override + public long countMemoryAllocatedToAccount(long accountId) { + String serviceOfferingRamSizeField = "ram_size"; + String sqlCountCpuNumberAllocatedToAccount = String.format(baseSqlCountComputingResourceAllocatedToAccount, serviceOfferingRamSizeField, serviceOfferingRamSizeField, "memory"); + return executeSqlCountComputingResourcesForAccount(accountId, sqlCountCpuNumberAllocatedToAccount); + } + + private long executeSqlCountComputingResourcesForAccount(long accountId, String sqlCountComputingResourcesAllocatedToAccount) { + try (TransactionLegacy tx = TransactionLegacy.currentTxn()) { + PreparedStatement pstmt = tx.prepareAutoCloseStatement(sqlCountComputingResourcesAllocatedToAccount); + pstmt.setLong(1, accountId); + + ResultSet rs = pstmt.executeQuery(); + if (!rs.next()) { + throw new CloudRuntimeException(String.format("An unexpected case happened while counting allocated computing resources for account: " + accountId)); + } + return rs.getLong("total"); + } catch (SQLException e) { + throw new CloudRuntimeException(e); + } + } } \ No newline at end of file diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index d8076fd5d68..81dfc33bb88 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -32,6 +32,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -434,13 +435,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co @DB public Pair getCommandHostDelegation(long hostId, Command cmd) { boolean needDelegation = false; - if (cmd instanceof StorageSubSystemCommand) { Boolean fullCloneEnabled = VmwareFullClone.value(); StorageSubSystemCommand c = (StorageSubSystemCommand)cmd; c.setExecuteInSequence(fullCloneEnabled); } - + if (cmd instanceof DownloadCommand) { + cmd.setContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key(), String.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.value())); + } //NOTE: the hostid can be a hypervisor host, or a ssvm agent. For copycommand, if it's for volume upload, the hypervisor //type is empty, so we need to check the format of volume at first. if (cmd instanceof CopyCommand) { @@ -514,11 +516,11 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co cmd.setContextParam("execid", String.valueOf(execLog.getId())); cmd.setContextParam("noderuninfo", String.format("%d-%d", _clusterMgr.getManagementNodeId(), _clusterMgr.getCurrentRunId())); cmd.setContextParam("vCenterSessionTimeout", String.valueOf(_vmwareMgr.getVcenterSessionTimeout())); + cmd.setContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key(), String.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.value())); if (cmd instanceof BackupSnapshotCommand || cmd instanceof CreatePrivateTemplateFromVolumeCommand || cmd instanceof CreatePrivateTemplateFromSnapshotCommand || cmd instanceof CopyVolumeCommand || cmd instanceof CopyCommand || cmd instanceof CreateVolumeOVACommand || cmd instanceof PrepareOVAPackingCommand || cmd instanceof CreateVolumeFromSnapshotCommand) { - String workerName = _vmwareMgr.composeWorkerName(); long checkPointId = 1; // FIXME: Fix long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName)); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java index 4a4d2ea7a53..efdbc724fbd 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java @@ -42,6 +42,9 @@ public interface VmwareManager { static final ConfigKey s_vmwareSearchExcludeFolder = new ConfigKey("Advanced", String.class, "vmware.search.exclude.folders", null, "Comma seperated list of Datastore Folders to exclude from VMWare search", true, ConfigKey.Scope.Global); + static final ConfigKey s_vmwareOVAPackageTimeout = new ConfigKey(Integer.class, "vmware.package.ova.timeout", "Advanced", "3600", + "Vmware script timeout for ova packaging process", true, ConfigKey.Scope.Global, 1000); + String composeWorkerName(); String getSystemVMIsoFileNameOnDatastore(); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index b7149ab2bf9..3cf0c0000d9 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -136,6 +136,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class); private static final long SECONDS_PER_MINUTE = 60; + private int _timeout; private String _instance; @@ -204,7 +205,6 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw private int _additionalPortRangeSize; private int _routerExtraPublicNics = 2; private int _vCenterSessionTimeout = 1200000; // Timeout in milliseconds - private String _rootDiskController = DiskControllerType.ide.toString(); private final String _dataDiskController = DiskControllerType.osdefault.toString(); @@ -229,9 +229,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {s_vmwareNicHotplugWaitTimeout, s_vmwareCleanOldWorderVMs, templateCleanupInterval, s_vmwareSearchExcludeFolder}; + return new ConfigKey[] {s_vmwareNicHotplugWaitTimeout, s_vmwareCleanOldWorderVMs, templateCleanupInterval, s_vmwareSearchExcludeFolder, s_vmwareOVAPackageTimeout}; } - @Override public boolean configure(String name, Map params) throws ConfigurationException { s_logger.info("Configure VmwareManagerImpl, manager name: " + name); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java index f78f370da31..e7cd91946db 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java @@ -51,7 +51,7 @@ public interface VmwareStorageManager { boolean execute(VmwareHostService hostService, CreateEntityDownloadURLCommand cmd); - public void createOva(String path, String name); + public void createOva(String path, String name, int archiveTimeout); - public String createOvaForTemplate(TemplateObjectTO template); + public String createOvaForTemplate(TemplateObjectTO template, int archiveTimeout); } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index a22410f4afe..b6f207acf10 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -98,28 +98,32 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { @Override public boolean execute(VmwareHostService hostService, CreateEntityDownloadURLCommand cmd) { DataTO data = cmd.getData(); + int timeout = NumbersUtil.parseInt(cmd.getContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key()), + Integer.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.defaultValue()) * VmwareManager.s_vmwareOVAPackageTimeout.multiplier()); if (data == null) { return false; } String newPath = null; if (data.getObjectType() == DataObjectType.VOLUME) { - newPath = createOvaForVolume((VolumeObjectTO)data); + newPath = createOvaForVolume((VolumeObjectTO)data, timeout); } else if (data.getObjectType() == DataObjectType.TEMPLATE) { - newPath = createOvaForTemplate((TemplateObjectTO)data); + newPath = createOvaForTemplate((TemplateObjectTO)data, timeout); } if (newPath != null) { cmd.setInstallPath(newPath); + return true; } - return true; + return false; + } @Override - public void createOva(String path, String name) { + public void createOva(String path, String name, int archiveTimeout) { Script commandSync = new Script(true, "sync", 0, s_logger); commandSync.execute(); - Script command = new Script(false, "tar", 0, s_logger); + Script command = new Script(false, "tar", archiveTimeout, s_logger); command.setWorkDir(path); command.add("-cf", name + ".ova"); command.add(name + ".ovf"); // OVF file should be the first file in OVA archive @@ -155,7 +159,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } @Override - public String createOvaForTemplate(TemplateObjectTO template) { + public String createOvaForTemplate(TemplateObjectTO template, int archiveTimeout) { DataStoreTO storeTO = template.getDataStore(); if (!(storeTO instanceof NfsTO)) { s_logger.debug("Can only handle NFS storage, while creating OVA from template"); @@ -173,7 +177,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { s_logger.debug("OVA file found at: " + installFullPath); } else { if (new File(installFullPath + ".meta").exists()) { - createOVAFromMetafile(installFullPath + ".meta"); + createOVAFromMetafile(installFullPath + ".meta", archiveTimeout); } else { String msg = "Unable to find OVA or OVA MetaFile to prepare template."; s_logger.error(msg); @@ -190,7 +194,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { //Fang: new command added; // Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature) - public String createOvaForVolume(VolumeObjectTO volume) { + public String createOvaForVolume(VolumeObjectTO volume, int archiveTimeout) { DataStoreTO storeTO = volume.getDataStore(); if (!(storeTO instanceof NfsTO)) { s_logger.debug("can only handle nfs storage, when create ova from volume"); @@ -215,15 +219,17 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } else { Script commandSync = new Script(true, "sync", 0, s_logger); commandSync.execute(); - - Script command = new Script(false, "tar", 0, s_logger); + Script command = new Script(false, "tar", archiveTimeout, s_logger); command.setWorkDir(installFullPath); command.add("-cf", volumeUuid + ".ova"); command.add(volumeUuid + ".ovf"); // OVF file should be the first file in OVA archive command.add(volumeUuid + "-disk0.vmdk"); - command.execute(); - return volumePath; + String result = command.execute(); + if (result != Script.ERR_TIMEOUT) { + return volumePath; + } + } } catch (Throwable e) { s_logger.info("Exception for createVolumeOVA"); @@ -1046,7 +1052,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { // here we use a method to return the ovf and vmdk file names; Another way to do it: // create a new class, and like TemplateLocation.java and create templateOvfInfo.java to handle it; - private String createOVAFromMetafile(String metafileName) throws Exception { + private String createOVAFromMetafile(String metafileName, int archiveTimeout) throws Exception { File ova_metafile = new File(metafileName); Properties props = null; String ovaFileName = ""; @@ -1080,7 +1086,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { s_logger.info("ova: " + ovaFileName + ", ovf:" + ovfFileName + ", vmdk:" + disks[0] + "."); Script commandSync = new Script(true, "sync", 0, s_logger); commandSync.execute(); - Script command = new Script(false, "tar", 0, s_logger); + Script command = new Script(false, "tar", archiveTimeout, s_logger); command.setWorkDir(exportDir); // Fang: pass this in to the method? command.add("-cf", ovaFileName); command.add(ovfFileName); // OVF file should be the first file in OVA archive diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java index d0d5964bfa9..ff00f55c8bc 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java @@ -145,8 +145,11 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe } protected Answer execute(CreateEntityDownloadURLCommand cmd) { - _storageMgr.execute(this, cmd); - return _resource.defaultAction(cmd); + boolean success = _storageMgr.execute(this, cmd); + if (success) { + return _resource.defaultAction(cmd); + } + return new Answer(cmd, false, "Failed to download"); } private Answer execute(PrimaryStorageDownloadCommand cmd) { diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageSubsystemCommandHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageSubsystemCommandHandler.java index fc199722b2b..02ae2fe5033 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageSubsystemCommandHandler.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageSubsystemCommandHandler.java @@ -21,6 +21,8 @@ package com.cloud.storage.resource; import java.io.File; import java.util.EnumMap; +import com.cloud.hypervisor.vmware.manager.VmwareManager; +import com.cloud.utils.NumbersUtil; import org.apache.log4j.Logger; import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.command.CopyCommand; @@ -95,6 +97,8 @@ public class VmwareStorageSubsystemCommandHandler extends StorageSubsystemComman DataTO destData = cmd.getDestTO(); DataStoreTO srcDataStore = srcData.getDataStore(); DataStoreTO destDataStore = destData.getDataStore(); + int timeout = NumbersUtil.parseInt(cmd.getContextParam(VmwareManager.s_vmwareOVAPackageTimeout.key()), + Integer.valueOf(VmwareManager.s_vmwareOVAPackageTimeout.defaultValue()) * VmwareManager.s_vmwareOVAPackageTimeout.multiplier()); //if copied between s3 and nfs cache, go to resource boolean needDelegation = false; if (destDataStore instanceof NfsTO && destDataStore.getRole() == DataStoreRole.ImageCache) { @@ -112,11 +116,11 @@ public class VmwareStorageSubsystemCommandHandler extends StorageSubsystemComman String path = vol.getPath(); int index = path.lastIndexOf(File.separator); String name = path.substring(index + 1); - storageManager.createOva(parentPath + File.separator + path, name); + storageManager.createOva(parentPath + File.separator + path, name, timeout); vol.setPath(path + File.separator + name + ".ova"); } else if (srcData.getObjectType() == DataObjectType.TEMPLATE) { // sync template from NFS cache to S3 in NFS migration to S3 case - storageManager.createOvaForTemplate((TemplateObjectTO)srcData); + storageManager.createOvaForTemplate((TemplateObjectTO)srcData, timeout); } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT) { // pack ova first // sync snapshot from NFS cache to S3 in NFS migration to S3 case @@ -126,7 +130,7 @@ public class VmwareStorageSubsystemCommandHandler extends StorageSubsystemComman int index = path.lastIndexOf(File.separator); String name = path.substring(index + 1); String snapDir = path.substring(0, index); - storageManager.createOva(parentPath + File.separator + snapDir, name); + storageManager.createOva(parentPath + File.separator + snapDir, name, timeout); if (destData.getObjectType() == DataObjectType.TEMPLATE) { //create template from snapshot on src at first, then copy it to s3 TemplateObjectTO cacheTemplate = (TemplateObjectTO)destData; @@ -169,7 +173,7 @@ public class VmwareStorageSubsystemCommandHandler extends StorageSubsystemComman int index = path.lastIndexOf(File.separator); String name = path.substring(index + 1); String dir = path.substring(0, index); - storageManager.createOva(parentPath + File.separator + dir, name); + storageManager.createOva(parentPath + File.separator + dir, name, timeout); newSnapshot.setPath(newSnapshot.getPath() + ".ova"); newSnapshot.setDataStore(cmd.getCacheTO().getDataStore()); CopyCommand newCmd = new CopyCommand(newSnapshot, destData, cmd.getWait(), cmd.executeInSequence()); diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java index e7f96ca4a79..3600ea92e61 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java @@ -43,6 +43,7 @@ import com.cloud.storage.Snapshot.State; import com.cloud.storage.SnapshotVO; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.Volume; import com.cloud.storage.VolumeDetailVO; import com.cloud.storage.VolumeVO; import com.cloud.storage.Storage.StoragePoolType; @@ -474,7 +475,9 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { if (volumes != null) { for (VolumeVO volume : volumes) { - usedIops += volume.getMinIops() != null ? volume.getMinIops() : 0; + if (!Volume.State.Creating.equals(volume.getState())) { + usedIops += volume.getMinIops() != null ? volume.getMinIops() : 0; + } } } diff --git a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java index a8d3b68833d..fdc3cfa40a5 100644 --- a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java @@ -214,7 +214,7 @@ public class AccountJoinDaoImpl extends GenericDaoBase impl //get resource limits for secondary storage space and convert it from Bytes to GiB long secondaryStorageLimit = ApiDBUtils.findCorrectResourceLimit(account.getSecondaryStorageLimit(), account.getId(), ResourceType.secondary_storage); String secondaryStorageLimitDisplay = (fullView || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf(secondaryStorageLimit / ResourceType.bytesToGiB); - long secondaryStorageTotal = (account.getSecondaryStorageTotal() == null) ? 0 : (account.getSecondaryStorageTotal() / ResourceType.bytesToGiB); + float secondaryStorageTotal = (account.getSecondaryStorageTotal() == null) ? 0 : (account.getSecondaryStorageTotal() / (ResourceType.bytesToGiB * 1f)); String secondaryStorageAvail = (fullView || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf((secondaryStorageLimit / ResourceType.bytesToGiB) - secondaryStorageTotal); diff --git a/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java index 497fc2c13a3..a613fcbfe46 100644 --- a/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/DomainJoinDaoImpl.java @@ -183,7 +183,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase implem //get resource limits for secondary storage space and convert it from Bytes to GiB long secondaryStorageLimit = ApiDBUtils.findCorrectResourceLimitForDomain(domain.getSecondaryStorageLimit(), ResourceType.secondary_storage, domain.getId()); String secondaryStorageLimitDisplay = (fullView || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf(secondaryStorageLimit / ResourceType.bytesToGiB); - long secondaryStorageTotal = (domain.getSecondaryStorageTotal() == null) ? 0 : (domain.getSecondaryStorageTotal() / ResourceType.bytesToGiB); + float secondaryStorageTotal = (domain.getSecondaryStorageTotal() == null) ? 0 : (domain.getSecondaryStorageTotal() / (ResourceType.bytesToGiB * 1f)); String secondaryStorageAvail = (fullView || secondaryStorageLimit == -1) ? "Unlimited" : String.valueOf((secondaryStorageLimit / ResourceType.bytesToGiB) - secondaryStorageTotal); response.setSecondaryStorageLimit(secondaryStorageLimitDisplay); response.setSecondaryStorageTotal(secondaryStorageTotal); diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index cc244ce41ba..5d8ad0a7051 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -1040,6 +1040,11 @@ StateListener { for (Long clusterId : clusterList) { ClusterVO clusterVO = _clusterDao.findById(clusterId); + if (clusterVO.getAllocationState() == Grouping.AllocationState.Disabled) { + s_logger.debug("Cannot deploy in disabled cluster " + clusterId + ", skipping this cluster"); + avoid.addCluster(clusterVO.getId()); + } + if (clusterVO.getHypervisorType() != vmProfile.getHypervisorType()) { s_logger.debug("Cluster: " + clusterId + " has HyperVisorType that does not match the VM, skipping this cluster"); avoid.addCluster(clusterVO.getId()); diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 86fa46b6c26..c3fef57e9f1 100644 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -69,7 +69,6 @@ import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount.Role; import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; -import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DataStoreRole; import com.cloud.storage.SnapshotVO; @@ -100,9 +99,6 @@ import com.cloud.utils.db.TransactionCallback; import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @@ -947,51 +943,11 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim } public long countCpusForAccount(long accountId) { - GenericSearchBuilder cpuSearch = _serviceOfferingDao.createSearchBuilder(SumCount.class); - cpuSearch.select("sum", Func.SUM, cpuSearch.entity().getCpu()); - SearchBuilder join1 = _userVmDao.createSearchBuilder(); - join1.and("accountId", join1.entity().getAccountId(), Op.EQ); - join1.and("type", join1.entity().getType(), Op.EQ); - join1.and("state", join1.entity().getState(), SearchCriteria.Op.NIN); - join1.and("displayVm", join1.entity().isDisplayVm(), Op.EQ); - cpuSearch.join("offerings", join1, cpuSearch.entity().getId(), join1.entity().getServiceOfferingId(), JoinBuilder.JoinType.INNER); - cpuSearch.done(); - - SearchCriteria sc = cpuSearch.create(); - sc.setJoinParameters("offerings", "accountId", accountId); - sc.setJoinParameters("offerings", "type", VirtualMachine.Type.User); - sc.setJoinParameters("offerings", "state", new Object[] {State.Destroyed, State.Error, State.Expunging}); - sc.setJoinParameters("offerings", "displayVm", 1); - List cpus = _serviceOfferingDao.customSearch(sc, null); - if (cpus != null) { - return cpus.get(0).sum; - } else { - return 0; - } + return _resourceCountDao.countCpuNumberAllocatedToAccount(accountId); } public long calculateMemoryForAccount(long accountId) { - GenericSearchBuilder memorySearch = _serviceOfferingDao.createSearchBuilder(SumCount.class); - memorySearch.select("sum", Func.SUM, memorySearch.entity().getRamSize()); - SearchBuilder join1 = _userVmDao.createSearchBuilder(); - join1.and("accountId", join1.entity().getAccountId(), Op.EQ); - join1.and("type", join1.entity().getType(), Op.EQ); - join1.and("state", join1.entity().getState(), SearchCriteria.Op.NIN); - join1.and("displayVm", join1.entity().isDisplayVm(), Op.EQ); - memorySearch.join("offerings", join1, memorySearch.entity().getId(), join1.entity().getServiceOfferingId(), JoinBuilder.JoinType.INNER); - memorySearch.done(); - - SearchCriteria sc = memorySearch.create(); - sc.setJoinParameters("offerings", "accountId", accountId); - sc.setJoinParameters("offerings", "type", VirtualMachine.Type.User); - sc.setJoinParameters("offerings", "state", new Object[] {State.Destroyed, State.Error, State.Expunging}); - sc.setJoinParameters("offerings", "displayVm", 1); - List memory = _serviceOfferingDao.customSearch(sc, null); - if (memory != null) { - return memory.get(0).sum; - } else { - return 0; - } + return _resourceCountDao.countMemoryAllocatedToAccount(accountId); } public long calculateSecondaryStorageForAccount(long accountId) { diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 724ca8a4745..46799c76cb0 100644 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -887,10 +887,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C s_logger.warn("Unable to delete storage id: " + id + " due to it is not in Maintenance state"); throw new InvalidParameterValueException("Unable to delete storage due to it is not in Maintenance state, id: " + id); } - if (sPool.isLocal()) { - s_logger.warn("Unable to delete local storage id:" + id); - throw new InvalidParameterValueException("Unable to delete local storage id: " + id); - } Pair vlms = _volsDao.getCountAndTotalByPool(id); if (forced) { @@ -1728,6 +1724,11 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } private boolean checkUsagedSpace(StoragePool pool) { + // Managed storage does not currently deal with accounting for physically used space (only provisioned space). Just return true if "pool" is managed. + if (pool.isManaged()) { + return true; + } + StatsCollector sc = StatsCollector.getInstance(); double storageUsedThreshold = CapacityManager.StorageCapacityDisableThreshold.valueIn(pool.getDataCenterId()); if (sc != null) { @@ -1806,6 +1807,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if(s_logger.isDebugEnabled()) { s_logger.debug("Destination pool id: " + pool.getId()); } + StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); long allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); long totalAskingSize = 0; @@ -1833,70 +1835,114 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl); } } - // A ready state volume is already allocated in a pool. so the asking size is zero for it. - // In case the volume is moving across pools or is not ready yet, the asking size has to be computed + if (s_logger.isDebugEnabled()) { - s_logger.debug("pool id for the volume with id: " + volumeVO.getId() + " is " + volumeVO.getPoolId()); + s_logger.debug("Pool ID for the volume with ID " + volumeVO.getId() + " is " + volumeVO.getPoolId()); } + + // A ready-state volume is already allocated in a pool, so the asking size is zero for it. + // In case the volume is moving across pools or is not ready yet, the asking size has to be computed. if ((volumeVO.getState() != Volume.State.Ready) || (volumeVO.getPoolId() != pool.getId())) { - if (ScopeType.ZONE.equals(poolVO.getScope()) && volumeVO.getTemplateId() != null) { - VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(volumeVO.getTemplateId()); + totalAskingSize += getDataObjectSizeIncludingHypervisorSnapshotReserve(volumeVO, poolVO); - if (tmpl != null && !ImageFormat.ISO.equals(tmpl.getFormat())) { - // Storage plug-ins for zone-wide primary storage can be designed in such a way as to store a template on the - // primary storage once and make use of it in different clusters (via cloning). - // This next call leads to CloudStack asking how many more bytes it will need for the template (if the template is - // already stored on the primary storage, then the answer is 0). - - if (clusterId != null && _clusterDao.getSupportsResigning(clusterId)) { - totalAskingSize += getBytesRequiredForTemplate(tmpl, pool); - } - } - } + totalAskingSize += getAskingSizeForTemplateBasedOnClusterAndStoragePool(volumeVO.getTemplateId(), clusterId, poolVO); } } long totalOverProvCapacity; + if (pool.getPoolType().supportsOverProvisioning()) { BigDecimal overProvFactor = getStorageOverProvisioningFactor(pool.getId()); + totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(pool.getCapacityBytes())).longValue(); - s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with overprovisioning factor " - + overProvFactor.toString()); - s_logger.debug("Total over provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes()); + + s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with over-provisioning factor " + + overProvFactor.toString()); + s_logger.debug("Total over-provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes()); } else { totalOverProvCapacity = pool.getCapacityBytes(); + s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString()); } - s_logger.debug("Total capacity of the pool " + poolVO.getName() + " id: " + pool.getId() + " is " + totalOverProvCapacity); + s_logger.debug("Total capacity of the pool " + poolVO.getName() + " with ID " + pool.getId() + " is " + totalOverProvCapacity); + double storageAllocatedThreshold = CapacityManager.StorageAllocatedCapacityDisableThreshold.valueIn(pool.getDataCenterId()); + if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking pool: " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize : " + totalOverProvCapacity + - ", totalAllocatedSize : " + allocatedSizeWithTemplate + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " + - storageAllocatedThreshold); + s_logger.debug("Checking pool with ID " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize: " + + totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize + + ", allocated disable threshold: " + storageAllocatedThreshold); } double usedPercentage = (allocatedSizeWithTemplate + totalAskingSize) / (double)(totalOverProvCapacity); + if (usedPercentage > storageAllocatedThreshold) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() + - " since its allocated percentage: " + usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + + s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() + + " since its allocated percentage " + usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold " + storageAllocatedThreshold + ", skipping this pool"); } + return false; } if (totalOverProvCapacity < (allocatedSizeWithTemplate + totalAskingSize)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() + - ", not enough storage, maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + allocatedSizeWithTemplate + ", askingSize : " + + s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() + + "; not enough storage, maxSize: " + totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize); } + return false; } + return true; } + /** + * Storage plug-ins for managed storage can be designed in such a way as to store a template on the primary storage once and + * make use of it via storage-side cloning. + * + * This method determines how many more bytes it will need for the template (if the template is already stored on the primary storage, + * then the answer is 0). + */ + private long getAskingSizeForTemplateBasedOnClusterAndStoragePool(Long templateId, Long clusterId, StoragePoolVO storagePoolVO) { + if (templateId == null || clusterId == null || storagePoolVO == null || !storagePoolVO.isManaged()) { + return 0; + } + + VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(templateId); + + if (tmpl == null || ImageFormat.ISO.equals(tmpl.getFormat())) { + return 0; + } + + HypervisorType hypervisorType = tmpl.getHypervisorType(); + + // The getSupportsResigning method is applicable for XenServer as a UUID-resigning patch may or may not be installed on those hypervisor hosts. + if (_clusterDao.getSupportsResigning(clusterId) || HypervisorType.VMware.equals(hypervisorType) || HypervisorType.KVM.equals(hypervisorType)) { + return getBytesRequiredForTemplate(tmpl, storagePoolVO); + } + + return 0; + } + + private long getDataObjectSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); + DataStoreDriver storeDriver = storeProvider.getDataStoreDriver(); + + if (storeDriver instanceof PrimaryDataStoreDriver) { + PrimaryDataStoreDriver primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver; + + VolumeInfo volumeInfo = volFactory.getVolume(volume.getId()); + + return primaryStoreDriver.getDataObjectSizeIncludingHypervisorSnapshotReserve(volumeInfo, pool); + } + + return volume.getSize(); + } + private DiskOfferingVO getDiskOfferingVO(Volume volume) { Long diskOfferingId = volume.getDiskOfferingId(); @@ -1915,21 +1961,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return null; } - private long getDataObjectSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { - DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); - DataStoreDriver storeDriver = storeProvider.getDataStoreDriver(); - - if (storeDriver instanceof PrimaryDataStoreDriver) { - PrimaryDataStoreDriver primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver; - - VolumeInfo volumeInfo = volFactory.getVolume(volume.getId()); - - return primaryStoreDriver.getDataObjectSizeIncludingHypervisorSnapshotReserve(volumeInfo, pool); - } - - return volume.getSize(); - } - private long getBytesRequiredForTemplate(VMTemplateVO tmpl, StoragePool pool) { DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); DataStoreDriver storeDriver = storeProvider.getDataStoreDriver(); diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index bea9b4ad5bf..69dfd1d86f3 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -367,6 +367,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic dataObject.getDataStore().getRole().toString()); command.setLocalPath(volumeStore.getLocalDownloadPath()); //using the existing max upload size configuration + command.setProcessTimeout(NumbersUtil.parseLong(_configDao.getValue("vmware.package.ova.timeout"), 3600)); command.setMaxUploadSize(_configDao.getValue(Config.MaxUploadVolumeSize.key())); command.setDefaultMaxAccountSecondaryStorage(_configDao.getValue(Config.DefaultMaxAccountSecondaryStorage.key())); command.setAccountId(vol.getAccountId()); diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index e526363799a..c798c820250 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -39,10 +39,6 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupService; @@ -80,7 +76,6 @@ import org.apache.cloudstack.engine.service.api.OrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; @@ -89,7 +84,6 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.command.DettachCommand; @@ -97,6 +91,10 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -125,7 +123,6 @@ import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; -import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityManager; import com.cloud.configuration.Config; @@ -136,14 +133,14 @@ import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.DedicatedResourceVO; import com.cloud.dc.HostPodVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; -import com.cloud.dc.Vlan; -import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlanner; @@ -211,9 +208,7 @@ import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.dao.SecurityGroupDao; -import com.cloud.network.security.dao.SecurityGroupVMMapDao; import com.cloud.network.vpc.VpcManager; -import com.cloud.network.vpc.dao.VpcDao; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Availability; @@ -222,10 +217,8 @@ import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.org.Cluster; import com.cloud.org.Grouping; -import com.cloud.projects.ProjectManager; import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; -import com.cloud.server.ConfigurationServer; import com.cloud.server.ManagementService; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -234,15 +227,15 @@ import com.cloud.storage.DataStoreRole; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; +import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage; -import com.cloud.storage.Snapshot; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.TemplateType; -import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.Volume; @@ -253,11 +246,8 @@ import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateApiService; import com.cloud.template.TemplateManager; import com.cloud.template.VirtualMachineTemplate; @@ -305,254 +295,224 @@ import com.cloud.vm.dao.InstanceGroupDao; import com.cloud.vm.dao.InstanceGroupVMMapDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicExtraDhcpOptionDao; -import com.cloud.vm.dao.SecondaryStorageVmDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.snapshot.VMSnapshotManager; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; -import com.cloud.storage.snapshot.SnapshotApiService; -import com.cloud.storage.VMTemplateStorageResourceAssoc; + public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable { private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class); - private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3 seconds - private static final long GB_TO_BYTES = 1024 * 1024 * 1024; + /** + * The number of seconds to wait before timing out when trying to acquire a global lock. + */ + private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; + + private static final long GiB_TO_BYTES = 1024 * 1024 * 1024; @Inject - EntityManager _entityMgr; + private EntityManager _entityMgr; @Inject - protected HostDao _hostDao = null; + private HostDao _hostDao; @Inject - protected ServiceOfferingDao _offeringDao = null; + private ServiceOfferingDao _offeringDao; @Inject - protected DiskOfferingDao _diskOfferingDao = null; + private DiskOfferingDao _diskOfferingDao; @Inject - protected VMTemplateDao _templateDao = null; + private VMTemplateDao _templateDao; @Inject - protected VMTemplateDetailsDao _templateDetailsDao = null; + private VMTemplateZoneDao _templateZoneDao; @Inject - protected VMTemplateZoneDao _templateZoneDao = null; + private TemplateDataStoreDao _templateStoreDao; @Inject - protected TemplateDataStoreDao _templateStoreDao; + private DomainDao _domainDao; @Inject - protected DomainDao _domainDao = null; + private UserVmDao _vmDao; @Inject - protected UserVmDao _vmDao = null; + private VolumeDao _volsDao; @Inject - protected UserVmJoinDao _vmJoinDao = null; + private DataCenterDao _dcDao; @Inject - protected VolumeDao _volsDao = null; + private FirewallRulesDao _rulesDao; @Inject - protected DataCenterDao _dcDao = null; + private LoadBalancerVMMapDao _loadBalancerVMMapDao; @Inject - protected FirewallRulesDao _rulesDao = null; + private PortForwardingRulesDao _portForwardingDao; @Inject - protected LoadBalancerVMMapDao _loadBalancerVMMapDao = null; + private IPAddressDao _ipAddressDao; @Inject - protected PortForwardingRulesDao _portForwardingDao; + private HostPodDao _podDao; @Inject - protected IPAddressDao _ipAddressDao = null; + private NetworkModel _networkModel; @Inject - protected HostPodDao _podDao = null; + private NetworkOrchestrationService _networkMgr; @Inject - protected NetworkModel _networkModel = null; + private AgentManager _agentMgr; @Inject - protected NetworkOrchestrationService _networkMgr = null; + private ConfigurationManager _configMgr; @Inject - protected StorageManager _storageMgr = null; + private AccountDao _accountDao; @Inject - protected SnapshotManager _snapshotMgr = null; + private UserDao _userDao; @Inject - protected AgentManager _agentMgr = null; + private SnapshotDao _snapshotDao; @Inject - protected ConfigurationManager _configMgr = null; + private GuestOSDao _guestOSDao; @Inject - protected AccountDao _accountDao = null; + private HighAvailabilityManager _haMgr; @Inject - protected UserDao _userDao = null; + private AlertManager _alertMgr; @Inject - protected SnapshotDao _snapshotDao = null; + private AccountManager _accountMgr; @Inject - protected GuestOSDao _guestOSDao = null; + private AccountService _accountService; @Inject - protected HighAvailabilityManager _haMgr = null; + private ClusterDao _clusterDao; @Inject - protected AlertManager _alertMgr = null; + private PrimaryDataStoreDao _storagePoolDao; @Inject - protected AccountManager _accountMgr; + private SecurityGroupManager _securityGroupMgr; @Inject - protected AccountService _accountService; + private ServiceOfferingDao _serviceOfferingDao; @Inject - protected AsyncJobManager _asyncMgr; + private NetworkOfferingDao _networkOfferingDao; @Inject - protected ClusterDao _clusterDao; + private InstanceGroupDao _vmGroupDao; @Inject - protected PrimaryDataStoreDao _storagePoolDao; + private InstanceGroupVMMapDao _groupVMMapDao; @Inject - protected SecurityGroupManager _securityGroupMgr; + private VirtualMachineManager _itMgr; @Inject - protected ServiceOfferingDao _serviceOfferingDao; + private NetworkDao _networkDao; @Inject - protected NetworkOfferingDao _networkOfferingDao; + private NicDao _nicDao; @Inject - protected InstanceGroupDao _vmGroupDao; + private RulesManager _rulesMgr; @Inject - protected InstanceGroupVMMapDao _groupVMMapDao; + private LoadBalancingRulesManager _lbMgr; @Inject - protected VirtualMachineManager _itMgr; + private SSHKeyPairDao _sshKeyPairDao; @Inject - protected NetworkDao _networkDao; + private UserVmDetailsDao _vmDetailsDao; @Inject - protected NicDao _nicDao; + private HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; @Inject - protected ServiceOfferingDao _offerringDao; + private SecurityGroupDao _securityGroupDao; @Inject - protected VpcDao _vpcDao; + private CapacityManager _capacityMgr; @Inject - protected RulesManager _rulesMgr; + private VMInstanceDao _vmInstanceDao; @Inject - protected LoadBalancingRulesManager _lbMgr; + private ResourceLimitService _resourceLimitMgr; @Inject - protected SSHKeyPairDao _sshKeyPairDao; + private FirewallManager _firewallMgr; @Inject - protected UserVmDetailsDao _vmDetailsDao; + private ResourceManager _resourceMgr; @Inject - protected HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; + private NetworkServiceMapDao _ntwkSrvcDao; @Inject - protected SecurityGroupDao _securityGroupDao; + private PhysicalNetworkDao _physicalNetworkDao; @Inject - protected CapacityManager _capacityMgr; + private VpcManager _vpcMgr; @Inject - protected VMInstanceDao _vmInstanceDao; + private TemplateManager _templateMgr; @Inject - protected ResourceLimitService _resourceLimitMgr; + private GuestOSCategoryDao _guestOSCategoryDao; @Inject - protected FirewallManager _firewallMgr; + private UsageEventDao _usageEventDao; @Inject - protected ProjectManager _projectMgr; + private VmDiskStatisticsDao _vmDiskStatsDao; @Inject - protected ResourceManager _resourceMgr; + private VMSnapshotDao _vmSnapshotDao; @Inject - protected NetworkServiceMapDao _ntwkSrvcDao; + private VMSnapshotManager _vmSnapshotMgr; @Inject - SecurityGroupVMMapDao _securityGroupVMMapDao; + private AffinityGroupVMMapDao _affinityGroupVMMapDao; @Inject - protected ItWorkDao _workDao; + private AffinityGroupDao _affinityGroupDao; @Inject - ResourceTagDao _resourceTagDao; + private DedicatedResourceDao _dedicatedDao; @Inject - PhysicalNetworkDao _physicalNetworkDao; + private AffinityGroupService _affinityGroupService; @Inject - VpcManager _vpcMgr; - @Inject - TemplateManager _templateMgr; - @Inject - protected GuestOSCategoryDao _guestOSCategoryDao; - @Inject - UsageEventDao _usageEventDao; - @Inject - SecondaryStorageVmDao _secondaryDao; - @Inject - VmDiskStatisticsDao _vmDiskStatsDao; - @Inject - protected VMSnapshotDao _vmSnapshotDao; - @Inject - protected VMSnapshotManager _vmSnapshotMgr; - @Inject - AffinityGroupVMMapDao _affinityGroupVMMapDao; - @Inject - AffinityGroupDao _affinityGroupDao; - @Inject - TemplateDataFactory templateFactory; - @Inject - DedicatedResourceDao _dedicatedDao; - @Inject - ConfigurationServer _configServer; - @Inject - AffinityGroupService _affinityGroupService; - @Inject - PlannerHostReservationDao _plannerHostReservationDao; + private PlannerHostReservationDao _plannerHostReservationDao; @Inject private ServiceOfferingDetailsDao serviceOfferingDetailsDao; @Inject private UserStatisticsDao _userStatsDao; @Inject - protected VlanDao _vlanDao; + private VlanDao _vlanDao; @Inject - VolumeService _volService; + private VolumeService _volService; @Inject - VolumeDataFactory volFactory; + private VolumeDataFactory volFactory; @Inject - UserVmDetailsDao _uservmDetailsDao; + private UserVmDetailsDao _uservmDetailsDao; @Inject - UUIDManager _uuidMgr; + private UUIDManager _uuidMgr; @Inject - DeploymentPlanningManager _planningMgr; + private DeploymentPlanningManager _planningMgr; @Inject - VolumeApiService _volumeService; + private VolumeApiService _volumeService; @Inject - DataStoreManager _dataStoreMgr; + private DataStoreManager _dataStoreMgr; @Inject - VpcVirtualNetworkApplianceManager _virtualNetAppliance; + private VpcVirtualNetworkApplianceManager _virtualNetAppliance; @Inject - DomainRouterDao _routerDao; + private DomainRouterDao _routerDao; @Inject - protected VMNetworkMapDao _vmNetworkMapDao; + private VMNetworkMapDao _vmNetworkMapDao; @Inject - protected IpAddressManager _ipAddrMgr; + private IpAddressManager _ipAddrMgr; @Inject - private SnapshotApiService _snapshotService; + private NicExtraDhcpOptionDao _nicExtraDhcpOptionDao; @Inject - NicExtraDhcpOptionDao _nicExtraDhcpOptionDao; + private TemplateApiService _tmplService; @Inject - protected TemplateApiService _tmplService; + private ConfigurationDao _configDao; - protected ScheduledExecutorService _executor = null; - protected ScheduledExecutorService _vmIpFetchExecutor = null; - protected int _expungeInterval; - protected int _expungeDelay; - protected boolean _dailyOrHourly = false; + private ScheduledExecutorService _executor = null; + private ScheduledExecutorService _vmIpFetchExecutor = null; + private int _expungeInterval; + private int _expungeDelay; + private boolean _dailyOrHourly = false; private int capacityReleaseInterval; - ExecutorService _vmIpFetchThreadExecutor; + private ExecutorService _vmIpFetchThreadExecutor; - protected String _instance; - protected String _zone; - protected boolean _instanceNameFlag; - protected int _scaleRetry; - protected Map vmIdCountMap = new ConcurrentHashMap<>(); + private String _instance; + private boolean _instanceNameFlag; + private int _scaleRetry; + private Map vmIdCountMap = new ConcurrentHashMap<>(); - @Inject - ConfigurationDao _configDao; - private static final int MAX_VM_NAME_LEN = 80; private static final int MAX_HTTP_GET_LENGTH = 2 * MAX_USER_DATA_LENGTH_BYTES; private static final int MAX_HTTP_POST_LENGTH = 16 * MAX_USER_DATA_LENGTH_BYTES; @Inject - protected OrchestrationService _orchSrvc; + private OrchestrationService _orchSrvc; @Inject - VolumeOrchestrationService volumeMgr; + private VolumeOrchestrationService volumeMgr; @Inject - ManagementService _mgr; + private ManagementService _mgr; - static final ConfigKey VmIpFetchWaitInterval = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmip.retrieval.interval", "180", + private static final ConfigKey VmIpFetchWaitInterval = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmip.retrieval.interval", "180", "Wait Interval (in seconds) for shared network vm dhcp ip addr fetch for next iteration ", true); - static final ConfigKey VmIpFetchTrialMax = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10", + private static final ConfigKey VmIpFetchTrialMax = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10", "The max number of retrieval times for shared entwork vm dhcp ip fetch, in case of failures", true); - static final ConfigKey VmIpFetchThreadPoolMax = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10", + private static final ConfigKey VmIpFetchThreadPoolMax = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10", "number of threads for fetching vms ip address", true); - static final ConfigKey VmIpFetchTaskWorkers = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10", - "number of worker threads for vm ip fetch task ", true); + private static final ConfigKey VmIpFetchTaskWorkers = new ConfigKey("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10", + "number of worker threads for vm ip fetch task ", true); - static final ConfigKey AllowDeployVmIfGivenHostFails = new ConfigKey("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false", + private static final ConfigKey AllowDeployVmIfGivenHostFails = new ConfigKey("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false", "allow vm to deploy on different host if vm fails to deploy on the given host ", true); @@ -566,19 +526,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return _vmDao.listByHostId(hostId); } - protected void resourceLimitCheck(Account owner, Boolean displayVm, Long cpu, Long memory) throws ResourceAllocationException { + private void resourceLimitCheck(Account owner, Boolean displayVm, Long cpu, Long memory) throws ResourceAllocationException { _resourceLimitMgr.checkResourceLimit(owner, ResourceType.user_vm, displayVm); _resourceLimitMgr.checkResourceLimit(owner, ResourceType.cpu, displayVm, cpu); _resourceLimitMgr.checkResourceLimit(owner, ResourceType.memory, displayVm, memory); } - protected void resourceCountIncrement(long accountId, Boolean displayVm, Long cpu, Long memory) { + private void resourceCountIncrement(long accountId, Boolean displayVm, Long cpu, Long memory) { _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm, displayVm); _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.cpu, displayVm, cpu); _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.memory, displayVm, memory); } - protected void resourceCountDecrement(long accountId, Boolean displayVm, Long cpu, Long memory) { + private void resourceCountDecrement(long accountId, Boolean displayVm, Long cpu, Long memory) { _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.user_vm, displayVm); _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.cpu, displayVm, cpu); _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, displayVm, memory); @@ -623,7 +583,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } - protected class VmIpAddrFetchThread extends ManagedContextRunnable { + private class VmIpAddrFetchThread extends ManagedContextRunnable { long nicId; @@ -633,9 +593,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir Long hostId; String networkCidr; - public VmIpAddrFetchThread() { - } - public VmIpAddrFetchThread(long vmId, long nicId, String instanceName, boolean windows, Long hostId, String networkCidr) { this.vmId = vmId; this.nicId = nicId; @@ -827,7 +784,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir SSHKeyPairVO s = _sshKeyPairDao.findByName(owner.getAccountId(), owner.getDomainId(), cmd.getName()); if (s == null) { throw new InvalidParameterValueException("A key pair with name '" + cmd.getName() + "' does not exist for account " + owner.getAccountName() - + " in specified domain id"); + + " in specified domain id"); } _accountMgr.checkAccess(caller, null, true, userVm); @@ -989,7 +946,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } else if (!(vmInstance.getState().equals(State.Stopped))) { throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vmInstance.toString() + " " + " in state " + vmInstance.getState() - + "; make sure the virtual machine is stopped"); + + "; make sure the virtual machine is stopped"); } _accountMgr.checkAccess(caller, null, true, vmInstance); @@ -1057,7 +1014,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } 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."); + + " is not customizable. This is predefined in the template."); } if (serviceOffering.getSpeed() == null) { @@ -1067,7 +1024,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } 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."); + + " is not customizable. This is predefined in the template."); } if (serviceOffering.getRamSize() == null) { @@ -1196,8 +1153,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir List allNics = _nicDao.listByVmId(vmInstance.getId()); for (NicVO nic : allNics) { - if (nic.getNetworkId() == network.getId()) + if (nic.getNetworkId() == network.getId()) { throw new CloudRuntimeException("A NIC already exists for VM:" + vmInstance.getInstanceName() + " in network: " + network.getUuid()); + } } if(_nicDao.findByNetworkIdAndMacAddress(networkId, macAddress) != null) { @@ -1265,10 +1223,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } } - - if (guestNic == null) { - throw new CloudRuntimeException("Unable to add NIC to " + vmInstance); - } CallContext.current().putContextParameter(Nic.class, guestNic.getUuid()); s_logger.debug("Successful addition of " + network + " from " + vmInstance); return _vmDao.findById(vmInstance.getId()); @@ -1623,7 +1577,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override @ActionEvent(eventType = EventTypes.EVENT_VM_UPGRADE, eventDescription = "Upgrading VM", async = true) public UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, - VirtualMachineMigrationException { + VirtualMachineMigrationException { Long vmId = cmd.getId(); Long newServiceOfferingId = cmd.getServiceOfferingId(); @@ -1683,7 +1637,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId, Map customParameters) throws ResourceUnavailableException, - ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { // Verify input parameters VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); @@ -1697,11 +1651,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return upgradeRunningVirtualMachine(vmId, newServiceOfferingId, customParameters); } } - return false; + return false; } private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingId, Map customParameters) throws ResourceUnavailableException, - ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { Account caller = CallContext.current().getCallingAccount(); VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); @@ -1770,7 +1724,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Check zone wide flag boolean enableDynamicallyScaleVm = EnableDynamicallyScaleVm.valueIn(vmInstance.getDataCenterId()); if (!enableDynamicallyScaleVm) { - throw new PermissionDeniedException("Dynamically scaling virtual machines is disabled for this zone, please contact your admin"); + throw new PermissionDeniedException("Dynamically scaling virtual machines is disabled for this zone, please contact your admin"); } // Check vm flag @@ -2017,8 +1971,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } UsageEventUtils - .publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), offeringId, - templateId, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + .publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), offeringId, + templateId, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } @@ -2135,9 +2089,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return true; } - protected UserVmManagerImpl() { - } - public String getRandomPrivateTemplateName() { return UUID.randomUUID().toString(); } @@ -2304,16 +2255,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir - protected class VmIpFetchTask extends ManagedContextRunnable { - - public VmIpFetchTask() { - GlobalLock scanLock = GlobalLock.getInternLock("vmIpFetch"); - } + private class VmIpFetchTask extends ManagedContextRunnable { @Override protected void runInContext() { GlobalLock scanLock = GlobalLock.getInternLock("vmIpFetch"); - try { if (scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { try { @@ -2362,7 +2308,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } - protected class ExpungeTask extends ManagedContextRunnable { + private class ExpungeTask extends ManagedContextRunnable { public ExpungeTask() { } @@ -2403,6 +2349,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override @ActionEvent(eventType = EventTypes.EVENT_VM_UPDATE, eventDescription = "updating Vm") public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException { + validateInputsAndPermissionForUpdateVirtualMachineCommand(cmd); + String displayName = cmd.getDisplayName(); String group = cmd.getGroup(); Boolean ha = cmd.getHaEnable(); @@ -2413,59 +2361,70 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir Boolean isDynamicallyScalable = cmd.isDynamicallyScalable(); String hostName = cmd.getHostName(); Map details = cmd.getDetails(); - Account caller = CallContext.current().getCallingAccount(); List securityGroupIdList = getSecurityGroupIdList(cmd); boolean cleanupDetails = cmd.isCleanupDetails(); - // Input validation and permission checks - UserVmVO vmInstance = _vmDao.findById(id); - if (vmInstance == null) { - throw new InvalidParameterValueException("unable to find virtual machine with id " + id); + UserVmVO vmInstance = _vmDao.findById(cmd.getId()); + + if (isDisplayVm != null && isDisplayVm != vmInstance.isDisplay()) { + updateDisplayVmFlag(isDisplayVm, id, vmInstance); } - - _accountMgr.checkAccess(caller, null, true, vmInstance); - - //If the flag is specified and is changed - if (isDisplayVm != null && isDisplayVm != vmInstance.isDisplayVm()) { - - //update vm - vmInstance.setDisplayVm(isDisplayVm); - - // Resource limit changes - ServiceOffering offering = _serviceOfferingDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); - _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.user_vm, isDisplayVm); - _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.cpu, isDisplayVm, new Long(offering.getCpu())); - _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.memory, isDisplayVm, new Long(offering.getRamSize())); - - // Usage - saveUsageEvent(vmInstance); - - // take care of the root volume as well. - List rootVols = _volsDao.findByInstanceAndType(id, Volume.Type.ROOT); - if(!rootVols.isEmpty()){ - _volumeService.updateDisplay(rootVols.get(0), isDisplayVm); - } - - // take care of the data volumes as well. - List dataVols = _volsDao.findByInstanceAndType(id, Volume.Type.DATADISK); - for(Volume dataVol : dataVols){ - _volumeService.updateDisplay(dataVol, isDisplayVm); - } - - } - if (cleanupDetails){ _vmDetailsDao.removeDetails(id); } - else if (details != null && !details.isEmpty()) { + else if (MapUtils.isNotEmpty(details)) { vmInstance.setDetails(details); _vmDao.saveDetails(vmInstance); } - return updateVirtualMachine(id, displayName, group, ha, isDisplayVm, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod(), cmd.getCustomId(), hostName, cmd.getInstanceName(), securityGroupIdList, cmd.getDhcpOptionsMap()); } + protected void updateDisplayVmFlag(Boolean isDisplayVm, Long id, UserVmVO vmInstance) { + vmInstance.setDisplayVm(isDisplayVm); + + // Resource limit changes + ServiceOffering offering = _serviceOfferingDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); + _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.user_vm, isDisplayVm); + _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.cpu, isDisplayVm, new Long(offering.getCpu())); + _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.memory, isDisplayVm, new Long(offering.getRamSize())); + + // Usage + saveUsageEvent(vmInstance); + + // take care of the root volume as well. + List rootVols = _volsDao.findByInstanceAndType(id, Volume.Type.ROOT); + if (!rootVols.isEmpty()) { + _volumeService.updateDisplay(rootVols.get(0), isDisplayVm); + } + + // take care of the data volumes as well. + List dataVols = _volsDao.findByInstanceAndType(id, Volume.Type.DATADISK); + for (Volume dataVol : dataVols) { + _volumeService.updateDisplay(dataVol, isDisplayVm); + } + } + + protected void validateInputsAndPermissionForUpdateVirtualMachineCommand(UpdateVMCmd cmd) { + UserVmVO vmInstance = _vmDao.findById(cmd.getId()); + if (vmInstance == null) { + throw new InvalidParameterValueException("unable to find virtual machine with id: " + cmd.getId()); + } + validateGuestOsIdForUpdateVirtualMachineCommand(cmd); + Account caller = CallContext.current().getCallingAccount(); + _accountMgr.checkAccess(caller, null, true, vmInstance); + } + + protected void validateGuestOsIdForUpdateVirtualMachineCommand(UpdateVMCmd cmd) { + Long osTypeId = cmd.getOsTypeId(); + if (osTypeId != null) { + GuestOSVO guestOS = _guestOSDao.findById(osTypeId); + if (guestOS == null) { + throw new InvalidParameterValueException("Please specify a valid guest OS ID."); + } + } + } + private void saveUsageEvent(UserVmVO vm) { // If vm not destroyed @@ -2664,8 +2623,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir List nics = _nicDao.listByVmId(vm.getId()); if (nics == null || nics.isEmpty()) { - s_logger.error("unable to find any nics for vm " + vm.getUuid()); - return false; + s_logger.error("unable to find any nics for vm " + vm.getUuid()); + return false; } boolean userDataApplied = false; @@ -2806,7 +2765,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } @DB - protected InstanceGroupVO createVmGroup(String groupName, long accountId) { + private InstanceGroupVO createVmGroup(String groupName, long accountId) { Account account = null; try { account = _accountDao.acquireInLockTable(accountId); // to ensure @@ -2886,26 +2845,26 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - // don't let the group be deleted when we are assigning vm to - // it. + // don't let the group be deleted when we are assigning vm to + // it. InstanceGroupVO ngrpLock = _vmGroupDao.lockRow(groupFinal.getId(), false); - if (ngrpLock == null) { + if (ngrpLock == null) { s_logger.warn("Failed to acquire lock on vm group id=" + groupFinal.getId() + " name=" + groupFinal.getName()); throw new CloudRuntimeException("Failed to acquire lock on vm group id=" + groupFinal.getId() + " name=" + groupFinal.getName()); - } + } - // Currently don't allow to assign a vm to more than one group - if (_groupVMMapDao.listByInstanceId(userVmId) != null) { - // Delete all mappings from group_vm_map table + // Currently don't allow to assign a vm to more than one group + if (_groupVMMapDao.listByInstanceId(userVmId) != null) { + // Delete all mappings from group_vm_map table List groupVmMaps = _groupVMMapDao.listByInstanceId(userVmId); - for (InstanceGroupVMMapVO groupMap : groupVmMaps) { + for (InstanceGroupVMMapVO groupMap : groupVmMaps) { SearchCriteria sc = _groupVMMapDao.createSearchCriteria(); sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId()); - _groupVMMapDao.expunge(sc); - } - } + _groupVMMapDao.expunge(sc); + } + } InstanceGroupVMMapVO groupVmMapVO = new InstanceGroupVMMapVO(groupFinal.getId(), userVmId); - _groupVMMapDao.persist(groupVmMapVO); + _groupVMMapDao.persist(groupVmMapVO); } }); @@ -2953,7 +2912,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } - protected boolean validPassword(String password) { + private boolean validPassword(String password) { if (password == null || password.length() == 0) { return false; } @@ -2971,7 +2930,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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, Map customParametes, String customId, Map> dhcpOptionMap, Map dataDiskTemplateToDiskOfferingMap) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, - StorageUnavailableException, ResourceAllocationException { + StorageUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); List networkList = new ArrayList(); @@ -3028,7 +2987,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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, Map customParameters, String customId, Map> dhcpOptionMap, Map dataDiskTemplateToDiskOfferingMap) throws InsufficientCapacityException, ConcurrentOperationException, - ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { + ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); List networkList = new ArrayList(); @@ -3138,7 +3097,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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, Map customParametrs, String customId, Map> dhcpOptionsMap, Map dataDiskTemplateToDiskOfferingMap) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, - StorageUnavailableException, ResourceAllocationException { + StorageUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); List networkList = new ArrayList(); @@ -3165,7 +3124,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir List requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false); if (requiredOfferings.size() < 1) { throw new InvalidParameterValueException("Unable to find network offering with availability=" + Availability.Required - + " to automatically create the network as a part of vm creation"); + + " to automatically create the network as a part of vm creation"); } if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { @@ -3184,8 +3143,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of deployVM process"); Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", - null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null, - null); + null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null, + null); if (newNetwork != null) { defaultNetwork = _networkDao.findById(newNetwork.getId()); } @@ -3263,11 +3222,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } @DB - protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate tmplt, String hostName, String displayName, Account owner, + private 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 isDisplayVm, String keyboard, List affinityGroupIdList, Map customParameters, String customId, Map> dhcpOptionMap, Map datadiskTemplateToDiskOfferringMap) throws InsufficientCapacityException, ResourceUnavailableException, - ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { + ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { _accountMgr.checkAccess(caller, null, true, owner); @@ -3336,7 +3295,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (rootDiskSize <= 0) { throw new InvalidParameterValueException("Root disk size should be a positive number."); } - size = rootDiskSize * GB_TO_BYTES; + size = rootDiskSize * GiB_TO_BYTES; } else { // For baremetal, size can be null Long templateSize = _templateDao.findById(template.getId()).getSize(); @@ -3356,7 +3315,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException("VM Creation failed. Volume size: " + diskSize + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize + " Min:" + customDiskOfferingMinSize); } - size += diskSize * GB_TO_BYTES; + size += diskSize * GiB_TO_BYTES; } size += _diskOfferingDao.findById(diskOfferingId).getDiskSize(); } @@ -3418,7 +3377,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException("Unable to find affinity group " + ag); } else if (!_affinityGroupService.isAffinityGroupProcessorAvailable(ag.getType())) { throw new InvalidParameterValueException("Affinity group type is not supported for group: " + ag + " ,type: " + ag.getType() - + " , Please try again after removing the affinity group"); + + " , Please try again after removing the affinity group"); } else { // verify permissions if (ag.getAclType() == ACLType.Domain) { @@ -3499,12 +3458,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } NetworkOffering ntwkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId()); - Long physicalNetworkId = _networkModel.findPhysicalNetworkId(zone.getId(), ntwkOffering.getTags(), - ntwkOffering.getTrafficType()); - if (physicalNetworkId == null) { - throw new InvalidParameterValueException("Network in which is VM getting deployed could not be" + - " streched to the zone, as we could not find a valid physical network"); - } + Long physicalNetworkId = _networkModel.findPhysicalNetworkId(zone.getId(), ntwkOffering.getTags(), ntwkOffering.getTrafficType()); String provider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.Connectivity); if (!_networkModel.isProviderEnabledInPhysicalNetwork(physicalNetworkId, provider)) { @@ -3515,10 +3469,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir //relax the check if the caller is admin account if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (!(network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain) - && !(network.getAclType() == ACLType.Account && network.getAccountId() == accountId)) { - throw new InvalidParameterValueException("only shared network or isolated network with the same account_id can be added to vm"); - } + if (!(network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain) + && !(network.getAclType() == ACLType.Account && network.getAccountId() == accountId)) { + throw new InvalidParameterValueException("only shared network or isolated network with the same account_id can be added to vm"); + } } IpAddresses requestedIpPair = null; @@ -3613,7 +3567,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // In case of VMware since VM name must be unique within a DC, check if VM with the same hostname already exists in the zone. VMInstanceVO vmByHostName = _vmInstanceDao.findVMByHostNameInZone(hostName, zone.getId()); if (vmByHostName != null && vmByHostName.getState() != VirtualMachine.State.Expunging) { - throw new InvalidParameterValueException("There already exists a VM by the name: " + hostName + "."); + throw new InvalidParameterValueException("There already exists a VM by the name: " + hostName + "."); } } else { if (hostName == null) { @@ -3703,9 +3657,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } private UserVmVO commitUserVm(final DataCenter zone, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner, - final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, - final long accountId, final long userId, final ServiceOfferingVO offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, - final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap) throws InsufficientCapacityException { + final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOfferingVO offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, + final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap) throws InsufficientCapacityException { return Transaction.execute(new TransactionCallbackWithException() { @Override public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCapacityException { @@ -3723,8 +3677,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir vm.setDetail("SSH.PublicKey", sshPublicKey); } - if (keyboard != null && !keyboard.isEmpty()) + if (keyboard != null && !keyboard.isEmpty()) { vm.setDetail(VmDetailConstants.KEYBOARD, keyboard); + } if (isIso) { vm.setIsoId(template.getId()); @@ -3834,7 +3789,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir { // rootdisksize must be larger than template. if ((rootDiskSize << 30) < templateVO.getSize()) { - Long templateVOSizeGB = templateVO.getSize() / GB_TO_BYTES; + Long templateVOSizeGB = templateVO.getSize() / GiB_TO_BYTES; String error = "Unsupported: rootdisksize override is smaller than template size " + templateVO.getSize() + "B (" + templateVOSizeGB + "GB)"; s_logger.error(error); throw new InvalidParameterValueException(error); @@ -3846,7 +3801,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir s_logger.error(error); throw new InvalidParameterValueException(error); } else { - s_logger.debug("Rootdisksize override validation successful. Template root disk size " + (templateVO.getSize() / GB_TO_BYTES) + "GB Root disk size specified " + rootDiskSize + "GB"); + s_logger.debug("Rootdisksize override validation successful. Template root disk size " + (templateVO.getSize() / GiB_TO_BYTES) + "GB Root disk size specified " + rootDiskSize + "GB"); } } else { s_logger.debug("Root disk size specified is " + (rootDiskSize << 30) + "B and Template root disk size is " + templateVO.getSize() + "B. Both are equal so no need to override"); @@ -3911,18 +3866,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public void collectVmNetworkStatistics (final UserVm userVm) { - if (!userVm.getHypervisorType().equals(HypervisorType.KVM)) + if (!userVm.getHypervisorType().equals(HypervisorType.KVM)) { return; - s_logger.debug("Collect vm network statistics from host before stopping Vm"); - long hostId = userVm.getHostId(); - List vmNames = new ArrayList(); - vmNames.add(userVm.getInstanceName()); - final HostVO host = _hostDao.findById(hostId); + } + s_logger.debug("Collect vm network statistics from host before stopping Vm"); + long hostId = userVm.getHostId(); + List vmNames = new ArrayList(); + vmNames.add(userVm.getInstanceName()); + final HostVO host = _hostDao.findById(hostId); - GetVmNetworkStatsAnswer networkStatsAnswer = null; - try { + GetVmNetworkStatsAnswer networkStatsAnswer = null; + try { networkStatsAnswer = (GetVmNetworkStatsAnswer) _agentMgr.easySend(hostId, new GetVmNetworkStatsCommand(vmNames, host.getGuid(), host.getName())); - } catch (Exception e) { + } catch (Exception e) { s_logger.warn("Error while collecting network stats for vm: " + userVm.getHostName() + " from host: " + host.getName(), e); return; } @@ -3937,11 +3893,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public void doInTransactionWithoutResult(TransactionStatus status) { HashMap> vmNetworkStatsByName = networkStatsAnswerFinal.getVmNetworkStatsMap(); - if (vmNetworkStatsByName == null) - return; + if (vmNetworkStatsByName == null) { + return; + } List vmNetworkStats = vmNetworkStatsByName.get(userVm.getInstanceName()); - if (vmNetworkStats == null) - return; + if (vmNetworkStats == null) { + return; + } for (VmNetworkStatsEntry vmNetworkStat:vmNetworkStats) { SearchCriteria sc_nic = _nicDao.createSearchCriteria(); @@ -3949,7 +3907,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir NicVO nic = _nicDao.search(sc_nic, null).get(0); List vlan = _vlanDao.listVlansByNetworkId(nic.getNetworkId()); if (vlan == null || vlan.size() == 0 || vlan.get(0).getVlanType() != VlanType.DirectAttached) + { break; // only get network statistics for DirectAttached network (shared networks in Basic zone and Advanced zone with/without SG) + } UserStatisticsVO previousvmNetworkStats = _userStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), nic.getNetworkId(), nic.getIPv4Address(), userVm.getId(), "UserVm"); if (previousvmNetworkStats == null) { previousvmNetworkStats = new UserStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(),nic.getIPv4Address(), userVm.getId(), "UserVm", nic.getNetworkId()); @@ -3969,7 +3929,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (previousvmNetworkStats != null && ((previousvmNetworkStats.getCurrentBytesSent() != vmNetworkStat_lock.getCurrentBytesSent()) - || (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) { + || (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) { s_logger.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " + "Ignoring current answer. Host: " + host.getName() + " . VM: " + vmNetworkStat.getVmName() + " Sent(Bytes): " + vmNetworkStat.getBytesSent() + " Received(Bytes): " + vmNetworkStat.getBytesReceived()); @@ -4061,7 +4021,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return startVirtualMachine(cmd, null, cmd.getDeploymentPlanner()); } - protected UserVm startVirtualMachine(DeployVMCmd cmd, Map additonalParams, String deploymentPlannerToUse) throws ResourceUnavailableException, + private UserVm startVirtualMachine(DeployVMCmd cmd, Map additonalParams, String deploymentPlannerToUse) + throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException { long vmId = cmd.getEntityId(); @@ -4195,7 +4156,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir diskstats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId()); if (diskstats == null) { diskstats = new VmDiskStatisticsVO(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId()); - _vmDiskStatsDao.persist(diskstats); + _vmDiskStatsDao.persist(diskstats); } } @@ -4208,8 +4169,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir UserVmVO vm = _vmDao.findById(profile.getId()); List vmSnapshots = _vmSnapshotDao.findByVm(vm.getId()); RestoreVMSnapshotCommand command = _vmSnapshotMgr.createRestoreCommand(vm, vmSnapshots); - if (command != null) + if (command != null) { cmds.addCommand("restoreVMSnapshot", command); + } return true; } @@ -4258,7 +4220,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } } - } + } } boolean ipChanged = false; if (originalIp != null && !originalIp.equalsIgnoreCase(returnedIp)) { @@ -4352,9 +4314,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir status = vmEntity.stop(Long.toString(userId)); } if (status) { - return _vmDao.findById(vmId); + return _vmDao.findById(vmId); } else { - return null; + return null; } } catch (ResourceUnavailableException e) { throw new CloudRuntimeException("Unable to contact the agent to stop the virtual machine " + vm, e); @@ -4473,9 +4435,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (template.getEnablePassword()) { if (vm.getDetail("password") != null) { password = DBEncryptionUtil.decrypt(vm.getDetail("password")); - } else { + } else { password = _mgr.generateRandomPassword(); - } + } } if (!validPassword(password)) { @@ -4584,8 +4546,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public void collectVmDiskStatistics(final UserVm userVm) { // support KVM only util 2013.06.25 - if (!userVm.getHypervisorType().equals(HypervisorType.KVM)) + if (!userVm.getHypervisorType().equals(HypervisorType.KVM)) { return; + } s_logger.debug("Collect vm disk statistics from host before stopping Vm"); long hostId = userVm.getHostId(); List vmNames = new ArrayList(); @@ -4610,18 +4573,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public void doInTransactionWithoutResult(TransactionStatus status) { HashMap> vmDiskStatsByName = diskStatsAnswerFinal.getVmDiskStatsMap(); - if (vmDiskStatsByName == null) + if (vmDiskStatsByName == null) { return; + } List vmDiskStats = vmDiskStatsByName.get(userVm.getInstanceName()); - if (vmDiskStats == null) + if (vmDiskStats == null) { return; + } for (VmDiskStatsEntry vmDiskStat : vmDiskStats) { SearchCriteria sc_volume = _volsDao.createSearchCriteria(); sc_volume.addAnd("path", SearchCriteria.Op.EQ, vmDiskStat.getPath()); List volumes = _volsDao.search(sc_volume, null); - if ((volumes == null) || (volumes.size() == 0)) + if ((volumes == null) || (volumes.size() == 0)) { break; + } VolumeVO volume = volumes.get(0); VmDiskStatisticsVO previousVmDiskStats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId()); VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), volume.getId()); @@ -4639,19 +4605,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (previousVmDiskStats != null && ((previousVmDiskStats.getCurrentIORead() != vmDiskStat_lock.getCurrentIORead()) || ((previousVmDiskStats.getCurrentIOWrite() != vmDiskStat_lock - .getCurrentIOWrite()) + .getCurrentIOWrite()) || (previousVmDiskStats.getCurrentBytesRead() != vmDiskStat_lock.getCurrentBytesRead()) || (previousVmDiskStats - .getCurrentBytesWrite() != vmDiskStat_lock.getCurrentBytesWrite())))) { + .getCurrentBytesWrite() != vmDiskStat_lock.getCurrentBytesWrite())))) { s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " + "Ignoring current answer. Host: " + host.getName() - + " . VM: " + vmDiskStat.getVmName() + " IO Read: " + vmDiskStat.getIORead() + " IO Write: " + vmDiskStat.getIOWrite() + " Bytes Read: " - + vmDiskStat.getBytesRead() + " Bytes Write: " + vmDiskStat.getBytesWrite()); + + " . VM: " + vmDiskStat.getVmName() + " IO Read: " + vmDiskStat.getIORead() + " IO Write: " + vmDiskStat.getIOWrite() + " Bytes Read: " + + vmDiskStat.getBytesRead() + " Bytes Write: " + vmDiskStat.getBytesWrite()); continue; } if (vmDiskStat_lock.getCurrentIORead() > vmDiskStat.getIORead()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Read # of IO that's less than the last one. " + "Assuming something went wrong and persisting it. Host: " + host.getName() - + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getIORead() + " Stored: " + vmDiskStat_lock.getCurrentIORead()); + + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getIORead() + " Stored: " + vmDiskStat_lock.getCurrentIORead()); } vmDiskStat_lock.setNetIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead()); } @@ -4659,7 +4625,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (vmDiskStat_lock.getCurrentIOWrite() > vmDiskStat.getIOWrite()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Write # of IO that's less than the last one. " + "Assuming something went wrong and persisting it. Host: " + host.getName() - + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getIOWrite() + " Stored: " + vmDiskStat_lock.getCurrentIOWrite()); + + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getIOWrite() + " Stored: " + vmDiskStat_lock.getCurrentIOWrite()); } vmDiskStat_lock.setNetIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite()); } @@ -4667,7 +4633,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (vmDiskStat_lock.getCurrentBytesRead() > vmDiskStat.getBytesRead()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Read # of Bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: " + host.getName() - + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getBytesRead() + " Stored: " + vmDiskStat_lock.getCurrentBytesRead()); + + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getBytesRead() + " Stored: " + vmDiskStat_lock.getCurrentBytesRead()); } vmDiskStat_lock.setNetBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead()); } @@ -4675,8 +4641,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (vmDiskStat_lock.getCurrentBytesWrite() > vmDiskStat.getBytesWrite()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Write # of Bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: " + host.getName() - + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getBytesWrite() + " Stored: " - + vmDiskStat_lock.getCurrentBytesWrite()); + + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getBytesWrite() + " Stored: " + + vmDiskStat_lock.getCurrentBytesWrite()); } vmDiskStat_lock.setNetBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite()); } @@ -4759,7 +4725,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, - StorageUnavailableException, ResourceAllocationException { + StorageUnavailableException, ResourceAllocationException { //Verify that all objects exist before passing them to the service Account owner = _accountService.getActiveAccountById(cmd.getEntityOwnerId()); @@ -4861,13 +4827,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return vm; } - private List getSecurityGroupIdList(SecurityGroupAction cmd) { + protected List getSecurityGroupIdList(SecurityGroupAction cmd) { if (cmd.getSecurityGroupNameList() != null && cmd.getSecurityGroupIdList() != null) { throw new InvalidParameterValueException("securitygroupids parameter is mutually exclusive with securitygroupnames parameter"); } - //transform group names to ids here - if (cmd.getSecurityGroupNameList() != null) { + //transform group names to ids here + if (cmd.getSecurityGroupNameList() != null) { List securityGroupIds = new ArrayList(); for (String groupName : cmd.getSecurityGroupNameList()) { SecurityGroup sg = _securityGroupMgr.getSecurityGroup(groupName, cmd.getEntityOwnerId()); @@ -4888,13 +4854,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // if specified, minIops should be <= maxIops private void verifyDetails(Map details) { if (details != null) { - String minIops = (String)details.get("minIops"); - String maxIops = (String)details.get("maxIops"); + String minIops = details.get("minIops"); + String maxIops = details.get("maxIops"); verifyMinAndMaxIops(minIops, maxIops); - minIops = (String)details.get("minIopsDo"); - maxIops = (String)details.get("maxIopsDo"); + minIops = details.get("minIopsDo"); + maxIops = details.get("maxIopsDo"); verifyMinAndMaxIops(minIops, maxIops); } @@ -4982,7 +4948,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir HypervisorType destHypervisorType = destPool.getHypervisor(); if (destHypervisorType == null) { destHypervisorType = _clusterDao.findById( - destPool.getClusterId()).getHypervisorType(); + destPool.getClusterId()).getHypervisorType(); } if (vm.getHypervisorType() != destHypervisorType && destHypervisorType != HypervisorType.Any) { @@ -5014,7 +4980,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override @ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true) public VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, - VirtualMachineMigrationException { + VirtualMachineMigrationException { // access check - only root admin can migrate VM Account caller = CallContext.current().getCallingAccount(); if (!_accountMgr.isRootAdmin(caller.getId())) { @@ -5074,7 +5040,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // check if host is UP if (destinationHost.getState() != com.cloud.host.Status.Up || destinationHost.getResourceState() != ResourceState.Enabled) { throw new InvalidParameterValueException("Cannot migrate VM, destination host is not in correct state, has status: " + destinationHost.getState() + ", state: " - + destinationHost.getResourceState()); + + destinationHost.getResourceState()); } if (vm.getType() != VirtualMachine.Type.User) { @@ -5090,7 +5056,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir checkHostsDedication(vm, srcHostId, destinationHost.getId()); - // call to core process + // call to core process DataCenterVO dcVO = _dcDao.findById(destinationHost.getDataCenterId()); HostPodVO pod = _podDao.findById(destinationHost.getPodId()); Cluster cluster = _clusterDao.findById(destinationHost.getClusterId()); @@ -5101,10 +5067,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (_capacityMgr.checkIfHostReachMaxGuestLimit(destinationHostVO)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Host name: " + destinationHost.getName() + ", hostId: " + destinationHost.getId() - + " already has max Running VMs(count includes system VMs), cannot migrate to this host"); + + " already has max Running VMs(count includes system VMs), cannot migrate to this host"); } throw new VirtualMachineMigrationException("Destination host, hostId: " + destinationHost.getId() - + " already has max Running VMs(count includes system VMs), cannot migrate to this host"); + + " already has max Running VMs(count includes system VMs), cannot migrate to this host"); } //check if there are any ongoing volume snapshots on the volumes associated with the VM. s_logger.debug("Checking if there are any ongoing snapshots volumes associated with VM with ID " + vmId); @@ -5121,7 +5087,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir _itMgr.migrate(vm.getUuid(), srcHostId, dest); VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); if (vmInstance.getType().equals(VirtualMachine.Type.User)) { - return _vmDao.findById(vmId); + return _vmDao.findById(vmId); } else { return vmInstance; } @@ -5238,7 +5204,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir //Check if all vms on destination host are created using strict implicit mode if (!checkIfAllVmsCreatedInStrictMode(accountOfVm, vmsOnDest)) { msg = "VM of account " + accountOfVm + " with strict implicit deployment planner being migrated to host " + destHost.getName() - + " not having all vms strict implicitly dedicated to account " + accountOfVm; + + " not having all vms strict implicitly dedicated to account " + accountOfVm; } } else { //If vm is deployed using preferred implicit planner, check if all vms on destination host must be @@ -5247,7 +5213,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir 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() - + " not having all vms implicitly dedicated to account " + accountOfVm; + + " not having all vms implicitly dedicated to account " + accountOfVm; } } } @@ -5317,8 +5283,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir private boolean checkIfAllVmsCreatedInStrictMode(Long accountId, List allVmsOnHost) { boolean createdByImplicitStrict = true; - if (allVmsOnHost.isEmpty()) + if (allVmsOnHost.isEmpty()) { return false; + } for (VMInstanceVO vm : allVmsOnHost) { if (!isImplicitPlannerUsedByOffering(vm.getServiceOfferingId()) || vm.getAccountId() != accountId) { s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by a planner other" + " than implicit, or running vms of other account"); @@ -5353,7 +5320,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override @ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true) public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, Map volumeToPool) throws ResourceUnavailableException, - ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { // Access check - only root administrator can migrate VM. Account caller = CallContext.current().getCallingAccount(); if (!_accountMgr.isRootAdmin(caller.getId())) { @@ -5500,7 +5467,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir HostVO destinationHostVO = _hostDao.findById(destinationHost.getId()); if (_capacityMgr.checkIfHostReachMaxGuestLimit(destinationHostVO)) { throw new VirtualMachineMigrationException("Host name: " + destinationHost.getName() + ", hostId: " + destinationHost.getId() - + " already has max running vms (count includes system VMs). Cannot" + " migrate to this host"); + + " already has max running vms (count includes system VMs). Cannot" + " migrate to this host"); } checkHostsDedication(vm, srcHostId, destinationHost.getId()); @@ -5630,8 +5597,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir public void doInTransactionWithoutResult(TransactionStatus status) { //generate destroy vm event for usage UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), - vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), - vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); + vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), + vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); // update resource counts for old account resourceCountDecrement(oldAccount.getAccountId(), vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); @@ -5643,7 +5610,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // OS 2: update volume for (VolumeVO volume : volumes) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.volume); _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); volume.setAccountId(newAccount.getAccountId()); @@ -5652,8 +5619,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.volume); _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), - volume.getUuid(), volume.isDisplayVolume()); + volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), + volume.getUuid(), volume.isDisplayVolume()); } //update resource count of new account @@ -5661,10 +5628,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir //generate usage events to account for this change UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), - vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString(), - VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); + vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString(), + VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); } - }); + }); VirtualMachine vmoi = _itMgr.findById(vm.getId()); VirtualMachineProfileImpl vmOldProfile = new VirtualMachineProfileImpl(vmoi); @@ -5919,7 +5886,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir List requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false); if (requiredOfferings.size() < 1) { throw new InvalidParameterValueException("Unable to find network offering with availability=" + Availability.Required - + " to automatically create the network as a part of vm creation"); + + " to automatically create the network as a part of vm creation"); } if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { // get Virtual networks @@ -5936,9 +5903,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir s_logger.debug("Creating network for account " + newAccount + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of deployVM process"); Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), newAccount.getAccountName() + "-network", - newAccount.getAccountName() + "-network", null, null, null, false, null, newAccount, - null, physicalNetwork, zone.getId(), ACLType.Account, null, null, - null, null, true, null, null); + newAccount.getAccountName() + "-network", null, null, null, false, null, newAccount, + null, physicalNetwork, zone.getId(), ACLType.Account, null, null, + null, null, true, null, null); // if the network offering has persistent set to true, implement the network if (requiredOfferings.get(0).getIsPersistent()) { DeployDestination dest = new DeployDestination(zone, null, null, null); @@ -5964,7 +5931,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir defaultNetwork = _networkDao.findById(newNetwork.getId()); } else if (virtualNetworks.size() > 1) { throw new InvalidParameterValueException("More than 1 default Isolated networks are found " + "for account " + newAccount - + "; please specify networkIds"); + + "; please specify networkIds"); } else { defaultNetwork = _networkDao.findById(virtualNetworks.get(0).getId()); } @@ -6065,7 +6032,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (templateId == null) { // Assuming that for a vm deployed using ISO, template ID is set to NULL isISO = true; - templateId = vm.getIsoId(); + templateId = vm.getIsoId(); } // If target VM has associated VM snapshots then don't allow restore of VM @@ -6124,10 +6091,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir vm.setTemplateId(newTemplateId); _vmDao.update(vmId, vm); } else { - newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); - vm.setGuestOSId(template.getGuestOSId()); - vm.setTemplateId(newTemplateId); - _vmDao.update(vmId, vm); + newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); } } else { newVol = volumeMgr.allocateDuplicateVolume(root, null); @@ -6155,7 +6122,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir s_logger.info("Expunging volume " + root.getId() + " from primary data store"); AsyncCallFuture future = _volService.expungeVolumeAsync(volFactory.getVolume(root.getId())); try { - future.get(); + future.get(); } catch (Exception e) { s_logger.debug("Failed to expunge volume:" + root.getId(), e); } @@ -6216,7 +6183,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } /** - * Perform basic checkings to make sure restore is possible. If not, #InvalidParameterValueException is thrown + * Perform basic checkings to make sure restore is possible. If not, #InvalidParameterValueException is thrown. + * * @param vm vm * @param template template * @throws InvalidParameterValueException if restore is not possible @@ -6389,6 +6357,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } + @Override public void persistDeviceBusInfo(UserVmVO vm, String rootDiskController) { String existingVmRootDiskController = vm.getDetail(VmDetailConstants.ROOT_DISK_CONTROLLER); if (StringUtils.isEmpty(existingVmRootDiskController) && !StringUtils.isEmpty(rootDiskController)) { @@ -6408,7 +6377,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public ConfigKey[] getConfigKeys() { return new ConfigKey[] {EnableDynamicallyScaleVm, AllowUserExpungeRecoverVm, VmIpFetchWaitInterval, VmIpFetchTrialMax, VmIpFetchThreadPoolMax, - VmIpFetchTaskWorkers, AllowDeployVmIfGivenHostFails}; + VmIpFetchTaskWorkers, AllowDeployVmIfGivenHostFails}; } @Override @@ -6418,7 +6387,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException("Unable to find virual machine with id " + vmId); } - //check permissions _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vm); return vm.getUserData(); } @@ -6430,7 +6398,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return vm.isDisplayVm(); } - return true; // no info then default to true + return true; } private boolean checkStatusOfVolumeSnapshots(long vmId, Volume.Type type) { @@ -6456,4 +6424,4 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } return false; } -} +} \ No newline at end of file diff --git a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java index b1e13313117..4402a1baf4b 100644 --- a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java +++ b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.acl; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import javax.inject.Inject; @@ -37,11 +38,15 @@ import org.apache.cloudstack.api.command.admin.acl.UpdateRolePermissionCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.PermissionDeniedException; import com.cloud.user.Account; +import com.cloud.user.AccountManager; import com.cloud.user.dao.AccountDao; import com.cloud.utils.ListUtils; import com.cloud.utils.component.ManagerBase; @@ -52,18 +57,23 @@ import com.cloud.utils.db.TransactionStatus; import com.google.common.base.Strings; public class RoleManagerImpl extends ManagerBase implements RoleService, Configurable, PluggableService { + + private Logger logger = Logger.getLogger(getClass()); + @Inject private AccountDao accountDao; @Inject private RoleDao roleDao; @Inject private RolePermissionsDao rolePermissionsDao; + @Inject + private AccountManager accountManager; private void checkCallerAccess() { if (!isEnabled()) { throw new PermissionDeniedException("Dynamic api checker is not enabled, aborting role operation"); } - Account caller = CallContext.current().getCallingAccount(); + Account caller = getCurrentAccount(); if (caller == null || caller.getRoleId() == null) { throw new PermissionDeniedException("Restricted API called by an invalid user account"); } @@ -79,11 +89,30 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu } @Override - public Role findRole(final Long id) { + public Role findRole(Long id) { if (id == null || id < 1L) { + logger.trace(String.format("Role ID is invalid [%s]", id)); return null; } - return roleDao.findById(id); + RoleVO role = roleDao.findById(id); + if (role == null) { + logger.trace(String.format("Role not found [id=%s]", id)); + return null; + } + Account account = getCurrentAccount(); + if (!accountManager.isRootAdmin(account.getId()) && RoleType.Admin == role.getRoleType()) { + logger.debug(String.format("Role [id=%s, name=%s] is of 'Admin' type and is only visible to 'Root admins'.", id, role.getName())); + return null; + } + return role; + } + + /** + * Simple call to {@link CallContext#current()} to retrieve the current calling account. + * This method facilitates unit testing, it avoids mocking static methods. + */ + protected Account getCurrentAccount() { + return CallContext.current().getCallingAccount(); } @Override @@ -125,7 +154,7 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu if (roleType != null && roleType == RoleType.Unknown) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unknown is not a valid role type"); } - RoleVO roleVO = (RoleVO) role; + RoleVO roleVO = (RoleVO)role; if (!Strings.isNullOrEmpty(name)) { roleVO.setName(name); } @@ -214,26 +243,55 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu } @Override - public List findRolesByName(final String name) { + public List findRolesByName(String name) { List roles = null; - if (!Strings.isNullOrEmpty(name)) { + if (StringUtils.isNotBlank(name)) { roles = roleDao.findAllByName(name); } + removeRootAdminRolesIfNeeded(roles); return ListUtils.toListOfInterface(roles); } - @Override - public List findRolesByType(final RoleType roleType) { - List roles = null; - if (roleType != null) { - roles = roleDao.findAllByRoleType(roleType); + /** + * Removes roles of the given list that have the type '{@link RoleType#Admin}' if the user calling the method is not a 'root admin'. + * The actual removal is executed via {@link #removeRootAdminRoles(List)}. Therefore, if the method is called by a 'root admin', we do nothing here. + */ + protected void removeRootAdminRolesIfNeeded(List roles) { + Account account = getCurrentAccount(); + if (!accountManager.isRootAdmin(account.getId())) { + removeRootAdminRoles(roles); } + } + + /** + * Remove all roles that have the {@link RoleType#Admin}. + */ + protected void removeRootAdminRoles(List roles) { + if (CollectionUtils.isEmpty(roles)) { + return; + } + Iterator rolesIterator = roles.iterator(); + while (rolesIterator.hasNext()) { + Role role = rolesIterator.next(); + if (RoleType.Admin == role.getRoleType()) { + rolesIterator.remove(); + } + } + } + + @Override + public List findRolesByType(RoleType roleType) { + if (roleType == null || RoleType.Admin == roleType && !accountManager.isRootAdmin(getCurrentAccount().getId())) { + return Collections.emptyList(); + } + List roles = roleDao.findAllByRoleType(roleType); return ListUtils.toListOfInterface(roles); } @Override public List listRoles() { List roles = roleDao.listAll(); + removeRootAdminRolesIfNeeded(roles); return ListUtils.toListOfInterface(roles); } @@ -253,7 +311,7 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[]{RoleService.EnableDynamicApiChecker}; + return new ConfigKey[] {RoleService.EnableDynamicApiChecker}; } @Override @@ -269,4 +327,4 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu cmdList.add(DeleteRolePermissionCmd.class); return cmdList; } - } +} diff --git a/server/test/com/cloud/vm/UserVmManagerImplTest.java b/server/test/com/cloud/vm/UserVmManagerImplTest.java new file mode 100644 index 00000000000..bec9d7dee6a --- /dev/null +++ b/server/test/com/cloud/vm/UserVmManagerImplTest.java @@ -0,0 +1,224 @@ +// 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.vm; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.cloudstack.api.BaseCmd.HTTPMethod; +import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; +import org.apache.cloudstack.context.CallContext; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.uservm.UserVm; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.UserVmDetailsDao; + +@RunWith(PowerMockRunner.class) +public class UserVmManagerImplTest { + + @Spy + @InjectMocks + private UserVmManagerImpl userVmManagerImpl = new UserVmManagerImpl(); + + @Mock + private GuestOSDao guestOSDao; + + @Mock + private UserVmDao userVmDao; + + @Mock + private UpdateVMCmd updateVmCommand; + + @Mock + private AccountManager accountManager; + + @Mock + private UserVmDetailsDao userVmDetailVO; + + @Mock + private UserVmVO userVmVoMock; + + private long vmId = 1l; + + @Before + public void beforeTest() { + Mockito.when(updateVmCommand.getId()).thenReturn(vmId); + + Mockito.when(userVmDao.findById(Mockito.eq(vmId))).thenReturn(userVmVoMock); + } + + @Test + public void validateGuestOsIdForUpdateVirtualMachineCommandTestOsTypeNull() { + Mockito.when(updateVmCommand.getOsTypeId()).thenReturn(null); + userVmManagerImpl.validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); + } + + @Test(expected = InvalidParameterValueException.class) + public void validateGuestOsIdForUpdateVirtualMachineCommandTestOsTypeNotFound() { + Mockito.when(updateVmCommand.getOsTypeId()).thenReturn(1l); + + userVmManagerImpl.validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); + } + + @Test + public void validateGuestOsIdForUpdateVirtualMachineCommandTestOsTypeFound() { + Mockito.when(updateVmCommand.getOsTypeId()).thenReturn(1l); + Mockito.when(guestOSDao.findById(Mockito.eq(1l))).thenReturn(Mockito.mock(GuestOSVO.class)); + + userVmManagerImpl.validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); + } + + @Test(expected = InvalidParameterValueException.class) + public void validateInputsAndPermissionForUpdateVirtualMachineCommandTestVmNotFound() { + Mockito.when(userVmDao.findById(Mockito.eq(vmId))).thenReturn(null); + + userVmManagerImpl.validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); + } + + @Test + @PrepareForTest(CallContext.class) + public void validateInputsAndPermissionForUpdateVirtualMachineCommandTest() { + Mockito.doNothing().when(userVmManagerImpl).validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); + + Account accountMock = Mockito.mock(Account.class); + CallContext callContextMock = Mockito.mock(CallContext.class); + + PowerMockito.mockStatic(CallContext.class); + BDDMockito.given(CallContext.current()).willReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + + Mockito.doNothing().when(accountManager).checkAccess(accountMock, null, true, userVmVoMock); + userVmManagerImpl.validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); + + Mockito.verify(userVmManagerImpl).validateGuestOsIdForUpdateVirtualMachineCommand(updateVmCommand); + Mockito.verify(accountManager).checkAccess(accountMock, null, true, userVmVoMock); + } + + @Test + public void updateVirtualMachineTestDisplayChanged() throws ResourceUnavailableException, InsufficientCapacityException { + configureDoNothingForMethodsThatWeDoNotWantToTest(); + + Mockito.when(userVmVoMock.isDisplay()).thenReturn(true); + Mockito.doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); + + userVmManagerImpl.updateVirtualMachine(updateVmCommand); + verifyMethodsThatAreAlwaysExecuted(); + + Mockito.verify(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); + Mockito.verify(userVmDetailVO, Mockito.times(0)).removeDetails(vmId); + } + + @Test + public void updateVirtualMachineTestCleanUpTrue() throws ResourceUnavailableException, InsufficientCapacityException { + configureDoNothingForMethodsThatWeDoNotWantToTest(); + + Mockito.when(updateVmCommand.isCleanupDetails()).thenReturn(true); + + Mockito.doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); + Mockito.doNothing().when(userVmDetailVO).removeDetails(vmId); + + userVmManagerImpl.updateVirtualMachine(updateVmCommand); + verifyMethodsThatAreAlwaysExecuted(); + Mockito.verify(userVmDetailVO).removeDetails(vmId); + Mockito.verify(userVmManagerImpl, Mockito.times(0)).updateDisplayVmFlag(false, vmId, userVmVoMock); + } + + @Test + public void updateVirtualMachineTestCleanUpTrueAndDetailEmpty() throws ResourceUnavailableException, InsufficientCapacityException { + prepareAndExecuteMethodDealingWithDetails(true, true); + } + + @Test + public void updateVirtualMachineTestCleanUpTrueAndDetailsNotEmpty() throws ResourceUnavailableException, InsufficientCapacityException { + prepareAndExecuteMethodDealingWithDetails(true, false); + } + + @Test + public void updateVirtualMachineTestCleanUpFalseAndDetailsNotEmpty() throws ResourceUnavailableException, InsufficientCapacityException { + prepareAndExecuteMethodDealingWithDetails(false, true); + } + + @Test + public void updateVirtualMachineTestCleanUpFalseAndDetailsEmpty() throws ResourceUnavailableException, InsufficientCapacityException { + prepareAndExecuteMethodDealingWithDetails(false, false); + } + + private void prepareAndExecuteMethodDealingWithDetails(boolean cleanUpDetails, boolean isDetailsEmpty) throws ResourceUnavailableException, InsufficientCapacityException { + configureDoNothingForMethodsThatWeDoNotWantToTest(); + + HashMap details = new HashMap<>(); + if(!isDetailsEmpty) { + details.put("", ""); + } + Mockito.when(updateVmCommand.getDetails()).thenReturn(details); + Mockito.when(updateVmCommand.isCleanupDetails()).thenReturn(cleanUpDetails); + + configureDoNothingForDetailsMethod(); + + userVmManagerImpl.updateVirtualMachine(updateVmCommand); + verifyMethodsThatAreAlwaysExecuted(); + + Mockito.verify(userVmVoMock, Mockito.times(cleanUpDetails || isDetailsEmpty ? 0 : 1)).setDetails(details); + Mockito.verify(userVmDetailVO, Mockito.times(cleanUpDetails ? 1: 0)).removeDetails(vmId); + Mockito.verify(userVmDao, Mockito.times(cleanUpDetails || isDetailsEmpty ? 0 : 1)).saveDetails(userVmVoMock); + Mockito.verify(userVmManagerImpl, Mockito.times(0)).updateDisplayVmFlag(false, vmId, userVmVoMock); + } + + private void configureDoNothingForDetailsMethod() { + Mockito.doNothing().when(userVmManagerImpl).updateDisplayVmFlag(false, vmId, userVmVoMock); + Mockito.doNothing().when(userVmDetailVO).removeDetails(vmId); + Mockito.doNothing().when(userVmDao).saveDetails(userVmVoMock); + } + + @SuppressWarnings("unchecked") + private void verifyMethodsThatAreAlwaysExecuted() throws ResourceUnavailableException, InsufficientCapacityException { + Mockito.verify(userVmManagerImpl).validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); + Mockito.verify(userVmManagerImpl).getSecurityGroupIdList(updateVmCommand); + Mockito.verify(userVmManagerImpl).updateVirtualMachine(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyLong(), + Mockito.anyString(), Mockito.anyBoolean(), Mockito.any(HTTPMethod.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyListOf(Long.class), + Mockito.anyMap()); + + } + + @SuppressWarnings("unchecked") + private void configureDoNothingForMethodsThatWeDoNotWantToTest() throws ResourceUnavailableException, InsufficientCapacityException { + Mockito.doNothing().when(userVmManagerImpl).validateInputsAndPermissionForUpdateVirtualMachineCommand(updateVmCommand); + Mockito.doReturn(new ArrayList()).when(userVmManagerImpl).getSecurityGroupIdList(updateVmCommand); + Mockito.doReturn(Mockito.mock(UserVm.class)).when(userVmManagerImpl).updateVirtualMachine(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), + Mockito.anyBoolean(), Mockito.anyLong(), + Mockito.anyString(), Mockito.anyBoolean(), Mockito.any(HTTPMethod.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyListOf(Long.class), + Mockito.anyMap()); + } +} diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index e58cd4077e9..b3df1050584 100644 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.vm; + import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -44,17 +45,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import com.cloud.dc.VlanVO; -import com.cloud.dc.dao.VlanDao; -import com.cloud.network.dao.IPAddressVO; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.BaseCmd; @@ -71,12 +61,23 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; import com.cloud.capacity.CapacityManager; import com.cloud.configuration.ConfigurationManager; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; import com.cloud.event.dao.UsageEventDao; import com.cloud.exception.ConcurrentOperationException; @@ -93,6 +94,7 @@ import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.element.UserDataServiceProvider; @@ -127,138 +129,107 @@ import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; +@RunWith(MockitoJUnitRunner.class) public class UserVmManagerTest { @Spy - UserVmManagerImpl _userVmMgr = new UserVmManagerImpl(); + @InjectMocks + private UserVmManagerImpl _userVmMgr; @Mock - VirtualMachineManager _itMgr; + private VirtualMachineManager _itMgr; @Mock - VolumeOrchestrationService _storageMgr; + private VolumeOrchestrationService _storageMgr; @Mock - Account _account; + private Account _account; @Mock - AccountManager _accountMgr; + private AccountManager _accountMgr; @Mock - AccountService _accountService; + private AccountService _accountService; @Mock - ConfigurationManager _configMgr; + private ConfigurationManager _configMgr; @Mock - CapacityManager _capacityMgr; + private CapacityManager _capacityMgr; @Mock - AccountDao _accountDao; + private AccountDao _accountDao; @Mock - ConfigurationDao _configDao; + private ConfigurationDao _configDao; @Mock - UserDao _userDao; + private UserDao _userDao; @Mock - UserVmDao _vmDao; + private UserVmDao _vmDao; @Mock - VMInstanceDao _vmInstanceDao; + private VMInstanceDao _vmInstanceDao; @Mock - VMTemplateDao _templateDao; + private VMTemplateDao _templateDao; @Mock - TemplateDataStoreDao _templateStoreDao; + private TemplateDataStoreDao _templateStoreDao; @Mock - VolumeDao _volsDao; + private VolumeDao _volsDao; @Mock - RestoreVMCmd _restoreVMCmd; + private RestoreVMCmd _restoreVMCmd; @Mock - AccountVO _accountMock; + private AccountVO _accountMock; @Mock - UserVO _userMock; + private UserVO _userMock; @Mock - UserVmVO _vmMock; + private UserVmVO _vmMock; @Mock - VMInstanceVO _vmInstance; + private VMInstanceVO _vmInstance; @Mock - VMTemplateVO _templateMock; + private VMTemplateVO _templateMock; @Mock - TemplateDataStoreVO _templateDataStoreMock; + private TemplateDataStoreVO _templateDataStoreMock; @Mock - VolumeVO _volumeMock; + private VolumeVO _volumeMock; @Mock - List _rootVols; + private List _rootVols; @Mock - Account _accountMock2; + private Account _accountMock2; @Mock - ServiceOfferingDao _offeringDao; + private ServiceOfferingDao _offeringDao; @Mock - ServiceOfferingVO _offeringVo; + private ServiceOfferingVO _offeringVo; @Mock - EntityManager _entityMgr; + private EntityManager _entityMgr; @Mock - ResourceLimitService _resourceLimitMgr; + private ResourceLimitService _resourceLimitMgr; @Mock - PrimaryDataStoreDao _storagePoolDao; + private PrimaryDataStoreDao _storagePoolDao; @Mock - UsageEventDao _usageEventDao; + private UsageEventDao _usageEventDao; @Mock - VMSnapshotDao _vmSnapshotDao; + private VMSnapshotDao _vmSnapshotDao; @Mock - UpdateVmNicIpCmd _updateVmNicIpCmd; + private UpdateVmNicIpCmd _updateVmNicIpCmd; @Mock - NicDao _nicDao; + private NicDao _nicDao; @Mock - VlanDao _vlanDao; + private VlanDao _vlanDao; @Mock - NicVO _nicMock; + private NicVO _nicMock; @Mock - NetworkModel _networkModel; + private NetworkModel _networkModel; @Mock - NetworkDao _networkDao; + private NetworkDao _networkDao; @Mock - NetworkVO _networkMock; + private NetworkVO _networkMock; @Mock - DataCenterDao _dcDao; + private DataCenterDao _dcDao; @Mock - DataCenterVO _dcMock; + private DataCenterVO _dcMock; @Mock - IpAddressManager _ipAddrMgr; + private IpAddressManager _ipAddrMgr; @Mock - IPAddressDao _ipAddressDao; + private IPAddressDao _ipAddressDao; @Mock - NetworkOfferingDao _networkOfferingDao; + private NetworkOfferingDao _networkOfferingDao; @Mock - NetworkOfferingVO _networkOfferingMock; + private NetworkOfferingVO _networkOfferingMock; @Mock - NetworkOrchestrationService _networkMgr; + private NetworkOrchestrationService _networkMgr; @Before public void setup() { - MockitoAnnotations.initMocks(this); - - _userVmMgr._vmDao = _vmDao; - _userVmMgr._vmInstanceDao = _vmInstanceDao; - _userVmMgr._templateDao = _templateDao; - _userVmMgr._templateStoreDao = _templateStoreDao; - _userVmMgr._volsDao = _volsDao; - _userVmMgr._usageEventDao = _usageEventDao; - _userVmMgr._itMgr = _itMgr; - _userVmMgr.volumeMgr = _storageMgr; - _userVmMgr._accountDao = _accountDao; - _userVmMgr._accountService = _accountService; - _userVmMgr._userDao = _userDao; - _userVmMgr._accountMgr = _accountMgr; - _userVmMgr._configMgr = _configMgr; - _userVmMgr._offeringDao = _offeringDao; - _userVmMgr._capacityMgr = _capacityMgr; - _userVmMgr._resourceLimitMgr = _resourceLimitMgr; - _userVmMgr._scaleRetry = 2; - _userVmMgr._entityMgr = _entityMgr; - _userVmMgr._storagePoolDao = _storagePoolDao; - _userVmMgr._vmSnapshotDao = _vmSnapshotDao; - _userVmMgr._configDao = _configDao; - _userVmMgr._nicDao = _nicDao; - _userVmMgr._vlanDao = _vlanDao; - _userVmMgr._networkModel = _networkModel; - _userVmMgr._networkDao = _networkDao; - _userVmMgr._dcDao = _dcDao; - _userVmMgr._ipAddrMgr = _ipAddrMgr; - _userVmMgr._ipAddressDao = _ipAddressDao; - _userVmMgr._networkOfferingDao = _networkOfferingDao; - _userVmMgr._networkMgr = _networkMgr; - doReturn(3L).when(_account).getId(); doReturn(8L).when(_vmMock).getAccountId(); when(_accountDao.findById(anyLong())).thenReturn(_accountMock); @@ -267,43 +238,40 @@ public class UserVmManagerTest { when(_vmMock.getId()).thenReturn(314L); when(_vmInstance.getId()).thenReturn(1L); when(_vmInstance.getServiceOfferingId()).thenReturn(2L); - List mockList = mock(List.class); + + List mockList = new ArrayList<>(); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(mockList); - when(mockList.size()).thenReturn(0); - when(_templateStoreDao.findByTemplateZoneReady(anyLong(),anyLong())).thenReturn(_templateDataStoreMock); + when(_templateStoreDao.findByTemplateZoneReady(anyLong(), anyLong())).thenReturn(_templateDataStoreMock); } - @Test - public void testValidateRootDiskResize() - { + public void testValidateRootDiskResize() { HypervisorType hypervisorType = HypervisorType.Any; Long rootDiskSize = Long.valueOf(10); - UserVmVO vm = Mockito.mock(UserVmVO.class); + UserVmVO vm = Mockito.mock(UserVmVO.class); VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); Map customParameters = new HashMap(); Map vmDetals = new HashMap(); - - vmDetals.put("rootDiskController","ide"); + vmDetals.put("rootDiskController", "ide"); when(vm.getDetails()).thenReturn(vmDetals); - when(templateVO.getSize()).thenReturn((rootDiskSize<<30)+1); + when(templateVO.getSize()).thenReturn((rootDiskSize << 30) + 1); //Case 1: > - try{ + try { _userVmMgr.validateRootDiskResize(hypervisorType, rootDiskSize, templateVO, vm, customParameters); Assert.fail("Function should throw InvalidParameterValueException"); - }catch(Exception e){ + } catch (Exception e) { assertThat(e, instanceOf(InvalidParameterValueException.class)); } //Case 2: = - when(templateVO.getSize()).thenReturn((rootDiskSize<<30)); - customParameters.put("rootdisksize","10"); + when(templateVO.getSize()).thenReturn((rootDiskSize << 30)); + customParameters.put("rootdisksize", "10"); _userVmMgr.validateRootDiskResize(hypervisorType, rootDiskSize, templateVO, vm, customParameters); - assert(!customParameters.containsKey("rootdisksize")); + assert (!customParameters.containsKey("rootdisksize")); - when(templateVO.getSize()).thenReturn((rootDiskSize<<30)-1); + when(templateVO.getSize()).thenReturn((rootDiskSize << 30) - 1); //Case 3: < @@ -315,12 +283,12 @@ public class UserVmManagerTest { try { _userVmMgr.validateRootDiskResize(hypervisorType, rootDiskSize, templateVO, vm, customParameters); Assert.fail("Function should throw InvalidParameterValueException"); - }catch(Exception e) { + } catch (Exception e) { assertThat(e, instanceOf(InvalidParameterValueException.class)); } //Case 3.3: 1->(rootDiskController==scsi) - vmDetals.put("rootDiskController","scsi"); + vmDetals.put("rootDiskController", "scsi"); _userVmMgr.validateRootDiskResize(hypervisorType, rootDiskSize, templateVO, vm, customParameters); } @@ -344,8 +312,7 @@ public class UserVmManagerTest { // Test restoreVm when VM is in stopped state @Test - public void testRestoreVMF2() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, - ResourceAllocationException { + public void testRestoreVMF2() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { doReturn(VirtualMachine.State.Stopped).when(_vmMock).getState(); when(_vmDao.findById(anyLong())).thenReturn(_vmMock); @@ -381,8 +348,7 @@ public class UserVmManagerTest { // Test restoreVM when VM is in running state @Test - public void testRestoreVMF3() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, - ResourceAllocationException { + public void testRestoreVMF3() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { doReturn(VirtualMachine.State.Running).when(_vmMock).getState(); when(_vmDao.findById(anyLong())).thenReturn(_vmMock); @@ -418,8 +384,7 @@ public class UserVmManagerTest { // Test restoreVM on providing new template Id, when VM is in running state @Test - public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, - ResourceAllocationException { + public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { doReturn(VirtualMachine.State.Running).when(_vmMock).getState(); when(_vmDao.findById(anyLong())).thenReturn(_vmMock); when(_volsDao.findByInstanceAndType(314L, Volume.Type.ROOT)).thenReturn(_rootVols); @@ -438,9 +403,9 @@ public class UserVmManagerTest { doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); doNothing().when(_volsDao).detachVolume(anyLong()); - List mockList = mock(List.class); + + List mockList = new ArrayList<>(); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(mockList); - when(mockList.size()).thenReturn(0); when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); @@ -458,13 +423,12 @@ public class UserVmManagerTest { } finally { CallContext.unregister(); } - + verify(_vmMock, times(0)).setIsoId(Mockito.anyLong()); } // Test restoreVM on providing new ISO Id, when VM(deployed using ISO) is in running state @Test - public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, - ResourceAllocationException { + public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { doReturn(VirtualMachine.State.Running).when(_vmMock).getState(); when(_vmDao.findById(anyLong())).thenReturn(_vmMock); when(_volsDao.findByInstanceAndType(314L, Volume.Type.ROOT)).thenReturn(_rootVols); @@ -485,9 +449,9 @@ public class UserVmManagerTest { doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); when(_volumeMock.getId()).thenReturn(3L); doNothing().when(_volsDao).detachVolume(anyLong()); - List mockList = mock(List.class); + List mockList = new ArrayList<>(); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(mockList); - when(mockList.size()).thenReturn(0); + when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); @@ -512,7 +476,7 @@ public class UserVmManagerTest { // Test scaleVm on incompatible HV. @Test(expected = InvalidParameterValueException.class) - public void testScaleVMF1() throws Exception { + public void testScaleVMF1() throws Exception { ScaleVMCmd cmd = new ScaleVMCmd(); Class _class = cmd.getClass(); @@ -527,7 +491,7 @@ public class UserVmManagerTest { when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); - // UserContext.current().setEventDetails("Vm Id: "+getId()); + // UserContext.current().setEventDetails("Vm Id: "+getId()); Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); //AccountVO(String accountName, long domainId, String networkDomain, short type, int regionId) @@ -544,7 +508,7 @@ public class UserVmManagerTest { // Test scaleVm on equal service offerings. @Test(expected = InvalidParameterValueException.class) - public void testScaleVMF2() throws Exception { + public void testScaleVMF2() throws Exception { ScaleVMCmd cmd = new ScaleVMCmd(); Class _class = cmd.getClass(); @@ -566,9 +530,7 @@ public class UserVmManagerTest { doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo); - ServiceOffering so1 = getSvcoffering(512); - ServiceOffering so2 = getSvcoffering(256); - + ServiceOffering so1 = getSvcoffering(512); when(_offeringDao.findById(anyLong())).thenReturn((ServiceOfferingVO)so1); when(_offeringDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn((ServiceOfferingVO)so1); @@ -585,7 +547,7 @@ public class UserVmManagerTest { // Test scaleVm for Stopped vm. //@Test(expected=InvalidParameterValueException.class) - public void testScaleVMF3() throws Exception { + public void testScaleVMF3() throws Exception { ScaleVMCmd cmd = new ScaleVMCmd(); Class _class = cmd.getClass(); @@ -601,8 +563,8 @@ public class UserVmManagerTest { when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); doReturn(Hypervisor.HypervisorType.XenServer).when(_vmInstance).getHypervisorType(); - ServiceOffering so1 = getSvcoffering(512); - ServiceOffering so2 = getSvcoffering(256); + ServiceOffering so1 = getSvcoffering(512); + ServiceOffering so2 = getSvcoffering(256); when(_entityMgr.findById(eq(ServiceOffering.class), anyLong())).thenReturn(so2); when(_entityMgr.findById(ServiceOffering.class, 1L)).thenReturn(so1); @@ -626,7 +588,7 @@ public class UserVmManagerTest { } // Test scaleVm for Running vm. Full positive test. - public void testScaleVMF4() throws Exception { + public void testScaleVMF4() throws Exception { ScaleVMCmd cmd = new ScaleVMCmd(); Class _class = cmd.getClass(); @@ -647,8 +609,8 @@ public class UserVmManagerTest { when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance); doReturn(Hypervisor.HypervisorType.XenServer).when(_vmInstance).getHypervisorType(); - ServiceOffering so1 = getSvcoffering(512); - ServiceOffering so2 = getSvcoffering(256); + ServiceOffering so1 = getSvcoffering(512); + ServiceOffering so2 = getSvcoffering(256); when(_entityMgr.findById(eq(ServiceOffering.class), anyLong())).thenReturn(so2); when(_entityMgr.findById(ServiceOffering.class, 1L)).thenReturn(so1); @@ -656,7 +618,7 @@ public class UserVmManagerTest { doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); //when(ApiDBUtils.getCpuOverprovisioningFactor()).thenReturn(3f); - when(_capacityMgr.checkIfHostHasCapacity(anyLong(), anyInt(), anyLong(), anyBoolean(), anyFloat(), anyFloat(), anyBoolean())).thenReturn(false); + when(_capacityMgr.checkIfHostHasCapacity(anyLong(), anyInt(), anyLong(), anyBoolean(), anyFloat(), anyFloat(), anyBoolean())).thenReturn(false); when(_itMgr.reConfigureVm(_vmInstance.getUuid(), so1, false)).thenReturn(_vmInstance); doReturn(true).when(_itMgr).upgradeVmDb(anyLong(), anyLong()); @@ -675,8 +637,6 @@ public class UserVmManagerTest { } private ServiceOfferingVO getSvcoffering(int ramSize) { - - long id = 4L; String name = "name"; String displayText = "displayText"; int cpu = 1; @@ -686,15 +646,14 @@ public class UserVmManagerTest { boolean ha = false; boolean useLocalStorage = false; - ServiceOfferingVO serviceOffering = - new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, ha, displayText, Storage.ProvisioningType.THIN, - useLocalStorage, false, null, false, null, false); + ServiceOfferingVO serviceOffering = new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, ha, displayText, Storage.ProvisioningType.THIN, useLocalStorage, false, null, false, null, + false); return serviceOffering; } // Test Move VM b/w accounts where caller is not ROOT/Domain admin @Test(expected = InvalidParameterValueException.class) - public void testMoveVmToUser1() throws Exception { + public void testMoveVmToUser1() throws Exception { AssignVMCmd cmd = new AssignVMCmd(); Class _class = cmd.getClass(); @@ -717,7 +676,7 @@ public class UserVmManagerTest { CallContext.register(user, caller); try { - _userVmMgr.moveVMToUser(cmd); + _userVmMgr.moveVMToUser(cmd); } finally { CallContext.unregister(); } @@ -725,7 +684,7 @@ public class UserVmManagerTest { // Test Move VM b/w accounts where caller doesn't have access to the old or new account @Test(expected = PermissionDeniedException.class) - public void testMoveVmToUser2() throws Exception { + public void testMoveVmToUser2() throws Exception { AssignVMCmd cmd = new AssignVMCmd(); Class _class = cmd.getClass(); @@ -756,8 +715,7 @@ public class UserVmManagerTest { when(_accountMgr.finalizeOwner(any(Account.class), anyString(), anyLong(), anyLong())).thenReturn(newAccount); - doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), - any(ControlledEntity.class)); + doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); CallContext.register(user, caller); @@ -805,7 +763,8 @@ public class UserVmManagerTest { when(_dcMock.getNetworkType()).thenReturn(NetworkType.Advanced); when(_ipAddrMgr.allocateGuestIP(Mockito.eq(_networkMock), anyString())).thenReturn("10.10.10.10"); - doNothing().when(_networkMgr).implementNetworkElementsAndResources(Mockito.any(DeployDestination.class), Mockito.any(ReservationContext.class), Mockito.eq(_networkMock), Mockito.eq(_networkOfferingMock)); + doNothing().when(_networkMgr).implementNetworkElementsAndResources(Mockito.any(DeployDestination.class), Mockito.any(ReservationContext.class), Mockito.eq(_networkMock), + Mockito.eq(_networkOfferingMock)); when(_nicDao.persist(any(NicVO.class))).thenReturn(nic); Account caller = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); diff --git a/server/test/org/apache/cloudstack/acl/RoleManagerImplTest.java b/server/test/org/apache/cloudstack/acl/RoleManagerImplTest.java new file mode 100644 index 00000000000..bc50f340898 --- /dev/null +++ b/server/test/org/apache/cloudstack/acl/RoleManagerImplTest.java @@ -0,0 +1,288 @@ +// 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.acl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.acl.dao.RoleDao; +import org.apache.commons.collections.CollectionUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; + +import com.cloud.user.Account; +import com.cloud.user.AccountManager; + +@RunWith(MockitoJUnitRunner.class) +public class RoleManagerImplTest { + + @Spy + @InjectMocks + private RoleManagerImpl roleManagerImpl; + @Mock + private AccountManager accountManagerMock; + @Mock + private RoleDao roleDaoMock; + + @Mock + private Account accountMock; + private long accountMockId = 100l; + + @Mock + private RoleVO roleVoMock; + private long roleMockId = 1l; + + @Before + public void beforeTest() { + Mockito.doReturn(accountMockId).when(accountMock).getId(); + Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + + Mockito.doReturn(roleMockId).when(roleVoMock).getId(); + } + + @Test + public void findRoleTestIdNull() { + Role returnedRole = roleManagerImpl.findRole(null); + Assert.assertNull(returnedRole); + } + + @Test + public void findRoleTestIdZero() { + Role returnedRole = roleManagerImpl.findRole(0l); + Assert.assertNull(returnedRole); + } + + @Test + public void findRoleTestIdNegative() { + Role returnedRole = roleManagerImpl.findRole(-1l); + Assert.assertNull(returnedRole); + } + + @Test + public void findRoleTestRoleNotFound() { + Mockito.doReturn(null).when(roleDaoMock).findById(roleMockId); + Role returnedRole = roleManagerImpl.findRole(roleMockId); + Assert.assertNull(returnedRole); + } + + @Test + public void findRoleTestNotRootAdminAndNotRoleAdminType() { + Mockito.doReturn(RoleType.DomainAdmin).when(roleVoMock).getRoleType(); + Mockito.doReturn(roleVoMock).when(roleDaoMock).findById(roleMockId); + Mockito.doReturn(false).when(accountManagerMock).isRootAdmin(accountMockId); + + Role returnedRole = roleManagerImpl.findRole(roleMockId); + + Assert.assertEquals(roleMockId, returnedRole.getId()); + Mockito.verify(accountManagerMock).isRootAdmin(accountMockId); + Mockito.verify(roleVoMock, Mockito.times(1)).getRoleType(); + } + + @Test + public void findRoleTestRootAdminAndNotRoleAdminType() { + Mockito.doReturn(RoleType.DomainAdmin).when(roleVoMock).getRoleType(); + Mockito.doReturn(roleVoMock).when(roleDaoMock).findById(roleMockId); + Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); + + Role returnedRole = roleManagerImpl.findRole(roleMockId); + + Assert.assertEquals(roleMockId, returnedRole.getId()); + Mockito.verify(accountManagerMock).isRootAdmin(accountMockId); + Mockito.verify(roleVoMock, Mockito.times(0)).getRoleType(); + } + + @Test + public void findRoleTestRootAdminAndRoleAdminType() { + Mockito.doReturn(RoleType.Admin).when(roleVoMock).getRoleType(); + Mockito.doReturn(roleVoMock).when(roleDaoMock).findById(roleMockId); + Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); + + Role returnedRole = roleManagerImpl.findRole(roleMockId); + + Assert.assertEquals(roleMockId, returnedRole.getId()); + Mockito.verify(accountManagerMock).isRootAdmin(accountMockId); + Mockito.verify(roleVoMock, Mockito.times(0)).getRoleType(); + } + + @Test + public void findRoleTestNotRootAdminAndRoleAdminType() { + Mockito.doReturn(RoleType.Admin).when(roleVoMock).getRoleType(); + Mockito.doReturn(roleVoMock).when(roleDaoMock).findById(roleMockId); + Mockito.doReturn(false).when(accountManagerMock).isRootAdmin(accountMockId); + + Role returnedRole = roleManagerImpl.findRole(roleMockId); + + Assert.assertNull(returnedRole); + Mockito.verify(accountManagerMock).isRootAdmin(accountMockId); + Mockito.verify(roleVoMock, Mockito.times(1)).getRoleType(); + } + + @Test + public void findRolesByNameTestNullRoleName() { + List rolesFound = roleManagerImpl.findRolesByName(null); + + Assert.assertTrue(CollectionUtils.isEmpty(rolesFound)); + } + + @Test + public void findRolesByNameTestEmptyRoleName() { + List rolesFound = roleManagerImpl.findRolesByName(""); + + Assert.assertTrue(CollectionUtils.isEmpty(rolesFound)); + } + + @Test + public void findRolesByNameTestBlankRoleName() { + List rolesFound = roleManagerImpl.findRolesByName(" "); + + Assert.assertTrue(CollectionUtils.isEmpty(rolesFound)); + } + + @Test + public void findRolesByNameTest() { + String roleName = "roleName"; + ArrayList toBeReturned = new ArrayList<>(); + Mockito.doReturn(toBeReturned).when(roleDaoMock).findAllByName(roleName); + + roleManagerImpl.findRolesByName(roleName); + + Mockito.verify(roleManagerImpl).removeRootAdminRolesIfNeeded(toBeReturned); + } + + @Test + public void removeRootAdminRolesIfNeededTestRootAdmin() { + Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); + + List roles = new ArrayList<>(); + roleManagerImpl.removeRootAdminRolesIfNeeded(roles); + + Mockito.verify(roleManagerImpl, Mockito.times(0)).removeRootAdminRoles(roles); + } + + @Test + public void removeRootAdminRolesIfNeededTestNonRootAdminUser() { + Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.doReturn(false).when(accountManagerMock).isRootAdmin(accountMockId); + + List roles = new ArrayList<>(); + roleManagerImpl.removeRootAdminRolesIfNeeded(roles); + + Mockito.verify(roleManagerImpl, Mockito.times(1)).removeRootAdminRoles(roles); + } + + @Test + public void removeRootAdminRolesTest() { + List roles = new ArrayList<>(); + Role roleRootAdmin = Mockito.mock(Role.class); + Mockito.doReturn(RoleType.Admin).when(roleRootAdmin).getRoleType(); + + Role roleDomainAdmin = Mockito.mock(Role.class); + Mockito.doReturn(RoleType.DomainAdmin).when(roleDomainAdmin).getRoleType(); + + Role roleResourceAdmin = Mockito.mock(Role.class); + Mockito.doReturn(RoleType.ResourceAdmin).when(roleResourceAdmin).getRoleType(); + + Role roleUser = Mockito.mock(Role.class); + Mockito.doReturn(RoleType.User).when(roleUser).getRoleType(); + + roles.add(roleRootAdmin); + roles.add(roleDomainAdmin); + roles.add(roleResourceAdmin); + roles.add(roleUser); + + roleManagerImpl.removeRootAdminRoles(roles); + + Assert.assertEquals(3, roles.size()); + Assert.assertEquals(roleDomainAdmin, roles.get(0)); + Assert.assertEquals(roleResourceAdmin, roles.get(1)); + Assert.assertEquals(roleUser, roles.get(2)); + } + + @Test + public void findRolesByTypeTestNullRoleType() { + List returnedRoles = roleManagerImpl.findRolesByType(null); + + Assert.assertEquals(0, returnedRoles.size()); + Mockito.verify(accountManagerMock, Mockito.times(0)).isRootAdmin(Mockito.anyLong()); + } + + @Test + public void findRolesByTypeTestAdminRoleNonRootAdminUser() { + Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.doReturn(false).when(accountManagerMock).isRootAdmin(accountMockId); + + List returnedRoles = roleManagerImpl.findRolesByType(RoleType.Admin); + + Assert.assertEquals(0, returnedRoles.size()); + Mockito.verify(accountManagerMock, Mockito.times(1)).isRootAdmin(Mockito.anyLong()); + Mockito.verify(roleDaoMock, Mockito.times(0)).findAllByRoleType(Mockito.any(RoleType.class)); + } + + @Test + public void findRolesByTypeTestAdminRoleRootAdminUser() { + Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); + + List roles = new ArrayList<>(); + roles.add(Mockito.mock(Role.class)); + Mockito.doReturn(roles).when(roleDaoMock).findAllByRoleType(RoleType.Admin); + List returnedRoles = roleManagerImpl.findRolesByType(RoleType.Admin); + + Assert.assertEquals(1, returnedRoles.size()); + Mockito.verify(accountManagerMock, Mockito.times(1)).isRootAdmin(Mockito.anyLong()); + Mockito.verify(roleDaoMock, Mockito.times(1)).findAllByRoleType(Mockito.any(RoleType.class)); + } + + @Test + public void findRolesByTypeTestNonAdminRoleRootAdminUser() { + Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); + + List roles = new ArrayList<>(); + roles.add(Mockito.mock(Role.class)); + Mockito.doReturn(roles).when(roleDaoMock).findAllByRoleType(RoleType.User); + List returnedRoles = roleManagerImpl.findRolesByType(RoleType.User); + + Assert.assertEquals(1, returnedRoles.size()); + Mockito.verify(accountManagerMock, Mockito.times(0)).isRootAdmin(Mockito.anyLong()); + Mockito.verify(roleDaoMock, Mockito.times(1)).findAllByRoleType(Mockito.any(RoleType.class)); + } + + @Test + public void listRolesTest() { + List roles = new ArrayList<>(); + roles.add(Mockito.mock(Role.class)); + + Mockito.doReturn(roles).when(roleDaoMock).listAll(); + Mockito.doNothing().when(roleManagerImpl).removeRootAdminRolesIfNeeded(roles); + + List returnedRoles = roleManagerImpl.listRoles(); + + Assert.assertEquals(roles.size(), returnedRoles.size()); + Mockito.verify(roleDaoMock).listAll(); + Mockito.verify(roleManagerImpl).removeRootAdminRolesIfNeeded(roles); + } +} diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java index 7a22b20ffdb..ea4e75d8943 100644 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java @@ -87,6 +87,8 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler> uriAttributes = decoderQuery.parameters(); uuid = uriAttributes.get("uuid").get(0); logger.info("URI: uuid=" + uuid); - UploadEntity uploadEntity = null; try { // Validate the request here @@ -175,6 +176,7 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler uploadEntityStateMap = new HashMap(); private String _ssvmPSK = null; + private long processTimeout; public void setParentPath(String path) { _parent = path; @@ -3350,6 +3351,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S throw new InvalidParameterValueException(errorMessage); } else { uuid = cmd.getEntityUUID(); + processTimeout = cmd.getProcessTimeout(); if (isOneTimePostUrlUsed(cmd)) { uploadEntity = uploadEntityStateMap.get(uuid); StringBuilder errorMessage = new StringBuilder("The one time post url is already used"); @@ -3371,6 +3373,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S uploadEntity = new UploadEntity(uuid, cmd.getEntityId(), UploadEntity.Status.IN_PROGRESS, cmd.getName(), absolutePath); uploadEntity.setMetaDataPopulated(true); uploadEntity.setResourceType(UploadEntity.ResourceType.valueOf(cmd.getType())); + uploadEntity.setProcessTimeout(processTimeout); uploadEntity.setFormat(Storage.ImageFormat.valueOf(cmd.getImageFormat())); //relative path with out ssvm mount info. uploadEntity.setTemplatePath(absolutePath); @@ -3452,7 +3455,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return (int)Math.ceil(sizeInBytes * 1.0d / (1024 * 1024 * 1024)); } - public String postUpload(String uuid, String filename) { + public String postUpload(String uuid, String filename, long processTimeout) { UploadEntity uploadEntity = uploadEntityStateMap.get(uuid); int installTimeoutPerGig = 180 * 60 * 1000; @@ -3557,7 +3560,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S for (Processor processor : processors.values()) { FormatInfo info = null; try { - info = processor.process(resourcePath, null, templateName); + info = processor.process(resourcePath, null, templateName, processTimeout * 1000); } catch (InternalErrorException e) { s_logger.error("Template process exception ", e); return e.toString(); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java index 5fa13a34cfc..2ace37f675a 100644 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java @@ -90,7 +90,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager private String _name; StorageLayer _storage; public Map _processors; - + private long _processTimeout; private Integer _nfsVersion; public class Completion implements DownloadCompleteCallback { @@ -459,7 +459,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager FormatInfo info = null; try { - info = processor.process(resourcePath, null, templateName); + info = processor.process(resourcePath, null, templateName, this._processTimeout); } catch (InternalErrorException e) { s_logger.error("Template process exception ", e); return e.toString(); @@ -677,6 +677,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager @Override public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd) { + int timeout = NumbersUtil.parseInt(cmd.getContextParam("vmware.package.ova.timeout"), 3600000); + this._processTimeout = timeout; ResourceType resourceType = cmd.getResourceType(); if (cmd instanceof DownloadProgressCommand) { return handleDownloadProgressCmd(resource, (DownloadProgressCommand)cmd); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java index d851143b200..031a163997e 100644 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java @@ -34,6 +34,7 @@ public class UploadEntity { private int maxSizeInGB; private String description; private long contentLength; + private long processTimeout; public static enum ResourceType { VOLUME, TEMPLATE @@ -60,6 +61,14 @@ public class UploadEntity { this.entityId=entityId; } + public void setProcessTimeout(long processTimeout) { + this.processTimeout = processTimeout; + } + + public long getProcessTimeout() { + return processTimeout; + } + public UploadEntity(){ } diff --git a/test/integration/plugins/solidfire/TestCapacityManagement.py b/test/integration/plugins/solidfire/TestCapacityManagement.py new file mode 100644 index 00000000000..ab6eff124cd --- /dev/null +++ b/test/integration/plugins/solidfire/TestCapacityManagement.py @@ -0,0 +1,334 @@ +# 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. + +import logging +import random +import SignedAPICall +import XenAPI + +from solidfire.factory import ElementFactory + +from util import sf_util + +# All tests inherit from cloudstackTestCase +from marvin.cloudstackTestCase import cloudstackTestCase + +# Import Integration Libraries + +# base - contains all resources as entities and defines create, delete, list operations on them +from marvin.lib.base import Account, ServiceOffering, StoragePool, User, VirtualMachine + +# common - commonly used methods for all tests are listed here +from marvin.lib.common import get_domain, get_template, get_zone, list_clusters, list_hosts + +# utils - utility classes for common cleanup, external library wrappers, etc. +from marvin.lib.utils import cleanup_resources + +# Prerequisites: +# Only one zone +# Only one pod +# Only one cluster +# +# Running the tests: +# If using XenServer, verify the "xen_server_hostname" variable is correct. +# +# Note: +# If you do have more than one cluster, you might need to change this line: cls.cluster = list_clusters(cls.apiClient)[0] + + +class TestData(): + # constants + account = "account" + capacityBytes = "capacitybytes" + capacityIops = "capacityiops" + clusterId = "clusterId" + computeOffering = "computeoffering" + computeOffering2 = "computeoffering2" + domainId = "domainId" + email = "email" + firstname = "firstname" + hypervisor = "hypervisor" + lastname = "lastname" + mvip = "mvip" + name = "name" + password = "password" + port = "port" + primaryStorage = "primarystorage" + primaryStorage2 = "primarystorage2" + provider = "provider" + scope = "scope" + solidFire = "solidfire" + storageTag = "SolidFire_SAN_1" + storageTag2 = "SolidFire_SAN_2" + tags = "tags" + url = "url" + user = "user" + username = "username" + xenServer = "xenserver" + zoneId = "zoneId" + + hypervisor_type = xenServer + xen_server_hostname = "XenServer-6.5-1" + + def __init__(self): + self.testdata = { + TestData.solidFire: { + TestData.mvip: "10.117.40.120", + TestData.username: "admin", + TestData.password: "admin", + TestData.port: 443, + TestData.url: "https://10.117.40.120:443" + }, + TestData.xenServer: { + TestData.username: "root", + TestData.password: "solidfire" + }, + TestData.account: { + TestData.email: "test@test.com", + TestData.firstname: "John", + TestData.lastname: "Doe", + TestData.username: "test", + TestData.password: "test" + }, + TestData.user: { + TestData.email: "user@test.com", + TestData.firstname: "Jane", + TestData.lastname: "Doe", + TestData.username: "testuser", + TestData.password: "password" + }, + TestData.primaryStorage: { + TestData.name: "SolidFire-%d" % random.randint(0, 100), + TestData.scope: "ZONE", + TestData.url: "MVIP=10.117.40.120;SVIP=10.117.41.120;" + + "clusterAdminUsername=admin;clusterAdminPassword=admin;" + + "clusterDefaultMinIops=10000;clusterDefaultMaxIops=15000;" + + "clusterDefaultBurstIopsPercentOfMaxIops=1.5;", + TestData.provider: "SolidFire", + TestData.tags: TestData.storageTag, + TestData.capacityIops: 100000, + TestData.capacityBytes: 214748364800, # 200 GiB + TestData.hypervisor: "Any" + }, + TestData.primaryStorage2: { + TestData.name: "SolidFire-%d" % random.randint(0, 100), + TestData.scope: "ZONE", + TestData.url: "MVIP=10.117.40.120;SVIP=10.117.41.120;" + + "clusterAdminUsername=admin;clusterAdminPassword=admin;" + + "clusterDefaultMinIops=10000;clusterDefaultMaxIops=15000;" + + "clusterDefaultBurstIopsPercentOfMaxIops=1.5;", + TestData.provider: "SolidFire", + TestData.tags: TestData.storageTag2, + TestData.capacityIops: 800, + TestData.capacityBytes: 2251799813685248, # 2 PiB + TestData.hypervisor: "Any" + }, + TestData.computeOffering: { + TestData.name: "SF_CO_1", + "displaytext": "SF_CO_1 (Min IOPS = 300; Max IOPS = 600)", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + "storagetype": "shared", + "customizediops": False, + "miniops": "300", + "maxiops": "600", + "hypervisorsnapshotreserve": 200, + TestData.tags: TestData.storageTag + }, + TestData.computeOffering2: { + TestData.name: "SF_CO_2", + "displaytext": "SF_CO_2 (Min IOPS = 300; Max IOPS = 600)", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + "storagetype": "shared", + "customizediops": False, + "miniops": "300", + "maxiops": "600", + "hypervisorsnapshotreserve": 200, + TestData.tags: TestData.storageTag2 + }, + TestData.zoneId: 1, + TestData.clusterId: 1, + TestData.domainId: 1, + TestData.url: "10.117.40.114" + } + + +class TestCapacityManagement(cloudstackTestCase): + @classmethod + def setUpClass(cls): + # Set up API client + testclient = super(TestCapacityManagement, cls).getClsTestClient() + + cls.apiClient = testclient.getApiClient() + cls.configData = testclient.getParsedTestDataConfig() + cls.dbConnection = testclient.getDbConnection() + + cls.testdata = TestData().testdata + + sf_util.set_supports_resign(True, cls.dbConnection) + + cls._connect_to_hypervisor() + + # Set up SolidFire connection + solidfire = cls.testdata[TestData.solidFire] + + cls.sfe = ElementFactory.create(solidfire[TestData.mvip], solidfire[TestData.username], solidfire[TestData.password]) + + # Get Resources from Cloud Infrastructure + cls.zone = get_zone(cls.apiClient, zone_id=cls.testdata[TestData.zoneId]) + cls.cluster = list_clusters(cls.apiClient)[0] + cls.template = get_template(cls.apiClient, cls.zone.id, hypervisor=TestData.hypervisor_type) + cls.domain = get_domain(cls.apiClient, cls.testdata[TestData.domainId]) + + # Create test account + cls.account = Account.create( + cls.apiClient, + cls.testdata["account"], + admin=1 + ) + + # Set up connection to make customized API calls + cls.user = User.create( + cls.apiClient, + cls.testdata["user"], + account=cls.account.name, + domainid=cls.domain.id + ) + + url = cls.testdata[TestData.url] + + api_url = "http://" + url + ":8080/client/api" + userkeys = User.registerUserKeys(cls.apiClient, cls.user.id) + + cls.cs_api = SignedAPICall.CloudStack(api_url, userkeys.apikey, userkeys.secretkey) + + primarystorage = cls.testdata[TestData.primaryStorage] + + cls.primary_storage = StoragePool.create( + cls.apiClient, + primarystorage, + scope=primarystorage[TestData.scope], + zoneid=cls.zone.id, + provider=primarystorage[TestData.provider], + tags=primarystorage[TestData.tags], + capacityiops=primarystorage[TestData.capacityIops], + capacitybytes=primarystorage[TestData.capacityBytes], + hypervisor=primarystorage[TestData.hypervisor] + ) + + primarystorage2 = cls.testdata[TestData.primaryStorage2] + + cls.primary_storage_2 = StoragePool.create( + cls.apiClient, + primarystorage2, + scope=primarystorage2[TestData.scope], + zoneid=cls.zone.id, + provider=primarystorage2[TestData.provider], + tags=primarystorage2[TestData.tags], + capacityiops=primarystorage2[TestData.capacityIops], + capacitybytes=primarystorage2[TestData.capacityBytes], + hypervisor=primarystorage2[TestData.hypervisor] + ) + + cls.compute_offering = ServiceOffering.create( + cls.apiClient, + cls.testdata[TestData.computeOffering] + ) + + cls.compute_offering_2 = ServiceOffering.create( + cls.apiClient, + cls.testdata[TestData.computeOffering2] + ) + + # Resources that are to be destroyed + cls._cleanup = [ + cls.compute_offering, + cls.compute_offering_2, + cls.user, + cls.account + ] + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiClient, cls._cleanup) + + cls.primary_storage.delete(cls.apiClient) + cls.primary_storage_2.delete(cls.apiClient) + + sf_util.purge_solidfire_volumes(cls.sfe) + except Exception as e: + logging.debug("Exception in tearDownClass(cls): %s" % e) + + def setUp(self): + self.cleanup = [] + + def tearDown(self): + cleanup_resources(self.apiClient, self.cleanup) + + def test_01_not_enough_storage_space(self): + self._run_vms(self.compute_offering.id) + + def test_02_not_enough_storage_performance(self): + self._run_vms(self.compute_offering_2.id) + + def _run_vms(self, compute_offering_id): + try: + # Based on the primary storage's space or performance and the storage requirements + # of the compute offering, we should fail to create a VM on the third try. + for _ in range(0, 3): + number = random.randint(0, 1000) + + vm_name = { + TestData.name: "VM-%d" % number, + "displayname": "Test VM %d" % number + } + + virtual_machine = VirtualMachine.create( + self.apiClient, + vm_name, + accountid=self.account.name, + zoneid=self.zone.id, + serviceofferingid=compute_offering_id, + templateid=self.template.id, + domainid=self.domain.id, + startvm=True + ) + + self.cleanup.append(virtual_machine) + except: + pass + + self.assertEqual( + len(self.cleanup), + 2, + "Only two VMs should have been successfully created." + ) + + @classmethod + def _connect_to_hypervisor(cls): + host_ip = "https://" + \ + list_hosts(cls.apiClient, clusterid=cls.testdata[TestData.clusterId], name=TestData.xen_server_hostname)[0].ipaddress + + cls.xen_session = XenAPI.Session(host_ip) + + xen_server = cls.testdata[TestData.xenServer] + + cls.xen_session.xenapi.login_with_password(xen_server[TestData.username], xen_server[TestData.password]) diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index 1cba7505491..e9b6138d0b6 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -2859,7 +2859,10 @@ if (jsonObj.state == "Ready") { allowedActions.push("remove"); allowedActions.push("revertToVMSnapshot"); - allowedActions.push("takeSnapshot"); + + if (args && args.context && args.context.instances && args.context.instances[0].hypervisor && args.context.instances[0].hypervisor === "KVM") { + allowedActions.push("takeSnapshot"); + } } return allowedActions; diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 14e41af2b23..0d38ed4c3f2 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -1334,7 +1334,7 @@ url: createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), success: function(json) { var items = json.listnetworkaclsresponse.networkacl.sort(function(a, b) { - return a.number >= b.number; + return a.number - b.number; }).map(function(acl) { if (parseInt(acl.protocol)) { // protocol number acl.protocolnumber = acl.protocol; diff --git a/utils/src/main/java/com/cloud/utils/DateUtil.java b/utils/src/main/java/com/cloud/utils/DateUtil.java index 7787e1be3ba..9f046d11446 100644 --- a/utils/src/main/java/com/cloud/utils/DateUtil.java +++ b/utils/src/main/java/com/cloud/utils/DateUtil.java @@ -38,10 +38,14 @@ public class DateUtil { return new Date(); } - // yyyy-MM-ddTHH:mm:ssZxxxx + // yyyy-MM-ddTHH:mm:ssZZZZ or yyyy-MM-ddTHH:mm:ssZxxxx public static Date parseTZDateString(String str) throws ParseException { - DateFormat dfParse = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'Z"); - return dfParse.parse(str); + try { + return s_outputFormat.parse(str); + } catch (ParseException e) { + final DateFormat dfParse = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'Z"); + return dfParse.parse(str); + } } public static Date parseDateString(TimeZone tz, String dateString) { diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index b73371ac715..35aa24b1a84 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -233,18 +233,23 @@ public class Script implements Callable { } while (true) { + _logger.debug("Executing while with timeout : " + _timeout); try { - if (_process.waitFor() == 0) { - _logger.debug("Execution is successful."); - if (interpreter != null) { - return interpreter.drain() ? task.getResult() : interpreter.interpret(ir); - } else { - // null return exitValue apparently - return String.valueOf(_process.exitValue()); + //process execution completed within timeout period + if (_process.waitFor(_timeout, TimeUnit.MILLISECONDS)) { + //process completed successfully + if (_process.exitValue() == 0) { + _logger.debug("Execution is successful."); + if (interpreter != null) { + return interpreter.drain() ? task.getResult() : interpreter.interpret(ir); + } else { + // null return exitValue apparently + return String.valueOf(_process.exitValue()); + } + } else { //process failed + break; } - } else { - break; - } + } //timeout } catch (InterruptedException e) { if (!_isTimeOut) { /* @@ -254,24 +259,25 @@ public class Script implements Callable { _logger.debug("We are interrupted but it's not a timeout, just continue"); continue; } - - TimedOutLogger log = new TimedOutLogger(_process); - Task timedoutTask = new Task(log, ir); - - timedoutTask.run(); - if (!_passwordCommand) { - _logger.warn("Timed out: " + buildCommandLine(command) + ". Output is: " + timedoutTask.getResult()); - } else { - _logger.warn("Timed out: " + buildCommandLine(command)); - } - - return ERR_TIMEOUT; } finally { if (future != null) { future.cancel(false); } Thread.interrupted(); } + + //timeout without completing the process + TimedOutLogger log = new TimedOutLogger(_process); + Task timedoutTask = new Task(log, ir); + + timedoutTask.run(); + if (!_passwordCommand) { + _logger.warn("Timed out: " + buildCommandLine(command) + ". Output is: " + timedoutTask.getResult()); + } else { + _logger.warn("Timed out: " + buildCommandLine(command)); + } + + return ERR_TIMEOUT; } _logger.debug("Exit value is " + _process.exitValue()); @@ -300,7 +306,7 @@ public class Script implements Callable { IOUtils.closeQuietly(_process.getErrorStream()); IOUtils.closeQuietly(_process.getOutputStream()); IOUtils.closeQuietly(_process.getInputStream()); - _process.destroy(); + _process.destroyForcibly(); } } } diff --git a/utils/src/test/java/com/cloud/utils/DateUtilTest.java b/utils/src/test/java/com/cloud/utils/DateUtilTest.java index ba88505f04d..190adeab2db 100644 --- a/utils/src/test/java/com/cloud/utils/DateUtilTest.java +++ b/utils/src/test/java/com/cloud/utils/DateUtilTest.java @@ -27,6 +27,9 @@ import java.util.TimeZone; import com.cloud.utils.DateUtil.IntervalType; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; public class DateUtilTest { @@ -44,17 +47,25 @@ public class DateUtilTest { if (args.length == 2) { System.out.println("Next run time: " + DateUtil.getNextRunTime(IntervalType.getIntervalType(args[0]), args[1], "GMT", time).toString()); } - - time = new Date(); - DateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'Z"); - String str = dfDate.format(time); - System.out.println("Formated TZ time string : " + str); - try { - Date dtParsed = DateUtil.parseTZDateString(str); - System.out.println("Parsed TZ time string : " + dtParsed.toString()); - } catch (ParseException e) { - System.err.println("Parsing failed\n string : " + str + "\nexception :" + e.getLocalizedMessage()); - } } + @Test + public void zonedTimeFormatLegacy() throws ParseException { + Date time = new Date(); + DateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'Z"); + String str = dfDate.format(time); + Date dtParsed = DateUtil.parseTZDateString(str); + + assertEquals(time.toString(), dtParsed.toString()); + } + + @Test + public void zonedTimeFormat() throws ParseException { + Date time = new Date(); + DateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + String str = dfDate.format(time); + Date dtParsed = DateUtil.parseTZDateString(str); + + assertEquals(time.toString(), dtParsed.toString()); + } }