mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge remote-tracking branch 'apache/4.19'
This commit is contained in:
commit
45daa1ce59
@ -175,6 +175,8 @@ public interface VolumeApiService {
|
|||||||
|
|
||||||
boolean validateVolumeSizeInBytes(long size);
|
boolean validateVolumeSizeInBytes(long size);
|
||||||
|
|
||||||
|
void validateDestroyVolume(Volume volume, Account caller, boolean expunge, boolean forceExpunge);
|
||||||
|
|
||||||
Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) throws ResourceAllocationException;
|
Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) throws ResourceAllocationException;
|
||||||
|
|
||||||
void publishVolumeCreationUsageEvent(Volume volume);
|
void publishVolumeCreationUsageEvent(Volume volume);
|
||||||
|
|||||||
@ -492,7 +492,7 @@ public interface UserVmService {
|
|||||||
|
|
||||||
UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
|
UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
|
||||||
|
|
||||||
UserVm restoreVirtualMachine(Account caller, long vmId, Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException;
|
UserVm restoreVirtualMachine(Account caller, long vmId, Long newTemplateId, Long rootDiskOfferingId, boolean expunge, Map<String, String> details) throws InsufficientCapacityException, ResourceUnavailableException;
|
||||||
|
|
||||||
UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
|
UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
|
||||||
VirtualMachineMigrationException;
|
VirtualMachineMigrationException;
|
||||||
|
|||||||
@ -16,9 +16,9 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.api.command.user.vm;
|
package org.apache.cloudstack.api.command.user.vm;
|
||||||
|
|
||||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
import com.cloud.vm.VmDetailConstants;
|
||||||
|
|
||||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||||
|
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||||
import org.apache.cloudstack.api.ACL;
|
import org.apache.cloudstack.api.ACL;
|
||||||
import org.apache.cloudstack.api.APICommand;
|
import org.apache.cloudstack.api.APICommand;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
@ -28,6 +28,7 @@ import org.apache.cloudstack.api.Parameter;
|
|||||||
import org.apache.cloudstack.api.ResponseObject.ResponseView;
|
import org.apache.cloudstack.api.ResponseObject.ResponseView;
|
||||||
import org.apache.cloudstack.api.ServerApiException;
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
import org.apache.cloudstack.api.command.user.UserCmd;
|
import org.apache.cloudstack.api.command.user.UserCmd;
|
||||||
|
import org.apache.cloudstack.api.response.DiskOfferingResponse;
|
||||||
import org.apache.cloudstack.api.response.TemplateResponse;
|
import org.apache.cloudstack.api.response.TemplateResponse;
|
||||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
@ -41,6 +42,8 @@ import com.cloud.user.Account;
|
|||||||
import com.cloud.uservm.UserVm;
|
import com.cloud.uservm.UserVm;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
|
@APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
|
||||||
requestHasSensitiveInfo = false,
|
requestHasSensitiveInfo = false,
|
||||||
responseHasSensitiveInfo = true)
|
responseHasSensitiveInfo = true)
|
||||||
@ -58,6 +61,28 @@ public class RestoreVMCmd extends BaseAsyncCmd implements UserCmd {
|
|||||||
description = "an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO")
|
description = "an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO")
|
||||||
private Long templateId;
|
private Long templateId;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.DISK_OFFERING_ID,
|
||||||
|
type = CommandType.UUID,
|
||||||
|
entityType = DiskOfferingResponse.class,
|
||||||
|
description = "Override root volume's diskoffering.", since = "4.19.1")
|
||||||
|
private Long rootDiskOfferingId;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ROOT_DISK_SIZE,
|
||||||
|
type = CommandType.LONG,
|
||||||
|
description = "Override root volume's size (in GB). Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided",
|
||||||
|
since = "4.19.1")
|
||||||
|
private Long rootDiskSize;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.19.1",
|
||||||
|
description = "used to specify the custom parameters")
|
||||||
|
private Map details;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.EXPUNGE,
|
||||||
|
type = CommandType.BOOLEAN,
|
||||||
|
description = "Optional field to expunge old root volume after restore.",
|
||||||
|
since = "4.19.1")
|
||||||
|
private Boolean expungeRootDisk;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getEventType() {
|
public String getEventType() {
|
||||||
return EventTypes.EVENT_VM_RESTORE;
|
return EventTypes.EVENT_VM_RESTORE;
|
||||||
@ -110,6 +135,22 @@ public class RestoreVMCmd extends BaseAsyncCmd implements UserCmd {
|
|||||||
return getVmId();
|
return getVmId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getRootDiskOfferingId() {
|
||||||
|
return rootDiskOfferingId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getDetails() {
|
||||||
|
Map<String, String> customparameterMap = convertDetailsToMap(details);
|
||||||
|
if (rootDiskSize != null && !customparameterMap.containsKey(VmDetailConstants.ROOT_DISK_SIZE)) {
|
||||||
|
customparameterMap.put(VmDetailConstants.ROOT_DISK_SIZE, rootDiskSize.toString());
|
||||||
|
}
|
||||||
|
return customparameterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getExpungeRootDisk() {
|
||||||
|
return expungeRootDisk != null && expungeRootDisk;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getApiResourceId() {
|
public Long getApiResourceId() {
|
||||||
return getId();
|
return getId();
|
||||||
|
|||||||
@ -254,7 +254,7 @@ public interface VirtualMachineManager extends Manager {
|
|||||||
*/
|
*/
|
||||||
boolean unmanage(String vmUuid);
|
boolean unmanage(String vmUuid);
|
||||||
|
|
||||||
UserVm restoreVirtualMachine(long vmId, Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException;
|
UserVm restoreVirtualMachine(long vmId, Long newTemplateId, Long rootDiskOfferingId, boolean expunge, Map<String, String> details) throws ResourceUnavailableException, InsufficientCapacityException;
|
||||||
|
|
||||||
boolean checkIfVmHasClusterWideVolumes(Long vmId);
|
boolean checkIfVmHasClusterWideVolumes(Long vmId);
|
||||||
|
|
||||||
|
|||||||
@ -5692,20 +5692,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserVm restoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException {
|
public UserVm restoreVirtualMachine(final long vmId, final Long newTemplateId, final Long rootDiskOfferingId, final boolean expunge, final Map<String, String> details) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||||
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
|
||||||
if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
||||||
VmWorkJobVO placeHolder = null;
|
VmWorkJobVO placeHolder = null;
|
||||||
placeHolder = createPlaceHolderWork(vmId);
|
placeHolder = createPlaceHolderWork(vmId);
|
||||||
try {
|
try {
|
||||||
return orchestrateRestoreVirtualMachine(vmId, newTemplateId);
|
return orchestrateRestoreVirtualMachine(vmId, newTemplateId, rootDiskOfferingId, expunge, details);
|
||||||
} finally {
|
} finally {
|
||||||
if (placeHolder != null) {
|
if (placeHolder != null) {
|
||||||
_workJobDao.expunge(placeHolder.getId());
|
_workJobDao.expunge(placeHolder.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final Outcome<VirtualMachine> outcome = restoreVirtualMachineThroughJobQueue(vmId, newTemplateId);
|
final Outcome<VirtualMachine> outcome = restoreVirtualMachineThroughJobQueue(vmId, newTemplateId, rootDiskOfferingId, expunge, details);
|
||||||
|
|
||||||
retrieveVmFromJobOutcome(outcome, String.valueOf(vmId), "restoreVirtualMachine");
|
retrieveVmFromJobOutcome(outcome, String.valueOf(vmId), "restoreVirtualMachine");
|
||||||
|
|
||||||
@ -5722,14 +5722,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserVm orchestrateRestoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException {
|
private UserVm orchestrateRestoreVirtualMachine(final long vmId, final Long newTemplateId, final Long rootDiskOfferingId, final boolean expunge, final Map<String, String> details) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||||
logger.debug("Restoring vm " + vmId + " with new templateId " + newTemplateId);
|
logger.debug("Restoring vm " + vmId + " with templateId : " + newTemplateId + " diskOfferingId : " + rootDiskOfferingId + " details : " + details);
|
||||||
final CallContext context = CallContext.current();
|
final CallContext context = CallContext.current();
|
||||||
final Account account = context.getCallingAccount();
|
final Account account = context.getCallingAccount();
|
||||||
return _userVmService.restoreVirtualMachine(account, vmId, newTemplateId);
|
return _userVmService.restoreVirtualMachine(account, vmId, newTemplateId, rootDiskOfferingId, expunge, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Outcome<VirtualMachine> restoreVirtualMachineThroughJobQueue(final long vmId, final Long newTemplateId) {
|
public Outcome<VirtualMachine> restoreVirtualMachineThroughJobQueue(final long vmId, final Long newTemplateId, final Long rootDiskOfferingId, final boolean expunge, Map<String, String> details) {
|
||||||
String commandName = VmWorkRestore.class.getName();
|
String commandName = VmWorkRestore.class.getName();
|
||||||
Pair<VmWorkJobVO, Long> pendingWorkJob = retrievePendingWorkJob(vmId, commandName);
|
Pair<VmWorkJobVO, Long> pendingWorkJob = retrievePendingWorkJob(vmId, commandName);
|
||||||
|
|
||||||
@ -5739,7 +5739,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
Pair<VmWorkJobVO, VmWork> newVmWorkJobAndInfo = createWorkJobAndWorkInfo(commandName, vmId);
|
Pair<VmWorkJobVO, VmWork> newVmWorkJobAndInfo = createWorkJobAndWorkInfo(commandName, vmId);
|
||||||
|
|
||||||
workJob = newVmWorkJobAndInfo.first();
|
workJob = newVmWorkJobAndInfo.first();
|
||||||
VmWorkRestore workInfo = new VmWorkRestore(newVmWorkJobAndInfo.second(), newTemplateId);
|
VmWorkRestore workInfo = new VmWorkRestore(newVmWorkJobAndInfo.second(), newTemplateId, rootDiskOfferingId, expunge, details);
|
||||||
|
|
||||||
setCmdInfoAndSubmitAsyncJob(workJob, workInfo, vmId);
|
setCmdInfoAndSubmitAsyncJob(workJob, workInfo, vmId);
|
||||||
}
|
}
|
||||||
@ -5751,7 +5751,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
@ReflectionUse
|
@ReflectionUse
|
||||||
private Pair<JobInfo.Status, String> orchestrateRestoreVirtualMachine(final VmWorkRestore work) throws Exception {
|
private Pair<JobInfo.Status, String> orchestrateRestoreVirtualMachine(final VmWorkRestore work) throws Exception {
|
||||||
VMInstanceVO vm = findVmById(work.getVmId());
|
VMInstanceVO vm = findVmById(work.getVmId());
|
||||||
UserVm uservm = orchestrateRestoreVirtualMachine(vm.getId(), work.getTemplateId());
|
UserVm uservm = orchestrateRestoreVirtualMachine(vm.getId(), work.getTemplateId(), work.getRootDiskOfferingId(), work.getExpunge(), work.getDetails());
|
||||||
HashMap<Long, String> passwordMap = new HashMap<>();
|
HashMap<Long, String> passwordMap = new HashMap<>();
|
||||||
passwordMap.put(uservm.getId(), uservm.getPassword());
|
passwordMap.put(uservm.getId(), uservm.getPassword());
|
||||||
return new Pair<>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(passwordMap));
|
return new Pair<>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(passwordMap));
|
||||||
|
|||||||
@ -16,23 +16,38 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.vm;
|
package com.cloud.vm;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class VmWorkRestore extends VmWork {
|
public class VmWorkRestore extends VmWork {
|
||||||
private static final long serialVersionUID = 195901782359759635L;
|
private static final long serialVersionUID = 195901782359759635L;
|
||||||
|
|
||||||
private Long templateId;
|
private Long templateId;
|
||||||
|
private Long rootDiskOfferingId;
|
||||||
|
private Map<String,String> details;
|
||||||
|
|
||||||
public VmWorkRestore(long userId, long accountId, long vmId, String handlerName, Long templateId) {
|
private boolean expunge;
|
||||||
super(userId, accountId, vmId, handlerName);
|
|
||||||
|
|
||||||
this.templateId = templateId;
|
public VmWorkRestore(VmWork vmWork, Long templateId, Long rootDiskOfferingId, boolean expunge, Map<String,String> details) {
|
||||||
}
|
|
||||||
|
|
||||||
public VmWorkRestore(VmWork vmWork, Long templateId) {
|
|
||||||
super(vmWork);
|
super(vmWork);
|
||||||
this.templateId = templateId;
|
this.templateId = templateId;
|
||||||
|
this.rootDiskOfferingId = rootDiskOfferingId;
|
||||||
|
this.expunge = expunge;
|
||||||
|
this.details = details;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getTemplateId() {
|
public Long getTemplateId() {
|
||||||
return templateId;
|
return templateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getRootDiskOfferingId() {
|
||||||
|
return rootDiskOfferingId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getExpunge() {
|
||||||
|
return expunge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getDetails() {
|
||||||
|
return details;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,9 @@ import com.cloud.vm.dao.UserVmDao;
|
|||||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
|
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
|
||||||
|
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class CloudOrchestrator implements OrchestrationService {
|
public class CloudOrchestrator implements OrchestrationService {
|
||||||
|
|
||||||
@ -196,8 +199,8 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||||||
Map<String, String> userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId());
|
Map<String, String> userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId());
|
||||||
|
|
||||||
if (userVmDetails != null) {
|
if (userVmDetails != null) {
|
||||||
String minIops = userVmDetails.get("minIops");
|
String minIops = userVmDetails.get(MIN_IOPS);
|
||||||
String maxIops = userVmDetails.get("maxIops");
|
String maxIops = userVmDetails.get(MAX_IOPS);
|
||||||
|
|
||||||
rootDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null);
|
rootDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null);
|
||||||
rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null);
|
rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null);
|
||||||
|
|||||||
@ -879,32 +879,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||||||
return diskProfile;
|
return diskProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveVolumeDetails(Long diskOfferingId, Long volumeId) {
|
|
||||||
List<VolumeDetailVO> volumeDetailsVO = new ArrayList<>();
|
|
||||||
DiskOfferingDetailVO bandwidthLimitDetail = _diskOfferingDetailDao.findDetail(diskOfferingId, Volume.BANDWIDTH_LIMIT_IN_MBPS);
|
|
||||||
if (bandwidthLimitDetail != null) {
|
|
||||||
volumeDetailsVO.add(new VolumeDetailVO(volumeId, Volume.BANDWIDTH_LIMIT_IN_MBPS, bandwidthLimitDetail.getValue(), false));
|
|
||||||
} else {
|
|
||||||
VolumeDetailVO bandwidthLimit = _volDetailDao.findDetail(volumeId, Volume.BANDWIDTH_LIMIT_IN_MBPS);
|
|
||||||
if (bandwidthLimit != null) {
|
|
||||||
_volDetailDao.remove(bandwidthLimit.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DiskOfferingDetailVO iopsLimitDetail = _diskOfferingDetailDao.findDetail(diskOfferingId, Volume.IOPS_LIMIT);
|
|
||||||
if (iopsLimitDetail != null) {
|
|
||||||
volumeDetailsVO.add(new VolumeDetailVO(volumeId, Volume.IOPS_LIMIT, iopsLimitDetail.getValue(), false));
|
|
||||||
} else {
|
|
||||||
VolumeDetailVO iopsLimit = _volDetailDao.findDetail(volumeId, Volume.IOPS_LIMIT);
|
|
||||||
if (iopsLimit != null) {
|
|
||||||
_volDetailDao.remove(iopsLimit.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!volumeDetailsVO.isEmpty()) {
|
|
||||||
_volDetailDao.saveDetails(volumeDetailsVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, Long rootDisksize, Long minIops, Long maxIops, VirtualMachineTemplate template, VirtualMachine vm,
|
private DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, Long rootDisksize, Long minIops, Long maxIops, VirtualMachineTemplate template, VirtualMachine vm,
|
||||||
Account owner, long deviceId, String configurationId) {
|
Account owner, long deviceId, String configurationId) {
|
||||||
assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template.";
|
assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template.";
|
||||||
@ -948,18 +922,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||||||
|
|
||||||
vol = _volsDao.persist(vol);
|
vol = _volsDao.persist(vol);
|
||||||
|
|
||||||
List<VolumeDetailVO> volumeDetailsVO = new ArrayList<VolumeDetailVO>();
|
saveVolumeDetails(offering.getId(), vol.getId());
|
||||||
DiskOfferingDetailVO bandwidthLimitDetail = _diskOfferingDetailDao.findDetail(offering.getId(), Volume.BANDWIDTH_LIMIT_IN_MBPS);
|
|
||||||
if (bandwidthLimitDetail != null) {
|
|
||||||
volumeDetailsVO.add(new VolumeDetailVO(vol.getId(), Volume.BANDWIDTH_LIMIT_IN_MBPS, bandwidthLimitDetail.getValue(), false));
|
|
||||||
}
|
|
||||||
DiskOfferingDetailVO iopsLimitDetail = _diskOfferingDetailDao.findDetail(offering.getId(), Volume.IOPS_LIMIT);
|
|
||||||
if (iopsLimitDetail != null) {
|
|
||||||
volumeDetailsVO.add(new VolumeDetailVO(vol.getId(), Volume.IOPS_LIMIT, iopsLimitDetail.getValue(), false));
|
|
||||||
}
|
|
||||||
if (!volumeDetailsVO.isEmpty()) {
|
|
||||||
_volDetailDao.saveDetails(volumeDetailsVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(configurationId)) {
|
if (StringUtils.isNotBlank(configurationId)) {
|
||||||
VolumeDetailVO deployConfigurationDetail = new VolumeDetailVO(vol.getId(), VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION, configurationId, false);
|
VolumeDetailVO deployConfigurationDetail = new VolumeDetailVO(vol.getId(), VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION, configurationId, false);
|
||||||
@ -983,6 +946,32 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||||||
return toDiskProfile(vol, offering);
|
return toDiskProfile(vol, offering);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveVolumeDetails(Long diskOfferingId, Long volumeId) {
|
||||||
|
List<VolumeDetailVO> volumeDetailsVO = new ArrayList<>();
|
||||||
|
DiskOfferingDetailVO bandwidthLimitDetail = _diskOfferingDetailDao.findDetail(diskOfferingId, Volume.BANDWIDTH_LIMIT_IN_MBPS);
|
||||||
|
if (bandwidthLimitDetail != null) {
|
||||||
|
volumeDetailsVO.add(new VolumeDetailVO(volumeId, Volume.BANDWIDTH_LIMIT_IN_MBPS, bandwidthLimitDetail.getValue(), false));
|
||||||
|
} else {
|
||||||
|
VolumeDetailVO bandwidthLimit = _volDetailDao.findDetail(volumeId, Volume.BANDWIDTH_LIMIT_IN_MBPS);
|
||||||
|
if (bandwidthLimit != null) {
|
||||||
|
_volDetailDao.remove(bandwidthLimit.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DiskOfferingDetailVO iopsLimitDetail = _diskOfferingDetailDao.findDetail(diskOfferingId, Volume.IOPS_LIMIT);
|
||||||
|
if (iopsLimitDetail != null) {
|
||||||
|
volumeDetailsVO.add(new VolumeDetailVO(volumeId, Volume.IOPS_LIMIT, iopsLimitDetail.getValue(), false));
|
||||||
|
} else {
|
||||||
|
VolumeDetailVO iopsLimit = _volDetailDao.findDetail(volumeId, Volume.IOPS_LIMIT);
|
||||||
|
if (iopsLimit != null) {
|
||||||
|
_volDetailDao.remove(iopsLimit.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!volumeDetailsVO.isEmpty()) {
|
||||||
|
_volDetailDao.saveDetails(volumeDetailsVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating ROOT volume", create = true)
|
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating ROOT volume", create = true)
|
||||||
@Override
|
@Override
|
||||||
public List<DiskProfile> allocateTemplatedVolumes(Type type, String name, DiskOffering offering, Long rootDisksize, Long minIops, Long maxIops, VirtualMachineTemplate template, VirtualMachine vm,
|
public List<DiskProfile> allocateTemplatedVolumes(Type type, String name, DiskOffering offering, Long rootDisksize, Long minIops, Long maxIops, VirtualMachineTemplate template, VirtualMachine vm,
|
||||||
|
|||||||
@ -1723,11 +1723,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
return _volStateMachine.transitTo(vol, event, null, _volsDao);
|
return _volStateMachine.transitTo(vol, event, null, _volsDao);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void validateDestroyVolume(Volume volume, Account caller, boolean expunge, boolean forceExpunge) {
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DESTROY, eventDescription = "destroying a volume")
|
|
||||||
public Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge) {
|
|
||||||
VolumeVO volume = retrieveAndValidateVolume(volumeId, caller);
|
|
||||||
|
|
||||||
if (expunge) {
|
if (expunge) {
|
||||||
// When trying to expunge, permission is denied when the caller is not an admin and the AllowUserExpungeRecoverVolume is false for the caller.
|
// When trying to expunge, permission is denied when the caller is not an admin and the AllowUserExpungeRecoverVolume is false for the caller.
|
||||||
final Long userId = caller.getAccountId();
|
final Long userId = caller.getAccountId();
|
||||||
@ -1737,6 +1733,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
} else if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.Uploaded) {
|
} else if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.Uploaded) {
|
||||||
throw new InvalidParameterValueException("The volume in Allocated/Uploaded state can only be expunged not destroyed/recovered");
|
throw new InvalidParameterValueException("The volume in Allocated/Uploaded state can only be expunged not destroyed/recovered");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DESTROY, eventDescription = "destroying a volume")
|
||||||
|
public Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge) {
|
||||||
|
VolumeVO volume = retrieveAndValidateVolume(volumeId, caller);
|
||||||
|
|
||||||
|
validateDestroyVolume(volume, caller, expunge, forceExpunge);
|
||||||
|
|
||||||
destroyVolumeIfPossible(volume);
|
destroyVolumeIfPossible(volume);
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@ package com.cloud.vm;
|
|||||||
|
|
||||||
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
|
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
|
||||||
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
|
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
|
||||||
|
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
|
||||||
|
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
@ -568,6 +570,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
@Inject
|
@Inject
|
||||||
private VmStatsDao vmStatsDao;
|
private VmStatsDao vmStatsDao;
|
||||||
@Inject
|
@Inject
|
||||||
|
private DataCenterDao dataCenterDao;
|
||||||
|
@Inject
|
||||||
private MessageBus messageBus;
|
private MessageBus messageBus;
|
||||||
@Inject
|
@Inject
|
||||||
protected CommandSetupHelper commandSetupHelper;
|
protected CommandSetupHelper commandSetupHelper;
|
||||||
@ -2194,11 +2198,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
Long maxIopsInNewDiskOffering = null;
|
Long maxIopsInNewDiskOffering = null;
|
||||||
boolean autoMigrate = false;
|
boolean autoMigrate = false;
|
||||||
boolean shrinkOk = false;
|
boolean shrinkOk = false;
|
||||||
if (customParameters.containsKey(ApiConstants.MIN_IOPS)) {
|
if (customParameters.containsKey(MIN_IOPS)) {
|
||||||
minIopsInNewDiskOffering = Long.parseLong(customParameters.get(ApiConstants.MIN_IOPS));
|
minIopsInNewDiskOffering = Long.parseLong(customParameters.get(MIN_IOPS));
|
||||||
}
|
}
|
||||||
if (customParameters.containsKey(ApiConstants.MAX_IOPS)) {
|
if (customParameters.containsKey(MAX_IOPS)) {
|
||||||
minIopsInNewDiskOffering = Long.parseLong(customParameters.get(ApiConstants.MAX_IOPS));
|
minIopsInNewDiskOffering = Long.parseLong(customParameters.get(MAX_IOPS));
|
||||||
}
|
}
|
||||||
if (customParameters.containsKey(ApiConstants.AUTO_MIGRATE)) {
|
if (customParameters.containsKey(ApiConstants.AUTO_MIGRATE)) {
|
||||||
autoMigrate = Boolean.parseBoolean(customParameters.get(ApiConstants.AUTO_MIGRATE));
|
autoMigrate = Boolean.parseBoolean(customParameters.get(ApiConstants.AUTO_MIGRATE));
|
||||||
@ -3301,7 +3305,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
ServiceOfferingVO offering = serviceOfferingDao.findById(vmInstance.getId(), serviceOfferingId);
|
ServiceOfferingVO offering = serviceOfferingDao.findById(vmInstance.getId(), serviceOfferingId);
|
||||||
if (offering != null && offering.getRemoved() == null) {
|
if (offering != null && offering.getRemoved() == null) {
|
||||||
if (offering.isVolatileVm()) {
|
if (offering.isVolatileVm()) {
|
||||||
return restoreVMInternal(caller, vmInstance, null);
|
return restoreVMInternal(caller, vmInstance);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId + " corresponding to the vm");
|
throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId + " corresponding to the vm");
|
||||||
@ -6451,8 +6455,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
// if specified, minIops should be <= maxIops
|
// if specified, minIops should be <= maxIops
|
||||||
private void verifyDetails(Map<String,String> details) {
|
private void verifyDetails(Map<String,String> details) {
|
||||||
if (details != null) {
|
if (details != null) {
|
||||||
String minIops = details.get("minIops");
|
String minIops = details.get(MIN_IOPS);
|
||||||
String maxIops = details.get("maxIops");
|
String maxIops = details.get(MAX_IOPS);
|
||||||
|
|
||||||
verifyMinAndMaxIops(minIops, maxIops);
|
verifyMinAndMaxIops(minIops, maxIops);
|
||||||
|
|
||||||
@ -7811,6 +7815,20 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DiskOfferingVO validateAndGetDiskOffering(Long diskOfferingId, UserVmVO vm, Account caller) {
|
||||||
|
DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
|
||||||
|
if (diskOffering == null) {
|
||||||
|
throw new InvalidParameterValueException("Cannot find disk offering with ID " + diskOfferingId);
|
||||||
|
}
|
||||||
|
DataCenterVO zone = dataCenterDao.findById(vm.getDataCenterId());
|
||||||
|
_accountMgr.checkAccess(caller, diskOffering, zone);
|
||||||
|
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getServiceOfferingId());
|
||||||
|
if (serviceOffering.getDiskOfferingStrictness() && !serviceOffering.getDiskOfferingId().equals(diskOfferingId)) {
|
||||||
|
throw new InvalidParameterValueException("VM's service offering has a strict disk offering requirement, and the specified disk offering does not match");
|
||||||
|
}
|
||||||
|
return diskOffering;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException {
|
public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException {
|
||||||
// Input validation
|
// Input validation
|
||||||
@ -7818,6 +7836,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
|
|
||||||
long vmId = cmd.getVmId();
|
long vmId = cmd.getVmId();
|
||||||
Long newTemplateId = cmd.getTemplateId();
|
Long newTemplateId = cmd.getTemplateId();
|
||||||
|
Long rootDiskOfferingId = cmd.getRootDiskOfferingId();
|
||||||
|
boolean expunge = cmd.getExpungeRootDisk();
|
||||||
|
Map<String, String> details = cmd.getDetails();
|
||||||
|
|
||||||
|
verifyDetails(details);
|
||||||
|
|
||||||
UserVmVO vm = _vmDao.findById(vmId);
|
UserVmVO vm = _vmDao.findById(vmId);
|
||||||
if (vm == null) {
|
if (vm == null) {
|
||||||
@ -7825,20 +7848,38 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
ex.addProxyObject(String.valueOf(vmId), "vmId");
|
ex.addProxyObject(String.valueOf(vmId), "vmId");
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
_accountMgr.checkAccess(caller, null, true, vm);
|
_accountMgr.checkAccess(caller, null, true, vm);
|
||||||
|
|
||||||
|
DiskOffering diskOffering = rootDiskOfferingId != null ? validateAndGetDiskOffering(rootDiskOfferingId, vm, caller) : null;
|
||||||
|
VMTemplateVO template = _templateDao.findById(newTemplateId);
|
||||||
|
if (template.getSize() != null) {
|
||||||
|
String rootDiskSize = details.get(VmDetailConstants.ROOT_DISK_SIZE);
|
||||||
|
Long templateSize = template.getSize();
|
||||||
|
if (StringUtils.isNumeric(rootDiskSize)) {
|
||||||
|
if (Long.parseLong(rootDiskSize) * GiB_TO_BYTES < templateSize) {
|
||||||
|
throw new InvalidParameterValueException(String.format("Root disk size [%s] is smaller than the template size [%s]", rootDiskSize, templateSize));
|
||||||
|
}
|
||||||
|
} else if (diskOffering != null && diskOffering.getDiskSize() < templateSize) {
|
||||||
|
throw new InvalidParameterValueException(String.format("Disk size for selected offering [%s] is less than the template's size [%s]", diskOffering.getDiskSize(), templateSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//check if there are any active snapshots on volumes associated with the VM
|
//check if there are any active snapshots on volumes associated with the VM
|
||||||
logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
|
logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
|
||||||
if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
|
if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
|
||||||
throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, Re-install VM is not permitted, please try again later.");
|
throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, Re-install VM is not permitted, please try again later.");
|
||||||
}
|
}
|
||||||
logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
|
logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
|
||||||
return restoreVMInternal(caller, vm, newTemplateId);
|
return restoreVMInternal(caller, vm, newTemplateId, rootDiskOfferingId, expunge, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException {
|
public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId, Long rootDiskOfferingId, boolean expunge, Map<String, String> details) throws InsufficientCapacityException, ResourceUnavailableException {
|
||||||
return _itMgr.restoreVirtualMachine(vm.getId(), newTemplateId);
|
return _itMgr.restoreVirtualMachine(vm.getId(), newTemplateId, rootDiskOfferingId, expunge, details);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UserVm restoreVMInternal(Account caller, UserVmVO vm) throws InsufficientCapacityException, ResourceUnavailableException {
|
||||||
|
return restoreVMInternal(caller, vm, null, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VMTemplateVO getRestoreVirtualMachineTemplate(Account caller, Long newTemplateId, List<VolumeVO> rootVols, UserVmVO vm) {
|
private VMTemplateVO getRestoreVirtualMachineTemplate(Account caller, Long newTemplateId, List<VolumeVO> rootVols, UserVmVO vm) {
|
||||||
@ -7883,7 +7924,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserVm restoreVirtualMachine(final Account caller, final long vmId, final Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException {
|
public UserVm restoreVirtualMachine(final Account caller, final long vmId, final Long newTemplateId,
|
||||||
|
final Long rootDiskOfferingId,
|
||||||
|
final boolean expunge, final Map<String, String> details) throws InsufficientCapacityException, ResourceUnavailableException {
|
||||||
Long userId = caller.getId();
|
Long userId = caller.getId();
|
||||||
_userDao.findById(userId);
|
_userDao.findById(userId);
|
||||||
UserVmVO vm = _vmDao.findById(vmId);
|
UserVmVO vm = _vmDao.findById(vmId);
|
||||||
@ -7940,9 +7983,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Volume> newVols = new ArrayList<>();
|
DiskOffering diskOffering = rootDiskOfferingId != null ? _diskOfferingDao.findById(rootDiskOfferingId) : null;
|
||||||
for (VolumeVO root : rootVols) {
|
for (VolumeVO root : rootVols) {
|
||||||
if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ) {
|
if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ) {
|
||||||
|
_volumeService.validateDestroyVolume(root, caller, expunge, false);
|
||||||
final UserVmVO userVm = vm;
|
final UserVmVO userVm = vm;
|
||||||
Pair<UserVmVO, Volume> vmAndNewVol = Transaction.execute(new TransactionCallbackWithException<Pair<UserVmVO, Volume>, CloudRuntimeException>() {
|
Pair<UserVmVO, Volume> vmAndNewVol = Transaction.execute(new TransactionCallbackWithException<Pair<UserVmVO, Volume>, CloudRuntimeException>() {
|
||||||
@Override
|
@Override
|
||||||
@ -7973,15 +8017,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
} else {
|
} else {
|
||||||
newVol = volumeMgr.allocateDuplicateVolume(root, null);
|
newVol = volumeMgr.allocateDuplicateVolume(root, null);
|
||||||
}
|
}
|
||||||
newVols.add(newVol);
|
|
||||||
|
|
||||||
if (userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE) == null && !newVol.getSize().equals(template.getSize())) {
|
updateVolume(newVol, template, userVm, diskOffering, details);
|
||||||
VolumeVO resizedVolume = (VolumeVO) newVol;
|
volumeMgr.saveVolumeDetails(newVol.getDiskOfferingId(), newVol.getId());
|
||||||
if (template.getSize() != null) {
|
|
||||||
resizedVolume.setSize(template.getSize());
|
|
||||||
_volsDao.update(resizedVolume.getId(), resizedVolume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Save usage event and update resource count for user vm volumes
|
// 1. Save usage event and update resource count for user vm volumes
|
||||||
try {
|
try {
|
||||||
@ -8010,7 +8048,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
|
|
||||||
// Detach, destroy and create the usage event for the old root volume.
|
// Detach, destroy and create the usage event for the old root volume.
|
||||||
_volsDao.detachVolume(root.getId());
|
_volsDao.detachVolume(root.getId());
|
||||||
volumeMgr.destroyVolume(root);
|
_volumeService.destroyVolume(root.getId(), caller, expunge, false);
|
||||||
|
|
||||||
// For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage
|
// For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage
|
||||||
if (vm.getHypervisorType() == HypervisorType.VMware) {
|
if (vm.getHypervisorType() == HypervisorType.VMware) {
|
||||||
@ -8073,6 +8111,48 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateVolume(Volume vol, VMTemplateVO template, UserVmVO userVm, DiskOffering diskOffering, Map<String, String> details) {
|
||||||
|
VolumeVO resizedVolume = (VolumeVO) vol;
|
||||||
|
|
||||||
|
if (userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE) == null && !vol.getSize().equals(template.getSize())) {
|
||||||
|
if (template.getSize() != null) {
|
||||||
|
resizedVolume.setSize(template.getSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diskOffering != null) {
|
||||||
|
resizedVolume.setDiskOfferingId(diskOffering.getId());
|
||||||
|
resizedVolume.setSize(diskOffering.getDiskSize());
|
||||||
|
if (diskOffering.isCustomized()) {
|
||||||
|
resizedVolume.setSize(vol.getSize());
|
||||||
|
}
|
||||||
|
if (diskOffering.getMinIops() != null) {
|
||||||
|
resizedVolume.setMinIops(diskOffering.getMinIops());
|
||||||
|
}
|
||||||
|
if (diskOffering.getMaxIops() != null) {
|
||||||
|
resizedVolume.setMaxIops(diskOffering.getMaxIops());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MapUtils.isNotEmpty(details)) {
|
||||||
|
if (StringUtils.isNumeric(details.get(VmDetailConstants.ROOT_DISK_SIZE))) {
|
||||||
|
Long rootDiskSize = Long.parseLong(details.get(VmDetailConstants.ROOT_DISK_SIZE)) * GiB_TO_BYTES;
|
||||||
|
resizedVolume.setSize(rootDiskSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
String minIops = details.get(MIN_IOPS);
|
||||||
|
String maxIops = details.get(MAX_IOPS);
|
||||||
|
|
||||||
|
if (StringUtils.isNumeric(minIops)) {
|
||||||
|
resizedVolume.setMinIops(Long.parseLong(minIops));
|
||||||
|
}
|
||||||
|
if (StringUtils.isNumeric(maxIops)) {
|
||||||
|
resizedVolume.setMinIops(Long.parseLong(maxIops));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_volsDao.update(resizedVolume.getId(), resizedVolume);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateVMDynamicallyScalabilityUsingTemplate(UserVmVO vm, Long newTemplateId) {
|
private void updateVMDynamicallyScalabilityUsingTemplate(UserVmVO vm, Long newTemplateId) {
|
||||||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getServiceOfferingId());
|
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getServiceOfferingId());
|
||||||
VMTemplateVO newTemplate = _templateDao.findById(newTemplateId);
|
VMTemplateVO newTemplate = _templateDao.findById(newTemplateId);
|
||||||
|
|||||||
@ -185,6 +185,9 @@ import java.util.Random;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
|
||||||
|
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
|
||||||
|
|
||||||
public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
||||||
public static final String VM_IMPORT_DEFAULT_TEMPLATE_NAME = "system-default-vm-import-dummy-template.iso";
|
public static final String VM_IMPORT_DEFAULT_TEMPLATE_NAME = "system-default-vm-import-dummy-template.iso";
|
||||||
public static final String KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME = "kvm-default-vm-import-dummy-template";
|
public static final String KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME = "kvm-default-vm-import-dummy-template";
|
||||||
@ -1200,12 +1203,12 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||||
}
|
}
|
||||||
Long minIops = null;
|
Long minIops = null;
|
||||||
if (details.containsKey("minIops")) {
|
if (details.containsKey(MIN_IOPS)) {
|
||||||
minIops = Long.parseLong(details.get("minIops"));
|
minIops = Long.parseLong(details.get(MIN_IOPS));
|
||||||
}
|
}
|
||||||
Long maxIops = null;
|
Long maxIops = null;
|
||||||
if (details.containsKey("maxIops")) {
|
if (details.containsKey(MAX_IOPS)) {
|
||||||
maxIops = Long.parseLong(details.get("maxIops"));
|
maxIops = Long.parseLong(details.get(MAX_IOPS));
|
||||||
}
|
}
|
||||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||||
diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()),
|
diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()),
|
||||||
|
|||||||
@ -97,8 +97,6 @@ import com.cloud.service.dao.ServiceOfferingDao;
|
|||||||
import com.cloud.storage.DiskOfferingVO;
|
import com.cloud.storage.DiskOfferingVO;
|
||||||
import com.cloud.storage.GuestOSVO;
|
import com.cloud.storage.GuestOSVO;
|
||||||
import com.cloud.storage.ScopeType;
|
import com.cloud.storage.ScopeType;
|
||||||
import com.cloud.storage.Snapshot;
|
|
||||||
import com.cloud.storage.SnapshotVO;
|
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
@ -1321,18 +1319,6 @@ public class UserVmManagerImplTest {
|
|||||||
when(cmd.getTemplateId()).thenReturn(2L);
|
when(cmd.getTemplateId()).thenReturn(2L);
|
||||||
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
|
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
|
||||||
|
|
||||||
List<VolumeVO> volumes = new ArrayList<>();
|
|
||||||
long rootVolumeId = 1l;
|
|
||||||
VolumeVO rootVolumeOfVm = Mockito.mock(VolumeVO.class);
|
|
||||||
Mockito.when(rootVolumeOfVm.getId()).thenReturn(rootVolumeId);
|
|
||||||
volumes.add(rootVolumeOfVm);
|
|
||||||
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(volumes);
|
|
||||||
|
|
||||||
List<SnapshotVO> snapshots = new ArrayList<>();
|
|
||||||
SnapshotVO snapshot = Mockito.mock(SnapshotVO.class);
|
|
||||||
snapshots.add(snapshot);
|
|
||||||
when(snapshotDaoMock.listByStatus(rootVolumeId, Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp)).thenReturn(snapshots);
|
|
||||||
|
|
||||||
userVmManagerImpl.restoreVM(cmd);
|
userVmManagerImpl.restoreVM(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,7 +1332,7 @@ public class UserVmManagerImplTest {
|
|||||||
when(userVmVoMock.getAccountId()).thenReturn(accountId);
|
when(userVmVoMock.getAccountId()).thenReturn(accountId);
|
||||||
when(accountDao.findById(accountId)).thenReturn(null);
|
when(accountDao.findById(accountId)).thenReturn(null);
|
||||||
|
|
||||||
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
|
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = PermissionDeniedException.class)
|
@Test(expected = PermissionDeniedException.class)
|
||||||
@ -1360,7 +1346,7 @@ public class UserVmManagerImplTest {
|
|||||||
when(accountDao.findById(accountId)).thenReturn(callerAccount);
|
when(accountDao.findById(accountId)).thenReturn(callerAccount);
|
||||||
when(callerAccount.getState()).thenReturn(Account.State.DISABLED);
|
when(callerAccount.getState()).thenReturn(Account.State.DISABLED);
|
||||||
|
|
||||||
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
|
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = CloudRuntimeException.class)
|
@Test(expected = CloudRuntimeException.class)
|
||||||
@ -1375,7 +1361,7 @@ public class UserVmManagerImplTest {
|
|||||||
when(accountDao.findById(accountId)).thenReturn(callerAccount);
|
when(accountDao.findById(accountId)).thenReturn(callerAccount);
|
||||||
when(userVmVoMock.getState()).thenReturn(VirtualMachine.State.Starting);
|
when(userVmVoMock.getState()).thenReturn(VirtualMachine.State.Starting);
|
||||||
|
|
||||||
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
|
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidParameterValueException.class)
|
@Test(expected = InvalidParameterValueException.class)
|
||||||
@ -1396,7 +1382,7 @@ public class UserVmManagerImplTest {
|
|||||||
when(templateDao.findById(currentTemplateId)).thenReturn(currentTemplate);
|
when(templateDao.findById(currentTemplateId)).thenReturn(currentTemplate);
|
||||||
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(new ArrayList<VolumeVO>());
|
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(new ArrayList<VolumeVO>());
|
||||||
|
|
||||||
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
|
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidParameterValueException.class)
|
@Test(expected = InvalidParameterValueException.class)
|
||||||
@ -1423,7 +1409,7 @@ public class UserVmManagerImplTest {
|
|||||||
volumes.add(rootVolume2);
|
volumes.add(rootVolume2);
|
||||||
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(volumes);
|
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(volumes);
|
||||||
|
|
||||||
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
|
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidParameterValueException.class)
|
@Test(expected = InvalidParameterValueException.class)
|
||||||
@ -1450,7 +1436,7 @@ public class UserVmManagerImplTest {
|
|||||||
vmSnapshots.add(vmSnapshot);
|
vmSnapshots.add(vmSnapshot);
|
||||||
when(vmSnapshotDaoMock.findByVm(vmId)).thenReturn(vmSnapshots);
|
when(vmSnapshotDaoMock.findByVm(vmId)).thenReturn(vmSnapshots);
|
||||||
|
|
||||||
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
|
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -164,33 +164,10 @@ export default {
|
|||||||
label: 'label.reinstall.vm',
|
label: 'label.reinstall.vm',
|
||||||
message: 'message.reinstall.vm',
|
message: 'message.reinstall.vm',
|
||||||
dataView: true,
|
dataView: true,
|
||||||
args: ['virtualmachineid', 'templateid'],
|
popup: true,
|
||||||
filters: (record) => {
|
|
||||||
var filters = {}
|
|
||||||
var filterParams = {}
|
|
||||||
filterParams.hypervisortype = record.hypervisor
|
|
||||||
filterParams.zoneid = record.zoneid
|
|
||||||
filters.templateid = filterParams
|
|
||||||
return filters
|
|
||||||
},
|
|
||||||
show: (record) => { return ['Running', 'Stopped'].includes(record.state) },
|
show: (record) => { return ['Running', 'Stopped'].includes(record.state) },
|
||||||
mapping: {
|
|
||||||
virtualmachineid: {
|
|
||||||
value: (record) => { return record.id }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
disabled: (record) => { return record.hostcontrolstate === 'Offline' },
|
disabled: (record) => { return record.hostcontrolstate === 'Offline' },
|
||||||
successMethod: (obj, result) => {
|
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/ReinstallVm.vue')))
|
||||||
const vm = result.jobresult.virtualmachine || {}
|
|
||||||
if (result.jobstatus === 1 && vm.password) {
|
|
||||||
const name = vm.displayname || vm.name || vm.id
|
|
||||||
obj.$notification.success({
|
|
||||||
message: `${obj.$t('label.reinstall.vm')}: ` + name,
|
|
||||||
description: `${obj.$t('label.password.reset.confirm')}: ` + vm.password,
|
|
||||||
duration: 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
api: 'createVMSnapshot',
|
api: 'createVMSnapshot',
|
||||||
|
|||||||
307
ui/src/views/compute/ReinstallVm.vue
Normal file
307
ui/src/views/compute/ReinstallVm.vue
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-form
|
||||||
|
v-ctrl-enter="handleSubmit"
|
||||||
|
@finish="handleSubmit"
|
||||||
|
layout="vertical"
|
||||||
|
>
|
||||||
|
<a-alert
|
||||||
|
type="warning"
|
||||||
|
show-icon
|
||||||
|
>
|
||||||
|
<template #message><span
|
||||||
|
style="margin-bottom: 5px"
|
||||||
|
v-html="$t('message.reinstall.vm')"
|
||||||
|
/></template>
|
||||||
|
</a-alert>
|
||||||
|
<a-form-item>
|
||||||
|
<template-iso-selection
|
||||||
|
input-decorator="templateid"
|
||||||
|
:items="templates"
|
||||||
|
:selected="tabKey"
|
||||||
|
:loading="loading.templates"
|
||||||
|
:preFillContent="resource.templateid"
|
||||||
|
:key="templateKey"
|
||||||
|
@handle-search-filter="($event) => fetchAllTemplates($event)"
|
||||||
|
@update-template-iso="updateFieldValue"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<template #label>
|
||||||
|
<tooltip-label
|
||||||
|
:title="$t('label.override.root.diskoffering')"
|
||||||
|
:tooltip="apiParams.diskofferingid.description"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<a-switch
|
||||||
|
v-model:checked="overrideDiskOffering"
|
||||||
|
@change="val => { overrideDiskOffering = val }"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="overrideDiskOffering">
|
||||||
|
<disk-offering-selection
|
||||||
|
:items="diskOfferings"
|
||||||
|
:row-count="diskOfferingCount"
|
||||||
|
:zoneId="resource.zoneId"
|
||||||
|
:value="diskOffering ? diskOffering.id : ''"
|
||||||
|
:loading="loading.diskOfferings"
|
||||||
|
:preFillContent="resource.diskofferingid"
|
||||||
|
:isIsoSelected="false"
|
||||||
|
:isRootDiskOffering="true"
|
||||||
|
@on-selected-disk-size="onSelectDiskSize"
|
||||||
|
@handle-search-filter="($event) => fetchDiskOfferings($event)"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="diskOffering && (diskOffering.iscustomized || diskOffering.iscustomizediops)">
|
||||||
|
<disk-size-selection
|
||||||
|
input-decorator="rootdisksize"
|
||||||
|
:diskSelected="diskOffering"
|
||||||
|
:isCustomized="diskOffering.iscustomized"
|
||||||
|
@handler-error="handlerError"
|
||||||
|
@update-disk-size="updateFieldValue"
|
||||||
|
@update-root-disk-iops-value="updateFieldValue"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="!(diskOffering && diskOffering.iscustomized)">
|
||||||
|
<template #label>
|
||||||
|
<tooltip-label
|
||||||
|
:title="$t('label.override.rootdisk.size')"
|
||||||
|
:tooltip="apiParams.rootdisksize.description"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<a-switch
|
||||||
|
v-model:checked="overrideDiskSize"
|
||||||
|
@change="val => { overrideDiskSize = val }"
|
||||||
|
/>
|
||||||
|
<disk-size-selection
|
||||||
|
v-if="overrideDiskSize"
|
||||||
|
input-decorator="rootdisksize"
|
||||||
|
:isCustomized="true"
|
||||||
|
@update-disk-size="(input, value) => updateFieldValue('overrideRootDiskSize', value)"
|
||||||
|
style="margin-top: 10px;"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<template #label>
|
||||||
|
<tooltip-label
|
||||||
|
:title="$t('label.expunge')"
|
||||||
|
:tooltip="apiParams.expunge.description"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<a-switch
|
||||||
|
v-model:checked="expungeDisk"
|
||||||
|
@change="val => { expungeDisk = val }"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<div
|
||||||
|
:span="24"
|
||||||
|
class="action-button"
|
||||||
|
>
|
||||||
|
<a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
|
||||||
|
<a-button
|
||||||
|
ref="submit"
|
||||||
|
type="primary"
|
||||||
|
@click="handleSubmit"
|
||||||
|
>{{ $t('label.ok') }}</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { api } from '@/api'
|
||||||
|
import DiskOfferingSelection from '@views/compute/wizard/DiskOfferingSelection'
|
||||||
|
import DiskSizeSelection from '@views/compute/wizard/DiskSizeSelection'
|
||||||
|
import TemplateIsoSelection from '@views/compute/wizard/TemplateIsoSelection'
|
||||||
|
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ReinstallVM',
|
||||||
|
components: {
|
||||||
|
DiskOfferingSelection,
|
||||||
|
DiskSizeSelection,
|
||||||
|
TemplateIsoSelection,
|
||||||
|
TooltipLabel
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inject: ['parentFetchData'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
overrideDiskOffering: false,
|
||||||
|
overrideDiskSize: false,
|
||||||
|
expungeDisk: false,
|
||||||
|
selectedDiskOffering: {},
|
||||||
|
loading: {
|
||||||
|
templates: false,
|
||||||
|
diskOfferings: false
|
||||||
|
},
|
||||||
|
rootDiskSizeKey: 'details[0].rootdisksize',
|
||||||
|
minIopsKey: 'details[0].minIops',
|
||||||
|
maxIopsKey: 'details[0].maxIops',
|
||||||
|
rootdisksize: 0,
|
||||||
|
minIops: 0,
|
||||||
|
maxIops: 0,
|
||||||
|
templateFilter: [
|
||||||
|
'featured',
|
||||||
|
'community',
|
||||||
|
'selfexecutable',
|
||||||
|
'sharedexecutable'
|
||||||
|
],
|
||||||
|
diskOffering: {},
|
||||||
|
diskOfferingCount: 0,
|
||||||
|
templateKey: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeCreate () {
|
||||||
|
this.apiParams = this.$getApiParams('restoreVirtualMachine')
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchData () {
|
||||||
|
this.fetchDiskOfferings({})
|
||||||
|
this.fetchAllTemplates()
|
||||||
|
},
|
||||||
|
closeAction () {
|
||||||
|
this.$emit('close-action')
|
||||||
|
},
|
||||||
|
handlerError (error) {
|
||||||
|
this.error = error
|
||||||
|
},
|
||||||
|
handleSubmit () {
|
||||||
|
const params = {
|
||||||
|
virtualmachineid: this.resource.id,
|
||||||
|
templateid: this.templateid
|
||||||
|
}
|
||||||
|
if (this.overrideDiskOffering) {
|
||||||
|
params.diskofferingid = this.diskOffering.id
|
||||||
|
if (this.diskOffering.iscustomized) {
|
||||||
|
params[this.rootDiskSizeKey] = this.rootdisksize
|
||||||
|
}
|
||||||
|
if (this.diskOffering.iscustomizediops) {
|
||||||
|
params[this.minIopsKey] = this.minIops
|
||||||
|
params[this.maxIopsKey] = this.maxIops
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.overrideDiskSize && this.overrideRootDiskSize) {
|
||||||
|
params.rootdisksize = this.overrideRootDiskSize
|
||||||
|
}
|
||||||
|
params.expunge = this.expungeDisk
|
||||||
|
api('restoreVirtualMachine', params).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.restorevmresponse.jobid,
|
||||||
|
successMessage: this.$t('label.reinstall.vm') + ' ' + this.$t('label.success'),
|
||||||
|
successMethod: (result) => {
|
||||||
|
const vm = result.jobresult.virtualmachine || {}
|
||||||
|
const name = vm.displayname || vm.name || vm.id
|
||||||
|
if (result.jobstatus === 1 && vm.password) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: `${this.$t('label.reinstall.vm')}: ` + name,
|
||||||
|
description: `${this.$t('label.password.reset.confirm')}: ` + vm.password,
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errorMessage: this.$t('label.reinstall.vm') + ' ' + this.$t('label.failed'),
|
||||||
|
errorMethod: (result) => {
|
||||||
|
this.closeAction()
|
||||||
|
},
|
||||||
|
loadingMessage: this.$t('label.reinstall.vm') + ': ' + this.resource.name,
|
||||||
|
catchMessage: this.$t('error.fetching.async.job.result')
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
this.$notifyError(error)
|
||||||
|
this.closeAction()
|
||||||
|
}).finally(() => {
|
||||||
|
this.closeAction()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetchAllTemplates (params) {
|
||||||
|
const promises = []
|
||||||
|
const templates = {}
|
||||||
|
this.loading.templates = true
|
||||||
|
this.templateFilter.forEach((filter) => {
|
||||||
|
templates[filter] = { count: 0, template: [] }
|
||||||
|
promises.push(this.fetchTemplates(filter, params))
|
||||||
|
})
|
||||||
|
this.templates = templates
|
||||||
|
Promise.all(promises).then((response) => {
|
||||||
|
response.forEach((resItem, idx) => {
|
||||||
|
templates[this.templateFilter[idx]] = _.isEmpty(resItem.listtemplatesresponse) ? { count: 0, template: [] } : resItem.listtemplatesresponse
|
||||||
|
this.templates = { ...templates }
|
||||||
|
})
|
||||||
|
}).catch((reason) => {
|
||||||
|
console.log(reason)
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading.templates = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetchTemplates (templateFilter, params) {
|
||||||
|
const args = Object.assign({}, params)
|
||||||
|
if (args.keyword || args.category !== templateFilter) {
|
||||||
|
args.page = 1
|
||||||
|
args.pageSize = args.pageSize || 10
|
||||||
|
}
|
||||||
|
args.zoneid = _.get(this.zone, 'id')
|
||||||
|
args.templatefilter = templateFilter
|
||||||
|
args.details = 'all'
|
||||||
|
args.showicon = 'true'
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
api('listTemplates', args).then((response) => {
|
||||||
|
resolve(response)
|
||||||
|
}).catch((reason) => {
|
||||||
|
reject(reason)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetchDiskOfferings (params) {
|
||||||
|
api('listDiskOfferings', { zoneid: this.resource.zoneid, listall: true, ...params }).then((response) => {
|
||||||
|
this.diskOfferings = response?.listdiskofferingsresponse?.diskoffering || []
|
||||||
|
this.diskOfferingCount = response?.listdiskofferingsresponse?.count || 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onSelectDiskSize (rowSelected) {
|
||||||
|
this.diskOffering = rowSelected
|
||||||
|
},
|
||||||
|
updateFieldValue (input, value) {
|
||||||
|
this[input] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style
|
||||||
|
scoped
|
||||||
|
lang="scss"
|
||||||
|
>
|
||||||
|
.ant-form {
|
||||||
|
width: 90vw;
|
||||||
|
|
||||||
|
@media (min-width: 700px) {
|
||||||
|
width: 50vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user