@Override
  public List<StoragePoolVO> findPoolsByTags(
      long dcId, long podId, Long clusterId, String[] tags, Boolean shared) {
    List<StoragePoolVO> storagePools = null;
    if (tags == null || tags.length == 0) {
      storagePools = listBy(dcId, podId, clusterId);
    } else {
      Map<String, String> details = tagsToDetails(tags);
      storagePools = findPoolsByDetails(dcId, podId, clusterId, details);
    }

    if (shared == null) {
      return storagePools;
    } else {
      List<StoragePoolVO> filteredStoragePools = new ArrayList<StoragePoolVO>(storagePools);
      for (StoragePoolVO pool : storagePools) {
        if (shared != pool.isShared()) {
          filteredStoragePools.remove(pool);
        }
      }

      return filteredStoragePools;
    }
  }
  @Override
  @DB
  public void recalculateCapacity() {
    // FIXME: the right way to do this is to register a listener (see RouterStatsListener,
    // VMSyncListener)
    //        for the vm sync state.  The listener model has connects/disconnects to keep things in
    // sync much better
    //        than this model right now, so when a VM is started, we update the amount allocated,
    // and when a VM
    //        is stopped we updated the amount allocated, and when VM sync reports a changed state,
    // we update
    //        the amount allocated.  Hopefully it's limited to 3 entry points and will keep the
    // amount allocated
    //        per host accurate.

    try {

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("recalculating system capacity");
        s_logger.debug("Executing cpu/ram capacity update");
      }

      // Calculate CPU and RAM capacities
      // 	get all hosts...even if they are not in 'UP' state
      List<HostVO> hosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing);
      for (HostVO host : hosts) {
        _capacityMgr.updateCapacityForHost(host);
      }

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Done executing cpu/ram capacity update");
        s_logger.debug("Executing storage capacity update");
      }
      // Calculate storage pool capacity
      List<StoragePoolVO> storagePools = _storagePoolDao.listAll();
      for (StoragePoolVO pool : storagePools) {
        long disk = 0l;
        Pair<Long, Long> sizes = _volumeDao.getCountAndTotalByPool(pool.getId());
        disk = sizes.second();
        if (pool.isShared()) {
          _storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, disk);
        } else {
          _storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, disk);
        }
      }

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Done executing storage capacity update");
        s_logger.debug("Executing capacity updates public ip and Vlans");
      }

      List<DataCenterVO> datacenters = _dcDao.listAll();
      for (DataCenterVO datacenter : datacenters) {
        long dcId = datacenter.getId();

        // NOTE
        // What happens if we have multiple vlans? Dashboard currently shows stats
        // with no filter based on a vlan
        // ideal way would be to remove out the vlan param, and filter only on dcId
        // implementing the same

        // Calculate new Public IP capacity for Virtual Network
        if (datacenter.getNetworkType() == NetworkType.Advanced) {
          createOrUpdateIpCapacity(dcId, null, CapacityVO.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP);
        }

        // Calculate new Public IP capacity for Direct Attached Network
        createOrUpdateIpCapacity(dcId, null, CapacityVO.CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP);

        if (datacenter.getNetworkType() == NetworkType.Advanced) {
          // Calculate VLAN's capacity
          createOrUpdateVlanCapacity(dcId);
        }
      }

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Done capacity updates for public ip and Vlans");
        s_logger.debug("Executing capacity updates for private ip");
      }

      // Calculate new Private IP capacity
      List<HostPodVO> pods = _podDao.listAll();
      for (HostPodVO pod : pods) {
        long podId = pod.getId();
        long dcId = pod.getDataCenterId();

        createOrUpdateIpCapacity(dcId, podId, CapacityVO.CAPACITY_TYPE_PRIVATE_IP);
      }

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Done executing capacity updates for private ip");
        s_logger.debug("Done recalculating system capacity");
      }

    } catch (Throwable t) {
      s_logger.error("Caught exception in recalculating capacity", t);
    }
  }