mirror of https://github.com/apache/cloudstack.git
api/server: create dummy KVM VM without volume and network is optional
This commit is contained in:
parent
c36cd2c26c
commit
ca4112e7d0
|
|
@ -216,6 +216,7 @@ public class ApiConstants {
|
|||
public static final String DOMAIN_PATH = "domainpath";
|
||||
public static final String DOMAIN_ID = "domainid";
|
||||
public static final String DOMAIN__ID = "domainId";
|
||||
public static final String DUMMY = "dummy";
|
||||
public static final String DURATION = "duration";
|
||||
public static final String ELIGIBLE = "eligible";
|
||||
public static final String EMAIL = "email";
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ public class DeployVMCmd extends BaseDeployVMCmd {
|
|||
@Parameter(name = ApiConstants.SNAPSHOT_ID, type = CommandType.UUID, entityType = SnapshotResponse.class, since = "4.21")
|
||||
private Long snapshotId;
|
||||
|
||||
@Parameter(name = ApiConstants.DUMMY, type = CommandType.BOOLEAN, since = "4.23", description = "Deploy a dummy VM without any disk. False by default. This supports KVM only.")
|
||||
private Boolean dummy;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -84,6 +88,10 @@ public class DeployVMCmd extends BaseDeployVMCmd {
|
|||
return snapshotId;
|
||||
}
|
||||
|
||||
public boolean getDummy() {
|
||||
return dummy != null && dummy;
|
||||
}
|
||||
|
||||
public boolean isVolumeOrSnapshotProvided() {
|
||||
return volumeId != null || snapshotId != null;
|
||||
}
|
||||
|
|
@ -132,7 +140,7 @@ public class DeployVMCmd extends BaseDeployVMCmd {
|
|||
|
||||
@Override
|
||||
public void create() throws ResourceAllocationException {
|
||||
if (Stream.of(templateId, snapshotId, volumeId).filter(Objects::nonNull).count() != 1) {
|
||||
if (!getDummy() && Stream.of(templateId, snapshotId, volumeId).filter(Objects::nonNull).count() != 1) {
|
||||
throw new CloudRuntimeException("Please provide only one of the following parameters - template ID, volume ID or snapshot ID");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -577,7 +577,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
logger.debug("Allocating disks for {}", persistedVm);
|
||||
|
||||
allocateRootVolume(persistedVm, template, rootDiskOfferingInfo, owner, rootDiskSizeFinal, volume, snapshot);
|
||||
if (_userVmMgr.isDummyTemplate(hyperType, template.getId())) {
|
||||
logger.debug("Template is a dummy template for hypervisor {}, skipping volume allocation", hyperType);
|
||||
return;
|
||||
} else {
|
||||
allocateRootVolume(persistedVm, template, rootDiskOfferingInfo, owner, rootDiskSizeFinal, volume, snapshot);
|
||||
}
|
||||
|
||||
|
||||
// Create new Volume context and inject event resource type, id and details to generate VOLUME.CREATE event for the ROOT disk.
|
||||
CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume);
|
||||
|
|
|
|||
|
|
@ -106,4 +106,6 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
|
|||
|
||||
VMTemplateVO findActiveSystemTemplateByHypervisorArchAndUrlPath(HypervisorType hypervisorType,
|
||||
CPU.CPUArch arch, String urlPathSuffix);
|
||||
|
||||
VMTemplateVO findByAccountAndName(Long accountId, String templateName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -945,4 +945,12 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
}
|
||||
return rows > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMTemplateVO findByAccountAndName(Long accountId, String templateName) {
|
||||
SearchCriteria<VMTemplateVO> sc = NameAccountIdSearch.create();
|
||||
sc.setParameters("name", templateName);
|
||||
sc.setParameters("accountId", accountId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@
|
|||
// under the License.
|
||||
package com.cloud.vm;
|
||||
|
||||
import static com.cloud.user.ResourceLimitService.ResourceLimitHostTags;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
|
|
@ -40,8 +41,7 @@ import com.cloud.storage.Storage.StoragePoolType;
|
|||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
import static com.cloud.user.ResourceLimitService.ResourceLimitHostTags;
|
||||
import com.cloud.utils.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -204,4 +204,5 @@ public interface UserVmManager extends UserVmService {
|
|||
*/
|
||||
boolean isVMPartOfAnyCKSCluster(VMInstanceVO vm);
|
||||
|
||||
boolean isDummyTemplate(HypervisorType hypervisorType, Long templateId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,9 +60,6 @@ import javax.naming.ConfigurationException;
|
|||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.storage.SnapshotPolicyVO;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
|
|
@ -315,6 +312,7 @@ import com.cloud.org.Grouping;
|
|||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
|
|
@ -324,8 +322,10 @@ import com.cloud.storage.DataStoreRole;
|
|||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.GuestOSCategoryVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.LaunchPermissionVO;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotPolicyVO;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
|
|
@ -343,7 +343,9 @@ import com.cloud.storage.VolumeVO;
|
|||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.LaunchPermissionDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
|
|
@ -421,6 +423,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
private static final long GiB_TO_BYTES = 1024 * 1024 * 1024;
|
||||
|
||||
public static final String KVM_VM_DUMMY_TEMPLATE_NAME = "kvm-vm-dummy-template";
|
||||
|
||||
|
||||
@Inject
|
||||
private EntityManager _entityMgr;
|
||||
@Inject
|
||||
|
|
@ -617,6 +622,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
@Inject
|
||||
BackupScheduleDao backupScheduleDao;
|
||||
@Inject
|
||||
LaunchPermissionDao launchPermissionDao;
|
||||
@Inject
|
||||
private UserDataDao userDataDao;
|
||||
@Inject
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
|
|
@ -651,6 +658,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
private boolean _instanceNameFlag;
|
||||
private int _scaleRetry;
|
||||
private Map<Long, VmAndCountDetails> vmIdCountMap = new ConcurrentHashMap<>();
|
||||
private static VMTemplateVO KVM_VM_DUMMY_TEMPLATE;
|
||||
|
||||
protected static long ROOT_DEVICE_ID = 0;
|
||||
|
||||
|
|
@ -2498,6 +2506,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
_vmIpFetchThreadExecutor = Executors.newFixedThreadPool(VmIpFetchThreadPoolMax.value(), new NamedThreadFactory("vmIpFetchThread"));
|
||||
|
||||
KVM_VM_DUMMY_TEMPLATE = _templateDao.findByAccountAndName(Account.ACCOUNT_ID_SYSTEM, KVM_VM_DUMMY_TEMPLATE_NAME);
|
||||
if (KVM_VM_DUMMY_TEMPLATE == null) {
|
||||
KVM_VM_DUMMY_TEMPLATE = VMTemplateVO.createSystemIso(_templateDao.getNextInSequence(Long.class, "id"), KVM_VM_DUMMY_TEMPLATE_NAME, KVM_VM_DUMMY_TEMPLATE_NAME, true,
|
||||
"", true, 64, Account.ACCOUNT_ID_SYSTEM, "",
|
||||
"Dummy Template for KVM VM", false, 1);
|
||||
KVM_VM_DUMMY_TEMPLATE.setState(VirtualMachineTemplate.State.Active);
|
||||
KVM_VM_DUMMY_TEMPLATE.setFormat(ImageFormat.QCOW2);
|
||||
KVM_VM_DUMMY_TEMPLATE = _templateDao.persist(KVM_VM_DUMMY_TEMPLATE);
|
||||
}
|
||||
|
||||
logger.info("User VM Manager is configured.");
|
||||
|
||||
return true;
|
||||
|
|
@ -3927,7 +3945,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
_accountMgr.checkAccess(owner, _diskOfferingDao.findById(diskOfferingId), zone);
|
||||
|
||||
// If no network is specified, find system security group enabled network
|
||||
if (networkIdList == null || networkIdList.isEmpty()) {
|
||||
if (isDummyTemplate(hypervisor, template.getId())) {
|
||||
logger.debug("Template is a dummy template for hypervisor {}, skipping network allocation in an advanced security group enabled zone", hypervisor);
|
||||
} else if (networkIdList == null || networkIdList.isEmpty()) {
|
||||
Network networkWithSecurityGroup = _networkModel.getNetworkWithSGWithFreeIPs(owner, zone.getId());
|
||||
if (networkWithSecurityGroup == null) {
|
||||
throw new InvalidParameterValueException("No network with security enabled is found in zone id=" + zone.getUuid());
|
||||
|
|
@ -4040,7 +4060,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
_accountMgr.checkAccess(owner, diskOffering, zone);
|
||||
|
||||
List<HypervisorType> vpcSupportedHTypes = _vpcMgr.getSupportedVpcHypervisors();
|
||||
if (networkIdList == null || networkIdList.isEmpty()) {
|
||||
if (isDummyTemplate(hypervisor, template.getId())) {
|
||||
logger.debug("Template is a dummy template for hypervisor {}, skipping network allocation in an advanced zone", hypervisor);
|
||||
} else if (networkIdList == null || networkIdList.isEmpty()) {
|
||||
NetworkVO defaultNetwork = getDefaultNetwork(zone, owner, false);
|
||||
if (defaultNetwork != null) {
|
||||
networkList.add(defaultNetwork);
|
||||
|
|
@ -4475,7 +4497,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
|
||||
if (TemplateType.SYSTEM.equals(template.getTemplateType()) && !CKS_NODE.equals(vmType) && !SHAREDFSVM.equals(vmType)) {
|
||||
if (TemplateType.SYSTEM.equals(template.getTemplateType()) && !CKS_NODE.equals(vmType) && !SHAREDFSVM.equals(vmType) && !isDummyTemplate(hypervisorType, template.getId())) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to use system template %s to deploy a user vm", template));
|
||||
}
|
||||
|
||||
|
|
@ -4488,7 +4510,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (CollectionUtils.isEmpty(snapshotsOnZone)) {
|
||||
throw new InvalidParameterValueException("The snapshot does not exist on zone " + zone.getId());
|
||||
}
|
||||
} else {
|
||||
} else if (!isDummyTemplate(hypervisorType, template.getId())) {
|
||||
List<VMTemplateZoneVO> listZoneTemplate = _templateZoneDao.listByZoneTemplate(zone.getId(), template.getId());
|
||||
if (listZoneTemplate == null || listZoneTemplate.isEmpty()) {
|
||||
throw new InvalidParameterValueException("The template " + template.getId() + " is not available for use");
|
||||
|
|
@ -4603,7 +4625,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
// by Agent Manager in order to configure default
|
||||
// gateway for the vm
|
||||
if (defaultNetworkNumber == 0) {
|
||||
throw new InvalidParameterValueException("At least 1 default network has to be specified for the vm");
|
||||
if (isDummyTemplate(hypervisorType, template.getId())) {
|
||||
logger.debug("Template is a dummy template for hypervisor {}, vm can be created without a default network", hypervisorType);
|
||||
} else {
|
||||
throw new InvalidParameterValueException("At least 1 default network has to be specified for the vm");
|
||||
}
|
||||
} else if (defaultNetworkNumber > 1) {
|
||||
throw new InvalidParameterValueException("Only 1 default network per vm is supported");
|
||||
}
|
||||
|
|
@ -5321,7 +5347,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
@ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", async = true)
|
||||
public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException {
|
||||
long vmId = cmd.getEntityId();
|
||||
if (!cmd.getStartVm()) {
|
||||
if (!cmd.getStartVm() || cmd.getDummy()) {
|
||||
return getUserVm(vmId);
|
||||
}
|
||||
Long podId = null;
|
||||
|
|
@ -6469,6 +6495,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
(!(HypervisorType.KVM.equals(template.getHypervisorType()) || HypervisorType.KVM.equals(cmd.getHypervisor())))) {
|
||||
throw new InvalidParameterValueException("Deploying a virtual machine with existing volume/snapshot is supported only from KVM hypervisors");
|
||||
}
|
||||
if (template == null && HypervisorType.KVM.equals(cmd.getHypervisor()) && cmd.getDummy()) {
|
||||
template = KVM_VM_DUMMY_TEMPLATE;
|
||||
logger.info("Creating launch permission for Dummy template");
|
||||
LaunchPermissionVO launchPermission = new LaunchPermissionVO(KVM_VM_DUMMY_TEMPLATE.getId(), owner.getId());
|
||||
launchPermissionDao.persist(launchPermission);
|
||||
}
|
||||
// Make sure a valid template ID was specified
|
||||
if (template == null) {
|
||||
throw new InvalidParameterValueException("Unable to use template " + templateId);
|
||||
|
|
@ -6627,6 +6659,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (isLeaseFeatureEnabled) {
|
||||
applyLeaseOnCreateInstance(vm, cmd.getLeaseDuration(), cmd.getLeaseExpiryAction(), svcOffering);
|
||||
}
|
||||
|
||||
if (KVM_VM_DUMMY_TEMPLATE != null && template.getId() == KVM_VM_DUMMY_TEMPLATE.getId() && cmd instanceof DeployVMCmd && ((DeployVMCmd) cmd).getDummy()) {
|
||||
logger.info("Revoking launch permission for Dummy template");
|
||||
launchPermissionDao.removePermissions(KVM_VM_DUMMY_TEMPLATE.getId(), Collections.singletonList(owner.getId()));
|
||||
}
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
|
|
@ -10061,4 +10099,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
vm.setVncPassword(customParameters.get(VmDetailConstants.KVM_VNC_PASSWORD));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDummyTemplate(HypervisorType hypervisorType, Long templateId) {
|
||||
if (HypervisorType.KVM.equals(hypervisorType) && KVM_VM_DUMMY_TEMPLATE != null && KVM_VM_DUMMY_TEMPLATE.getId() == templateId) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue