mirror of https://github.com/apache/cloudstack.git
fixes, sharedfs restore, restrict unsupported instances
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
parent
bc7ec163f3
commit
14a2e8e2f2
|
|
@ -47,6 +47,13 @@ public class DeployVMCmdByAdmin extends DeployVMCmd implements AdminCmd {
|
|||
since = "4.23.0")
|
||||
private Boolean blankInstance;
|
||||
|
||||
// Internal flag to allow deploying instance with a given type
|
||||
private String instanceType;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
////////////////// Getters //////////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getPodId() {
|
||||
return podId;
|
||||
}
|
||||
|
|
@ -60,6 +67,14 @@ public class DeployVMCmdByAdmin extends DeployVMCmd implements AdminCmd {
|
|||
return Boolean.TRUE.equals(blankInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInstanceType() {
|
||||
if (!isBlankInstance()) {
|
||||
return null;
|
||||
}
|
||||
return instanceType;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
////////////////// Setters //////////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -71,4 +86,8 @@ public class DeployVMCmdByAdmin extends DeployVMCmd implements AdminCmd {
|
|||
public void setBlankInstance(boolean blankInstance) {
|
||||
this.blankInstance = blankInstance;
|
||||
}
|
||||
|
||||
public void setInstanceType(String instanceType) {
|
||||
this.instanceType = instanceType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
package org.apache.cloudstack.api.command.admin.vm;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ResponseObject.ResponseView;
|
||||
import org.apache.cloudstack.api.command.admin.AdminCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
|
||||
|
|
@ -27,4 +29,20 @@ import com.cloud.vm.VirtualMachine;
|
|||
@APICommand(name = "destroyVirtualMachine", description = "Destroys an Instance. Once destroyed, only the administrator can recover it.", responseObject = UserVmResponse.class, responseView = ResponseView.Full, entityType = {VirtualMachine.class},
|
||||
requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = true)
|
||||
public class DestroyVMCmdByAdmin extends DestroyVMCmd implements AdminCmd {}
|
||||
public class DestroyVMCmdByAdmin extends DestroyVMCmd implements AdminCmd {
|
||||
|
||||
@Parameter( name = ApiConstants.FORCED,
|
||||
type = CommandType.BOOLEAN,
|
||||
description = "Force destroy the Instance",
|
||||
since = "4.23.0")
|
||||
Boolean forced;
|
||||
|
||||
@Override
|
||||
public boolean isForced() {
|
||||
return Boolean.TRUE.equals(forced);
|
||||
}
|
||||
|
||||
public void setForced(Boolean forced) {
|
||||
this.forced = forced;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ public abstract class BaseDeployVMCmd extends BaseAsyncCreateCustomIdCmd impleme
|
|||
@ACL
|
||||
@Parameter(name = ApiConstants.SECURITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = SecurityGroupResponse.class, description = "comma separated list of security groups id that going to be applied to the virtual machine. "
|
||||
+ "Should be passed only when vm is created from a zone with Basic Network support." + " Mutually exclusive with securitygroupnames parameter")
|
||||
private List<Long> securityGroupIdList;
|
||||
protected List<Long> securityGroupIdList;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SECURITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = SecurityGroupResponse.class, description = "comma separated list of security groups names that going to be applied to the virtual machine."
|
||||
|
|
@ -799,6 +799,10 @@ public abstract class BaseDeployVMCmd extends BaseAsyncCreateCustomIdCmd impleme
|
|||
return null;
|
||||
}
|
||||
|
||||
public String getInstanceType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -191,6 +191,10 @@ public class DeployVMCmd extends BaseDeployVMCmd {
|
|||
this.sshKeyPairNames = sshKeyPairNames;
|
||||
}
|
||||
|
||||
public void setSecurityGroupList(List<Long> securityGroupIdList) {
|
||||
this.securityGroupIdList = securityGroupIdList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
UserVm result;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ public class DestroyVMCmd extends BaseAsyncCmd implements UserCmd {
|
|||
return volumeIds;
|
||||
}
|
||||
|
||||
public boolean isForced() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ import org.apache.cloudstack.api.command.user.storage.sharedfs.ChangeSharedFSDis
|
|||
import org.apache.cloudstack.api.command.user.storage.sharedfs.ChangeSharedFSServiceOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.user.storage.sharedfs.CreateSharedFSCmd;
|
||||
import org.apache.cloudstack.api.command.user.storage.sharedfs.DestroySharedFSCmd;
|
||||
import org.apache.cloudstack.api.command.user.storage.sharedfs.ListSharedFSCmd;
|
||||
import org.apache.cloudstack.api.command.user.storage.sharedfs.UpdateSharedFSCmd;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.SharedFSResponse;
|
||||
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.ManagementServerException;
|
||||
|
|
@ -31,11 +35,6 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.VirtualMachineMigrationException;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.storage.sharedfs.ListSharedFSCmd;
|
||||
import org.apache.cloudstack.api.command.user.storage.sharedfs.UpdateSharedFSCmd;
|
||||
import org.apache.cloudstack.api.response.SharedFSResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
|
||||
public interface SharedFSService {
|
||||
|
||||
List<SharedFSProvider> getSharedFSProviders();
|
||||
|
|
@ -69,4 +68,10 @@ public interface SharedFSService {
|
|||
SharedFS recoverSharedFS(Long sharedFSId);
|
||||
|
||||
void deleteSharedFS(Long sharedFSId);
|
||||
|
||||
SharedFS getSharedFSByUuid(String uuid);
|
||||
|
||||
SharedFS getSharedFSForVmId(long vmId);
|
||||
|
||||
SharedFS updateSharedFSPostRestore(long sharedFsId, long volumeId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,6 @@ public interface SharedFSDao extends GenericDao<SharedFSVO, Long>, StateDao<Shar
|
|||
List<SharedFSVO> listSharedFSToBeDestroyed(Date date);
|
||||
|
||||
SharedFSVO findSharedFSByNameAccountDomain(String name, Long accountId, Long domainId);
|
||||
|
||||
SharedFSVO findByVm(long vmId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,4 +114,14 @@ public class SharedFSDaoImpl extends GenericDaoBase<SharedFSVO, Long> implements
|
|||
sc.setParameters("domainId", domainId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedFSVO findByVm(long vmId) {
|
||||
SearchBuilder<SharedFSVO> sb = createSearchBuilder();
|
||||
sb.and("vmId", sb.entity().getVmId(), SearchCriteria.Op.EQ);
|
||||
sb.done();
|
||||
SearchCriteria<SharedFSVO> sc = sb.create();
|
||||
sc.setParameters("vmId", vmId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
|
|||
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.DeployVMCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.admin.vm.DestroyVMCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
|
||||
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
|
||||
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
|
||||
|
|
@ -92,6 +93,8 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
|||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.sharedfs.SharedFS;
|
||||
import org.apache.cloudstack.storage.sharedfs.SharedFSService;
|
||||
import org.apache.cloudstack.veeam.VeeamControlService;
|
||||
import org.apache.cloudstack.veeam.api.converter.AsyncJobJoinVOToJobConverter;
|
||||
import org.apache.cloudstack.veeam.api.converter.BackupVOToBackupConverter;
|
||||
|
|
@ -160,8 +163,12 @@ import com.cloud.exception.ResourceUnavailableException;
|
|||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.as.AutoScaleVmGroupVmMapVO;
|
||||
import com.cloud.network.as.dao.AutoScaleVmGroupVmMapDao;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.security.SecurityGroupVO;
|
||||
import com.cloud.network.security.dao.SecurityGroupDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.org.Grouping;
|
||||
import com.cloud.projects.Project;
|
||||
|
|
@ -333,6 +340,15 @@ public class ServerAdapter extends ManagerBase {
|
|||
@Inject
|
||||
GuestOSDao guestOSDao;
|
||||
|
||||
@Inject
|
||||
SecurityGroupDao securityGroupDao;
|
||||
|
||||
@Inject
|
||||
SharedFSService sharedFSService;
|
||||
|
||||
@Inject
|
||||
AutoScaleVmGroupVmMapDao autoScaleVmGroupVmMapDao;
|
||||
|
||||
protected static Map<String, Tag> getDummyTags() {
|
||||
Map<String, Tag> tags = new HashMap<>();
|
||||
Tag rootTag = ResourceTagVOToTagConverter.getRootTag();
|
||||
|
|
@ -582,11 +598,76 @@ public class ServerAdapter extends ManagerBase {
|
|||
return validatedNames;
|
||||
}
|
||||
|
||||
protected AffinityGroupVO getValidatedAffinityGroup(String affinityGroupUuid) {
|
||||
if (StringUtils.isBlank(affinityGroupUuid)) {
|
||||
return null;
|
||||
}
|
||||
AffinityGroupVO group = affinityGroupDao.findByUuid(affinityGroupUuid);
|
||||
if (group == null) {
|
||||
logger.warn("Failed to find affinity group with ID {} specified in Instance creation request, " +
|
||||
"skipping affinity group assignment", affinityGroupUuid);
|
||||
return null;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
protected UserDataVO getValidatedUserdata(String userdataUuid) {
|
||||
if (StringUtils.isBlank(userdataUuid)) {
|
||||
return null;
|
||||
}
|
||||
UserDataVO userDataVO = userDataDao.findByUuid(userdataUuid);
|
||||
if (userDataVO == null) {
|
||||
logger.warn("Failed to find userdata with ID {} specified in Instance creation request, " +
|
||||
"skipping userdata assignment", userdataUuid);
|
||||
return null;
|
||||
}
|
||||
return userDataVO;
|
||||
}
|
||||
|
||||
protected SecurityGroupVO getValidatedSecurityGroup(String securityGroupUuid) {
|
||||
if (StringUtils.isBlank(securityGroupUuid)) {
|
||||
return null;
|
||||
}
|
||||
SecurityGroupVO group = securityGroupDao.findByUuid(securityGroupUuid);
|
||||
if (group == null) {
|
||||
logger.warn("Failed to find userdata with ID {} specified in Instance creation request, " +
|
||||
"skipping security group assignment", securityGroupUuid);
|
||||
return null;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
protected String getValidatedInstanceType(Vm request) {
|
||||
String instanceType = StringUtils.trimToNull(request.getInstanceType());
|
||||
if (StringUtils.isEmpty(request.getInstanceType())) {
|
||||
return null;
|
||||
}
|
||||
if (!UserVmManager.SHAREDFSVM.equals(instanceType)) {
|
||||
logger.warn("{} is not supported for restore, returning null Instance type");
|
||||
return null;
|
||||
}
|
||||
if (StringUtils.isBlank(request.getSharedFSId())) {
|
||||
logger.warn("Shared Filesystem ID not available, returning null Instance type");
|
||||
return null;
|
||||
}
|
||||
SharedFS sharedFS = sharedFSService.getSharedFSByUuid(request.getSharedFSId());
|
||||
if (sharedFS == null) {
|
||||
logger.warn("Shared Filesystem for ID: {} not found, returning null Instance type", request.getSharedFSId());
|
||||
return null;
|
||||
}
|
||||
UserVmVO existingVm = userVmDao.findById(sharedFS.getVmId());
|
||||
if (existingVm != null) {
|
||||
logger.error("{} already has a {}, returning null Instance type", sharedFS, existingVm);
|
||||
return null;
|
||||
}
|
||||
return instanceType;
|
||||
}
|
||||
|
||||
protected Pair<Vm, UserVm> createInstance(com.cloud.dc.DataCenter zone, Long clusterId, Account owner, Long domainId,
|
||||
String accountName, Long projectId, String name, String displayName, String serviceOfferingUuid,
|
||||
int cpu, int memory, String templateUuid, GuestOS guestOs, String userdata, ApiConstants.BootType bootType,
|
||||
ApiConstants.BootMode bootMode, String affinityGroupId, String userDataId, String sshKeyPairNames,
|
||||
Map<String, String> details) {
|
||||
String instanceType, String securityGroupId, Map<String, String> details) {
|
||||
Account account = owner != null ? owner : CallContext.current().getCallingAccount();
|
||||
ServiceOffering serviceOffering = getServiceOfferingIdForVmCreation(zone, account, serviceOfferingUuid, cpu,
|
||||
memory);
|
||||
|
|
@ -625,27 +706,22 @@ public class ServerAdapter extends ManagerBase {
|
|||
} else if (guestOs != null) {
|
||||
CallContext.current().putContextParameter(ApiConstants.OS_ID, guestOs);
|
||||
}
|
||||
if (StringUtils.isNotBlank(affinityGroupId)) {
|
||||
AffinityGroupVO group = affinityGroupDao.findByUuid(affinityGroupId);
|
||||
if (group == null) {
|
||||
logger.warn("Failed to find affinity group with ID {} specified in Instance creation request, " +
|
||||
"skipping affinity group assignment", affinityGroupId);
|
||||
} else {
|
||||
cmd.setAffinityGroupIds(List.of(group.getId()));
|
||||
}
|
||||
AffinityGroupVO group = getValidatedAffinityGroup(affinityGroupId);
|
||||
if (group != null) {
|
||||
cmd.setAffinityGroupIds(List.of(group.getId()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(userDataId)) {
|
||||
UserDataVO userData = userDataDao.findByUuid(userDataId);
|
||||
if (userData == null) {
|
||||
logger.warn("Failed to find userdata with ID {} specified in Instance creation request, " +
|
||||
"skipping userdata assignment", userDataId);
|
||||
} else {
|
||||
cmd.setUserDataId(userData.getId());
|
||||
}
|
||||
UserDataVO userData = getValidatedUserdata(userDataId);
|
||||
if (userData != null) {
|
||||
cmd.setUserDataId(userData.getId());
|
||||
}
|
||||
SecurityGroupVO securityGroup = getValidatedSecurityGroup(securityGroupId);
|
||||
if (securityGroup != null) {
|
||||
cmd.setSecurityGroupList(List.of(securityGroup.getId()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(sshKeyPairNames)) {
|
||||
cmd.setSshKeyPairNames(getValidatedSshKeyPairNames(sshKeyPairNames, owner));
|
||||
}
|
||||
cmd.setInstanceType(StringUtils.trimToNull(instanceType));
|
||||
cmd.setHypervisor(Hypervisor.HypervisorType.KVM.name());
|
||||
Map<String, String> instanceDetails = getDetailsForInstanceCreation(userdata, serviceOffering, details);
|
||||
if (MapUtils.isNotEmpty(instanceDetails)) {
|
||||
|
|
@ -660,7 +736,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
UserVmJoinVO vo = userVmJoinDao.findById(vm.getId());
|
||||
Vm vmObj = UserVmJoinVOToVmConverter.toVm(vo, this::getHostById, this::getDetailsByInstanceId,
|
||||
this::listTagsByInstanceId, this::listDiskAttachmentsByInstanceId, this::listNicsByInstance,
|
||||
false);
|
||||
null, false);
|
||||
return new Pair<>(vmObj, vm);
|
||||
} catch (InsufficientCapacityException | ResourceUnavailableException | ResourceAllocationException | CloudRuntimeException e) {
|
||||
throw new CloudRuntimeException("Failed to create VM: " + e.getMessage(), e);
|
||||
|
|
@ -714,6 +790,39 @@ public class ServerAdapter extends ManagerBase {
|
|||
vmInstanceDetailsDao.removeDetail(vm.getId(), RESTORE_CONFIG);
|
||||
}
|
||||
|
||||
protected void processInstanceRestoreConfigIfNeeded(UserVm userVm, Volume volume) {
|
||||
VMInstanceDetailVO detail = vmInstanceDetailsDao.findDetail(userVm.getId(), RESTORE_CONFIG);
|
||||
if (detail == null) {
|
||||
return;
|
||||
}
|
||||
String config = detail.getValue();
|
||||
if (StringUtils.isAnyBlank(userVm.getUserVmType(), config)) {
|
||||
removeInstanceRestoreConfig(userVm);
|
||||
return;
|
||||
}
|
||||
Vm vm = OvfXmlUtil.parseVmRestoreConfig(config, logger);
|
||||
if (StringUtils.isAnyBlank(vm.getSharedFSId(), vm.getSharedFsVolumeName())) {
|
||||
removeInstanceRestoreConfig(userVm);
|
||||
return;
|
||||
}
|
||||
if (!vm.getSharedFsVolumeName().equals(volume.getName())) {
|
||||
return;
|
||||
}
|
||||
removeInstanceRestoreConfig(userVm);
|
||||
SharedFS sharedFS = sharedFSService.getSharedFSByUuid(vm.getSharedFSId());
|
||||
if (sharedFS == null) {
|
||||
logger.warn("Shared Filesystem with ID {} specified in the restore config for {} not found, unable to restore Instance for Shared Filesystem",
|
||||
vm.getSharedFSId(), userVm);
|
||||
return;
|
||||
}
|
||||
UserVm existingVm = userVmDao.findById(sharedFS.getId());
|
||||
if (existingVm != null) {
|
||||
logger.error("{} specified in the restore config for {} is already associated with {}, unable to restore Instance for Shared Filesystem",
|
||||
sharedFS, userVm, existingVm);
|
||||
}
|
||||
sharedFSService.updateSharedFSPostRestore(sharedFS.getId(), volume.getId());
|
||||
}
|
||||
|
||||
protected Pair<String, String> getValidatedInstanceNicDetails(final UserVmVO vm, final NetworkVO network) {
|
||||
if (ObjectUtils.anyNull(vm, network)) {
|
||||
return new Pair<>(null, null);
|
||||
|
|
@ -881,6 +990,20 @@ public class ServerAdapter extends ManagerBase {
|
|||
return vmInstanceDetailsDao.listDetailsKeyPairs(instanceId, true);
|
||||
}
|
||||
|
||||
protected SharedFS getSharedFSForInstance(UserVmJoinVO vo) {
|
||||
if (vo == null || !UserVmManager.SHAREDFSVM.equals(vo.getUserVmType())) {
|
||||
return null;
|
||||
}
|
||||
return sharedFSService.getSharedFSForVmId(vo.getId());
|
||||
}
|
||||
|
||||
protected void validateInstanceBackupConditions(UserVm vm) {
|
||||
List<AutoScaleVmGroupVmMapVO> asGroupVmVOs = autoScaleVmGroupVmMapDao.listByVm(vm.getId());
|
||||
if (CollectionUtils.isNotEmpty(asGroupVmVOs)) {
|
||||
throw new CloudRuntimeException("Instance is part of an AutoScale group, unable to proceed with backup");
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<User, Account> getServiceAccount() {
|
||||
String serviceAccountUuid = VeeamControlService.ServiceAccountId.value();
|
||||
if (StringUtils.isEmpty(serviceAccountUuid)) {
|
||||
|
|
@ -1016,14 +1139,15 @@ public class ServerAdapter extends ManagerBase {
|
|||
boolean allContent, Long offset, Long limit) {
|
||||
Filter filter = new Filter(UserVmJoinVO.class, "id", true, offset, limit);
|
||||
Pair<List<Long>, String> ownerDetails = getResourceOwnerFilters();
|
||||
List<UserVmJoinVO> vms = userVmJoinDao.listByHypervisorTypeAndOwners(Hypervisor.HypervisorType.KVM,
|
||||
ownerDetails.first(), ownerDetails.second(), filter);
|
||||
List<UserVmJoinVO> vms = userVmJoinDao.listByHypervisorNotTypesAndOwners(Hypervisor.HypervisorType.KVM,
|
||||
Arrays.asList(UserVmManager.CKS_NODE), ownerDetails.first(), ownerDetails.second(), filter);
|
||||
return UserVmJoinVOToVmConverter.toVmList(vms,
|
||||
this::getHostById,
|
||||
this::getDetailsByInstanceId,
|
||||
includeTags ? this::listTagsByInstanceId : null,
|
||||
includeDisks ? this::listDiskAttachmentsByInstanceId : null,
|
||||
includeNics ? this::listNicsByInstance : null,
|
||||
allContent ? this::getSharedFSForInstance: null,
|
||||
allContent);
|
||||
}
|
||||
|
||||
|
|
@ -1040,6 +1164,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
includeTags ? this::listTagsByInstanceId : null,
|
||||
includeDisks ? this::listDiskAttachmentsByInstanceId : null,
|
||||
includeNics ? this::listNicsByInstance : null,
|
||||
allContent ? this::getSharedFSForInstance : null,
|
||||
allContent);
|
||||
}
|
||||
|
||||
|
|
@ -1104,10 +1229,12 @@ public class ServerAdapter extends ManagerBase {
|
|||
templateUuid = request.getTemplate().getId();
|
||||
}
|
||||
GuestOS guestOs = getGuestOsForInstance(request, StringUtils.isNotEmpty(userdata));
|
||||
String instanceType = getValidatedInstanceType(request);
|
||||
Pair<Vm, UserVm> result = createInstance(zone, clusterId, owner, ownerDetails.first(), ownerDetails.second(),
|
||||
ownerDetails.third(), name, displayName, serviceOfferingUuid, cpu, memoryMB, templateUuid, guestOs,
|
||||
userdata, bootOptions.first(), bootOptions.second(), request.getAffinityGroupId(),
|
||||
request.getUserDataId(), request.getSshKeyPairNames(), request.getDetails());
|
||||
request.getUserDataId(), request.getSshKeyPairNames(), instanceType,
|
||||
request.getSecurityGroupId(), request.getDetails());
|
||||
saveInstanceRestoreConfig(request, result.second());
|
||||
return result.first();
|
||||
}
|
||||
|
|
@ -1124,13 +1251,17 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (vo == null) {
|
||||
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
|
||||
}
|
||||
boolean isAdmin = accountService.isRootAdmin(CallContext.current().getCallingAccountId());
|
||||
try {
|
||||
DestroyVMCmd cmd = new DestroyVMCmd();
|
||||
DestroyVMCmd cmd = isAdmin ? new DestroyVMCmdByAdmin() : new DestroyVMCmd();
|
||||
cmd.setHttpMethod(BaseCmd.HTTPMethod.POST.name());
|
||||
ComponentContext.inject(cmd);
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(ApiConstants.ID, vo.getUuid());
|
||||
params.put(ApiConstants.EXPUNGE, Boolean.TRUE.toString());
|
||||
if (isAdmin) {
|
||||
params.put(ApiConstants.FORCED, Boolean.TRUE.toString());
|
||||
}
|
||||
ApiServerService.AsyncCmdResult result = processAsyncCmdWithContext(cmd, params);
|
||||
AsyncJobJoinVO jobVo = asyncJobJoinDao.findById(result.jobId);
|
||||
if (jobVo == null) {
|
||||
|
|
@ -1313,7 +1444,6 @@ public class ServerAdapter extends ManagerBase {
|
|||
}
|
||||
accountService.checkAccess(CallContext.current().getCallingAccount(), SecurityChecker.AccessType.OperateEntry,
|
||||
false, vmVo);
|
||||
removeInstanceRestoreConfig(vmVo);
|
||||
if (vmVo.getAccountId() != volumeVO.getAccountId()) {
|
||||
if (VeeamControlService.InstanceRestoreAssignOwner.value()) {
|
||||
assignVolumeToAccount(volumeVO, vmVo.getAccountId());
|
||||
|
|
@ -1326,7 +1456,8 @@ public class ServerAdapter extends ManagerBase {
|
|||
if (Boolean.parseBoolean(request.getBootable()) || Volume.Type.ROOT.equals(volumeVO.getVolumeType())) {
|
||||
deviceId = 0L;
|
||||
}
|
||||
Volume volume = volumeApiService.attachVolumeToVM(vmVo.getId(), volumeVO.getId(), deviceId, false);
|
||||
Volume volume = volumeApiService.attachVolumeToVM(vmVo.getId(), volumeVO.getId(), deviceId, true);
|
||||
processInstanceRestoreConfigIfNeeded(vmVo, volume);
|
||||
VolumeJoinVO attachedVolumeVO = volumeJoinDao.findById(volume.getId());
|
||||
return VolumeJoinVOToDiskConverter.toDiskAttachment(attachedVolumeVO, this::getVolumePhysicalSize);
|
||||
}
|
||||
|
|
@ -1699,6 +1830,7 @@ public class ServerAdapter extends ManagerBase {
|
|||
}
|
||||
accountService.checkAccess(CallContext.current().getCallingAccount(), SecurityChecker.AccessType.OperateEntry,
|
||||
false, vmVo);
|
||||
validateInstanceBackupConditions(vmVo);
|
||||
validateInstanceStorage(vmVo);
|
||||
try {
|
||||
StartBackupCmd cmd = new StartBackupCmd();
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public class AsyncJobJoinVOToJobConverter {
|
|||
public static VmAction toVmAction(final AsyncJobJoinVO vo, final UserVmJoinVO vm) {
|
||||
VmAction action = new VmAction();
|
||||
fillAction(action, vo);
|
||||
action.setVm(UserVmJoinVOToVmConverter.toVm(vm, null, null, null, null, null, false));
|
||||
action.setVm(UserVmJoinVOToVmConverter.toVm(vm, null, null, null, null, null, null, false));
|
||||
return action;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,12 @@ import java.util.Arrays;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.storage.sharedfs.SharedFS;
|
||||
import org.apache.cloudstack.veeam.VeeamControlService;
|
||||
import org.apache.cloudstack.veeam.api.ApiRouteHandler;
|
||||
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
|
||||
|
|
@ -61,6 +63,7 @@ public final class UserVmJoinVOToVmConverter {
|
|||
final Function<Long, List<Tag>> tagsResolver,
|
||||
final Function<Long, List<DiskAttachment>> disksResolver,
|
||||
final Function<UserVmJoinVO, List<Nic>> nicsResolver,
|
||||
final Function<UserVmJoinVO, SharedFS> sharedFsResolver,
|
||||
final boolean allContent) {
|
||||
if (src == null) {
|
||||
return null;
|
||||
|
|
@ -173,8 +176,11 @@ public final class UserVmJoinVOToVmConverter {
|
|||
dst.setSshKeyPairNames(src.getKeypairNames());
|
||||
dst.setGuestOsId(src.getGuestOsUuid());
|
||||
dst.setGuestOsName(src.getGuestOsDisplayName());
|
||||
dst.setInstanceType(src.getUserVmType());
|
||||
updateSharedFSDetailsIfNeeded(src, sharedFsResolver, dst);
|
||||
dst.setSecurityGroupId(src.getSecurityGroupUuid());
|
||||
|
||||
// Keep at last
|
||||
// Keep at end
|
||||
if (allContent) {
|
||||
dst.setInitialization(getOvfInitialization(dst, src));
|
||||
}
|
||||
|
|
@ -182,6 +188,24 @@ public final class UserVmJoinVOToVmConverter {
|
|||
return dst;
|
||||
}
|
||||
|
||||
private static void updateSharedFSDetailsIfNeeded(UserVmJoinVO src, Function<UserVmJoinVO, SharedFS> sharedFsResolver, Vm dst) {
|
||||
if (sharedFsResolver == null || dst.getDiskAttachments() == null) {
|
||||
return;
|
||||
}
|
||||
SharedFS sharedFS = sharedFsResolver.apply(src);
|
||||
if (sharedFS == null) {
|
||||
return;
|
||||
}
|
||||
Optional<DiskAttachment> disk = dst.getDiskAttachments().getItems()
|
||||
.stream()
|
||||
.filter(d -> d.getInternalId() == sharedFS.getVolumeId())
|
||||
.findFirst();
|
||||
disk.ifPresent(diskAttachment -> {
|
||||
dst.setSharedFSId(sharedFS.getUuid());
|
||||
dst.setSharedFsVolumeName(diskAttachment.getLogicalName());
|
||||
});
|
||||
}
|
||||
|
||||
private static Vm.Initialization getOvfInitialization(Vm vm, UserVmJoinVO vo) {
|
||||
final Vm.Initialization.Configuration configuration = new Vm.Initialization.Configuration();
|
||||
configuration.setType("ovf");
|
||||
|
|
@ -198,9 +222,11 @@ public final class UserVmJoinVOToVmConverter {
|
|||
final Function<Long, List<Tag>> tagsResolver,
|
||||
final Function<Long, List<DiskAttachment>> disksResolver,
|
||||
final Function<UserVmJoinVO, List<Nic>> nicsResolver,
|
||||
final Function<UserVmJoinVO, SharedFS> sharedFsResolver,
|
||||
final boolean allContent) {
|
||||
return srcList.stream()
|
||||
.map(v -> toVm(v, hostResolver, detailsResolver, tagsResolver, disksResolver, nicsResolver, allContent))
|
||||
.map(v -> toVm(v, hostResolver, detailsResolver, tagsResolver, disksResolver,
|
||||
nicsResolver, sharedFsResolver, allContent))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,11 +153,13 @@ public class VolumeJoinVOToDiskConverter {
|
|||
// Properties
|
||||
da.setActive("true");
|
||||
da.setBootable(String.valueOf(Volume.Type.ROOT.equals(vol.getVolumeType())));
|
||||
da.setIface("virtio_scsi");
|
||||
da.setIface("virtio");
|
||||
da.setLogicalName(vol.getName());
|
||||
da.setReadOnly("false");
|
||||
da.setPassDiscard("false");
|
||||
|
||||
da.setInternalId(vol.getId());
|
||||
|
||||
return da;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.apache.cloudstack.veeam.api.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
|
|
@ -34,6 +35,9 @@ public final class DiskAttachment extends BaseDto {
|
|||
private Disk disk;
|
||||
private Vm vm;
|
||||
|
||||
// Internal properties
|
||||
private long internalId;
|
||||
|
||||
public DiskAttachment() {
|
||||
}
|
||||
|
||||
|
|
@ -108,4 +112,13 @@ public final class DiskAttachment extends BaseDto {
|
|||
public void setVm(Vm vm) {
|
||||
this.vm = vm;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public long getInternalId() {
|
||||
return internalId;
|
||||
}
|
||||
|
||||
public void setInternalId(long internalId) {
|
||||
this.internalId = internalId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import org.apache.commons.collections.MapUtils;
|
|||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
|
@ -68,6 +69,7 @@ public class OvfXmlUtil {
|
|||
sdf.setTimeZone(UTC);
|
||||
return sdf;
|
||||
});
|
||||
private static final org.slf4j.Logger log = LoggerFactory.getLogger(OvfXmlUtil.class);
|
||||
|
||||
protected enum MemoryAllocationUnit {
|
||||
Bytes("byte", 1),
|
||||
|
|
@ -478,6 +480,16 @@ public class OvfXmlUtil {
|
|||
if (StringUtils.isNotBlank(vm.getGuestOsName())) {
|
||||
sb.append("<GuestOsName>").append(escapeText(vm.getGuestOsName())).append("</GuestOsName>");
|
||||
}
|
||||
if (StringUtils.isNotBlank(vm.getInstanceType())) {
|
||||
sb.append("<Type>").append(escapeText(vm.getInstanceType())).append("</Type>");
|
||||
}
|
||||
if (StringUtils.isNoneBlank(vm.getSharedFSId(), vm.getSharedFsVolumeName())) {
|
||||
sb.append("<SharedFSId>").append(escapeText(vm.getSharedFSId())).append("</SharedFSId>");
|
||||
sb.append("<SharedFSVolumeName>").append(escapeText(vm.getSharedFsVolumeName())).append("</SharedFSVolumeName>");
|
||||
}
|
||||
if (StringUtils.isNotBlank(vm.getSecurityGroupId())) {
|
||||
sb.append("<SecurityGroupId>").append(escapeText(vm.getSecurityGroupId())).append("</SecurityGroupId>");
|
||||
}
|
||||
sb.append("</CloudStack>");
|
||||
sb.append("</Section>");
|
||||
}
|
||||
|
|
@ -583,6 +595,33 @@ public class OvfXmlUtil {
|
|||
return new Pair<>(null, null);
|
||||
}
|
||||
|
||||
public static Vm parseVmRestoreConfig(String xmlConfig, Logger logger) {
|
||||
Vm vm = new Vm();
|
||||
if (StringUtils.isBlank(xmlConfig)) {
|
||||
logger.error("No XML configuration provided for VM restore");
|
||||
return vm;
|
||||
}
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(new ByteArrayInputStream(xmlConfig.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
XPathFactory xpf = XPathFactory.newInstance();
|
||||
XPath xpath = xpf.newXPath();
|
||||
Node metadataSection = (Node) xpath.evaluate(
|
||||
"//*[local-name()='Section' and @*[local-name()='type']='ovf:CloudStackMetadata_Type']",
|
||||
doc,
|
||||
XPathConstants.NODE
|
||||
);
|
||||
updateFromXmlCloudStackMetadataSection(vm, metadataSection, xpath);
|
||||
} catch (ParserConfigurationException | XPathExpressionException | IOException | SAXException e) {
|
||||
logger.error("Failed to parse VM configuration XML for restore: {}", e.getMessage());
|
||||
}
|
||||
return vm;
|
||||
}
|
||||
|
||||
private static String nodeToString(Node node) {
|
||||
try {
|
||||
// Implementation using string manipulation
|
||||
|
|
@ -783,6 +822,22 @@ public class OvfXmlUtil {
|
|||
if (StringUtils.isNotBlank(guestOsName)) {
|
||||
vm.setGuestOsId(guestOsName);
|
||||
}
|
||||
String instanceType = xpathString(xpath, metadataSection, ".//*[local-name()='Type']/text()");
|
||||
if (StringUtils.isNotBlank(instanceType)) {
|
||||
vm.setInstanceType(instanceType);
|
||||
}
|
||||
String sharedFSId = xpathString(xpath, metadataSection, ".//*[local-name()='SharedFSId']/text()");
|
||||
if (StringUtils.isNotBlank(sharedFSId)) {
|
||||
vm.setSharedFSId(sharedFSId);
|
||||
}
|
||||
String sharedFSVolumeName = xpathString(xpath, metadataSection, ".//*[local-name()='SharedFSVolumeName']/text()");
|
||||
if (StringUtils.isNotBlank(sharedFSVolumeName)) {
|
||||
vm.setSharedFsVolumeName(sharedFSVolumeName);
|
||||
}
|
||||
String securityGroupId = xpathString(xpath, metadataSection, ".//*[local-name()='SecurityGroupId']/text()");
|
||||
if (StringUtils.isNotBlank(securityGroupId)) {
|
||||
vm.setInstanceType(securityGroupId);
|
||||
}
|
||||
final Map<String, String> details = new HashMap<>();
|
||||
try {
|
||||
NodeList detailNodes = (NodeList) xpath.evaluate(
|
||||
|
|
@ -918,7 +973,7 @@ public class OvfXmlUtil {
|
|||
|
||||
private static String mapDiskInterface(String iface) {
|
||||
if (StringUtils.isBlank(iface)) {
|
||||
return "VirtIO_SCSI";
|
||||
return "VirtIO";
|
||||
}
|
||||
String v = iface.toLowerCase(Locale.ROOT);
|
||||
if (v.contains("virtio") && v.contains("scsi")) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ public final class Vm extends BaseDto {
|
|||
private String sshKeyPairNames;
|
||||
private String guestOsId;
|
||||
private String guestOsName;
|
||||
private String instanceType;
|
||||
private String sharedFSId;
|
||||
private String sharedFsVolumeName;
|
||||
private String securityGroupId;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
@ -358,6 +362,42 @@ public final class Vm extends BaseDto {
|
|||
this.guestOsName = guestOsName;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getInstanceType() {
|
||||
return instanceType;
|
||||
}
|
||||
|
||||
public void setInstanceType(String instanceType) {
|
||||
this.instanceType = instanceType;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getSharedFSId() {
|
||||
return sharedFSId;
|
||||
}
|
||||
|
||||
public void setSharedFSId(String sharedFSId) {
|
||||
this.sharedFSId = sharedFSId;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getSharedFsVolumeName() {
|
||||
return sharedFsVolumeName;
|
||||
}
|
||||
|
||||
public void setSharedFsVolumeName(String sharedFsVolumeName) {
|
||||
this.sharedFsVolumeName = sharedFsVolumeName;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getSecurityGroupId() {
|
||||
return securityGroupId;
|
||||
}
|
||||
|
||||
public void setSecurityGroupId(String securityGroupId) {
|
||||
this.securityGroupId = securityGroupId;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class Bios {
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class UserVmJoinVOToVmConverterTest {
|
|||
when(src.getAffinityGroupUuid()).thenReturn("ag-1");
|
||||
when(src.getUserDataUuid()).thenReturn("ud-1");
|
||||
|
||||
final Vm vm = UserVmJoinVOToVmConverter.toVm(src, null, null, null, null, null, false);
|
||||
final Vm vm = UserVmJoinVOToVmConverter.toVm(src, null, null, null, null, null, null, false);
|
||||
|
||||
assertEquals("vm-1", vm.getId());
|
||||
assertEquals("vm-1-name", vm.getName());
|
||||
|
|
@ -122,6 +122,7 @@ public class UserVmJoinVOToVmConverterTest {
|
|||
id -> List.of(tag),
|
||||
id -> List.of(disk),
|
||||
ignored -> List.of(nic),
|
||||
null,
|
||||
false);
|
||||
|
||||
assertEquals("down", vm.getStatus());
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public interface UserVmJoinDao extends GenericDao<UserVmJoinVO, Long> {
|
|||
|
||||
List<UserVmJoinVO> listLeaseInstancesExpiringInDays(int days);
|
||||
|
||||
List<UserVmJoinVO> listByHypervisorTypeAndOwners(Hypervisor.HypervisorType hypervisorType, List<Long> accountIds,
|
||||
String domainPath, Filter filter);
|
||||
List<UserVmJoinVO> listByHypervisorNotTypesAndOwners(Hypervisor.HypervisorType hypervisorType,
|
||||
List<String> excludeTypes, List<Long> accountIds,
|
||||
String domainPath, Filter filter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -845,10 +845,11 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<UserVmJoinVO> listByHypervisorTypeAndOwners(Hypervisor.HypervisorType hypervisorType,
|
||||
List<Long> accountIds, String domainPath, Filter filter) {
|
||||
public List<UserVmJoinVO> listByHypervisorNotTypesAndOwners(Hypervisor.HypervisorType hypervisorType,
|
||||
List<String> excludeTypes, List<Long> accountIds, String domainPath, Filter filter) {
|
||||
SearchBuilder<UserVmJoinVO> sb = createSearchBuilder();
|
||||
sb.and("hypervisorType", sb.entity().getHypervisorType(), Op.EQ);
|
||||
sb.and("type", sb.entity().getUserVmType(), Op.NOTIN);
|
||||
boolean accountIdsNotEmpty = CollectionUtils.isNotEmpty(accountIds);
|
||||
boolean domainPathNotBlank = StringUtils.isNotBlank(domainPath);
|
||||
if (accountIdsNotEmpty || domainPathNotBlank) {
|
||||
|
|
@ -859,6 +860,9 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
sb.done();
|
||||
SearchCriteria<UserVmJoinVO> sc = sb.create();
|
||||
sc.setParameters("hypervisorType", hypervisorType);
|
||||
if (CollectionUtils.isNotEmpty(excludeTypes)) {
|
||||
sc.setParameters("type", excludeTypes.toArray());
|
||||
}
|
||||
if (accountIdsNotEmpty) {
|
||||
sc.setParameters("account", accountIds.toArray());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,10 +219,10 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.utils.fsm.StateMachine2;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VMInstanceDetailVO;
|
||||
import com.cloud.vm.UserVmManager;
|
||||
import com.cloud.vm.UserVmService;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceDetailVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
|
|
@ -241,14 +241,13 @@ import com.cloud.vm.VmWorkResizeVolume;
|
|||
import com.cloud.vm.VmWorkSerializer;
|
||||
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.dao.VMInstanceDetailsDao;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -3567,6 +3567,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
CallContext ctx = CallContext.current();
|
||||
long vmId = cmd.getId();
|
||||
boolean expunge = cmd.getExpunge();
|
||||
boolean forced = cmd.isForced();
|
||||
|
||||
if (expunge) {
|
||||
String jobParamsString = ((AsyncJobVO) cmd.getJob()).getCmdInfo();
|
||||
|
|
@ -3581,26 +3582,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (vm == null || vm.getRemoved() != null) {
|
||||
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
|
||||
}
|
||||
if (UserVmManager.SHAREDFSVM.equals(vm.getUserVmType())) {
|
||||
throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance");
|
||||
}
|
||||
|
||||
if (Arrays.asList(State.Destroyed, State.Expunging).contains(vm.getState()) && !expunge) {
|
||||
logger.debug("Vm {} is already destroyed", vm);
|
||||
return vm;
|
||||
}
|
||||
|
||||
if (vm.isDeleteProtection()) {
|
||||
throw new InvalidParameterValueException(String.format(
|
||||
"Instance [id = %s, name = %s] has delete protection enabled and cannot be deleted.",
|
||||
vm.getUuid(), vm.getName()));
|
||||
}
|
||||
|
||||
// check if vm belongs to AutoScale vm group in Disabled state
|
||||
autoScaleManager.checkIfVmActionAllowed(vmId);
|
||||
|
||||
// check if vm belongs to any plugin resources
|
||||
checkPluginsIfVmCanBeDestroyed(vm);
|
||||
validateVmDestroyAllowed(vm, forced);
|
||||
|
||||
// check if there are active volume snapshots tasks
|
||||
logger.debug("Checking if there are any ongoing Snapshots on the ROOT volumes associated with Instance {}", vm);
|
||||
|
|
@ -3659,6 +3647,26 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return destroyedVm;
|
||||
}
|
||||
|
||||
private void validateVmDestroyAllowed(UserVmVO vm, boolean forced) {
|
||||
if (forced) {
|
||||
return;
|
||||
}
|
||||
if (UserVmManager.SHAREDFSVM.equals(vm.getUserVmType())) {
|
||||
throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance");
|
||||
}
|
||||
if (vm.isDeleteProtection()) {
|
||||
throw new InvalidParameterValueException(String.format(
|
||||
"Instance [id = %s, name = %s] has delete protection enabled and cannot be deleted.",
|
||||
vm.getUuid(), vm.getName()));
|
||||
}
|
||||
|
||||
// check if vm belongs to AutoScale vm group in Disabled state
|
||||
autoScaleManager.checkIfVmActionAllowed(vm.getId());
|
||||
|
||||
// check if vm belongs to any plugin resources
|
||||
checkPluginsIfVmCanBeDestroyed(vm);
|
||||
}
|
||||
|
||||
private List<VolumeVO> getVolumesFromIds(DestroyVMCmd cmd) {
|
||||
List<VolumeVO> volumes = new ArrayList<>();
|
||||
if (cmd.getVolumeIds() != null) {
|
||||
|
|
@ -4487,7 +4495,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
if (TemplateType.SYSTEM.equals(template.getTemplateType()) && !CKS_NODE.equals(vmType) &&
|
||||
!SHAREDFSVM.equals(vmType) && !_itMgr.isBlankInstanceDefaultTemplate(template)) {
|
||||
!SHAREDFSVM.equals(vmType) && !_itMgr.isBlankInstance(template)) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to use system template %s to deploy a user vm", template));
|
||||
}
|
||||
|
||||
|
|
@ -6416,7 +6424,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
private void verifyTemplate(BaseDeployVMCmd cmd, VirtualMachineTemplate template, Long serviceOfferingId) {
|
||||
if (TemplateType.VNF.equals(template.getTemplateType())) {
|
||||
vnfTemplateManager.validateVnfApplianceNics(template, cmd.getNetworkIds(), cmd.getVmNetworkMap());
|
||||
if (!_itMgr.isBlankInstance(template)) {
|
||||
vnfTemplateManager.validateVnfApplianceNics(template, cmd.getNetworkIds(), cmd.getVmNetworkMap());
|
||||
}
|
||||
} else if (cmd instanceof DeployVnfApplianceCmd) {
|
||||
throw new InvalidParameterValueException("Can't deploy VNF appliance from a non-VNF template");
|
||||
}
|
||||
|
|
@ -6604,6 +6614,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
String keyboard = cmd.getKeyboard();
|
||||
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap = cmd.getDataDiskTemplateToDiskOfferingMap();
|
||||
Map<String, String> userVmOVFProperties = cmd.getVmProperties();
|
||||
final String instanceType = cmd.getInstanceType();
|
||||
if (zone.getNetworkType() == NetworkType.Basic) {
|
||||
if (networkIds != null) {
|
||||
throw new InvalidParameterValueException("Can't specify network Ids in Basic zone");
|
||||
|
|
@ -6619,7 +6630,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
vm = createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, networkIds, getSecurityGroupIdList(cmd, zone, template, owner), owner, name,
|
||||
displayName, diskOfferingId, size, dataDiskInfoList, group, hypervisor, cmd.getHttpMethod(), userData, userDataId, userDataDetails, sshKeyPairNames, ipToNetworkMap, addrs, displayVm, keyboard,
|
||||
cmd.getAffinityGroupIdList(), cmd.getDetails(), cmd.getCustomId(), cmd.getDhcpOptionsMap(),
|
||||
dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, dynamicScalingEnabled, overrideDiskOfferingId, null, volume, snapshot);
|
||||
dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, dynamicScalingEnabled, overrideDiskOfferingId, instanceType, volume, snapshot);
|
||||
|
||||
} else {
|
||||
if (cmd.getSecurityGroupIdList() != null && !cmd.getSecurityGroupIdList().isEmpty()) {
|
||||
|
|
@ -6627,7 +6638,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
vm = createAdvancedVirtualMachine(zone, serviceOffering, template, networkIds, owner, name, displayName, diskOfferingId, size, dataDiskInfoList, group,
|
||||
hypervisor, cmd.getHttpMethod(), userData, userDataId, userDataDetails, sshKeyPairNames, ipToNetworkMap, addrs, displayVm, keyboard, cmd.getAffinityGroupIdList(), cmd.getDetails(),
|
||||
cmd.getCustomId(), cmd.getDhcpOptionsMap(), dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, dynamicScalingEnabled, null, overrideDiskOfferingId, volume, snapshot);
|
||||
cmd.getCustomId(), cmd.getDhcpOptionsMap(), dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, dynamicScalingEnabled, instanceType, overrideDiskOfferingId, volume, snapshot);
|
||||
if (cmd instanceof DeployVnfApplianceCmd) {
|
||||
vnfTemplateManager.createIsolatedNetworkRulesForVnfAppliance(zone, template, owner, vm, (DeployVnfApplianceCmd) cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -660,6 +660,39 @@ public class SharedFSServiceImpl extends ManagerBase implements SharedFSService,
|
|||
sharedFSDao.remove(sharedFS.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedFS getSharedFSByUuid(String uuid) {
|
||||
return sharedFSDao.findByUuid(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedFS getSharedFSForVmId(long vmId) {
|
||||
return sharedFSDao.findByVm(vmId);
|
||||
}
|
||||
|
||||
public SharedFS updateSharedFSPostRestore(long sharedFsId, long volumeId) {
|
||||
SharedFSVO sharedFS = sharedFSDao.findById(sharedFsId);
|
||||
if (sharedFS == null) {
|
||||
throw new CloudRuntimeException("Unable to find the Shared FileSystem");
|
||||
}
|
||||
VolumeVO volume = volumeDao.findById(volumeId);
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException("Unable to find the Volume");
|
||||
}
|
||||
if (volume.getInstanceId() == null) {
|
||||
throw new CloudRuntimeException("Volume is not attached to any Instance");
|
||||
}
|
||||
if (sharedFS.getAccountId() != volume.getAccountId() || sharedFS.getDomainId() != volume.getDomainId()) {
|
||||
throw new CloudRuntimeException("Shared FileSystem and the Volume do not belong to the same account");
|
||||
}
|
||||
sharedFS.setVolumeId(volume.getId());
|
||||
sharedFS.setVmId(volume.getInstanceId());
|
||||
if (!sharedFSDao.update(sharedFS.getId(), sharedFS)) {
|
||||
throw new CloudRuntimeException("Failed to update Shared FileSystem with the restored Volume information");
|
||||
}
|
||||
return sharedFS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return SharedFSService.class.getSimpleName();
|
||||
|
|
|
|||
Loading…
Reference in New Issue