http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/00df9727/server/src/com/cloud/template/TemplateManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index f9cf277..736f712 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -26,6 +26,9 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -35,22 +38,50 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; -import org.apache.cloudstack.api.command.user.iso.*; -import org.apache.cloudstack.api.command.user.template.*; +import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; +import org.apache.cloudstack.api.command.user.iso.ExtractIsoCmd; +import org.apache.cloudstack.api.command.user.iso.ListIsoPermissionsCmd; +import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; +import org.apache.cloudstack.api.command.user.iso.UpdateIsoPermissionsCmd; +import org.apache.cloudstack.api.command.user.template.CopyTemplateCmd; +import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; +import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; +import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd; +import org.apache.cloudstack.api.command.user.template.ListTemplatePermissionsCmd; +import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; +import org.apache.cloudstack.api.command.user.template.UpdateTemplatePermissionsCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.ComputeChecksumCommand; import com.cloud.agent.api.downloadTemplateFromSwiftToSecondaryStorageCommand; +import com.cloud.agent.api.uploadTemplateToSwiftFromSecondaryStorageCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.to.SwiftTO; -import com.cloud.agent.api.uploadTemplateToSwiftFromSecondaryStorageCommand; + +import com.cloud.api.ApiDBUtils; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; import com.cloud.configuration.Config; @@ -64,12 +95,14 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; +import com.cloud.event.UsageEventVO; import com.cloud.event.dao.EventDao; import com.cloud.event.dao.UsageEventDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; @@ -77,34 +110,72 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.projects.Project; import com.cloud.projects.ProjectManager; -import com.cloud.storage.*; + +import com.cloud.resource.ResourceManager; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.LaunchPermissionVO; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage; + import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolStatus; -import com.cloud.storage.StoragePoolVO; import com.cloud.storage.TemplateProfile; import com.cloud.storage.Upload; import com.cloud.storage.Upload.Type; + +import com.cloud.storage.UploadVO; +import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.VMTemplateS3VO; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.dao.*; +import com.cloud.storage.VMTemplateSwiftVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeManager; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.LaunchPermissionDao; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.StoragePoolDao; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.storage.dao.UploadDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplateDetailsDao; +import com.cloud.storage.dao.VMTemplateHostDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VMTemplateS3Dao; +import com.cloud.storage.dao.VMTemplateSwiftDao; +import com.cloud.storage.dao.VMTemplateZoneDao; +import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.download.DownloadMonitor; import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.upload.UploadMonitor; import com.cloud.template.TemplateAdapter.TemplateAdapterType; -import com.cloud.user.*; + +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.User; +import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserAccountDao; import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ManagerBase; - import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.*; import com.cloud.utils.exception.CloudRuntimeException; @@ -123,6 +194,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, @Inject VMTemplateHostDao _tmpltHostDao; @Inject VMTemplatePoolDao _tmpltPoolDao; @Inject VMTemplateZoneDao _tmpltZoneDao; + @Inject + protected VMTemplateDetailsDao _templateDetailsDao; @Inject VMInstanceDao _vmInstanceDao; @Inject StoragePoolDao _poolDao; @Inject StoragePoolHostDao _poolHostDao; @@ -153,6 +226,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, ClusterDao _clusterDao; @Inject DomainDao _domainDao; @Inject UploadDao _uploadDao; + @Inject + protected GuestOSDao _guestOSDao; long _routerTemplateId = -1; @Inject StorageManager _storageMgr; @Inject AsyncJobManager _asyncMgr; @@ -164,6 +239,20 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, @Inject SecondaryStorageVmManager _ssvmMgr; @Inject LaunchPermissionDao _launchPermissionDao; @Inject ProjectManager _projectMgr; + @Inject + VolumeDataFactory volFactory; + @Inject + ImageDataFactory tmplFactory; + @Inject + SnapshotDataFactory snapshotFactory; + @Inject + ImageService imageSvr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + protected ResourceManager _resourceMgr; + @Inject VolumeManager volumeMgr; + @Inject VMTemplateHostDao templateHostDao; int _primaryStorageDownloadWait; @@ -217,7 +306,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if(!_accountService.isRootAdmin(account.getType())){ throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied"); } - } + } + TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor())); TemplateProfile profile = adapter.prepare(cmd); VMTemplateVO template = adapter.create(profile); @@ -228,6 +318,22 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, throw new CloudRuntimeException("Failed to create a template"); } } + + @Override + public DataStore getImageStore(String storeUuid, long zoneId) { + DataStore imageStore = null; + if (storeUuid != null) { + imageStore = this.dataStoreMgr.getDataStore(storeUuid, DataStoreRole.Image); + } else { + List<DataStore> stores = this.dataStoreMgr.getImageStores(new ZoneScope(zoneId)); + if (stores.size() > 1) { + throw new CloudRuntimeException("multiple image stores, don't know which one to use"); + } + imageStore = stores.get(0); + } + + return imageStore; + } @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_EXTRACT, eventDescription = "extracting ISO", async = true) @@ -330,7 +436,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - List<HostVO> sservers = _storageMgr.getSecondaryStorageHosts(zoneId); + List<HostVO> sservers = getSecondaryStorageHosts(zoneId); VMTemplateHostVO tmpltHostRef = null; if (sservers != null) { @@ -425,7 +531,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, private void reallyRun() { s_logger.info("Start to preload template " + template.getId() + " into primary storage " + pool.getId()); - prepareTemplateForCreate(template, pool); + StoragePool pol = (StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId()); + prepareTemplateForCreate(template, pol); s_logger.info("End of preloading template " + template.getId() + " into primary storage " + pool.getId()); } }); @@ -539,8 +646,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } @Override @DB - public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO template, StoragePool pool) { - template = _tmpltDao.findById(template.getId(), true); + public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO templ, StoragePool pool) { + VMTemplateVO template = _tmpltDao.findById(templ.getId(), true); long poolId = pool.getId(); long templateId = template.getId(); @@ -564,7 +671,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } } - templateHostRef = _storageMgr.findVmTemplateHost(templateId, pool); + templateHostRef = findVmTemplateHost(templateId, pool); if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { String result = downloadTemplateFromSwiftToSecondaryStorage(dcId, templateId); @@ -578,7 +685,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); return null; } - templateHostRef = _storageMgr.findVmTemplateHost(templateId, pool); + templateHostRef = findVmTemplateHost(templateId, pool); if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); return null; @@ -671,6 +778,61 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, return null; } + + + + @Override + public VMTemplateHostVO findVmTemplateHost(long templateId, + StoragePool pool) { + long dcId = pool.getDataCenterId(); + Long podId = pool.getPodId(); + + List<HostVO> secHosts = _ssvmMgr + .listSecondaryStorageHostsInOneZone(dcId); + + + if (secHosts.size() == 1) { + VMTemplateHostVO templateHostVO = this._tmpltHostDao + .findByHostTemplate(secHosts.get(0).getId(), templateId); + return templateHostVO; + } + if (podId != null) { + List<VMTemplateHostVO> templHosts = this._tmpltHostDao + .listByTemplateStatus(templateId, dcId, podId, + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (templHosts != null && !templHosts.isEmpty()) { + Collections.shuffle(templHosts); + return templHosts.get(0); + } + } + List<VMTemplateHostVO> templHosts = this._tmpltHostDao + .listByTemplateStatus(templateId, dcId, + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (templHosts != null && !templHosts.isEmpty()) { + Collections.shuffle(templHosts); + return templHosts.get(0); + } + return null; + } + + @Override + public String getChecksum(Long hostId, String templatePath) { + HostVO ssHost = _hostDao.findById(hostId); + Host.Type type = ssHost.getType(); + if (type != Host.Type.SecondaryStorage + && type != Host.Type.LocalSecondaryStorage) { + return null; + } + String secUrl = ssHost.getStorageUrl(); + Answer answer; + answer = _agentMgr.sendToSecStorage(ssHost, new ComputeChecksumCommand( + secUrl, templatePath)); + if (answer != null && answer.getResult()) { + return answer.getDetails(); + } + return null; + } + @Override @DB public VMTemplateHostVO prepareISOForCreate(VMTemplateVO template, StoragePool pool) { @@ -684,7 +846,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, long templateStoragePoolRefId; String origUrl = null; - templateHostRef = _storageMgr.findVmTemplateHost(templateId, pool); + templateHostRef = findVmTemplateHost(templateId, pool); if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { String result = downloadTemplateFromSwiftToSecondaryStorage(dcId, templateId); @@ -698,7 +860,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); return null; } - templateHostRef = _storageMgr.findVmTemplateHost(templateId, pool); + templateHostRef = findVmTemplateHost(templateId, pool); if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) { s_logger.error("Unable to find a secondary storage host who has completely downloaded the template."); return null; @@ -839,13 +1001,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, throw new InvalidParameterValueException("Unable to find template with id"); } - HostVO dstSecHost = _storageMgr.getSecondaryStorageHost(destZoneId, templateId); + HostVO dstSecHost = getSecondaryStorageHost(destZoneId, templateId); if ( dstSecHost != null ) { s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecHost.getId() + " in zone " + destZoneId + " , don't need to copy"); return template; } - HostVO srcSecHost = _storageMgr.getSecondaryStorageHost(sourceZoneId, templateId); + HostVO srcSecHost = getSecondaryStorageHost(sourceZoneId, templateId); if ( srcSecHost == null ) { throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId ); } @@ -900,7 +1062,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, @Override public void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO) { - StoragePoolVO pool = _poolDao.findById(templatePoolVO.getPoolId()); + StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId()); VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId()); @@ -1176,12 +1338,57 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, throw new CloudRuntimeException("Failed to attach iso"); } } + + private boolean attachISOToVM(long vmId, long isoId, boolean attach) { + UserVmVO vm = this._userVmDao.findById(vmId); + + if (vm == null) { + return false; + } else if (vm.getState() != State.Running) { + return true; + } + String isoPath; + VMTemplateVO tmplt = this._tmpltDao.findById(isoId); + if (tmplt == null) { + s_logger.warn("ISO: " + isoId + " does not exist"); + return false; + } + // Get the path of the ISO + Pair<String, String> isoPathPair = null; + if (tmplt.getTemplateType() == TemplateType.PERHOST) { + isoPath = tmplt.getName(); + } else { + isoPathPair = getAbsoluteIsoPath(isoId, + vm.getDataCenterId()); + if (isoPathPair == null) { + s_logger.warn("Couldn't get absolute iso path"); + return false; + } else { + isoPath = isoPathPair.first(); + } + } + + String vmName = vm.getInstanceName(); + + HostVO host = _hostDao.findById(vm.getHostId()); + if (host == null) { + s_logger.warn("Host: " + vm.getHostId() + " does not exist"); + return false; + } + AttachIsoCommand cmd = new AttachIsoCommand(vmName, isoPath, attach); + if (isoPathPair != null) { + cmd.setStoreUrl(isoPathPair.second()); + } + Answer a = _agentMgr.easySend(vm.getHostId(), cmd); + + return (a != null && a.getResult()); + } private boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach) { UserVmVO vm = _userVmDao.findById(vmId); VMTemplateVO iso = _tmpltDao.findById(isoId); - boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach); + boolean success = attachISOToVM(vmId, isoId, attach); if ( success && attach) { vm.setIsoId(iso.getId()); _userVmDao.update(vmId, vm); @@ -1475,4 +1682,456 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, return true; } + + private String getRandomPrivateTemplateName() { + return UUID.randomUUID().toString(); + } + + + + + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", async = true) + public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) + throws CloudRuntimeException { + Long userId = UserContext.current().getCallerUserId(); + if (userId == null) { + userId = User.UID_SYSTEM; + } + long templateId = command.getEntityId(); + Long volumeId = command.getVolumeId(); + Long snapshotId = command.getSnapshotId(); + VMTemplateVO privateTemplate = null; + Long accountId = null; + SnapshotVO snapshot = null; + + try { + TemplateInfo tmplInfo = this.tmplFactory.getTemplate(templateId); + snapshot = _snapshotDao.findById(snapshotId); + ZoneScope scope = new ZoneScope(snapshot.getDataCenterId()); + List<DataStore> store = this.dataStoreMgr.getImageStores(scope); + if (store.size() > 1) { + throw new CloudRuntimeException("muliple image data store, don't know which one to use"); + } + AsyncCallFuture<CommandResult> future = null; + if (snapshotId != null) { + SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshotId); + future = this.imageSvr.createTemplateFromSnapshotAsync(snapInfo, tmplInfo, store.get(0)); + } else if (volumeId != null) { + VolumeInfo volInfo = this.volFactory.getVolume(volumeId); + future = this.imageSvr.createTemplateFromVolumeAsync(volInfo, tmplInfo, store.get(0)); + } else { + throw new CloudRuntimeException( + "Creating private Template need to specify snapshotId or volumeId"); + } + + CommandResult result = null; + try { + result = future.get(); + if (result.isFailed()) { + privateTemplate = null; + s_logger.debug("Failed to create template" + result.getResult()); + throw new CloudRuntimeException("Failed to create template" + result.getResult()); + } + + privateTemplate = this._tmpltDao.findById(templateId); + UsageEventVO usageEvent = new UsageEventVO( + EventTypes.EVENT_TEMPLATE_CREATE, + privateTemplate.getAccountId(), + snapshot.getDataCenterId(), + privateTemplate.getId(), privateTemplate.getName(), + null, privateTemplate.getSourceTemplateId(), + privateTemplate.getSize()); + _usageEventDao.persist(usageEvent); + } catch (InterruptedException e) { + s_logger.debug("Failed to create template", e); + throw new CloudRuntimeException("Failed to create template", e); + } catch (ExecutionException e) { + s_logger.debug("Failed to create template", e); + throw new CloudRuntimeException("Failed to create template", e); + } + + } finally { + /*if (snapshot != null && snapshot.getSwiftId() != null + && secondaryStorageURL != null && zoneId != null + && accountId != null && volumeId != null) { + _snapshotMgr.deleteSnapshotsForVolume(secondaryStorageURL, + zoneId, accountId, volumeId); + }*/ + if (privateTemplate == null) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + // Remove the template record + this._tmpltDao.expunge(templateId); + + // decrement resource count + if (accountId != null) { + _resourceLimitMgr.decrementResourceCount(accountId, + ResourceType.template); + } + txn.commit(); + } + } + + if (privateTemplate != null) { + return privateTemplate; + } else { + throw new CloudRuntimeException("Failed to create a template"); + } + } + + private static boolean isAdmin(short accountType) { + return ((accountType == Account.ACCOUNT_TYPE_ADMIN) + || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) + || (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); + } + @Override + @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true) + public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, + Account templateOwner) throws ResourceAllocationException { + Long userId = UserContext.current().getCallerUserId(); + + Account caller = UserContext.current().getCaller(); + boolean isAdmin = (isAdmin(caller.getType())); + + _accountMgr.checkAccess(caller, null, true, templateOwner); + + String name = cmd.getTemplateName(); + if ((name == null) || (name.length() > 32)) { + throw new InvalidParameterValueException( + "Template name cannot be null and should be less than 32 characters"); + } + + if (cmd.getTemplateTag() != null) { + if (!_accountService.isRootAdmin(caller.getType())) { + throw new PermissionDeniedException( + "Parameter templatetag can only be specified by a Root Admin, permission denied"); + } + } + + // do some parameter defaulting + Integer bits = cmd.getBits(); + Boolean requiresHvm = cmd.getRequiresHvm(); + Boolean passwordEnabled = cmd.isPasswordEnabled(); + Boolean isPublic = cmd.isPublic(); + Boolean featured = cmd.isFeatured(); + int bitsValue = ((bits == null) ? 64 : bits.intValue()); + boolean requiresHvmValue = ((requiresHvm == null) ? true : requiresHvm + .booleanValue()); + boolean passwordEnabledValue = ((passwordEnabled == null) ? false + : passwordEnabled.booleanValue()); + if (isPublic == null) { + isPublic = Boolean.FALSE; + } + boolean allowPublicUserTemplates = Boolean.parseBoolean(_configDao + .getValue("allow.public.user.templates")); + if (!isAdmin && !allowPublicUserTemplates && isPublic) { + throw new PermissionDeniedException("Failed to create template " + + name + ", only private templates can be created."); + } + + Long volumeId = cmd.getVolumeId(); + Long snapshotId = cmd.getSnapshotId(); + if ((volumeId == null) && (snapshotId == null)) { + throw new InvalidParameterValueException( + "Failed to create private template record, neither volume ID nor snapshot ID were specified."); + } + if ((volumeId != null) && (snapshotId != null)) { + throw new InvalidParameterValueException( + "Failed to create private template record, please specify only one of volume ID (" + + volumeId + + ") and snapshot ID (" + + snapshotId + + ")"); + } + + HypervisorType hyperType; + VolumeVO volume = null; + VMTemplateVO privateTemplate = null; + if (volumeId != null) { // create template from volume + volume = this._volumeDao.findById(volumeId); + if (volume == null) { + throw new InvalidParameterValueException( + "Failed to create private template record, unable to find volume " + + volumeId); + } + // check permissions + _accountMgr.checkAccess(caller, null, true, volume); + + // If private template is created from Volume, check that the volume + // will not be active when the private template is + // created + if (!this.volumeMgr.volumeInactive(volume)) { + String msg = "Unable to create private template for volume: " + + volume.getName() + + "; volume is attached to a non-stopped VM, please stop the VM first"; + if (s_logger.isInfoEnabled()) { + s_logger.info(msg); + } + throw new CloudRuntimeException(msg); + } + hyperType = this._volumeDao.getHypervisorType(volumeId); + } else { // create template from snapshot + SnapshotVO snapshot = _snapshotDao.findById(snapshotId); + if (snapshot == null) { + throw new InvalidParameterValueException( + "Failed to create private template record, unable to find snapshot " + + snapshotId); + } + + volume = this._volumeDao.findById(snapshot.getVolumeId()); + VolumeVO snapshotVolume = this._volumeDao + .findByIdIncludingRemoved(snapshot.getVolumeId()); + + // check permissions + _accountMgr.checkAccess(caller, null, true, snapshot); + + if (snapshot.getState() != Snapshot.State.BackedUp) { + throw new InvalidParameterValueException("Snapshot id=" + + snapshotId + " is not in " + Snapshot.State.BackedUp + + " state yet and can't be used for template creation"); + } + + /* + * // bug #11428. Operation not supported if vmware and snapshots + * parent volume = ROOT if(snapshot.getHypervisorType() == + * HypervisorType.VMware && snapshotVolume.getVolumeType() == + * Type.DATADISK){ throw new UnsupportedServiceException( + * "operation not supported, snapshot with id " + snapshotId + + * " is created from Data Disk"); } + */ + + hyperType = snapshot.getHypervisorType(); + } + + _resourceLimitMgr.checkResourceLimit(templateOwner, + ResourceType.template); + + if (!isAdmin || featured == null) { + featured = Boolean.FALSE; + } + Long guestOSId = cmd.getOsTypeId(); + GuestOSVO guestOS = this._guestOSDao.findById(guestOSId); + if (guestOS == null) { + throw new InvalidParameterValueException("GuestOS with ID: " + + guestOSId + " does not exist."); + } + + String uniqueName = Long.valueOf((userId == null) ? 1 : userId) + .toString() + + UUID.nameUUIDFromBytes(name.getBytes()).toString(); + Long nextTemplateId = this._tmpltDao.getNextInSequence(Long.class, "id"); + String description = cmd.getDisplayText(); + boolean isExtractable = false; + Long sourceTemplateId = null; + if (volume != null) { + VMTemplateVO template = ApiDBUtils.findTemplateById(volume + .getTemplateId()); + isExtractable = template != null + && template.isExtractable() + && template.getTemplateType() != Storage.TemplateType.SYSTEM; + if (template != null) { + sourceTemplateId = template.getId(); + } else if (volume.getVolumeType() == Volume.Type.ROOT) { // vm created out + // of blank + // template + UserVm userVm = ApiDBUtils.findUserVmById(volume + .getInstanceId()); + sourceTemplateId = userVm.getIsoId(); + } + } + String templateTag = cmd.getTemplateTag(); + if (templateTag != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Adding template tag: " + templateTag); + } + } + privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, + ImageFormat.RAW, isPublic, featured, isExtractable, + TemplateType.USER, null, null, requiresHvmValue, bitsValue, + templateOwner.getId(), null, description, passwordEnabledValue, + guestOS.getId(), true, hyperType, templateTag, cmd.getDetails()); + if (sourceTemplateId != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("This template is getting created from other template, setting source template Id to: " + + sourceTemplateId); + } + } + privateTemplate.setSourceTemplateId(sourceTemplateId); + + VMTemplateVO template = this._tmpltDao.persist(privateTemplate); + // Increment the number of templates + if (template != null) { + if (cmd.getDetails() != null) { + this._templateDetailsDao.persist(template.getId(), cmd.getDetails()); + } + + _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), + ResourceType.template); + } + + if (template != null) { + return template; + } else { + throw new CloudRuntimeException("Failed to create a template"); + } + + } + + @Override + public Pair<String, String> getAbsoluteIsoPath(long templateId, + long dataCenterId) { + String isoPath = null; + + List<HostVO> storageHosts = _resourceMgr.listAllHostsInOneZoneByType( + Host.Type.SecondaryStorage, dataCenterId); + if (storageHosts != null) { + for (HostVO storageHost : storageHosts) { + List<VMTemplateHostVO> templateHostVOs = this._tmpltHostDao + .listByTemplateHostStatus( + templateId, + storageHost.getId(), + VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + if (templateHostVOs != null && !templateHostVOs.isEmpty()) { + VMTemplateHostVO tmpHostVO = templateHostVOs.get(0); + isoPath = storageHost.getStorageUrl() + "/" + + tmpHostVO.getInstallPath(); + return new Pair<String, String>(isoPath, + storageHost.getStorageUrl()); + } + } + } + s_logger.warn("Unable to find secondary storage in zone id=" + + dataCenterId); + return null; + } + + @Override + public String getSecondaryStorageURL(long zoneId) { + // Determine the secondary storage URL + HostVO secondaryStorageHost = getSecondaryStorageHost(zoneId); + + if (secondaryStorageHost == null) { + return null; + } + + return secondaryStorageHost.getStorageUrl(); + } + + @Override + public HostVO getSecondaryStorageHost(long zoneId, long tmpltId) { + List<HostVO> hosts = _ssvmMgr + .listSecondaryStorageHostsInOneZone(zoneId); + if (hosts == null || hosts.size() == 0) { + return null; + } + for (HostVO host : hosts) { + VMTemplateHostVO tmpltHost = this._tmpltHostDao.findByHostTemplate( + host.getId(), tmpltId); + if (tmpltHost != null + && !tmpltHost.getDestroyed() + && tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + return host; + } + } + return null; + } + + @Override + public VMTemplateHostVO getTemplateHostRef(long zoneId, long tmpltId, + boolean readyOnly) { + List<HostVO> hosts = _ssvmMgr + .listSecondaryStorageHostsInOneZone(zoneId); + if (hosts == null || hosts.size() == 0) { + return null; + } + VMTemplateHostVO inProgress = null; + VMTemplateHostVO other = null; + for (HostVO host : hosts) { + VMTemplateHostVO tmpltHost = this._tmpltHostDao.findByHostTemplate( + host.getId(), tmpltId); + if (tmpltHost != null && !tmpltHost.getDestroyed()) { + if (tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + return tmpltHost; + } else if (tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) { + inProgress = tmpltHost; + } else { + other = tmpltHost; + } + } + } + if (inProgress != null) { + return inProgress; + } + return other; + } + + @Override + public HostVO getSecondaryStorageHost(long zoneId) { + List<HostVO> hosts = _ssvmMgr + .listSecondaryStorageHostsInOneZone(zoneId); + if (hosts == null || hosts.size() == 0) { + hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId); + if (hosts.isEmpty()) { + return null; + } + } + + int size = hosts.size(); + Random rn = new Random(); + int index = rn.nextInt(size); + return hosts.get(index); + } + + @Override + public List<HostVO> getSecondaryStorageHosts(long zoneId) { + List<HostVO> hosts = _ssvmMgr + .listSecondaryStorageHostsInOneZone(zoneId); + if (hosts == null || hosts.size() == 0) { + hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId); + if (hosts.isEmpty()) { + return new ArrayList<HostVO>(); + } + } + return hosts; + } + + @Override + public Long getTemplateSize(long templateId, long zoneId) { + SearchCriteria<VMTemplateHostVO> sc = HostTemplateStatesSearch.create(); + sc.setParameters("id", templateId); + sc.setParameters( + "state", + com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + sc.setJoinParameters("host", "dcId", zoneId); + List<VMTemplateSwiftVO> tsvs = _tmpltSwiftDao + .listByTemplateId(templateId); + Long size = null; + if (tsvs != null && tsvs.size() > 0) { + size = tsvs.get(0).getSize(); + } + + if (size == null && _s3Mgr.isS3Enabled()) { + VMTemplateS3VO vmTemplateS3VO = _vmS3TemplateDao + .findOneByTemplateId(templateId); + if (vmTemplateS3VO != null) { + size = vmTemplateS3VO.getSize(); + } + } + + if (size == null) { + List<VMTemplateHostVO> sss = this.templateHostDao.search(sc, null); + if (sss == null || sss.size() == 0) { + throw new CloudRuntimeException("Template " + + templateId + + " has not been completely downloaded to zone " + + zoneId); + } + size = sss.get(0).getSize(); + } + return size; + } + }
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/00df9727/server/src/com/cloud/user/AccountManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index a3f9505..f9a61e8 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -104,6 +104,7 @@ import com.cloud.server.auth.UserAuthenticator; import com.cloud.storage.StorageManager; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; @@ -118,7 +119,6 @@ import com.cloud.user.dao.UserDao; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; - import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -226,6 +226,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M Site2SiteVpnManager _vpnMgr; @Inject private AutoScaleManager _autoscaleMgr; + @Inject VolumeManager volumeMgr; @Inject private List<UserAuthenticator> _userAuthenticators; @@ -576,7 +577,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M for (VolumeVO volume : volumes) { if (!volume.getState().equals(Volume.State.Destroy)) { try { - _storageMgr.deleteVolume(volume.getId(), caller); + this.volumeMgr.deleteVolume(volume.getId(), caller); } catch (Exception ex) { s_logger.warn("Failed to cleanup volumes as a part of account id=" + accountId + " cleanup due to Exception: ", ex); accountCleanupNeeded = true; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/00df9727/server/src/com/cloud/vm/UserVmManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index 3e4a2db..cc1fffd 100755 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -49,16 +49,7 @@ public interface UserVmManager extends VirtualMachineGuru<UserVmVO>, UserVmServi * @return VirtualMachine */ UserVmVO getVirtualMachine(long vmId); - - /** - * Attaches an ISO to the virtual CDROM device of the specified VM. Will eject any existing virtual CDROM if isoPath is null. - * @param vmId - * @param isoId - * @param attach whether to attach or detach the given iso - * @return - */ - boolean attachISOToVM(long vmId, long isoId, boolean attach); - + /** * Stops the virtual machine * @param userId the id of the user performing the action @@ -101,8 +92,6 @@ public interface UserVmManager extends VirtualMachineGuru<UserVmVO>, UserVmServi */ Pair<List<UserVmJoinVO>, Integer> searchForUserVMs(Criteria c, Account caller, Long domainId, boolean isRecursive, List<Long> permittedAccounts, boolean listAll, ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags); - String getChecksum(Long hostId, String templatePath); - Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMachine(long vmId, Long hostId, Map<VirtualMachineProfile.Param, Object> additionalParams) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; }
