mirror of https://github.com/apache/cloudstack.git
Merge commit '19b4ef106931aa1d6a8fed06984009d86760e4de' into 4.22
This commit is contained in:
commit
1085da4ef8
|
|
@ -26,10 +26,13 @@ public final class BucketTO {
|
|||
|
||||
private String secretKey;
|
||||
|
||||
private long accountId;
|
||||
|
||||
public BucketTO(Bucket bucket) {
|
||||
this.name = bucket.getName();
|
||||
this.accessKey = bucket.getAccessKey();
|
||||
this.secretKey = bucket.getSecretKey();
|
||||
this.accountId = bucket.getAccountId();
|
||||
}
|
||||
|
||||
public BucketTO(String name) {
|
||||
|
|
@ -47,4 +50,8 @@ public final class BucketTO {
|
|||
public String getSecretKey() {
|
||||
return this.secretKey;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public interface ProjectService {
|
|||
|
||||
Project updateProject(long id, String name, String displayText, String newOwnerName, Long userId, Role newRole) throws ResourceAllocationException;
|
||||
|
||||
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType);
|
||||
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException;
|
||||
|
||||
boolean deleteAccountFromProject(long projectId, String accountName);
|
||||
|
||||
|
|
@ -100,6 +100,6 @@ public interface ProjectService {
|
|||
|
||||
Project findByProjectAccountIdIncludingRemoved(long projectAccountId);
|
||||
|
||||
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole);
|
||||
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@ import org.apache.cloudstack.api.InternalIdentity;
|
|||
|
||||
public interface VMTemplateStorageResourceAssoc extends InternalIdentity {
|
||||
public static enum Status {
|
||||
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
|
||||
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, LIMIT_REACHED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
|
||||
}
|
||||
|
||||
List<Status> ERROR_DOWNLOAD_STATES = List.of(Status.DOWNLOAD_ERROR, Status.ABANDONED, Status.LIMIT_REACHED, Status.UNKNOWN);
|
||||
List<Status> PENDING_DOWNLOAD_STATES = List.of(Status.NOT_DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
|
||||
|
||||
String getInstallPath();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
|
||||
public interface ResourceLimitService {
|
||||
|
||||
|
|
@ -191,6 +192,7 @@ public interface ResourceLimitService {
|
|||
*/
|
||||
public void checkResourceLimit(Account account, ResourceCount.ResourceType type, long... count) throws ResourceAllocationException;
|
||||
public void checkResourceLimitWithTag(Account account, ResourceCount.ResourceType type, String tag, long... count) throws ResourceAllocationException;
|
||||
public void checkResourceLimitWithTag(Account account, Long domainId, boolean considerSystemAccount, ResourceCount.ResourceType type, String tag, long... count) throws ResourceAllocationException;
|
||||
|
||||
/**
|
||||
* Gets the count of resources for a resource type and account
|
||||
|
|
@ -251,12 +253,12 @@ public interface ResourceLimitService {
|
|||
List<String> getResourceLimitStorageTags(DiskOffering diskOffering);
|
||||
void updateTaggedResourceLimitsAndCountsForAccounts(List<AccountResponse> responses, String tag);
|
||||
void updateTaggedResourceLimitsAndCountsForDomains(List<DomainResponse> responses, String tag);
|
||||
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
|
||||
|
||||
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering);
|
||||
void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
|
||||
DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException;
|
||||
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
|
||||
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
|
||||
void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
|
||||
|
|
@ -273,25 +275,23 @@ public interface ResourceLimitService {
|
|||
|
||||
void incrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
|
||||
void decrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
|
||||
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
|
||||
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
|
||||
void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
|
||||
|
||||
void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException;
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException;
|
||||
void incrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
|
||||
void decrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
|
||||
void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException;
|
||||
void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
|
||||
void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
|
||||
|
||||
void checkVmGpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) throws ResourceAllocationException;
|
||||
void incrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
|
||||
void decrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
|
||||
|
||||
long recalculateDomainResourceCount(final long domainId, final ResourceType type, String tag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ public class ApiConstants {
|
|||
public static final String RECOVER = "recover";
|
||||
public static final String REPAIR = "repair";
|
||||
public static final String REQUIRES_HVM = "requireshvm";
|
||||
public static final String RESERVED_RESOURCE_DETAILS = "reservedresourcedetails";
|
||||
public static final String RESOURCES = "resources";
|
||||
public static final String RESOURCE_COUNT = "resourcecount";
|
||||
public static final String RESOURCE_NAME = "resourcename";
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.account;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
|
|
@ -106,7 +107,7 @@ public class AddAccountToProjectCmd extends BaseAsyncCmd {
|
|||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public void execute() throws ResourceAllocationException {
|
||||
if (accountName == null && email == null) {
|
||||
throw new InvalidParameterValueException("Either accountName or email is required");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.apache.cloudstack.api.command.user.account;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
|
|
@ -111,7 +112,7 @@ public class AddUserToProjectCmd extends BaseAsyncCmd {
|
|||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public void execute() throws ResourceAllocationException {
|
||||
validateInput();
|
||||
boolean result = _projectService.addUserToProject(getProjectId(), getUsername(), getEmail(), getProjectRoleId(), getRoleType());
|
||||
if (result) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command.user.backup;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
|
|
@ -53,6 +54,7 @@ public class RestoreVolumeFromBackupAndAttachToVMCmd extends BaseAsyncCmd {
|
|||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.BACKUP_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = BackupResponse.class,
|
||||
|
|
@ -60,12 +62,14 @@ public class RestoreVolumeFromBackupAndAttachToVMCmd extends BaseAsyncCmd {
|
|||
description = "ID of the Instance backup")
|
||||
private Long backupId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.VOLUME_ID,
|
||||
type = CommandType.STRING,
|
||||
required = true,
|
||||
description = "ID of the volume backed up")
|
||||
private String volumeUuid;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = UserVmResponse.class,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public class CreateVMFromBackupCmd extends BaseDeployVMCmd {
|
|||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.BACKUP_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = BackupResponse.class,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ public class ExtensionResponse extends BaseResponse {
|
|||
@Param(description = "Removal timestamp of the extension, if applicable")
|
||||
private Date removed;
|
||||
|
||||
@SerializedName(ApiConstants.RESERVED_RESOURCE_DETAILS)
|
||||
@Param(description = "Resource detail names as comma separated string that should be reserved and not visible " +
|
||||
"to end users",
|
||||
since = "4.22.1")
|
||||
protected String reservedResourceDetails;
|
||||
|
||||
public ExtensionResponse(String id, String name, String description, String type) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
|
|
@ -179,4 +185,8 @@ public class ExtensionResponse extends BaseResponse {
|
|||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
public void setReservedResourceDetails(String reservedResourceDetails) {
|
||||
this.reservedResourceDetails = reservedResourceDetails;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,11 @@
|
|||
|
||||
package org.apache.cloudstack.extension;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtensionHelper {
|
||||
Long getExtensionIdForCluster(long clusterId);
|
||||
Extension getExtension(long id);
|
||||
Extension getExtensionForCluster(long clusterId);
|
||||
List<String> getExtensionReservedResourceDetails(long extensionId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
// 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.resourcelimit;
|
||||
|
||||
/**
|
||||
* Interface implemented by <code>CheckedReservation</code>.
|
||||
* </br></br>
|
||||
* This is defined in <code>cloud-api</code> to allow methods declared in modules that do not depend on <code>cloud-server</code>
|
||||
* to receive <code>CheckedReservations</code> as parameters.
|
||||
*/
|
||||
public interface Reserver extends AutoCloseable {
|
||||
|
||||
void close();
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.test;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
|
@ -149,6 +150,8 @@ public class AddAccountToProjectCmdTest extends TestCase {
|
|||
addAccountToProjectCmd.execute();
|
||||
} catch (InvalidParameterValueException exception) {
|
||||
Assert.assertEquals("Either accountName or email is required", exception.getLocalizedMessage());
|
||||
} catch (ResourceAllocationException exception) {
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ public class DownloadAnswer extends Answer {
|
|||
}
|
||||
|
||||
public Long getTemplateSize() {
|
||||
return templateSize;
|
||||
return templateSize == 0 ? templatePhySicalSize : templateSize;
|
||||
}
|
||||
|
||||
public void setTemplatePhySicalSize(long templatePhySicalSize) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package org.apache.cloudstack.direct.download;
|
|||
import com.cloud.utils.UriUtils;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.utils.security.DigestHelper;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
|
@ -33,6 +34,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDownloader {
|
||||
|
||||
|
|
@ -128,15 +130,14 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown
|
|||
*/
|
||||
protected File createTemporaryDirectoryAndFile(String downloadDir) {
|
||||
createFolder(downloadDir);
|
||||
return new File(downloadDir + File.separator + getFileNameFromUrl());
|
||||
return new File(downloadDir + File.separator + getTemporaryFileName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return filename from url
|
||||
* Return filename from the temporary download file
|
||||
*/
|
||||
public String getFileNameFromUrl() {
|
||||
String[] urlParts = url.split("/");
|
||||
return urlParts[urlParts.length - 1];
|
||||
public String getTemporaryFileName() {
|
||||
return String.format("%s.%s", UUID.randomUUID(), FilenameUtils.getExtension(url));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm
|
|||
DirectTemplateDownloader urlDownloader = createDownloaderForMetalinks(getUrl(), getTemplateId(), getDestPoolPath(),
|
||||
getChecksum(), headers, connectTimeout, soTimeout, null, temporaryDownloadPath);
|
||||
try {
|
||||
setDownloadedFilePath(downloadDir + File.separator + getFileNameFromUrl());
|
||||
setDownloadedFilePath(downloadDir + File.separator + getTemporaryFileName());
|
||||
File f = new File(getDownloadedFilePath());
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public class NfsDirectTemplateDownloader extends DirectTemplateDownloaderImpl {
|
|||
String mount = String.format(mountCommand, srcHost + ":" + srcPath, "/mnt/" + mountSrcUuid);
|
||||
Script.runSimpleBashScript(mount);
|
||||
String downloadDir = getDestPoolPath() + File.separator + getDirectDownloadTempPath(getTemplateId());
|
||||
setDownloadedFilePath(downloadDir + File.separator + getFileNameFromUrl());
|
||||
setDownloadedFilePath(downloadDir + File.separator + getTemporaryFileName());
|
||||
Script.runSimpleBashScript("cp /mnt/" + mountSrcUuid + srcPath + " " + getDownloadedFilePath());
|
||||
Script.runSimpleBashScript("umount /mnt/" + mountSrcUuid);
|
||||
return new Pair<>(true, getDownloadedFilePath());
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import com.cloud.configuration.Resource;
|
||||
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
|
||||
|
||||
public class TemplateOrVolumePostUploadCommand {
|
||||
|
||||
long entityId;
|
||||
|
|
@ -185,6 +188,11 @@ public class TemplateOrVolumePostUploadCommand {
|
|||
this.description = description;
|
||||
}
|
||||
|
||||
public void setDefaultMaxSecondaryStorageInBytes(long defaultMaxSecondaryStorageInBytes) {
|
||||
this.defaultMaxSecondaryStorageInGB = defaultMaxSecondaryStorageInBytes != Resource.RESOURCE_UNLIMITED ?
|
||||
ByteScaleUtils.bytesToGibibytes(defaultMaxSecondaryStorageInBytes) : Resource.RESOURCE_UNLIMITED;
|
||||
}
|
||||
|
||||
public void setDefaultMaxSecondaryStorageInGB(long defaultMaxSecondaryStorageInGB) {
|
||||
this.defaultMaxSecondaryStorageInGB = defaultMaxSecondaryStorageInGB;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class UploadStatusCommand extends Command {
|
|||
}
|
||||
private String entityUuid;
|
||||
private EntityType entityType;
|
||||
private Boolean abort;
|
||||
|
||||
protected UploadStatusCommand() {
|
||||
}
|
||||
|
|
@ -37,6 +38,11 @@ public class UploadStatusCommand extends Command {
|
|||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
public UploadStatusCommand(String entityUuid, EntityType entityType, Boolean abort) {
|
||||
this(entityUuid, entityType);
|
||||
this.abort = abort;
|
||||
}
|
||||
|
||||
public String getEntityUuid() {
|
||||
return entityUuid;
|
||||
}
|
||||
|
|
@ -45,6 +51,10 @@ public class UploadStatusCommand extends Command {
|
|||
return entityType;
|
||||
}
|
||||
|
||||
public Boolean getAbort() {
|
||||
return abort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ public interface NetworkOrchestrationService {
|
|||
|
||||
void removeDhcpServiceInSubnet(Nic nic);
|
||||
|
||||
boolean resourceCountNeedsUpdate(NetworkOffering ntwkOff, ACLType aclType);
|
||||
boolean isResourceCountUpdateNeeded(NetworkOffering networkOffering);
|
||||
|
||||
void prepareAllNicsForMigration(VirtualMachineProfile vm, DeployDestination dest);
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ public interface VolumeOrchestrationService {
|
|||
void destroyVolume(Volume volume);
|
||||
|
||||
DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template,
|
||||
Account owner, Long deviceId);
|
||||
Account owner, Long deviceId, boolean incrementResourceCount);
|
||||
|
||||
VolumeInfo createVolumeOnPrimaryStorage(VirtualMachine vm, VolumeInfo volume, HypervisorType rootDiskHyperType, StoragePool storagePool) throws NoTransitionException;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import javax.inject.Inject;
|
|||
import javax.naming.ConfigurationException;
|
||||
import javax.persistence.EntityExistsException;
|
||||
|
||||
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
|
|
@ -308,7 +307,6 @@ import com.cloud.vm.snapshot.VMSnapshotVO;
|
|||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
||||
public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, VmWorkJobHandler, Listener, Configurable {
|
||||
|
||||
public static final String VM_WORK_JOB_HANDLER = VirtualMachineManagerImpl.class.getSimpleName();
|
||||
|
|
@ -586,7 +584,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
Long deviceId = dataDiskDeviceIds.get(index++);
|
||||
String volumeName = deviceId == null ? "DATA-" + persistedVm.getId() : "DATA-" + persistedVm.getId() + "-" + String.valueOf(deviceId);
|
||||
volumeMgr.allocateRawVolume(Type.DATADISK, volumeName, dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
|
||||
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, deviceId);
|
||||
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, deviceId, true);
|
||||
}
|
||||
}
|
||||
if (datadiskTemplateToDiskOfferingMap != null && !datadiskTemplateToDiskOfferingMap.isEmpty()) {
|
||||
|
|
@ -596,7 +594,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
long diskOfferingSize = diskOffering.getDiskSize() / (1024 * 1024 * 1024);
|
||||
VMTemplateVO dataDiskTemplate = _templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
|
||||
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId() + "-" + String.valueOf( diskNumber), diskOffering, diskOfferingSize, null, null,
|
||||
persistedVm, dataDiskTemplate, owner, diskNumber);
|
||||
persistedVm, dataDiskTemplate, owner, diskNumber, true);
|
||||
diskNumber++;
|
||||
}
|
||||
}
|
||||
|
|
@ -626,7 +624,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
String rootVolumeName = String.format("ROOT-%s", vm.getId());
|
||||
if (template.getFormat() == ImageFormat.ISO) {
|
||||
volumeMgr.allocateRawVolume(Type.ROOT, rootVolumeName, rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(),
|
||||
rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vm, template, owner, null);
|
||||
rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vm, template, owner, null, true);
|
||||
} else if (Arrays.asList(ImageFormat.BAREMETAL, ImageFormat.EXTERNAL).contains(template.getFormat())) {
|
||||
logger.debug("{} has format [{}]. Skipping ROOT volume [{}] allocation.", template, template.getFormat(), rootVolumeName);
|
||||
} else {
|
||||
|
|
@ -2213,7 +2211,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
protected boolean sendStop(final VirtualMachineGuru guru, final VirtualMachineProfile profile, final boolean force, final boolean checkBeforeCleanup) {
|
||||
final VirtualMachine vm = profile.getVirtualMachine();
|
||||
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
|
||||
|
||||
StopCommand stpCmd = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), checkBeforeCleanup);
|
||||
updateStopCommandForExternalHypervisorType(vm.getHypervisorType(), profile, stpCmd);
|
||||
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
|
||||
|
|
@ -5272,9 +5269,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
private void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering) {
|
||||
Map<String, String> details = vmInstanceDetailsDao.listDetailsKeyPairs(vmId);
|
||||
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
|
||||
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
|
||||
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
|
||||
|
||||
// We need to restore only the customizable parameters. If we save a parameter that is not customizable and attempt
|
||||
// to restore a VM snapshot, com.cloud.vm.UserVmManagerImpl.validateCustomParameters will fail.
|
||||
ServiceOffering unfilledOffering = _serviceOfferingDao.findByIdIncludingRemoved(serviceOffering.getId());
|
||||
if (unfilledOffering.getCpu() == null) {
|
||||
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
|
||||
}
|
||||
if (unfilledOffering.getSpeed() == null) {
|
||||
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
|
||||
}
|
||||
if (unfilledOffering.getRamSize() == null) {
|
||||
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
|
||||
}
|
||||
|
||||
List<VMInstanceDetailVO> detailList = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry: details.entrySet()) {
|
||||
VMInstanceDetailVO detailVO = new VMInstanceDetailVO(vmId, entry.getKey(), entry.getValue(), true);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import org.apache.cloudstack.framework.messagebus.PublishScope;
|
|||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.network.RoutedIpv4Manager;
|
||||
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
|
@ -86,6 +87,7 @@ import com.cloud.api.query.dao.DomainRouterJoinDao;
|
|||
import com.cloud.api.query.vo.DomainRouterJoinVO;
|
||||
import com.cloud.bgp.BGPService;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.dc.ASNumberVO;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
|
|
@ -214,6 +216,7 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
|
|||
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ManagementServer;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.ResourceLimitService;
|
||||
|
|
@ -447,6 +450,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
ClusterDao clusterDao;
|
||||
@Inject
|
||||
RoutedIpv4Manager routedIpv4Manager;
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
|
||||
protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
|
||||
ScheduledExecutorService _executor;
|
||||
|
|
@ -2752,12 +2757,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return null;
|
||||
}
|
||||
|
||||
final boolean updateResourceCount = resourceCountNeedsUpdate(ntwkOff, aclType);
|
||||
//check resource limits
|
||||
if (updateResourceCount) {
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.network, isDisplayNetworkEnabled);
|
||||
}
|
||||
|
||||
// Validate network offering
|
||||
if (ntwkOff.getState() != NetworkOffering.State.Enabled) {
|
||||
// see NetworkOfferingVO
|
||||
|
|
@ -2776,6 +2775,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
|
||||
boolean ipv6 = false;
|
||||
|
||||
try (CheckedReservation networkReservation = new CheckedReservation(owner, domainId, Resource.ResourceType.network, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
if (StringUtils.isNoneBlank(ip6Gateway, ip6Cidr)) {
|
||||
ipv6 = true;
|
||||
}
|
||||
|
|
@ -3115,8 +3116,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
}
|
||||
}
|
||||
|
||||
if (updateResourceCount) {
|
||||
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.network, isDisplayNetworkEnabled);
|
||||
if (isResourceCountUpdateNeeded(ntwkOff)) {
|
||||
changeAccountResourceCountOrRecalculateDomainResourceCount(owner.getAccountId(), domainId, isDisplayNetworkEnabled, true);
|
||||
}
|
||||
UsageEventUtils.publishNetworkCreation(network);
|
||||
|
||||
|
|
@ -3127,6 +3128,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
CallContext.current().setEventDetails("Network Id: " + network.getId());
|
||||
CallContext.current().putContextParameter(Network.class, network.getUuid());
|
||||
return network;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -3492,9 +3494,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
}
|
||||
|
||||
final NetworkOffering ntwkOff = _entityMgr.findById(NetworkOffering.class, networkFinal.getNetworkOfferingId());
|
||||
final boolean updateResourceCount = resourceCountNeedsUpdate(ntwkOff, networkFinal.getAclType());
|
||||
if (updateResourceCount) {
|
||||
_resourceLimitMgr.decrementResourceCount(networkFinal.getAccountId(), ResourceType.network, networkFinal.getDisplayNetwork());
|
||||
if (isResourceCountUpdateNeeded(ntwkOff)) {
|
||||
changeAccountResourceCountOrRecalculateDomainResourceCount(networkFinal.getAccountId(), networkFinal.getDomainId(), networkFinal.getDisplayNetwork(), false);
|
||||
}
|
||||
}
|
||||
return deletedVlans.second();
|
||||
|
|
@ -3517,6 +3518,23 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* If it is a shared network with {@link ACLType#Domain}, it will belong to account {@link Account#ACCOUNT_ID_SYSTEM} and the resources will be not incremented for the
|
||||
* domain. Therefore, we force the recalculation of the domain's resource count in this case. Otherwise, it will change the count for the account owner.
|
||||
* @param incrementAccountResourceCount If true, the account resource count will be incremented by 1; otherwise, it will decremented by 1.
|
||||
*/
|
||||
private void changeAccountResourceCountOrRecalculateDomainResourceCount(Long accountId, Long domainId, boolean displayNetwork, boolean incrementAccountResourceCount) {
|
||||
if (Account.ACCOUNT_ID_SYSTEM == accountId && ObjectUtils.isNotEmpty(domainId)) {
|
||||
_resourceLimitMgr.recalculateDomainResourceCount(domainId, ResourceType.network, null);
|
||||
} else {
|
||||
if (incrementAccountResourceCount) {
|
||||
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.network, displayNetwork);
|
||||
} else {
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.network, displayNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void publishDeletedVlanRanges(List<VlanVO> deletedVlanRangeToPublish) {
|
||||
if (CollectionUtils.isNotEmpty(deletedVlanRangeToPublish)) {
|
||||
for (VlanVO vlan : deletedVlanRangeToPublish) {
|
||||
|
|
@ -3526,10 +3544,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean resourceCountNeedsUpdate(final NetworkOffering ntwkOff, final ACLType aclType) {
|
||||
//Update resource count only for Isolated account specific non-system networks
|
||||
final boolean updateResourceCount = ntwkOff.getGuestType() == GuestType.Isolated && !ntwkOff.isSystemOnly() && aclType == ACLType.Account;
|
||||
return updateResourceCount;
|
||||
public boolean isResourceCountUpdateNeeded(NetworkOffering networkOffering) {
|
||||
return !networkOffering.isSystemOnly();
|
||||
}
|
||||
|
||||
protected Pair<Boolean, List<VlanVO>> deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import javax.naming.ConfigurationException;
|
|||
|
||||
import com.cloud.deploy.DeploymentClusterPlanner;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
|
|
@ -82,6 +83,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
|||
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
||||
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.secret.PassphraseVO;
|
||||
import org.apache.cloudstack.secret.dao.PassphraseDao;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
|
|
@ -862,7 +864,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", create = true)
|
||||
@Override
|
||||
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner,
|
||||
Long deviceId) {
|
||||
Long deviceId, boolean incrementResourceCount) {
|
||||
if (size == null) {
|
||||
size = offering.getDiskSize();
|
||||
} else {
|
||||
|
|
@ -901,7 +903,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
saveVolumeDetails(offering.getId(), vol.getId());
|
||||
|
||||
// Save usage event and update resource count for user vm volumes
|
||||
if (vm.getType() == VirtualMachine.Type.User) {
|
||||
if (vm.getType() == VirtualMachine.Type.User && incrementResourceCount) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
|
||||
Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
|
||||
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
|
||||
|
|
@ -1942,14 +1944,20 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
template == null ? null : template.getSize(),
|
||||
vol.getPassphraseId() != null);
|
||||
|
||||
if (newSize != vol.getSize()) {
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
|
||||
if (newSize == vol.getSize()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
VMInstanceVO vm = vol.getInstanceId() != null ? vmInstanceDao.findById(vol.getInstanceId()) : null;
|
||||
if (vm == null || vm.getType() == VirtualMachine.Type.User) {
|
||||
// Update resource count for user vm volumes when volume is attached
|
||||
if (newSize > vol.getSize()) {
|
||||
_resourceLimitMgr.checkPrimaryStorageResourceLimit(_accountMgr.getActiveAccountById(vol.getAccountId()),
|
||||
vol.isDisplay(), newSize - vol.getSize(), diskOffering);
|
||||
vol.isDisplay(), newSize - vol.getSize(), diskOffering, reservations);
|
||||
_resourceLimitMgr.incrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(),
|
||||
newSize - vol.getSize(), diskOffering);
|
||||
} else {
|
||||
|
|
@ -1957,9 +1965,11 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
vol.getSize() - newSize, diskOffering);
|
||||
}
|
||||
}
|
||||
vol.setSize(newSize);
|
||||
_volsDao.persist(vol);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
vol.setSize(newSize);
|
||||
_volsDao.persist(vol);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,6 +27,6 @@ public interface AccountVlanMapDao extends GenericDao<AccountVlanMapVO, Long> {
|
|||
|
||||
public List<AccountVlanMapVO> listAccountVlanMapsByVlan(long vlanDbId);
|
||||
|
||||
public AccountVlanMapVO findAccountVlanMap(long accountId, long vlanDbId);
|
||||
public AccountVlanMapVO findAccountVlanMap(Long accountId, long vlanDbId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ public class AccountVlanMapDaoImpl extends GenericDaoBase<AccountVlanMapVO, Long
|
|||
}
|
||||
|
||||
@Override
|
||||
public AccountVlanMapVO findAccountVlanMap(long accountId, long vlanDbId) {
|
||||
public AccountVlanMapVO findAccountVlanMap(Long accountId, long vlanDbId) {
|
||||
SearchCriteria<AccountVlanMapVO> sc = AccountVlanSearch.create();
|
||||
sc.setParameters("accountId", accountId);
|
||||
sc.setParametersIfNotNull("accountId", accountId);
|
||||
sc.setParameters("vlanDbId", vlanDbId);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,5 +24,5 @@ import com.cloud.utils.db.GenericDao;
|
|||
public interface DomainVlanMapDao extends GenericDao<DomainVlanMapVO, Long> {
|
||||
public List<DomainVlanMapVO> listDomainVlanMapsByDomain(long domainId);
|
||||
public List<DomainVlanMapVO> listDomainVlanMapsByVlan(long vlanDbId);
|
||||
public DomainVlanMapVO findDomainVlanMap(long domainId, long vlanDbId);
|
||||
public DomainVlanMapVO findDomainVlanMap(Long domainId, long vlanDbId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ public class DomainVlanMapDaoImpl extends GenericDaoBase<DomainVlanMapVO, Long>
|
|||
}
|
||||
|
||||
@Override
|
||||
public DomainVlanMapVO findDomainVlanMap(long domainId, long vlanDbId) {
|
||||
public DomainVlanMapVO findDomainVlanMap(Long domainId, long vlanDbId) {
|
||||
SearchCriteria<DomainVlanMapVO> sc = DomainVlanSearch.create();
|
||||
sc.setParameters("domainId", domainId);
|
||||
sc.setParametersIfNotNull("domainId", domainId);
|
||||
sc.setParameters("vlanDbId", vlanDbId);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ SELECT
|
|||
`vm_template`.`format` AS `template_format`,
|
||||
`vm_template`.`display_text` AS `template_display_text`,
|
||||
`vm_template`.`enable_password` AS `password_enabled`,
|
||||
`vm_template`.`extension_id` AS `template_extension_id`,
|
||||
`iso`.`id` AS `iso_id`,
|
||||
`iso`.`uuid` AS `iso_uuid`,
|
||||
`iso`.`name` AS `iso_name`,
|
||||
|
|
|
|||
|
|
@ -230,8 +230,10 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
|
|||
updateBuilder.setJobId(answer.getJobId());
|
||||
updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
|
||||
updateBuilder.setInstallPath(answer.getInstallPath());
|
||||
updateBuilder.setSize(answer.getTemplateSize());
|
||||
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
|
||||
if (!VMTemplateStorageResourceAssoc.ERROR_DOWNLOAD_STATES.contains(answer.getDownloadStatus())) {
|
||||
updateBuilder.setSize(answer.getTemplateSize());
|
||||
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
|
||||
}
|
||||
_templateStoreDao.update(tmpltStoreVO.getId(), updateBuilder);
|
||||
// update size in vm_template table
|
||||
VMTemplateVO tmlptUpdater = _templateDao.createForUpdate();
|
||||
|
|
@ -241,8 +243,7 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
|
|||
|
||||
AsyncCompletionCallback<CreateCmdResult> caller = context.getParentCallback();
|
||||
|
||||
if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR ||
|
||||
answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) {
|
||||
if (VMTemplateStorageResourceAssoc.ERROR_DOWNLOAD_STATES.contains(answer.getDownloadStatus())) {
|
||||
CreateCmdResult result = new CreateCmdResult(null, null);
|
||||
result.setSuccess(false);
|
||||
result.setResult(answer.getErrorString());
|
||||
|
|
@ -285,19 +286,22 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
|
|||
updateBuilder.setJobId(answer.getJobId());
|
||||
updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
|
||||
updateBuilder.setInstallPath(answer.getInstallPath());
|
||||
updateBuilder.setSize(answer.getTemplateSize());
|
||||
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
|
||||
if (!VMTemplateStorageResourceAssoc.ERROR_DOWNLOAD_STATES.contains(answer.getDownloadStatus())) {
|
||||
updateBuilder.setSize(answer.getTemplateSize());
|
||||
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
|
||||
}
|
||||
_volumeStoreDao.update(volStoreVO.getId(), updateBuilder);
|
||||
// update size in volume table
|
||||
VolumeVO volUpdater = volumeDao.createForUpdate();
|
||||
volUpdater.setSize(answer.getTemplateSize());
|
||||
volumeDao.update(obj.getId(), volUpdater);
|
||||
if (!VMTemplateStorageResourceAssoc.ERROR_DOWNLOAD_STATES.contains(answer.getDownloadStatus())) {
|
||||
VolumeVO volUpdater = volumeDao.createForUpdate();
|
||||
volUpdater.setSize(answer.getTemplateSize());
|
||||
volumeDao.update(obj.getId(), volUpdater);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncCompletionCallback<CreateCmdResult> caller = context.getParentCallback();
|
||||
|
||||
if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR ||
|
||||
answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) {
|
||||
if (VMTemplateStorageResourceAssoc.ERROR_DOWNLOAD_STATES.contains(answer.getDownloadStatus())) {
|
||||
CreateCmdResult result = new CreateCmdResult(null, null);
|
||||
result.setSuccess(false);
|
||||
result.setResult(answer.getErrorString());
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ public class CreateExtensionCmd extends BaseCmd {
|
|||
description = "Details in key/value pairs using format details[i].keyname=keyvalue. Example: details[0].endpoint.url=urlvalue")
|
||||
protected Map details;
|
||||
|
||||
@Parameter(name = ApiConstants.RESERVED_RESOURCE_DETAILS, type = CommandType.STRING,
|
||||
description = "Resource detail names as comma separated string that should be reserved and not visible " +
|
||||
"to end users",
|
||||
since = "4.22.1")
|
||||
protected String reservedResourceDetails;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -115,6 +121,10 @@ public class CreateExtensionCmd extends BaseCmd {
|
|||
return convertDetailsToMap(details);
|
||||
}
|
||||
|
||||
public String getReservedResourceDetails() {
|
||||
return reservedResourceDetails;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -78,6 +78,12 @@ public class UpdateExtensionCmd extends BaseCmd {
|
|||
"if false or not set, no action)")
|
||||
private Boolean cleanupDetails;
|
||||
|
||||
@Parameter(name = ApiConstants.RESERVED_RESOURCE_DETAILS, type = CommandType.STRING,
|
||||
description = "Resource detail names as comma separated string that should be reserved and not visible " +
|
||||
"to end users",
|
||||
since = "4.22.1")
|
||||
protected String reservedResourceDetails;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -106,6 +112,10 @@ public class UpdateExtensionCmd extends BaseCmd {
|
|||
return cleanupDetails;
|
||||
}
|
||||
|
||||
public String getReservedResourceDetails() {
|
||||
return reservedResourceDetails;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -216,6 +216,11 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
@Inject
|
||||
AccountService accountService;
|
||||
|
||||
// Map of in-built extension names and their reserved resource details that shouldn't be accessible to end-users
|
||||
protected static final Map<String, List<String>> INBUILT_RESERVED_RESOURCE_DETAILS = Map.of(
|
||||
"proxmox", List.of("proxmox_vmid")
|
||||
);
|
||||
|
||||
private ScheduledExecutorService extensionPathStateCheckExecutor;
|
||||
|
||||
protected String getDefaultExtensionRelativePath(String name) {
|
||||
|
|
@ -563,6 +568,25 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
updateExtensionPathReady(extension, true);
|
||||
}
|
||||
|
||||
protected void addInbuiltExtensionReservedResourceDetails(long extensionId, List<String> reservedResourceDetails) {
|
||||
ExtensionVO vo = extensionDao.findById(extensionId);
|
||||
if (vo == null || vo.isUserDefined()) {
|
||||
return;
|
||||
}
|
||||
String lowerName = StringUtils.defaultString(vo.getName()).toLowerCase();
|
||||
Optional<Map.Entry<String, List<String>>> match = INBUILT_RESERVED_RESOURCE_DETAILS.entrySet().stream()
|
||||
.filter(e -> lowerName.contains(e.getKey().toLowerCase()))
|
||||
.findFirst();
|
||||
if (match.isPresent()) {
|
||||
Set<String> existing = new HashSet<>(reservedResourceDetails);
|
||||
for (String detailKey : match.get().getValue()) {
|
||||
if (existing.add(detailKey)) {
|
||||
reservedResourceDetails.add(detailKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtensionsPath() {
|
||||
return externalProvisioner.getExtensionsPath();
|
||||
|
|
@ -577,6 +601,7 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
String relativePath = cmd.getPath();
|
||||
final Boolean orchestratorRequiresPrepareVm = cmd.isOrchestratorRequiresPrepareVm();
|
||||
final String stateStr = cmd.getState();
|
||||
final String reservedResourceDetails = cmd.getReservedResourceDetails();
|
||||
ExtensionVO extensionByName = extensionDao.findByName(name);
|
||||
if (extensionByName != null) {
|
||||
throw new CloudRuntimeException("Extension by name already exists");
|
||||
|
|
@ -624,6 +649,10 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM, String.valueOf(orchestratorRequiresPrepareVm),
|
||||
false));
|
||||
}
|
||||
if (StringUtils.isNotBlank(reservedResourceDetails)) {
|
||||
detailsVOList.add(new ExtensionDetailsVO(extension.getId(),
|
||||
ApiConstants.RESERVED_RESOURCE_DETAILS, reservedResourceDetails, false));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(detailsVOList)) {
|
||||
extensionDetailsDao.saveDetails(detailsVOList);
|
||||
}
|
||||
|
|
@ -704,6 +733,7 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
final String stateStr = cmd.getState();
|
||||
final Map<String, String> details = cmd.getDetails();
|
||||
final Boolean cleanupDetails = cmd.isCleanupDetails();
|
||||
final String reservedResourceDetails = cmd.getReservedResourceDetails();
|
||||
final ExtensionVO extensionVO = extensionDao.findById(id);
|
||||
if (extensionVO == null) {
|
||||
throw new InvalidParameterValueException("Failed to find the extension");
|
||||
|
|
@ -732,7 +762,8 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
throw new CloudRuntimeException(String.format("Failed to updated the extension: %s",
|
||||
extensionVO.getName()));
|
||||
}
|
||||
updateExtensionsDetails(cleanupDetails, details, orchestratorRequiresPrepareVm, id);
|
||||
updateExtensionsDetails(cleanupDetails, details, orchestratorRequiresPrepareVm, reservedResourceDetails,
|
||||
id);
|
||||
return extensionVO;
|
||||
});
|
||||
if (StringUtils.isNotBlank(stateStr)) {
|
||||
|
|
@ -748,9 +779,11 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
return result;
|
||||
}
|
||||
|
||||
protected void updateExtensionsDetails(Boolean cleanupDetails, Map<String, String> details, Boolean orchestratorRequiresPrepareVm, long id) {
|
||||
protected void updateExtensionsDetails(Boolean cleanupDetails, Map<String, String> details,
|
||||
Boolean orchestratorRequiresPrepareVm, String reservedResourceDetails, long id) {
|
||||
final boolean needToUpdateAllDetails = Boolean.TRUE.equals(cleanupDetails) || MapUtils.isNotEmpty(details);
|
||||
if (!needToUpdateAllDetails && orchestratorRequiresPrepareVm == null) {
|
||||
if (!needToUpdateAllDetails && orchestratorRequiresPrepareVm == null &&
|
||||
StringUtils.isBlank(reservedResourceDetails)) {
|
||||
return;
|
||||
}
|
||||
if (needToUpdateAllDetails) {
|
||||
|
|
@ -761,6 +794,9 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
hiddenDetails.put(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM,
|
||||
String.valueOf(orchestratorRequiresPrepareVm));
|
||||
}
|
||||
if (StringUtils.isNotBlank(reservedResourceDetails)) {
|
||||
hiddenDetails.put(ApiConstants.RESERVED_RESOURCE_DETAILS, reservedResourceDetails);
|
||||
}
|
||||
if (MapUtils.isNotEmpty(hiddenDetails)) {
|
||||
hiddenDetails.forEach((key, value) -> detailsVOList.add(
|
||||
new ExtensionDetailsVO(id, key, value, false)));
|
||||
|
|
@ -775,15 +811,29 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
extensionDetailsDao.removeDetails(id);
|
||||
}
|
||||
} else {
|
||||
ExtensionDetailsVO detailsVO = extensionDetailsDao.findDetail(id,
|
||||
ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM);
|
||||
if (detailsVO == null) {
|
||||
extensionDetailsDao.persist(new ExtensionDetailsVO(id,
|
||||
ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM,
|
||||
String.valueOf(orchestratorRequiresPrepareVm), false));
|
||||
} else if (Boolean.parseBoolean(detailsVO.getValue()) != orchestratorRequiresPrepareVm) {
|
||||
detailsVO.setValue(String.valueOf(orchestratorRequiresPrepareVm));
|
||||
extensionDetailsDao.update(detailsVO.getId(), detailsVO);
|
||||
if (orchestratorRequiresPrepareVm != null) {
|
||||
ExtensionDetailsVO detailsVO = extensionDetailsDao.findDetail(id,
|
||||
ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM);
|
||||
if (detailsVO == null) {
|
||||
extensionDetailsDao.persist(new ExtensionDetailsVO(id,
|
||||
ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM,
|
||||
String.valueOf(orchestratorRequiresPrepareVm), false));
|
||||
} else if (Boolean.parseBoolean(detailsVO.getValue()) != orchestratorRequiresPrepareVm) {
|
||||
detailsVO.setValue(String.valueOf(orchestratorRequiresPrepareVm));
|
||||
extensionDetailsDao.update(detailsVO.getId(), detailsVO);
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotBlank(reservedResourceDetails)) {
|
||||
ExtensionDetailsVO detailsVO = extensionDetailsDao.findDetail(id,
|
||||
ApiConstants.RESERVED_RESOURCE_DETAILS);
|
||||
if (detailsVO == null) {
|
||||
extensionDetailsDao.persist(new ExtensionDetailsVO(id,
|
||||
ApiConstants.RESERVED_RESOURCE_DETAILS,
|
||||
reservedResourceDetails, false));
|
||||
} else if (!reservedResourceDetails.equals(detailsVO.getValue())) {
|
||||
detailsVO.setValue(reservedResourceDetails);
|
||||
extensionDetailsDao.update(detailsVO.getId(), detailsVO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -961,12 +1011,16 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
hiddenDetails = extensionDetails.second();
|
||||
} else {
|
||||
hiddenDetails = extensionDetailsDao.listDetailsKeyPairs(extension.getId(),
|
||||
List.of(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM));
|
||||
List.of(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM,
|
||||
ApiConstants.RESERVED_RESOURCE_DETAILS));
|
||||
}
|
||||
if (hiddenDetails.containsKey(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM)) {
|
||||
response.setOrchestratorRequiresPrepareVm(Boolean.parseBoolean(
|
||||
hiddenDetails.get(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM)));
|
||||
}
|
||||
if (hiddenDetails.containsKey(ApiConstants.RESERVED_RESOURCE_DETAILS)) {
|
||||
response.setReservedResourceDetails(hiddenDetails.get(ApiConstants.RESERVED_RESOURCE_DETAILS));
|
||||
}
|
||||
response.setObjectName(Extension.class.getSimpleName().toLowerCase());
|
||||
return response;
|
||||
}
|
||||
|
|
@ -1605,6 +1659,24 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
|
|||
return extensionDao.findById(extensionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExtensionReservedResourceDetails(long extensionId) {
|
||||
ExtensionDetailsVO detailsVO = extensionDetailsDao.findDetail(extensionId,
|
||||
ApiConstants.RESERVED_RESOURCE_DETAILS);
|
||||
if (detailsVO == null || !StringUtils.isNotBlank(detailsVO.getValue())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> reservedDetails = new ArrayList<>();
|
||||
String[] parts = detailsVO.getValue().split(",");
|
||||
for (String part : parts) {
|
||||
if (StringUtils.isNotBlank(part)) {
|
||||
reservedDetails.add(part.trim());
|
||||
}
|
||||
}
|
||||
addInbuiltExtensionReservedResourceDetails(extensionId, reservedDetails);
|
||||
return reservedDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
long pathStateCheckInterval = PathStateCheckInterval.value();
|
||||
|
|
|
|||
|
|
@ -94,4 +94,18 @@ public class CreateExtensionCmdTest {
|
|||
setField(cmd, "details", details);
|
||||
assertTrue(MapUtils.isNotEmpty(cmd.getDetails()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReservedResourceDetailsReturnsValueWhenSet() {
|
||||
setField(cmd, "reservedResourceDetails", "detail1,detail2,detail3");
|
||||
String result = cmd.getReservedResourceDetails();
|
||||
assertEquals("detail1,detail2,detail3", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReservedResourceDetailsReturnsNullWhenNotSet() {
|
||||
setField(cmd, "reservedResourceDetails", null);
|
||||
String result = cmd.getReservedResourceDetails();
|
||||
assertNull(result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import static org.mockito.Mockito.doNothing;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.setField;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -134,6 +135,20 @@ public class UpdateExtensionCmdTest {
|
|||
assertTrue(cmd.isCleanupDetails());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReservedResourceDetailsReturnsValueWhenSet() {
|
||||
setField(cmd, "reservedResourceDetails", "detail1,detail2,detail3");
|
||||
String result = cmd.getReservedResourceDetails();
|
||||
assertEquals("detail1,detail2,detail3", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReservedResourceDetailsReturnsNullWhenNotSet() {
|
||||
setField(cmd, "reservedResourceDetails", null);
|
||||
String result = cmd.getReservedResourceDetails();
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeSetsExtensionResponseWhenManagerSucceeds() {
|
||||
Extension extension = mock(Extension.class);
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ import static org.junit.Assert.assertNotNull;
|
|||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyBoolean;
|
||||
import static org.mockito.Mockito.anyLong;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
|
|
@ -40,6 +42,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import java.io.File;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
|
@ -49,8 +52,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.user.AccountService;
|
||||
import org.apache.cloudstack.acl.Role;
|
||||
import org.apache.cloudstack.acl.RoleService;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
|
|
@ -85,9 +86,11 @@ import org.apache.cloudstack.framework.extensions.dao.ExtensionResourceMapDao;
|
|||
import org.apache.cloudstack.framework.extensions.dao.ExtensionResourceMapDetailsDao;
|
||||
import org.apache.cloudstack.framework.extensions.vo.ExtensionCustomActionDetailsVO;
|
||||
import org.apache.cloudstack.framework.extensions.vo.ExtensionCustomActionVO;
|
||||
import org.apache.cloudstack.framework.extensions.vo.ExtensionDetailsVO;
|
||||
import org.apache.cloudstack.framework.extensions.vo.ExtensionResourceMapVO;
|
||||
import org.apache.cloudstack.framework.extensions.vo.ExtensionVO;
|
||||
import org.apache.cloudstack.utils.identity.ManagementServerNode;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -113,6 +116,7 @@ import com.cloud.dc.dao.ClusterDao;
|
|||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
|
|
@ -122,6 +126,7 @@ import com.cloud.org.Cluster;
|
|||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.UuidUtils;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
|
|
@ -664,6 +669,8 @@ public class ExtensionsManagerImplTest {
|
|||
when(cmd.getPath()).thenReturn(null);
|
||||
when(cmd.isOrchestratorRequiresPrepareVm()).thenReturn(null);
|
||||
when(cmd.getState()).thenReturn(null);
|
||||
String reservedResourceDetails = "abc,xyz";
|
||||
when(cmd.getReservedResourceDetails()).thenReturn(reservedResourceDetails);
|
||||
when(extensionDao.findByName("ext1")).thenReturn(null);
|
||||
when(extensionDao.persist(any())).thenAnswer(inv -> {
|
||||
ExtensionVO extensionVO = inv.getArgument(0);
|
||||
|
|
@ -671,11 +678,20 @@ public class ExtensionsManagerImplTest {
|
|||
return extensionVO;
|
||||
});
|
||||
when(managementServerHostDao.listBy(any())).thenReturn(Collections.emptyList());
|
||||
|
||||
List<ExtensionDetailsVO> detailsList = new ArrayList<>();
|
||||
doAnswer(inv -> {
|
||||
List<ExtensionDetailsVO> detailsVO = inv.getArgument(0);
|
||||
detailsList.addAll(detailsVO);
|
||||
return null;
|
||||
}).when(extensionDetailsDao).saveDetails(anyList());
|
||||
Extension ext = extensionsManager.createExtension(cmd);
|
||||
|
||||
assertEquals("ext1", ext.getName());
|
||||
verify(extensionDao).persist(any());
|
||||
assertTrue(CollectionUtils.isNotEmpty(detailsList));
|
||||
assertTrue(detailsList.stream()
|
||||
.anyMatch(detail -> ApiConstants.RESERVED_RESOURCE_DETAILS.equals(detail.getName())
|
||||
&& reservedResourceDetails.equals(detail.getValue())));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -938,14 +954,32 @@ public class ExtensionsManagerImplTest {
|
|||
public void updateExtensionsDetails_SavesDetails_WhenDetailsProvided() {
|
||||
long extensionId = 10L;
|
||||
Map<String, String> details = Map.of("foo", "bar", "baz", "qux");
|
||||
extensionsManager.updateExtensionsDetails(false, details, null, extensionId);
|
||||
extensionsManager.updateExtensionsDetails(false, details, null, null, extensionId);
|
||||
verify(extensionDetailsDao).saveDetails(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateExtensionsDetails_PersistReservedDetail_WhenProvided() {
|
||||
long extensionId = 10L;
|
||||
when(extensionDetailsDao.persist(any())).thenReturn(mock(ExtensionDetailsVO.class));
|
||||
extensionsManager.updateExtensionsDetails(false, null, null, "abc,xyz", extensionId);
|
||||
verify(extensionDetailsDao).persist(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateExtensionsDetails_UpdateReservedDetail_WhenProvided() {
|
||||
long extensionId = 10L;
|
||||
when(extensionDetailsDao.findDetail(anyLong(), eq(ApiConstants.RESERVED_RESOURCE_DETAILS)))
|
||||
.thenReturn(mock(ExtensionDetailsVO.class));
|
||||
when(extensionDetailsDao.update(anyLong(), any())).thenReturn(true);
|
||||
extensionsManager.updateExtensionsDetails(false, null, null, "abc,xyz", extensionId);
|
||||
verify(extensionDetailsDao).update(anyLong(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateExtensionsDetails_DoesNothing_WhenDetailsAndCleanupAreNull() {
|
||||
long extensionId = 11L;
|
||||
extensionsManager.updateExtensionsDetails(null, null, null, extensionId);
|
||||
extensionsManager.updateExtensionsDetails(null, null, null, null, extensionId);
|
||||
verify(extensionDetailsDao, never()).removeDetails(anyLong());
|
||||
verify(extensionDetailsDao, never()).saveDetails(any());
|
||||
}
|
||||
|
|
@ -953,7 +987,7 @@ public class ExtensionsManagerImplTest {
|
|||
@Test
|
||||
public void updateExtensionsDetails_RemovesDetailsOnly_WhenCleanupIsTrue() {
|
||||
long extensionId = 12L;
|
||||
extensionsManager.updateExtensionsDetails(true, null, null, extensionId);
|
||||
extensionsManager.updateExtensionsDetails(true, null, null, null, extensionId);
|
||||
verify(extensionDetailsDao).removeDetails(extensionId);
|
||||
verify(extensionDetailsDao, never()).saveDetails(any());
|
||||
}
|
||||
|
|
@ -961,7 +995,7 @@ public class ExtensionsManagerImplTest {
|
|||
@Test
|
||||
public void updateExtensionsDetails_PersistsOrchestratorFlag_WhenFlagIsNotNull() {
|
||||
long extensionId = 13L;
|
||||
extensionsManager.updateExtensionsDetails(false, null, true, extensionId);
|
||||
extensionsManager.updateExtensionsDetails(false, null, true, null, extensionId);
|
||||
verify(extensionDetailsDao).persist(any());
|
||||
}
|
||||
|
||||
|
|
@ -970,7 +1004,7 @@ public class ExtensionsManagerImplTest {
|
|||
long extensionId = 14L;
|
||||
Map<String, String> details = Map.of("foo", "bar");
|
||||
doThrow(CloudRuntimeException.class).when(extensionDetailsDao).saveDetails(any());
|
||||
extensionsManager.updateExtensionsDetails(false, details, null, extensionId);
|
||||
extensionsManager.updateExtensionsDetails(false, details, null, null, extensionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1161,7 +1195,8 @@ public class ExtensionsManagerImplTest {
|
|||
when(externalProvisioner.getExtensionPath("entry2.sh")).thenReturn("/some/path/entry2.sh");
|
||||
|
||||
Map<String, String> hiddenDetails = Map.of(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM, "false");
|
||||
when(extensionDetailsDao.listDetailsKeyPairs(2L, List.of(ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM)))
|
||||
when(extensionDetailsDao.listDetailsKeyPairs(2L, List.of(
|
||||
ApiConstants.ORCHESTRATOR_REQUIRES_PREPARE_VM, ApiConstants.RESERVED_RESOURCE_DETAILS)))
|
||||
.thenReturn(hiddenDetails);
|
||||
|
||||
EnumSet<ApiConstants.ExtensionDetails> viewDetails = EnumSet.noneOf(ApiConstants.ExtensionDetails.class);
|
||||
|
|
@ -2069,4 +2104,118 @@ public class ExtensionsManagerImplTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExtensionReservedResourceDetailsReturnsEmptyListWhenDetailsNotFound() {
|
||||
long extensionId = 1L;
|
||||
when(extensionDetailsDao.findDetail(extensionId, ApiConstants.RESERVED_RESOURCE_DETAILS)).thenReturn(null);
|
||||
|
||||
List<String> result = extensionsManager.getExtensionReservedResourceDetails(extensionId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExtensionReservedResourceDetailsReturnsEmptyListWhenValueIsBlank() {
|
||||
long extensionId = 2L;
|
||||
ExtensionDetailsVO detailsVO = mock(ExtensionDetailsVO.class);
|
||||
when(detailsVO.getValue()).thenReturn(" ");
|
||||
when(extensionDetailsDao.findDetail(extensionId, ApiConstants.RESERVED_RESOURCE_DETAILS)).thenReturn(detailsVO);
|
||||
|
||||
List<String> result = extensionsManager.getExtensionReservedResourceDetails(extensionId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExtensionReservedResourceDetailsReturnsListOfTrimmedDetails() {
|
||||
long extensionId = 3L;
|
||||
ExtensionDetailsVO detailsVO = mock(ExtensionDetailsVO.class);
|
||||
when(detailsVO.getValue()).thenReturn(" detail1 , detail2,detail3 ");
|
||||
when(extensionDetailsDao.findDetail(extensionId, ApiConstants.RESERVED_RESOURCE_DETAILS)).thenReturn(detailsVO);
|
||||
|
||||
List<String> result = extensionsManager.getExtensionReservedResourceDetails(extensionId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(3, result.size());
|
||||
assertEquals("detail1", result.get(0));
|
||||
assertEquals("detail2", result.get(1));
|
||||
assertEquals("detail3", result.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExtensionReservedResourceDetailsHandlesEmptyPartsGracefully() {
|
||||
long extensionId = 4L;
|
||||
ExtensionDetailsVO detailsVO = mock(ExtensionDetailsVO.class);
|
||||
when(detailsVO.getValue()).thenReturn("detail1,,detail2, ,detail3");
|
||||
when(extensionDetailsDao.findDetail(extensionId, ApiConstants.RESERVED_RESOURCE_DETAILS)).thenReturn(detailsVO);
|
||||
|
||||
List<String> result = extensionsManager.getExtensionReservedResourceDetails(extensionId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(3, result.size());
|
||||
assertEquals("detail1", result.get(0));
|
||||
assertEquals("detail2", result.get(1));
|
||||
assertEquals("detail3", result.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExtensionReservedResourceDetailsReturnsEmptyListWhenSplitResultsInNoParts() {
|
||||
long extensionId = 5L;
|
||||
ExtensionDetailsVO detailsVO = mock(ExtensionDetailsVO.class);
|
||||
when(detailsVO.getValue()).thenReturn(",");
|
||||
when(extensionDetailsDao.findDetail(extensionId, ApiConstants.RESERVED_RESOURCE_DETAILS)).thenReturn(detailsVO);
|
||||
|
||||
List<String> result = extensionsManager.getExtensionReservedResourceDetails(extensionId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addInbuiltExtensionReservedResourceDetailsDoesNothingWhenExtensionNotFound() {
|
||||
when(extensionDao.findById(1L)).thenReturn(null);
|
||||
List<String> reservedResourceDetails = new ArrayList<>();
|
||||
extensionsManager.addInbuiltExtensionReservedResourceDetails(1L, reservedResourceDetails);
|
||||
assertTrue(reservedResourceDetails.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addInbuiltExtensionReservedResourceDetailsDoesNothingForUserDefinedExtension() {
|
||||
ExtensionVO extension = mock(ExtensionVO.class);
|
||||
when(extension.isUserDefined()).thenReturn(true);
|
||||
when(extensionDao.findById(2L)).thenReturn(extension);
|
||||
List<String> reservedResourceDetails = new ArrayList<>();
|
||||
reservedResourceDetails.add("existing-detail");
|
||||
extensionsManager.addInbuiltExtensionReservedResourceDetails(2L, reservedResourceDetails);
|
||||
assertEquals(1, reservedResourceDetails.size());
|
||||
assertTrue(reservedResourceDetails.contains("existing-detail"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addInbuiltExtensionReservedResourceDetailsDoesNothingWhenNoMatchFound() {
|
||||
ExtensionVO extension = mock(ExtensionVO.class);
|
||||
when(extension.isUserDefined()).thenReturn(false);
|
||||
when(extension.getName()).thenReturn("no-such-inbuilt-key-expected");
|
||||
when(extensionDao.findById(3L)).thenReturn(extension);
|
||||
List<String> reservedResourceDetails = new ArrayList<>();
|
||||
extensionsManager.addInbuiltExtensionReservedResourceDetails(3L, reservedResourceDetails);
|
||||
assertTrue(reservedResourceDetails.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addInbuiltExtensionReservedResourceDetailsAddedDetails() {
|
||||
ExtensionVO extension = mock(ExtensionVO.class);
|
||||
when(extension.isUserDefined()).thenReturn(false);
|
||||
Map.Entry<String, List<String>> entry =
|
||||
ExtensionsManagerImpl.INBUILT_RESERVED_RESOURCE_DETAILS.entrySet().iterator().next();
|
||||
when(extension.getName()).thenReturn(entry.getKey());
|
||||
when(extensionDao.findById(3L)).thenReturn(extension);
|
||||
List<String> reservedResourceDetails = new ArrayList<>();
|
||||
extensionsManager.addInbuiltExtensionReservedResourceDetails(3L, reservedResourceDetails);
|
||||
assertFalse(reservedResourceDetails.isEmpty());
|
||||
assertEquals(reservedResourceDetails.size(), entry.getValue().size());
|
||||
assertTrue(reservedResourceDetails.containsAll(entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,6 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem
|
|||
}
|
||||
}
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
return template;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
|
|
@ -98,6 +100,51 @@ public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
|
|||
return String.format("%s-%s", ACS_PREFIX, account.getUuid());
|
||||
}
|
||||
|
||||
private void updateCannedPolicy(long storeId, Account account, String excludeBucket) {
|
||||
List<BucketVO> buckets = _bucketDao.listByObjectStoreIdAndAccountId(storeId, account.getId());
|
||||
|
||||
String resources = buckets.stream()
|
||||
.map(BucketVO::getName)
|
||||
.filter(name -> !Objects.equals(name, excludeBucket))
|
||||
.map(name -> "\"arn:aws:s3:::" + name + "/*\"")
|
||||
.collect(Collectors.joining(",\n"));
|
||||
String policy;
|
||||
if (resources.isEmpty()) {
|
||||
// Resource cannot be empty in a canned Policy so deny access to all resources if the user has no buckets
|
||||
policy = " {\n" +
|
||||
" \"Statement\": [\n" +
|
||||
" {\n" +
|
||||
" \"Action\": \"s3:*\",\n" +
|
||||
" \"Effect\": \"Deny\",\n" +
|
||||
" \"Resource\": [\"arn:aws:s3:::*\", \"arn:aws:s3:::*/*\"]\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"Version\": \"2012-10-17\"\n" +
|
||||
" }";
|
||||
} else {
|
||||
policy = " {\n" +
|
||||
" \"Statement\": [\n" +
|
||||
" {\n" +
|
||||
" \"Action\": \"s3:*\",\n" +
|
||||
" \"Effect\": \"Allow\",\n" +
|
||||
" \"Resource\": [" + resources + "]\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"Version\": \"2012-10-17\"\n" +
|
||||
" }";
|
||||
}
|
||||
|
||||
MinioAdminClient minioAdminClient = getMinIOAdminClient(storeId);
|
||||
String policyName = getUserOrAccessKeyForAccount(account) + "-policy";
|
||||
String userName = getUserOrAccessKeyForAccount(account);
|
||||
try {
|
||||
minioAdminClient.addCannedPolicy(policyName, policy);
|
||||
minioAdminClient.setPolicy(userName, false, policyName);
|
||||
} catch (NoSuchAlgorithmException | IOException | InvalidKeyException e) {
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bucket createBucket(Bucket bucket, boolean objectLock) {
|
||||
//ToDo Client pool mgmt
|
||||
|
|
@ -125,33 +172,8 @@ public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
|
|||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
|
||||
List<BucketVO> buckets = _bucketDao.listByObjectStoreIdAndAccountId(storeId, accountId);
|
||||
StringBuilder resources_builder = new StringBuilder();
|
||||
for(BucketVO exitingBucket : buckets) {
|
||||
resources_builder.append("\"arn:aws:s3:::"+exitingBucket.getName()+"/*\",\n");
|
||||
}
|
||||
resources_builder.append("\"arn:aws:s3:::"+bucketName+"/*\"\n");
|
||||
updateCannedPolicy(storeId, account,null);
|
||||
|
||||
String policy = " {\n" +
|
||||
" \"Statement\": [\n" +
|
||||
" {\n" +
|
||||
" \"Action\": \"s3:*\",\n" +
|
||||
" \"Effect\": \"Allow\",\n" +
|
||||
" \"Principal\": \"*\",\n" +
|
||||
" \"Resource\": ["+resources_builder+"]" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"Version\": \"2012-10-17\"\n" +
|
||||
" }";
|
||||
MinioAdminClient minioAdminClient = getMinIOAdminClient(storeId);
|
||||
String policyName = getUserOrAccessKeyForAccount(account) + "-policy";
|
||||
String userName = getUserOrAccessKeyForAccount(account);
|
||||
try {
|
||||
minioAdminClient.addCannedPolicy(policyName, policy);
|
||||
minioAdminClient.setPolicy(userName, false, policyName);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
String accessKey = _accountDetailsDao.findDetail(accountId, MINIO_ACCESS_KEY).getValue();
|
||||
String secretKey = _accountDetailsDao.findDetail(accountId, MINIO_SECRET_KEY).getValue();
|
||||
ObjectStoreVO store = _storeDao.findById(storeId);
|
||||
|
|
@ -183,6 +205,8 @@ public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
|
|||
@Override
|
||||
public boolean deleteBucket(BucketTO bucket, long storeId) {
|
||||
String bucketName = bucket.getName();
|
||||
long accountId = bucket.getAccountId();
|
||||
Account account = _accountDao.findById(accountId);
|
||||
MinioClient minioClient = getMinIOClient(storeId);
|
||||
try {
|
||||
if(!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
|
||||
|
|
@ -197,6 +221,9 @@ public class MinIOObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
|
|||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
|
||||
updateCannedPolicy(storeId, account, bucketName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,10 +129,15 @@ public class MinIOObjectStoreDriverImplTest {
|
|||
@Test
|
||||
public void testDeleteBucket() throws Exception {
|
||||
String bucketName = "test-bucket";
|
||||
BucketTO bucket = new BucketTO(bucketName);
|
||||
BucketVO bucketVO = new BucketVO(1L, 1L, 1L, bucketName, 1, false, false, false, null);
|
||||
BucketTO bucket = new BucketTO(bucketVO);
|
||||
when(accountDao.findById(1L)).thenReturn(account);
|
||||
when(account.getUuid()).thenReturn(UUID.randomUUID().toString());
|
||||
when(bucketDao.listByObjectStoreIdAndAccountId(anyLong(), anyLong())).thenReturn(new ArrayList<BucketVO>());
|
||||
doReturn(minioClient).when(minioObjectStoreDriverImpl).getMinIOClient(anyLong());
|
||||
when(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())).thenReturn(true);
|
||||
doNothing().when(minioClient).removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
|
||||
doReturn(minioAdminClient).when(minioObjectStoreDriverImpl).getMinIOAdminClient(anyLong());
|
||||
boolean success = minioObjectStoreDriverImpl.deleteBucket(bucket, 1L);
|
||||
assertTrue(success);
|
||||
verify(minioClient, times(1)).bucketExists(any());
|
||||
|
|
|
|||
|
|
@ -2289,6 +2289,10 @@ public class ApiDBUtils {
|
|||
return s_accountService.isAdmin(account.getId());
|
||||
}
|
||||
|
||||
public static Account getSystemAccount() {
|
||||
return s_accountService.getSystemAccount();
|
||||
}
|
||||
|
||||
public static List<ResourceTagJoinVO> listResourceTagViewByResourceUUID(String resourceUUID, ResourceObjectType resourceType) {
|
||||
return s_tagJoinDao.listBy(resourceUUID, resourceType);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,14 +17,13 @@
|
|||
package com.cloud.api.query.dao;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
|
@ -34,8 +33,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.gpu.dao.VgpuProfileDao;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
|
|
@ -49,6 +46,7 @@ import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
|||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.api.response.VnfNicResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.extension.ExtensionHelper;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.cloudstack.vm.lease.VMLeaseManager;
|
||||
|
|
@ -61,11 +59,13 @@ import com.cloud.api.ApiDBUtils;
|
|||
import com.cloud.api.ApiResponseHelper;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.gpu.GPU;
|
||||
import com.cloud.gpu.dao.VgpuProfileDao;
|
||||
import com.cloud.host.ControlState;
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.service.ServiceOfferingDetailsVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.GuestOS;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
|
|
@ -94,7 +94,6 @@ import com.cloud.vm.VirtualMachine.State;
|
|||
import com.cloud.vm.VmStats;
|
||||
import com.cloud.vm.dao.NicExtraDhcpOptionDao;
|
||||
import com.cloud.vm.dao.NicSecondaryIpVO;
|
||||
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
|
||||
@Component
|
||||
|
|
@ -128,6 +127,8 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
private VgpuProfileDao vgpuProfileDao;
|
||||
@Inject
|
||||
VMTemplateDao vmTemplateDao;
|
||||
@Inject
|
||||
ExtensionHelper extensionHelper;
|
||||
|
||||
private final SearchBuilder<UserVmJoinVO> VmDetailSearch;
|
||||
private final SearchBuilder<UserVmJoinVO> activeVmByIsoSearch;
|
||||
|
|
@ -460,7 +461,16 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
|
||||
// Remove deny listed settings if user is not admin
|
||||
if (caller.getType() != Account.Type.ADMIN) {
|
||||
String[] userVmSettingsToHide = QueryService.UserVMDeniedDetails.value().split(",");
|
||||
List<String> userVmSettingsToHide = new ArrayList<>();
|
||||
String[] parts = QueryService.UserVMDeniedDetails.value().split(",");
|
||||
if (parts.length > 0) {
|
||||
Collections.addAll(userVmSettingsToHide, parts);
|
||||
}
|
||||
if (userVm.getTemplateExtensionId() != null) {
|
||||
userVmSettingsToHide.addAll(extensionHelper.getExtensionReservedResourceDetails(
|
||||
userVm.getTemplateExtensionId()));
|
||||
}
|
||||
|
||||
for (String key : userVmSettingsToHide) {
|
||||
resourceDetails.remove(key.trim());
|
||||
}
|
||||
|
|
@ -520,7 +530,6 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
return userVmResponse;
|
||||
}
|
||||
|
||||
|
||||
private long computeLeaseDurationFromExpiryDate(Date created, Date leaseExpiryDate) {
|
||||
LocalDate createdDate = created.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
LocalDate expiryDate = leaseExpiryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
|
|
@ -556,7 +565,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
|
||||
/**
|
||||
* The resulting Response attempts to be in line with what is returned from
|
||||
* @see com.cloud.api.ApiResponseHelper#createNicResponse(Nic)
|
||||
* @see com.cloud.api.ApiResponseHelper#{code}createNicResponse(Nic){code}
|
||||
*/
|
||||
@Override
|
||||
public UserVmResponse setUserVmResponse(ResponseView view, UserVmResponse userVmData, UserVmJoinVO uvo) {
|
||||
|
|
|
|||
|
|
@ -207,6 +207,9 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
@Column(name = "template_format")
|
||||
private Storage.ImageFormat templateFormat;
|
||||
|
||||
@Column(name = "template_extension_id")
|
||||
private Long templateExtensionId;
|
||||
|
||||
@Column(name = "password_enabled")
|
||||
private boolean passwordEnabled;
|
||||
|
||||
|
|
@ -709,6 +712,10 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
return templateFormat;
|
||||
}
|
||||
|
||||
public Long getTemplateExtensionId() {
|
||||
return templateExtensionId;
|
||||
}
|
||||
|
||||
public boolean isPasswordEnabled() {
|
||||
return passwordEnabled;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ import org.apache.cloudstack.region.PortableIpVO;
|
|||
import org.apache.cloudstack.region.Region;
|
||||
import org.apache.cloudstack.region.RegionVO;
|
||||
import org.apache.cloudstack.region.dao.RegionDao;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
|
|
@ -264,6 +265,7 @@ import com.cloud.org.Grouping;
|
|||
import com.cloud.org.Grouping.AllocationState;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingDetailsVO;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
|
|
@ -408,6 +410,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
@Inject
|
||||
ResourceLimitService _resourceLimitMgr;
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
@Inject
|
||||
ProjectManager _projectMgr;
|
||||
@Inject
|
||||
NetworkOfferingServiceMapDao _ntwkOffServiceMapDao;
|
||||
|
|
@ -646,7 +650,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
protected void populateConfigKeysAllowedOnlyForDefaultAdmin() {
|
||||
configKeysAllowedOnlyForDefaultAdmin.add(AccountManagerImpl.listOfRoleTypesAllowedForOperationsOfSameRoleType.key());
|
||||
configKeysAllowedOnlyForDefaultAdmin.add(AccountManagerImpl.allowOperationsOnUsersInSameAccount.key());
|
||||
|
||||
configKeysAllowedOnlyForDefaultAdmin.add(VirtualMachineManager.SystemVmEnableUserData.key());
|
||||
configKeysAllowedOnlyForDefaultAdmin.add(ConsoleProxyManager.ConsoleProxyVmUserData.key());
|
||||
configKeysAllowedOnlyForDefaultAdmin.add(SecondaryStorageVmManager.SecondaryStorageVmUserData.key());
|
||||
|
|
@ -995,7 +998,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
String hypervisors = _configDao.getValue(hypervisorListConfigName);
|
||||
if (Arrays.asList(hypervisors.split(",")).contains(previousValue)) {
|
||||
hypervisors = hypervisors.replace(previousValue, newValue);
|
||||
logger.info("Updating the hypervisor list configuration '{}}' to match the new custom hypervisor display name",
|
||||
logger.info("Updating the hypervisor list configuration '{}' to match the new custom hypervisor display name",
|
||||
hypervisorListConfigName);
|
||||
_configDao.update(hypervisorListConfigName, hypervisors);
|
||||
}
|
||||
|
|
@ -5043,22 +5046,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks");
|
||||
}
|
||||
|
||||
if (forVirtualNetwork) {
|
||||
if (vlanOwner != null) {
|
||||
|
||||
final long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1;
|
||||
|
||||
// check resource limits
|
||||
_resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountIpRange);
|
||||
}
|
||||
}
|
||||
// Check if the IP range overlaps with the private ip
|
||||
if (ipv4) {
|
||||
checkOverlapPrivateIpRange(zoneId, startIP, endIP);
|
||||
}
|
||||
|
||||
return commitVlan(zoneId, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, forVirtualNetwork, forSystemVms, networkId, physicalNetworkId, startIPv6, endIPv6, ip6Gateway,
|
||||
ip6Cidr, domain, vlanOwner, network, sameSubnet, cmd.getProvider());
|
||||
long reservedIpAddressesAmount = 0L;
|
||||
if (forVirtualNetwork && vlanOwner != null) {
|
||||
reservedIpAddressesAmount = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1;
|
||||
}
|
||||
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(vlanOwner, ResourceType.public_ip, null, null, null, reservedIpAddressesAmount, null, reservationDao, _resourceLimitMgr)) {
|
||||
return commitVlan(zoneId, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, forVirtualNetwork, forSystemVms, networkId, physicalNetworkId, startIPv6, endIPv6, ip6Gateway,
|
||||
ip6Cidr, domain, vlanOwner, network, sameSubnet, cmd.getProvider());
|
||||
}
|
||||
}
|
||||
|
||||
private Network getNetwork(Long networkId) {
|
||||
|
|
@ -5594,7 +5595,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
ip.isSourceNat(), vlan.getVlanType().toString(), ip.getSystem(), usageHidden, ip.getClass().getName(), ip.getUuid());
|
||||
}
|
||||
// increment resource count for dedicated public ip's
|
||||
_resourceLimitMgr.incrementResourceCount(vlanOwner.getId(), ResourceType.public_ip, new Long(ips.size()));
|
||||
_resourceLimitMgr.incrementResourceCount(vlanOwner.getId(), ResourceType.public_ip, (long)ips.size());
|
||||
} else if (domain != null && !forSystemVms) {
|
||||
// This VLAN is domain-wide, so create a DomainVlanMapVO entry
|
||||
final DomainVlanMapVO domainVlanMapVO = new DomainVlanMapVO(domain.getId(), vlan.getId());
|
||||
|
|
@ -5638,7 +5639,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
String endIpv6,
|
||||
String ip6Gateway,
|
||||
String ip6Cidr,
|
||||
Boolean forSystemVms) throws ConcurrentOperationException {
|
||||
Boolean forSystemVms) throws ConcurrentOperationException, ResourceAllocationException {
|
||||
|
||||
VlanVO vlanRange = _vlanDao.findById(id);
|
||||
if (vlanRange == null) {
|
||||
|
|
@ -5658,24 +5659,49 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
}
|
||||
|
||||
AccountVlanMapVO accountMap = _accountVlanMapDao.findAccountVlanMap(null, id);
|
||||
Account account = accountMap != null ? _accountDao.findById(accountMap.getAccountId()) : null;
|
||||
|
||||
DomainVlanMapVO domainMap = _domainVlanMapDao.findDomainVlanMap(null, id);
|
||||
Long domainId = domainMap != null ? domainMap.getDomainId() : null;
|
||||
|
||||
final Boolean isRangeForSystemVM = checkIfVlanRangeIsForSystemVM(id);
|
||||
if (forSystemVms != null && isRangeForSystemVM != forSystemVms) {
|
||||
if (VlanType.DirectAttached.equals(vlanRange.getVlanType())) {
|
||||
throw new InvalidParameterValueException("forSystemVms is not available for this IP range with vlan type: " + VlanType.DirectAttached);
|
||||
}
|
||||
// Check if range has already been dedicated
|
||||
final List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(id);
|
||||
if (maps != null && !maps.isEmpty()) {
|
||||
if (account != null) {
|
||||
throw new InvalidParameterValueException("Specified Public IP range has already been dedicated to an account");
|
||||
}
|
||||
|
||||
List<DomainVlanMapVO> domainmaps = _domainVlanMapDao.listDomainVlanMapsByVlan(id);
|
||||
if (domainmaps != null && !domainmaps.isEmpty()) {
|
||||
if (domainId != null) {
|
||||
throw new InvalidParameterValueException("Specified Public IP range has already been dedicated to a domain");
|
||||
}
|
||||
}
|
||||
if (ipv4) {
|
||||
updateVlanAndIpv4Range(id, vlanRange, startIp, endIp, gateway, netmask, isRangeForSystemVM, forSystemVms);
|
||||
long existingIpAddressAmount = 0L;
|
||||
long newIpAddressAmount = 0L;
|
||||
|
||||
if (account != null) {
|
||||
// IPv4 public range is dedicated to an account (IPv6 cannot be dedicated at the moment).
|
||||
// We need to update the resource count.
|
||||
existingIpAddressAmount = _publicIpAddressDao.countIPs(vlanRange.getDataCenterId(), id, false);
|
||||
newIpAddressAmount = NetUtils.ip2Long(endIp) - NetUtils.ip2Long(startIp) + 1;
|
||||
}
|
||||
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(account, ResourceType.public_ip, null, null, null, newIpAddressAmount, existingIpAddressAmount, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
updateVlanAndIpv4Range(id, vlanRange, startIp, endIp, gateway, netmask, isRangeForSystemVM, forSystemVms);
|
||||
|
||||
if (account != null) {
|
||||
long countDiff = newIpAddressAmount - existingIpAddressAmount;
|
||||
if (countDiff > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), ResourceType.public_ip, countDiff);
|
||||
} else if (countDiff < 0) {
|
||||
_resourceLimitMgr.decrementResourceCount(account.getId(), ResourceType.public_ip, Math.abs(countDiff));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ipv6) {
|
||||
updateVlanAndIpv6Range(id, vlanRange, startIpv6, endIpv6, ip6Gateway, ip6Cidr, isRangeForSystemVM, forSystemVms);
|
||||
|
|
@ -5954,7 +5980,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
} finally {
|
||||
_vlanDao.releaseFromLockTable(vlanDbId);
|
||||
if (resourceCountToBeDecrement > 0) { //Making sure to decrement the count of only success operations above. For any reaason if disassociation fails then this number will vary from original range length.
|
||||
_resourceLimitMgr.decrementResourceCount(acctVln.get(0).getAccountId(), ResourceType.public_ip, new Long(resourceCountToBeDecrement));
|
||||
_resourceLimitMgr.decrementResourceCount(acctVln.get(0).getAccountId(), ResourceType.public_ip, (long)resourceCountToBeDecrement);
|
||||
}
|
||||
}
|
||||
} else { // !isAccountSpecific
|
||||
|
|
@ -6062,12 +6088,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
throw new InvalidParameterValueException("Public IP range can be dedicated to an account only in the zone of type " + NetworkType.Advanced);
|
||||
}
|
||||
|
||||
// Check Public IP resource limits
|
||||
if (vlanOwner != null) {
|
||||
final int accountPublicIpRange = _publicIpAddressDao.countIPs(zoneId, vlanDbId, false);
|
||||
_resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountPublicIpRange);
|
||||
}
|
||||
|
||||
// Check if any of the Public IP addresses is allocated to another
|
||||
// account
|
||||
final List<IPAddressVO> ips = _publicIpAddressDao.listByVlanId(vlanDbId);
|
||||
|
|
@ -6088,29 +6108,35 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
}
|
||||
|
||||
if (vlanOwner != null) {
|
||||
// Create an AccountVlanMapVO entry
|
||||
final AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(vlanOwner.getId(), vlan.getId());
|
||||
_accountVlanMapDao.persist(accountVlanMapVO);
|
||||
// Check Public IP resource limits
|
||||
long reservedIpAddressesAmount = vlanOwner != null ? _publicIpAddressDao.countIPs(zoneId, vlanDbId, false) : 0L;
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(vlanOwner, ResourceType.public_ip, null, null, null, reservedIpAddressesAmount, null, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
// generate usage event for dedication of every ip address in the range
|
||||
for (final IPAddressVO ip : ips) {
|
||||
final boolean usageHidden = _ipAddrMgr.isUsageHidden(ip);
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, vlanOwner.getId(), ip.getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(),
|
||||
vlan.getVlanType().toString(), ip.getSystem(), usageHidden, ip.getClass().getName(), ip.getUuid());
|
||||
if (vlanOwner != null) {
|
||||
// Create an AccountVlanMapVO entry
|
||||
final AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(vlanOwner.getId(), vlan.getId());
|
||||
_accountVlanMapDao.persist(accountVlanMapVO);
|
||||
|
||||
// generate usage event for dedication of every ip address in the range
|
||||
for (final IPAddressVO ip : ips) {
|
||||
final boolean usageHidden = _ipAddrMgr.isUsageHidden(ip);
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, vlanOwner.getId(), ip.getDataCenterId(), ip.getId(), ip.getAddress().toString(), ip.isSourceNat(),
|
||||
vlan.getVlanType().toString(), ip.getSystem(), usageHidden, ip.getClass().getName(), ip.getUuid());
|
||||
}
|
||||
} else if (domain != null) {
|
||||
// Create an DomainVlanMapVO entry
|
||||
DomainVlanMapVO domainVlanMapVO = new DomainVlanMapVO(domain.getId(), vlan.getId());
|
||||
_domainVlanMapDao.persist(domainVlanMapVO);
|
||||
}
|
||||
} else if (domain != null) {
|
||||
// Create an DomainVlanMapVO entry
|
||||
DomainVlanMapVO domainVlanMapVO = new DomainVlanMapVO(domain.getId(), vlan.getId());
|
||||
_domainVlanMapDao.persist(domainVlanMapVO);
|
||||
}
|
||||
|
||||
// increment resource count for dedicated public ip's
|
||||
if (vlanOwner != null) {
|
||||
_resourceLimitMgr.incrementResourceCount(vlanOwner.getId(), ResourceType.public_ip, new Long(ips.size()));
|
||||
}
|
||||
// increment resource count for dedicated public ip's
|
||||
if (vlanOwner != null) {
|
||||
_resourceLimitMgr.incrementResourceCount(vlanOwner.getId(), ResourceType.public_ip, (long)ips.size());
|
||||
}
|
||||
|
||||
return vlan;
|
||||
return vlan;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -6199,7 +6225,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
}
|
||||
// decrement resource count for dedicated public ip's
|
||||
_resourceLimitMgr.decrementResourceCount(acctVln.get(0).getAccountId(), ResourceType.public_ip, new Long(ips.size()));
|
||||
_resourceLimitMgr.decrementResourceCount(acctVln.get(0).getAccountId(), ResourceType.public_ip, (long)ips.size());
|
||||
success = true;
|
||||
} else if (isDomainSpecific && _domainVlanMapDao.remove(domainVlan.get(0).getId())) {
|
||||
logger.debug("Remove the vlan from domain_vlan_map successfully.");
|
||||
|
|
@ -6368,7 +6394,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
final List<Object> newCidrPair = new ArrayList<>();
|
||||
newCidrPair.add(0, getCidrAddress(cidr));
|
||||
newCidrPair.add(1, (long)getCidrSize(cidr));
|
||||
currentPodCidrSubnets.put(new Long(-1), newCidrPair);
|
||||
currentPodCidrSubnets.put(-1L, newCidrPair);
|
||||
|
||||
final DataCenterVO dcVo = _zoneDao.findById(dcId);
|
||||
final String guestNetworkCidr = dcVo.getGuestNetworkCidr();
|
||||
|
|
@ -6468,7 +6494,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
private String getPodName(final long podId) {
|
||||
return _podDao.findById(new Long(podId)).getName();
|
||||
return _podDao.findById(podId).getName();
|
||||
}
|
||||
|
||||
private boolean validZone(final String zoneName) {
|
||||
|
|
@ -6480,7 +6506,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
private String getZoneName(final long zoneId) {
|
||||
final DataCenterVO zone = _zoneDao.findById(new Long(zoneId));
|
||||
final DataCenterVO zone = _zoneDao.findById(zoneId);
|
||||
if (zone != null) {
|
||||
return zone.getName();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import java.util.UUID;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.alert.AlertService;
|
||||
|
|
@ -76,6 +77,7 @@ import org.apache.cloudstack.network.NetworkPermissionVO;
|
|||
import org.apache.cloudstack.network.RoutedIpv4Manager;
|
||||
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
|
||||
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
|
@ -335,6 +337,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
@Inject
|
||||
ResourceLimitService _resourceLimitMgr;
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
@Inject
|
||||
DomainManager _domainMgr;
|
||||
@Inject
|
||||
ProjectManager _projectMgr;
|
||||
|
|
@ -1152,15 +1156,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
if (ipDedicatedAccountId != null && !ipDedicatedAccountId.equals(account.getAccountId())) {
|
||||
throw new InvalidParameterValueException("Unable to reserve a IP because it is dedicated to another Account.");
|
||||
}
|
||||
if (ipDedicatedAccountId == null) {
|
||||
// Check that the maximum number of public IPs for the given accountId will not be exceeded
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(account, Resource.ResourceType.public_ip);
|
||||
} catch (ResourceAllocationException ex) {
|
||||
logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + account);
|
||||
throw new AccountLimitException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded.");
|
||||
}
|
||||
}
|
||||
|
||||
long reservedIpAddressesAmount = ipDedicatedAccountId == null ? 1L : 0L;
|
||||
try (CheckedReservation publicIpAddressReservation = new CheckedReservation(account, Resource.ResourceType.public_ip, reservedIpAddressesAmount, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(ipVO.getVlanId());
|
||||
ipVO.setAllocatedTime(new Date());
|
||||
ipVO.setAllocatedToAccountId(account.getAccountId());
|
||||
|
|
@ -1170,10 +1169,15 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
ipVO.setDisplay(displayIp);
|
||||
}
|
||||
ipVO = _ipAddressDao.persist(ipVO);
|
||||
if (ipDedicatedAccountId == null) {
|
||||
if (reservedIpAddressesAmount > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), Resource.ResourceType.public_ip);
|
||||
}
|
||||
return ipVO;
|
||||
|
||||
} catch (ResourceAllocationException ex) {
|
||||
logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + account);
|
||||
throw new AccountLimitException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -3209,7 +3213,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
if (displayNetwork != null && displayNetwork != network.getDisplayNetwork()) {
|
||||
// Update resource count if it needs to be updated
|
||||
NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
||||
if (_networkMgr.resourceCountNeedsUpdate(networkOffering, network.getAclType())) {
|
||||
if (_networkMgr.isResourceCountUpdateNeeded(networkOffering)) {
|
||||
_resourceLimitMgr.changeResourceCount(network.getAccountId(), Resource.ResourceType.network, displayNetwork);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,29 +42,8 @@ import javax.annotation.PostConstruct;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.configuration.ConfigurationManagerImpl;
|
||||
import com.cloud.bgp.BGPService;
|
||||
import com.cloud.dc.ASNumberVO;
|
||||
import com.cloud.dc.dao.ASNumberDao;
|
||||
import com.cloud.dc.Vlan;
|
||||
import com.cloud.network.RemoteAccessVpn;
|
||||
import com.cloud.network.Site2SiteVpnConnection;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import com.cloud.network.dao.RemoteAccessVpnDao;
|
||||
import com.cloud.network.dao.RemoteAccessVpnVO;
|
||||
import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
|
||||
import com.cloud.network.dao.Site2SiteCustomerGatewayVO;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionDao;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionVO;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.element.NetworkACLServiceProvider;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
import com.cloud.network.rules.RulesManager;
|
||||
import com.cloud.network.vpn.RemoteAccessVpnService;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.alert.AlertService;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
|
|
@ -106,12 +85,18 @@ import com.cloud.agent.manager.Commands;
|
|||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.api.query.dao.VpcOfferingJoinDao;
|
||||
import com.cloud.api.query.vo.VpcOfferingJoinVO;
|
||||
import com.cloud.bgp.BGPService;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.configuration.ConfigurationManagerImpl;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.dc.ASNumberVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.dc.Vlan;
|
||||
import com.cloud.dc.VlanVO;
|
||||
import com.cloud.dc.dao.ASNumberDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.VlanDao;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
|
|
@ -141,18 +126,33 @@ import com.cloud.network.NetworkService;
|
|||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.network.PhysicalNetwork;
|
||||
import com.cloud.network.RemoteAccessVpn;
|
||||
import com.cloud.network.Site2SiteVpnConnection;
|
||||
import com.cloud.network.addr.PublicIp;
|
||||
import com.cloud.network.dao.FirewallRulesDao;
|
||||
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.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import com.cloud.network.dao.RemoteAccessVpnDao;
|
||||
import com.cloud.network.dao.RemoteAccessVpnVO;
|
||||
import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
|
||||
import com.cloud.network.dao.Site2SiteCustomerGatewayVO;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionDao;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionVO;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.element.NetworkACLServiceProvider;
|
||||
import com.cloud.network.element.NetworkElement;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
import com.cloud.network.element.StaticNatServiceProvider;
|
||||
import com.cloud.network.element.VpcProvider;
|
||||
import com.cloud.network.router.CommandSetupHelper;
|
||||
import com.cloud.network.router.NetworkHelper;
|
||||
import com.cloud.network.router.VpcVirtualNetworkApplianceManager;
|
||||
import com.cloud.network.rules.RulesManager;
|
||||
import com.cloud.network.vpn.RemoteAccessVpnService;
|
||||
import com.cloud.network.vpc.VpcOffering.State;
|
||||
import com.cloud.network.vpc.dao.NetworkACLDao;
|
||||
import com.cloud.network.vpc.dao.PrivateIpDao;
|
||||
|
|
@ -171,6 +171,7 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
|
|||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ResourceTag.ResourceObjectType;
|
||||
import com.cloud.tags.ResourceTagVO;
|
||||
import com.cloud.tags.dao.ResourceTagDao;
|
||||
|
|
@ -207,6 +208,7 @@ import com.cloud.vm.ReservationContextImpl;
|
|||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
import static com.cloud.offering.NetworkOffering.RoutingMode.Dynamic;
|
||||
|
||||
|
|
@ -1220,9 +1222,6 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
// Verify that caller can perform actions in behalf of vpc owner
|
||||
_accountMgr.checkAccess(caller, null, false, owner);
|
||||
|
||||
// check resource limit
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.vpc);
|
||||
|
||||
// Validate zone
|
||||
final DataCenter zone = _dcDao.findById(zoneId);
|
||||
if (zone == null) {
|
||||
|
|
@ -1317,6 +1316,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
vpc.setDisplay(Boolean.TRUE.equals(displayVpc));
|
||||
vpc.setUseRouterIpResolver(Boolean.TRUE.equals(useVrIpResolver));
|
||||
|
||||
try (CheckedReservation vpcReservation = new CheckedReservation(owner, ResourceType.vpc, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
if (vpc.getCidr() == null && cidrSize != null) {
|
||||
// Allocate a CIDR for VPC
|
||||
Ipv4GuestSubnetNetworkMap subnet = routedIpv4Manager.getOrCreateIpv4SubnetForVpc(vpc, cidrSize);
|
||||
|
|
@ -1336,6 +1336,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
routedIpv4Manager.persistBgpPeersForVpc(newVpc.getId(), bgpPeerIds);
|
||||
}
|
||||
return newVpc;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateVpcCidrSize(Account caller, long accountId, VpcOffering vpcOffering, String cidr, Integer cidrSize, long zoneId) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import javax.inject.Inject;
|
|||
import javax.mail.MessagingException;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ProjectRole;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
|
|
@ -47,6 +48,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.PublishScope;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.utils.mailing.MailAddress;
|
||||
import org.apache.cloudstack.utils.mailing.SMTPMailProperties;
|
||||
import org.apache.cloudstack.utils.mailing.SMTPMailSender;
|
||||
|
|
@ -159,6 +161,8 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
private VpcManager _vpcMgr;
|
||||
@Inject
|
||||
MessageBus messageBus;
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
|
||||
protected boolean _invitationRequired = false;
|
||||
protected long _invitationTimeOut = 86400000;
|
||||
|
|
@ -272,8 +276,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
owner = _accountDao.findById(user.getAccountId());
|
||||
}
|
||||
|
||||
//do resource limit check
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.project);
|
||||
try (CheckedReservation projectReservation = new CheckedReservation(owner, ResourceType.project, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
final Account ownerFinal = owner;
|
||||
User finalUser = user;
|
||||
|
|
@ -308,6 +311,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
messageBus.publish(_name, ProjectManager.MESSAGE_CREATE_TUNGSTEN_PROJECT_EVENT, PublishScope.LOCAL, project);
|
||||
|
||||
return project;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -491,6 +495,9 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
//remove account
|
||||
ProjectAccountVO projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId());
|
||||
success = _projectAccountDao.remove(projectAccount.getId());
|
||||
if (projectAccount.getAccountRole() == Role.Admin) {
|
||||
_resourceLimitMgr.decrementResourceCount(account.getId(), ResourceType.project);
|
||||
}
|
||||
|
||||
//remove all invitations for account
|
||||
if (success) {
|
||||
|
|
@ -537,7 +544,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_USER_ADD, eventDescription = "adding user to project", async = true)
|
||||
public boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) {
|
||||
public boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
Project project = getProject(projectId);
|
||||
|
|
@ -594,12 +601,20 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
if (username == null) {
|
||||
throw new InvalidParameterValueException("User information (ID) is required to add user to the project");
|
||||
}
|
||||
|
||||
boolean shouldIncrementResourceCount = projectRole != null && Role.Admin == projectRole;
|
||||
try (CheckedReservation cr = new CheckedReservation(userAccount, ResourceType.project, shouldIncrementResourceCount ? 1L : 0L, reservationDao, _resourceLimitMgr)) {
|
||||
if (assignUserToProject(project, user.getId(), user.getAccountId(), projectRole,
|
||||
Optional.ofNullable(role).map(ProjectRole::getId).orElse(null)) != null) {
|
||||
if (shouldIncrementResourceCount) {
|
||||
_resourceLimitMgr.incrementResourceCount(userAccount.getId(), ResourceType.project);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
logger.warn("Failed to add user to project: {}", project);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
logger.warn("Failed to add user to project: {}", project);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -652,14 +667,18 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
}
|
||||
|
||||
private void updateProjectAccount(ProjectAccountVO futureOwner, Role newAccRole, Long accountId) throws ResourceAllocationException {
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), ResourceType.project);
|
||||
Account account = _accountMgr.getAccount(accountId);
|
||||
boolean shouldIncrementResourceCount = Role.Admin == newAccRole;
|
||||
|
||||
try (CheckedReservation checkedReservation = new CheckedReservation(account, ResourceType.project, shouldIncrementResourceCount ? 1L : 0L, reservationDao, _resourceLimitMgr)) {
|
||||
futureOwner.setAccountRole(newAccRole);
|
||||
_projectAccountDao.update(futureOwner.getId(), futureOwner);
|
||||
if (newAccRole != null && Role.Admin == newAccRole) {
|
||||
if (shouldIncrementResourceCount) {
|
||||
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.project);
|
||||
} else {
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.project);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -701,9 +720,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
" doesn't belong to the project. Add it to the project first and then change the project's ownership");
|
||||
}
|
||||
|
||||
//do resource limit check
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(futureOwnerAccount.getId()), ResourceType.project);
|
||||
|
||||
try (CheckedReservation checkedReservation = new CheckedReservation(futureOwnerAccount, ResourceType.project, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
//unset the role for the old owner
|
||||
ProjectAccountVO currentOwner = _projectAccountDao.findByProjectIdAccountId(projectId, currentOwnerAccount.getId());
|
||||
currentOwner.setAccountRole(Role.Regular);
|
||||
|
|
@ -714,7 +731,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
futureOwner.setAccountRole(Role.Admin);
|
||||
_projectAccountDao.update(futureOwner.getId(), futureOwner);
|
||||
_resourceLimitMgr.incrementResourceCount(futureOwnerAccount.getId(), ResourceType.project);
|
||||
|
||||
}
|
||||
} else {
|
||||
logger.trace("Future owner {}is already the owner of the project {}", newOwnerName, project);
|
||||
}
|
||||
|
|
@ -792,7 +809,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ACCOUNT_ADD, eventDescription = "adding account to project", async = true)
|
||||
public boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) {
|
||||
public boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
//check that the project exists
|
||||
|
|
@ -857,13 +874,20 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
if (account == null) {
|
||||
throw new InvalidParameterValueException("Account information is required for assigning account to the project");
|
||||
}
|
||||
|
||||
boolean shouldIncrementResourceCount = projectRoleType != null && Role.Admin == projectRoleType;
|
||||
try (CheckedReservation cr = new CheckedReservation(account, ResourceType.project, shouldIncrementResourceCount ? 1L : 0L, reservationDao, _resourceLimitMgr)) {
|
||||
if (assignAccountToProject(project, account.getId(), projectRoleType, null,
|
||||
Optional.ofNullable(projectRole).map(ProjectRole::getId).orElse(null)) != null) {
|
||||
if (shouldIncrementResourceCount) {
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), ResourceType.project);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
logger.warn("Failed to add account {} to project {}", accountName, project);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1042,7 +1066,9 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
boolean success = true;
|
||||
ProjectAccountVO projectAccount = _projectAccountDao.findByProjectIdUserId(projectId, user.getAccountId(), user.getId());
|
||||
success = _projectAccountDao.remove(projectAccount.getId());
|
||||
|
||||
if (projectAccount.getAccountRole() == Role.Admin) {
|
||||
_resourceLimitMgr.decrementResourceCount(user.getAccountId(), ResourceType.project);
|
||||
}
|
||||
if (success) {
|
||||
logger.debug("Removed user {} from project. Removing any invite sent to the user", user);
|
||||
ProjectInvitation invite = _projectInvitationDao.findByUserIdProjectId(user.getId(), user.getAccountId(), projectId);
|
||||
|
|
|
|||
|
|
@ -20,13 +20,17 @@ package com.cloud.resourcelimit;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.user.ResourceReservation;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
|
@ -40,7 +44,7 @@ import com.cloud.utils.db.GlobalLock;
|
|||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
|
||||
public class CheckedReservation implements AutoCloseable {
|
||||
public class CheckedReservation implements Reserver {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
private static final int TRY_TO_GET_LOCK_TIME = 120;
|
||||
|
|
@ -48,11 +52,15 @@ public class CheckedReservation implements AutoCloseable {
|
|||
ReservationDao reservationDao;
|
||||
|
||||
ResourceLimitService resourceLimitService;
|
||||
private final Account account;
|
||||
private final ResourceType resourceType;
|
||||
private Long amount;
|
||||
private Account account;
|
||||
private Long domainId;
|
||||
private ResourceType resourceType;
|
||||
private Long resourceId;
|
||||
private Long reservationAmount;
|
||||
private List<String> reservationTags;
|
||||
private Long existingAmount;
|
||||
private List<String> existingLimitTags;
|
||||
private List<ResourceReservation> reservations;
|
||||
private List<String> resourceLimitTags;
|
||||
|
||||
private String getContextParameterKey() {
|
||||
return getResourceReservationContextParameterKey(resourceType);
|
||||
|
|
@ -73,12 +81,12 @@ public class CheckedReservation implements AutoCloseable {
|
|||
this.reservations = null;
|
||||
}
|
||||
|
||||
protected void checkLimitAndPersistReservations(Account account, ResourceType resourceType, Long resourceId, List<String> resourceLimitTags, Long amount) throws ResourceAllocationException {
|
||||
protected void checkLimitAndPersistReservations(Account account, Long domainId, ResourceType resourceType, Long resourceId, List<String> resourceLimitTags, Long amount) throws ResourceAllocationException {
|
||||
try {
|
||||
checkLimitAndPersistReservation(account, resourceType, resourceId, null, amount);
|
||||
checkLimitAndPersistReservation(account, domainId, resourceType, resourceId, null, amount);
|
||||
if (CollectionUtils.isNotEmpty(resourceLimitTags)) {
|
||||
for (String tag : resourceLimitTags) {
|
||||
checkLimitAndPersistReservation(account, resourceType, resourceId, tag, amount);
|
||||
checkLimitAndPersistReservation(account, domainId, resourceType, resourceId, tag, amount);
|
||||
}
|
||||
}
|
||||
} catch (ResourceAllocationException rae) {
|
||||
|
|
@ -87,11 +95,11 @@ public class CheckedReservation implements AutoCloseable {
|
|||
}
|
||||
}
|
||||
|
||||
protected void checkLimitAndPersistReservation(Account account, ResourceType resourceType, Long resourceId, String tag, Long amount) throws ResourceAllocationException {
|
||||
protected void checkLimitAndPersistReservation(Account account, Long domainId, ResourceType resourceType, Long resourceId, String tag, Long amount) throws ResourceAllocationException {
|
||||
if (amount > 0) {
|
||||
resourceLimitService.checkResourceLimitWithTag(account, resourceType, tag, amount);
|
||||
resourceLimitService.checkResourceLimitWithTag(account, domainId, true, resourceType, tag, amount);
|
||||
}
|
||||
ReservationVO reservationVO = new ReservationVO(account.getAccountId(), account.getDomainId(), resourceType, tag, amount);
|
||||
ReservationVO reservationVO = new ReservationVO(account.getAccountId(), domainId, resourceType, tag, amount);
|
||||
if (resourceId != null) {
|
||||
reservationVO.setResourceId(resourceId);
|
||||
}
|
||||
|
|
@ -99,9 +107,25 @@ public class CheckedReservation implements AutoCloseable {
|
|||
this.reservations.add(reservation);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, List<String> resourceLimitTags, Long amount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, resourceType, null, resourceLimitTags, amount, reservationDao, resourceLimitService);
|
||||
// TODO: refactor these into a Builder to avoid having so many constructors
|
||||
public CheckedReservation(Account account, ResourceType resourceType, List<String> resourceLimitTags, Long reservationAmount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, resourceType, null, resourceLimitTags, null, reservationAmount, null, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long resourceId, List<String> reservedTags,
|
||||
List<String> existingTags, Long reservationAmount, Long existingAmount, ReservationDao reservationDao,
|
||||
ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, null, resourceType, resourceId, reservedTags, existingTags, reservationAmount, existingAmount, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, Long domainId, ResourceType resourceType, Long resourceId, List<String> reservedTags,
|
||||
Long reservationAmount, ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, domainId, resourceType, resourceId, reservedTags, null, reservationAmount, null, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long resourceId, List<String> reservedTags, Long reservationAmount, ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, null, resourceType, resourceId, reservedTags, null, reservationAmount, null, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -109,25 +133,48 @@ public class CheckedReservation implements AutoCloseable {
|
|||
* - create DB entry for reservation
|
||||
* - hold the id of this record as a ticket for implementation
|
||||
*
|
||||
* @param amount positive number of the resource type to reserve
|
||||
* @param reservationAmount positive number of the resource type to reserve
|
||||
* @throws ResourceAllocationException
|
||||
*/
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long resourceId, List<String> resourceLimitTags, Long amount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
public CheckedReservation(Account account, Long domainId, ResourceType resourceType, Long resourceId, List<String> reservedTags,
|
||||
List<String> existingTags, Long reservationAmount, Long existingAmount, ReservationDao reservationDao,
|
||||
ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
|
||||
if (ObjectUtils.allNull(account, domainId)) {
|
||||
logger.debug("Not reserving any {} resources, as no account/domain was provided.", resourceType);
|
||||
return;
|
||||
}
|
||||
|
||||
this.reservationDao = reservationDao;
|
||||
this.resourceLimitService = resourceLimitService;
|
||||
this.account = account;
|
||||
this.resourceType = resourceType;
|
||||
this.amount = amount;
|
||||
this.reservations = new ArrayList<>();
|
||||
this.resourceLimitTags = resourceLimitTags;
|
||||
|
||||
if (this.amount != null && this.amount != 0) {
|
||||
if (amount > 0) {
|
||||
// When allocating to a domain instead of a specific account, consider the system account as the owner for the validations here.
|
||||
if (account == null) {
|
||||
account = ApiDBUtils.getSystemAccount();
|
||||
}
|
||||
this.account = account;
|
||||
|
||||
if (domainId == null) {
|
||||
domainId = account.getDomainId();
|
||||
}
|
||||
this.domainId = domainId;
|
||||
|
||||
this.resourceType = resourceType;
|
||||
this.reservationAmount = reservationAmount;
|
||||
this.existingAmount = existingAmount;
|
||||
this.reservations = new ArrayList<>();
|
||||
|
||||
this.reservationTags = getTagsWithoutNull(reservedTags);
|
||||
this.existingLimitTags = getTagsWithoutNull(existingTags);
|
||||
|
||||
// TODO: refactor me
|
||||
if (this.reservationAmount != null && this.reservationAmount != 0) {
|
||||
if (reservationAmount > 0) {
|
||||
setGlobalLock();
|
||||
if (quotaLimitLock.lock(TRY_TO_GET_LOCK_TIME)) {
|
||||
try {
|
||||
checkLimitAndPersistReservations(account, resourceType, resourceId, resourceLimitTags, amount);
|
||||
adjustCountToNotConsiderExistingAmount();
|
||||
checkLimitAndPersistReservations(account, this.domainId, resourceType, resourceId, reservationTags, reservationAmount);
|
||||
CallContext.current().putContextParameter(getContextParameterKey(), getIds());
|
||||
} catch (NullPointerException npe) {
|
||||
throw new CloudRuntimeException("not enough means to check limits", npe);
|
||||
|
|
@ -138,14 +185,28 @@ public class CheckedReservation implements AutoCloseable {
|
|||
throw new ResourceAllocationException(String.format("unable to acquire resource reservation \"%s\"", quotaLimitLock.getName()), resourceType);
|
||||
}
|
||||
} else {
|
||||
checkLimitAndPersistReservations(account, resourceType, resourceId, resourceLimitTags, amount);
|
||||
checkLimitAndPersistReservations(account, this.domainId, resourceType, resourceId, reservationTags, reservationAmount);
|
||||
}
|
||||
} else {
|
||||
logger.debug("not reserving any amount of resources for {} in domain {}, type: {}, tag: {}",
|
||||
account.getAccountName(), account.getDomainId(), resourceType, getResourceLimitTagsAsString());
|
||||
account.getAccountName(), this.domainId, resourceType, getResourceLimitTagsAsString());
|
||||
}
|
||||
}
|
||||
|
||||
protected List<String> getTagsWithoutNull(List<String> tags) {
|
||||
if (tags == null) {
|
||||
return null;
|
||||
}
|
||||
return tags.stream().filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected void adjustCountToNotConsiderExistingAmount() throws ResourceAllocationException {
|
||||
if (existingAmount == null || existingAmount == 0) {
|
||||
return;
|
||||
}
|
||||
checkLimitAndPersistReservations(account, domainId, resourceType, resourceId, existingLimitTags, -1 * existingAmount);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long amount, ReservationDao reservationDao,
|
||||
ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, resourceType, null, amount, reservationDao, resourceLimitService);
|
||||
|
|
@ -153,7 +214,7 @@ public class CheckedReservation implements AutoCloseable {
|
|||
|
||||
@NotNull
|
||||
private void setGlobalLock() {
|
||||
String lockName = String.format("CheckedReservation-%s/%d", account.getDomainId(), resourceType.getOrdinal());
|
||||
String lockName = String.format("CheckedReservation-%s/%d", this.domainId, resourceType.getOrdinal());
|
||||
setQuotaLimitLock(GlobalLock.getInternLock(lockName));
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +223,7 @@ public class CheckedReservation implements AutoCloseable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
public void close() {
|
||||
removeAllReservations();
|
||||
}
|
||||
|
||||
|
|
@ -171,11 +232,11 @@ public class CheckedReservation implements AutoCloseable {
|
|||
}
|
||||
|
||||
public String getResourceLimitTagsAsString() {
|
||||
return CollectionUtils.isNotEmpty(resourceLimitTags) ? StringUtils.join(resourceLimitTags) : null;
|
||||
return CollectionUtils.isNotEmpty(reservationTags) ? StringUtils.join(reservationTags) : null;
|
||||
}
|
||||
|
||||
public Long getReservedAmount() {
|
||||
return amount;
|
||||
return reservationAmount;
|
||||
}
|
||||
|
||||
public List<ResourceReservation> getReservations() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// 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.resourcelimit;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ReservationHelper {
|
||||
|
||||
public static void closeAll(List<Reserver> reservations) throws CloudRuntimeException {
|
||||
for (Reserver reservation : reservations) {
|
||||
reservation.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -54,6 +54,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||
|
|
@ -92,6 +93,7 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkDomainDao;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
|
|
@ -175,6 +177,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
@Inject
|
||||
private ResourceLimitService resourceLimitService;
|
||||
@Inject
|
||||
protected SnapshotDao _snapshotDao;
|
||||
@Inject
|
||||
protected BackupDao backupDao;
|
||||
|
|
@ -204,6 +208,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
DiskOfferingDao diskOfferingDao;
|
||||
@Inject
|
||||
BucketDao bucketDao;
|
||||
@Inject
|
||||
private NetworkDomainDao networkDomainDao;
|
||||
|
||||
protected GenericSearchBuilder<TemplateDataStoreVO, SumCount> templateSizeSearch;
|
||||
protected GenericSearchBuilder<SnapshotDataStoreVO, SumCount> snapshotSizeSearch;
|
||||
|
|
@ -267,7 +273,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
|
||||
templateSizeSearch = _vmTemplateStoreDao.createSearchBuilder(SumCount.class);
|
||||
templateSizeSearch.select("sum", Func.SUM, templateSizeSearch.entity().getSize());
|
||||
templateSizeSearch.and("downloadState", templateSizeSearch.entity().getDownloadState(), Op.EQ);
|
||||
templateSizeSearch.and("downloadState", templateSizeSearch.entity().getDownloadState(), Op.IN);
|
||||
templateSizeSearch.and("destroyed", templateSizeSearch.entity().getDestroyed(), Op.EQ);
|
||||
SearchBuilder<VMTemplateVO> join1 = _vmTemplateDao.createSearchBuilder();
|
||||
join1.and("accountId", join1.entity().getAccountId(), Op.EQ);
|
||||
|
|
@ -515,15 +521,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
return max;
|
||||
}
|
||||
|
||||
protected void checkDomainResourceLimit(final Account account, final Project project, final ResourceType type, String tag, long numResources) throws ResourceAllocationException {
|
||||
// check all domains in the account's domain hierarchy
|
||||
Long domainId;
|
||||
if (project != null) {
|
||||
domainId = project.getDomainId();
|
||||
} else {
|
||||
domainId = account.getDomainId();
|
||||
}
|
||||
|
||||
protected void checkDomainResourceLimit(Long domainId, final ResourceType type, String tag, long numResources) throws ResourceAllocationException {
|
||||
while (domainId != null) {
|
||||
DomainVO domain = _domainDao.findById(domainId);
|
||||
// no limit check if it is ROOT domain
|
||||
|
|
@ -645,11 +643,16 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
|
||||
@Override
|
||||
public void checkResourceLimitWithTag(final Account account, final ResourceType type, String tag, long... count) throws ResourceAllocationException {
|
||||
checkResourceLimitWithTag(account, null, false, type, tag, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkResourceLimitWithTag(final Account account, Long domainId, boolean considerSystemAccount, final ResourceType type, String tag, long... count) throws ResourceAllocationException {
|
||||
final long numResources = ((count.length == 0) ? 1 : count[0]);
|
||||
Project project = null;
|
||||
|
||||
// Don't place any limits on system or root admin accounts
|
||||
if (_accountMgr.isRootAdmin(account.getId())) {
|
||||
if (_accountMgr.isRootAdmin(account.getId()) && !(considerSystemAccount && Account.ACCOUNT_ID_SYSTEM == account.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -657,6 +660,14 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
project = _projectDao.findByProjectAccountId(account.getId());
|
||||
}
|
||||
|
||||
if (domainId == null) {
|
||||
if (project != null) {
|
||||
domainId = project.getDomainId();
|
||||
} else {
|
||||
domainId = account.getDomainId();
|
||||
}
|
||||
}
|
||||
Long domainIdFinal = domainId;
|
||||
final Project projectFinal = project;
|
||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<ResourceAllocationException>() {
|
||||
@Override
|
||||
|
|
@ -666,7 +677,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
// Check account limits
|
||||
checkAccountResourceLimit(account, projectFinal, type, tag, numResources);
|
||||
// check all domains in the account's domain hierarchy
|
||||
checkDomainResourceLimit(account, projectFinal, type, tag, numResources);
|
||||
checkDomainResourceLimit(domainIdFinal, type, tag, numResources);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -1203,7 +1214,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
* @param type the resource type to do the recalculation for
|
||||
* @return the resulting new resource count
|
||||
*/
|
||||
protected long recalculateDomainResourceCount(final long domainId, final ResourceType type, String tag) {
|
||||
public long recalculateDomainResourceCount(final long domainId, final ResourceType type, String tag) {
|
||||
List<AccountVO> accounts = _accountDao.findActiveAccountsForDomain(domainId);
|
||||
List<DomainVO> childDomains = _domainDao.findImmediateChildrenForParent(domainId);
|
||||
|
||||
|
|
@ -1239,9 +1250,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
long newResourceCount = 0L;
|
||||
ResourceCountVO domainRC = null;
|
||||
|
||||
// calculate project count here
|
||||
if (type == ResourceType.project) {
|
||||
newResourceCount += _projectDao.countProjectsForDomain(domainId);
|
||||
if (type == ResourceType.network) {
|
||||
newResourceCount += networkDomainDao.listDomainNetworkMapByDomain(domainId).size();
|
||||
}
|
||||
|
||||
// TODO make sure that the resource counts are not null
|
||||
|
|
@ -1488,7 +1498,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
long totalTemplatesSize = 0;
|
||||
|
||||
SearchCriteria<SumCount> sc = templateSizeSearch.create();
|
||||
sc.setParameters("downloadState", Status.DOWNLOADED);
|
||||
sc.setParameters("downloadState", Status.DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
|
||||
sc.setParameters("destroyed", false);
|
||||
sc.setJoinParameters("templates", "accountId", accountId);
|
||||
List<SumCount> templates = _vmTemplateStoreDao.customSearch(sc, null);
|
||||
|
|
@ -1725,7 +1735,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
return tags;
|
||||
}
|
||||
|
||||
protected List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering) {
|
||||
@Override
|
||||
public List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering) {
|
||||
if (Boolean.FALSE.equals(display)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
|
@ -1739,54 +1750,53 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException {
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitStorageTagsForResourceCountOperation(display, diskOffering);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.volume, tag);
|
||||
if (size != null) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, size);
|
||||
}
|
||||
|
||||
CheckedReservation volumeReservation = new CheckedReservation(owner, ResourceType.volume, tags, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
if (size != null) {
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, tags, size, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException {
|
||||
public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitStorageTagsForResourceCountOperation(display, diskOffering);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (size != null) {
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, size);
|
||||
}
|
||||
}
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, tags, size, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
|
||||
DiskOffering currentOffering, DiskOffering newOffering
|
||||
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations
|
||||
) throws ResourceAllocationException {
|
||||
Ternary<Set<String>, Set<String>, Set<String>> updatedResourceLimitStorageTags = getResourceLimitStorageTagsForDiskOfferingChange(display, currentOffering, newOffering);
|
||||
if (updatedResourceLimitStorageTags == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> sameTags = updatedResourceLimitStorageTags.first();
|
||||
Set<String> newTags = updatedResourceLimitStorageTags.second();
|
||||
|
||||
if (newSize > currentSize) {
|
||||
for (String tag : sameTags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, newSize - currentSize);
|
||||
}
|
||||
List<String> currentTags = getResourceLimitStorageTagsForResourceCountOperation(true, currentOffering);
|
||||
List<String> tagsAfterUpdate = getResourceLimitStorageTagsForResourceCountOperation(true, newOffering);
|
||||
if (currentTags.isEmpty() && tagsAfterUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String tag : newTags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.volume, tag, 1L);
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, newSize);
|
||||
}
|
||||
CheckedReservation volumeReservation = new CheckedReservation(owner, ResourceType.volume, null, tagsAfterUpdate,
|
||||
currentTags, 1L, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, null,
|
||||
tagsAfterUpdate, currentTags, newSize, currentSize, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
|
||||
@DB
|
||||
|
|
@ -2013,20 +2023,27 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException {
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckedReservation vmReservation = new CheckedReservation(owner, ResourceType.user_vm, tags, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(vmReservation);
|
||||
|
||||
Long cpu = serviceOffering.getCpu() != null ? Long.valueOf(serviceOffering.getCpu()) : 0L;
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, ResourceType.cpu, tags, cpu, reservationDao, resourceLimitService);
|
||||
reservations.add(cpuReservation);
|
||||
|
||||
Long ram = serviceOffering.getRamSize() != null ? Long.valueOf(serviceOffering.getRamSize()) : 0L;
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, tags, ram, reservationDao, resourceLimitService);
|
||||
reservations.add(memReservation);
|
||||
|
||||
Long gpu = serviceOffering.getGpuCount() != null ? Long.valueOf(serviceOffering.getGpuCount()) : 0L;
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.user_vm, tag);
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, cpu);
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, ram);
|
||||
checkResourceLimitWithTag(owner, ResourceType.gpu, tag, gpu);
|
||||
}
|
||||
CheckedReservation gpuReservation = new CheckedReservation(owner, ResourceType.gpu, tags, gpu, reservationDao, resourceLimitService);
|
||||
reservations.add(gpuReservation);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2076,83 +2093,60 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
|
||||
@Override
|
||||
public void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException {
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
checkVmResourceLimitsForServiceOfferingAndTemplateChange(owner, display, null, null,
|
||||
null, null, offering, offering, currentTemplate, newTemplate);
|
||||
null, null, offering, offering, currentTemplate, newTemplate, reservations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory,
|
||||
ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template
|
||||
ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template, List<Reserver> reservations
|
||||
) throws ResourceAllocationException {
|
||||
checkVmResourceLimitsForServiceOfferingAndTemplateChange(owner, display, currentCpu, newCpu, currentMemory, newMemory, currentOffering,
|
||||
newOffering != null ? newOffering : currentOffering, template, template);
|
||||
newOffering != null ? newOffering : currentOffering, template, template, reservations);
|
||||
}
|
||||
|
||||
private void checkVmResourceLimitsForServiceOfferingAndTemplateChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering,
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations
|
||||
) throws ResourceAllocationException {
|
||||
Ternary<Set<String>, Set<String>, Set<String>> updatedResourceLimitHostTags = getResourceLimitHostTagsForVmServiceOfferingAndTemplateChange(display, currentOffering, newOffering, currentTemplate, newTemplate);
|
||||
if (updatedResourceLimitHostTags == null) {
|
||||
List<String> currentTags = getResourceLimitHostTagsForResourceCountOperation(true, currentOffering, currentTemplate);
|
||||
List<String> tagsAfterUpdate = getResourceLimitHostTagsForResourceCountOperation(true, newOffering, newTemplate);
|
||||
if (currentTags.isEmpty() && tagsAfterUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckedReservation vmReservation = new CheckedReservation(owner, ResourceType.user_vm, null, tagsAfterUpdate,
|
||||
currentTags, 1L, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(vmReservation);
|
||||
|
||||
if (currentCpu == null) {
|
||||
currentCpu = currentOffering.getCpu() != null ? Long.valueOf(currentOffering.getCpu()) : 0L;
|
||||
}
|
||||
if (newCpu == null) {
|
||||
newCpu = newOffering.getCpu() != null ? Long.valueOf(newOffering.getCpu()) : 0L;
|
||||
}
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, ResourceType.cpu, null, tagsAfterUpdate,
|
||||
currentTags, newCpu, currentCpu, reservationDao, resourceLimitService);
|
||||
reservations.add(cpuReservation);
|
||||
|
||||
if (currentMemory == null) {
|
||||
currentMemory = currentOffering.getRamSize() != null ? Long.valueOf(currentOffering.getRamSize()) : 0L;
|
||||
}
|
||||
if (newMemory == null) {
|
||||
newMemory = newOffering.getRamSize() != null ? Long.valueOf(newOffering.getRamSize()) : 0L;
|
||||
}
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, null, tagsAfterUpdate,
|
||||
currentTags, newMemory, currentMemory, reservationDao, resourceLimitService);
|
||||
reservations.add(memReservation);
|
||||
|
||||
Long currentGpu = currentOffering.getGpuCount() != null ? Long.valueOf(currentOffering.getGpuCount()) : 0L;
|
||||
Long newGpu = newOffering.getGpuCount() != null ? Long.valueOf(newOffering.getGpuCount()) : 0L;
|
||||
|
||||
Set<String> sameTags = updatedResourceLimitHostTags.first();
|
||||
Set<String> newTags = updatedResourceLimitHostTags.second();
|
||||
|
||||
if (newCpu - currentCpu > 0 || newMemory - currentMemory > 0 || newGpu - currentGpu > 0) {
|
||||
for (String tag : sameTags) {
|
||||
if (newCpu - currentCpu > 0) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, newCpu - currentCpu);
|
||||
}
|
||||
|
||||
if (newMemory - currentMemory > 0) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, newMemory - currentMemory);
|
||||
}
|
||||
|
||||
if (newGpu - currentGpu > 0) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.gpu, tag, newGpu - currentGpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String tag : newTags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.user_vm, tag, 1L);
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, newCpu);
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, newMemory);
|
||||
checkResourceLimitWithTag(owner, ResourceType.gpu, tag, newGpu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (cpu == null) {
|
||||
cpu = serviceOffering.getCpu() != null ? Long.valueOf(serviceOffering.getCpu()) : 0L;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, cpu);
|
||||
}
|
||||
CheckedReservation gpuReservation = new CheckedReservation(owner, ResourceType.gpu, null, tagsAfterUpdate,
|
||||
currentTags, newGpu, currentGpu, reservationDao, resourceLimitService);
|
||||
reservations.add(gpuReservation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2183,20 +2177,6 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (memory == null) {
|
||||
memory = serviceOffering.getRamSize() != null ? Long.valueOf(serviceOffering.getRamSize()) : 0L;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, memory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
|
|
@ -2225,20 +2205,6 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmGpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (gpu == null) {
|
||||
gpu = serviceOffering.getGpuCount() != null ? Long.valueOf(serviceOffering.getGpuCount()) : 0L;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.gpu, tag, gpu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.agent.api.to.OVFInformationTO;
|
||||
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.EndPoint;
|
||||
|
|
@ -37,6 +36,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
|
|||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.storage.command.UploadStatusAnswer;
|
||||
import org.apache.cloudstack.storage.command.UploadStatusAnswer.UploadStatus;
|
||||
import org.apache.cloudstack.storage.command.UploadStatusCommand;
|
||||
|
|
@ -55,6 +55,7 @@ import com.cloud.agent.api.AgentControlCommand;
|
|||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.to.OVFInformationTO;
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.api.query.dao.TemplateJoinDao;
|
||||
import com.cloud.api.query.vo.TemplateJoinVO;
|
||||
|
|
@ -62,15 +63,20 @@ import com.cloud.configuration.Resource;
|
|||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
import com.cloud.exception.ConnectionException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.ResourceLimitService;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
|
|
@ -117,6 +123,12 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
private TemplateJoinDao templateJoinDao;
|
||||
@Inject
|
||||
private DeployAsIsHelper deployAsIsHelper;
|
||||
@Inject
|
||||
private AccountDao accountDao;
|
||||
@Inject
|
||||
private AccountManager _accountMgr;
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
|
||||
private long _nodeId;
|
||||
private ScheduledExecutorService _executor = null;
|
||||
|
|
@ -205,6 +217,36 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
public UploadStatusCheck() {
|
||||
}
|
||||
|
||||
private Answer sendUploadStatusCommandForVolume(EndPoint ep, UploadStatusCommand cmd, VolumeVO volume) {
|
||||
Answer answer = null;
|
||||
try {
|
||||
answer = ep.sendMessage(cmd);
|
||||
} catch (CloudRuntimeException e) {
|
||||
logger.warn("Unable to get upload status for volume {}. Error details: {}", volume, e.getMessage());
|
||||
answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage());
|
||||
}
|
||||
if (answer == null || !(answer instanceof UploadStatusAnswer)) {
|
||||
logger.warn("No or invalid answer corresponding to UploadStatusCommand for volume {}", volume);
|
||||
return null;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private Answer sendUploadStatusCommandForTemplate(EndPoint ep, UploadStatusCommand cmd, VMTemplateVO template) {
|
||||
Answer answer = null;
|
||||
try {
|
||||
answer = ep.sendMessage(cmd);
|
||||
} catch (CloudRuntimeException e) {
|
||||
logger.warn("Unable to get upload status for template {}. Error details: {}", template, e.getMessage());
|
||||
answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage());
|
||||
}
|
||||
if (answer == null || !(answer instanceof UploadStatusAnswer)) {
|
||||
logger.warn("No or invalid answer corresponding to UploadStatusCommand for template {}", template);
|
||||
return null;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
// 1. Select all entries with download_state = Not_Downloaded or Download_In_Progress
|
||||
|
|
@ -231,18 +273,17 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
UploadStatusCommand cmd = new UploadStatusCommand(volume.getUuid(), EntityType.Volume);
|
||||
if (host != null && host.getManagementServerId() != null) {
|
||||
if (_nodeId == host.getManagementServerId().longValue()) {
|
||||
Answer answer = null;
|
||||
try {
|
||||
answer = ep.sendMessage(cmd);
|
||||
} catch (CloudRuntimeException e) {
|
||||
logger.warn("Unable to get upload status for volume {}. Error details: {}", volume, e.getMessage());
|
||||
answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage());
|
||||
}
|
||||
if (answer == null || !(answer instanceof UploadStatusAnswer)) {
|
||||
logger.warn("No or invalid answer corresponding to UploadStatusCommand for volume {}", volume);
|
||||
Answer answer = sendUploadStatusCommandForVolume(ep, cmd, volume);
|
||||
if (answer == null) {
|
||||
continue;
|
||||
}
|
||||
handleVolumeStatusResponse((UploadStatusAnswer)answer, volume, volumeDataStore);
|
||||
if (!handleVolumeStatusResponse((UploadStatusAnswer)answer, volume, volumeDataStore)) {
|
||||
cmd = new UploadStatusCommand(volume.getUuid(), EntityType.Volume, true);
|
||||
answer = sendUploadStatusCommandForVolume(ep, cmd, volume);
|
||||
if (answer == null) {
|
||||
logger.warn("Unable to abort upload for volume {}", volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String error = "Volume " + volume.getUuid() + " failed to upload as SSVM is either destroyed or SSVM agent not in 'Up' state";
|
||||
|
|
@ -275,18 +316,17 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
UploadStatusCommand cmd = new UploadStatusCommand(template.getUuid(), EntityType.Template);
|
||||
if (host != null && host.getManagementServerId() != null) {
|
||||
if (_nodeId == host.getManagementServerId().longValue()) {
|
||||
Answer answer = null;
|
||||
try {
|
||||
answer = ep.sendMessage(cmd);
|
||||
} catch (CloudRuntimeException e) {
|
||||
logger.warn("Unable to get upload status for template {}. Error details: {}", template, e.getMessage());
|
||||
answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage());
|
||||
}
|
||||
if (answer == null || !(answer instanceof UploadStatusAnswer)) {
|
||||
logger.warn("No or invalid answer corresponding to UploadStatusCommand for template {}", template);
|
||||
Answer answer = sendUploadStatusCommandForTemplate(ep, cmd, template);
|
||||
if (answer == null) {
|
||||
continue;
|
||||
}
|
||||
handleTemplateStatusResponse((UploadStatusAnswer)answer, template, templateDataStore);
|
||||
if (!handleTemplateStatusResponse((UploadStatusAnswer) answer, template, templateDataStore)) {
|
||||
cmd = new UploadStatusCommand(template.getUuid(), EntityType.Template, true);
|
||||
answer = sendUploadStatusCommandForTemplate(ep, cmd, template);
|
||||
if (answer == null) {
|
||||
logger.warn("Unable to abort upload for template {}", template);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String error = String.format(
|
||||
|
|
@ -303,7 +343,41 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
}
|
||||
}
|
||||
|
||||
private void handleVolumeStatusResponse(final UploadStatusAnswer answer, final VolumeVO volume, final VolumeDataStoreVO volumeDataStore) {
|
||||
private Boolean checkAndUpdateSecondaryStorageResourceLimit(Long accountId, Long lastSize, Long currentSize) {
|
||||
if (lastSize >= currentSize) {
|
||||
return true;
|
||||
}
|
||||
Long usage = currentSize - lastSize;
|
||||
try (CheckedReservation secStorageReservation = new CheckedReservation(_accountMgr.getAccount(accountId), Resource.ResourceType.secondary_storage, null, null, usage, reservationDao, _resourceLimitMgr)) {
|
||||
_resourceLimitMgr.incrementResourceCount(accountId, Resource.ResourceType.secondary_storage, usage);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, Resource.ResourceType.secondary_storage, lastSize);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean checkAndUpdateVolumeResourceLimit(VolumeVO volume, VolumeDataStoreVO volumeDataStore, UploadStatusAnswer answer) {
|
||||
boolean success = true;
|
||||
Long currentSize = answer.getVirtualSize() != 0 ? answer.getVirtualSize() : answer.getPhysicalSize();
|
||||
Long lastSize = volume.getSize() != null ? volume.getSize() : 0L;
|
||||
if (!checkAndUpdateSecondaryStorageResourceLimit(volume.getAccountId(), volume.getSize(), currentSize)) {
|
||||
volumeDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
|
||||
volumeDataStore.setState(State.Failed);
|
||||
volumeDataStore.setErrorString("Storage Limit Reached");
|
||||
Account owner = accountDao.findById(volume.getAccountId());
|
||||
String msg = String.format("Upload of volume [%s] failed because its owner [%s] does not have enough secondary storage space available.", volume.getUuid(), owner.getUuid());
|
||||
logger.error(msg);
|
||||
success = false;
|
||||
}
|
||||
VolumeVO volumeUpdate = _volumeDao.findById(volume.getId());
|
||||
volumeUpdate.setSize(currentSize);
|
||||
_volumeDao.update(volumeUpdate.getId(), volumeUpdate);
|
||||
return success;
|
||||
}
|
||||
|
||||
private boolean handleVolumeStatusResponse(final UploadStatusAnswer answer, final VolumeVO volume, final VolumeDataStoreVO volumeDataStore) {
|
||||
final boolean[] needAbort = new boolean[]{false};
|
||||
final StateMachine2<Volume.State, Event, Volume> stateMachine = Volume.State.getStateMachine();
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
|
|
@ -315,6 +389,11 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
try {
|
||||
switch (answer.getStatus()) {
|
||||
case COMPLETED:
|
||||
if (!checkAndUpdateVolumeResourceLimit(tmpVolume, tmpVolumeDataStore, answer)) {
|
||||
stateMachine.transitTo(tmpVolume, Event.OperationFailed, null, _volumeDao);
|
||||
sendAlert = true;
|
||||
break;
|
||||
}
|
||||
tmpVolumeDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
tmpVolumeDataStore.setState(State.Ready);
|
||||
tmpVolumeDataStore.setInstallPath(answer.getInstallPath());
|
||||
|
|
@ -326,7 +405,6 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
volumeUpdate.setSize(answer.getVirtualSize());
|
||||
_volumeDao.update(tmpVolume.getId(), volumeUpdate);
|
||||
stateMachine.transitTo(tmpVolume, Event.OperationSucceeded, null, _volumeDao);
|
||||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), Resource.ResourceType.secondary_storage, answer.getVirtualSize());
|
||||
|
||||
// publish usage events
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_UPLOAD, tmpVolume.getAccountId(),
|
||||
|
|
@ -339,6 +417,12 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
}
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
if (!checkAndUpdateVolumeResourceLimit(tmpVolume, tmpVolumeDataStore, answer)) {
|
||||
stateMachine.transitTo(tmpVolume, Event.OperationFailed, null, _volumeDao);
|
||||
sendAlert = true;
|
||||
needAbort[0] = true;
|
||||
break;
|
||||
}
|
||||
if (tmpVolume.getState() == Volume.State.NotUploaded) {
|
||||
tmpVolumeDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS);
|
||||
tmpVolumeDataStore.setDownloadPercent(answer.getDownloadPercent());
|
||||
|
|
@ -387,10 +471,29 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
}
|
||||
}
|
||||
});
|
||||
return !needAbort[0];
|
||||
}
|
||||
|
||||
private void handleTemplateStatusResponse(final UploadStatusAnswer answer, final VMTemplateVO template, final TemplateDataStoreVO templateDataStore) {
|
||||
private Boolean checkAndUpdateTemplateResourceLimit(VMTemplateVO template, TemplateDataStoreVO templateDataStore, UploadStatusAnswer answer) {
|
||||
boolean success = true;
|
||||
Long currentSize = answer.getVirtualSize() != 0 ? answer.getVirtualSize() : answer.getPhysicalSize();
|
||||
Long lastSize = template.getSize() != null ? template.getSize() : 0L;
|
||||
if (!checkAndUpdateSecondaryStorageResourceLimit(template.getAccountId(), lastSize, currentSize)) {
|
||||
templateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
|
||||
templateDataStore.setErrorString("Storage Limit Reached");
|
||||
templateDataStore.setState(State.Failed);
|
||||
Account owner = accountDao.findById(template.getAccountId());
|
||||
String msg = String.format("Upload of template [%s] failed because its owner [%s] does not have enough secondary storage space available.", template.getUuid(), owner.getUuid());
|
||||
logger.error(msg);
|
||||
success = false;
|
||||
}
|
||||
templateDataStore.setSize(currentSize);
|
||||
return success;
|
||||
}
|
||||
|
||||
private boolean handleTemplateStatusResponse(final UploadStatusAnswer answer, final VMTemplateVO template, final TemplateDataStoreVO templateDataStore) {
|
||||
final StateMachine2<VirtualMachineTemplate.State, VirtualMachineTemplate.Event, VirtualMachineTemplate> stateMachine = VirtualMachineTemplate.State.getStateMachine();
|
||||
final boolean[] needAbort = new boolean[]{false};
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
|
|
@ -401,6 +504,11 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
try {
|
||||
switch (answer.getStatus()) {
|
||||
case COMPLETED:
|
||||
if (!checkAndUpdateTemplateResourceLimit(tmpTemplate, tmpTemplateDataStore, answer)) {
|
||||
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
|
||||
sendAlert = true;
|
||||
break;
|
||||
}
|
||||
tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
tmpTemplateDataStore.setState(State.Ready);
|
||||
tmpTemplateDataStore.setInstallPath(answer.getInstallPath());
|
||||
|
|
@ -436,8 +544,23 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Account owner = accountDao.findById(template.getAccountId());
|
||||
long templateSize = answer.getVirtualSize();
|
||||
|
||||
try (CheckedReservation secondaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.secondary_storage, null, null, templateSize, reservationDao, _resourceLimitMgr)) {
|
||||
_resourceLimitMgr.incrementResourceCount(owner.getId(), Resource.ResourceType.secondary_storage, templateSize);
|
||||
} catch (ResourceAllocationException e) {
|
||||
tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.UPLOAD_ERROR);
|
||||
tmpTemplateDataStore.setState(State.Failed);
|
||||
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
|
||||
msg = String.format("Upload of template [%s] failed because its owner [%s] does not have enough secondary storage space available.", template.getUuid(), owner.getUuid());
|
||||
logger.warn(msg);
|
||||
sendAlert = true;
|
||||
break;
|
||||
}
|
||||
|
||||
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationSucceeded, null, _templateDao);
|
||||
_resourceLimitMgr.incrementResourceCount(template.getAccountId(), Resource.ResourceType.secondary_storage, answer.getVirtualSize());
|
||||
//publish usage event
|
||||
String etype = EventTypes.EVENT_TEMPLATE_CREATE;
|
||||
if (tmpTemplate.getFormat() == Storage.ImageFormat.ISO) {
|
||||
|
|
@ -453,6 +576,12 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
}
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
if (!checkAndUpdateTemplateResourceLimit(tmpTemplate, tmpTemplateDataStore, answer)) {
|
||||
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
|
||||
sendAlert = true;
|
||||
needAbort[0] = true;
|
||||
break;
|
||||
}
|
||||
if (tmpTemplate.getState() == VirtualMachineTemplate.State.NotUploaded) {
|
||||
tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS);
|
||||
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.UploadRequested, null, _templateDao);
|
||||
|
|
@ -502,6 +631,7 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
|
|||
}
|
||||
}
|
||||
});
|
||||
return !needAbort[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,16 +35,11 @@ import java.util.stream.Collectors;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDetailsDao;
|
||||
import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.CheckAndRepairVolumeCmd;
|
||||
|
|
@ -94,10 +89,12 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
|||
import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl;
|
||||
import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
|
||||
import org.apache.cloudstack.jobs.JobInfo;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.SnapshotPolicyDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.apache.cloudstack.resourcedetail.dao.SnapshotPolicyDetailsDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
|
|
@ -166,8 +163,12 @@ import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.server.ResourceTag;
|
||||
|
|
@ -242,8 +243,12 @@ import com.cloud.vm.VmWorkTakeVolumeSnapshot;
|
|||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDetailsDao;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
|
@ -351,10 +356,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
private ManagementService managementService;
|
||||
@Inject
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
|
||||
@Inject
|
||||
protected DomainDao domainDao;
|
||||
|
||||
@Inject
|
||||
protected ProjectManager projectManager;
|
||||
@Inject
|
||||
|
|
@ -367,7 +370,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
HostPodDao podDao;
|
||||
@Inject
|
||||
EndPointSelector _epSelector;
|
||||
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
@Inject
|
||||
private VMSnapshotDetailsDao vmSnapshotDetailsDao;
|
||||
|
||||
|
|
@ -440,9 +444,17 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
Long diskOfferingId = cmd.getDiskOfferingId();
|
||||
String imageStoreUuid = cmd.getImageStoreUuid();
|
||||
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, url, format, diskOfferingId);
|
||||
VolumeVO volume;
|
||||
|
||||
VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, format, diskOfferingId, Volume.State.Allocated);
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, url, format, diskOfferingId, reservations);
|
||||
volume = persistVolume(owner, zoneId, volumeName, url, format, diskOfferingId, Volume.State.Allocated);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
||||
|
||||
|
|
@ -482,77 +494,83 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
final Long diskOfferingId = cmd.getDiskOfferingId();
|
||||
String imageStoreUuid = cmd.getImageStoreUuid();
|
||||
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId);
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId, reservations);
|
||||
|
||||
return Transaction.execute(new TransactionCallbackWithException<GetUploadParamsResponse, MalformedURLException>() {
|
||||
@Override
|
||||
public GetUploadParamsResponse doInTransaction(TransactionStatus status) throws MalformedURLException {
|
||||
return Transaction.execute(new TransactionCallbackWithException<GetUploadParamsResponse, MalformedURLException>() {
|
||||
@Override
|
||||
public GetUploadParamsResponse doInTransaction(TransactionStatus status) throws MalformedURLException {
|
||||
|
||||
VolumeVO volume = persistVolume(owner, zoneId, volumeName, null, format, diskOfferingId, Volume.State.NotUploaded);
|
||||
VolumeVO volume = persistVolume(owner, zoneId, volumeName, null, format, diskOfferingId, Volume.State.NotUploaded);
|
||||
|
||||
final DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId, volume);
|
||||
final DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId, volume);
|
||||
|
||||
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
||||
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
||||
|
||||
RegisterVolumePayload payload = new RegisterVolumePayload(null, cmd.getChecksum(), format);
|
||||
vol.addPayload(payload);
|
||||
RegisterVolumePayload payload = new RegisterVolumePayload(null, cmd.getChecksum(), format);
|
||||
vol.addPayload(payload);
|
||||
|
||||
Pair<EndPoint, DataObject> pair = volService.registerVolumeForPostUpload(vol, store);
|
||||
EndPoint ep = pair.first();
|
||||
DataObject dataObject = pair.second();
|
||||
Pair<EndPoint, DataObject> pair = volService.registerVolumeForPostUpload(vol, store);
|
||||
EndPoint ep = pair.first();
|
||||
DataObject dataObject = pair.second();
|
||||
|
||||
GetUploadParamsResponse response = new GetUploadParamsResponse();
|
||||
GetUploadParamsResponse response = new GetUploadParamsResponse();
|
||||
|
||||
String ssvmUrlDomain = _configDao.getValue(Config.SecStorageSecureCopyCert.key());
|
||||
String protocol = UseHttpsToUpload.value() ? "https" : "http";
|
||||
String ssvmUrlDomain = _configDao.getValue(Config.SecStorageSecureCopyCert.key());
|
||||
String protocol = UseHttpsToUpload.value() ? "https" : "http";
|
||||
|
||||
String url = ImageStoreUtil.generatePostUploadUrl(ssvmUrlDomain, ep.getPublicAddr(), vol.getUuid(), protocol);
|
||||
response.setPostURL(new URL(url));
|
||||
String url = ImageStoreUtil.generatePostUploadUrl(ssvmUrlDomain, ep.getPublicAddr(), vol.getUuid(), protocol);
|
||||
response.setPostURL(new URL(url));
|
||||
|
||||
// set the post url, this is used in the monitoring thread to determine the SSVM
|
||||
VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(vol.getId());
|
||||
assert (volumeStore != null) : "sincle volume is registered, volumestore cannot be null at this stage";
|
||||
volumeStore.setExtractUrl(url);
|
||||
_volumeStoreDao.persist(volumeStore);
|
||||
// set the post url, this is used in the monitoring thread to determine the SSVM
|
||||
VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(vol.getId());
|
||||
assert (volumeStore != null) : "sincle volume is registered, volumestore cannot be null at this stage";
|
||||
volumeStore.setExtractUrl(url);
|
||||
_volumeStoreDao.persist(volumeStore);
|
||||
|
||||
response.setId(UUID.fromString(vol.getUuid()));
|
||||
response.setId(UUID.fromString(vol.getUuid()));
|
||||
|
||||
int timeout = ImageStoreUploadMonitorImpl.getUploadOperationTimeout();
|
||||
DateTime currentDateTime = new DateTime(DateTimeZone.UTC);
|
||||
String expires = currentDateTime.plusMinutes(timeout).toString();
|
||||
response.setTimeout(expires);
|
||||
int timeout = ImageStoreUploadMonitorImpl.getUploadOperationTimeout();
|
||||
DateTime currentDateTime = new DateTime(DateTimeZone.UTC);
|
||||
String expires = currentDateTime.plusMinutes(timeout).toString();
|
||||
response.setTimeout(expires);
|
||||
|
||||
String key = _configDao.getValue(Config.SSVMPSK.key());
|
||||
/*
|
||||
* encoded metadata using the post upload config key
|
||||
*/
|
||||
TemplateOrVolumePostUploadCommand command = new TemplateOrVolumePostUploadCommand(vol.getId(), vol.getUuid(), volumeStore.getInstallPath(), cmd.getChecksum(), vol.getType().toString(),
|
||||
vol.getName(), vol.getFormat().toString(), dataObject.getDataStore().getUri(), 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()));
|
||||
String key = _configDao.getValue(Config.SSVMPSK.key());
|
||||
/*
|
||||
* encoded metadata using the post upload config key
|
||||
*/
|
||||
TemplateOrVolumePostUploadCommand command = new TemplateOrVolumePostUploadCommand(vol.getId(), vol.getUuid(), volumeStore.getInstallPath(), cmd.getChecksum(), vol.getType().toString(),
|
||||
vol.getName(), vol.getFormat().toString(), dataObject.getDataStore().getUri(), 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()));
|
||||
|
||||
long accountId = vol.getAccountId();
|
||||
Account account = _accountDao.findById(accountId);
|
||||
Domain domain = domainDao.findById(account.getDomainId());
|
||||
long accountId = vol.getAccountId();
|
||||
Account account = _accountDao.findById(accountId);
|
||||
Domain domain = domainDao.findById(account.getDomainId());
|
||||
|
||||
command.setDefaultMaxSecondaryStorageInGB(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
|
||||
command.setAccountId(accountId);
|
||||
Gson gson = new GsonBuilder().create();
|
||||
String metadata = EncryptionUtil.encodeData(gson.toJson(command), key);
|
||||
response.setMetadata(metadata);
|
||||
command.setDefaultMaxSecondaryStorageInBytes(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
|
||||
command.setAccountId(accountId);
|
||||
Gson gson = new GsonBuilder().create();
|
||||
String metadata = EncryptionUtil.encodeData(gson.toJson(command), key);
|
||||
response.setMetadata(metadata);
|
||||
|
||||
/*
|
||||
* signature calculated on the url, expiry, metadata.
|
||||
*/
|
||||
response.setSignature(EncryptionUtil.generateSignature(metadata + url + expires, key));
|
||||
return response;
|
||||
}
|
||||
});
|
||||
/*
|
||||
* signature calculated on the url, expiry, metadata.
|
||||
*/
|
||||
response.setSignature(EncryptionUtil.generateSignature(metadata + url + expires, key));
|
||||
return response;
|
||||
}
|
||||
});
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format, Long diskOfferingId) throws ResourceAllocationException {
|
||||
private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format, Long diskOfferingId, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
// permission check
|
||||
Account volumeOwner = _accountMgr.getActiveAccountById(ownerId);
|
||||
|
|
@ -563,7 +581,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
_accountMgr.checkAccess(caller, null, true, volumeOwner);
|
||||
|
||||
// Check that the resource limit for volumes won't be exceeded
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(volumeOwner, true, null, diskOffering);
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(volumeOwner, true, null, diskOffering, reservations);
|
||||
|
||||
// Verify that zone exists
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
|
|
@ -937,30 +955,39 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
|
||||
Storage.ProvisioningType provisioningType = diskOffering.getProvisioningType();
|
||||
|
||||
// Check that the resource limit for volume & primary storage won't be exceeded
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(owner,displayVolume, size, diskOffering);
|
||||
|
||||
// Verify that zone exists
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
|
||||
List<String> tags = _resourceLimitMgr.getResourceLimitStorageTagsForResourceCountOperation(displayVolume, diskOffering);
|
||||
if (tags.size() == 1 && tags.get(0) == null) {
|
||||
tags = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Check if zone is disabled
|
||||
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
|
||||
throw new PermissionDeniedException(String.format("Cannot perform this operation, Zone: %s is currently disabled", zone));
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(owner, displayVolume, size, diskOffering, reservations);
|
||||
|
||||
// Verify that zone exists
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
|
||||
}
|
||||
|
||||
// Check if zone is disabled
|
||||
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
|
||||
throw new PermissionDeniedException(String.format("Cannot perform this operation, Zone: %s is currently disabled", zone));
|
||||
}
|
||||
|
||||
// If local storage is disabled then creation of volume with local disk
|
||||
// offering not allowed
|
||||
if (!zone.isLocalStorageEnabled() && diskOffering.isUseLocalStorage()) {
|
||||
throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
|
||||
}
|
||||
|
||||
String userSpecifiedName = getVolumeNameFromCommand(cmd);
|
||||
|
||||
return commitVolume(cmd.getSnapshotId(), caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName,
|
||||
_uuidMgr.generateUuid(Volume.class, cmd.getCustomId()), details);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
// If local storage is disabled then creation of volume with local disk
|
||||
// offering not allowed
|
||||
if (!zone.isLocalStorageEnabled() && diskOffering.isUseLocalStorage()) {
|
||||
throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
|
||||
}
|
||||
|
||||
String userSpecifiedName = getVolumeNameFromCommand(cmd);
|
||||
|
||||
return commitVolume(cmd.getSnapshotId(), caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName,
|
||||
_uuidMgr.generateUuid(Volume.class, cmd.getCustomId()), details);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -978,7 +1005,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
return Transaction.execute(new TransactionCallback<VolumeVO>() {
|
||||
@Override
|
||||
public VolumeVO doInTransaction(TransactionStatus status) {
|
||||
VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, provisioningType, 0, Volume.Type.DATADISK);
|
||||
VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, -1L, null, null, provisioningType, 0, Volume.Type.DATADISK);
|
||||
volume.setPoolId(null);
|
||||
volume.setUuid(uuid);
|
||||
volume.setDataCenterId(zoneId);
|
||||
|
|
@ -1317,134 +1344,141 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
if (dataStore != null && dataStore.getDriver() instanceof PrimaryDataStoreDriver) {
|
||||
newSize = ((PrimaryDataStoreDriver) dataStore.getDriver()).getVolumeSizeRequiredOnPool(newSize, null, isEncryptionRequired);
|
||||
}
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering);
|
||||
|
||||
// Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform
|
||||
// the requested change
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering, reservations);
|
||||
|
||||
/* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
|
||||
// We need to publish this event to usage_volume table
|
||||
if (volume.getState() == Volume.State.Allocated) {
|
||||
logger.debug("Volume is in the allocated state, but has never been created. Simply updating database with new size and IOPS.");
|
||||
// Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform
|
||||
// the requested change
|
||||
|
||||
volume.setSize(newSize);
|
||||
volume.setMinIops(newMinIops);
|
||||
volume.setMaxIops(newMaxIops);
|
||||
volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
|
||||
/* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
|
||||
// We need to publish this event to usage_volume table
|
||||
if (volume.getState() == Volume.State.Allocated) {
|
||||
logger.debug("Volume is in the allocated state, but has never been created. Simply updating database with new size and IOPS.");
|
||||
|
||||
if (newDiskOffering != null) {
|
||||
volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
|
||||
}
|
||||
volume.setSize(newSize);
|
||||
volume.setMinIops(newMinIops);
|
||||
volume.setMaxIops(newMaxIops);
|
||||
volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
|
||||
|
||||
_volsDao.update(volume.getId(), volume);
|
||||
_resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
|
||||
diskOffering, newDiskOffering);
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
|
||||
volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
|
||||
return volume;
|
||||
}
|
||||
|
||||
Long newDiskOfferingId = newDiskOffering != null ? newDiskOffering.getId() : diskOffering.getId();
|
||||
|
||||
boolean volumeMigrateRequired = false;
|
||||
List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = null;
|
||||
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
|
||||
if (!storageMgr.storagePoolHasEnoughSpaceForResize(storagePool, currentSize, newSize)) {
|
||||
if (!autoMigrateVolume) {
|
||||
throw new CloudRuntimeException(String.format("Failed to resize volume %s since the storage pool does not have enough space to accommodate new size for the volume %s, try with automigrate set to true in order to check in the other suitable pools for the new size and then migrate & resize volume there.", volume.getUuid(), volume.getName()));
|
||||
}
|
||||
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOfferingId, currentSize, newMinIops, newMaxIops, true, false);
|
||||
List<? extends StoragePool> suitableStoragePools = poolsPair.second();
|
||||
if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering or new size", volume.getUuid()));
|
||||
}
|
||||
final Long newSizeFinal = newSize;
|
||||
suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) with enough space found.", volume.getUuid()));
|
||||
}
|
||||
Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
|
||||
volumeMigrateRequired = true;
|
||||
}
|
||||
|
||||
boolean volumeResizeRequired = false;
|
||||
if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
|
||||
volumeResizeRequired = true;
|
||||
}
|
||||
if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) {
|
||||
_volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
|
||||
volume = _volsDao.findById(volume.getId());
|
||||
updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
if (volumeMigrateRequired) {
|
||||
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOfferingId, true);
|
||||
try {
|
||||
Volume result = migrateVolume(migrateVolumeCmd);
|
||||
volume = (result != null) ? _volsDao.findById(result.getId()) : null;
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
|
||||
}
|
||||
}
|
||||
|
||||
UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
|
||||
|
||||
if (userVm != null) {
|
||||
// serialize VM operation
|
||||
AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
||||
|
||||
if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
||||
// avoid re-entrance
|
||||
|
||||
VmWorkJobVO placeHolder = null;
|
||||
|
||||
placeHolder = createPlaceHolderWork(userVm.getId());
|
||||
|
||||
try {
|
||||
return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
|
||||
newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
|
||||
} finally {
|
||||
_workJobDao.expunge(placeHolder.getId());
|
||||
}
|
||||
} else {
|
||||
Outcome<Volume> outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
|
||||
newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
|
||||
|
||||
try {
|
||||
outcome.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Operation was interrupted", e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException("Execution exception", e);
|
||||
if (newDiskOffering != null) {
|
||||
volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
|
||||
}
|
||||
|
||||
Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
|
||||
_volsDao.update(volume.getId(), volume);
|
||||
_resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
|
||||
diskOffering, newDiskOffering);
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
|
||||
volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
|
||||
return volume;
|
||||
}
|
||||
|
||||
if (jobResult != null) {
|
||||
if (jobResult instanceof ConcurrentOperationException) {
|
||||
throw (ConcurrentOperationException) jobResult;
|
||||
} else if (jobResult instanceof ResourceAllocationException) {
|
||||
throw (ResourceAllocationException) jobResult;
|
||||
} else if (jobResult instanceof RuntimeException) {
|
||||
throw (RuntimeException) jobResult;
|
||||
} else if (jobResult instanceof Throwable) {
|
||||
throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
|
||||
} else if (jobResult instanceof Long) {
|
||||
return _volsDao.findById((Long) jobResult);
|
||||
}
|
||||
Long newDiskOfferingId = newDiskOffering != null ? newDiskOffering.getId() : diskOffering.getId();
|
||||
|
||||
boolean volumeMigrateRequired = false;
|
||||
List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = null;
|
||||
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
|
||||
if (!storageMgr.storagePoolHasEnoughSpaceForResize(storagePool, currentSize, newSize)) {
|
||||
if (!autoMigrateVolume) {
|
||||
throw new CloudRuntimeException(String.format("Failed to resize volume %s since the storage pool does not have enough space to accommodate new size for the volume %s, try with automigrate set to true in order to check in the other suitable pools for the new size and then migrate & resize volume there.", volume.getUuid(), volume.getName()));
|
||||
}
|
||||
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOfferingId, currentSize, newMinIops, newMaxIops, true, false);
|
||||
List<? extends StoragePool> suitableStoragePools = poolsPair.second();
|
||||
if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering or new size", volume.getUuid()));
|
||||
}
|
||||
final Long newSizeFinal = newSize;
|
||||
suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) with enough space found.", volume.getUuid()));
|
||||
}
|
||||
Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
|
||||
volumeMigrateRequired = true;
|
||||
}
|
||||
|
||||
boolean volumeResizeRequired = false;
|
||||
if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
|
||||
volumeResizeRequired = true;
|
||||
}
|
||||
if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) {
|
||||
_volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
|
||||
volume = _volsDao.findById(volume.getId());
|
||||
updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
|
||||
|
||||
return volume;
|
||||
}
|
||||
}
|
||||
|
||||
return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null,
|
||||
shrinkOk);
|
||||
if (volumeMigrateRequired) {
|
||||
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOfferingId, true);
|
||||
try {
|
||||
Volume result = migrateVolume(migrateVolumeCmd);
|
||||
volume = (result != null) ? _volsDao.findById(result.getId()) : null;
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
|
||||
}
|
||||
}
|
||||
|
||||
UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
|
||||
|
||||
if (userVm != null) {
|
||||
// serialize VM operation
|
||||
AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
||||
|
||||
if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
||||
// avoid re-entrance
|
||||
|
||||
VmWorkJobVO placeHolder = null;
|
||||
|
||||
placeHolder = createPlaceHolderWork(userVm.getId());
|
||||
|
||||
try {
|
||||
return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
|
||||
newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
|
||||
} finally {
|
||||
_workJobDao.expunge(placeHolder.getId());
|
||||
}
|
||||
} else {
|
||||
Outcome<Volume> outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
|
||||
newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
|
||||
|
||||
try {
|
||||
outcome.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Operation was interrupted", e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException("Execution exception", e);
|
||||
}
|
||||
|
||||
Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
|
||||
|
||||
if (jobResult != null) {
|
||||
if (jobResult instanceof ConcurrentOperationException) {
|
||||
throw (ConcurrentOperationException) jobResult;
|
||||
} else if (jobResult instanceof ResourceAllocationException) {
|
||||
throw (ResourceAllocationException) jobResult;
|
||||
} else if (jobResult instanceof RuntimeException) {
|
||||
throw (RuntimeException) jobResult;
|
||||
} else if (jobResult instanceof Throwable) {
|
||||
throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
|
||||
} else if (jobResult instanceof Long) {
|
||||
return _volsDao.findById((Long) jobResult);
|
||||
}
|
||||
}
|
||||
|
||||
return volume;
|
||||
}
|
||||
}
|
||||
|
||||
return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null,
|
||||
shrinkOk);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateNoVmSnapshots(VolumeVO volume) {
|
||||
|
|
@ -1901,24 +1935,29 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
throw new InvalidParameterValueException("Please specify a volume in Destroy state.");
|
||||
}
|
||||
|
||||
DiskOffering diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize());
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(_accountMgr.getAccount(volume.getAccountId()), volume.isDisplayVolume(), volume.getSize(), diskOffering, reservations);
|
||||
|
||||
try {
|
||||
_volsDao.detachVolume(volume.getId());
|
||||
stateTransitTo(volume, Volume.Event.RecoverRequested);
|
||||
} catch (NoTransitionException e) {
|
||||
logger.debug("Failed to recover volume {}", volume, e);
|
||||
throw new CloudRuntimeException(String.format("Failed to recover volume %s", volume), e);
|
||||
}
|
||||
_resourceLimitMgr.incrementVolumeResourceCount(volume.getAccountId(), volume.isDisplay(),
|
||||
volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
try {
|
||||
_volsDao.detachVolume(volume.getId());
|
||||
stateTransitTo(volume, Volume.Event.RecoverRequested);
|
||||
} catch (NoTransitionException e) {
|
||||
logger.debug("Failed to recover volume {}", volume, e);
|
||||
throw new CloudRuntimeException(String.format("Failed to recover volume %s", volume), e);
|
||||
}
|
||||
_resourceLimitMgr.incrementVolumeResourceCount(volume.getAccountId(), volume.isDisplay(),
|
||||
volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
|
||||
|
||||
|
||||
publishVolumeCreationUsageEvent(volume);
|
||||
|
||||
return volume;
|
||||
|
|
@ -2147,96 +2186,102 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
newSize = ((PrimaryDataStoreDriver) dataStore.getDriver()).getVolumeSizeRequiredOnPool(newSize, null, newDiskOffering.getEncrypt());
|
||||
}
|
||||
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering);
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering, reservations);
|
||||
|
||||
/* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
|
||||
// We need to publish this event to usage_volume table
|
||||
if (volume.getState() == Volume.State.Allocated) {
|
||||
logger.debug("Volume {} is in the allocated state, but has never been created. Simply updating database with new size and IOPS.", volume);
|
||||
/* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
|
||||
// We need to publish this event to usage_volume table
|
||||
if (volume.getState() == Volume.State.Allocated) {
|
||||
logger.debug("Volume {} is in the allocated state, but has never been created. Simply updating database with new size and IOPS.", volume);
|
||||
|
||||
volume.setSize(newSize);
|
||||
volume.setMinIops(newMinIops);
|
||||
volume.setMaxIops(newMaxIops);
|
||||
volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
|
||||
volume.setSize(newSize);
|
||||
volume.setMinIops(newMinIops);
|
||||
volume.setMaxIops(newMaxIops);
|
||||
volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
|
||||
|
||||
if (newDiskOffering != null) {
|
||||
volume.setDiskOfferingId(newDiskOfferingId);
|
||||
_volumeMgr.saveVolumeDetails(newDiskOfferingId, volume.getId());
|
||||
}
|
||||
|
||||
_volsDao.update(volume.getId(), volume);
|
||||
_resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
|
||||
existingDiskOffering, newDiskOffering);
|
||||
|
||||
if (currentSize != newSize) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
|
||||
volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
|
||||
}
|
||||
return volume;
|
||||
}
|
||||
|
||||
if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
|
||||
volumeResizeRequired = true;
|
||||
validateVolumeReadyStateAndHypervisorChecks(volume, currentSize, newSize);
|
||||
}
|
||||
|
||||
StoragePoolVO existingStoragePool = _storagePoolDao.findById(volume.getPoolId());
|
||||
|
||||
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOffering.getId(), currentSize, newMinIops, newMaxIops, true, false);
|
||||
List<? extends StoragePool> suitableStoragePools = poolsPair.second();
|
||||
|
||||
if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == existingStoragePool.getId()))) {
|
||||
volumeMigrateRequired = true;
|
||||
if (!autoMigrateVolume) {
|
||||
throw new InvalidParameterValueException(String.format("Failed to change offering for volume %s since automigrate is set to false but volume needs to migrated", volume.getUuid()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!volumeMigrateRequired && !volumeResizeRequired) {
|
||||
_volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
|
||||
volume = _volsDao.findById(volume.getId());
|
||||
updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
if (volumeMigrateRequired) {
|
||||
if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) found for migrating to support new disk offering", volume));
|
||||
}
|
||||
final Long newSizeFinal = newSize;
|
||||
List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) with enough space found for volume migration.", volume));
|
||||
}
|
||||
Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
|
||||
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOffering.getId(), true);
|
||||
try {
|
||||
Volume result = migrateVolume(migrateVolumeCmd);
|
||||
volume = (result != null) ? _volsDao.findById(result.getId()) : null;
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s", volume, suitableStoragePools.get(0)));
|
||||
if (newDiskOffering != null) {
|
||||
volume.setDiskOfferingId(newDiskOfferingId);
|
||||
_volumeMgr.saveVolumeDetails(newDiskOfferingId, volume.getId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s due to %s", volume, suitableStoragePools.get(0), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
if (volumeResizeRequired) {
|
||||
// refresh volume data
|
||||
volume = _volsDao.findById(volume.getId());
|
||||
try {
|
||||
volume = resizeVolumeInternal(volume, newDiskOffering, currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, shrinkOk);
|
||||
} catch (Exception e) {
|
||||
if (volumeMigrateRequired) {
|
||||
logger.warn(String.format("Volume change offering operation succeeded for volume ID: %s but volume resize operation failed, so please try resize volume operation separately", volume.getUuid()));
|
||||
} else {
|
||||
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume ID: %s due to resize volume operation failed", volume.getUuid()));
|
||||
_volsDao.update(volume.getId(), volume);
|
||||
_resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
|
||||
existingDiskOffering, newDiskOffering);
|
||||
|
||||
if (currentSize != newSize) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
|
||||
volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
|
||||
}
|
||||
return volume;
|
||||
}
|
||||
|
||||
if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
|
||||
volumeResizeRequired = true;
|
||||
validateVolumeReadyStateAndHypervisorChecks(volume, currentSize, newSize);
|
||||
}
|
||||
|
||||
StoragePoolVO existingStoragePool = _storagePoolDao.findById(volume.getPoolId());
|
||||
|
||||
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOffering.getId(), currentSize, newMinIops, newMaxIops, true, false);
|
||||
List<? extends StoragePool> suitableStoragePools = poolsPair.second();
|
||||
|
||||
if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == existingStoragePool.getId()))) {
|
||||
volumeMigrateRequired = true;
|
||||
if (!autoMigrateVolume) {
|
||||
throw new InvalidParameterValueException(String.format("Failed to change offering for volume %s since automigrate is set to false but volume needs to migrated", volume.getUuid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return volume;
|
||||
if (!volumeMigrateRequired && !volumeResizeRequired) {
|
||||
_volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
|
||||
volume = _volsDao.findById(volume.getId());
|
||||
updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
if (volumeMigrateRequired) {
|
||||
if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) found for migrating to support new disk offering", volume));
|
||||
}
|
||||
final Long newSizeFinal = newSize;
|
||||
List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) with enough space found for volume migration.", volume));
|
||||
}
|
||||
Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
|
||||
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOffering.getId(), true);
|
||||
try {
|
||||
Volume result = migrateVolume(migrateVolumeCmd);
|
||||
volume = (result != null) ? _volsDao.findById(result.getId()) : null;
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s", volume, suitableStoragePools.get(0)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s due to %s", volume, suitableStoragePools.get(0), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
if (volumeResizeRequired) {
|
||||
// refresh volume data
|
||||
volume = _volsDao.findById(volume.getId());
|
||||
try {
|
||||
volume = resizeVolumeInternal(volume, newDiskOffering, currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, shrinkOk);
|
||||
} catch (Exception e) {
|
||||
if (volumeMigrateRequired) {
|
||||
logger.warn(String.format("Volume change offering operation succeeded for volume ID: %s but volume resize operation failed, so please try resize volume operation separately", volume.getUuid()));
|
||||
} else {
|
||||
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume ID: %s due to resize volume operation failed", volume.getUuid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return volume;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStorageWithTheNewDiskOffering(VolumeVO volume, DiskOfferingVO newDiskOffering) {
|
||||
|
|
@ -2442,7 +2487,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
}
|
||||
|
||||
private void validateVolumeResizeWithSize(VolumeVO volume, long currentSize, Long newSize, boolean shrinkOk,
|
||||
DiskOfferingVO existingDiskOffering, DiskOfferingVO newDiskOffering) throws ResourceAllocationException {
|
||||
DiskOfferingVO existingDiskOffering, DiskOfferingVO newDiskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
// if the caller is looking to change the size of the volume
|
||||
if (newSize != null && currentSize != newSize) {
|
||||
|
|
@ -2507,7 +2552,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
/* Check resource limit for this account */
|
||||
_resourceLimitMgr.checkVolumeResourceLimitForDiskOfferingChange(_accountMgr.getAccount(volume.getAccountId()),
|
||||
volume.isDisplayVolume(), currentSize, newSize != null ? newSize : currentSize,
|
||||
existingDiskOffering, newDiskOffering);
|
||||
existingDiskOffering, newDiskOffering, reservations);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2686,7 +2731,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
|
||||
checkForBackups(vm, true);
|
||||
|
||||
checkRightsToAttach(caller, volumeToAttach, vm);
|
||||
_accountMgr.checkAccess(caller, null, true, volumeToAttach, vm);
|
||||
|
||||
StoragePoolVO volumeToAttachStoragePool = _storagePoolDao.findById(volumeToAttach.getPoolId());
|
||||
if (logger.isTraceEnabled() && volumeToAttachStoragePool != null) {
|
||||
|
|
@ -2710,6 +2755,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
throw new InvalidParameterValueException("Volume's disk offering has encryption enabled, but volume encryption is not supported for hypervisor type " + rootDiskHyperType);
|
||||
}
|
||||
|
||||
Account owner = _accountDao.findById(volumeToAttach.getAccountId());
|
||||
List<String> resourceLimitStorageTags = _resourceLimitMgr.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering);
|
||||
Long requiredPrimaryStorageSpace = getRequiredPrimaryStorageSizeForVolumeAttach(resourceLimitStorageTags, volumeToAttach);
|
||||
|
||||
try (CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, resourceLimitStorageTags, requiredPrimaryStorageSpace, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
_jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
|
||||
|
||||
if (asyncExecutionContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
||||
|
|
@ -2717,9 +2768,21 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
} else {
|
||||
return getVolumeAttachJobResult(vmId, volumeId, deviceId);
|
||||
}
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable private Volume getVolumeAttachJobResult(Long vmId, Long volumeId, Long deviceId) {
|
||||
protected Long getRequiredPrimaryStorageSizeForVolumeAttach(List<String> resourceLimitStorageTags, VolumeInfo volumeToAttach) {
|
||||
if (CollectionUtils.isEmpty(resourceLimitStorageTags) || Arrays.asList(Volume.State.Allocated, Volume.State.Ready).contains(volumeToAttach.getState())) {
|
||||
return 0L;
|
||||
}
|
||||
return volumeToAttach.getSize();
|
||||
}
|
||||
|
||||
@Nullable protected Volume getVolumeAttachJobResult(Long vmId, Long volumeId, Long deviceId) {
|
||||
Outcome<Volume> outcome = attachVolumeToVmThroughJobQueue(vmId, volumeId, deviceId);
|
||||
|
||||
Volume vol = null;
|
||||
|
|
@ -2768,21 +2831,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
}
|
||||
}
|
||||
|
||||
private void checkRightsToAttach(Account caller, VolumeInfo volumeToAttach, UserVmVO vm) {
|
||||
_accountMgr.checkAccess(caller, null, true, volumeToAttach, vm);
|
||||
|
||||
Account owner = _accountDao.findById(volumeToAttach.getAccountId());
|
||||
|
||||
if (!Arrays.asList(Volume.State.Allocated, Volume.State.Ready).contains(volumeToAttach.getState())) {
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize());
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForVMSnapshots(Long vmId, UserVmVO vm) {
|
||||
// if target VM has associated VM snapshots
|
||||
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
|
||||
|
|
@ -4348,7 +4396,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
_accountMgr.checkAccess(caller, null, true, oldAccount);
|
||||
_accountMgr.checkAccess(caller, null, true, newAccount);
|
||||
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(newAccount, true, volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(newAccount, true, volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()), reservations);
|
||||
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
|
|
@ -4358,6 +4408,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
});
|
||||
|
||||
return volume;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateVolumeAccount(Account oldAccount, VolumeVO volume, Account newAccount) {
|
||||
|
|
@ -5314,20 +5368,20 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
private Pair<JobInfo.Status, String> orchestrateAttachVolumeToVM(VmWorkAttachVolume work) throws Exception {
|
||||
Volume vol = orchestrateAttachVolumeToVM(work.getVmId(), work.getVolumeId(), work.getDeviceId());
|
||||
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(vol.getId())));
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(vol.getId()));
|
||||
}
|
||||
|
||||
@ReflectionUse
|
||||
private Pair<JobInfo.Status, String> orchestrateDetachVolumeFromVM(VmWorkDetachVolume work) throws Exception {
|
||||
Volume vol = orchestrateDetachVolumeFromVM(work.getVmId(), work.getVolumeId());
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(vol.getId())));
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(vol.getId()));
|
||||
}
|
||||
|
||||
@ReflectionUse
|
||||
private Pair<JobInfo.Status, String> orchestrateResizeVolume(VmWorkResizeVolume work) throws Exception {
|
||||
Volume vol = orchestrateResizeVolume(work.getVolumeId(), work.getCurrentSize(), work.getNewSize(), work.getNewMinIops(), work.getNewMaxIops(), work.getNewHypervisorSnapshotReserve(),
|
||||
work.getNewServiceOfferingId(), work.isShrinkOk());
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(vol.getId())));
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(vol.getId()));
|
||||
}
|
||||
|
||||
@ReflectionUse
|
||||
|
|
|
|||
|
|
@ -95,6 +95,11 @@ public abstract class DownloadActiveState extends DownloadState {
|
|||
return Status.ABANDONED.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleLimitReached() {
|
||||
return Status.LIMIT_REACHED.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleDisconnect() {
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ public class DownloadErrorState extends DownloadInactiveState {
|
|||
return Status.ABANDONED.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleLimitReached() {
|
||||
return Status.LIMIT_REACHED.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Status.DOWNLOAD_ERROR.toString();
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@ public abstract class DownloadInactiveState extends DownloadState {
|
|||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleLimitReached() {
|
||||
// ignore and stay put
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleDisconnect() {
|
||||
//ignore and stay put
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
// 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.storage.download;
|
||||
|
||||
import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
|
||||
public class DownloadLimitReachedState extends DownloadInactiveState {
|
||||
|
||||
public DownloadLimitReachedState(DownloadListener dl) {
|
||||
super(dl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Status.LIMIT_REACHED.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleEvent(DownloadEvent event, Object eventObj) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
getDownloadListener().log("handleEvent, event type=" + event + ", curr state=" + getName(), Level.TRACE);
|
||||
}
|
||||
return Status.LIMIT_REACHED.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntry(String prevState, DownloadEvent event, Object evtObj) {
|
||||
if (!prevState.equalsIgnoreCase(getName())) {
|
||||
DownloadAnswer answer = new DownloadAnswer("Storage Limit Reached", Status.LIMIT_REACHED);
|
||||
getDownloadListener().callback(answer);
|
||||
getDownloadListener().cancelStatusTask();
|
||||
getDownloadListener().cancelTimeoutTask();
|
||||
getDownloadListener().scheduleImmediateStatusCheck(RequestType.PURGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,15 @@ import java.util.Timer;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.ResourceLimitService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
|
|
@ -34,10 +43,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.storage.command.DownloadCommand;
|
||||
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
|
||||
import org.apache.cloudstack.storage.command.DownloadProgressCommand;
|
||||
import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
||||
import org.apache.cloudstack.utils.cache.LazyCache;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
|
@ -107,6 +119,7 @@ public class DownloadListener implements Listener {
|
|||
public static final String DOWNLOAD_ERROR = Status.DOWNLOAD_ERROR.toString();
|
||||
public static final String DOWNLOAD_IN_PROGRESS = Status.DOWNLOAD_IN_PROGRESS.toString();
|
||||
public static final String DOWNLOAD_ABANDONED = Status.ABANDONED.toString();
|
||||
public static final String DOWNLOAD_LIMIT_REACHED = Status.LIMIT_REACHED.toString();
|
||||
|
||||
private EndPoint _ssAgent;
|
||||
|
||||
|
|
@ -137,6 +150,18 @@ public class DownloadListener implements Listener {
|
|||
private DataStoreManager _storeMgr;
|
||||
@Inject
|
||||
private VolumeService _volumeSrv;
|
||||
@Inject
|
||||
private VMTemplateDao _templateDao;
|
||||
@Inject
|
||||
private TemplateDataStoreDao _templateDataStoreDao;
|
||||
@Inject
|
||||
private VolumeDao _volumeDao;
|
||||
@Inject
|
||||
private ResourceLimitService _resourceLimitMgr;
|
||||
@Inject
|
||||
private AccountManager _accountMgr;
|
||||
@Inject
|
||||
ReservationDao _reservationDao;
|
||||
|
||||
private LazyCache<Long, List<Hypervisor.HypervisorType>> zoneHypervisorsCache;
|
||||
|
||||
|
|
@ -160,7 +185,7 @@ public class DownloadListener implements Listener {
|
|||
_downloadMonitor = downloadMonitor;
|
||||
_cmd = cmd;
|
||||
initStateMachine();
|
||||
_currState = getState(Status.NOT_DOWNLOADED.toString());
|
||||
_currState = getState(NOT_DOWNLOADED);
|
||||
this._timer = timer;
|
||||
_timeoutTask = new TimeoutTask(this);
|
||||
this._timer.schedule(_timeoutTask, 3 * STATUS_POLL_INTERVAL);
|
||||
|
|
@ -184,11 +209,12 @@ public class DownloadListener implements Listener {
|
|||
}
|
||||
|
||||
private void initStateMachine() {
|
||||
_stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this));
|
||||
_stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this));
|
||||
_stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this));
|
||||
_stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this));
|
||||
_stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this));
|
||||
_stateMap.put(NOT_DOWNLOADED, new NotDownloadedState(this));
|
||||
_stateMap.put(DOWNLOADED, new DownloadCompleteState(this));
|
||||
_stateMap.put(DOWNLOAD_ERROR, new DownloadErrorState(this));
|
||||
_stateMap.put(DOWNLOAD_IN_PROGRESS, new DownloadInProgressState(this));
|
||||
_stateMap.put(DOWNLOAD_ABANDONED, new DownloadAbandonedState(this));
|
||||
_stateMap.put(DOWNLOAD_LIMIT_REACHED, new DownloadLimitReachedState(this));
|
||||
}
|
||||
|
||||
private DownloadState getState(String stateName) {
|
||||
|
|
@ -239,10 +265,53 @@ public class DownloadListener implements Listener {
|
|||
return false;
|
||||
}
|
||||
|
||||
private Long getAccountIdForDataObject() {
|
||||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
if (DataObjectType.TEMPLATE.equals(object.getType())) {
|
||||
VMTemplateVO t = _templateDao.findById(object.getId());
|
||||
return t != null ? t.getAccountId() : null;
|
||||
} else if (DataObjectType.VOLUME.equals(object.getType())) {
|
||||
VolumeVO v = _volumeDao.findById(object.getId());
|
||||
return v != null ? v.getAccountId() : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Long getSizeFromDB() {
|
||||
Long lastSize = 0L;
|
||||
if (DataObjectType.TEMPLATE.equals(object.getType())) {
|
||||
TemplateDataStoreVO t = _templateDataStoreDao.findByStoreTemplate(object.getDataStore().getId(), object.getId());
|
||||
lastSize = t.getSize();
|
||||
} else if (DataObjectType.VOLUME.equals(object.getType())) {
|
||||
VolumeVO v = _volumeDao.findById(object.getId());
|
||||
lastSize = v.getSize();
|
||||
}
|
||||
return lastSize;
|
||||
}
|
||||
|
||||
private Boolean checkAndUpdateResourceLimits(DownloadAnswer answer) {
|
||||
Long lastSize = getSizeFromDB();
|
||||
Long currentSize = answer.getTemplateSize();
|
||||
|
||||
if (currentSize > lastSize) {
|
||||
Long accountId = getAccountIdForDataObject();
|
||||
Account account = _accountMgr.getAccount(accountId);
|
||||
Long usage = currentSize - lastSize;
|
||||
try (CheckedReservation secStorageReservation = new CheckedReservation(account, Resource.ResourceType.secondary_storage, usage, _reservationDao, _resourceLimitMgr)) {
|
||||
_resourceLimitMgr.incrementResourceCount(accountId, Resource.ResourceType.secondary_storage, usage);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
|
||||
boolean processed = false;
|
||||
if (answers != null & answers.length > 0) {
|
||||
if (answers != null && answers.length > 0) {
|
||||
if (answers[0] instanceof DownloadAnswer) {
|
||||
final DownloadAnswer answer = (DownloadAnswer)answers[0];
|
||||
if (getJobId() == null) {
|
||||
|
|
@ -250,7 +319,11 @@ public class DownloadListener implements Listener {
|
|||
} else if (!getJobId().equalsIgnoreCase(answer.getJobId())) {
|
||||
return false;//TODO
|
||||
}
|
||||
transition(DownloadEvent.DOWNLOAD_ANSWER, answer);
|
||||
if (!checkAndUpdateResourceLimits(answer)) {
|
||||
transition(DownloadEvent.LIMIT_REACHED, answer);
|
||||
} else {
|
||||
transition(DownloadEvent.DOWNLOAD_ANSWER, answer);
|
||||
}
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import com.cloud.agent.api.storage.DownloadAnswer;
|
|||
|
||||
public abstract class DownloadState {
|
||||
public static enum DownloadEvent {
|
||||
DOWNLOAD_ANSWER, ABANDON_DOWNLOAD, TIMEOUT_CHECK, DISCONNECT
|
||||
DOWNLOAD_ANSWER, ABANDON_DOWNLOAD, LIMIT_REACHED, TIMEOUT_CHECK, DISCONNECT
|
||||
};
|
||||
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
|
@ -51,6 +51,8 @@ public abstract class DownloadState {
|
|||
return handleAnswer(answer);
|
||||
case ABANDON_DOWNLOAD:
|
||||
return handleAbort();
|
||||
case LIMIT_REACHED:
|
||||
return handleLimitReached();
|
||||
case TIMEOUT_CHECK:
|
||||
Date now = new Date();
|
||||
long update = now.getTime() - dl.getLastUpdated().getTime();
|
||||
|
|
@ -78,6 +80,8 @@ public abstract class DownloadState {
|
|||
|
||||
public abstract String handleAbort();
|
||||
|
||||
public abstract String handleLimitReached();
|
||||
|
||||
public abstract String handleDisconnect();
|
||||
|
||||
public abstract String handleAnswer(DownloadAnswer answer);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@
|
|||
// under the License.
|
||||
package com.cloud.storage.snapshot;
|
||||
|
||||
|
||||
import com.cloud.storage.StoragePoolStatus;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
|
@ -36,9 +34,6 @@ import java.util.stream.Collectors;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.storage.Upload;
|
||||
import com.cloud.storage.dao.SnapshotDetailsDao;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
|
|
@ -77,6 +72,7 @@ import org.apache.cloudstack.framework.config.Configurable;
|
|||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJob;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcedetail.SnapshotPolicyDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.SnapshotPolicyDetailsDao;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
|
|
@ -119,10 +115,12 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ResourceTag.ResourceObjectType;
|
||||
import com.cloud.server.TaggedResourceService;
|
||||
import com.cloud.storage.CreateSnapshotPayload;
|
||||
|
|
@ -135,15 +133,18 @@ import com.cloud.storage.SnapshotPolicyVO;
|
|||
import com.cloud.storage.SnapshotScheduleVO;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.StoragePoolStatus;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.Upload;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.SnapshotDetailsDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.storage.dao.SnapshotScheduleDao;
|
||||
|
|
@ -251,7 +252,8 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
public TaggedResourceService taggedResourceService;
|
||||
@Inject
|
||||
private AnnotationDao annotationDao;
|
||||
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
@Inject
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
@Inject
|
||||
|
|
@ -321,7 +323,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
hostIdsToTryFirst = new long[] {vmHostId};
|
||||
}
|
||||
|
||||
List<Long> hostIdsToAvoid = new ArrayList<Long>();
|
||||
List<Long> hostIdsToAvoid = new ArrayList<>();
|
||||
for (int retry = _totalRetries; retry >= 0; retry--) {
|
||||
try {
|
||||
Pair<Long, Answer> result = _storageMgr.sendToPool(pool, hostIdsToTryFirst, hostIdsToAvoid, cmd);
|
||||
|
|
@ -421,7 +423,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
|
||||
public void updateVolumeSizeAndPrimaryStorageCount(VolumeVO volume, SnapshotVO snapshot) {
|
||||
Long differenceBetweenVolumeAndSnapshotSize = new Long(volume.getSize() - snapshot.getSize());
|
||||
long differenceBetweenVolumeAndSnapshotSize = volume.getSize() - snapshot.getSize();
|
||||
if (differenceBetweenVolumeAndSnapshotSize != 0) {
|
||||
if (differenceBetweenVolumeAndSnapshotSize > 0) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshot.getAccountId(), ResourceType.primary_storage, differenceBetweenVolumeAndSnapshotSize);
|
||||
|
|
@ -695,7 +697,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
} catch (Exception e) {
|
||||
logger.debug("Failed to backup Snapshot from Instance Snapshot", e);
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.snapshot);
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.secondary_storage, new Long(volume.getSize()));
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwnerId, ResourceType.secondary_storage, volume.getSize());
|
||||
throw new CloudRuntimeException("Failed to backup Snapshot from Instance Snapshot", e);
|
||||
} finally {
|
||||
if (snapshotOnPrimaryStore != null) {
|
||||
|
|
@ -910,43 +912,36 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
List<SnapshotDataStoreVO> snapshotStoreRefs = storeRefAndZones.first();
|
||||
List<Long> zoneIds = storeRefAndZones.second();
|
||||
|
||||
boolean result = snapshotStrategy.deleteSnapshot(snapshotId, zoneId);
|
||||
if (result) {
|
||||
for (Long zId : zoneIds) {
|
||||
if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(), zId, snapshotId,
|
||||
snapshotCheck.getName(), null, null, 0L, snapshotCheck.getClass().getName(), snapshotCheck.getUuid());
|
||||
try {
|
||||
boolean result = snapshotStrategy.deleteSnapshot(snapshotId, zoneId);
|
||||
if (result) {
|
||||
for (Long zId : zoneIds) {
|
||||
if (snapshotCheck.getState() == Snapshot.State.BackedUp) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_DELETE, snapshotCheck.getAccountId(), zId, snapshotId,
|
||||
snapshotCheck.getName(), null, null, 0L, snapshotCheck.getClass().getName(), snapshotCheck.getUuid());
|
||||
}
|
||||
}
|
||||
final SnapshotVO postDeleteSnapshotEntry = _snapshotDao.findById(snapshotId);
|
||||
if (postDeleteSnapshotEntry == null || Snapshot.State.Destroyed.equals(postDeleteSnapshotEntry.getState())) {
|
||||
annotationDao.removeByEntityType(AnnotationService.EntityType.SNAPSHOT.name(), snapshotCheck.getUuid());
|
||||
|
||||
if (snapshotCheck.getState() != Snapshot.State.Error && snapshotCheck.getState() != Snapshot.State.Destroyed) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.snapshot);
|
||||
}
|
||||
}
|
||||
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
|
||||
if (ObjectInDataStoreStateMachine.State.Ready.equals(snapshotStoreRef.getState()) && !DataStoreRole.Primary.equals(snapshotStoreRef.getRole())) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.secondary_storage, snapshotStoreRef.getPhysicalSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
final SnapshotVO postDeleteSnapshotEntry = _snapshotDao.findById(snapshotId);
|
||||
if (postDeleteSnapshotEntry == null || Snapshot.State.Destroyed.equals(postDeleteSnapshotEntry.getState())) {
|
||||
annotationDao.removeByEntityType(AnnotationService.EntityType.SNAPSHOT.name(), snapshotCheck.getUuid());
|
||||
|
||||
if (snapshotCheck.getState() != Snapshot.State.Error && snapshotCheck.getState() != Snapshot.State.Destroyed) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.snapshot);
|
||||
}
|
||||
}
|
||||
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
|
||||
if (ObjectInDataStoreStateMachine.State.Ready.equals(snapshotStoreRef.getState()) && !DataStoreRole.Primary.equals(snapshotStoreRef.getRole())) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.secondary_storage, new Long(snapshotStoreRef.getPhysicalSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
final SnapshotVO postDeleteSnapshotEntry = _snapshotDao.findById(snapshotId);
|
||||
if (postDeleteSnapshotEntry == null || Snapshot.State.Destroyed.equals(postDeleteSnapshotEntry.getState())) {
|
||||
annotationDao.removeByEntityType(AnnotationService.EntityType.SNAPSHOT.name(), snapshotCheck.getUuid());
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed to delete snapshot {}:{}", snapshotCheck, e.toString());
|
||||
|
||||
if (snapshotCheck.getState() != Snapshot.State.Error && snapshotCheck.getState() != Snapshot.State.Destroyed) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.snapshot);
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to delete snapshot:" + e.toString());
|
||||
}
|
||||
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
|
||||
if (ObjectInDataStoreStateMachine.State.Ready.equals(snapshotStoreRef.getState()) && !DataStoreRole.Primary.equals(snapshotStoreRef.getRole())) {
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotCheck.getAccountId(), ResourceType.secondary_storage, new Long(snapshotStoreRef.getPhysicalSize()));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -960,7 +955,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
Map<String, String> tags = cmd.getTags();
|
||||
Long zoneId = cmd.getZoneId();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
List<Long> permittedAccounts = new ArrayList<>();
|
||||
|
||||
// Verify parameters
|
||||
if (volumeId != null) {
|
||||
|
|
@ -972,7 +967,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds());
|
||||
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(),
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(),
|
||||
cmd.isRecursive(), null);
|
||||
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
|
|
@ -1065,7 +1060,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
|
||||
Pair<List<SnapshotVO>, Integer> result = _snapshotDao.searchAndCount(sc, searchFilter);
|
||||
return new Pair<List<? extends Snapshot>, Integer>(result.first(), result.second());
|
||||
return new Pair<>(result.first(), result.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1081,7 +1076,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
if (volume.getPoolId() == null) {
|
||||
continue;
|
||||
}
|
||||
Long volumeId = volume.getId();
|
||||
long volumeId = volume.getId();
|
||||
Long dcId = volume.getDataCenterId();
|
||||
if (_snapshotDao.listByVolumeIdIncludingRemoved(volumeId).isEmpty()) {
|
||||
// This volume doesn't have any snapshots. Nothing do delete.
|
||||
|
|
@ -1125,7 +1120,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
if (Type.MANUAL == snapshot.getRecurringType()) {
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.snapshot);
|
||||
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, new Long(snapshotStoreRef.getPhysicalSize()));
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, snapshotStoreRef.getPhysicalSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1154,7 +1149,6 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
throw new InvalidParameterValueException("Backing up of snapshot is not supported by the zone of the volume. Snapshots can not be taken for multiple zones");
|
||||
}
|
||||
boolean isRootAdminCaller = _accountMgr.isRootAdmin(caller.getId());
|
||||
|
||||
if (hasZones) {
|
||||
for (Long zoneId : zoneIds) {
|
||||
getCheckedDestinationZoneForSnapshotCopy(zoneId, isRootAdminCaller);
|
||||
|
|
@ -1290,7 +1284,6 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
logger.debug("Acquired lock for creating snapshot policy [{}] for volume {}.", intervalType, volume);
|
||||
|
||||
|
||||
try {
|
||||
SnapshotPolicyVO policy = _snapshotPolicyDao.findOneByVolumeInterval(volumeId, intervalType);
|
||||
|
||||
|
|
@ -1497,7 +1490,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
|
||||
// List only future schedules, not past ones.
|
||||
List<SnapshotScheduleVO> snapshotSchedules = new ArrayList<SnapshotScheduleVO>();
|
||||
List<SnapshotScheduleVO> snapshotSchedules = new ArrayList<>();
|
||||
if (policyId == null) {
|
||||
List<SnapshotPolicyVO> policyInstances = listPoliciesforVolume(volumeId);
|
||||
for (SnapshotPolicyVO policyInstance : policyInstances) {
|
||||
|
|
@ -1631,7 +1624,6 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
Long snapshotId = payload.getSnapshotId();
|
||||
Account snapshotOwner = payload.getAccount();
|
||||
|
||||
SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotId, volume.getDataStore());
|
||||
StoragePool storagePool = _storagePoolDao.findById(volume.getPoolId());
|
||||
|
||||
|
|
@ -1697,7 +1689,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
ResourceType storeResourceType = dataStoreRole == DataStoreRole.Image ? ResourceType.secondary_storage : ResourceType.primary_storage;
|
||||
// Correct the resource count of snapshot in case of delta snapshots.
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), storeResourceType, new Long(volume.getSize() - snapshotStoreRef.getPhysicalSize()));
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), storeResourceType, volume.getSize() - snapshotStoreRef.getPhysicalSize());
|
||||
|
||||
if (!payload.getAsyncBackup()) {
|
||||
if (backupSnapToSecondary) {
|
||||
|
|
@ -1716,7 +1708,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
ResourceType storeResourceType = getStoreResourceType(volume.getDataCenterId(), payload.getLocationType());
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), storeResourceType, new Long(volume.getSize()));
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), storeResourceType, volume.getSize());
|
||||
throw cre;
|
||||
} catch (Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
|
@ -1724,7 +1716,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
ResourceType storeResourceType = getStoreResourceType(volume.getDataCenterId(), payload.getLocationType());
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), storeResourceType, new Long(volume.getSize()));
|
||||
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), storeResourceType, volume.getSize());
|
||||
throw new CloudRuntimeException("Failed to create snapshot", e);
|
||||
}
|
||||
return snapshot;
|
||||
|
|
@ -1934,7 +1926,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
|
||||
if (policyIds == null) {
|
||||
policyIds = new ArrayList<Long>();
|
||||
policyIds = new ArrayList<>();
|
||||
policyIds.add(policyId);
|
||||
} else if (policyIds.size() <= 0) {
|
||||
// Not even sure how this is even possible
|
||||
|
|
@ -2017,20 +2009,6 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
Type snapshotType = getSnapshotType(policyId);
|
||||
Account owner = _accountMgr.getAccount(volume.getAccountId());
|
||||
|
||||
ResourceType storeResourceType = getStoreResourceType(volume.getDataCenterId(), locationType);
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.snapshot);
|
||||
_resourceLimitMgr.checkResourceLimit(owner, storeResourceType, volume.getSize());
|
||||
} catch (ResourceAllocationException e) {
|
||||
if (snapshotType != Type.MANUAL) {
|
||||
String msg = String.format("Snapshot resource limit exceeded for account %s. Failed to create recurring snapshots", owner);
|
||||
logger.warn(msg);
|
||||
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, "Snapshot resource limit exceeded for account id : " + owner.getId()
|
||||
+ ". Failed to create recurring snapshots; please use updateResourceLimit to increase the limit");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Determine the name for this snapshot
|
||||
// Snapshot Name: VMInstancename + volumeName + timeString
|
||||
String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT);
|
||||
|
|
@ -2062,6 +2040,14 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
hypervisorType = volume.getHypervisorType();
|
||||
}
|
||||
|
||||
ResourceType storeResourceType = ResourceType.secondary_storage;
|
||||
if (!isBackupSnapshotToSecondaryForZone(volume.getDataCenterId()) ||
|
||||
Snapshot.LocationType.PRIMARY.equals(locationType)) {
|
||||
storeResourceType = ResourceType.primary_storage;
|
||||
}
|
||||
|
||||
try (CheckedReservation volumeSnapshotReservation = new CheckedReservation(owner, ResourceType.snapshot, null, null, 1L, reservationDao, _resourceLimitMgr);
|
||||
CheckedReservation storageReservation = new CheckedReservation(owner, storeResourceType, null, null, volume.getSize(), reservationDao, _resourceLimitMgr)) {
|
||||
SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), snapshotName,
|
||||
(short)snapshotType.ordinal(), snapshotType.name(), volume.getSize(), volume.getMinIops(), volume.getMaxIops(), hypervisorType, locationType);
|
||||
|
||||
|
|
@ -2073,6 +2059,14 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.snapshot);
|
||||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), storeResourceType, volume.getSize());
|
||||
return snapshot;
|
||||
} catch (ResourceAllocationException e) {
|
||||
if (snapshotType != Type.MANUAL) {
|
||||
String msg = String.format("Snapshot resource limit exceeded for account id : %s. Failed to create recurring snapshots", owner.getId());
|
||||
logger.warn(msg);
|
||||
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, msg + ". Please, use updateResourceLimit to increase the limit");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2122,57 +2116,61 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
@DB
|
||||
private boolean copySnapshotToZone(SnapshotDataStoreVO snapshotDataStoreVO, DataStore srcSecStore,
|
||||
DataCenterVO dstZone, DataStore dstSecStore, Account account, boolean kvmIncrementalSnapshot)
|
||||
DataCenterVO dstZone, DataStore dstSecStore, Account account, boolean kvmIncrementalSnapshot, boolean shouldCheckResourceLimits)
|
||||
throws ResourceAllocationException {
|
||||
final long snapshotId = snapshotDataStoreVO.getSnapshotId();
|
||||
final long dstZoneId = dstZone.getId();
|
||||
if (checkAndProcessSnapshotAlreadyExistInStore(snapshotId, dstSecStore)) {
|
||||
return true;
|
||||
}
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, snapshotDataStoreVO.getSize());
|
||||
// snapshotId may refer to ID of a removed parent snapshot
|
||||
SnapshotInfo snapshotOnSecondary = snapshotFactory.getSnapshot(snapshotId, srcSecStore);
|
||||
if (kvmIncrementalSnapshot) {
|
||||
snapshotOnSecondary = snapshotHelper.convertSnapshotIfNeeded(snapshotOnSecondary);
|
||||
}
|
||||
String copyUrl = null;
|
||||
try {
|
||||
AsyncCallFuture<CreateCmdResult> future = snapshotSrv.queryCopySnapshot(snapshotOnSecondary);
|
||||
CreateCmdResult result = future.get();
|
||||
if (!result.isFailed()) {
|
||||
copyUrl = result.getPath();
|
||||
// Resource limit checks are not performed here at the moment, but they were added in case this method is used
|
||||
// in the future to copy a standalone snapshot
|
||||
long requiredSecondaryStorageSpace = shouldCheckResourceLimits ? snapshotDataStoreVO.getSize() : 0L;
|
||||
try (CheckedReservation secondaryStorageReservation = new CheckedReservation(account, ResourceType.secondary_storage, null, null, null, requiredSecondaryStorageSpace, null, reservationDao, _resourceLimitMgr)) {
|
||||
// snapshotId may refer to ID of a removed parent snapshot
|
||||
SnapshotInfo snapshotOnSecondary = snapshotFactory.getSnapshot(snapshotId, srcSecStore);
|
||||
if (kvmIncrementalSnapshot) {
|
||||
snapshotOnSecondary = snapshotHelper.convertSnapshotIfNeeded(snapshotOnSecondary);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException | ResourceUnavailableException ex) {
|
||||
logger.error("Failed to prepare URL for copy for snapshot ID: {} on store: {}", snapshotId, srcSecStore, ex);
|
||||
}
|
||||
if (StringUtils.isEmpty(copyUrl)) {
|
||||
logger.error("Unable to prepare URL for copy for snapshot ID: {} on store: {}", snapshotId, srcSecStore);
|
||||
return false;
|
||||
}
|
||||
logger.debug(String.format("Copying snapshot ID: %d to destination zones using download URL: %s", snapshotId, copyUrl));
|
||||
try {
|
||||
AsyncCallFuture<SnapshotResult> future = snapshotSrv.copySnapshot(snapshotOnSecondary, copyUrl, dstSecStore);
|
||||
SnapshotResult result = future.get();
|
||||
if (result.isFailed()) {
|
||||
logger.debug("Copy snapshot ID: {} failed for image store {}: {}", snapshotId, dstSecStore, result.getResult());
|
||||
String copyUrl = null;
|
||||
try {
|
||||
AsyncCallFuture<CreateCmdResult> future = snapshotSrv.queryCopySnapshot(snapshotOnSecondary);
|
||||
CreateCmdResult result = future.get();
|
||||
if (!result.isFailed()) {
|
||||
copyUrl = result.getPath();
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException | ResourceUnavailableException ex) {
|
||||
logger.error("Failed to prepare URL for copy for snapshot ID: {} on store: {}", snapshotId, srcSecStore, ex);
|
||||
}
|
||||
if (StringUtils.isEmpty(copyUrl)) {
|
||||
logger.error("Unable to prepare URL for copy for snapshot ID: {} on store: {}", snapshotId, srcSecStore);
|
||||
return false;
|
||||
}
|
||||
snapshotZoneDao.addSnapshotToZone(snapshotId, dstZoneId);
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), ResourceType.secondary_storage, snapshotDataStoreVO.getSize());
|
||||
if (account.getId() != Account.ACCOUNT_ID_SYSTEM) {
|
||||
SnapshotVO snapshotVO = _snapshotDao.findByIdIncludingRemoved(snapshotId);
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_COPY, account.getId(), dstZoneId, snapshotId, null, null, null, snapshotVO.getSize(),
|
||||
snapshotVO.getSize(), snapshotVO.getClass().getName(), snapshotVO.getUuid());
|
||||
}
|
||||
if (kvmIncrementalSnapshot) {
|
||||
((ImageStoreEntity) srcSecStore).deleteExtractUrl(snapshotOnSecondary.getPath(), copyUrl, Upload.Type.SNAPSHOT);
|
||||
}
|
||||
logger.debug(String.format("Copying snapshot ID: %d to destination zones using download URL: %s", snapshotId, copyUrl));
|
||||
try {
|
||||
AsyncCallFuture<SnapshotResult> future = snapshotSrv.copySnapshot(snapshotOnSecondary, copyUrl, dstSecStore);
|
||||
SnapshotResult result = future.get();
|
||||
if (result.isFailed()) {
|
||||
logger.debug("Copy snapshot ID: {} failed for image store {}: {}", snapshotId, dstSecStore, result.getResult());
|
||||
return false;
|
||||
}
|
||||
snapshotZoneDao.addSnapshotToZone(snapshotId, dstZoneId);
|
||||
_resourceLimitMgr.incrementResourceCount(account.getId(), ResourceType.secondary_storage, snapshotDataStoreVO.getSize());
|
||||
if (account.getId() != Account.ACCOUNT_ID_SYSTEM) {
|
||||
SnapshotVO snapshotVO = _snapshotDao.findByIdIncludingRemoved(snapshotId);
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_COPY, account.getId(), dstZoneId, snapshotId, null, null, null, snapshotVO.getSize(),
|
||||
snapshotVO.getSize(), snapshotVO.getClass().getName(), snapshotVO.getUuid());
|
||||
}
|
||||
if (kvmIncrementalSnapshot) {
|
||||
((ImageStoreEntity) srcSecStore).deleteExtractUrl(snapshotOnSecondary.getPath(), copyUrl, Upload.Type.SNAPSHOT);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (InterruptedException | ExecutionException | ResourceUnavailableException ex) {
|
||||
logger.debug("Failed to copy snapshot ID: {} to image store: {}", snapshotId, dstSecStore);
|
||||
return true;
|
||||
} catch (InterruptedException | ExecutionException | ResourceUnavailableException ex) {
|
||||
logger.debug("Failed to copy snapshot ID: {} to image store: {}", snapshotId, dstSecStore);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@DB
|
||||
|
|
@ -2204,13 +2202,6 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
if (CollectionUtils.isEmpty(snapshotChain)) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, size);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("Unable to allocate secondary storage resources for snapshot chain for %s with size: %d", snapshotVO, size), e);
|
||||
return false;
|
||||
}
|
||||
Collections.reverse(snapshotChain);
|
||||
if (dstSecStore == null) {
|
||||
// find all eligible image stores for the destination zone
|
||||
List<DataStore> dstSecStores = dataStoreMgr.getImageStoresByScopeExcludingReadOnly(new ZoneScope(destZoneId));
|
||||
|
|
@ -2222,16 +2213,23 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
throw new StorageUnavailableException("Destination zone is not ready, no image store with free capacity", DataCenter.class, destZoneId);
|
||||
}
|
||||
}
|
||||
logger.debug("Copying snapshot chain for snapshot ID: {} on secondary store: {} of zone ID: {}", snapshotVO, dstSecStore, destZone);
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotChain) {
|
||||
if (!copySnapshotToZone(snapshotDataStoreVO, srcSecStore, destZone, dstSecStore, account, kvmIncrementalSnapshot)) {
|
||||
logger.error("Failed to copy snapshot: {} to zone: {} due to failure to copy snapshot ID: {} from snapshot chain",
|
||||
snapshotVO, destZone, snapshotDataStoreVO.getSnapshotId());
|
||||
return false;
|
||||
try (CheckedReservation secondaryStorageReservation = new CheckedReservation(account, ResourceType.secondary_storage, null, null, null, size, null, reservationDao, _resourceLimitMgr)) {
|
||||
logger.debug("Copying snapshot chain for snapshot ID: {} on secondary store: {} of zone ID: {}", snapshotVO, dstSecStore, destZone);
|
||||
Collections.reverse(snapshotChain);
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotChain) {
|
||||
if (!copySnapshotToZone(snapshotDataStoreVO, srcSecStore, destZone, dstSecStore, account, kvmIncrementalSnapshot, false)) {
|
||||
logger.error("Failed to copy snapshot: {} to zone: {} due to failure to copy snapshot ID: {} from snapshot chain",
|
||||
snapshotVO, destZone, snapshotDataStoreVO.getSnapshotId());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("Unable to allocate secondary storage resources for snapshot chain for %s with size: %d", snapshotVO, size), e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@DB
|
||||
private List<String> copySnapshotToZones(SnapshotVO snapshotVO, DataStore srcSecStore, List<DataCenterVO> dstZones) throws StorageUnavailableException, ResourceAllocationException {
|
||||
AccountVO account = _accountDao.findById(snapshotVO.getAccountId());
|
||||
|
|
|
|||
|
|
@ -34,10 +34,8 @@ import org.apache.cloudstack.annotation.AnnotationService;
|
|||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
|
||||
import org.apache.cloudstack.api.command.user.iso.GetUploadParamsForIsoCmd;
|
||||
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
|
||||
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
|
||||
import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplateCmd;
|
||||
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.direct.download.DirectDownloadManager;
|
||||
|
|
@ -197,19 +195,6 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
|||
profile.setSize(templateSize);
|
||||
}
|
||||
profile.setUrl(url);
|
||||
// Check that the resource limit for secondary storage won't be exceeded
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()),
|
||||
ResourceType.secondary_storage,
|
||||
UriUtils.getRemoteSize(url, followRedirects));
|
||||
return profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateProfile prepare(GetUploadParamsForIsoCmd cmd) throws ResourceAllocationException {
|
||||
TemplateProfile profile = super.prepare(cmd);
|
||||
|
||||
// Check that the resource limit for secondary storage won't be exceeded
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage);
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
|
@ -228,19 +213,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
|||
profile.setForCks(cmd.isForCks());
|
||||
}
|
||||
profile.setUrl(url);
|
||||
// Check that the resource limit for secondary storage won't be exceeded
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()),
|
||||
ResourceType.secondary_storage,
|
||||
UriUtils.getRemoteSize(url, followRedirects));
|
||||
return profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateProfile prepare(GetUploadParamsForTemplateCmd cmd) throws ResourceAllocationException {
|
||||
TemplateProfile profile = super.prepare(cmd);
|
||||
|
||||
// Check that the resource limit for secondary storage won't be exceeded
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage);
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +241,6 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
|||
persistDirectDownloadTemplate(template.getId(), profile.getSize());
|
||||
}
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
return template;
|
||||
}
|
||||
|
||||
|
|
@ -377,7 +349,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
|||
if(payloads.isEmpty()) {
|
||||
throw new CloudRuntimeException("unable to find zone or an image store with enough capacity");
|
||||
}
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
|
||||
return payloads;
|
||||
}
|
||||
});
|
||||
|
|
@ -396,13 +368,12 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
|||
CreateTemplateContext<TemplateApiResult> context) {
|
||||
TemplateApiResult result = callback.getResult();
|
||||
TemplateInfo template = context.template;
|
||||
VMTemplateVO tmplt = _tmpltDao.findById(template.getId());
|
||||
if (result.isSuccess()) {
|
||||
VMTemplateVO tmplt = _tmpltDao.findById(template.getId());
|
||||
// need to grant permission for public templates
|
||||
if (tmplt.isPublicTemplate()) {
|
||||
_messageBus.publish(_name, TemplateManager.MESSAGE_REGISTER_PUBLIC_TEMPLATE_EVENT, PublishScope.LOCAL, tmplt.getId());
|
||||
}
|
||||
long accountId = tmplt.getAccountId();
|
||||
if (template.getSize() != null) {
|
||||
// publish usage event
|
||||
String etype = EventTypes.EVENT_TEMPLATE_CREATE;
|
||||
|
|
@ -431,9 +402,13 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
|||
UsageEventUtils.publishUsageEvent(etype, template.getAccountId(), -1, template.getId(), template.getName(), null, null, physicalSize,
|
||||
template.getSize(), VirtualMachineTemplate.class.getName(), template.getUuid());
|
||||
}
|
||||
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.secondary_storage, template.getSize());
|
||||
}
|
||||
}
|
||||
if (tmplt != null) {
|
||||
long accountId = tmplt.getAccountId();
|
||||
Account account = _accountDao.findById(accountId);
|
||||
_resourceLimitMgr.recalculateResourceCount(accountId, account.getDomainId(), ResourceType.secondary_storage.getOrdinal());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
|
|||
Account account = _accountDao.findById(accountId);
|
||||
Domain domain = _domainDao.findById(account.getDomainId());
|
||||
|
||||
payload.setDefaultMaxSecondaryStorageInGB(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
|
||||
payload.setDefaultMaxSecondaryStorageInBytes(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
|
||||
payload.setAccountId(accountId);
|
||||
payload.setRemoteEndPoint(ep.getPublicAddr());
|
||||
payload.setRequiresHvm(template.requiresHvm());
|
||||
|
|
@ -363,8 +363,6 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
|
|||
throw new IllegalArgumentException("Unable to find user with id " + userId);
|
||||
}
|
||||
|
||||
_resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);
|
||||
|
||||
// If a zoneId is specified, make sure it is valid
|
||||
if (zoneIdList != null) {
|
||||
for (Long zoneId :zoneIdList) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.PublishScope;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.secstorage.dao.SecondaryStorageHeuristicDao;
|
||||
import org.apache.cloudstack.secstorage.heuristics.HeuristicType;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
|
|
@ -152,6 +153,7 @@ import com.cloud.hypervisor.HypervisorGuru;
|
|||
import com.cloud.hypervisor.HypervisorGuruManager;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.ImageStoreUploadMonitorImpl;
|
||||
|
|
@ -201,6 +203,7 @@ import com.cloud.utils.EncryptionUtil;
|
|||
import com.cloud.utils.EnumUtils;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.UriUtils;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
|
|
@ -302,29 +305,27 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
private VMTemplateDetailsDao _tmpltDetailsDao;
|
||||
@Inject
|
||||
private HypervisorGuruManager _hvGuruMgr;
|
||||
|
||||
private List<TemplateAdapter> _adapters;
|
||||
|
||||
ExecutorService _preloadExecutor;
|
||||
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
@Inject
|
||||
private StorageCacheManager cacheMgr;
|
||||
@Inject
|
||||
private EndPointSelector selector;
|
||||
|
||||
@Inject
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
@Inject
|
||||
VnfTemplateManager vnfTemplateManager;
|
||||
@Inject
|
||||
TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
|
||||
|
||||
@Inject
|
||||
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
|
||||
|
||||
@Inject
|
||||
private HeuristicRuleHelper heuristicRuleHelper;
|
||||
|
||||
private List<TemplateAdapter> _adapters;
|
||||
|
||||
ExecutorService _preloadExecutor;
|
||||
|
||||
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
||||
|
||||
private TemplateAdapter getAdapter(HypervisorType type) {
|
||||
|
|
@ -353,14 +354,30 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
@ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "Creating ISO")
|
||||
public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException {
|
||||
TemplateAdapter adapter = getAdapter(HypervisorType.None);
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
VMTemplateVO template = adapter.create(profile);
|
||||
Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
|
||||
|
||||
if (template != null) {
|
||||
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
|
||||
return template;
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to create ISO");
|
||||
// Secondary storage resource count is not incremented for BareMetalTemplateAdapter
|
||||
// Note: checking the file size before registering will require the Management Server host to have access to the Internet and a DNS server
|
||||
// If it does not, UriUtils.getRemoteSize will return 0L.
|
||||
long secondaryStorageUsage = adapter instanceof HypervisorTemplateAdapter && !cmd.isDirectDownload() ?
|
||||
UriUtils.getRemoteSize(cmd.getUrl(), StorageManager.DataStoreDownloadFollowRedirects.value()) : 0L;
|
||||
|
||||
try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr);
|
||||
CheckedReservation secondaryStorageReservation = new CheckedReservation(owner, ResourceType.secondary_storage, null, null, secondaryStorageUsage, reservationDao, _resourceLimitMgr)) {
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
VMTemplateVO template = adapter.create(profile);
|
||||
|
||||
// Secondary storage resource usage will be incremented in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
if (secondaryStorageUsage > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, secondaryStorageUsage);
|
||||
}
|
||||
if (template != null) {
|
||||
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
|
||||
return template;
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to create ISO");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -380,17 +397,32 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
}
|
||||
|
||||
TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
VMTemplateVO template = adapter.create(profile);
|
||||
Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
|
||||
|
||||
if (template != null) {
|
||||
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
|
||||
if (cmd instanceof RegisterVnfTemplateCmd) {
|
||||
vnfTemplateManager.persistVnfTemplate(template.getId(), (RegisterVnfTemplateCmd) cmd);
|
||||
long secondaryStorageUsage = adapter instanceof HypervisorTemplateAdapter && !cmd.isDirectDownload() ?
|
||||
UriUtils.getRemoteSize(cmd.getUrl(), StorageManager.DataStoreDownloadFollowRedirects.value()) : 0L;
|
||||
|
||||
try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr);
|
||||
CheckedReservation secondaryStorageReservation = new CheckedReservation(owner, ResourceType.secondary_storage, null, null, secondaryStorageUsage, reservationDao, _resourceLimitMgr)) {
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
VMTemplateVO template = adapter.create(profile);
|
||||
|
||||
// Secondary storage resource usage will be recalculated in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
|
||||
// for HypervisorTemplateAdapter
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
if (secondaryStorageUsage > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, secondaryStorageUsage);
|
||||
}
|
||||
|
||||
if (template != null) {
|
||||
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
|
||||
if (cmd instanceof RegisterVnfTemplateCmd) {
|
||||
vnfTemplateManager.persistVnfTemplate(template.getId(), (RegisterVnfTemplateCmd) cmd);
|
||||
}
|
||||
return template;
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to create a Template");
|
||||
}
|
||||
return template;
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to create a Template");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -455,17 +487,35 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "Creating post upload ISO")
|
||||
public GetUploadParamsResponse registerIsoForPostUpload(GetUploadParamsForIsoCmd cmd) throws ResourceAllocationException, MalformedURLException {
|
||||
TemplateAdapter adapter = getAdapter(HypervisorType.None);
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
return registerPostUploadInternal(adapter, profile);
|
||||
Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
|
||||
|
||||
try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
TemplateAdapter adapter = getAdapter(HypervisorType.None);
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
|
||||
GetUploadParamsResponse response = registerPostUploadInternal(adapter, profile);
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "Creating post upload Template")
|
||||
public GetUploadParamsResponse registerTemplateForPostUpload(GetUploadParamsForTemplateCmd cmd) throws ResourceAllocationException, MalformedURLException {
|
||||
TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
return registerPostUploadInternal(adapter, profile);
|
||||
Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
|
||||
|
||||
try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
|
||||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
|
||||
GetUploadParamsResponse response = registerPostUploadInternal(adapter, profile);
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -527,7 +577,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
|
||||
VMTemplateVO vmTemplate = _tmpltDao.findById(templateId);
|
||||
if (vmTemplate == null) {
|
||||
throw new InvalidParameterValueException("Unable to find Template id=" + templateId);
|
||||
throw new InvalidParameterValueException("Unable to find Template ID=" + templateId);
|
||||
}
|
||||
|
||||
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, vmTemplate);
|
||||
|
|
@ -832,9 +882,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
// find the size of the template to be copied
|
||||
TemplateDataStoreVO srcTmpltStore = _tmplStoreDao.findByStoreTemplate(srcSecStore.getId(), tmpltId);
|
||||
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.template);
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, new Long(srcTmpltStore.getSize()).longValue());
|
||||
|
||||
// Event details
|
||||
String copyEventType;
|
||||
if (template.getFormat().equals(ImageFormat.ISO)) {
|
||||
|
|
@ -897,9 +944,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception ex) {
|
||||
logger.debug("Failed to copy Template to image store:{} ,will try next one", dstSecStore, ex);
|
||||
}
|
||||
|
|
@ -981,21 +1025,21 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
// sync template from cache store to region store if it is not there, for cases where we are going to migrate existing NFS to S3.
|
||||
_tmpltSvr.syncTemplateToRegionStore(template, srcSecStore);
|
||||
}
|
||||
|
||||
AccountVO templateOwner = _accountDao.findById(template.getAccountId());
|
||||
|
||||
for (Long destZoneId : destZoneIds) {
|
||||
DataStore dstSecStore = getImageStore(destZoneId, templateId);
|
||||
if (dstSecStore != null) {
|
||||
logger.debug("There is Template {} in secondary storage {} in zone {} , don't need to copy", template, dstSecStore, dataCenterVOs.get(destZoneId));
|
||||
continue;
|
||||
}
|
||||
if (!copy(userId, template, srcSecStore, dataCenterVOs.get(destZoneId))) {
|
||||
failedZones.add(dataCenterVOs.get(destZoneId).getName());
|
||||
}
|
||||
else{
|
||||
if (template.getSize() != null) {
|
||||
// increase resource count
|
||||
long accountId = template.getAccountId();
|
||||
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.secondary_storage, template.getSize());
|
||||
try (CheckedReservation secondaryStorageReservation = new CheckedReservation(templateOwner, ResourceType.secondary_storage, null, null, template.getSize(), reservationDao, _resourceLimitMgr)) {
|
||||
if (!copy(userId, template, srcSecStore, dataCenterVOs.get(destZoneId))) {
|
||||
failedZones.add(dataCenterVOs.get(destZoneId).getName());
|
||||
continue;
|
||||
}
|
||||
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage, template.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1018,9 +1062,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
|
||||
AccountVO account = _accountDao.findById(template.getAccountId());
|
||||
|
||||
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.template);
|
||||
|
||||
try {
|
||||
_tmpltDao.addTemplateToZone(template, dstZoneId);
|
||||
return true;
|
||||
|
|
@ -1839,7 +1880,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
// decrement resource count
|
||||
if (accountId != null) {
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, new Long(volumeFinal != null ? volumeFinal.getSize()
|
||||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, (long)(volumeFinal != null ? volumeFinal.getSize()
|
||||
: snapshotFinal.getSize()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1990,107 +2031,106 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
}
|
||||
}
|
||||
|
||||
_resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);
|
||||
_resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.secondary_storage, new Long(volume != null ? volume.getSize() : snapshot.getSize()).longValue());
|
||||
long templateSize = volume != null ? volume.getSize() : snapshot.getSize();
|
||||
try (CheckedReservation templateReservation = new CheckedReservation(templateOwner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr);
|
||||
CheckedReservation secondaryStorageReservation = new CheckedReservation(templateOwner, ResourceType.secondary_storage, null, null, templateSize, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
if (!isAdmin || featured == null) {
|
||||
featured = Boolean.FALSE;
|
||||
}
|
||||
Long guestOSId = cmd.getOsTypeId();
|
||||
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
|
||||
if (guestOS == null) {
|
||||
throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist.");
|
||||
}
|
||||
|
||||
Long nextTemplateId = _tmpltDao.getNextInSequence(Long.class, "id");
|
||||
String description = cmd.getDisplayText();
|
||||
boolean isExtractable = false;
|
||||
Long sourceTemplateId = null;
|
||||
if (volume != null) {
|
||||
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
|
||||
isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
|
||||
if (template != null) {
|
||||
arch = template.getArch();
|
||||
if (!isAdmin || featured == null) {
|
||||
featured = Boolean.FALSE;
|
||||
}
|
||||
if (volume.getIsoId() != null && volume.getIsoId() != 0) {
|
||||
sourceTemplateId = volume.getIsoId();
|
||||
} else if (volume.getTemplateId() != null) {
|
||||
sourceTemplateId = volume.getTemplateId();
|
||||
Long guestOSId = cmd.getOsTypeId();
|
||||
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
|
||||
if (guestOS == null) {
|
||||
throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist.");
|
||||
}
|
||||
}
|
||||
String templateTag = cmd.getTemplateTag();
|
||||
if (templateTag != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Adding Template tag: " + templateTag);
|
||||
|
||||
Long nextTemplateId = _tmpltDao.getNextInSequence(Long.class, "id");
|
||||
String description = cmd.getDisplayText();
|
||||
boolean isExtractable = false;
|
||||
Long sourceTemplateId = null;
|
||||
if (volume != null) {
|
||||
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
|
||||
isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
|
||||
if (template != null) {
|
||||
arch = template.getArch();
|
||||
}
|
||||
if (volume.getIsoId() != null && volume.getIsoId() != 0) {
|
||||
sourceTemplateId = volume.getIsoId();
|
||||
} else if (volume.getTemplateId() != null) {
|
||||
sourceTemplateId = volume.getTemplateId();
|
||||
}
|
||||
}
|
||||
}
|
||||
privateTemplate = new VMTemplateVO(nextTemplateId, name, ImageFormat.RAW, isPublic, featured, isExtractable,
|
||||
TemplateType.USER, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description,
|
||||
passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails(), sshKeyEnabledValue, isDynamicScalingEnabled, false, false, arch, null);
|
||||
|
||||
if (sourceTemplateId != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("This Template is getting created from other Template, setting source Template ID to: " + sourceTemplateId);
|
||||
String templateTag = cmd.getTemplateTag();
|
||||
if (templateTag != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Adding Template tag: " + templateTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// for region wide storage, set cross zones flag
|
||||
List<ImageStoreVO> stores = _imgStoreDao.findRegionImageStores();
|
||||
if (!CollectionUtils.isEmpty(stores)) {
|
||||
privateTemplate.setCrossZones(true);
|
||||
}
|
||||
|
||||
privateTemplate.setSourceTemplateId(sourceTemplateId);
|
||||
|
||||
VMTemplateVO template = _tmpltDao.persist(privateTemplate);
|
||||
// Increment the number of templates
|
||||
if (template != null) {
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
privateTemplate = new VMTemplateVO(nextTemplateId, name, ImageFormat.RAW, isPublic, featured, isExtractable,
|
||||
TemplateType.USER, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description,
|
||||
passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails(), sshKeyEnabledValue, isDynamicScalingEnabled, false, false, arch, null);
|
||||
|
||||
if (sourceTemplateId != null) {
|
||||
VMTemplateVO sourceTemplate = _tmpltDao.findById(sourceTemplateId);
|
||||
if (sourceTemplate != null && sourceTemplate.getDetails() != null) {
|
||||
details.putAll(sourceTemplate.getDetails());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("This Template is getting created from other Template, setting source Template ID to: " + sourceTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
if (volume != null) {
|
||||
Long vmId = volume.getInstanceId();
|
||||
if (vmId != null) {
|
||||
UserVmVO userVm = _userVmDao.findById(vmId);
|
||||
if (userVm != null) {
|
||||
_userVmDao.loadDetails(userVm);
|
||||
Map<String, String> vmDetails = userVm.getDetails();
|
||||
vmDetails = vmDetails.entrySet()
|
||||
.stream()
|
||||
.filter(map -> map.getValue() != null)
|
||||
.collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
|
||||
details.putAll(vmDetails);
|
||||
// for region wide storage, set cross zones flag
|
||||
List<ImageStoreVO> stores = _imgStoreDao.findRegionImageStores();
|
||||
if (!CollectionUtils.isEmpty(stores)) {
|
||||
privateTemplate.setCrossZones(true);
|
||||
}
|
||||
|
||||
privateTemplate.setSourceTemplateId(sourceTemplateId);
|
||||
|
||||
VMTemplateVO template = _tmpltDao.persist(privateTemplate);
|
||||
// Increment the number of templates
|
||||
if (template != null) {
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
|
||||
if (sourceTemplateId != null) {
|
||||
VMTemplateVO sourceTemplate = _tmpltDao.findById(sourceTemplateId);
|
||||
if (sourceTemplate != null && sourceTemplate.getDetails() != null) {
|
||||
details.putAll(sourceTemplate.getDetails());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cmd.getDetails() != null) {
|
||||
details.remove(VmDetailConstants.ENCRYPTED_PASSWORD); // new password will be generated during vm deployment from password enabled template
|
||||
details.putAll(cmd.getDetails());
|
||||
}
|
||||
if (!details.isEmpty()) {
|
||||
privateTemplate.setDetails(details);
|
||||
_tmpltDao.saveDetails(privateTemplate);
|
||||
|
||||
if (volume != null) {
|
||||
Long vmId = volume.getInstanceId();
|
||||
if (vmId != null) {
|
||||
UserVmVO userVm = _userVmDao.findById(vmId);
|
||||
if (userVm != null) {
|
||||
_userVmDao.loadDetails(userVm);
|
||||
Map<String, String> vmDetails = userVm.getDetails();
|
||||
vmDetails = vmDetails.entrySet()
|
||||
.stream()
|
||||
.filter(map -> map.getValue() != null)
|
||||
.collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
|
||||
details.putAll(vmDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cmd.getDetails() != null) {
|
||||
details.remove(VmDetailConstants.ENCRYPTED_PASSWORD); // new password will be generated during vm deployment from password enabled template
|
||||
details.putAll(cmd.getDetails());
|
||||
}
|
||||
if (!details.isEmpty()) {
|
||||
privateTemplate.setDetails(details);
|
||||
_tmpltDao.saveDetails(privateTemplate);
|
||||
}
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
|
||||
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage, templateSize);
|
||||
}
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
|
||||
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage,
|
||||
new Long(volume != null ? volume.getSize() : snapshot.getSize()));
|
||||
if (template != null) {
|
||||
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
|
||||
return template;
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to create a Template");
|
||||
}
|
||||
}
|
||||
|
||||
if (template != null) {
|
||||
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
|
||||
return template;
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to create a Template");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2262,7 +2302,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
templateTag == null &&
|
||||
forCks == null &&
|
||||
arch == null &&
|
||||
(!cleanupDetails && details == null) //update details in every case except this one
|
||||
(! cleanupDetails && details == null) // update details in every case except this one
|
||||
);
|
||||
if (!updateNeeded) {
|
||||
return template;
|
||||
|
|
@ -2457,7 +2497,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
if (MapUtils.isEmpty(details)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String bootMode = details.get(ApiConstants.BootType.UEFI.toString());
|
||||
if (bootMode == null) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -60,8 +60,7 @@ import javax.naming.ConfigurationException;
|
|||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import com.cloud.storage.SnapshotPolicyVO;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
|
|
@ -128,6 +127,7 @@ 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;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
|
||||
import org.apache.cloudstack.extension.ExtensionHelper;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
|
|
@ -137,6 +137,7 @@ import org.apache.cloudstack.framework.messagebus.PublishScope;
|
|||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
|
|
@ -266,12 +267,12 @@ import com.cloud.hypervisor.kvm.dpdk.DpdkHelper;
|
|||
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
|
||||
import com.cloud.network.IpAddressManager;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkService;
|
||||
import com.cloud.network.Network.GuestType;
|
||||
import com.cloud.network.Network.IpAddresses;
|
||||
import com.cloud.network.Network.Provider;
|
||||
import com.cloud.network.Network.Service;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.NetworkService;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.network.PhysicalNetwork;
|
||||
import com.cloud.network.as.AutoScaleManager;
|
||||
|
|
@ -325,6 +326,7 @@ import com.cloud.storage.GuestOSCategoryVO;
|
|||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotPolicyVO;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
|
|
@ -343,6 +345,7 @@ import com.cloud.storage.dao.DiskOfferingDao;
|
|||
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
|
|
@ -615,29 +618,26 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
SnapshotPolicyDao snapshotPolicyDao;
|
||||
@Inject
|
||||
BackupScheduleDao backupScheduleDao;
|
||||
|
||||
@Inject
|
||||
private StatsCollector statsCollector;
|
||||
@Inject
|
||||
private UserDataDao userDataDao;
|
||||
|
||||
@Inject
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
|
||||
@Inject
|
||||
private AutoScaleManager autoScaleManager;
|
||||
|
||||
@Inject
|
||||
VMScheduleManager vmScheduleManager;
|
||||
@Inject
|
||||
NsxProviderDao nsxProviderDao;
|
||||
|
||||
@Inject
|
||||
NetworkService networkService;
|
||||
|
||||
@Inject
|
||||
SnapshotDataFactory snapshotDataFactory;
|
||||
|
||||
@Inject
|
||||
ExtensionHelper extensionHelper;
|
||||
|
||||
private ScheduledExecutorService _executor = null;
|
||||
private ScheduledExecutorService _vmIpFetchExecutor = null;
|
||||
private int _expungeInterval;
|
||||
|
|
@ -682,19 +682,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
@Inject
|
||||
VnfTemplateManager vnfTemplateManager;
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchWaitInterval = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmip.retrieval.interval", "180",
|
||||
private static final ConfigKey<Integer> 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);
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchTrialMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10",
|
||||
private static final ConfigKey<Integer> VmIpFetchTrialMax = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10",
|
||||
"The max number of retrieval times for shared network vm dhcp ip fetch, in case of failures", true);
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchThreadPoolMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10",
|
||||
private static final ConfigKey<Integer> VmIpFetchThreadPoolMax = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10",
|
||||
"number of threads for fetching vms ip address", true);
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchTaskWorkers = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10",
|
||||
private static final ConfigKey<Integer> VmIpFetchTaskWorkers = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10",
|
||||
"number of worker threads for vm ip fetch task ", true);
|
||||
|
||||
private static final ConfigKey<Boolean> AllowDeployVmIfGivenHostFails = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false",
|
||||
private static final ConfigKey<Boolean> 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);
|
||||
|
||||
private static final ConfigKey<String> KvmAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
|
|
@ -706,7 +706,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
private static final ConfigKey<String> VmwareAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
"allow.additional.vm.configuration.list.vmware", "Advanced", "", "Comma separated list of allowed additional configuration options.", true, ConfigKey.Scope.Global, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
|
||||
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
|
||||
"On destroy, force-stop takes this value ", true);
|
||||
|
||||
@Override
|
||||
|
|
@ -1192,7 +1192,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
|
||||
//List all networks of vm
|
||||
List<Long> vmNetworks = _vmNetworkMapDao.getNetworks(vmId);
|
||||
List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
|
||||
List<DomainRouterVO> routers = new ArrayList<>();
|
||||
//List the stopped routers
|
||||
for (long vmNetworkId : vmNetworks) {
|
||||
List<DomainRouterVO> router = _routerDao.listStopped(vmNetworkId);
|
||||
|
|
@ -1393,9 +1393,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
Account owner = _accountMgr.getActiveAccountById(vmInstance.getAccountId());
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vmInstance.getTemplateId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
if (!VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
|
||||
_resourceLimitMgr.checkVmResourceLimitsForServiceOfferingChange(owner, vmInstance.isDisplay(), (long) currentCpu, (long) newCpu,
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template);
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template, reservations);
|
||||
}
|
||||
|
||||
// Check that the specified service offering ID is valid
|
||||
|
|
@ -1418,6 +1421,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
return _vmDao.findById(vmInstance.getId());
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2111,9 +2117,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vmInstance.getTemplateId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
// Check resource limits
|
||||
_resourceLimitMgr.checkVmResourceLimitsForServiceOfferingChange(owner, vmInstance.isDisplay(), (long) currentCpu, (long) newCpu,
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template);
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template, reservations);
|
||||
|
||||
// Dynamically upgrade the running vms
|
||||
boolean success = false;
|
||||
|
|
@ -2185,6 +2193,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
return success;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateDiskOfferingChecks(ServiceOfferingVO currentServiceOffering, ServiceOfferingVO newServiceOffering) {
|
||||
|
|
@ -2370,10 +2382,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
// First check that the maximum number of UserVMs, CPU and Memory limit for the given
|
||||
// accountId will not be exceeded
|
||||
if (!VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), serviceOffering, template);
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), serviceOffering, template, reservations);
|
||||
}
|
||||
|
||||
_haMgr.cancelDestroy(vm, vm.getHostId());
|
||||
|
|
@ -2398,6 +2412,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
//Update Resource Count for the given account
|
||||
resourceCountIncrement(account.getId(), vm.isDisplayVm(), serviceOffering, template);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2832,53 +2850,25 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
long currentCpu = currentServiceOffering.getCpu();
|
||||
long currentMemory = currentServiceOffering.getRamSize();
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vmInstance.getTemplateId());
|
||||
Long currentGpu = currentServiceOffering.getGpuCount() != null ? Long.valueOf(currentServiceOffering.getGpuCount()) : 0L;
|
||||
Long newGpu = svcOffering.getGpuCount() != null ? Long.valueOf(svcOffering.getGpuCount()) : 0L;
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkVmLimits(owner, vmInstance, svcOffering, template, newCpu, currentCpu, newMemory, currentMemory, newGpu, currentGpu);
|
||||
_resourceLimitMgr.checkVmResourceLimitsForServiceOfferingChange(owner, vmInstance.isDisplay(), currentCpu, newCpu,
|
||||
currentMemory, newMemory, currentServiceOffering, svcOffering, template, reservations);
|
||||
if (newCpu > currentCpu) {
|
||||
_resourceLimitMgr.incrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newCpu - currentCpu);
|
||||
} else if (newCpu > 0 && currentCpu > newCpu){
|
||||
_resourceLimitMgr.decrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentCpu - newCpu);
|
||||
}
|
||||
if (newMemory > currentMemory) {
|
||||
_resourceLimitMgr.incrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newMemory - currentMemory);
|
||||
} else if (newMemory > 0 && currentMemory > newMemory){
|
||||
_resourceLimitMgr.decrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentMemory - newMemory);
|
||||
}
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("Failed to updated VM due to: %s", e.getLocalizedMessage()));
|
||||
throw new InvalidParameterValueException(e.getLocalizedMessage());
|
||||
}
|
||||
adjustVmLimits(owner, vmInstance, svcOffering, template, newCpu, currentCpu, newMemory, currentMemory, newGpu, currentGpu);
|
||||
}
|
||||
|
||||
private void checkVmLimits(Account owner, UserVmVO vmInstance, ServiceOfferingVO svcOffering,
|
||||
VMTemplateVO template, Long newCpu, Long currentCpu, Long newMemory, Long currentMemory,
|
||||
Long newGpu, Long currentGpu
|
||||
) throws ResourceAllocationException {
|
||||
if (newCpu > currentCpu) {
|
||||
_resourceLimitMgr.checkVmCpuResourceLimit(owner, vmInstance.isDisplay(), svcOffering,
|
||||
template, newCpu - currentCpu);
|
||||
}
|
||||
if (newMemory > currentMemory) {
|
||||
_resourceLimitMgr.checkVmMemoryResourceLimit(owner, vmInstance.isDisplay(), svcOffering,
|
||||
template, newMemory - currentMemory);
|
||||
}
|
||||
if (newGpu > currentGpu) {
|
||||
_resourceLimitMgr.checkVmGpuResourceLimit(owner, vmInstance.isDisplay(), svcOffering,
|
||||
template, newGpu - currentGpu);
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustVmLimits(Account owner, UserVmVO vmInstance, ServiceOfferingVO svcOffering,
|
||||
VMTemplateVO template, Long newCpu, Long currentCpu, Long newMemory, Long currentMemory,
|
||||
Long newGpu, Long currentGpu
|
||||
) {
|
||||
if (newCpu > currentCpu) {
|
||||
_resourceLimitMgr.incrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newCpu - currentCpu);
|
||||
} else if (newCpu > 0 && currentCpu > newCpu) {
|
||||
_resourceLimitMgr.decrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentCpu - newCpu);
|
||||
}
|
||||
if (newMemory > currentMemory) {
|
||||
_resourceLimitMgr.incrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newMemory - currentMemory);
|
||||
} else if (newMemory > 0 && currentMemory > newMemory) {
|
||||
_resourceLimitMgr.decrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentMemory - newMemory);
|
||||
}
|
||||
if (newGpu > currentGpu) {
|
||||
_resourceLimitMgr.incrementVmGpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newGpu - currentGpu);
|
||||
} else if (newGpu > 0 && currentGpu > newGpu) {
|
||||
_resourceLimitMgr.decrementVmGpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentGpu - newGpu);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2927,6 +2917,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
.map(item -> (item).trim())
|
||||
.collect(Collectors.toList());
|
||||
userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings);
|
||||
if (template != null && template.getExtensionId() != null) {
|
||||
userDenyListedSettings.addAll(extensionHelper.getExtensionReservedResourceDetails(
|
||||
template.getExtensionId()));
|
||||
}
|
||||
|
||||
final List<String> userReadOnlySettings = Stream.of(QueryService.UserVMReadOnlyDetails.value().split(","))
|
||||
.map(item -> (item).trim())
|
||||
.collect(Collectors.toList());
|
||||
|
|
@ -3234,7 +3229,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
// Verify that vm's hostName is unique
|
||||
|
||||
List<NetworkVO> vmNtwks = new ArrayList<NetworkVO>(nics.size());
|
||||
List<NetworkVO> vmNtwks = new ArrayList<>(nics.size());
|
||||
for (Nic nic : nics) {
|
||||
vmNtwks.add(_networkDao.findById(nic.getNetworkId()));
|
||||
}
|
||||
|
|
@ -3815,7 +3810,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
|
||||
List<NetworkVO> networkList = new ArrayList<>();
|
||||
|
||||
// Verify that caller can perform actions in behalf of vm owner
|
||||
_accountMgr.checkAccess(caller, null, true, owner);
|
||||
|
|
@ -3841,7 +3836,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
//add the default securityGroup only if no security group is specified
|
||||
if (securityGroupIdList == null || securityGroupIdList.isEmpty()) {
|
||||
if (securityGroupIdList == null) {
|
||||
securityGroupIdList = new ArrayList<Long>();
|
||||
securityGroupIdList = new ArrayList<>();
|
||||
}
|
||||
SecurityGroup defaultGroup = _securityGroupMgr.getDefaultSecurityGroup(owner.getId());
|
||||
if (defaultGroup != null) {
|
||||
|
|
@ -3873,7 +3868,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, Map<String, String> userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType, Volume volume, Snapshot snapshot) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
|
||||
List<NetworkVO> networkList = new ArrayList<>();
|
||||
boolean isSecurityGroupEnabledNetworkUsed = false;
|
||||
boolean isVmWare = (template.getHypervisorType() == HypervisorType.VMware || (hypervisor != null && hypervisor == HypervisorType.VMware));
|
||||
|
||||
|
|
@ -3951,7 +3946,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
//add the default securityGroup only if no security group is specified
|
||||
if (securityGroupIdList == null || securityGroupIdList.isEmpty()) {
|
||||
if (securityGroupIdList == null) {
|
||||
securityGroupIdList = new ArrayList<Long>();
|
||||
securityGroupIdList = new ArrayList<>();
|
||||
}
|
||||
|
||||
SecurityGroup defaultGroup = _securityGroupMgr.getDefaultSecurityGroup(owner.getId());
|
||||
|
|
@ -3986,7 +3981,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
|
||||
List<NetworkVO> networkList = new ArrayList<>();
|
||||
|
||||
// Verify that caller can perform actions in behalf of vm owner
|
||||
_accountMgr.checkAccess(caller, null, true, owner);
|
||||
|
|
@ -4385,7 +4380,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new InvalidParameterValueException(String.format("Invalid disk offering %s specified for datadisk Template %s. Disk offering size should be greater than or equal to the Template size", dataDiskOffering, dataDiskTemplate));
|
||||
}
|
||||
_templateDao.loadDetails(dataDiskTemplate);
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, dataDiskOffering.getDiskSize(), dataDiskOffering);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4941,10 +4935,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.debug("Allocating in the DB for vm");
|
||||
DataCenterDeployment plan = new DataCenterDeployment(zone.getId());
|
||||
|
||||
List<String> computeTags = new ArrayList<String>();
|
||||
List<String> computeTags = new ArrayList<>();
|
||||
computeTags.add(offering.getHostTag());
|
||||
|
||||
List<String> rootDiskTags = new ArrayList<String>();
|
||||
List<String> rootDiskTags = new ArrayList<>();
|
||||
DiskOfferingVO rootDiskOfferingVO = _diskOfferingDao.findById(rootDiskOfferingId);
|
||||
rootDiskTags.add(rootDiskOfferingVO.getTags());
|
||||
|
||||
|
|
@ -5158,7 +5152,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
VirtualMachine.class.getName(), vm.getUuid(), isDisplay);
|
||||
}
|
||||
else {
|
||||
Map<String, String> customParameters = new HashMap<String, String>();
|
||||
Map<String, String> customParameters = new HashMap<>();
|
||||
customParameters.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
|
||||
customParameters.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
|
||||
customParameters.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
|
||||
|
|
@ -5175,7 +5169,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
logger.debug("Collect vm network statistics from host before stopping Vm");
|
||||
long hostId = userVm.getHostId();
|
||||
List<String> vmNames = new ArrayList<String>();
|
||||
List<String> vmNames = new ArrayList<>();
|
||||
vmNames.add(userVm.getInstanceName());
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
Account account = _accountMgr.getAccount(userVm.getAccountId());
|
||||
|
|
@ -5735,13 +5729,135 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return startVirtualMachine(vmId, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, true);
|
||||
}
|
||||
|
||||
private Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachineUnchecked(UserVmVO vm, VMTemplateVO template, Long podId,
|
||||
Long clusterId, Long hostId, @NotNull Map<VirtualMachineProfile.Param, Object> additionalParams, String deploymentPlannerToUse,
|
||||
boolean isExplicitHost, boolean isRootAdmin) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||
|
||||
// check if vm is security group enabled
|
||||
if (_securityGroupMgr.isVmSecurityGroupEnabled(vm.getId()) && _securityGroupMgr.getSecurityGroupsForVm(vm.getId()).isEmpty()
|
||||
&& !_securityGroupMgr.isVmMappedToDefaultSecurityGroup(vm.getId()) && _networkModel.canAddDefaultSecurityGroup()) {
|
||||
// if vm is not mapped to security group, create a mapping
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Vm " + vm + " is security group enabled, but not mapped to default security group; creating the mapping automatically");
|
||||
}
|
||||
|
||||
SecurityGroup defaultSecurityGroup = _securityGroupMgr.getDefaultSecurityGroup(vm.getAccountId());
|
||||
if (defaultSecurityGroup != null) {
|
||||
List<Long> groupList = new ArrayList<>();
|
||||
groupList.add(defaultSecurityGroup.getId());
|
||||
_securityGroupMgr.addInstanceToGroups(vm, groupList);
|
||||
}
|
||||
}
|
||||
|
||||
// Choose deployment planner
|
||||
// Host takes 1st preference, Cluster takes 2nd preference and Pod takes 3rd
|
||||
// Default behaviour is invoked when host, cluster or pod are not specified
|
||||
Pod destinationPod = getDestinationPod(podId, isRootAdmin);
|
||||
Cluster destinationCluster = getDestinationCluster(clusterId, isRootAdmin);
|
||||
HostVO destinationHost = getDestinationHost(hostId, isRootAdmin, isExplicitHost);
|
||||
DataCenterDeployment plan = null;
|
||||
boolean deployOnGivenHost = false;
|
||||
if (destinationHost != null) {
|
||||
logger.debug("Destination Host to deploy the VM is specified, specifying a deployment plan to deploy the VM");
|
||||
_hostDao.loadHostTags(destinationHost);
|
||||
validateStrictHostTagCheck(vm, destinationHost);
|
||||
|
||||
final ServiceOfferingVO offering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = _capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(destinationHost, offering, false);
|
||||
if (!cpuCapabilityAndCapacity.first() || !cpuCapabilityAndCapacity.second()) {
|
||||
String errorMsg;
|
||||
if (!cpuCapabilityAndCapacity.first()) {
|
||||
errorMsg = String.format("Cannot deploy the VM to specified host %s, requested CPU and speed is more than the host capability", destinationHost);
|
||||
} else {
|
||||
errorMsg = String.format("Cannot deploy the VM to specified host %s, host does not have enough free CPU or RAM, please check the logs", destinationHost);
|
||||
}
|
||||
logger.info(errorMsg);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
throw new InvalidParameterValueException(errorMsg);
|
||||
}
|
||||
} else {
|
||||
plan = new DataCenterDeployment(vm.getDataCenterId(), destinationHost.getPodId(), destinationHost.getClusterId(), destinationHost.getId(), null, null);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
deployOnGivenHost = true;
|
||||
}
|
||||
}
|
||||
} else if (destinationCluster != null) {
|
||||
logger.debug("Destination Cluster to deploy the VM is specified, specifying a deployment plan to deploy the VM");
|
||||
plan = new DataCenterDeployment(vm.getDataCenterId(), destinationCluster.getPodId(), destinationCluster.getId(), null, null, null);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
deployOnGivenHost = true;
|
||||
}
|
||||
} else if (destinationPod != null) {
|
||||
logger.debug("Destination Pod to deploy the VM is specified, specifying a deployment plan to deploy the VM");
|
||||
plan = new DataCenterDeployment(vm.getDataCenterId(), destinationPod.getId(), null, null, null, null);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
deployOnGivenHost = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Set parameters
|
||||
Map<VirtualMachineProfile.Param, Object> params = null;
|
||||
if (vm.isUpdateParameters()) {
|
||||
_vmDao.loadDetails(vm);
|
||||
String password = getCurrentVmPasswordOrDefineNewPassword(String.valueOf(additionalParams.getOrDefault(VirtualMachineProfile.Param.VmPassword, "")), vm, template);
|
||||
if (!validPassword(password)) {
|
||||
throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
|
||||
}
|
||||
// Check if an SSH key pair was selected for the instance and if so
|
||||
// use it to encrypt & save the vm password
|
||||
encryptAndStorePassword(vm, password);
|
||||
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.VmPassword, password);
|
||||
}
|
||||
|
||||
if (additionalParams.containsKey(VirtualMachineProfile.Param.BootIntoSetup)) {
|
||||
if (!HypervisorType.VMware.equals(vm.getHypervisorType())) {
|
||||
throw new InvalidParameterValueException(ApiConstants.BOOT_INTO_SETUP + " makes no sense for " + vm.getHypervisorType());
|
||||
}
|
||||
Object paramValue = additionalParams.get(VirtualMachineProfile.Param.BootIntoSetup);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("It was specified whether to enter setup mode: " + paramValue.toString());
|
||||
}
|
||||
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.BootIntoSetup, paramValue);
|
||||
}
|
||||
|
||||
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
|
||||
|
||||
DeploymentPlanner planner = null;
|
||||
if (deploymentPlannerToUse != null) {
|
||||
// if set to null, the deployment planner would be later figured out either from global config var, or from
|
||||
// the service offering
|
||||
planner = _planningMgr.getDeploymentPlannerByName(deploymentPlannerToUse);
|
||||
if (planner == null) {
|
||||
throw new InvalidParameterValueException("Can't find a planner by name " + deploymentPlannerToUse);
|
||||
}
|
||||
}
|
||||
vmEntity.setParamsToEntity(additionalParams);
|
||||
|
||||
UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
|
||||
String reservationId = vmEntity.reserve(planner, plan, new ExcludeList(), Long.toString(callerUser.getId()));
|
||||
vmEntity.deploy(reservationId, Long.toString(callerUser.getId()), params, deployOnGivenHost);
|
||||
|
||||
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(vm, params);
|
||||
if (vm.isUpdateParameters()) {
|
||||
// this value is not being sent to the backend; need only for api
|
||||
// display purposes
|
||||
if (template.isEnablePassword()) {
|
||||
if (vm.getDetail(VmDetailConstants.PASSWORD) != null) {
|
||||
vmInstanceDetailsDao.removeDetail(vm.getId(), VmDetailConstants.PASSWORD);
|
||||
}
|
||||
vm.setUpdateParameters(false);
|
||||
_vmDao.update(vm.getId(), vm);
|
||||
}
|
||||
}
|
||||
return vmParamPair;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long podId, Long clusterId, Long hostId,
|
||||
@NotNull Map<VirtualMachineProfile.Param, Object> additionalParams, String deploymentPlannerToUse, boolean isExplicitHost)
|
||||
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException {
|
||||
// Input validation
|
||||
final Account callerAccount = CallContext.current().getCallingAccount();
|
||||
UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
|
||||
|
||||
// if account is removed, return error
|
||||
if (callerAccount == null || callerAccount.getRemoved() != null) {
|
||||
|
|
@ -5769,133 +5885,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (owner.getState() == Account.State.DISABLED) {
|
||||
throw new PermissionDeniedException(String.format("The owner of %s is disabled: %s", vm, owner));
|
||||
}
|
||||
boolean isRootAdmin = _accountService.isRootAdmin(callerAccount.getId());
|
||||
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
if (VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
|
||||
// check if account/domain is with in resource limits to start a new vm
|
||||
ServiceOfferingVO offering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
resourceLimitService.checkVmResourceLimit(owner, vm.isDisplayVm(), offering, template);
|
||||
List<String> resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(offering, template);
|
||||
try (CheckedReservation vmReservation = new CheckedReservation(owner, ResourceType.user_vm, resourceLimitHostTags, 1l, reservationDao, resourceLimitService);
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, ResourceType.cpu, resourceLimitHostTags, Long.valueOf(offering.getCpu()), reservationDao, resourceLimitService);
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, resourceLimitHostTags, Long.valueOf(offering.getRamSize()), reservationDao, resourceLimitService);
|
||||
) {
|
||||
return startVirtualMachineUnchecked(vm, template, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, isExplicitHost, isRootAdmin);
|
||||
}
|
||||
} else {
|
||||
return startVirtualMachineUnchecked(vm, template, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, isExplicitHost, isRootAdmin);
|
||||
}
|
||||
// check if vm is security group enabled
|
||||
if (_securityGroupMgr.isVmSecurityGroupEnabled(vmId) && _securityGroupMgr.getSecurityGroupsForVm(vmId).isEmpty()
|
||||
&& !_securityGroupMgr.isVmMappedToDefaultSecurityGroup(vmId) && _networkModel.canAddDefaultSecurityGroup()) {
|
||||
// if vm is not mapped to security group, create a mapping
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Vm " + vm + " is security group enabled, but not mapped to default security group; creating the mapping automatically");
|
||||
}
|
||||
|
||||
SecurityGroup defaultSecurityGroup = _securityGroupMgr.getDefaultSecurityGroup(vm.getAccountId());
|
||||
if (defaultSecurityGroup != null) {
|
||||
List<Long> groupList = new ArrayList<Long>();
|
||||
groupList.add(defaultSecurityGroup.getId());
|
||||
_securityGroupMgr.addInstanceToGroups(vm, groupList);
|
||||
}
|
||||
}
|
||||
// Choose deployment planner
|
||||
// Host takes 1st preference, Cluster takes 2nd preference and Pod takes 3rd
|
||||
// Default behaviour is invoked when host, cluster or pod are not specified
|
||||
boolean isRootAdmin = _accountService.isRootAdmin(callerAccount.getId());
|
||||
Pod destinationPod = getDestinationPod(podId, isRootAdmin);
|
||||
Cluster destinationCluster = getDestinationCluster(clusterId, isRootAdmin);
|
||||
HostVO destinationHost = getDestinationHost(hostId, isRootAdmin, isExplicitHost);
|
||||
DataCenterDeployment plan = null;
|
||||
boolean deployOnGivenHost = false;
|
||||
if (destinationHost != null) {
|
||||
logger.debug("Destination Host to deploy the VM is specified, specifying a deployment plan to deploy the VM");
|
||||
_hostDao.loadHostTags(destinationHost);
|
||||
validateStrictHostTagCheck(vm, destinationHost);
|
||||
|
||||
final ServiceOfferingVO offering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = _capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(destinationHost, offering, false);
|
||||
if (!cpuCapabilityAndCapacity.first() || !cpuCapabilityAndCapacity.second()) {
|
||||
String errorMsg;
|
||||
if (!cpuCapabilityAndCapacity.first()) {
|
||||
errorMsg = String.format("Cannot deploy the VM to specified host %s, requested CPU and speed is more than the host capability", destinationHost);
|
||||
} else {
|
||||
errorMsg = String.format("Cannot deploy the VM to specified host %s, host does not have enough free CPU or RAM, please check the logs", destinationHost);
|
||||
}
|
||||
logger.info(errorMsg);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
throw new InvalidParameterValueException(errorMsg);
|
||||
};
|
||||
} else {
|
||||
plan = new DataCenterDeployment(vm.getDataCenterId(), destinationHost.getPodId(), destinationHost.getClusterId(), destinationHost.getId(), null, null);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
deployOnGivenHost = true;
|
||||
}
|
||||
}
|
||||
} else if (destinationCluster != null) {
|
||||
logger.debug("Destination Cluster to deploy the VM is specified, specifying a deployment plan to deploy the VM");
|
||||
plan = new DataCenterDeployment(vm.getDataCenterId(), destinationCluster.getPodId(), destinationCluster.getId(), null, null, null);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
deployOnGivenHost = true;
|
||||
}
|
||||
} else if (destinationPod != null) {
|
||||
logger.debug("Destination Pod to deploy the VM is specified, specifying a deployment plan to deploy the VM");
|
||||
plan = new DataCenterDeployment(vm.getDataCenterId(), destinationPod.getId(), null, null, null, null);
|
||||
if (!AllowDeployVmIfGivenHostFails.value()) {
|
||||
deployOnGivenHost = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Set parameters
|
||||
Map<VirtualMachineProfile.Param, Object> params = null;
|
||||
if (vm.isUpdateParameters()) {
|
||||
_vmDao.loadDetails(vm);
|
||||
|
||||
String password = getCurrentVmPasswordOrDefineNewPassword(String.valueOf(additionalParams.getOrDefault(VirtualMachineProfile.Param.VmPassword, "")), vm, template);
|
||||
|
||||
if (!validPassword(password)) {
|
||||
throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
|
||||
}
|
||||
|
||||
// Check if an SSH key pair was selected for the instance and if so
|
||||
// use it to encrypt & save the vm password
|
||||
encryptAndStorePassword(vm, password);
|
||||
|
||||
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.VmPassword, password);
|
||||
}
|
||||
|
||||
if (additionalParams.containsKey(VirtualMachineProfile.Param.BootIntoSetup)) {
|
||||
if (! HypervisorType.VMware.equals(vm.getHypervisorType())) {
|
||||
throw new InvalidParameterValueException(ApiConstants.BOOT_INTO_SETUP + " makes no sense for " + vm.getHypervisorType());
|
||||
}
|
||||
Object paramValue = additionalParams.get(VirtualMachineProfile.Param.BootIntoSetup);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("It was specified whether to enter setup mode: " + paramValue.toString());
|
||||
}
|
||||
params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.BootIntoSetup, paramValue);
|
||||
}
|
||||
|
||||
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
|
||||
|
||||
DeploymentPlanner planner = null;
|
||||
if (deploymentPlannerToUse != null) {
|
||||
// if set to null, the deployment planner would be later figured out either from global config var, or from
|
||||
// the service offering
|
||||
planner = _planningMgr.getDeploymentPlannerByName(deploymentPlannerToUse);
|
||||
if (planner == null) {
|
||||
throw new InvalidParameterValueException("Can't find a planner by name " + deploymentPlannerToUse);
|
||||
}
|
||||
}
|
||||
vmEntity.setParamsToEntity(additionalParams);
|
||||
|
||||
String reservationId = vmEntity.reserve(planner, plan, new ExcludeList(), Long.toString(callerUser.getId()));
|
||||
vmEntity.deploy(reservationId, Long.toString(callerUser.getId()), params, deployOnGivenHost);
|
||||
|
||||
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(vm, params);
|
||||
if (vm != null && vm.isUpdateParameters()) {
|
||||
// this value is not being sent to the backend; need only for api
|
||||
// display purposes
|
||||
if (template.isEnablePassword()) {
|
||||
if (vm.getDetail(VmDetailConstants.PASSWORD) != null) {
|
||||
vmInstanceDetailsDao.removeDetail(vm.getId(), VmDetailConstants.PASSWORD);
|
||||
}
|
||||
vm.setUpdateParameters(false);
|
||||
_vmDao.update(vm.getId(), vm);
|
||||
}
|
||||
}
|
||||
|
||||
return vmParamPair;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6074,7 +6078,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return;
|
||||
}
|
||||
long hostId = userVm.getHostId();
|
||||
List<String> vmNames = new ArrayList<String>();
|
||||
List<String> vmNames = new ArrayList<>();
|
||||
vmNames.add(userVm.getInstanceName());
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
Account account = _accountMgr.getAccount(userVm.getAccountId());
|
||||
|
|
@ -6939,7 +6943,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
//transform group names to ids here
|
||||
if (cmd.getSecurityGroupNameList() != null) {
|
||||
List<Long> securityGroupIds = new ArrayList<Long>();
|
||||
List<Long> securityGroupIds = new ArrayList<>();
|
||||
for (String groupName : cmd.getSecurityGroupNameList()) {
|
||||
SecurityGroup sg = _securityGroupMgr.getSecurityGroup(groupName, cmd.getEntityOwnerId());
|
||||
if (sg == null) {
|
||||
|
|
@ -7724,7 +7728,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
private Map<Long, Long> getVolumePoolMappingForMigrateVmWithStorage(VMInstanceVO vm, Map<String, String> volumeToPool) {
|
||||
Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
|
||||
Map<Long, Long> volToPoolObjectMap = new HashMap<>();
|
||||
|
||||
List<VolumeVO> vmVolumes = getVmVolumesForMigrateVmWithStorage(vm);
|
||||
|
||||
|
|
@ -7868,38 +7872,29 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return findMigratedVm(vm.getId(), vm.getType());
|
||||
}
|
||||
|
||||
protected void checkVolumesLimits(Account account, List<VolumeVO> volumes) throws ResourceAllocationException {
|
||||
Long totalVolumes = 0L;
|
||||
Long totalVolumesSize = 0L;
|
||||
protected void checkVolumesLimits(Account account, List<VolumeVO> volumes, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
Map<Long, List<String>> diskOfferingTagsMap = new HashMap<>();
|
||||
Map<String, Long> tagVolumeCountMap = new HashMap<>();
|
||||
Map<String, Long> tagSizeMap = new HashMap<>();
|
||||
|
||||
for (VolumeVO volume : volumes) {
|
||||
if (!volume.isDisplay()) {
|
||||
continue;
|
||||
}
|
||||
totalVolumes++;
|
||||
totalVolumesSize += volume.getSize();
|
||||
if (!diskOfferingTagsMap.containsKey(volume.getDiskOfferingId())) {
|
||||
diskOfferingTagsMap.put(volume.getDiskOfferingId(), _resourceLimitMgr.getResourceLimitStorageTags(
|
||||
_diskOfferingDao.findById(volume.getDiskOfferingId())));
|
||||
|
||||
Long diskOfferingId = volume.getDiskOfferingId();
|
||||
if (!diskOfferingTagsMap.containsKey(diskOfferingId)) {
|
||||
DiskOffering diskOffering = _diskOfferingDao.findById(diskOfferingId);
|
||||
List<String> tagsForDiskOffering = _resourceLimitMgr.getResourceLimitStorageTags(diskOffering);
|
||||
diskOfferingTagsMap.put(diskOfferingId, tagsForDiskOffering);
|
||||
}
|
||||
List<String> tags = diskOfferingTagsMap.get(volume.getDiskOfferingId());
|
||||
for (String tag : tags) {
|
||||
if (tagVolumeCountMap.containsKey(tag)) {
|
||||
tagVolumeCountMap.put(tag, tagVolumeCountMap.get(tag) + 1);
|
||||
tagSizeMap.put(tag, tagSizeMap.get(tag) + volume.getSize());
|
||||
} else {
|
||||
tagVolumeCountMap.put(tag, 1L);
|
||||
tagSizeMap.put(tag, volume.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.volume, totalVolumes);
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.primary_storage, totalVolumesSize);
|
||||
for (String tag : tagVolumeCountMap.keySet()) {
|
||||
resourceLimitService.checkResourceLimitWithTag(account, ResourceType.volume, tag, tagVolumeCountMap.get(tag));
|
||||
resourceLimitService.checkResourceLimitWithTag(account, ResourceType.primary_storage, tag, tagSizeMap.get(tag));
|
||||
|
||||
List<String> tags = diskOfferingTagsMap.get(diskOfferingId);
|
||||
|
||||
CheckedReservation volumeReservation = new CheckedReservation(account, ResourceType.volume, tags, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
long size = ObjectUtils.defaultIfNull(volume.getSize(), 0L);
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(account, ResourceType.primary_storage, tags, size, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7941,14 +7936,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
final ServiceOfferingVO offering = serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId());
|
||||
VirtualMachineTemplate template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
|
||||
verifyResourceLimitsForAccountAndStorage(newAccount, vm, offering, volumes, template);
|
||||
|
||||
validateIfNewOwnerHasAccessToTemplate(vm, newAccount, template);
|
||||
|
||||
DomainVO domain = _domainDao.findById(domainId);
|
||||
logger.trace("Verifying if the new account [{}] has access to the specified domain [{}].", newAccount, domain);
|
||||
_accountMgr.checkAccess(newAccount, domain);
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
verifyResourceLimitsForAccountAndStorage(newAccount, vm, offering, volumes, template, reservations);
|
||||
|
||||
Network newNetwork = ensureDestinationNetwork(cmd, vm, newAccount);
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
|
|
@ -7965,6 +7962,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw e;
|
||||
}
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
logger.info("VM [{}] now belongs to account [{}].", vm.getInstanceName(), newAccountName);
|
||||
return vm;
|
||||
}
|
||||
|
|
@ -8035,18 +8036,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
* @param volumes The volumes whose total size can exceed resource limits.
|
||||
* @throws ResourceAllocationException
|
||||
*/
|
||||
protected void verifyResourceLimitsForAccountAndStorage(Account account, UserVmVO vm, ServiceOfferingVO offering, List<VolumeVO> volumes, VirtualMachineTemplate template)
|
||||
protected void verifyResourceLimitsForAccountAndStorage(Account account, UserVmVO vm, ServiceOfferingVO offering, List<VolumeVO> volumes, VirtualMachineTemplate template, List<Reserver> reservations)
|
||||
throws ResourceAllocationException {
|
||||
|
||||
logger.trace("Verifying if CPU and RAM for VM [{}] do not exceed account [{}] limit.", vm, account);
|
||||
|
||||
if (!countOnlyRunningVmsInResourceLimitation()) {
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), offering, template);
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), offering, template, reservations);
|
||||
}
|
||||
|
||||
logger.trace("Verifying if volume size for VM [{}] does not exceed account [{}] limit.", vm, account);
|
||||
|
||||
checkVolumesLimits(account, volumes);
|
||||
checkVolumesLimits(account, volumes, reservations);
|
||||
}
|
||||
|
||||
protected boolean countOnlyRunningVmsInResourceLimitation() {
|
||||
|
|
@ -8678,10 +8679,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
/**
|
||||
* Attempts to create a network suitable for the creation of a VM ({@link NetworkOrchestrationService#createGuestNetwork}).
|
||||
* If no physical network is found, throws a {@link InvalidParameterValueException}.
|
||||
* @param caller The account which calls for the network creation.
|
||||
* @param newAccount The account to which the network will be created.
|
||||
* @param zone The zone where the network will be created.
|
||||
* @param requiredOffering The network offering required to create the network.
|
||||
* @return The NetworkVO for the network created.
|
||||
* @throws InsufficientCapacityException
|
||||
* @throws ResourceAllocationException
|
||||
|
|
@ -8945,12 +8944,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
VMTemplateVO template = getRestoreVirtualMachineTemplate(caller, newTemplateId, rootVols, vm);
|
||||
DiskOffering diskOffering = rootDiskOfferingId != null ? _diskOfferingDao.findById(rootDiskOfferingId) : null;
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkRestoreVmFromTemplate(vm, template, rootVols, diskOffering, details);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("Failed to restore VM {} due to {}", vm, e.getMessage(), e);
|
||||
throw new CloudRuntimeException("Failed to restore VM " + vm.getUuid() + " due to " + e.getMessage(), e);
|
||||
}
|
||||
checkRestoreVmFromTemplate(vm, template, rootVols, diskOffering, details, reservations);
|
||||
|
||||
if (needRestart) {
|
||||
try {
|
||||
|
|
@ -9097,6 +9094,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.debug("Restore VM {} done successfully", vm);
|
||||
return vm;
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("Failed to restore VM {} due to {}", vm, e.getMessage(), e);
|
||||
throw new CloudRuntimeException("Failed to restore VM " + vm.getUuid() + " due to " + e.getMessage(), e);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
Long getRootVolumeSizeForVmRestore(Volume vol, VMTemplateVO template, UserVmVO userVm, DiskOffering diskOffering, Map<String, String> details, boolean update) {
|
||||
|
|
@ -9196,7 +9199,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
* @param template template
|
||||
* @throws InvalidParameterValueException if restore is not possible
|
||||
*/
|
||||
private void checkRestoreVmFromTemplate(UserVmVO vm, VMTemplateVO template, List<VolumeVO> rootVolumes, DiskOffering newDiskOffering, Map<String,String> details) throws ResourceAllocationException {
|
||||
private void checkRestoreVmFromTemplate(UserVmVO vm, VMTemplateVO template, List<VolumeVO> rootVolumes, DiskOffering newDiskOffering, Map<String,String> details, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
TemplateDataStoreVO tmplStore;
|
||||
if (!template.isDirectDownload()) {
|
||||
tmplStore = _templateStoreDao.findByTemplateZoneReady(template.getId(), vm.getDataCenterId());
|
||||
|
|
@ -9214,7 +9217,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (vm.getTemplateId() != template.getId()) {
|
||||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
VMTemplateVO currentTemplate = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
_resourceLimitMgr.checkVmResourceLimitsForTemplateChange(owner, vm.isDisplay(), serviceOffering, currentTemplate, template);
|
||||
_resourceLimitMgr.checkVmResourceLimitsForTemplateChange(owner, vm.isDisplay(), serviceOffering, currentTemplate, template, reservations);
|
||||
}
|
||||
|
||||
for (Volume vol : rootVolumes) {
|
||||
|
|
@ -9225,7 +9228,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (newDiskOffering != null || !vol.getSize().equals(newSize)) {
|
||||
DiskOffering currentOffering = _diskOfferingDao.findById(vol.getDiskOfferingId());
|
||||
_resourceLimitMgr.checkVolumeResourceLimitForDiskOfferingChange(owner, vol.isDisplay(),
|
||||
vol.getSize(), newSize, currentOffering, newDiskOffering);
|
||||
vol.getSize(), newSize, currentOffering, newDiskOffering, reservations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -448,7 +448,6 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
* Create, persist and return vm snapshot for userVmVo with given parameters.
|
||||
* Persistence and support for custom service offerings are done on the same transaction
|
||||
* @param userVmVo user vm
|
||||
* @param vmId vm id
|
||||
* @param vsDescription vm description
|
||||
* @param vmSnapshotName vm snapshot name
|
||||
* @param vsDisplayName vm snapshot display name
|
||||
|
|
@ -815,37 +814,43 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* If snapshot was taken with a different service offering than actual used in vm, should change it back to it
|
||||
* @param userVm vm to change service offering (if necessary)
|
||||
* If snapshot was taken with a different service offering than actual used in vm, should change it back to it.
|
||||
* We also call <code>changeUserVmServiceOffering</code> in case the service offering is dynamic in order to
|
||||
* perform resource limit validation, as the amount of CPUs or memory may have been changed.
|
||||
* @param vmSnapshotVo vm snapshot
|
||||
*/
|
||||
protected void updateUserVmServiceOffering(UserVm userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
if (vmSnapshotVo.getServiceOfferingId() != userVm.getServiceOfferingId()) {
|
||||
changeUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
return;
|
||||
}
|
||||
ServiceOfferingVO serviceOffering = _serviceOfferingDao.findById(userVm.getServiceOfferingId());
|
||||
if (serviceOffering.isDynamic()) {
|
||||
changeUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user vm details as a map
|
||||
* @param userVm user vm
|
||||
* @param vmSnapshotVo snapshot to get the details from
|
||||
* @return map
|
||||
*/
|
||||
protected Map<String, String> getVmMapDetails(UserVm userVm) {
|
||||
List<VMInstanceDetailVO> userVmDetails = _vmInstanceDetailsDao.listDetails(userVm.getId());
|
||||
protected Map<String, String> getVmMapDetails(VMSnapshotVO vmSnapshotVo) {
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = _vmSnapshotDetailsDao.listDetails(vmSnapshotVo.getId());
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
for (VMInstanceDetailVO detail : userVmDetails) {
|
||||
for (VMSnapshotDetailsVO detail : vmSnapshotDetails) {
|
||||
details.put(detail.getName(), detail.getValue());
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update service offering on {@link userVm} to the one specified in {@link vmSnapshotVo}
|
||||
* Update service offering on {code}userVm{code} to the one specified in {code}vmSnapshotVo{code}
|
||||
* @param userVm user vm to be updated
|
||||
* @param vmSnapshotVo vm snapshot
|
||||
*/
|
||||
protected void changeUserVmServiceOffering(UserVm userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
Map<String, String> vmDetails = getVmMapDetails(userVm);
|
||||
Map<String, String> vmDetails = getVmMapDetails(vmSnapshotVo);
|
||||
boolean result = upgradeUserVmServiceOffering(userVm, vmSnapshotVo.getServiceOfferingId(), vmDetails);
|
||||
if (! result){
|
||||
throw new CloudRuntimeException("Instance Snapshot reverting failed because the Instance service offering couldn't be changed to the one used when Snapshot was taken");
|
||||
|
|
@ -854,8 +859,8 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* Upgrade virtual machine {@linkplain vmId} to new service offering {@linkplain serviceOfferingId}
|
||||
* @param vmId vm id
|
||||
* Upgrade virtual machine {code}vm{code} to new service offering {code}serviceOfferingId{code}
|
||||
* @param vm vm
|
||||
* @param serviceOfferingId service offering id
|
||||
* @param details vm details
|
||||
* @return if operation was successful
|
||||
|
|
@ -1293,7 +1298,7 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
public Pair<JobInfo.Status, String> orchestrateCreateVMSnapshot(VmWorkCreateVMSnapshot work) throws Exception {
|
||||
VMSnapshot snapshot = orchestrateCreateVMSnapshot(work.getVmId(), work.getVmSnapshotId(), work.isQuiesceVm());
|
||||
return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
|
||||
_jobMgr.marshallResultObject(new Long(snapshot.getId())));
|
||||
_jobMgr.marshallResultObject(Long.valueOf(snapshot.getId())));
|
||||
}
|
||||
|
||||
@ReflectionUse
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
|||
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
|
||||
import org.apache.cloudstack.poll.BackgroundPollManager;
|
||||
import org.apache.cloudstack.poll.BackgroundPollTask;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
|
@ -85,6 +86,8 @@ import org.apache.commons.lang.math.NumberUtils;
|
|||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.amazonaws.util.CollectionUtils;
|
||||
import com.cloud.alert.AlertManager;
|
||||
|
|
@ -119,6 +122,7 @@ import com.cloud.network.dao.NetworkDao;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
|
|
@ -170,8 +174,6 @@ import com.cloud.vm.dao.VMInstanceDetailsDao;
|
|||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
||||
|
||||
|
|
@ -237,6 +239,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
private AlertManager alertManager;
|
||||
@Inject
|
||||
private GuestOSDao _guestOSDao;
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
|
||||
private AsyncJobDispatcher asyncJobDispatcher;
|
||||
private Timer backupTimer;
|
||||
|
|
@ -790,14 +794,6 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
Long backupScheduleId = getBackupScheduleId(job);
|
||||
boolean isScheduledBackup = backupScheduleId != null;
|
||||
Account owner = accountManager.getAccount(vm.getAccountId());
|
||||
try {
|
||||
resourceLimitMgr.checkResourceLimit(owner, Resource.ResourceType.backup);
|
||||
} catch (ResourceAllocationException e) {
|
||||
if (isScheduledBackup) {
|
||||
sendExceededBackupLimitAlert(owner.getUuid(), Resource.ResourceType.backup);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
Long backupSize = 0L;
|
||||
for (final Volume volume: volumeDao.findByInstance(vmId)) {
|
||||
|
|
@ -809,42 +805,57 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
backupSize += volumeSize;
|
||||
}
|
||||
}
|
||||
try {
|
||||
resourceLimitMgr.checkResourceLimit(owner, Resource.ResourceType.backup_storage, backupSize);
|
||||
} catch (ResourceAllocationException e) {
|
||||
if (isScheduledBackup) {
|
||||
sendExceededBackupLimitAlert(owner.getUuid(), Resource.ResourceType.backup_storage);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
ActionEventUtils.onStartedActionEvent(User.UID_SYSTEM, vm.getAccountId(),
|
||||
EventTypes.EVENT_VM_BACKUP_CREATE, "creating backup for VM ID:" + vm.getUuid(),
|
||||
vmId, ApiCommandResourceType.VirtualMachine.toString(),
|
||||
true, 0);
|
||||
|
||||
Pair<Boolean, Backup> result = backupProvider.takeBackup(vm, cmd.getQuiesceVM());
|
||||
if (!result.first()) {
|
||||
throw new CloudRuntimeException("Failed to create VM backup");
|
||||
}
|
||||
Backup backup = result.second();
|
||||
if (backup != null) {
|
||||
BackupVO vmBackup = backupDao.findById(result.second().getId());
|
||||
vmBackup.setBackupScheduleId(backupScheduleId);
|
||||
if (cmd.getName() != null) {
|
||||
vmBackup.setName(cmd.getName());
|
||||
}
|
||||
vmBackup.setDescription(cmd.getDescription());
|
||||
backupDao.update(vmBackup.getId(), vmBackup);
|
||||
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup);
|
||||
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup_storage, backup.getSize());
|
||||
}
|
||||
createCheckedBackup(cmd, owner, isScheduledBackup, backupSize, vm, vmId, backupProvider, backupScheduleId);
|
||||
if (isScheduledBackup) {
|
||||
deleteOldestBackupFromScheduleIfRequired(vmId, backupScheduleId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createCheckedBackup(CreateBackupCmd cmd, Account owner, boolean isScheduledBackup, Long backupSize,
|
||||
VMInstanceVO vm, Long vmId, BackupProvider backupProvider, Long backupScheduleId)
|
||||
throws ResourceAllocationException {
|
||||
try (CheckedReservation backupReservation = new CheckedReservation(owner, Resource.ResourceType.backup,
|
||||
1L, reservationDao, resourceLimitMgr);
|
||||
CheckedReservation backupStorageReservation = new CheckedReservation(owner,
|
||||
Resource.ResourceType.backup_storage, backupSize, reservationDao, resourceLimitMgr)) {
|
||||
|
||||
ActionEventUtils.onStartedActionEvent(User.UID_SYSTEM, vm.getAccountId(),
|
||||
EventTypes.EVENT_VM_BACKUP_CREATE, "creating backup for VM ID:" + vm.getUuid(),
|
||||
vmId, ApiCommandResourceType.VirtualMachine.toString(),
|
||||
true, 0);
|
||||
|
||||
Pair<Boolean, Backup> result = backupProvider.takeBackup(vm, cmd.getQuiesceVM());
|
||||
if (!result.first()) {
|
||||
throw new CloudRuntimeException("Failed to create VM backup");
|
||||
}
|
||||
Backup backup = result.second();
|
||||
if (backup != null) {
|
||||
BackupVO vmBackup = backupDao.findById(result.second().getId());
|
||||
vmBackup.setBackupScheduleId(backupScheduleId);
|
||||
if (cmd.getName() != null) {
|
||||
vmBackup.setName(cmd.getName());
|
||||
}
|
||||
vmBackup.setDescription(cmd.getDescription());
|
||||
backupDao.update(vmBackup.getId(), vmBackup);
|
||||
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup);
|
||||
resourceLimitMgr.incrementResourceCount(vm.getAccountId(), Resource.ResourceType.backup_storage, backup.getSize());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof ResourceAllocationException) {
|
||||
ResourceAllocationException rae = (ResourceAllocationException)e;
|
||||
if (isScheduledBackup && (Resource.ResourceType.backup.equals(rae.getResourceType()) ||
|
||||
Resource.ResourceType.backup_storage.equals(rae.getResourceType()))) {
|
||||
sendExceededBackupLimitAlert(owner.getUuid(), rae.getResourceType());
|
||||
}
|
||||
throw rae;
|
||||
} else if (e instanceof CloudRuntimeException) {
|
||||
throw (CloudRuntimeException)e;
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to create backup for VM with ID: " + vm.getUuid(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an alert when the backup limit has been exceeded for a given account.
|
||||
*
|
||||
|
|
@ -971,7 +982,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
sb.and("backupOfferingId", sb.entity().getBackupOfferingId(), SearchCriteria.Op.EQ);
|
||||
|
||||
if (keyword != null) {
|
||||
sb.or().op("keywordName", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and().op("keywordName", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
SearchBuilder<VMInstanceVO> vmSearch = vmInstanceDao.createSearchBuilder();
|
||||
sb.join("vmSearch", vmSearch, sb.entity().getVmId(), vmSearch.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
sb.or("vmSearch", "keywordVmName", vmSearch.entity().getHostName(), SearchCriteria.Op.LIKE);
|
||||
|
|
@ -1538,19 +1549,35 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
throw new CloudRuntimeException(String.format("Backup offering with ID [%s] does not exist.", backup.getBackupOfferingId()));
|
||||
}
|
||||
final BackupProvider backupProvider = getBackupProvider(backup.getZoneId());
|
||||
boolean result = backupProvider.deleteBackup(backup, forced);
|
||||
if (result) {
|
||||
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup);
|
||||
Long backupSize = backup.getSize() != null ? backup.getSize() : 0L;
|
||||
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup_storage, backupSize);
|
||||
if (backupDao.remove(backup.getId())) {
|
||||
checkAndGenerateUsageForLastBackupDeletedAfterOfferingRemove(vm, backup);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return deleteCheckedBackup(forced, backupProvider, backup, vm);
|
||||
}
|
||||
|
||||
private boolean deleteCheckedBackup(Boolean forced, BackupProvider backupProvider, BackupVO backup, VMInstanceVO vm) {
|
||||
Account owner = accountManager.getAccount(backup.getAccountId());
|
||||
long backupSize = backup.getSize() != null ? backup.getSize() : 0L;
|
||||
try (CheckedReservation backupReservation = new CheckedReservation(owner, Resource.ResourceType.backup,
|
||||
backup.getId(), null, -1L, reservationDao, resourceLimitMgr);
|
||||
CheckedReservation backupStorageReservation = new CheckedReservation(owner,
|
||||
Resource.ResourceType.backup_storage, backup.getId(), null, -1 * backupSize,
|
||||
reservationDao, resourceLimitMgr)) {
|
||||
boolean result = backupProvider.deleteBackup(backup, forced);
|
||||
if (result) {
|
||||
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup);
|
||||
resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup_storage, backupSize);
|
||||
if (backupDao.remove(backup.getId())) {
|
||||
checkAndGenerateUsageForLastBackupDeletedAfterOfferingRemove(vm, backup);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to delete the backup");
|
||||
} catch (Exception e) {
|
||||
if (e instanceof CloudRuntimeException) {
|
||||
throw (CloudRuntimeException) e;
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to delete the backup due to: " + e.getMessage(), e);
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to delete the backup");
|
||||
}
|
||||
|
||||
private void checkForPendingBackupJobs(final BackupVO backup) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,27 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.storage.object;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.bucket.CreateBucketCmd;
|
||||
import org.apache.cloudstack.api.command.user.bucket.UpdateBucketCmd;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.amazonaws.services.s3.internal.BucketNameUtils;
|
||||
import com.amazonaws.services.s3.model.IllegalBucketNameException;
|
||||
import com.cloud.agent.api.to.BucketTO;
|
||||
|
|
@ -24,6 +45,7 @@ import com.cloud.event.ActionEvent;
|
|||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.resourcelimit.ResourceLimitManagerImpl;
|
||||
import com.cloud.storage.BucketVO;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
|
|
@ -36,22 +58,6 @@ import com.cloud.utils.component.ManagerBase;
|
|||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.api.command.user.bucket.CreateBucketCmd;
|
||||
import org.apache.cloudstack.api.command.user.bucket.UpdateBucketCmd;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BucketApiServiceImpl extends ManagerBase implements BucketApiService, Configurable {
|
||||
|
||||
|
|
@ -68,6 +74,8 @@ public class BucketApiServiceImpl extends ManagerBase implements BucketApiServic
|
|||
|
||||
@Inject
|
||||
private BucketStatisticsDao _bucketStatisticsDao;
|
||||
@Inject
|
||||
ReservationDao reservationDao;
|
||||
|
||||
private ScheduledExecutorService _executor = null;
|
||||
|
||||
|
|
@ -136,13 +144,33 @@ public class BucketApiServiceImpl extends ManagerBase implements BucketApiServic
|
|||
return null;
|
||||
}
|
||||
|
||||
resourceLimitManager.checkResourceLimit(owner, Resource.ResourceType.bucket);
|
||||
resourceLimitManager.checkResourceLimit(owner, Resource.ResourceType.object_storage, (cmd.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
long size = ObjectUtils.defaultIfNull(cmd.getQuota(), 0) * Resource.ResourceType.bytesToGiB;
|
||||
return createCheckedBucket(cmd, owner, size, ownerId);
|
||||
}
|
||||
|
||||
BucketVO bucket = new BucketVO(ownerId, owner.getDomainId(), cmd.getObjectStoragePoolId(), cmd.getBucketName(), cmd.getQuota(),
|
||||
cmd.isVersioning(), cmd.isEncryption(), cmd.isObjectLocking(), cmd.getPolicy());
|
||||
_bucketDao.persist(bucket);
|
||||
return bucket;
|
||||
@NotNull
|
||||
private BucketVO createCheckedBucket(CreateBucketCmd cmd, Account owner, long size, long ownerId) throws ResourceAllocationException {
|
||||
try (CheckedReservation bucketReservation = new CheckedReservation(owner, Resource.ResourceType.bucket,
|
||||
1L, reservationDao, resourceLimitManager);
|
||||
CheckedReservation objectStorageReservation = new CheckedReservation(owner,
|
||||
Resource.ResourceType.object_storage, size, reservationDao, resourceLimitManager)) {
|
||||
BucketVO bucket = new BucketVO(ownerId, owner.getDomainId(), cmd.getObjectStoragePoolId(), cmd.getBucketName(), cmd.getQuota(),
|
||||
cmd.isVersioning(), cmd.isEncryption(), cmd.isObjectLocking(), cmd.getPolicy());
|
||||
_bucketDao.persist(bucket);
|
||||
resourceLimitManager.incrementResourceCount(bucket.getAccountId(), Resource.ResourceType.bucket);
|
||||
if (size > 0) {
|
||||
resourceLimitManager.incrementResourceCount(bucket.getAccountId(), Resource.ResourceType.object_storage,
|
||||
(cmd.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
}
|
||||
return bucket;
|
||||
} catch (Exception e) {
|
||||
if (e instanceof ResourceAllocationException) {
|
||||
throw (ResourceAllocationException)e;
|
||||
} else if (e instanceof CloudRuntimeException) {
|
||||
throw (CloudRuntimeException)e;
|
||||
}
|
||||
throw new CloudRuntimeException(String.format("Failed to create bucket due to: %s", e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -160,7 +188,6 @@ public class BucketApiServiceImpl extends ManagerBase implements BucketApiServic
|
|||
try {
|
||||
bucketTO = new BucketTO(objectStore.createBucket(bucket, objectLock));
|
||||
bucketCreated = true;
|
||||
resourceLimitManager.incrementResourceCount(bucket.getAccountId(), Resource.ResourceType.bucket);
|
||||
|
||||
if (cmd.isVersioning()) {
|
||||
objectStore.setBucketVersioning(bucketTO);
|
||||
|
|
@ -172,7 +199,6 @@ public class BucketApiServiceImpl extends ManagerBase implements BucketApiServic
|
|||
|
||||
if (cmd.getQuota() != null) {
|
||||
objectStore.setQuota(bucketTO, cmd.getQuota());
|
||||
resourceLimitManager.incrementResourceCount(bucket.getAccountId(), Resource.ResourceType.object_storage, (cmd.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
if (objectStoreVO.getTotalSize() != null && objectStoreVO.getTotalSize() != 0 && objectStoreVO.getAllocatedSize() != null) {
|
||||
Long allocatedSize = objectStoreVO.getAllocatedSize() / Resource.ResourceType.bytesToGiB;
|
||||
Long totalSize = objectStoreVO.getTotalSize() / Resource.ResourceType.bytesToGiB;
|
||||
|
|
@ -193,11 +219,16 @@ public class BucketApiServiceImpl extends ManagerBase implements BucketApiServic
|
|||
_objectStoreDao.updateAllocatedSize(objectStoreVO, cmd.getQuota() * Resource.ResourceType.bytesToGiB);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed to create bucket with name: "+bucket.getName(), e);
|
||||
logger.debug("Failed to create bucket with name: {}", bucket.getName(), e);
|
||||
if(bucketCreated) {
|
||||
objectStore.deleteBucket(bucketTO);
|
||||
}
|
||||
_bucketDao.remove(bucket.getId());
|
||||
resourceLimitManager.decrementResourceCount(bucket.getAccountId(), Resource.ResourceType.bucket);
|
||||
if (bucket.getQuota() != null) {
|
||||
resourceLimitManager.decrementResourceCount(bucket.getAccountId(), Resource.ResourceType.object_storage,
|
||||
(bucket.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to create bucket with name: "+bucket.getName()+". "+e.getMessage());
|
||||
}
|
||||
return bucket;
|
||||
|
|
@ -207,22 +238,39 @@ public class BucketApiServiceImpl extends ManagerBase implements BucketApiServic
|
|||
@ActionEvent(eventType = EventTypes.EVENT_BUCKET_DELETE, eventDescription = "deleting bucket")
|
||||
public boolean deleteBucket(long bucketId, Account caller) {
|
||||
Bucket bucket = _bucketDao.findById(bucketId);
|
||||
BucketTO bucketTO = new BucketTO(bucket);
|
||||
if (bucket == null) {
|
||||
throw new InvalidParameterValueException("Unable to find bucket with ID: " + bucketId);
|
||||
}
|
||||
_accountMgr.checkAccess(caller, null, true, bucket);
|
||||
ObjectStoreVO objectStoreVO = _objectStoreDao.findById(bucket.getObjectStoreId());
|
||||
ObjectStoreEntity objectStore = (ObjectStoreEntity)_dataStoreMgr.getDataStore(objectStoreVO.getId(), DataStoreRole.Object);
|
||||
if (objectStore.deleteBucket(bucketTO)) {
|
||||
resourceLimitManager.decrementResourceCount(bucket.getAccountId(), Resource.ResourceType.bucket);
|
||||
if (bucket.getQuota() != null) {
|
||||
resourceLimitManager.decrementResourceCount(bucket.getAccountId(), Resource.ResourceType.object_storage, (bucket.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
_objectStoreDao.updateAllocatedSize(objectStoreVO, -(bucket.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
return deleteCheckedBucket(objectStore, bucket, objectStoreVO);
|
||||
}
|
||||
|
||||
private boolean deleteCheckedBucket(ObjectStoreEntity objectStore, Bucket bucket, ObjectStoreVO objectStoreVO) {
|
||||
Account owner = _accountMgr.getAccount(bucket.getAccountId());
|
||||
try (CheckedReservation bucketReservation = new CheckedReservation(owner, Resource.ResourceType.bucket,
|
||||
bucket.getId(), null, -1L, reservationDao, resourceLimitManager);
|
||||
CheckedReservation objectStorageReservation = new CheckedReservation(owner,
|
||||
Resource.ResourceType.object_storage, bucket.getId(), null,
|
||||
-1*(ObjectUtils.defaultIfNull(bucket.getQuota(), 0) * Resource.ResourceType.bytesToGiB), reservationDao, resourceLimitManager)) {
|
||||
BucketTO bucketTO = new BucketTO(bucket);
|
||||
if (objectStore.deleteBucket(bucketTO)) {
|
||||
resourceLimitManager.decrementResourceCount(bucket.getAccountId(), Resource.ResourceType.bucket);
|
||||
if (bucket.getQuota() != null) {
|
||||
resourceLimitManager.decrementResourceCount(bucket.getAccountId(), Resource.ResourceType.object_storage, (bucket.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
_objectStoreDao.updateAllocatedSize(objectStoreVO, -(bucket.getQuota() * Resource.ResourceType.bytesToGiB));
|
||||
}
|
||||
_bucketDao.remove(bucket.getId());
|
||||
return true;
|
||||
}
|
||||
return _bucketDao.remove(bucketId);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
if (e instanceof CloudRuntimeException) {
|
||||
throw (CloudRuntimeException) e;
|
||||
}
|
||||
throw new CloudRuntimeException(String.format("Failed to delete bucket due to: %s", e.getMessage()), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.cloud.host.HostVO;
|
|||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.Storage;
|
||||
|
|
@ -69,6 +70,7 @@ import org.apache.cloudstack.api.response.VolumeResponse;
|
|||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
|
@ -199,10 +201,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
logFailureAndThrowException("Volume is a reference of snapshot on primary: " + volume.getFullPath());
|
||||
}
|
||||
|
||||
// 5. check resource limitation
|
||||
checkResourceLimitForImportVolume(owner, volume);
|
||||
|
||||
// 6. get disk offering
|
||||
// 5. get disk offering
|
||||
DiskOfferingVO diskOffering = getOrCreateDiskOffering(owner, cmd.getDiskOfferingId(), pool.getDataCenterId(), pool.isLocal());
|
||||
if (diskOffering.isCustomized()) {
|
||||
volumeApiService.validateCustomDiskOfferingSizeRange(volume.getVirtualSize() / ByteScaleUtils.GiB);
|
||||
|
|
@ -211,6 +210,11 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
logFailureAndThrowException(String.format("Disk offering: %s storage tags are not compatible with selected storage pool: %s", diskOffering, pool));
|
||||
}
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
// 6. check resource limitation
|
||||
checkResourceLimitForImportVolume(owner, volume, diskOffering, reservations);
|
||||
|
||||
// 7. create records
|
||||
String volumeName = StringUtils.isNotBlank(cmd.getName()) ? cmd.getName().trim() : volumePath;
|
||||
VolumeVO volumeVO = importVolumeInternal(volume, diskOffering, owner, pool, volumeName);
|
||||
|
|
@ -222,6 +226,10 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
publicUsageEventForVolumeImportAndUnmanage(volumeVO, true);
|
||||
|
||||
return responseGenerator.createVolumeResponse(ResponseObject.ResponseView.Full, volumeVO);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected VolumeOnStorageTO getVolumeOnStorageAndCheck(StoragePoolVO pool, String volumePath) {
|
||||
|
|
@ -457,11 +465,10 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
return volumeDao.findById(diskProfile.getVolumeId());
|
||||
}
|
||||
|
||||
protected void checkResourceLimitForImportVolume(Account owner, VolumeOnStorageTO volume) {
|
||||
protected void checkResourceLimitForImportVolume(Account owner, VolumeOnStorageTO volume, DiskOfferingVO diskOffering, List<Reserver> reservations) {
|
||||
Long volumeSize = volume.getVirtualSize();
|
||||
try {
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume);
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.primary_storage, volumeSize);
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, volumeSize, diskOffering, reservations);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("VM resource allocation error for account: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
|
|||
import com.cloud.org.Cluster;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
|
|
@ -164,6 +166,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
|
|
@ -252,6 +256,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
@Inject
|
||||
private ResourceLimitService resourceLimitService;
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
@Inject
|
||||
private VMInstanceDetailsDao vmInstanceDetailsDao;
|
||||
@Inject
|
||||
private UserVmManager userVmManager;
|
||||
|
|
@ -575,7 +581,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
return new Pair<>(rootDisk, dataDisks);
|
||||
}
|
||||
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed)
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List<Reserver> reservations)
|
||||
throws ServerApiException, PermissionDeniedException, ResourceAllocationException {
|
||||
if (serviceOffering == null && diskOffering == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID [%s] not found during VM [%s] import.", disk.getDiskId(), instanceName));
|
||||
|
|
@ -583,7 +589,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (diskOffering != null) {
|
||||
accountService.checkAccess(owner, diskOffering, zone);
|
||||
}
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, null, diskOffering);
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import", disk.getDiskId()));
|
||||
}
|
||||
|
|
@ -598,9 +603,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) {
|
||||
throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId()));
|
||||
}
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), diskOffering, reservations);
|
||||
}
|
||||
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List<UnmanagedInstanceTO.Disk> disks, final Map<String, Long> diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed)
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List<UnmanagedInstanceTO.Disk> disks, final Map<String, Long> diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List<Reserver> reservations)
|
||||
throws ServerApiException, PermissionDeniedException, ResourceAllocationException {
|
||||
String diskController = null;
|
||||
for (UnmanagedInstanceTO.Disk disk : disks) {
|
||||
|
|
@ -617,7 +623,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all data disk controllers are of the same type", diskController, disk.getController()));
|
||||
}
|
||||
}
|
||||
checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed);
|
||||
checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed, reservations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1044,40 +1050,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
}
|
||||
|
||||
protected void checkUnmanagedDiskLimits(Account account, UnmanagedInstanceTO.Disk rootDisk, ServiceOffering serviceOffering,
|
||||
List<UnmanagedInstanceTO.Disk> dataDisks, Map<String, Long> dataDiskOfferingMap) throws ResourceAllocationException {
|
||||
Long totalVolumes = 0L;
|
||||
Long totalVolumesSize = 0L;
|
||||
List<UnmanagedInstanceTO.Disk> disks = new ArrayList<>();
|
||||
disks.add(rootDisk);
|
||||
disks.addAll(dataDisks);
|
||||
Map<String, Long> diskOfferingMap = new HashMap<>(dataDiskOfferingMap);
|
||||
diskOfferingMap.put(rootDisk.getDiskId(), serviceOffering.getDiskOfferingId());
|
||||
Map<Long, Long> diskOfferingVolumeCountMap = new HashMap<>();
|
||||
Map<Long, Long> diskOfferingSizeMap = new HashMap<>();
|
||||
for (UnmanagedInstanceTO.Disk disk : disks) {
|
||||
totalVolumes++;
|
||||
totalVolumesSize += disk.getCapacity();
|
||||
Long diskOfferingId = diskOfferingMap.get(disk.getDiskId());
|
||||
if (diskOfferingVolumeCountMap.containsKey(diskOfferingId)) {
|
||||
diskOfferingVolumeCountMap.put(diskOfferingId, diskOfferingVolumeCountMap.get(diskOfferingId) + 1);
|
||||
diskOfferingSizeMap.put(diskOfferingId, diskOfferingSizeMap.get(diskOfferingId) + disk.getCapacity());
|
||||
} else {
|
||||
diskOfferingVolumeCountMap.put(diskOfferingId, 1L);
|
||||
diskOfferingSizeMap.put(diskOfferingId, disk.getCapacity());
|
||||
}
|
||||
}
|
||||
resourceLimitService.checkResourceLimit(account, Resource.ResourceType.volume, totalVolumes);
|
||||
resourceLimitService.checkResourceLimit(account, Resource.ResourceType.primary_storage, totalVolumesSize);
|
||||
for (Long diskOfferingId : diskOfferingVolumeCountMap.keySet()) {
|
||||
List<String> tags = resourceLimitService.getResourceLimitStorageTags(diskOfferingDao.findById(diskOfferingId));
|
||||
for (String tag : tags) {
|
||||
resourceLimitService.checkResourceLimitWithTag(account, Resource.ResourceType.volume, tag, diskOfferingVolumeCountMap.get(diskOfferingId));
|
||||
resourceLimitService.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, diskOfferingSizeMap.get(diskOfferingId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, final DataCenter zone, final Cluster cluster, final HostVO host,
|
||||
final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId,
|
||||
final ServiceOfferingVO serviceOffering, final Map<String, Long> dataDiskOfferingMap,
|
||||
|
|
@ -1135,99 +1107,103 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size));
|
||||
}
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed);
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations);
|
||||
if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed);
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations);
|
||||
allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController());
|
||||
}
|
||||
checkUnmanagedDiskLimits(owner, rootDisk, serviceOffering, dataDisks, dataDiskOfferingMap);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
||||
// Check NICs and supplied networks
|
||||
Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
|
||||
Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType());
|
||||
if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) {
|
||||
allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) {
|
||||
allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword());
|
||||
}
|
||||
|
||||
addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails);
|
||||
|
||||
VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
|
||||
if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) {
|
||||
powerState = VirtualMachine.PowerState.PowerOn;
|
||||
}
|
||||
|
||||
try {
|
||||
userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner,
|
||||
null, caller, true, null, owner.getAccountId(), userId,
|
||||
validatedServiceOffering, null, guestOsId, hostName,
|
||||
cluster.getHypervisorType(), allDetails, powerState, null);
|
||||
} catch (InsufficientCapacityException ice) {
|
||||
String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage());
|
||||
logger.error(errorMsg, ice);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg);
|
||||
}
|
||||
|
||||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName));
|
||||
}
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
Long minIops = null;
|
||||
if (details.containsKey(MIN_IOPS)) {
|
||||
minIops = Long.parseLong(details.get(MIN_IOPS));
|
||||
}
|
||||
Long maxIops = null;
|
||||
if (details.containsKey(MAX_IOPS)) {
|
||||
maxIops = Long.parseLong(details.get(MAX_IOPS));
|
||||
}
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()),
|
||||
rootDisk.getCapacity(), minIops, maxIops, template, owner, null));
|
||||
long deviceId = 1L;
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()),
|
||||
disk.getCapacity(), offering.getMinIops(), offering.getMaxIops(),
|
||||
template, owner, deviceId));
|
||||
deviceId++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
try {
|
||||
int nicIndex = 0;
|
||||
for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) {
|
||||
Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId()));
|
||||
Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId());
|
||||
importNic(nic, userVm, network, ipAddresses, nicIndex, nicIndex == 0, forced);
|
||||
nicIndex++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
if (migrateAllowed) {
|
||||
userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList);
|
||||
}
|
||||
publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template);
|
||||
return userVm;
|
||||
|
||||
} catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet
|
||||
logger.error("Volume resource allocation error for owner: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
// Check NICs and supplied networks
|
||||
Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
|
||||
Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType());
|
||||
if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) {
|
||||
allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) {
|
||||
allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword());
|
||||
}
|
||||
|
||||
addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails);
|
||||
|
||||
VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
|
||||
if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) {
|
||||
powerState = VirtualMachine.PowerState.PowerOn;
|
||||
}
|
||||
|
||||
try {
|
||||
userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner,
|
||||
null, caller, true, null, owner.getAccountId(), userId,
|
||||
validatedServiceOffering, null, guestOsId, hostName,
|
||||
cluster.getHypervisorType(), allDetails, powerState, null);
|
||||
} catch (InsufficientCapacityException ice) {
|
||||
String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage());
|
||||
logger.error(errorMsg, ice);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg);
|
||||
}
|
||||
|
||||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName));
|
||||
}
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
Long minIops = null;
|
||||
if (details.containsKey(MIN_IOPS)) {
|
||||
minIops = Long.parseLong(details.get(MIN_IOPS));
|
||||
}
|
||||
Long maxIops = null;
|
||||
if (details.containsKey(MAX_IOPS)) {
|
||||
maxIops = Long.parseLong(details.get(MAX_IOPS));
|
||||
}
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()),
|
||||
rootDisk.getCapacity(), minIops, maxIops, template, owner, null));
|
||||
long deviceId = 1L;
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()),
|
||||
disk.getCapacity(), offering.getMinIops(), offering.getMaxIops(),
|
||||
template, owner, deviceId));
|
||||
deviceId++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
try {
|
||||
int nicIndex = 0;
|
||||
for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) {
|
||||
Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId()));
|
||||
Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId());
|
||||
importNic(nic, userVm, network, ipAddresses, nicIndex, nicIndex == 0, forced);
|
||||
nicIndex++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
if (migrateAllowed) {
|
||||
userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList);
|
||||
}
|
||||
publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template);
|
||||
return userVm;
|
||||
}
|
||||
|
||||
private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map<String, String> allDetails) {
|
||||
|
|
@ -1332,8 +1308,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), cluster.getHypervisorType());
|
||||
ServiceOfferingVO serviceOffering = getServiceOfferingForImportInstance(cmd.getServiceOfferingId(), owner, zone);
|
||||
|
||||
checkResourceLimitForImportInstance(owner);
|
||||
|
||||
String displayName = getDisplayNameForImportInstance(cmd.getDisplayName(), instanceName);
|
||||
String hostName = getHostNameForImportInstance(cmd.getHostName(), cluster.getHypervisorType(), instanceName, displayName);
|
||||
|
||||
|
|
@ -1349,31 +1323,41 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
List<String> managedVms = new ArrayList<>(additionalNameFilters);
|
||||
managedVms.addAll(getHostsManagedVms(hosts));
|
||||
|
||||
ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT,
|
||||
cmd.getEventDescription(), null, null, true, 0);
|
||||
List<String> resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template);
|
||||
try (CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService);
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, Long.valueOf(serviceOffering.getCpu()), reservationDao, resourceLimitService);
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, Long.valueOf(serviceOffering.getRamSize()), reservationDao, resourceLimitService)) {
|
||||
|
||||
if (cmd instanceof ImportVmCmd) {
|
||||
ImportVmCmd importVmCmd = (ImportVmCmd) cmd;
|
||||
if (StringUtils.isBlank(importVmCmd.getImportSource())) {
|
||||
throw new CloudRuntimeException("Please provide an import source for importing the VM");
|
||||
}
|
||||
String source = importVmCmd.getImportSource().toUpperCase();
|
||||
ImportSource importSource = Enum.valueOf(ImportSource.class, source);
|
||||
if (ImportSource.VMWARE == importSource) {
|
||||
userVm = importUnmanagedInstanceFromVmwareToKvm(zone, cluster,
|
||||
template, instanceName, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap,
|
||||
details, importVmCmd, forced);
|
||||
}
|
||||
} else {
|
||||
if (List.of(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM).contains(cluster.getHypervisorType())) {
|
||||
userVm = importUnmanagedInstanceFromHypervisor(zone, cluster, hosts, additionalNameFilters,
|
||||
template, instanceName, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap,
|
||||
details, cmd.getMigrateAllowed(), managedVms, forced);
|
||||
ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT,
|
||||
cmd.getEventDescription(), null, null, true, 0);
|
||||
|
||||
if (cmd instanceof ImportVmCmd) {
|
||||
ImportVmCmd importVmCmd = (ImportVmCmd) cmd;
|
||||
if (StringUtils.isBlank(importVmCmd.getImportSource())) {
|
||||
throw new CloudRuntimeException("Please provide an import source for importing the VM");
|
||||
}
|
||||
String source = importVmCmd.getImportSource().toUpperCase();
|
||||
ImportSource importSource = Enum.valueOf(ImportSource.class, source);
|
||||
if (ImportSource.VMWARE == importSource) {
|
||||
userVm = importUnmanagedInstanceFromVmwareToKvm(zone, cluster,
|
||||
template, instanceName, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap,
|
||||
details, importVmCmd, forced);
|
||||
}
|
||||
} else {
|
||||
if (List.of(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM).contains(cluster.getHypervisorType())) {
|
||||
userVm = importUnmanagedInstanceFromHypervisor(zone, cluster, hosts, additionalNameFilters,
|
||||
template, instanceName, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap,
|
||||
details, cmd.getMigrateAllowed(), managedVms, forced);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
|
||||
if (userVm == null) {
|
||||
|
|
@ -1462,15 +1446,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
return StringUtils.isEmpty(displayName) ? instanceName : displayName;
|
||||
}
|
||||
|
||||
private void checkResourceLimitForImportInstance(Account owner) {
|
||||
try {
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("VM resource allocation error for account: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
}
|
||||
|
||||
private ServiceOfferingVO getServiceOfferingForImportInstance(Long serviceOfferingId, Account owner, DataCenter zone) {
|
||||
if (serviceOfferingId == null) {
|
||||
throw new InvalidParameterValueException("Service offering ID cannot be null");
|
||||
|
|
@ -1705,7 +1680,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering);
|
||||
sourceVMwareInstance = sourceInstanceDetails.first();
|
||||
isClonedInstance = sourceInstanceDetails.second();
|
||||
|
||||
boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows");
|
||||
if (isWindowsVm) {
|
||||
checkConversionSupportOnHost(convertHost, sourceVMName, true);
|
||||
|
|
@ -2466,12 +2440,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new InvalidParameterValueException(String.format("Service offering ID: %d cannot be found", serviceOfferingId));
|
||||
}
|
||||
accountService.checkAccess(owner, serviceOffering, zone);
|
||||
try {
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("VM resource allocation error for account: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
String displayName = cmd.getDisplayName();
|
||||
if (StringUtils.isEmpty(displayName)) {
|
||||
displayName = instanceName;
|
||||
|
|
@ -2559,26 +2527,37 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
|
||||
UserVm userVm = null;
|
||||
|
||||
if (ImportSource.EXTERNAL == importSource) {
|
||||
String username = cmd.getUsername();
|
||||
String password = cmd.getPassword();
|
||||
String tmpPath = cmd.getTmpPath();
|
||||
userVm = importExternalKvmVirtualMachine(unmanagedInstanceTO, instanceName, zone,
|
||||
template, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap, remoteUrl, username, password, tmpPath, details);
|
||||
} else if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) {
|
||||
try {
|
||||
userVm = importKvmVirtualMachineFromDisk(importSource, instanceName, zone,
|
||||
List<String> resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template);
|
||||
try (CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService);
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, Long.valueOf(serviceOffering.getCpu()), reservationDao, resourceLimitService);
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, Long.valueOf(serviceOffering.getRamSize()), reservationDao, resourceLimitService)) {
|
||||
|
||||
if (ImportSource.EXTERNAL == importSource) {
|
||||
String username = cmd.getUsername();
|
||||
String password = cmd.getPassword();
|
||||
String tmpPath = cmd.getTmpPath();
|
||||
userVm = importExternalKvmVirtualMachine(unmanagedInstanceTO, instanceName, zone,
|
||||
template, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap, networkId, hostId, poolId, diskPath,
|
||||
details);
|
||||
} catch (InsufficientCapacityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ResourceAllocationException e) {
|
||||
throw new RuntimeException(e);
|
||||
serviceOffering, dataDiskOfferingMap,
|
||||
nicNetworkMap, nicIpAddressMap, remoteUrl, username, password, tmpPath, details);
|
||||
} else if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) {
|
||||
try {
|
||||
userVm = importKvmVirtualMachineFromDisk(importSource, instanceName, zone,
|
||||
template, displayName, hostName, caller, owner, userId,
|
||||
serviceOffering, dataDiskOfferingMap, networkId, hostId, poolId, diskPath,
|
||||
details);
|
||||
} catch (InsufficientCapacityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ResourceAllocationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
|
||||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import Vm with name: %s ", instanceName));
|
||||
}
|
||||
|
|
@ -2592,7 +2571,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId,
|
||||
final ServiceOfferingVO serviceOffering, final Map<String, Long> dataDiskOfferingMap,
|
||||
final Map<String, Long> nicNetworkMap, final Map<String, Network.IpAddresses> callerNicIpAddressMap,
|
||||
final String remoteUrl, String username, String password, String tmpPath, final Map<String, String> details) {
|
||||
final String remoteUrl, String username, String password, String tmpPath, final Map<String, String> details) throws ResourceAllocationException {
|
||||
UserVm userVm = null;
|
||||
|
||||
Map<String, String> allDetails = new HashMap<>(details);
|
||||
|
|
@ -2603,6 +2582,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName));
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
Pair<UnmanagedInstanceTO.Disk, List<UnmanagedInstanceTO.Disk>> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap);
|
||||
final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first();
|
||||
final List<UnmanagedInstanceTO.Disk> dataDisks = rootAndDataDisksPair.second();
|
||||
|
|
@ -2611,13 +2591,17 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController());
|
||||
|
||||
// Check NICs and supplied networks
|
||||
Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
|
||||
Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM);
|
||||
if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) {
|
||||
allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType());
|
||||
}
|
||||
VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkVolumeResourceLimitsForExternalKvmVmImport(owner, rootDisk, dataDisks, diskOffering, dataDiskOfferingMap, reservations);
|
||||
|
||||
// Check NICs and supplied networks
|
||||
Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
|
||||
Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM);
|
||||
if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) {
|
||||
allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType());
|
||||
}
|
||||
VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
|
||||
|
||||
try {
|
||||
userVm = userVmManager.importVM(zone, null, template, null, displayName, owner,
|
||||
|
|
@ -2631,77 +2615,93 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName));
|
||||
}
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
String rootVolumeName = String.format("ROOT-%s", userVm.getId());
|
||||
DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null);
|
||||
DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false);
|
||||
|
||||
DiskProfile[] dataDiskProfiles = new DiskProfile[dataDisks.size()];
|
||||
int diskSeq = 0;
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", disk.getDiskId()));
|
||||
}
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null);
|
||||
DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null, false);
|
||||
dataDiskProfiles[diskSeq++] = dataDiskProfile;
|
||||
}
|
||||
|
||||
final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null);
|
||||
ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId());
|
||||
profile.setServiceOffering(dummyOffering);
|
||||
DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList();
|
||||
final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null, null, null);
|
||||
DeployDestination dest = null;
|
||||
try {
|
||||
dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName()));
|
||||
}
|
||||
if(dest == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName()));
|
||||
}
|
||||
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null);
|
||||
ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId());
|
||||
profile.setServiceOffering(dummyOffering);
|
||||
DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList();
|
||||
final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null, null, null);
|
||||
DeployDestination dest = null;
|
||||
try {
|
||||
dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName()));
|
||||
}
|
||||
if(dest == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName()));
|
||||
}
|
||||
|
||||
diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT,
|
||||
template, null, remoteUrl, username, password, tmpPath, diskProfile));
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT,
|
||||
template, null, remoteUrl, username, password, tmpPath, diskProfile));
|
||||
|
||||
long deviceId = 1L;
|
||||
diskSeq = 0;
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
DiskProfile dataDiskProfile = dataDiskProfiles[diskSeq++];
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
long deviceId = 1L;
|
||||
diskSeq = 0;
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
DiskProfile dataDiskProfile = dataDiskProfiles[diskSeq++];
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
|
||||
diskProfileStoragePoolList.add(importExternalDisk(disk, userVm, dest, offering, Volume.Type.DATADISK,
|
||||
template, deviceId, remoteUrl, username, password, tmpPath, dataDiskProfile));
|
||||
deviceId++;
|
||||
diskProfileStoragePoolList.add(importExternalDisk(disk, userVm, dest, offering, Volume.Type.DATADISK,
|
||||
template, deviceId, remoteUrl, username, password, tmpPath, dataDiskProfile));
|
||||
deviceId++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
try {
|
||||
int nicIndex = 0;
|
||||
for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) {
|
||||
Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId()));
|
||||
Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId());
|
||||
importNic(nic, userVm, network, ipAddresses, nicIndex, nicIndex==0, true);
|
||||
nicIndex++;
|
||||
try {
|
||||
int nicIndex = 0;
|
||||
for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) {
|
||||
Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId()));
|
||||
Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId());
|
||||
importNic(nic, userVm, network, ipAddresses, nicIndex, nicIndex==0, true);
|
||||
nicIndex++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e);
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage())));
|
||||
publishVMUsageUpdateResourceCount(userVm, dummyOffering, template);
|
||||
return userVm;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkVolumeResourceLimitsForExternalKvmVmImport(Account owner, UnmanagedInstanceTO.Disk rootDisk,
|
||||
List<UnmanagedInstanceTO.Disk> dataDisks, DiskOfferingVO rootDiskOffering,
|
||||
Map<String, Long> dataDiskOfferingMap, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, rootDisk.getCapacity(), rootDiskOffering, reservations);
|
||||
|
||||
if (CollectionUtils.isEmpty(dataDisks)) {
|
||||
return;
|
||||
}
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Data disk ID: %s size is invalid", disk.getDiskId()));
|
||||
}
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), offering, reservations);
|
||||
}
|
||||
publishVMUsageUpdateResourceCount(userVm, dummyOffering, template);
|
||||
return userVm;
|
||||
}
|
||||
|
||||
private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource, final String instanceName, final DataCenter zone,
|
||||
|
|
@ -2769,9 +2769,18 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName));
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
List<String> resourceLimitStorageTags = resourceLimitService.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering);
|
||||
try {
|
||||
CheckedReservation volumeReservation = new CheckedReservation(owner, Resource.ResourceType.volume, resourceLimitStorageTags,
|
||||
CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? 1L : 0L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
String rootVolumeName = String.format("ROOT-%s", userVm.getId());
|
||||
DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null);
|
||||
DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false);
|
||||
|
||||
final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null);
|
||||
ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId());
|
||||
|
|
@ -2815,6 +2824,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
diskProfile.setSize(checkVolumeAnswer.getSize());
|
||||
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.primary_storage, resourceLimitStorageTags,
|
||||
CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? diskProfile.getSize() : 0L, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
long deviceId = 1L;
|
||||
|
|
@ -2833,6 +2846,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
networkOrchestrationService.importNic(macAddress, 0, network, true, userVm, requestedIpPair, zone, true);
|
||||
publishVMUsageUpdateResourceCount(userVm, dummyOffering, template);
|
||||
return userVm;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkVolume(Map<VolumeOnStorageTO.Detail, String> volumeDetails) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
|||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.extension.ExtensionHelper;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
|
@ -82,6 +83,9 @@ public class UserVmJoinDaoImplTest extends GenericDaoBaseWithTagInformationBaseT
|
|||
@Mock
|
||||
private VMTemplateDao vmTemplateDao;
|
||||
|
||||
@Mock
|
||||
ExtensionHelper extensionHelper;
|
||||
|
||||
private UserVmJoinVO userVm = new UserVmJoinVO();
|
||||
private UserVmResponse userVmResponse = new UserVmResponse();
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.cloud.agent.api.routing.UpdateNetworkCommand;
|
|||
import com.cloud.agent.api.to.IpAddressTO;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.VlanVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
|
|
@ -54,6 +53,7 @@ import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
|||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offerings.NetworkOfferingServiceMapVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
|
|
@ -81,6 +81,7 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
|
@ -490,7 +491,6 @@ public class VpcManagerImplTest {
|
|||
public void testCreateVpcDnsOfferingServiceFailure() {
|
||||
mockVpcDnsResources(false, false);
|
||||
try {
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], null, null, null, true, 1500, null, null, null, false);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
@ -502,7 +502,6 @@ public class VpcManagerImplTest {
|
|||
public void testCreateVpcDnsIpv6OfferingFailure() {
|
||||
mockVpcDnsResources(true, false);
|
||||
try {
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], ip6Dns[0], null, true, 1500, null, null, null, false);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
@ -516,8 +515,7 @@ public class VpcManagerImplTest {
|
|||
VpcVO vpc = Mockito.mock(VpcVO.class);
|
||||
Mockito.when(vpcDao.persist(any(), anyMap())).thenReturn(vpc);
|
||||
Mockito.when(vpc.getUuid()).thenReturn("uuid");
|
||||
try {
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
@ -533,8 +531,7 @@ public class VpcManagerImplTest {
|
|||
Mockito.when(vpc.getUuid()).thenReturn("uuid");
|
||||
doReturn(true).when(routedIpv4Manager).isRoutedVpc(any());
|
||||
doNothing().when(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyString());
|
||||
try {
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
@ -556,8 +553,7 @@ public class VpcManagerImplTest {
|
|||
Ipv4GuestSubnetNetworkMap ipv4GuestSubnetNetworkMap = Mockito.mock(Ipv4GuestSubnetNetworkMap.class);
|
||||
doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyInt());
|
||||
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
|
||||
try {
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, null, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds, false);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
|
|||
|
|
@ -149,23 +149,10 @@ public class CheckedReservationTest {
|
|||
@Test
|
||||
public void testMultipleReservationsWithOneFailing() {
|
||||
List<String> tags = List.of("abc", "xyz");
|
||||
when(account.getAccountId()).thenReturn(1L);
|
||||
when(account.getDomainId()).thenReturn(4L);
|
||||
Map<Long, ReservationVO> persistedReservations = new HashMap<>();
|
||||
Mockito.when(reservationDao.persist(Mockito.any(ReservationVO.class))).thenAnswer((Answer<ReservationVO>) invocation -> {
|
||||
ReservationVO reservationVO = (ReservationVO) invocation.getArguments()[0];
|
||||
Long id = (long) (persistedReservations.size() + 1);
|
||||
ReflectionTestUtils.setField(reservationVO, "id", id);
|
||||
persistedReservations.put(id, reservationVO);
|
||||
return reservationVO;
|
||||
});
|
||||
Mockito.when(reservationDao.remove(Mockito.anyLong())).thenAnswer((Answer<Boolean>) invocation -> {
|
||||
Long id = (Long) invocation.getArguments()[0];
|
||||
persistedReservations.remove(id);
|
||||
return true;
|
||||
});
|
||||
|
||||
try {
|
||||
Mockito.doThrow(ResourceAllocationException.class).when(resourceLimitService).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, "xyz", 1L);
|
||||
Mockito.doThrow(ResourceAllocationException.class).when(resourceLimitService).checkResourceLimitWithTag(account, account.getDomainId(), true, Resource.ResourceType.cpu, "xyz", 1L);
|
||||
try (CheckedReservation vmReservation = new CheckedReservation(account, Resource.ResourceType.user_vm, tags, 1L, reservationDao, resourceLimitService);
|
||||
CheckedReservation cpuReservation = new CheckedReservation(account, Resource.ResourceType.cpu, tags, 1L, reservationDao, resourceLimitService);
|
||||
CheckedReservation memReservation = new CheckedReservation(account, Resource.ResourceType.memory, tags, 256L, reservationDao, resourceLimitService);
|
||||
|
|
|
|||
|
|
@ -34,9 +34,10 @@ import org.apache.cloudstack.api.response.TaggedResourceLimitAndCountResponse;
|
|||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.junit.After;
|
||||
|
|
@ -46,6 +47,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
|
|
@ -83,6 +85,7 @@ import com.cloud.user.ResourceLimitService;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
|
|
@ -278,6 +281,7 @@ public class ResourceLimitManagerImplTest {
|
|||
|
||||
@Test
|
||||
public void testCheckVmResourceLimit() {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
|
|
@ -285,72 +289,12 @@ public class ResourceLimitManagerImplTest {
|
|||
Mockito.when(serviceOffering.getRamSize()).thenReturn(256);
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmResourceLimit(account, true, serviceOffering, template);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
resourceLimitManager.checkVmResourceLimit(account, true, serviceOffering, template, reservations);
|
||||
List<String> tags = new ArrayList<>();
|
||||
tags.add(null);
|
||||
tags.add(hostTags.get(0));
|
||||
for (String tag: tags) {
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.user_vm, tag);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, tag, 2L);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, tag, 256L);
|
||||
}
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckVmCpuResourceLimit() {
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
long cpu = 2L;
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmCpuResourceLimit(account, true, serviceOffering, template, cpu);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, null, cpu);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), cpu);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckVmMemoryResourceLimit() {
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
long delta = 256L;
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmMemoryResourceLimit(account, true, serviceOffering, template, delta);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, null, delta);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, hostTags.get(0), delta);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckVmGpuResourceLimit() {
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
long gpuCount = 2L;
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmGpuResourceLimit(account, true, serviceOffering, template, gpuCount);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.gpu, null, gpuCount);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.gpu, hostTags.get(0), gpuCount);
|
||||
Assert.assertEquals(4, mockCheckedReservation.constructed().size());
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -358,22 +302,15 @@ public class ResourceLimitManagerImplTest {
|
|||
|
||||
@Test
|
||||
public void testCheckVolumeResourceLimit() {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
String checkTag = storageTags.get(0);
|
||||
DiskOffering diskOffering = Mockito.mock(DiskOffering.class);
|
||||
Mockito.when(diskOffering.getTags()).thenReturn(checkTag);
|
||||
Mockito.when(diskOffering.getTagsArray()).thenReturn(new String[]{checkTag});
|
||||
Account account = Mockito.mock(Account.class);
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, true, 100L, diskOffering);
|
||||
List<String> tags = new ArrayList<>();
|
||||
tags.add(null);
|
||||
tags.add(checkTag);
|
||||
for (String tag: tags) {
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.volume, tag);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, 100L);
|
||||
}
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, true, 100L, diskOffering, reservations);
|
||||
Assert.assertEquals(2, reservations.size());
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -626,10 +563,11 @@ public class ResourceLimitManagerImplTest {
|
|||
public void testCheckResourceLimitWithTagNonAdmin() throws ResourceAllocationException {
|
||||
AccountVO account = Mockito.mock(AccountVO.class);
|
||||
Mockito.when(account.getId()).thenReturn(1L);
|
||||
Mockito.when(account.getDomainId()).thenReturn(1L);
|
||||
Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(false);
|
||||
Mockito.doReturn(new ArrayList<ResourceLimitVO>()).when(resourceLimitManager).lockAccountAndOwnerDomainRows(Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
|
||||
Mockito.doNothing().when(resourceLimitManager).checkAccountResourceLimit(account, null, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
Mockito.doNothing().when(resourceLimitManager).checkDomainResourceLimit(account, null, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
Mockito.doNothing().when(resourceLimitManager).checkDomainResourceLimit(1L, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
try {
|
||||
resourceLimitManager.checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
@ -645,9 +583,10 @@ public class ResourceLimitManagerImplTest {
|
|||
Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(false);
|
||||
ProjectVO projectVO = Mockito.mock(ProjectVO.class);
|
||||
Mockito.when(projectDao.findByProjectAccountId(Mockito.anyLong())).thenReturn(projectVO);
|
||||
Mockito.when(projectVO.getDomainId()).thenReturn(1L);
|
||||
Mockito.doReturn(new ArrayList<ResourceLimitVO>()).when(resourceLimitManager).lockAccountAndOwnerDomainRows(Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
|
||||
Mockito.doNothing().when(resourceLimitManager).checkAccountResourceLimit(account, projectVO, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
Mockito.doNothing().when(resourceLimitManager).checkDomainResourceLimit(account, projectVO, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
Mockito.doNothing().when(resourceLimitManager).checkDomainResourceLimit(1L, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
try {
|
||||
resourceLimitManager.checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), 1);
|
||||
} catch (ResourceAllocationException e) {
|
||||
|
|
@ -991,13 +930,6 @@ public class ResourceLimitManagerImplTest {
|
|||
Mockito.anyList(), Mockito.eq(tag));
|
||||
}
|
||||
|
||||
private void mockCheckResourceLimitWithTag() throws ResourceAllocationException {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(
|
||||
Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(
|
||||
Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString(), Mockito.anyLong());
|
||||
}
|
||||
|
||||
private void mockIncrementResourceCountWithTag() {
|
||||
Mockito.doNothing().when(resourceLimitManager).incrementResourceCountWithTag(
|
||||
Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
|
||||
|
|
@ -1014,6 +946,7 @@ public class ResourceLimitManagerImplTest {
|
|||
|
||||
@Test
|
||||
public void testCheckVolumeResourceCount() throws ResourceAllocationException {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
Account account = Mockito.mock(Account.class);
|
||||
String tag = "tag";
|
||||
long delta = 10L;
|
||||
|
|
@ -1027,12 +960,11 @@ public class ResourceLimitManagerImplTest {
|
|||
|
||||
Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
|
||||
.getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
|
||||
mockCheckResourceLimitWithTag();
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, false, delta, Mockito.mock(DiskOffering.class));
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(
|
||||
account, Resource.ResourceType.volume, tag);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, 10L);
|
||||
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, false, delta, Mockito.mock(DiskOffering.class), reservations);
|
||||
Assert.assertEquals(2, reservations.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
|
@ -44,6 +43,7 @@ import java.util.concurrent.ExecutionException;
|
|||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
|
|
@ -91,6 +91,7 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.InOrder;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
|
|
@ -99,7 +100,6 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||
|
||||
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
|
@ -551,7 +551,9 @@ public class VolumeApiServiceImplTest {
|
|||
@Test
|
||||
public void attachRootVolumePositive() throws NoSuchFieldException, IllegalAccessException {
|
||||
thrown.expect(NullPointerException.class);
|
||||
volumeApiServiceImpl.attachVolumeToVM(2L, 6L, 0L, false);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
volumeApiServiceImpl.attachVolumeToVM(2L, 6L, 0L, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Negative test - attach data volume, to the vm on non-kvm hypervisor
|
||||
|
|
@ -570,7 +572,9 @@ public class VolumeApiServiceImplTest {
|
|||
DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
|
||||
when(diskOffering.getEncrypt()).thenReturn(true);
|
||||
when(_diskOfferingDao.findById(anyLong())).thenReturn(diskOffering);
|
||||
volumeApiServiceImpl.attachVolumeToVM(4L, 10L, 1L, false);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
volumeApiServiceImpl.attachVolumeToVM(4L, 10L, 1L, false);
|
||||
}
|
||||
}
|
||||
|
||||
// volume not Ready
|
||||
|
|
@ -655,9 +659,7 @@ public class VolumeApiServiceImplTest {
|
|||
* The resource limit check for primary storage should not be skipped for Volume in 'Uploaded' state.
|
||||
*/
|
||||
@Test
|
||||
public void testResourceLimitCheckForUploadedVolume() throws NoSuchFieldException, IllegalAccessException, ResourceAllocationException {
|
||||
doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(resourceLimitServiceMock)
|
||||
.checkResourceLimit(any(AccountVO.class), any(Resource.ResourceType.class), any(Long.class));
|
||||
public void testAttachVolumeToVMPerformsResourceReservation() throws NoSuchFieldException, IllegalAccessException, ResourceAllocationException {
|
||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
||||
AccountVO acc = Mockito.mock(AccountVO.class);
|
||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
||||
|
|
@ -678,10 +680,10 @@ public class VolumeApiServiceImplTest {
|
|||
DataCenterVO zoneWithDisabledLocalStorage = Mockito.mock(DataCenterVO.class);
|
||||
when(_dcDao.findById(anyLong())).thenReturn(zoneWithDisabledLocalStorage);
|
||||
when(zoneWithDisabledLocalStorage.isLocalStorageEnabled()).thenReturn(true);
|
||||
try {
|
||||
doReturn(volumeVoMock).when(volumeApiServiceImpl).getVolumeAttachJobResult(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
volumeApiServiceImpl.attachVolumeToVM(2L, 9L, null, false);
|
||||
} catch (InvalidParameterValueException e) {
|
||||
Assert.assertEquals(e.getMessage(), ("primary storage resource limit check failed"));
|
||||
Assert.assertEquals(1, mockCheckedReservation.constructed().size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2208,6 +2210,36 @@ public class VolumeApiServiceImplTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredPrimaryStorageSizeForVolumeAttachTestTagsAreEmptyReturnsZero() {
|
||||
List<String> tags = new ArrayList<>();
|
||||
|
||||
Long result = volumeApiServiceImpl.getRequiredPrimaryStorageSizeForVolumeAttach(tags, volumeInfoMock);
|
||||
|
||||
Assert.assertEquals(0L, (long) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredPrimaryStorageSizeForVolumeAttachTestVolumeIsReadyReturnsZero() {
|
||||
List<String> tags = List.of("tag1", "tag2");
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeInfoMock).getState();
|
||||
|
||||
Long result = volumeApiServiceImpl.getRequiredPrimaryStorageSizeForVolumeAttach(tags, volumeInfoMock);
|
||||
|
||||
Assert.assertEquals(0L, (long) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredPrimaryStorageSizeForVolumeAttachTestTagsAreNotEmptyAndVolumeIsUploadedReturnsVolumeSize() {
|
||||
List<String> tags = List.of("tag1", "tag2");
|
||||
Mockito.doReturn(Volume.State.Uploaded).when(volumeInfoMock).getState();
|
||||
Mockito.doReturn(2L).when(volumeInfoMock).getSize();
|
||||
|
||||
Long result = volumeApiServiceImpl.getRequiredPrimaryStorageSizeForVolumeAttach(tags, volumeInfoMock);
|
||||
|
||||
Assert.assertEquals(2L, (long) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateNoVmSnapshotsTestNoInstanceId() {
|
||||
Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import com.cloud.dc.dao.DataCenterDao;
|
|||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
|
|
@ -317,12 +316,11 @@ public class SnapshotManagerImplTest {
|
|||
Mockito.when(result1.isFailed()).thenReturn(false);
|
||||
AsyncCallFuture<SnapshotResult> future1 = Mockito.mock(AsyncCallFuture.class);
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitService).checkResourceLimit(Mockito.any(), Mockito.any(), Mockito.anyLong());
|
||||
Mockito.when(future.get()).thenReturn(result);
|
||||
Mockito.when(snapshotService.queryCopySnapshot(Mockito.any())).thenReturn(future);
|
||||
Mockito.when(future1.get()).thenReturn(result1);
|
||||
Mockito.when(snapshotService.copySnapshot(Mockito.any(SnapshotInfo.class), Mockito.anyString(), Mockito.any(DataStore.class))).thenReturn(future1);
|
||||
} catch (ResourceAllocationException | ResourceUnavailableException | ExecutionException | InterruptedException e) {
|
||||
} catch (ResourceUnavailableException | ExecutionException | InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
List<Long> addedZone = new ArrayList<>();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,27 @@
|
|||
// under the License.
|
||||
package com.cloud.storage.snapshot;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.snapshot.ExtractSnapshotCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
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.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
||||
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.dc.DataCenter;
|
||||
|
|
@ -27,6 +48,7 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.server.TaggedResourceService;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
|
|
@ -57,27 +79,6 @@ import com.cloud.vm.snapshot.VMSnapshot;
|
|||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.snapshot.ExtractSnapshotCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
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.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
|
@ -87,6 +88,7 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.BDDMockito;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
|
@ -237,8 +239,6 @@ public class SnapshotManagerTest {
|
|||
when(_storageStrategyFactory.getSnapshotStrategy(Mockito.any(SnapshotVO.class), Mockito.eq(SnapshotOperation.BACKUP))).thenReturn(snapshotStrategy);
|
||||
when(_storageStrategyFactory.getSnapshotStrategy(Mockito.any(SnapshotVO.class), Mockito.eq(SnapshotOperation.REVERT))).thenReturn(snapshotStrategy);
|
||||
|
||||
doNothing().when(_resourceLimitMgr).checkResourceLimit(any(Account.class), any(ResourceType.class));
|
||||
doNothing().when(_resourceLimitMgr).checkResourceLimit(any(Account.class), any(ResourceType.class), anyLong());
|
||||
doNothing().when(_resourceLimitMgr).incrementResourceCount(anyLong(), any(ResourceType.class));
|
||||
doNothing().when(_resourceLimitMgr).incrementResourceCount(anyLong(), any(ResourceType.class), anyLong());
|
||||
|
||||
|
|
@ -320,7 +320,12 @@ public class SnapshotManagerTest {
|
|||
when(mockList2.size()).thenReturn(0);
|
||||
when(_vmSnapshotDao.listByInstanceId(TEST_VM_ID, VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging)).thenReturn(mockList2);
|
||||
when(_snapshotDao.persist(any(SnapshotVO.class))).thenReturn(snapshotMock);
|
||||
_snapshotMgr.allocSnapshot(TEST_VOLUME_ID, Snapshot.MANUAL_POLICY_ID, null, null);
|
||||
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
_snapshotMgr.allocSnapshot(TEST_VOLUME_ID, Snapshot.MANUAL_POLICY_ID, null, null);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(String.format("Failure with exception: %s", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
|
|
@ -468,7 +473,7 @@ public class SnapshotManagerTest {
|
|||
public void validateCreateTagsForSnapshotPolicyWithValidTags(){
|
||||
Mockito.doReturn(null).when(taggedResourceServiceMock).createTags(any(), any(), any(), any());
|
||||
|
||||
Map map = new HashMap<>();
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("test", "test");
|
||||
|
||||
_snapshotMgr.createTagsForSnapshotPolicy(map, snapshotPolicyVoMock);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ package com.cloud.template;
|
|||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.api.query.dao.SnapshotJoinDao;
|
||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
|
|
@ -34,6 +33,7 @@ import com.cloud.host.dao.HostDao;
|
|||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.HypervisorGuruManager;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.Snapshot;
|
||||
|
|
@ -64,12 +64,14 @@ import com.cloud.user.User;
|
|||
import com.cloud.user.UserData;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
|
||||
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
|
||||
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
|
||||
|
|
@ -92,6 +94,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.secstorage.dao.SecondaryStorageHeuristicDao;
|
||||
import org.apache.cloudstack.secstorage.heuristics.HeuristicType;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
|
|
@ -104,14 +107,21 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
|||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
||||
import org.apache.cloudstack.storage.heuristics.HeuristicRuleHelper;
|
||||
import org.apache.cloudstack.storage.template.VnfTemplateManager;
|
||||
|
||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
import org.junit.After;
|
||||
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.MockedConstruction;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
|
@ -120,11 +130,7 @@ import org.springframework.context.annotation.FilterType;
|
|||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -137,81 +143,81 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
public class TemplateManagerImplTest {
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TemplateManagerImplTest extends TestCase {
|
||||
|
||||
@Inject
|
||||
TemplateManagerImpl templateManager = new TemplateManagerImpl();
|
||||
@Spy
|
||||
@InjectMocks
|
||||
TemplateManagerImpl templateManager;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
DataStoreManager dataStoreManager;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
VMTemplateDao vmTemplateDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
VMTemplatePoolDao vmTemplatePoolDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
TemplateDataStoreDao templateDataStoreDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
StoragePoolHostDao storagePoolHostDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
PrimaryDataStoreDao primaryDataStoreDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
ResourceLimitService resourceLimitMgr;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
ImageStoreDao imgStoreDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
GuestOSDao guestOSDao;
|
||||
|
||||
@Inject
|
||||
VMTemplateDao tmpltDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
SnapshotDao snapshotDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
VolumeDao volumeDao;
|
||||
|
||||
@Mock
|
||||
VMTemplateDetailsDao tmpltDetailsDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
StorageStrategyFactory storageStrategyFactory;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
VMInstanceDao _vmInstanceDao;
|
||||
|
||||
@Inject
|
||||
private VMTemplateDao _tmpltDao;
|
||||
@Mock
|
||||
ReservationDao reservationDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
HypervisorGuruManager _hvGuruMgr;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
AccountManager _accountMgr;
|
||||
@Inject
|
||||
|
||||
@Mock
|
||||
VnfTemplateManager vnfTemplateManager;
|
||||
@Inject
|
||||
@Mock
|
||||
SnapshotJoinDao snapshotJoinDao;
|
||||
@Inject
|
||||
@Mock
|
||||
TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
|
||||
|
||||
@Inject
|
||||
@Mock
|
||||
HeuristicRuleHelper heuristicRuleHelperMock;
|
||||
|
||||
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
|
|
@ -241,7 +247,6 @@ public class TemplateManagerImplTest {
|
|||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ComponentContext.initComponentsLifeCycle();
|
||||
AccountVO account = new AccountVO("admin", 1L, "networkDomain", Account.Type.NORMAL, "uuid");
|
||||
UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
|
||||
CallContext.register(user, account);
|
||||
|
|
@ -275,7 +280,7 @@ public class TemplateManagerImplTest {
|
|||
List<TemplateAdapter> adapters = new ArrayList<TemplateAdapter>();
|
||||
adapters.add(templateAdapter);
|
||||
when(cmd.getId()).thenReturn(0L);
|
||||
when(_tmpltDao.findById(cmd.getId())).thenReturn(template);
|
||||
when(vmTemplateDao.findById(cmd.getId())).thenReturn(template);
|
||||
when(cmd.getZoneId()).thenReturn(null);
|
||||
|
||||
when(template.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None);
|
||||
|
|
@ -296,7 +301,6 @@ public class TemplateManagerImplTest {
|
|||
//case 2.2: When Force delete flag is 'false' and VM instance VO list is non empty.
|
||||
when(cmd.isForced()).thenReturn(false);
|
||||
VMInstanceVO vmInstanceVO = mock(VMInstanceVO.class);
|
||||
when(vmInstanceVO.getInstanceName()).thenReturn("mydDummyVM");
|
||||
vmInstanceVOList.add(vmInstanceVO);
|
||||
when(_vmInstanceDao.listNonExpungedByTemplate(anyLong())).thenReturn(vmInstanceVOList);
|
||||
try {
|
||||
|
|
@ -311,7 +315,6 @@ public class TemplateManagerImplTest {
|
|||
when(mockTemplate.getId()).thenReturn(202l);
|
||||
|
||||
StoragePoolVO mockPool = mock(StoragePoolVO.class);
|
||||
when(mockPool.getId()).thenReturn(2l);
|
||||
|
||||
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
|
||||
when(mockPrimaryDataStore.getId()).thenReturn(2l);
|
||||
|
|
@ -319,7 +322,6 @@ public class TemplateManagerImplTest {
|
|||
VMTemplateStoragePoolVO mockTemplateStore = mock(VMTemplateStoragePoolVO.class);
|
||||
when(mockTemplateStore.getDownloadState()).thenReturn(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
|
||||
when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
|
||||
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
|
||||
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(mockTemplateStore);
|
||||
|
||||
|
|
@ -335,13 +337,11 @@ public class TemplateManagerImplTest {
|
|||
when(mockTemplate.getId()).thenReturn(202l);
|
||||
|
||||
StoragePoolVO mockPool = mock(StoragePoolVO.class);
|
||||
when(mockPool.getId()).thenReturn(2l);
|
||||
|
||||
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
|
||||
when(mockPrimaryDataStore.getId()).thenReturn(2l);
|
||||
when(mockPrimaryDataStore.getDataCenterId()).thenReturn(1l);
|
||||
|
||||
when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
|
||||
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
|
||||
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(null);
|
||||
when(templateDataStoreDao.findByTemplateZoneDownloadStatus(202l, 1l, VMTemplateStorageResourceAssoc.Status.DOWNLOADED)).thenReturn(null);
|
||||
|
|
@ -356,7 +356,6 @@ public class TemplateManagerImplTest {
|
|||
when(mockTemplate.getId()).thenReturn(202l);
|
||||
|
||||
StoragePoolVO mockPool = mock(StoragePoolVO.class);
|
||||
when(mockPool.getId()).thenReturn(2l);
|
||||
|
||||
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
|
||||
when(mockPrimaryDataStore.getId()).thenReturn(2l);
|
||||
|
|
@ -364,7 +363,6 @@ public class TemplateManagerImplTest {
|
|||
|
||||
TemplateDataStoreVO mockTemplateDataStore = mock(TemplateDataStoreVO.class);
|
||||
|
||||
when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
|
||||
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
|
||||
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(null);
|
||||
when(templateDataStoreDao.findByTemplateZoneDownloadStatus(202l, 1l, VMTemplateStorageResourceAssoc.Status.DOWNLOADED)).thenReturn(mockTemplateDataStore);
|
||||
|
|
@ -415,20 +413,10 @@ public class TemplateManagerImplTest {
|
|||
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
|
||||
VMTemplateStoragePoolVO mockTemplateStore = mock(VMTemplateStoragePoolVO.class);
|
||||
|
||||
when(mockPrimaryDataStore.getId()).thenReturn(2l);
|
||||
when(mockPool.getId()).thenReturn(2l);
|
||||
when(mockPool.getStatus()).thenReturn(StoragePoolStatus.Disabled);
|
||||
when(mockPool.getDataCenterId()).thenReturn(1l);
|
||||
when(mockTemplate.getId()).thenReturn(202l);
|
||||
when(mockTemplateStore.getDownloadState()).thenReturn(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
when(vmTemplateDao.findById(anyLong())).thenReturn(mockTemplate);
|
||||
when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
|
||||
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
|
||||
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(mockTemplateStore);
|
||||
when(primaryDataStoreDao.findById(anyLong())).thenReturn(mockPool);
|
||||
|
||||
doNothing().when(mockTemplateStore).setMarkedForGC(anyBoolean());
|
||||
|
||||
ExecutorService preloadExecutor = new CustomThreadPoolExecutor(8, 8, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(),
|
||||
new NamedThreadFactory("Template-Preloader"));
|
||||
templateManager._preloadExecutor = preloadExecutor;
|
||||
|
|
@ -446,15 +434,10 @@ public class TemplateManagerImplTest {
|
|||
|
||||
StoragePoolVO mockPool1 = mock(StoragePoolVO.class);
|
||||
when(mockPool1.getId()).thenReturn(2l);
|
||||
when(mockPool1.getStatus()).thenReturn(StoragePoolStatus.Up);
|
||||
when(mockPool1.getDataCenterId()).thenReturn(1l);
|
||||
StoragePoolVO mockPool2 = mock(StoragePoolVO.class);
|
||||
when(mockPool2.getId()).thenReturn(3l);
|
||||
when(mockPool2.getStatus()).thenReturn(StoragePoolStatus.Up);
|
||||
when(mockPool2.getDataCenterId()).thenReturn(1l);
|
||||
StoragePoolVO mockPool3 = mock(StoragePoolVO.class);
|
||||
when(mockPool3.getId()).thenReturn(4l);
|
||||
when(mockPool3.getStatus()).thenReturn(StoragePoolStatus.Up);
|
||||
when(mockPool3.getDataCenterId()).thenReturn(2l);
|
||||
pools.add(mockPool1);
|
||||
pools.add(mockPool2);
|
||||
|
|
@ -467,9 +450,6 @@ public class TemplateManagerImplTest {
|
|||
when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
|
||||
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
|
||||
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(mockTemplateStore);
|
||||
when(primaryDataStoreDao.findById(2l)).thenReturn(mockPool1);
|
||||
when(primaryDataStoreDao.findById(3l)).thenReturn(mockPool2);
|
||||
when(primaryDataStoreDao.findById(4l)).thenReturn(mockPool3);
|
||||
when(primaryDataStoreDao.listByStatus(StoragePoolStatus.Up)).thenReturn(pools);
|
||||
|
||||
doNothing().when(mockTemplateStore).setMarkedForGC(anyBoolean());
|
||||
|
|
@ -497,7 +477,6 @@ public class TemplateManagerImplTest {
|
|||
when(mockCreateCmd.getVolumeId()).thenReturn(null);
|
||||
when(mockCreateCmd.getSnapshotId()).thenReturn(1L);
|
||||
when(mockCreateCmd.getOsTypeId()).thenReturn(1L);
|
||||
when(mockCreateCmd.getEventDescription()).thenReturn("test");
|
||||
when(mockCreateCmd.getDetails()).thenReturn(null);
|
||||
when(mockCreateCmd.getZoneId()).thenReturn(null);
|
||||
|
||||
|
|
@ -510,20 +489,17 @@ public class TemplateManagerImplTest {
|
|||
when(mockSnapshot.getState()).thenReturn(Snapshot.State.BackedUp);
|
||||
when(mockSnapshot.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer);
|
||||
|
||||
doNothing().when(resourceLimitMgr).checkResourceLimit(any(Account.class), eq(Resource.ResourceType.template));
|
||||
doNothing().when(resourceLimitMgr).checkResourceLimit(any(Account.class), eq(Resource.ResourceType.secondary_storage), anyLong());
|
||||
|
||||
GuestOSVO mockGuestOS = mock(GuestOSVO.class);
|
||||
when(guestOSDao.findById(anyLong())).thenReturn(mockGuestOS);
|
||||
|
||||
when(tmpltDao.getNextInSequence(eq(Long.class), eq("id"))).thenReturn(1L);
|
||||
when(vmTemplateDao.getNextInSequence(eq(Long.class), eq("id"))).thenReturn(1L);
|
||||
|
||||
List<ImageStoreVO> mockRegionStores = new ArrayList<>();
|
||||
ImageStoreVO mockRegionStore = mock(ImageStoreVO.class);
|
||||
mockRegionStores.add(mockRegionStore);
|
||||
when(imgStoreDao.findRegionImageStores()).thenReturn(mockRegionStores);
|
||||
|
||||
when(tmpltDao.persist(any(VMTemplateVO.class))).thenAnswer(new Answer<VMTemplateVO>() {
|
||||
when(vmTemplateDao.persist(any(VMTemplateVO.class))).thenAnswer(new Answer<VMTemplateVO>() {
|
||||
@Override
|
||||
public VMTemplateVO answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||
Object[] args = invocationOnMock.getArguments();
|
||||
|
|
@ -531,8 +507,10 @@ public class TemplateManagerImplTest {
|
|||
}
|
||||
});
|
||||
|
||||
VMTemplateVO template = templateManager.createPrivateTemplateRecord(mockCreateCmd, mockTemplateOwner);
|
||||
assertTrue("Template in a region store should have cross zones set", template.isCrossZones());
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
VMTemplateVO template = templateManager.createPrivateTemplateRecord(mockCreateCmd, mockTemplateOwner);
|
||||
assertTrue("Template in a region store should have cross zones set", template.isCrossZones());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -544,7 +522,7 @@ public class TemplateManagerImplTest {
|
|||
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
|
||||
|
||||
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
|
||||
when(_tmpltDao.findById(anyLong())).thenReturn(template);
|
||||
when(vmTemplateDao.findById(anyLong())).thenReturn(template);
|
||||
|
||||
VirtualMachineTemplate resultTemplate = templateManager.linkUserDataToTemplate(cmd);
|
||||
|
||||
|
|
@ -560,7 +538,6 @@ public class TemplateManagerImplTest {
|
|||
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
|
||||
|
||||
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
|
||||
when(_tmpltDao.findById(1L)).thenReturn(template);
|
||||
|
||||
templateManager.linkUserDataToTemplate(cmd);
|
||||
}
|
||||
|
|
@ -574,7 +551,6 @@ public class TemplateManagerImplTest {
|
|||
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
|
||||
|
||||
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
|
||||
when(_tmpltDao.findById(1L)).thenReturn(template);
|
||||
|
||||
templateManager.linkUserDataToTemplate(cmd);
|
||||
}
|
||||
|
|
@ -587,7 +563,7 @@ public class TemplateManagerImplTest {
|
|||
when(cmd.getUserdataId()).thenReturn(2L);
|
||||
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
|
||||
|
||||
when(_tmpltDao.findById(anyLong())).thenReturn(null);
|
||||
when(vmTemplateDao.findById(anyLong())).thenReturn(null);
|
||||
|
||||
templateManager.linkUserDataToTemplate(cmd);
|
||||
}
|
||||
|
|
@ -602,7 +578,7 @@ public class TemplateManagerImplTest {
|
|||
|
||||
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
|
||||
when(template.getId()).thenReturn(1L);
|
||||
when(_tmpltDao.findById(1L)).thenReturn(template);
|
||||
when(vmTemplateDao.findById(1L)).thenReturn(template);
|
||||
|
||||
VirtualMachineTemplate resultTemplate = templateManager.linkUserDataToTemplate(cmd);
|
||||
|
||||
|
|
@ -633,7 +609,6 @@ public class TemplateManagerImplTest {
|
|||
DataStore dataStore = Mockito.mock(DataStore.class);
|
||||
VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
|
||||
|
||||
Mockito.when(dataStoreManager.getDataStore(Mockito.anyString(), Mockito.any(DataStoreRole.class))).thenReturn(null);
|
||||
Mockito.when(heuristicRuleHelperMock.getImageStoreIfThereIsHeuristicRule(Mockito.anyLong(), Mockito.any(HeuristicType.class), Mockito.any(VolumeVO.class))).thenReturn(null);
|
||||
Mockito.when(dataStoreManager.getImageStoreWithFreeCapacity(Mockito.anyLong())).thenReturn(dataStore);
|
||||
|
||||
|
|
@ -646,7 +621,6 @@ public class TemplateManagerImplTest {
|
|||
DataStore dataStore = Mockito.mock(DataStore.class);
|
||||
VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
|
||||
|
||||
Mockito.when(dataStoreManager.getDataStore(Mockito.anyString(), Mockito.any(DataStoreRole.class))).thenReturn(null);
|
||||
Mockito.when(heuristicRuleHelperMock.getImageStoreIfThereIsHeuristicRule(Mockito.anyLong(), Mockito.any(HeuristicType.class), Mockito.any(VolumeVO.class))).thenReturn(dataStore);
|
||||
|
||||
templateManager.getImageStore(null, 1L, volumeVO);
|
||||
|
|
@ -987,6 +961,11 @@ public class TemplateManagerImplTest {
|
|||
return Mockito.mock(TemplateDeployAsIsDetailsDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ReservationDao reservationDao() {
|
||||
return Mockito.mock(ReservationDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SnapshotHelper snapshotHelper() {
|
||||
return Mockito.mock(SnapshotHelper.class);
|
||||
|
|
|
|||
|
|
@ -59,9 +59,20 @@ import java.util.Map;
|
|||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import org.junit.After;
|
||||
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.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
|
|
@ -85,6 +96,7 @@ import org.apache.cloudstack.backup.dao.BackupDao;
|
|||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
|
|
@ -95,18 +107,6 @@ import org.apache.cloudstack.storage.template.VnfTemplateManager;
|
|||
import org.apache.cloudstack.userdata.UserDataManager;
|
||||
import org.apache.cloudstack.vm.UnmanagedVMsManager;
|
||||
import org.apache.cloudstack.vm.lease.VMLeaseManager;
|
||||
import org.junit.After;
|
||||
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.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
|
||||
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
|
||||
|
|
@ -133,6 +133,7 @@ import com.cloud.host.Host;
|
|||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.as.AutoScaleManager;
|
||||
|
|
@ -157,6 +158,7 @@ import com.cloud.offering.NetworkOffering;
|
|||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
|
|
@ -173,6 +175,7 @@ import com.cloud.storage.VolumeVO;
|
|||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
|
|
@ -195,6 +198,7 @@ import com.cloud.utils.db.EntityManager;
|
|||
import com.cloud.utils.db.UUIDManager;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExceptionProxyObject;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
|
|
@ -692,7 +696,6 @@ public class UserVmManagerImplTest {
|
|||
Mockito.doNothing().when(userVmManagerImpl).validateOldAndNewAccounts(Mockito.nullable(Account.class), Mockito.nullable(Account.class), Mockito.anyLong(), Mockito.nullable(String.class), Mockito.nullable(Long.class));
|
||||
Mockito.doNothing().when(userVmManagerImpl).validateIfVmHasNoRules(Mockito.any(), Mockito.anyLong());
|
||||
Mockito.doNothing().when(userVmManagerImpl).removeInstanceFromInstanceGroup(Mockito.anyLong());
|
||||
Mockito.doNothing().when(userVmManagerImpl).verifyResourceLimitsForAccountAndStorage(Mockito.any(), Mockito.any(), Mockito.any(), anyList(), Mockito.any());
|
||||
Mockito.doNothing().when(userVmManagerImpl).validateIfNewOwnerHasAccessToTemplate(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
Mockito.doNothing().when(userVmManagerImpl).updateVmOwner(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
|
@ -1703,23 +1706,11 @@ public class UserVmManagerImplTest {
|
|||
Mockito.when(vol5.isDisplay()).thenReturn(true);
|
||||
|
||||
List<VolumeVO> volumes = List.of(vol1, undisplayedVolume, vol3, vol4, vol5);
|
||||
Long size = volumes.stream().filter(VolumeVO::isDisplay).mapToLong(VolumeVO::getSize).sum();
|
||||
try {
|
||||
userVmManagerImpl.checkVolumesLimits(account, volumes);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimit(account, Resource.ResourceType.volume, 4);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimit(account, Resource.ResourceType.primary_storage, size);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.volume, "tag1", 2);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.volume, "tag2", 3);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, "tag1",
|
||||
vol1.getSize() + vol5.getSize());
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, "tag2",
|
||||
vol1.getSize() + vol3.getSize() + vol5.getSize());
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
userVmManagerImpl.checkVolumesLimits(account, volumes, reservations);
|
||||
Assert.assertEquals(8, reservations.size());
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
|
|
@ -2010,26 +2001,26 @@ public class UserVmManagerImplTest {
|
|||
|
||||
@Test
|
||||
public void verifyResourceLimitsForAccountAndStorageTestCountOnlyRunningVmsInResourceLimitationIsTrueDoesNotCallVmResourceLimitCheck() throws ResourceAllocationException {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
LinkedList<VolumeVO> volumeVoList = new LinkedList<VolumeVO>();
|
||||
Mockito.doReturn(true).when(userVmManagerImpl).countOnlyRunningVmsInResourceLimitation();
|
||||
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock);
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock, reservations);
|
||||
|
||||
Mockito.verify(resourceLimitMgr, Mockito.never()).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.volume, 0l);
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.primary_storage, 0l);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.never()).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(resourceLimitMgr, Mockito.never()).checkVolumeResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyResourceLimitsForAccountAndStorageTestCountOnlyRunningVmsInResourceLimitationIsFalseCallsVmResourceLimitCheck() throws ResourceAllocationException {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
LinkedList<VolumeVO> volumeVoList = new LinkedList<VolumeVO>();
|
||||
Mockito.doReturn(false).when(userVmManagerImpl).countOnlyRunningVmsInResourceLimitation();
|
||||
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock);
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock, reservations);
|
||||
|
||||
Mockito.verify(resourceLimitMgr).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.volume, 0l);
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.primary_storage, 0l);
|
||||
Mockito.verify(resourceLimitMgr).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(userVmManagerImpl).checkVolumesLimits(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -3074,7 +3065,7 @@ public class UserVmManagerImplTest {
|
|||
configureDoNothingForMethodsThatWeDoNotWantToTest();
|
||||
|
||||
doThrow(ResourceAllocationException.class).when(userVmManagerImpl).verifyResourceLimitsForAccountAndStorage(Mockito.any(), Mockito.any(),
|
||||
Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
Assert.assertThrows(ResourceAllocationException.class, () -> userVmManagerImpl.moveVmToUser(assignVmCmdMock));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,13 +357,13 @@ public class VMSnapshotManagerTest {
|
|||
_vmSnapshotMgr.updateUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
|
||||
verify(_vmSnapshotMgr).changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVmMapDetails() {
|
||||
Map<String, String> result = _vmSnapshotMgr.getVmMapDetails(userVm);
|
||||
Map<String, String> result = _vmSnapshotMgr.getVmMapDetails(vmSnapshotVO);
|
||||
assert(result.containsKey(userVmDetailCpuNumber.getName()));
|
||||
assert(result.containsKey(userVmDetailMemory.getName()));
|
||||
assertEquals(userVmDetails.size(), result.size());
|
||||
|
|
@ -375,7 +375,7 @@ public class VMSnapshotManagerTest {
|
|||
public void testChangeUserVmServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ public class VMSnapshotManagerTest {
|
|||
public void testChangeUserVmServiceOfferingFailOnUpgradeVMServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(false);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -952,7 +952,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean resourceCountNeedsUpdate(NetworkOffering ntwkOff, ACLType aclType) {
|
||||
public boolean isResourceCountUpdateNeeded(NetworkOffering ntwkOff) {
|
||||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import javax.naming.ConfigurationException;
|
|||
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
|
|
@ -237,6 +238,11 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkResourceLimitWithTag(Account account, Long domainId, boolean considerSystemAccount, ResourceType type, String tag, long... count) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getResourceLimitHostTags() {
|
||||
return null;
|
||||
|
|
@ -268,19 +274,24 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException {
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
|
||||
DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException {
|
||||
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size,
|
||||
DiskOffering diskOffering) {
|
||||
DiskOffering diskOffering, List<Reserver> reservations) {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -324,7 +335,7 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException {
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -341,19 +352,14 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
@Override
|
||||
public void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering,
|
||||
VirtualMachineTemplate template) throws ResourceAllocationException {
|
||||
VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
|
||||
VirtualMachineTemplate currentTemplate,
|
||||
VirtualMachineTemplate newTemplate) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException {
|
||||
VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -367,11 +373,6 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) {
|
||||
|
||||
|
|
@ -382,11 +383,6 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmGpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) {
|
||||
|
||||
|
|
@ -396,4 +392,9 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
public void decrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long recalculateDomainResourceCount(long domainId, ResourceType type, String tag) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,73 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.backup;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.After;
|
||||
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.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.backup.dao.BackupDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupDetailsDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
||||
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.dc.DataCenter;
|
||||
|
|
@ -31,6 +95,7 @@ import com.cloud.event.ActionEventUtils;
|
|||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
|
|
@ -42,7 +107,6 @@ import com.cloud.offering.DiskOffering;
|
|||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.Volume;
|
||||
|
|
@ -61,6 +125,8 @@ import com.cloud.user.User;
|
|||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.db.DbUtil;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
|
@ -68,68 +134,11 @@ import com.cloud.utils.fsm.NoTransitionException;
|
|||
import com.cloud.vm.VMInstanceDetailVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import com.google.gson.Gson;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.backup.dao.BackupDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupDetailsDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
||||
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BackupManagerTest {
|
||||
|
|
@ -239,6 +248,9 @@ public class BackupManagerTest {
|
|||
@Mock
|
||||
DomainDao domainDao;
|
||||
|
||||
@Mock
|
||||
ReservationDao reservationDao;
|
||||
|
||||
@Mock
|
||||
private GuestOSDao _guestOSDao;
|
||||
|
||||
|
|
@ -252,6 +264,8 @@ public class BackupManagerTest {
|
|||
private AutoCloseable closeable;
|
||||
private ConfigDepotImpl configDepotImpl;
|
||||
private boolean updatedConfigKeyDepot = false;
|
||||
private MockedStatic<DbUtil> dbUtilMockedStatic;
|
||||
private final List<String> mockedGlobalLocks = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
|
|
@ -283,6 +297,29 @@ public class BackupManagerTest {
|
|||
backupProvidersMap.put(backupProvider.getName().toLowerCase(), backupProvider);
|
||||
ReflectionTestUtils.setField(backupManager, "backupProvidersMap", backupProvidersMap);
|
||||
|
||||
when(reservationDao.persist(any(ReservationVO.class)))
|
||||
.thenAnswer((Answer<ReservationVO>) invocation -> {
|
||||
ReservationVO reservationVO = (ReservationVO)invocation.getArguments()[0];
|
||||
ReflectionTestUtils.setField(reservationVO, "id", 10L);
|
||||
return reservationVO;
|
||||
});
|
||||
dbUtilMockedStatic = Mockito.mockStatic(DbUtil.class);
|
||||
dbUtilMockedStatic.when(() -> DbUtil.getGlobalLock(anyString(), anyInt())).thenAnswer((Answer<Boolean>) invocation -> {
|
||||
String lockName = invocation.getArgument(0);
|
||||
if (!StringUtils.isBlank(lockName) && !mockedGlobalLocks.contains(lockName)) {
|
||||
mockedGlobalLocks.add(lockName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
dbUtilMockedStatic.when(() -> DbUtil.releaseGlobalLock(anyString())).thenAnswer((Answer<Boolean>) invocation -> {
|
||||
String lockName = invocation.getArgument(0);
|
||||
if (!StringUtils.isBlank(lockName)) {
|
||||
mockedGlobalLocks.remove(lockName);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
Account account = mock(Account.class);
|
||||
User user = mock(User.class);
|
||||
CallContext.register(user, account);
|
||||
|
|
@ -290,6 +327,7 @@ public class BackupManagerTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
dbUtilMockedStatic.close();
|
||||
closeable.close();
|
||||
if (updatedConfigKeyDepot) {
|
||||
ReflectionTestUtils.setField(BackupManager.BackupFrameworkEnabled, "s_depot", configDepotImpl);
|
||||
|
|
@ -626,6 +664,7 @@ public class BackupManagerTest {
|
|||
Long oldestBackupId = 7L;
|
||||
Long newBackupSize = 1000000000L;
|
||||
Long oldBackupSize = 400000000L;
|
||||
long domainId = 101L;
|
||||
|
||||
when(vmInstanceDao.findById(vmId)).thenReturn(vmInstanceVOMock);
|
||||
when(vmInstanceVOMock.getDataCenterId()).thenReturn(zoneId);
|
||||
|
|
@ -640,6 +679,7 @@ public class BackupManagerTest {
|
|||
Mockito.doReturn(scheduleId).when(backupManager).getBackupScheduleId(asyncJobVOMock);
|
||||
|
||||
when(accountManager.getAccount(accountId)).thenReturn(accountVOMock);
|
||||
when(accountVOMock.getDomainId()).thenReturn(domainId);
|
||||
|
||||
BackupScheduleVO schedule = mock(BackupScheduleVO.class);
|
||||
when(backupScheduleDao.findById(scheduleId)).thenReturn(schedule);
|
||||
|
|
@ -681,8 +721,10 @@ public class BackupManagerTest {
|
|||
|
||||
assertTrue(backupManager.createBackup(cmd, asyncJobVOMock));
|
||||
|
||||
Mockito.verify(resourceLimitMgr, times(1)).checkResourceLimit(accountVOMock, Resource.ResourceType.backup);
|
||||
Mockito.verify(resourceLimitMgr, times(1)).checkResourceLimit(accountVOMock, Resource.ResourceType.backup_storage, newBackupSize);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimitWithTag(accountVOMock, domainId, true, Resource.ResourceType.backup, null, 1L);
|
||||
Mockito.verify(resourceLimitMgr, times(1))
|
||||
.checkResourceLimitWithTag(accountVOMock, domainId, true, Resource.ResourceType.backup_storage, null, newBackupSize);
|
||||
|
||||
Mockito.verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup);
|
||||
Mockito.verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, newBackupSize);
|
||||
|
|
@ -698,6 +740,7 @@ public class BackupManagerTest {
|
|||
Long scheduleId = 3L;
|
||||
Long backupOfferingId = 4L;
|
||||
Long accountId = 5L;
|
||||
long domainId = 101L;
|
||||
|
||||
when(vmInstanceDao.findById(vmId)).thenReturn(vmInstanceVOMock);
|
||||
when(vmInstanceVOMock.getDataCenterId()).thenReturn(zoneId);
|
||||
|
|
@ -712,7 +755,9 @@ public class BackupManagerTest {
|
|||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(accountManager.getAccount(accountId)).thenReturn(account);
|
||||
Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup)).when(resourceLimitMgr).checkResourceLimit(account, Resource.ResourceType.backup);
|
||||
when(account.getDomainId()).thenReturn(domainId);
|
||||
Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup)).when(resourceLimitMgr)
|
||||
.checkResourceLimitWithTag(account, domainId, true, Resource.ResourceType.backup, null, 1L);
|
||||
|
||||
CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
|
||||
when(cmd.getVmId()).thenReturn(vmId);
|
||||
|
|
@ -736,6 +781,8 @@ public class BackupManagerTest {
|
|||
Long scheduleId = 3L;
|
||||
Long backupOfferingId = 4L;
|
||||
Long accountId = 5L;
|
||||
long domainId = 101L;
|
||||
long size = 10000L;
|
||||
|
||||
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
|
||||
when(vmInstanceDao.findById(vmId)).thenReturn(vm);
|
||||
|
|
@ -743,6 +790,11 @@ public class BackupManagerTest {
|
|||
when(vm.getBackupOfferingId()).thenReturn(backupOfferingId);
|
||||
when(vm.getAccountId()).thenReturn(accountId);
|
||||
|
||||
VolumeVO volume = mock(VolumeVO.class);
|
||||
when(volumeDao.findByInstance(vmId)).thenReturn(List.of(volume));
|
||||
when(volume.getState()).thenReturn(Volume.State.Ready);
|
||||
when(volumeApiService.getVolumePhysicalSize(null, null, null)).thenReturn(size);
|
||||
|
||||
overrideBackupFrameworkConfigValue();
|
||||
BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.findById(backupOfferingId)).thenReturn(offering);
|
||||
|
|
@ -753,7 +805,10 @@ public class BackupManagerTest {
|
|||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(accountManager.getAccount(accountId)).thenReturn(account);
|
||||
Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup_storage)).when(resourceLimitMgr).checkResourceLimit(account, Resource.ResourceType.backup_storage, 0L);
|
||||
when(account.getDomainId()).thenReturn(domainId);
|
||||
Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup_storage))
|
||||
.when(resourceLimitMgr)
|
||||
.checkResourceLimitWithTag(account, domainId, true, Resource.ResourceType.backup_storage, null, size);
|
||||
|
||||
CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
|
||||
when(cmd.getVmId()).thenReturn(vmId);
|
||||
|
|
@ -1491,6 +1546,7 @@ public class BackupManagerTest {
|
|||
when(backup.getVmId()).thenReturn(vmId);
|
||||
when(backup.getZoneId()).thenReturn(zoneId);
|
||||
when(backup.getAccountId()).thenReturn(accountId);
|
||||
when(accountManager.getAccount(accountId)).thenReturn(accountVOMock);
|
||||
when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
|
||||
when(backup.getSize()).thenReturn(100L);
|
||||
when(backup.getUuid()).thenReturn("backup-uuid");
|
||||
|
|
|
|||
|
|
@ -16,19 +16,36 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.storage.object;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.bucket.CreateBucketCmd;
|
||||
import org.apache.cloudstack.api.command.user.bucket.UpdateBucketCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.After;
|
||||
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.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.cloud.agent.api.to.BucketTO;
|
||||
|
|
@ -40,6 +57,9 @@ import com.cloud.storage.DataStoreRole;
|
|||
import com.cloud.storage.dao.BucketDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.utils.db.DbUtil;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BucketApiServiceImplTest {
|
||||
|
|
@ -62,33 +82,90 @@ public class BucketApiServiceImplTest {
|
|||
@Mock
|
||||
private BucketDao bucketDao;
|
||||
|
||||
@Mock
|
||||
ReservationDao reservationDao;
|
||||
|
||||
@Mock
|
||||
private AccountVO mockAccountVO;
|
||||
|
||||
private MockedStatic<DbUtil> dbUtilMockedStatic;
|
||||
private final List<String> mockedGlobalLocks = new ArrayList<>();
|
||||
private static final long ACCOUNT_ID = 1001L;
|
||||
private static final long DOMAIN_ID = 10L;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
when(accountManager.getActiveAccountById(ACCOUNT_ID)).thenReturn(mockAccountVO);
|
||||
when(mockAccountVO.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
when(reservationDao.persist(any(ReservationVO.class)))
|
||||
.thenAnswer((Answer<ReservationVO>) invocation -> {
|
||||
ReservationVO reservationVO = (ReservationVO)invocation.getArguments()[0];
|
||||
ReflectionTestUtils.setField(reservationVO, "id", 10L);
|
||||
return reservationVO;
|
||||
});
|
||||
dbUtilMockedStatic = Mockito.mockStatic(DbUtil.class);
|
||||
dbUtilMockedStatic.when(() -> DbUtil.getGlobalLock(anyString(), anyInt()))
|
||||
.thenAnswer((Answer<Boolean>) invocation -> {
|
||||
String lockName = invocation.getArgument(0);
|
||||
if (!StringUtils.isBlank(lockName) && !mockedGlobalLocks.contains(lockName)) {
|
||||
mockedGlobalLocks.add(lockName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
dbUtilMockedStatic.when(() -> DbUtil.releaseGlobalLock(anyString()))
|
||||
.thenAnswer((Answer<Boolean>) invocation -> {
|
||||
String lockName = invocation.getArgument(0);
|
||||
if (!StringUtils.isBlank(lockName)) {
|
||||
mockedGlobalLocks.remove(lockName);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
Account account = mock(Account.class);
|
||||
User user = mock(User.class);
|
||||
CallContext.register(user, account);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
dbUtilMockedStatic.close();
|
||||
CallContext.unregister();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllocBucket() throws ResourceAllocationException {
|
||||
String bucketName = "bucket1";
|
||||
Long accountId = 1L;
|
||||
Long poolId = 2L;
|
||||
Long objectStoreId = 3L;
|
||||
int quota = 1;
|
||||
|
||||
CreateBucketCmd cmd = Mockito.mock(CreateBucketCmd.class);
|
||||
Mockito.when(cmd.getBucketName()).thenReturn(bucketName);
|
||||
Mockito.when(cmd.getEntityOwnerId()).thenReturn(accountId);
|
||||
Mockito.when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
Mockito.when(cmd.getObjectStoragePoolId()).thenReturn(poolId);
|
||||
Mockito.when(cmd.getQuota()).thenReturn(1);
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
Mockito.when(accountManager.getActiveAccountById(accountId)).thenReturn(account);
|
||||
Mockito.when(cmd.getQuota()).thenReturn(quota);
|
||||
|
||||
ObjectStoreVO objectStoreVO = Mockito.mock(ObjectStoreVO.class);
|
||||
Mockito.when(objectStoreVO.getId()).thenReturn(objectStoreId);
|
||||
Mockito.when(objectStoreDao.findById(poolId)).thenReturn(objectStoreVO);
|
||||
ObjectStoreEntity objectStore = Mockito.mock(ObjectStoreEntity.class);
|
||||
Mockito.when(dataStoreMgr.getDataStore(objectStoreId, DataStoreRole.Object)).thenReturn(objectStore);
|
||||
Mockito.when(objectStore.createUser(accountId)).thenReturn(true);
|
||||
Mockito.when(objectStore.createUser(ACCOUNT_ID)).thenReturn(true);
|
||||
|
||||
bucketApiService.allocBucket(cmd);
|
||||
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimit(account, Resource.ResourceType.bucket);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimit(account, Resource.ResourceType.object_storage, 1 * Resource.ResourceType.bytesToGiB);
|
||||
long size = quota * Resource.ResourceType.bytesToGiB;
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(mockAccountVO, DOMAIN_ID, true,
|
||||
Resource.ResourceType.bucket, null, 1L);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(mockAccountVO, DOMAIN_ID, true,
|
||||
Resource.ResourceType.object_storage, null, size);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.incrementResourceCount(ACCOUNT_ID, Resource.ResourceType.bucket);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.incrementResourceCount(ACCOUNT_ID, Resource.ResourceType.object_storage, size);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -96,21 +173,21 @@ public class BucketApiServiceImplTest {
|
|||
Long objectStoreId = 1L;
|
||||
Long poolId = 2L;
|
||||
Long bucketId = 3L;
|
||||
Long accountId = 4L;
|
||||
String bucketName = "bucket1";
|
||||
int quota = 3;
|
||||
|
||||
CreateBucketCmd cmd = Mockito.mock(CreateBucketCmd.class);
|
||||
Mockito.when(cmd.getObjectStoragePoolId()).thenReturn(poolId);
|
||||
Mockito.when(cmd.getEntityId()).thenReturn(bucketId);
|
||||
Mockito.when(cmd.getQuota()).thenReturn(1);
|
||||
Mockito.when(cmd.getQuota()).thenReturn(quota);
|
||||
|
||||
BucketVO bucket = new BucketVO(bucketName);
|
||||
Mockito.when(bucketDao.findById(bucketId)).thenReturn(bucket);
|
||||
ReflectionTestUtils.setField(bucket, "accountId", accountId);
|
||||
ReflectionTestUtils.setField(bucket, "accountId", ACCOUNT_ID);
|
||||
|
||||
ObjectStoreVO objectStoreVO = Mockito.mock(ObjectStoreVO.class);
|
||||
Mockito.when(objectStoreVO.getId()).thenReturn(objectStoreId);
|
||||
Mockito.when(objectStoreVO.getTotalSize()).thenReturn(2000000000L);
|
||||
Mockito.when(objectStoreVO.getTotalSize()).thenReturn(10 * Resource.ResourceType.bytesToGiB);
|
||||
Mockito.when(objectStoreDao.findById(poolId)).thenReturn(objectStoreVO);
|
||||
ObjectStoreEntity objectStore = Mockito.mock(ObjectStoreEntity.class);
|
||||
Mockito.when(dataStoreMgr.getDataStore(objectStoreId, DataStoreRole.Object)).thenReturn(objectStore);
|
||||
|
|
@ -118,23 +195,23 @@ public class BucketApiServiceImplTest {
|
|||
|
||||
bucketApiService.createBucket(cmd);
|
||||
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).incrementResourceCount(accountId, Resource.ResourceType.bucket);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).incrementResourceCount(accountId, Resource.ResourceType.object_storage, 1 * Resource.ResourceType.bytesToGiB);
|
||||
Assert.assertEquals(bucket.getState(), Bucket.State.Created);
|
||||
Assert.assertEquals(Bucket.State.Created, bucket.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteBucket() {
|
||||
Long bucketId = 1L;
|
||||
Long accountId = 2L;
|
||||
Long objectStoreId = 3L;
|
||||
String bucketName = "bucket1";
|
||||
int quota = 2;
|
||||
|
||||
BucketVO bucket = new BucketVO(bucketName);
|
||||
BucketVO bucket = mock(BucketVO.class);
|
||||
when(bucket.getName()).thenReturn(bucketName);
|
||||
when(bucket.getObjectStoreId()).thenReturn(objectStoreId);
|
||||
when(bucket.getQuota()).thenReturn(quota);
|
||||
when(bucket.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(accountManager.getAccount(ACCOUNT_ID)).thenReturn(mock(AccountVO.class));
|
||||
Mockito.when(bucketDao.findById(bucketId)).thenReturn(bucket);
|
||||
ReflectionTestUtils.setField(bucket, "objectStoreId", objectStoreId);
|
||||
ReflectionTestUtils.setField(bucket, "quota", 1);
|
||||
ReflectionTestUtils.setField(bucket, "accountId", accountId);
|
||||
|
||||
ObjectStoreVO objectStoreVO = Mockito.mock(ObjectStoreVO.class);
|
||||
Mockito.when(objectStoreVO.getId()).thenReturn(objectStoreId);
|
||||
|
|
@ -145,15 +222,17 @@ public class BucketApiServiceImplTest {
|
|||
|
||||
bucketApiService.deleteBucket(bucketId, null);
|
||||
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).decrementResourceCount(accountId, Resource.ResourceType.bucket);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).decrementResourceCount(accountId, Resource.ResourceType.object_storage, 1 * Resource.ResourceType.bytesToGiB);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.decrementResourceCount(ACCOUNT_ID, Resource.ResourceType.bucket);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.decrementResourceCount(ACCOUNT_ID, Resource.ResourceType.object_storage,
|
||||
quota * Resource.ResourceType.bytesToGiB);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateBucket() throws ResourceAllocationException {
|
||||
Long bucketId = 1L;
|
||||
Long objectStoreId = 2L;
|
||||
Long accountId = 3L;
|
||||
Integer bucketQuota = 2;
|
||||
Integer cmdQuota = 1;
|
||||
String bucketName = "bucket1";
|
||||
|
|
@ -164,12 +243,10 @@ public class BucketApiServiceImplTest {
|
|||
|
||||
BucketVO bucket = new BucketVO(bucketName);
|
||||
ReflectionTestUtils.setField(bucket, "quota", bucketQuota);
|
||||
ReflectionTestUtils.setField(bucket, "accountId", accountId);
|
||||
ReflectionTestUtils.setField(bucket, "accountId", ACCOUNT_ID);
|
||||
ReflectionTestUtils.setField(bucket, "objectStoreId", objectStoreId);
|
||||
Mockito.when(bucketDao.findById(bucketId)).thenReturn(bucket);
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
|
||||
ObjectStoreVO objectStoreVO = Mockito.mock(ObjectStoreVO.class);
|
||||
Mockito.when(objectStoreVO.getId()).thenReturn(objectStoreId);
|
||||
Mockito.when(objectStoreDao.findById(objectStoreId)).thenReturn(objectStoreVO);
|
||||
|
|
@ -178,6 +255,8 @@ public class BucketApiServiceImplTest {
|
|||
|
||||
bucketApiService.updateBucket(cmd, null);
|
||||
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).decrementResourceCount(accountId, Resource.ResourceType.object_storage, (bucketQuota - cmdQuota) * Resource.ResourceType.bytesToGiB);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.decrementResourceCount(ACCOUNT_ID, Resource.ResourceType.object_storage,
|
||||
(bucketQuota - cmdQuota) * Resource.ResourceType.bytesToGiB);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,9 +268,6 @@ public class VolumeImportUnmanageManagerImplTest {
|
|||
doNothing().when(volumeImportUnmanageManager).checkIfVolumeIsEncrypted(volumeOnStorageTO);
|
||||
doNothing().when(volumeImportUnmanageManager).checkIfVolumeHasBackingFile(volumeOnStorageTO);
|
||||
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.volume);
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.primary_storage, virtualSize);
|
||||
|
||||
DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
|
||||
when(diskOffering.isCustomized()).thenReturn(true);
|
||||
doReturn(diskOffering).when(volumeImportUnmanageManager).getOrCreateDiskOffering(account, diskOfferingId, zoneId, isLocal);
|
||||
|
|
|
|||
|
|
@ -39,11 +39,22 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.vm.ImportVMTaskVO;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
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.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ResponseGenerator;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
|
|
@ -66,20 +77,6 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
|||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
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.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
|
@ -98,7 +95,6 @@ import com.cloud.agent.api.GetUnmanagedInstancesCommand;
|
|||
import com.cloud.agent.api.ImportConvertedInstanceAnswer;
|
||||
import com.cloud.agent.api.ImportConvertedInstanceCommand;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
|
@ -115,7 +111,6 @@ import com.cloud.exception.InsufficientServerCapacityException;
|
|||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.UnsupportedServiceException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
|
|
@ -128,16 +123,20 @@ import com.cloud.network.Network;
|
|||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.StoragePoolHostVO;
|
||||
|
|
@ -147,6 +146,7 @@ import com.cloud.storage.Volume;
|
|||
import com.cloud.storage.VolumeApiService;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
|
|
@ -164,6 +164,7 @@ import com.cloud.utils.Pair;
|
|||
import com.cloud.utils.db.EntityManager;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.ImportVMTaskVO;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.UserVmManager;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
|
|
@ -308,7 +309,6 @@ public class UnmanagedVMsManagerImplTest {
|
|||
clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString());
|
||||
when(clusterDao.findById(anyLong())).thenReturn(clusterVO);
|
||||
when(configurationDao.getValue(Mockito.anyString())).thenReturn(null);
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong());
|
||||
List<HostVO> hosts = new ArrayList<>();
|
||||
HostVO hostVO = Mockito.mock(HostVO.class);
|
||||
when(hostVO.isInMaintenanceStates()).thenReturn(false);
|
||||
|
|
@ -448,7 +448,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance");
|
||||
when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null);
|
||||
when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -650,7 +651,7 @@ public class UnmanagedVMsManagerImplTest {
|
|||
DeployDestination mockDest = Mockito.mock(DeployDestination.class);
|
||||
when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest);
|
||||
DiskProfile diskProfile = Mockito.mock(DiskProfile.class);
|
||||
when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()))
|
||||
when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean()))
|
||||
.thenReturn(diskProfile);
|
||||
Map<Volume, StoragePool> storage = new HashMap<>();
|
||||
VolumeVO volume = Mockito.mock(VolumeVO.class);
|
||||
|
|
@ -662,7 +663,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
CopyRemoteVolumeAnswer copyAnswer = Mockito.mock(CopyRemoteVolumeAnswer.class);
|
||||
when(copyAnswer.getResult()).thenReturn(true);
|
||||
when(agentManager.easySend(anyLong(), any(CopyRemoteVolumeCommand.class))).thenReturn(copyAnswer);
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importVm(cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -850,7 +852,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer);
|
||||
}
|
||||
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importVm(importVmCmd);
|
||||
verify(vmwareGuru).getHypervisorVMOutOfBandAndCloneIfRequired(Mockito.eq(host), Mockito.eq(vmName), anyMap());
|
||||
verify(vmwareGuru).createVMTemplateOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap(), any(DataStoreTO.class), anyInt());
|
||||
|
|
@ -884,7 +887,7 @@ public class UnmanagedVMsManagerImplTest {
|
|||
DeployDestination mockDest = Mockito.mock(DeployDestination.class);
|
||||
when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest);
|
||||
DiskProfile diskProfile = Mockito.mock(DiskProfile.class);
|
||||
when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()))
|
||||
when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean()))
|
||||
.thenReturn(diskProfile);
|
||||
Map<Volume, StoragePool> storage = new HashMap<>();
|
||||
VolumeVO volume = Mockito.mock(VolumeVO.class);
|
||||
|
|
@ -903,7 +906,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
|
||||
StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class);
|
||||
when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost);
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importVm(cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -1251,42 +1255,6 @@ public class UnmanagedVMsManagerImplTest {
|
|||
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckUnmanagedDiskLimits() {
|
||||
Account owner = Mockito.mock(Account.class);
|
||||
UnmanagedInstanceTO.Disk disk = Mockito.mock(UnmanagedInstanceTO.Disk.class);
|
||||
Mockito.when(disk.getDiskId()).thenReturn("disk1");
|
||||
Mockito.when(disk.getCapacity()).thenReturn(100L);
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
Mockito.when(serviceOffering.getDiskOfferingId()).thenReturn(1L);
|
||||
UnmanagedInstanceTO.Disk dataDisk = Mockito.mock(UnmanagedInstanceTO.Disk.class);
|
||||
Mockito.when(dataDisk.getDiskId()).thenReturn("disk2");
|
||||
Mockito.when(dataDisk.getCapacity()).thenReturn(1000L);
|
||||
Map<String, Long> dataDiskMap = new HashMap<>();
|
||||
dataDiskMap.put("disk2", 2L);
|
||||
DiskOfferingVO offering1 = Mockito.mock(DiskOfferingVO.class);
|
||||
Mockito.when(diskOfferingDao.findById(1L)).thenReturn(offering1);
|
||||
String tag1 = "tag1";
|
||||
Mockito.when(resourceLimitService.getResourceLimitStorageTags(offering1)).thenReturn(List.of(tag1));
|
||||
DiskOfferingVO offering2 = Mockito.mock(DiskOfferingVO.class);
|
||||
Mockito.when(diskOfferingDao.findById(2L)).thenReturn(offering2);
|
||||
String tag2 = "tag2";
|
||||
Mockito.when(resourceLimitService.getResourceLimitStorageTags(offering2)).thenReturn(List.of(tag2));
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitService).checkResourceLimit(any(), any(), any());
|
||||
Mockito.doNothing().when(resourceLimitService).checkResourceLimitWithTag(any(), any(), any(), any());
|
||||
unmanagedVMsManager.checkUnmanagedDiskLimits(owner, disk, serviceOffering, List.of(dataDisk), dataDiskMap);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimit(owner, Resource.ResourceType.volume, 2);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimit(owner, Resource.ResourceType.primary_storage, 1100L);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.volume, tag1,1);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.volume, tag2,1);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.primary_storage, tag1,100L);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.primary_storage, tag2,1000L);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckConversionStoragePoolSecondaryStorageStaging() {
|
||||
unmanagedVMsManager.checkConversionStoragePool(null, false);
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
|
|||
if (decoder != null) {
|
||||
decoder.cleanFiles();
|
||||
}
|
||||
storageResource.deregisterUploadChannel(uuid);
|
||||
requestProcessed = false;
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +183,7 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
|
|||
requestProcessed = true;
|
||||
return;
|
||||
}
|
||||
storageResource.registerUploadChannel(uuid, ctx.channel());
|
||||
//set the base directory to download the file
|
||||
DiskFileUpload.baseDirectory = uploadEntity.getInstallPathPrefix();
|
||||
this.processTimeout = uploadEntity.getProcessTimeout();
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
|
@ -258,7 +259,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
protected String _parent = "/mnt/SecStorage";
|
||||
final private String _tmpltpp = "template.properties";
|
||||
protected String createTemplateFromSnapshotXenScript;
|
||||
private HashMap<String, UploadEntity> uploadEntityStateMap = new HashMap<>();
|
||||
private final Map<String, UploadEntity> uploadEntityStateMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, Channel> uploadChannelMap = new ConcurrentHashMap<>();
|
||||
private String _ssvmPSK = null;
|
||||
private long processTimeout;
|
||||
|
||||
|
|
@ -2399,6 +2401,20 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
String entityUuid = cmd.getEntityUuid();
|
||||
if (uploadEntityStateMap.containsKey(entityUuid)) {
|
||||
UploadEntity uploadEntity = uploadEntityStateMap.get(entityUuid);
|
||||
if (Boolean.TRUE.equals(cmd.getAbort())) {
|
||||
updateStateMapWithError(entityUuid, "Upload Entity aborted");
|
||||
String errorMsg = uploadEntity.getErrorMessage();
|
||||
if (errorMsg == null) {
|
||||
errorMsg = "Upload aborted by management server";
|
||||
}
|
||||
Channel channel = uploadChannelMap.remove(entityUuid);
|
||||
if (channel != null && channel.isActive()) {
|
||||
logger.info("Closing upload channel for entity {}", entityUuid);
|
||||
channel.close();
|
||||
}
|
||||
uploadEntityStateMap.remove(entityUuid);
|
||||
return new UploadStatusAnswer(cmd, UploadStatus.ERROR, errorMsg);
|
||||
}
|
||||
if (uploadEntity.getUploadState() == UploadEntity.Status.ERROR) {
|
||||
uploadEntityStateMap.remove(entityUuid);
|
||||
return new UploadStatusAnswer(cmd, UploadStatus.ERROR, uploadEntity.getErrorMessage());
|
||||
|
|
@ -2417,6 +2433,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
UploadStatusAnswer answer = new UploadStatusAnswer(cmd, UploadStatus.IN_PROGRESS);
|
||||
long downloadedSize = FileUtils.sizeOfDirectory(new File(uploadEntity.getInstallPathPrefix()));
|
||||
int downloadPercent = (int)(100 * downloadedSize / uploadEntity.getContentLength());
|
||||
answer.setPhysicalSize(downloadedSize);
|
||||
answer.setDownloadPercent(Math.min(downloadPercent, 100));
|
||||
return answer;
|
||||
}
|
||||
|
|
@ -3446,6 +3463,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
|
||||
public String postUpload(String uuid, String filename, long processTimeout) {
|
||||
UploadEntity uploadEntity = uploadEntityStateMap.get(uuid);
|
||||
if (uploadEntity == null) {
|
||||
logger.warn("Upload entity not found for uuid: {}. Upload may have been aborted.", uuid);
|
||||
return "Upload entity not found. Upload may have been aborted.";
|
||||
}
|
||||
int installTimeoutPerGig = 180 * 60 * 1000;
|
||||
|
||||
String resourcePath = uploadEntity.getInstallPathPrefix();
|
||||
|
|
@ -3596,6 +3617,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
return _ssvmPSK;
|
||||
}
|
||||
|
||||
public void registerUploadChannel(String uuid, Channel channel) {
|
||||
uploadChannelMap.put(uuid, channel);
|
||||
}
|
||||
|
||||
public void deregisterUploadChannel(String uuid) {
|
||||
if (uuid != null) {
|
||||
uploadChannelMap.remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateStateMapWithError(String uuid, String errorMessage) {
|
||||
UploadEntity uploadEntity = null;
|
||||
if (uploadEntityStateMap.get(uuid) != null) {
|
||||
|
|
|
|||
|
|
@ -999,7 +999,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
|
|||
break; // TODO
|
||||
}
|
||||
return new DownloadAnswer(jobId, getDownloadPct(jobId), getDownloadError(jobId), getDownloadStatus2(jobId), getDownloadLocalPath(jobId), getInstallPath(jobId),
|
||||
getDownloadTemplateSize(jobId), getDownloadTemplatePhysicalSize(jobId), getDownloadCheckSum(jobId));
|
||||
getDownloadTemplateSize(jobId), td.getDownloadedBytes(), getDownloadCheckSum(jobId));
|
||||
}
|
||||
|
||||
private String getInstallPath(String jobId) {
|
||||
|
|
|
|||
|
|
@ -2104,6 +2104,7 @@
|
|||
"label.requireshvm": "HVM",
|
||||
"label.requiresupgrade": "Requires upgrade",
|
||||
"label.reserved": "Reserved",
|
||||
"label.reservedresourcedetails": "Reserved resource details",
|
||||
"label.reserved.system.gateway": "Reserved system gateway",
|
||||
"label.reserved.system.ip": "Reserved system IP",
|
||||
"label.reserved.system.netmask": "Reserved system netmask",
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default {
|
|||
}, 'created']
|
||||
return fields
|
||||
},
|
||||
details: ['name', 'description', 'id', 'type', 'details', 'path', 'pathready', 'isuserdefined', 'orchestratorrequirespreparevm', 'created'],
|
||||
details: ['name', 'description', 'id', 'type', 'details', 'path', 'pathready', 'isuserdefined', 'orchestratorrequirespreparevm', 'reservedresourcedetails', 'created'],
|
||||
filters: ['orchestrator'],
|
||||
tabs: [{
|
||||
name: 'details',
|
||||
|
|
|
|||
|
|
@ -89,6 +89,14 @@
|
|||
<details-input
|
||||
v-model:value="form.details" />
|
||||
</a-form-item>
|
||||
<a-form-item name="reservedresourcedetails" ref="reservedresourcedetails">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.reservedresourcedetails')" :tooltip="apiParams.reservedresourcedetails.description"/>
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.reservedresourcedetails"
|
||||
:placeholder="apiParams.reservedresourcedetails.description" />
|
||||
</a-form-item>
|
||||
<a-form-item name="state" ref="state">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.enabled')" :tooltip="apiParams.state.description"/>
|
||||
|
|
@ -201,6 +209,9 @@ export default {
|
|||
params['details[0].' + key] = value
|
||||
})
|
||||
}
|
||||
if (values.reservedresourcedetails) {
|
||||
params.reservedresourcedetails = values.reservedresourcedetails
|
||||
}
|
||||
postAPI('createExtension', params).then(response => {
|
||||
this.$emit('refresh-data')
|
||||
this.$notification.success({
|
||||
|
|
|
|||
|
|
@ -46,6 +46,14 @@
|
|||
<details-input
|
||||
v-model:value="form.details" />
|
||||
</a-form-item>
|
||||
<a-form-item name="reservedresourcedetails" ref="reservedresourcedetails">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.reservedresourcedetails')" :tooltip="apiParams.reservedresourcedetails.description"/>
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.reservedresourcedetails"
|
||||
:placeholder="apiParams.reservedresourcedetails.description" />
|
||||
</a-form-item>
|
||||
<div :span="24" class="action-button">
|
||||
<a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
|
||||
<a-button :loading="loading" ref="submit" type="primary" @click="handleSubmit">{{ $t('label.ok') }}</a-button>
|
||||
|
|
@ -90,13 +98,16 @@ export default {
|
|||
this.form = reactive({
|
||||
description: this.resource.description,
|
||||
details: this.resource.details,
|
||||
orchestratorrequirespreparevm: this.resource.orchestratorrequirespreparevm
|
||||
orchestratorrequirespreparevm: this.resource.orchestratorrequirespreparevm,
|
||||
reservedresourcedetails: this.resource.reservedresourcedetails
|
||||
})
|
||||
},
|
||||
fetchData () {
|
||||
this.loading = true
|
||||
getAPI('listExtensions', { id: this.resource.id }).then(json => {
|
||||
this.form.details = json?.listextensionsresponse?.extension?.[0]?.details
|
||||
const ext = json?.listextensionsresponse?.extension?.[0] || {}
|
||||
this.form.details = ext.details
|
||||
this.form.reservedresourcedetails = ext.reservedresourcedetails
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
|
|
@ -110,7 +121,7 @@ export default {
|
|||
const params = {
|
||||
id: this.resource.id
|
||||
}
|
||||
const keys = ['description', 'orchestratorrequirespreparevm']
|
||||
const keys = ['description', 'orchestratorrequirespreparevm', 'reservedresourcedetails']
|
||||
for (const key of keys) {
|
||||
if (values[key] !== undefined || values[key] !== null) {
|
||||
params[key] = values[key]
|
||||
|
|
|
|||
Loading…
Reference in New Issue