// update template_zone_ref for cross-zone template for newly added zone
  @Override
  public void associateCrosszoneTemplatesToZone(long dcId) {
    VMTemplateZoneVO tmpltZone;

    List<VMTemplateVO> allTemplates = _templateDao.listAll();
    for (VMTemplateVO vt : allTemplates) {
      if (vt.isCrossZones()) {
        tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, vt.getId());
        if (tmpltZone == null) {
          VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, vt.getId(), new Date());
          _vmTemplateZoneDao.persist(vmTemplateZone);
        }
      }
    }
  }
  @Override
  @DB
  public boolean delete(TemplateProfile profile) {
    boolean success = true;

    VMTemplateVO template = profile.getTemplate();
    Long zoneId = profile.getZoneId();
    Long templateId = template.getId();

    String zoneName;
    List<HostVO> secondaryStorageHosts;
    if (!template.isCrossZones() && zoneId != null) {
      DataCenterVO zone = _dcDao.findById(zoneId);
      zoneName = zone.getName();
      secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId);
    } else {
      zoneName = "(all zones)";
      secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones();
    }

    s_logger.debug(
        "Attempting to mark template host refs for template: "
            + template.getName()
            + " as destroyed in zone: "
            + zoneName);

    // Make sure the template is downloaded to all the necessary secondary storage hosts
    for (HostVO secondaryStorageHost : secondaryStorageHosts) {
      long hostId = secondaryStorageHost.getId();
      List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId);
      for (VMTemplateHostVO templateHostVO : templateHostVOs) {
        if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) {
          String errorMsg = "Please specify a template that is not currently being downloaded.";
          s_logger.debug(
              "Template: "
                  + template.getName()
                  + " is currently being downloaded to secondary storage host: "
                  + secondaryStorageHost.getName()
                  + "; cant' delete it.");
          throw new CloudRuntimeException(errorMsg);
        }
      }
    }

    Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
    String eventType = "";

    if (template.getFormat().equals(ImageFormat.ISO)) {
      eventType = EventTypes.EVENT_ISO_DELETE;
    } else {
      eventType = EventTypes.EVENT_TEMPLATE_DELETE;
    }

    // Iterate through all necessary secondary storage hosts and mark the template on each host as
    // destroyed
    for (HostVO secondaryStorageHost : secondaryStorageHosts) {
      long hostId = secondaryStorageHost.getId();
      long sZoneId = secondaryStorageHost.getDataCenterId();
      List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId);
      for (VMTemplateHostVO templateHostVO : templateHostVOs) {
        VMTemplateHostVO lock = _tmpltHostDao.acquireInLockTable(templateHostVO.getId());
        try {
          if (lock == null) {
            s_logger.debug(
                "Failed to acquire lock when deleting templateHostVO with ID: "
                    + templateHostVO.getId());
            success = false;
            break;
          }
          UsageEventVO usageEvent =
              new UsageEventVO(eventType, account.getId(), sZoneId, templateId, null);
          _usageEventDao.persist(usageEvent);
          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));

            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());
          }
          VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(sZoneId, templateId);

          if (templateZone != null) {
            _tmpltZoneDao.remove(templateZone.getId());
          }
        } finally {
          if (lock != null) {
            _tmpltHostDao.releaseFromLockTable(lock.getId());
          }
        }
      }

      if (!success) {
        break;
      }
    }

    s_logger.debug(
        "Successfully marked template host refs for template: "
            + template.getName()
            + " as destroyed in zone: "
            + zoneName);

    // If there are no more non-destroyed template host entries for this template, delete it
    if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) {
      long accountId = template.getAccountId();

      VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId);

      try {
        if (lock == null) {
          s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
          success = false;
        } else if (_tmpltDao.remove(templateId)) {
          // Decrement the number of templates
          _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
        }

      } finally {
        if (lock != null) {
          _tmpltDao.releaseFromLockTable(lock.getId());
        }
      }

      s_logger.debug(
          "Removed template: "
              + template.getName()
              + " because all of its template host refs were marked as destroyed.");
    }

    return success;
  }
  @Override
  @DB
  public boolean delete(TemplateProfile profile) {
    VMTemplateVO template = profile.getTemplate();
    Long templateId = template.getId();
    boolean success = true;
    String zoneName;

    if (!template.isCrossZones() && profile.getZoneId() != null) {
      zoneName = profile.getZoneId().toString();
    } else {
      zoneName = "all zones";
    }

    s_logger.debug(
        "Attempting to mark template host refs for template: "
            + template.getName()
            + " as destroyed in zone: "
            + zoneName);
    Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
    String eventType = EventTypes.EVENT_TEMPLATE_DELETE;
    List<TemplateDataStoreVO> templateHostVOs = this._tmpltStoreDao.listByTemplate(templateId);

    for (TemplateDataStoreVO vo : templateHostVOs) {
      TemplateDataStoreVO lock = null;
      try {
        lock = _tmpltStoreDao.acquireInLockTable(vo.getId());
        if (lock == null) {
          s_logger.debug(
              "Failed to acquire lock when deleting templateDataStoreVO with ID: " + vo.getId());
          success = false;
          break;
        }

        vo.setDestroyed(true);
        _tmpltStoreDao.update(vo.getId(), vo);

      } finally {
        if (lock != null) {
          _tmpltStoreDao.releaseFromLockTable(lock.getId());
        }
      }
    }

    if (profile.getZoneId() != null) {
      UsageEventVO usageEvent =
          new UsageEventVO(eventType, account.getId(), profile.getZoneId(), templateId, null);
      _usageEventDao.persist(usageEvent);
    } else {
      List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
      for (DataCenterVO dc : dcs) {
        UsageEventVO usageEvent =
            new UsageEventVO(eventType, account.getId(), dc.getId(), templateId, null);
        _usageEventDao.persist(usageEvent);
      }
    }

    VMTemplateZoneVO templateZone =
        _tmpltZoneDao.findByZoneTemplate(profile.getZoneId(), templateId);

    if (templateZone != null) {
      _tmpltZoneDao.remove(templateZone.getId());
    }

    s_logger.debug(
        "Successfully marked template host refs for template: "
            + template.getName()
            + " as destroyed in zone: "
            + zoneName);

    // If there are no more non-destroyed template host entries for this template, delete it
    if (success && (_tmpltStoreDao.listByTemplate(templateId).size() == 0)) {
      long accountId = template.getAccountId();

      VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId);

      try {
        if (lock == null) {
          s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
          success = false;
        } else if (_tmpltDao.remove(templateId)) {
          // Decrement the number of templates and total secondary storage space used by the
          // account.
          _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
          _resourceLimitMgr.recalculateResourceCount(
              accountId, template.getDomainId(), ResourceType.secondary_storage.getOrdinal());
        }

      } finally {
        if (lock != null) {
          _tmpltDao.releaseFromLockTable(lock.getId());
        }
      }
      s_logger.debug(
          "Removed template: "
              + template.getName()
              + " because all of its template host refs were marked as destroyed.");
    }

    return success;
  }