diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java index a3adffc8b26..dccc902e912 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java @@ -54,8 +54,12 @@ public interface VMTemplateDao extends GenericDao, StateDao< public List listAllInZone(long dataCenterId); + public List listInZoneByState(long dataCenterId, VirtualMachineTemplate.State... states); + public List listAllActive(); + public List listByState(VirtualMachineTemplate.State... states); + public List listByHypervisorType(List hyperTypes); public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags); diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index 90196a8b3d5..02fb4b466ed 100644 --- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -372,7 +372,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem tmpltZoneSearch.and("zoneId", tmpltZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); TmpltsInZoneSearch = createSearchBuilder(); - TmpltsInZoneSearch.and("state", TmpltsInZoneSearch.entity().getState(), SearchCriteria.Op.EQ); + TmpltsInZoneSearch.and("state", TmpltsInZoneSearch.entity().getState(), SearchCriteria.Op.IN); TmpltsInZoneSearch.and().op("avoidtype", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NEQ); TmpltsInZoneSearch.or("templateType", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NULL); TmpltsInZoneSearch.cp(); @@ -381,7 +381,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem TmpltsInZoneSearch.done(); ActiveTmpltSearch = createSearchBuilder(); - ActiveTmpltSearch.and("state", ActiveTmpltSearch.entity().getState(), SearchCriteria.Op.EQ); + ActiveTmpltSearch.and("state", ActiveTmpltSearch.entity().getState(), SearchCriteria.Op.IN); CountTemplatesByAccount = createSearchBuilder(Long.class); CountTemplatesByAccount.select(null, Func.COUNT, null); @@ -792,6 +792,15 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return listBy(sc); } + @Override + public List listInZoneByState(long dataCenterId, VirtualMachineTemplate.State... states) { + SearchCriteria sc = TmpltsInZoneSearch.create(); + sc.setParameters("avoidtype", TemplateType.PERHOST.toString()); + sc.setParameters("state", (Object[])states); + sc.setJoinParameters("tmpltzone", "zoneId", dataCenterId); + return listBy(sc); + } + @Override public List listAllActive() { SearchCriteria sc = ActiveTmpltSearch.create(); @@ -799,6 +808,13 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return listBy(sc); } + @Override + public List listByState(VirtualMachineTemplate.State... states) { + SearchCriteria sc = ActiveTmpltSearch.create(); + sc.setParameters("state", (Object[])states); + return listBy(sc); + } + @Override public List listDefaultBuiltinTemplates() { SearchCriteria sc = tmpltTypeSearch.create(); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java index f6dc33e7ee5..ccb70c4aba3 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -291,10 +291,10 @@ public class TemplateServiceImpl implements TemplateService { List allTemplates = null; if (zoneId == null) { // region wide store - allTemplates = _templateDao.listAllActive(); + allTemplates = _templateDao.listByState(VirtualMachineTemplate.State.Active, VirtualMachineTemplate.State.NotUploaded, VirtualMachineTemplate.State.UploadInProgress); } else { // zone wide store - allTemplates = _templateDao.listAllInZone(zoneId); + allTemplates = _templateDao.listInZoneByState(zoneId, VirtualMachineTemplate.State.Active, VirtualMachineTemplate.State.NotUploaded, VirtualMachineTemplate.State.UploadInProgress); } List rtngTmplts = _templateDao.listAllSystemVMTemplates(); List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); diff --git a/test/integration/component/test_browse_templates.py b/test/integration/component/test_browse_templates.py index 2cacdb6e678..9366914cfd9 100644 --- a/test/integration/component/test_browse_templates.py +++ b/test/integration/component/test_browse_templates.py @@ -1674,6 +1674,42 @@ class TestBrowseUploadVolume(cloudstackTestCase): return + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_browser_upload_template_incomplete(self): + """ + Test browser based incomplete template upload, followed by SSVM destroy. Template should go to UploadAbandoned state and get cleaned up. + """ + try: + self.debug("========================= Test browser based incomplete template upload ========================") + + #Only register template, without uploading + cmd = getUploadParamsForTemplate.getUploadParamsForTemplateCmd() + cmd.zoneid = self.zone.id + cmd.format = self.uploadtemplateformat + cmd.name=self.templatename+self.account.name+(random.choice(string.ascii_uppercase)) + cmd.account=self.account.name + cmd.domainid=self.domain.id + cmd.displaytext=cmd.name + cmd.hypervisor=self.templatehypervisor + cmd.ostypeid=self.templateostypeid + template_response=self.apiclient.getUploadParamsForTemplate(cmd) + + #Destroy SSVM, and wait for new one to start + self.destroy_ssvm() + + #Verify that the template is cleaned up as part of sync-up during new SSVM start + list_template_response=Template.list( + self.apiclient, + id=template_response.id, + templatefilter="all", + zoneid=self.zone.id) + self.assertEqual(list_template_response, None, "Template is not cleaned up, some issue with template sync-up") + + except Exception as e: + self.fail("Exceptione occurred : %s" % e) + return + + @classmethod def tearDownClass(self): try: