_configMgr.checkZoneAccess(caller, zone);
// check that vm owner can create vm in the domain
_configMgr.checkZoneAccess(owner, zone);
}
ServiceOfferingVO offering = _serviceOfferingDao.findById(serviceOffering.getId());
// check if account/domain is with in resource limits to create a new vm
boolean isIso = Storage.ImageFormat.ISO == template.getFormat();
// For baremetal, size can be null
Long tmp = _templateDao.findById(template.getId()).getSize();
long size = 0;
if (tmp != null) {
size = tmp;
}
if (diskOfferingId != null) {
size += _diskOfferingDao.findById(diskOfferingId).getDiskSize();
}
resourceLimitCheck(owner, new Long(offering.getCpu()), new Long(offering.getRamSize()));
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, (isIso
|| diskOfferingId == null ? 1 : 2));
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, new Long (size));
// verify security group ids
if (securityGroupIdList != null) {
for (Long securityGroupId : securityGroupIdList) {
SecurityGroup sg = _securityGroupDao.findById(securityGroupId);
if (sg == null) {
throw new InvalidParameterValueException(
"Unable to find security group by id "
+ securityGroupId);
} else {
// verify permissions
_accountMgr.checkAccess(caller, null, true, owner, sg);
}
}
}
// check that the affinity groups exist
if (affinityGroupIdList != null) {
for (Long affinityGroupId : affinityGroupIdList) {
AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId);
if (ag == null) {
throw new InvalidParameterValueException("Unable to find affinity group " + ag);
} else if (!_affinityGroupService.isAffinityGroupProcessorAvailable(ag.getType())) {
throw new InvalidParameterValueException("Affinity group type is not supported for group: " + ag
+ " ,type: " + ag.getType() + " , Please try again after removing the affinity group");
} else {
// verify permissions
if (ag.getAclType() == ACLType.Domain) {
_accountMgr.checkAccess(caller, null, false, owner, ag);
// Root admin has access to both VM and AG by default,
// but
// make sure the owner of these entities is same
if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) {
if (!_affinityGroupService.isAffinityGroupAvailableInDomain(ag.getId(), owner.getDomainId())) {
throw new PermissionDeniedException("Affinity Group " + ag
+ " does not belong to the VM's domain");
}
}
} else {
_accountMgr.checkAccess(caller, null, true, owner, ag);
// Root admin has access to both VM and AG by default,
// but
// make sure the owner of these entities is same
if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) {
if (ag.getAccountId() != owner.getAccountId()) {
throw new PermissionDeniedException("Affinity Group " + ag
+ " does not belong to the VM's account");
}
}
}
}
}
}
if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) {
// check if we have available pools for vm deployment
long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up);
if (availablePools < 1) {
throw new StorageUnavailableException("There are no available pools in the UP state for vm deployment", -1);
}
}
if (template.getTemplateType().equals(TemplateType.SYSTEM)) {
throw new InvalidParameterValueException(
"Unable to use system template " + template.getId()
+ " to deploy a user vm");
}
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");
}
if (isIso && !template.isBootable()) {
throw new InvalidParameterValueException(
"Installing from ISO requires an ISO that is bootable: "
+ template.getId());
}
// Check templates permissions
if (!template.isPublicTemplate()) {
Account templateOwner = _accountMgr.getAccount(template
.getAccountId());
_accountMgr.checkAccess(owner, null, true, templateOwner);
}
// check if the user data is correct
validateUserData(userData, httpmethod);
// Find an SSH public key corresponding to the key pair name, if one is
// given
String sshPublicKey = null;
if (sshKeyPair != null && !sshKeyPair.equals("")) {
SSHKeyPair pair = _sshKeyPairDao.findByName(owner.getAccountId(),
owner.getDomainId(), sshKeyPair);
if (pair == null) {
throw new InvalidParameterValueException(
"A key pair with name '" + sshKeyPair
+ "' was not found.");
}
sshPublicKey = pair.getPublicKey();
}
List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
LinkedHashMap<String, NicProfile> networkNicMap = new LinkedHashMap<String, NicProfile>();
short defaultNetworkNumber = 0;
boolean securityGroupEnabled = false;
boolean vpcNetwork = false;
for (NetworkVO network : networkList) {
if (network.getDataCenterId() != zone.getId()) {
throw new InvalidParameterValueException("Network id="
+ network.getId() + " doesn't belong to zone "
+ zone.getId());
}
IpAddresses requestedIpPair = null;
if (requestedIps != null && !requestedIps.isEmpty()) {
requestedIpPair = requestedIps.get(network.getId());
}
if (requestedIpPair == null) {
requestedIpPair = new IpAddresses(null, null);
} else {
_networkModel.checkRequestedIpAddresses(network.getId(), requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
}
NicProfile profile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address());
if (defaultNetworkNumber == 0) {
defaultNetworkNumber++;
// if user requested specific ip for default network, add it
if (defaultIps.getIp4Address() != null || defaultIps.getIp6Address() != null) {
_networkModel.checkRequestedIpAddresses(network.getId(), defaultIps.getIp4Address(), defaultIps.getIp6Address());
profile = new NicProfile(defaultIps.getIp4Address(), defaultIps.getIp6Address());
}
profile.setDefaultNic(true);
}
networks.add(new Pair<NetworkVO, NicProfile>(network, profile));
if (_networkModel.isSecurityGroupSupportedInNetwork(network)) {
securityGroupEnabled = true;
}
// vm can't be a part of more than 1 VPC network
if (network.getVpcId() != null) {
if (vpcNetwork) {
throw new InvalidParameterValueException(
"Vm can't be a part of more than 1 VPC network");
}
vpcNetwork = true;
}
networkNicMap.put(network.getUuid(), profile);
}
if (securityGroupIdList != null && !securityGroupIdList.isEmpty()
&& !securityGroupEnabled) {
throw new InvalidParameterValueException(
"Unable to deploy vm with security groups as SecurityGroup service is not enabled for the vm's network");
}
// Verify network information - network default network has to be set;
// and vm can't have more than one default network
// This is a part of business logic because default network is required
// 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");
} else if (defaultNetworkNumber > 1) {
throw new InvalidParameterValueException(
"Only 1 default network per vm is supported");
}
long id = _vmDao.getNextInSequence(Long.class, "id");
if (hostName != null) {
// Check is hostName is RFC compliant
checkNameForRFCCompliance(hostName);
}
String instanceName = null;
String uuidName = UUID.randomUUID().toString();
if (_instanceNameFlag && hypervisor.equals(HypervisorType.VMware)) {
if (hostName == null) {
if (displayName != null) {
hostName = displayName;
} else {
hostName = uuidName;
}
}
} else {
if (hostName == null) {
hostName = uuidName;
}
}
instanceName = VirtualMachineName.getVmName(id, owner.getId(), _instance);
// Check if VM with instanceName already exists.
VMInstanceVO vmObj = _vmInstanceDao.findVMByInstanceName(instanceName);
if (vmObj != null && vmObj.getState() != VirtualMachine.State.Expunging) {
throw new InvalidParameterValueException("There already exists a VM by the display name supplied");
}
// Check that hostName is unique in the network domain
Map<String, List<Long>> ntwkDomains = new HashMap<String, List<Long>>();
for (NetworkVO network : networkList) {
String ntwkDomain = network.getNetworkDomain();
if (!ntwkDomains.containsKey(ntwkDomain)) {
List<Long> ntwkIds = new ArrayList<Long>();
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
} else {
List<Long> ntwkIds = ntwkDomains.get(ntwkDomain);
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
}
}
for (String ntwkDomain : ntwkDomains.keySet()) {
for (Long ntwkId : ntwkDomains.get(ntwkDomain)) {
// * get all vms hostNames in the network
List<String> hostNames = _vmInstanceDao.listDistinctHostNames(ntwkId);
// * verify that there are no duplicates
if (hostNames.contains(hostName)) {
throw new InvalidParameterValueException("The vm with hostName " + hostName
+ " already exists in the network domain: " + ntwkDomain + "; network="
+ _networkModel.getNetwork(ntwkId));
}
}
}
HypervisorType hypervisorType = null;
if (template == null || template.getHypervisorType() == null
|| template.getHypervisorType() == HypervisorType.None) {
hypervisorType = hypervisor;
} else {
hypervisorType = template.getHypervisorType();
}
Transaction txn = Transaction.currentTxn();
txn.start();
UserVmVO vm = new UserVmVO(id, instanceName, displayName,
template.getId(), hypervisorType, template.getGuestOSId(),
offering.getOfferHA(), offering.getLimitCpuUse(),
owner.getDomainId(), owner.getId(), offering.getId(), userData,
hostName, diskOfferingId);
vm.setUuid(uuidName);
vm.setDynamicallyScalable(template.isDynamicallyScalable());
if (sshPublicKey != null) {
vm.setDetail("SSH.PublicKey", sshPublicKey);
}
if (keyboard != null && !keyboard.isEmpty())
vm.setDetail(VmDetailConstants.KEYBOARD, keyboard);
if (isIso) {
vm.setIsoId(template.getId());
}
if(isDisplayVmEnabled != null){
if(!_accountMgr.isRootAdmin(caller.getType())){
throw new PermissionDeniedException( "Cannot update parameter displayvm, only admin permitted ");
}
vm.setDisplayVm(isDisplayVmEnabled);
}else {
vm.setDisplayVm(true);
}
// If hypervisor is vSphere, check for clone type setting.
if (hypervisorType.equals(HypervisorType.VMware)) {
// retrieve clone flag.
UserVmCloneType cloneType = UserVmCloneType.linked;
String value = _configDao.getValue(Config.VmwareCreateFullClone.key());
if (value != null) {
if (Boolean.parseBoolean(value) == true)
cloneType = UserVmCloneType.full;
}
UserVmCloneSettingVO vmCloneSettingVO = new UserVmCloneSettingVO(id, cloneType.toString());
_vmCloneSettingDao.persist(vmCloneSettingVO);
}
long guestOSId = template.getGuestOSId();
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
long guestOSCategoryId = guestOS.getCategoryId();
GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId);
// If hypervisor is vSphere and OS is OS X, set special settings.
if (hypervisorType.equals(HypervisorType.VMware)) {
if (guestOS.getDisplayName().toLowerCase().contains("apple mac os")){
vm.setDetail("smc.present", "TRUE");
vm.setDetail(VmDetailConstants.ROOK_DISK_CONTROLLER, "scsi");
vm.setDetail("firmware", "efi");
s_logger.info("guestOS is OSX : overwrite root disk controller to scsi, use smc and efi");
}
}
_vmDao.persist(vm);
_vmDao.saveDetails(vm);
s_logger.debug("Allocating in the DB for vm");
DataCenterDeployment plan = new DataCenterDeployment(zone.getId());
List<String> computeTags = new ArrayList<String>();
computeTags.add(offering.getHostTag());
List<String> rootDiskTags = new ArrayList<String>();
rootDiskTags.add(offering.getTags());
if(isIso){
VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), new Long(owner.getAccountId()).toString(), vm.getIsoId().toString(), hostName, displayName, hypervisor.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan);
}else {
VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachine(vm.getUuid(), new Long(owner.getAccountId()).toString(), new Long(template.getId()).toString(), hostName, displayName, hypervisor.name(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan);
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully allocated DB entry for " + vm);
}
UserContext.current().setEventDetails("Vm Id: " + vm.getId());
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(),
vm.getHostName(), offering.getId(), template.getId(), hypervisorType.toString(),
VirtualMachine.class.getName(), vm.getUuid());
//Update Resource Count for the given account
resourceCountIncrement(accountId, new Long(offering.getCpu()),
new Long(offering.getRamSize()));
txn.commit();
// Assign instance to the group
try {