diff --git a/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java index 4d19bfc0074..7f35eabfaa7 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java @@ -258,7 +258,6 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId()); + //check if there is any Vm using this ISO. + if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { + DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssHost.getStorageUrl(), tInfo.getInstallPath()); + try { + _agentMgr.sendToSecStorage(ssHost, dtCommand, null); + } catch (AgentUnavailableException e) { + String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database"; + s_logger.error(err); + return; + } - String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database"; - s_logger.info(description); + String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database"; + s_logger.info(description); + } } } diff --git a/server/src/com/cloud/template/HyervisorTemplateAdapter.java b/server/src/com/cloud/template/HyervisorTemplateAdapter.java index c1177f4a060..ad41af51506 100755 --- a/server/src/com/cloud/template/HyervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HyervisorTemplateAdapter.java @@ -63,6 +63,8 @@ import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.Account; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.UserVmVO; + import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; @@ -86,7 +88,6 @@ public class HyervisorTemplateAdapter extends TemplateAdapterBase implements Tem @Inject ImageDataFactory imageFactory; @Inject TemplateManager templateMgr; - @Override public String getName() { return TemplateAdapterType.Hypervisor.getName(); @@ -248,17 +249,21 @@ public class HyervisorTemplateAdapter extends TemplateAdapterBase implements Tem templateHostVO.setDestroyed(true); _tmpltHostDao.update(templateHostVO.getId(), templateHostVO); String installPath = templateHostVO.getInstallPath(); - if (installPath != null) { - Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(), installPath)); + List userVmUsingIso = _userVmDao.listByIsoId(templateId); + //check if there is any VM using this ISO. + if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { + if (installPath != null) { + Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(), installPath)); - if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); + if (answer == null || !answer.getResult()) { + s_logger.debug("Failed to delete " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); + } else { + _tmpltHostDao.remove(templateHostVO.getId()); + s_logger.debug("Deleted template at: " + installPath); + } } else { _tmpltHostDao.remove(templateHostVO.getId()); - s_logger.debug("Deleted template at: " + installPath); } - } else { - _tmpltHostDao.remove(templateHostVO.getId()); } VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(sZoneId, templateId); diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index 247ce636cf2..1b114250621 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -63,6 +63,7 @@ import com.cloud.utils.EnumUtils; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.UserVmDao; public abstract class TemplateAdapterBase extends AdapterBase implements TemplateAdapter { private final static Logger s_logger = Logger.getLogger(TemplateAdapterBase.class); @@ -77,6 +78,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat protected @Inject VMTemplateZoneDao _tmpltZoneDao; protected @Inject UsageEventDao _usageEventDao; protected @Inject HostDao _hostDao; + protected @Inject UserVmDao _userVmDao; protected @Inject ResourceLimitService _resourceLimitMgr; protected @Inject DataStoreManager storeMgr; @Inject TemplateManager templateMgr; diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 101c3d9c714..29659d3deee 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -1227,32 +1227,37 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } @Override - public boolean templateIsDeleteable(VMTemplateHostVO templateHostRef) { - VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templateHostRef.getTemplateId()); - long templateId = template.getId(); - HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId()); - long zoneId = secondaryStorageHost.getDataCenterId(); - DataCenterVO zone = _dcDao.findById(zoneId); - - // Check if there are VMs running in the template host ref's zone that use the template - List nonExpungedVms = _vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateId); - - if (!nonExpungedVms.isEmpty()) { - s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are non-expunged VMs deployed from this template."); - return false; - } - - // Check if there are any snapshots for the template in the template host ref's zone - List volumes = _volumeDao.findByTemplateAndZone(templateId, zoneId); - for (VolumeVO volume : volumes) { - List snapshots = _snapshotDao.listByVolumeIdVersion(volume.getId(), "2.1"); - if (!snapshots.isEmpty()) { - s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are 2.1 snapshots using this template."); - return false; - } - } - - return true; + public boolean templateIsDeleteable(VMTemplateHostVO templateHostRef) { + VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templateHostRef.getTemplateId()); + long templateId = template.getId(); + HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId()); + long zoneId = secondaryStorageHost.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + + // Check if there are VMs running in the template host ref's zone that use the template + List nonExpungedVms = _vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateId); + + if (!nonExpungedVms.isEmpty()) { + s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are non-expunged VMs deployed from this template."); + return false; + } + List userVmUsingIso = _userVmDao.listByIsoId(templateId); + //check if there is any VM using this ISO. + if (!userVmUsingIso.isEmpty()) { + s_logger.debug("ISO " + template.getName() + " in zone " + zone.getName() + " is not deleteable because it is attached to " + userVmUsingIso.size() + " VMs"); + return false; + } + // Check if there are any snapshots for the template in the template host ref's zone + List volumes = _volumeDao.findByTemplateAndZone(templateId, zoneId); + for (VolumeVO volume : volumes) { + List snapshots = _snapshotDao.listByVolumeIdVersion(volume.getId(), "2.1"); + if (!snapshots.isEmpty()) { + s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are 2.1 snapshots using this template."); + return false; + } + } + + return true; } @Override diff --git a/server/src/com/cloud/vm/dao/UserVmDao.java b/server/src/com/cloud/vm/dao/UserVmDao.java index 9fbcde377dd..81d13cda2ed 100755 --- a/server/src/com/cloud/vm/dao/UserVmDao.java +++ b/server/src/com/cloud/vm/dao/UserVmDao.java @@ -70,5 +70,7 @@ public interface UserVmDao extends GenericDao { public Long countAllocatedVMsForAccount(long accountId); Hashtable listVmDetails(Hashtable userVmData); + + List listByIsoId(Long isoId); } diff --git a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java index f2fc10bbaa4..02604fe767b 100755 --- a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java +++ b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java @@ -72,10 +72,11 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use protected SearchBuilder DestroySearch; protected SearchBuilder AccountDataCenterVirtualSearch; protected GenericSearchBuilder CountByAccountPod; - protected GenericSearchBuilder CountByAccount; - protected GenericSearchBuilder PodsHavingVmsForAccount; - - protected SearchBuilder UserVmSearch; + protected GenericSearchBuilder CountByAccount; + protected GenericSearchBuilder PodsHavingVmsForAccount; + + protected SearchBuilder UserVmSearch; + protected SearchBuilder UserVmByIsoSearch; protected Attribute _updateTimeAttr; // ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class); @Inject ResourceTagsDaoImpl _tagsDao; @@ -194,7 +195,10 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use AccountDataCenterVirtualSearch.and("dc", AccountDataCenterVirtualSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); AccountDataCenterVirtualSearch.join("nicSearch", nicSearch, AccountDataCenterVirtualSearch.entity().getId(), nicSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER); AccountDataCenterVirtualSearch.done(); - + + UserVmByIsoSearch = createSearchBuilder(); + UserVmByIsoSearch.and("isoId", UserVmByIsoSearch.entity().getIsoId(), SearchCriteria.Op.EQ); + UserVmByIsoSearch.done(); _updateTimeAttr = _allAttributes.get("updateTime"); assert _updateTimeAttr != null : "Couldn't get this updateTime attribute"; @@ -248,13 +252,20 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use public List listByHostId(Long id) { SearchCriteria sc = HostSearch.create(); sc.setParameters("host", id); - - return listBy(sc); - } - - @Override - public List listUpByHostId(Long hostId) { - SearchCriteria sc = HostUpSearch.create(); + + return listBy(sc); + } + + @Override + public List listByIsoId(Long isoId) { + SearchCriteria sc = UserVmByIsoSearch.create(); + sc.setParameters("isoId", isoId); + return listBy(sc); + } + + @Override + public List listUpByHostId(Long hostId) { + SearchCriteria sc = HostUpSearch.create(); sc.setParameters("host", hostId); sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging}); return listBy(sc);