Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 411E71113F for ; Mon, 13 May 2013 17:58:00 +0000 (UTC) Received: (qmail 27487 invoked by uid 500); 13 May 2013 12:25:35 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 26659 invoked by uid 500); 13 May 2013 12:25:33 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 26468 invoked by uid 99); 13 May 2013 12:25:31 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 May 2013 12:25:31 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 494C188F437; Mon, 13 May 2013 12:25:31 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: nitin@apache.org To: commits@cloudstack.apache.org Date: Mon, 13 May 2013 12:25:31 -0000 Message-Id: <2570cc0d573e44ba8ecf113450d2c1a8@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [01/57] [abbrv] [partial] merge master Updated Branches: refs/heads/master 052c24c4d -> f84b6abde http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c11dbad9/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java new file mode 100755 index 0000000..25ae933 --- /dev/null +++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -0,0 +1,1136 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.storage.dao; + +import static com.cloud.utils.StringUtils.join; +import static com.cloud.utils.db.DbUtil.closeResources; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.projects.Project.ListProjectResourcesCriteria; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.storage.Storage; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.tags.ResourceTagVO; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.template.VirtualMachineTemplate.TemplateFilter; +import com.cloud.user.Account; +import com.cloud.utils.Pair; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.UpdateBuilder; +import com.cloud.utils.exception.CloudRuntimeException; + +@Component +@Local(value={VMTemplateDao.class}) +public class VMTemplateDaoImpl extends GenericDaoBase implements VMTemplateDao { + private static final Logger s_logger = Logger.getLogger(VMTemplateDaoImpl.class); + + @Inject + VMTemplateZoneDao _templateZoneDao; + @Inject + VMTemplateDetailsDao _templateDetailsDao; + + @Inject + ConfigurationDao _configDao; + @Inject + HostDao _hostDao; + @Inject + DomainDao _domainDao; + @Inject + DataCenterDao _dcDao; + private final String SELECT_TEMPLATE_HOST_REF = "SELECT t.id, h.data_center_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; + + private final String SELECT_TEMPLATE_ZONE_REF = "SELECT t.id, tzr.zone_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t INNER JOIN template_zone_ref tzr on (t.id = tzr.template_id) "; + + private final String SELECT_TEMPLATE_SWIFT_REF = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; + + private final String SELECT_TEMPLATE_S3_REF = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t"; + + private static final String SELECT_S3_CANDIDATE_TEMPLATES = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, " + + "t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, t.checksum, t.display_text, " + + "t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type " + + "FROM vm_template t JOIN template_host_ref r ON t.id=r.template_id JOIN host h ON h.id=r.host_id " + + "WHERE t.hypervisor_type IN (SELECT hypervisor_type FROM host) AND r.download_state = 'DOWNLOADED' AND " + + "r.template_id NOT IN (SELECT template_id FROM template_s3_ref) AND r.destroyed = 0 AND t.type <> 'PERHOST'"; + + protected SearchBuilder TemplateNameSearch; + protected SearchBuilder UniqueNameSearch; + protected SearchBuilder tmpltTypeSearch; + protected SearchBuilder tmpltTypeHyperSearch; + protected SearchBuilder tmpltTypeHyperSearch2; + + protected SearchBuilder AccountIdSearch; + protected SearchBuilder NameSearch; + protected SearchBuilder TmpltsInZoneSearch; + private SearchBuilder PublicSearch; + private SearchBuilder NameAccountIdSearch; + private SearchBuilder PublicIsoSearch; + private SearchBuilder UserIsoSearch; + private GenericSearchBuilder CountTemplatesByAccount; + private SearchBuilder updateStateSearch; + + @Inject ResourceTagDao _tagsDao; + + + private String routerTmpltName; + private String consoleProxyTmpltName; + + public VMTemplateDaoImpl() { + } + + @Override + public List listByPublic() { + SearchCriteria sc = PublicSearch.create(); + sc.setParameters("public", 1); + return listBy(sc); + } + + @Override + public VMTemplateVO findByName(String templateName) { + SearchCriteria sc = UniqueNameSearch.create(); + sc.setParameters("uniqueName", templateName); + return findOneIncludingRemovedBy(sc); + } + + @Override + public VMTemplateVO findByTemplateName(String templateName) { + SearchCriteria sc = NameSearch.create(); + sc.setParameters("name", templateName); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags){ + + SearchBuilder sb = null; + if (tags == null || tags.isEmpty()) { + sb = PublicIsoSearch; + } else { + sb = createSearchBuilder(); + sb.and("public", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.EQ); + sb.and("type", sb.entity().getTemplateType(), SearchCriteria.Op.EQ); + sb.and("bootable", sb.entity().isBootable(), SearchCriteria.Op.EQ); + sb.and("removed", sb.entity().getRemoved(), SearchCriteria.Op.EQ); + + SearchBuilder tagSearch = _tagsDao.createSearchBuilder(); + for (int count=0; count < tags.size(); count++) { + tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); + tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); + tagSearch.cp(); + } + tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); + sb.groupBy(sb.entity().getId()); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + } + + SearchCriteria sc = sb.create(); + + sc.setParameters("public", 1); + sc.setParameters("format", "ISO"); + sc.setParameters("type", TemplateType.PERHOST.toString()); + if (bootable != null) { + sc.setParameters("bootable", bootable); + } + + if (!listRemoved) { + sc.setParameters("removed", (Object)null); + } + + if (tags != null && !tags.isEmpty()) { + int count = 0; + sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.ISO.toString()); + for (String key : tags.keySet()) { + sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); + sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); + count++; + } + } + + return listBy(sc); + } + + @Override + public List userIsoSearch(boolean listRemoved){ + + SearchBuilder sb = null; + sb = UserIsoSearch; + SearchCriteria sc = sb.create(); + + sc.setParameters("format", Storage.ImageFormat.ISO); + sc.setParameters("type", TemplateType.USER.toString()); + + if (!listRemoved) { + sc.setParameters("removed", (Object)null); + } + + return listBy(sc); + } + @Override + public List listAllSystemVMTemplates() { + SearchCriteria sc = tmpltTypeSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + + Filter filter = new Filter(VMTemplateVO.class, "id", false, null, null); + return listBy(sc, filter); + } + + @Override + public List listPrivateTemplatesByHost(Long hostId) { + + String sql = "select * from template_host_ref as thr INNER JOIN vm_template as t ON t.id=thr.template_id " + + "where thr.host_id=? and t.public=0 and t.featured=0 and t.type='USER' and t.removed is NULL"; + + List l = new ArrayList(); + + Transaction txn = Transaction.currentTxn(); + + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, hostId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + l.add(rs.getLong(1)); + } + } catch (SQLException e) { + } catch (Throwable e) { + } + return l; + } + + @Override + public List listReadyTemplates() { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("ready", SearchCriteria.Op.EQ, true); + sc.addAnd("format", SearchCriteria.Op.NEQ, Storage.ImageFormat.ISO); + return listIncludingRemovedBy(sc); + } + + @Override + public List findIsosByIdAndPath(Long domainId, Long accountId, String path) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("iso", SearchCriteria.Op.EQ, true); + if (domainId != null) { + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); + } + if (accountId != null) { + sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); + } + if (path != null) { + sc.addAnd("path", SearchCriteria.Op.EQ, path); + } + return listIncludingRemovedBy(sc); + } + + @Override + public List listByAccountId(long accountId) { + SearchCriteria sc = AccountIdSearch.create(); + sc.setParameters("accountId", accountId); + return listBy(sc); + } + + @Override + public List listByHypervisorType(List hyperTypes) { + SearchCriteria sc = createSearchCriteria(); + hyperTypes.add(HypervisorType.None); + sc.addAnd("hypervisorType", SearchCriteria.Op.IN, hyperTypes.toArray()); + return listBy(sc); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + boolean result = super.configure(name, params); + + PublicSearch = createSearchBuilder(); + PublicSearch.and("public", PublicSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + + routerTmpltName = (String)params.get("routing.uniquename"); + + s_logger.debug("Found parameter routing unique name " + routerTmpltName); + if (routerTmpltName==null) { + routerTmpltName="routing"; + } + + consoleProxyTmpltName = (String)params.get("consoleproxy.uniquename"); + if(consoleProxyTmpltName == null) { + consoleProxyTmpltName = "routing"; + } + if(s_logger.isDebugEnabled()) { + s_logger.debug("Use console proxy template : " + consoleProxyTmpltName); + } + + UniqueNameSearch = createSearchBuilder(); + UniqueNameSearch.and("uniqueName", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ); + NameSearch = createSearchBuilder(); + NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ); + + NameAccountIdSearch = createSearchBuilder(); + NameAccountIdSearch.and("name", NameAccountIdSearch.entity().getName(), SearchCriteria.Op.EQ); + NameAccountIdSearch.and("accountId", NameAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + + PublicIsoSearch = createSearchBuilder(); + PublicIsoSearch.and("public", PublicIsoSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("format", PublicIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("type", PublicIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("bootable", PublicIsoSearch.entity().isBootable(), SearchCriteria.Op.EQ); + PublicIsoSearch.and("removed", PublicIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); + + UserIsoSearch = createSearchBuilder(); + UserIsoSearch.and("format", UserIsoSearch.entity().getFormat(), SearchCriteria.Op.EQ); + UserIsoSearch.and("type", UserIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + UserIsoSearch.and("removed", UserIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); + + tmpltTypeHyperSearch = createSearchBuilder(); + tmpltTypeHyperSearch.and("templateType", tmpltTypeHyperSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + SearchBuilder hostHyperSearch = _hostDao.createSearchBuilder(); + hostHyperSearch.and("type", hostHyperSearch.entity().getType(), SearchCriteria.Op.EQ); + hostHyperSearch.and("zoneId", hostHyperSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + hostHyperSearch.groupBy(hostHyperSearch.entity().getHypervisorType()); + + tmpltTypeHyperSearch.join("tmplHyper", hostHyperSearch, hostHyperSearch.entity().getHypervisorType(), tmpltTypeHyperSearch.entity().getHypervisorType(), JoinBuilder.JoinType.INNER); + hostHyperSearch.done(); + tmpltTypeHyperSearch.done(); + + tmpltTypeHyperSearch2 = createSearchBuilder(); + tmpltTypeHyperSearch2.and("templateType", tmpltTypeHyperSearch2.entity().getTemplateType(), SearchCriteria.Op.EQ); + tmpltTypeHyperSearch2.and("hypervisorType", tmpltTypeHyperSearch2.entity().getHypervisorType(), SearchCriteria.Op.EQ); + tmpltTypeHyperSearch2.and("templateName", tmpltTypeHyperSearch2.entity().getName(), SearchCriteria.Op.EQ); + + + tmpltTypeSearch = createSearchBuilder(); + tmpltTypeSearch.and("removed", tmpltTypeSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + tmpltTypeSearch.and("templateType", tmpltTypeSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + + AccountIdSearch = createSearchBuilder(); + AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountIdSearch.and("publicTemplate", AccountIdSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + AccountIdSearch.done(); + + SearchBuilder tmpltZoneSearch = _templateZoneDao.createSearchBuilder(); + tmpltZoneSearch.and("removed", tmpltZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + tmpltZoneSearch.and("zoneId", tmpltZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + + TmpltsInZoneSearch = createSearchBuilder(); + TmpltsInZoneSearch.and("removed", TmpltsInZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + TmpltsInZoneSearch.and().op("avoidtype", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NEQ); + TmpltsInZoneSearch.or("templateType", TmpltsInZoneSearch.entity().getTemplateType(), SearchCriteria.Op.NULL); + TmpltsInZoneSearch.cp(); + TmpltsInZoneSearch.join("tmpltzone", tmpltZoneSearch, tmpltZoneSearch.entity().getTemplateId(), TmpltsInZoneSearch.entity().getId(), JoinBuilder.JoinType.INNER); + tmpltZoneSearch.done(); + TmpltsInZoneSearch.done(); + + CountTemplatesByAccount = createSearchBuilder(Long.class); + CountTemplatesByAccount.select(null, Func.COUNT, null); + CountTemplatesByAccount.and("account", CountTemplatesByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); + CountTemplatesByAccount.and("removed", CountTemplatesByAccount.entity().getRemoved(), SearchCriteria.Op.NULL); + CountTemplatesByAccount.done(); + + updateStateSearch = this.createSearchBuilder(); + updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); + updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); + updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ); + updateStateSearch.done(); + + return result; + } + + @Override + public String getRoutingTemplateUniqueName() { + return routerTmpltName; + } + + @Override + public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, + Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, Map tags) { + + StringBuilder builder = new StringBuilder(); + if (!permittedAccounts.isEmpty()) { + for (Account permittedAccount : permittedAccounts) { + builder.append(permittedAccount.getAccountId() + ","); + } + } + + String permittedAccountsStr = builder.toString(); + + if (permittedAccountsStr.length() > 0) { + // chop the "," off + permittedAccountsStr = permittedAccountsStr.substring(0, permittedAccountsStr.length() - 1); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + Set> templateZonePairList = new HashSet>(); + PreparedStatement pstmt = null; + ResultSet rs = null; + String sql = SELECT_TEMPLATE_SWIFT_REF; + try { + String joinClause = ""; + String whereClause = " WHERE t.removed IS NULL"; + + if (isIso) { + whereClause += " AND t.format = 'ISO'"; + if (!hyperType.equals(HypervisorType.None)) { + joinClause = " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "; + whereClause += " AND goh.hypervisor_type = '" + hyperType.toString() + "'"; + } + } else { + whereClause += " AND t.format <> 'ISO'"; + if (hypers.isEmpty()) { + return templateZonePairList; + } else { + StringBuilder relatedHypers = new StringBuilder(); + for (HypervisorType hyper : hypers) { + relatedHypers.append("'"); + relatedHypers.append(hyper.toString()); + relatedHypers.append("'"); + relatedHypers.append(","); + } + relatedHypers.setLength(relatedHypers.length() - 1); + whereClause += " AND t.hypervisor_type IN (" + relatedHypers + ")"; + } + } + joinClause += " INNER JOIN template_swift_ref tsr on (t.id = tsr.template_id)"; + if (keyword != null) { + whereClause += " AND t.name LIKE \"%" + keyword + "%\""; + } else if (name != null) { + whereClause += " AND t.name LIKE \"%" + name + "%\""; + } + + if (bootable != null) { + whereClause += " AND t.bootable = " + bootable; + } + + if (!showDomr) { + whereClause += " AND t.type != '" + Storage.TemplateType.SYSTEM.toString() + "'"; + } + + if (templateFilter == TemplateFilter.featured) { + whereClause += " AND t.public = 1 AND t.featured = 1"; + } else if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + joinClause += " INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id)"; + whereClause += " AND d.path LIKE '" + domain.getPath() + "%'"; + } else { + whereClause += " AND t.account_id IN (" + permittedAccountsStr + ")"; + } + } else if ((templateFilter == TemplateFilter.shared || templateFilter == TemplateFilter.sharedexecutable) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + joinClause += " LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE" + " (t.account_id IN (" + permittedAccountsStr + ") OR" + " lp.account_id IN (" + + permittedAccountsStr + "))"; + } else { + joinClause += " INNER JOIN account a on (t.account_id = a.id) "; + } + } else if (templateFilter == TemplateFilter.executable && !permittedAccounts.isEmpty()) { + whereClause += " AND (t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; + } else if (templateFilter == TemplateFilter.community) { + whereClause += " AND t.public = 1 AND t.featured = 0"; + } else if (templateFilter == TemplateFilter.all && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { + } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + return templateZonePairList; + } + + sql += joinClause + whereClause + getOrderByLimit(pageSize, startIndex); + pstmt = txn.prepareStatement(sql); + rs = pstmt.executeQuery(); + while (rs.next()) { + Pair templateZonePair = new Pair(rs.getLong(1), -1L); + templateZonePairList.add(templateZonePair); + } + + } catch (Exception e) { + s_logger.warn("Error listing templates", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + txn.commit(); + } catch (SQLException sqle) { + s_logger.warn("Error in cleaning up", sqle); + } + } + + return templateZonePairList; + } + + + @Override + public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, + boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, + Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr,List permittedAccounts, + Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags, String zoneType) { + StringBuilder builder = new StringBuilder(); + if (!permittedAccounts.isEmpty()) { + for (Account permittedAccount : permittedAccounts) { + builder.append(permittedAccount.getAccountId() + ","); + } + } + + String permittedAccountsStr = builder.toString(); + + if (permittedAccountsStr.length() > 0) { + //chop the "," off + permittedAccountsStr = permittedAccountsStr.substring(0, permittedAccountsStr.length()-1); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + /* Use LinkedHashSet here to guarantee iteration order */ + Set> templateZonePairList = new LinkedHashSet>(); + PreparedStatement pstmt = null; + ResultSet rs = null; + StringBuilder relatedDomainIds = new StringBuilder(); + String sql = SELECT_TEMPLATE_ZONE_REF; + String groupByClause = ""; + try { + //short accountType; + //String accountId = null; + String guestOSJoin = ""; + StringBuilder templateHostRefJoin = new StringBuilder(); + String dataCenterJoin = "", lpjoin = ""; + String tagsJoin = ""; + + if (isIso && !hyperType.equals(HypervisorType.None)) { + guestOSJoin = " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "; + } + if (onlyReady){ + templateHostRefJoin.append(" INNER JOIN template_host_ref thr on (t.id = thr.template_id) INNER JOIN host h on (thr.host_id = h.id)"); + sql = SELECT_TEMPLATE_HOST_REF; + groupByClause = " GROUP BY t.id, h.data_center_id "; + } + if ((templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.community)) { + dataCenterJoin = " INNER JOIN data_center dc on (h.data_center_id = dc.id)"; + } + + if (zoneType != null) { + dataCenterJoin = " INNER JOIN template_host_ref thr on (t.id = thr.template_id) INNER JOIN host h on (thr.host_id = h.id)"; + dataCenterJoin += " INNER JOIN data_center dc on (h.data_center_id = dc.id)"; + } + + if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared ){ + lpjoin = " INNER JOIN launch_permission lp ON t.id = lp.template_id "; + } + + if (tags != null && !tags.isEmpty()) { + tagsJoin = " INNER JOIN resource_tags r ON t.id = r.resource_id "; + } + + sql += guestOSJoin + templateHostRefJoin + dataCenterJoin + lpjoin + tagsJoin; + String whereClause = ""; + + //All joins have to be made before we start setting the condition settings + if ((listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources + || (!permittedAccounts.isEmpty() && !(templateFilter == TemplateFilter.community || templateFilter == TemplateFilter.featured))) && + !(caller.getType() != Account.ACCOUNT_TYPE_NORMAL && templateFilter == TemplateFilter.all)) { + whereClause += " INNER JOIN account a on (t.account_id = a.id)"; + if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)) { + whereClause += " INNER JOIN domain d on (a.domain_id = d.id) WHERE d.path LIKE '" + domain.getPath() + "%'"; + if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { + whereClause += " AND a.type != " + Account.ACCOUNT_TYPE_PROJECT; + } + } else + if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { + whereClause += " WHERE a.type != " + Account.ACCOUNT_TYPE_PROJECT; + } + } + + if (!permittedAccounts.isEmpty()) { + for (Account account : permittedAccounts) { + //accountType = account.getType(); + //accountId = Long.toString(account.getId()); + DomainVO accountDomain = _domainDao.findById(account.getDomainId()); + + // get all parent domain ID's all the way till root domain + DomainVO domainTreeNode = accountDomain; + while (true) { + relatedDomainIds.append(domainTreeNode.getId()); + relatedDomainIds.append(","); + if (domainTreeNode.getParent() != null) { + domainTreeNode = _domainDao.findById(domainTreeNode.getParent()); + } else { + break; + } + } + + // get all child domain ID's + if (isAdmin(account.getType()) ) { + List allChildDomains = _domainDao.findAllChildren(accountDomain.getPath(), accountDomain.getId()); + for (DomainVO childDomain : allChildDomains) { + relatedDomainIds.append(childDomain.getId()); + relatedDomainIds.append(","); + } + } + relatedDomainIds.setLength(relatedDomainIds.length()-1); + } + } + + String attr = " AND "; + if (whereClause.endsWith(" WHERE ")) { + attr += " WHERE "; + } + + if (!isIso) { + if ( hypers.isEmpty() ) { + return templateZonePairList; + } else { + StringBuilder relatedHypers = new StringBuilder(); + for (HypervisorType hyper : hypers ) { + relatedHypers.append("'"); + relatedHypers.append(hyper.toString()); + relatedHypers.append("'"); + relatedHypers.append(","); + } + relatedHypers.setLength(relatedHypers.length()-1); + whereClause += attr + " t.hypervisor_type IN (" + relatedHypers + ")"; + } + } + + if (!permittedAccounts.isEmpty() && !(templateFilter == TemplateFilter.featured || + templateFilter == TemplateFilter.community || templateFilter == TemplateFilter.executable + || templateFilter == TemplateFilter.shared || templateFilter == TemplateFilter.sharedexecutable) && !isAdmin(caller.getType()) ) { + whereClause += attr + "t.account_id IN (" + permittedAccountsStr + ")"; + } + + if (templateFilter == TemplateFilter.featured) { + whereClause += attr + "t.public = 1 AND t.featured = 1"; + if (!permittedAccounts.isEmpty()) { + whereClause += attr + "(dc.domain_id IN (" + relatedDomainIds + ") OR dc.domain_id is NULL)"; + } + } else if (templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) { + whereClause += " AND t.account_id IN (" + permittedAccountsStr + ")"; + } else if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared ) { + whereClause += " AND " + + " (t.account_id IN (" + permittedAccountsStr + ") OR" + + " lp.account_id IN (" + permittedAccountsStr + "))"; + } else if (templateFilter == TemplateFilter.executable && !permittedAccounts.isEmpty()) { + whereClause += attr + "(t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; + } else if (templateFilter == TemplateFilter.community) { + whereClause += attr + "t.public = 1 AND t.featured = 0"; + if (!permittedAccounts.isEmpty()) { + whereClause += attr + "(dc.domain_id IN (" + relatedDomainIds + ") OR dc.domain_id is NULL)"; + } + } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && !isIso) { + return templateZonePairList; + } + + if (tags != null && !tags.isEmpty()) { + whereClause += " AND ("; + boolean first = true; + for (String key : tags.keySet()) { + if (!first) { + whereClause += " OR "; + } + whereClause += "(r.key=\"" + key + "\" and r.value=\"" + tags.get(key) + "\")"; + first = false; + } + whereClause += ")"; + } + + if (whereClause.equals("")) { + whereClause += " WHERE "; + } else if (!whereClause.equals(" WHERE ")) { + whereClause += " AND "; + } + + sql += whereClause + getExtrasWhere(templateFilter, name, keyword, isIso, bootable, hyperType, zoneId, + onlyReady, showDomr, zoneType) + groupByClause + getOrderByLimit(pageSize, startIndex); + + pstmt = txn.prepareStatement(sql); + rs = pstmt.executeQuery(); + + while (rs.next()) { + Pair templateZonePair = new Pair(rs.getLong(1), rs.getLong(2)); + templateZonePairList.add(templateZonePair); + } + //for now, defaulting pageSize to a large val if null; may need to revisit post 2.2RC2 + if(isIso && templateZonePairList.size() < (pageSize != null ? pageSize : 500) + && templateFilter != TemplateFilter.community + && !(templateFilter == TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType())) ){ //evaluates to true If root admin and filter=self + + List publicIsos = publicIsoSearch(bootable, false, tags); + List userIsos = userIsoSearch(false); + + //Listing the ISOs according to the page size.Restricting the total no. of ISOs on a page + //to be less than or equal to the pageSize parameter + + int i=0; + + if (startIndex > userIsos.size()) { + i=(int) (startIndex - userIsos.size()); + } + + for (; i < publicIsos.size(); i++) { + if(templateZonePairList.size() >= pageSize){ + break; + } else { + if (keyword != null && publicIsos.get(i).getName().contains(keyword)) { + templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); + continue; + } else if (name != null && publicIsos.get(i).getName().contains(name)) { + templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); + continue; + } else if (keyword == null && name == null){ + templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); + } + } + } + } + } catch (Exception e) { + s_logger.warn("Error listing templates", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + txn.commit(); + } catch( SQLException sqle) { + s_logger.warn("Error in cleaning up", sqle); + } + } + + return templateZonePairList; + } + + private String getExtrasWhere(TemplateFilter templateFilter, String name, String keyword, boolean isIso, Boolean bootable, HypervisorType hyperType, Long zoneId, boolean onlyReady, boolean showDomr, String zoneType) { + String sql = ""; + if (keyword != null) { + sql += " t.name LIKE \"%" + keyword + "%\" AND"; + } else if (name != null) { + sql += " t.name LIKE \"%" + name + "%\" AND"; + } + + if (isIso) { + sql += " t.format = 'ISO'"; + if (!hyperType.equals(HypervisorType.None)) { + sql += " AND goh.hypervisor_type = '" + hyperType.toString() + "'"; + } + } else { + sql += " t.format <> 'ISO'"; + if (!hyperType.equals(HypervisorType.None)) { + sql += " AND t.hypervisor_type = '" + hyperType.toString() + "'"; + } + } + + if (bootable != null) { + sql += " AND t.bootable = " + bootable; + } + + if (onlyReady){ + sql += " AND thr.download_state = '" +Status.DOWNLOADED.toString() + "'" + " AND thr.destroyed=0 "; + if (zoneId != null){ + sql += " AND h.data_center_id = " +zoneId; + } + }else if (zoneId != null){ + sql += " AND tzr.zone_id = " +zoneId+ " AND tzr.removed is null" ; + }else{ + sql += " AND tzr.removed is null "; + } + + if (zoneType != null){ + sql += " AND dc.networktype = '" + zoneType + "'"; + } + + if (!showDomr){ + sql += " AND t.type != '" +Storage.TemplateType.SYSTEM.toString() + "'"; + } + + sql += " AND t.removed IS NULL"; + + return sql; + } + + private String getOrderByLimit(Long pageSize, Long startIndex) { + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + + String sql; + if (isAscending) { + sql = " ORDER BY t.sort_key ASC"; + } else { + sql = " ORDER BY t.sort_key DESC"; + } + + if ((pageSize != null) && (startIndex != null)) { + sql += " LIMIT " + startIndex.toString() + "," + pageSize.toString(); + } + return sql; + } + + @Override + @DB + public long addTemplateToZone(VMTemplateVO tmplt, long zoneId) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + VMTemplateVO tmplt2 = findById(tmplt.getId()); + if (tmplt2 == null){ + if (persist(tmplt) == null) { + throw new CloudRuntimeException("Failed to persist the template " + tmplt); + } + if(tmplt.getDetails() != null) { + _templateDetailsDao.persist(tmplt.getId(), tmplt.getDetails()); + } + } + VMTemplateZoneVO tmpltZoneVO = _templateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); + if (tmpltZoneVO == null ) { + tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date()); + _templateZoneDao.persist(tmpltZoneVO); + } else { + tmpltZoneVO.setRemoved(null); + tmpltZoneVO.setLastUpdated(new Date()); + _templateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); + } + txn.commit(); + + return tmplt.getId(); + } + + @Override + @DB + public List listAllInZone(long dataCenterId) { + SearchCriteria sc = TmpltsInZoneSearch.create(); + sc.setParameters("avoidtype", TemplateType.PERHOST.toString()); + sc.setJoinParameters("tmpltzone", "zoneId", dataCenterId); + return listBy(sc); + } + + @Override + public List listDefaultBuiltinTemplates() { + SearchCriteria sc = tmpltTypeSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.BUILTIN); + return listBy(sc); + } + + @Override + public VMTemplateVO findSystemVMTemplate(long zoneId) { + SearchCriteria sc = tmpltTypeHyperSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); + sc.setJoinParameters("tmplHyper", "zoneId", zoneId); + + //order by descending order of id and select the first (this is going to be the latest) + List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1l)); + + if (tmplts.size() > 0) { + return tmplts.get(0); + } else { + return null; + } + } + + public VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType) { + SearchCriteria sc = tmpltTypeHyperSearch.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); + sc.setJoinParameters("tmplHyper", "zoneId", zoneId); + + //order by descending order of id + List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null)); + + for (VMTemplateVO tmplt: tmplts) { + if (tmplt.getHypervisorType() == hType) { + return tmplt; + } + } + if (tmplts.size() > 0 && hType == HypervisorType.Any) { + return tmplts.get(0); + } + return null; + } + + @Override + public VMTemplateVO findRoutingTemplate(HypervisorType hType, String templateName) { + SearchCriteria sc = tmpltTypeHyperSearch2.create(); + sc.setParameters("templateType", Storage.TemplateType.SYSTEM); + sc.setParameters("hypervisorType", hType); + if (templateName != null) { + sc.setParameters("templateName", templateName); + } + + //order by descending order of id and select the first (this is going to be the latest) + List tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1l)); + + if (tmplts.size() > 0) { + return tmplts.get(0); + } else { + return null; + } + } + + @Override + public Long countTemplatesForAccount(long accountId) { + SearchCriteria sc = CountTemplatesByAccount.create(); + sc.setParameters("account", accountId); + return customSearch(sc, null).get(0); + } + + @Override + @DB + public boolean remove(Long id) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + VMTemplateVO template = createForUpdate(); + template.setRemoved(new Date()); + + VMTemplateVO vo = findById(id); + if (vo != null) { + if (vo.getFormat() == ImageFormat.ISO) { + _tagsDao.removeByIdAndType(id, TaggedResourceType.ISO); + } else { + _tagsDao.removeByIdAndType(id, TaggedResourceType.Template); + } + } + + boolean result = update(id, template); + txn.commit(); + return result; + } + + private 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 + public List findTemplatesToSyncToS3() { + return executeList(SELECT_S3_CANDIDATE_TEMPLATES, new Object[] {}); + } + + @Override + public Set> searchS3Templates(final String name, + final String keyword, final TemplateFilter templateFilter, + final boolean isIso, final List hypers, + final Boolean bootable, final DomainVO domain, final Long pageSize, + final Long startIndex, final Long zoneId, + final HypervisorType hyperType, final boolean onlyReady, + final boolean showDomr, final List permittedAccounts, + final Account caller, final Map tags) { + + final String permittedAccountsStr = join(",", permittedAccounts); + + final Transaction txn = Transaction.currentTxn(); + txn.start(); + + Set> templateZonePairList = new HashSet>(); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + + final StringBuilder joinClause = new StringBuilder(); + final StringBuilder whereClause = new StringBuilder(" WHERE t.removed IS NULL"); + + if (isIso) { + whereClause.append(" AND t.format = 'ISO'"); + if (!hyperType.equals(HypervisorType.None)) { + joinClause.append(" INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "); + whereClause.append(" AND goh.hypervisor_type = '"); + whereClause.append(hyperType); + whereClause.append("'"); + } + } else { + whereClause.append(" AND t.format <> 'ISO'"); + if (hypers.isEmpty()) { + return templateZonePairList; + } else { + final StringBuilder relatedHypers = new StringBuilder(); + for (HypervisorType hyper : hypers) { + relatedHypers.append("'"); + relatedHypers.append(hyper.toString()); + relatedHypers.append("'"); + relatedHypers.append(","); + } + relatedHypers.setLength(relatedHypers.length() - 1); + whereClause.append(" AND t.hypervisor_type IN ("); + whereClause.append(relatedHypers); + whereClause.append(")"); + } + } + + joinClause.append(" INNER JOIN template_s3_ref tsr on (t.id = tsr.template_id)"); + + whereClause.append("AND t.name LIKE \"%"); + whereClause.append(keyword == null ? keyword : name); + whereClause.append("%\""); + + if (bootable != null) { + whereClause.append(" AND t.bootable = "); + whereClause.append(bootable); + } + + if (!showDomr) { + whereClause.append(" AND t.type != '"); + whereClause.append(Storage.TemplateType.SYSTEM); + whereClause.append("'"); + } + + if (templateFilter == TemplateFilter.featured) { + whereClause.append(" AND t.public = 1 AND t.featured = 1"); + } else if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) + && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN + || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + joinClause.append(" INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id)"); + whereClause.append(" AND d.path LIKE '"); + whereClause.append(domain.getPath()); + whereClause.append("%'"); + } else { + whereClause.append(" AND t.account_id IN ("); + whereClause.append(permittedAccountsStr); + whereClause.append(")"); + } + } else if (templateFilter == TemplateFilter.sharedexecutable + && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + joinClause.append(" LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE (t.account_id IN ("); + joinClause.append(permittedAccountsStr); + joinClause.append(") OR lp.account_id IN ("); + joinClause.append(permittedAccountsStr); + joinClause.append("))"); + } else { + joinClause.append(" INNER JOIN account a on (t.account_id = a.id) "); + } + } else if (templateFilter == TemplateFilter.executable + && !permittedAccounts.isEmpty()) { + whereClause.append(" AND (t.public = 1 OR t.account_id IN ("); + whereClause.append(permittedAccountsStr); + whereClause.append("))"); + } else if (templateFilter == TemplateFilter.community) { + whereClause.append(" AND t.public = 1 AND t.featured = 0"); + } else if (templateFilter == TemplateFilter.all + && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { + } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + return templateZonePairList; + } + + final StringBuilder sql = new StringBuilder(SELECT_TEMPLATE_S3_REF); + sql.append(joinClause); + sql.append(whereClause); + sql.append(getOrderByLimit(pageSize, startIndex)); + + pstmt = txn.prepareStatement(sql.toString()); + rs = pstmt.executeQuery(); + while (rs.next()) { + final Pair templateZonePair = new Pair( + rs.getLong(1), -1L); + templateZonePairList.add(templateZonePair); + } + txn.commit(); + } catch (Exception e) { + s_logger.warn("Error listing S3 templates", e); + if (txn != null) { + txn.rollback(); + } + } finally { + closeResources(pstmt, rs); + if (txn != null) { + txn.close(); + } + } + + return templateZonePairList; + } + + @Override + public boolean updateState(TemplateState currentState, TemplateEvent event, + TemplateState nextState, VMTemplateVO vo, Object data) { + Long oldUpdated = vo.getUpdatedCount(); + Date oldUpdatedTime = vo.getUpdated(); + + + SearchCriteria sc = updateStateSearch.create(); + sc.setParameters("id", vo.getId()); + sc.setParameters("state", currentState); + sc.setParameters("updatedCount", vo.getUpdatedCount()); + + vo.incrUpdatedCount(); + + UpdateBuilder builder = getUpdateBuilder(vo); + builder.set(vo, "state", nextState); + builder.set(vo, "updated", new Date()); + + int rows = update((VMTemplateVO) vo, sc); + if (rows == 0 && s_logger.isDebugEnabled()) { + VMTemplateVO dbVol = findByIdIncludingRemoved(vo.getId()); + if (dbVol != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={id=").append(dbVol.getId()).append("; state=").append(dbVol.getState()).append("; updatecount=").append(dbVol.getUpdatedCount()).append(";updatedTime=") + .append(dbVol.getUpdated()); + str.append(": New Data={id=").append(vo.getId()).append("; state=").append(nextState).append("; event=").append(event).append("; updatecount=").append(vo.getUpdatedCount()) + .append("; updatedTime=").append(vo.getUpdated()); + str.append(": stale Data={id=").append(vo.getId()).append("; state=").append(currentState).append("; event=").append(event).append("; updatecount=").append(oldUpdated) + .append("; updatedTime=").append(oldUpdatedTime); + } else { + s_logger.debug("Unable to update objectIndatastore: id=" + vo.getId() + ", as there is no such object exists in the database anymore"); + } + } + return rows > 0; + } +}