@DB
  @Override
  public void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost) {

    long hostId = vm.getHostId();
    HostVO host = _hostDao.findById(hostId);
    long clusterId = host.getClusterId();
    float cpuOvercommitRatio =
        Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue());
    float memoryOvercommitRatio =
        Float.parseFloat(
            _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue());

    ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId());

    CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU);
    CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY);

    if (capacityCpu == null || capacityMem == null || svo == null) {
      return;
    }

    int cpu = (int) (svo.getCpu() * svo.getSpeed());
    long ram = (long) (svo.getRamSize() * 1024L * 1024L);

    Transaction txn = Transaction.currentTxn();

    try {
      txn.start();
      capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true);
      capacityMem = _capacityDao.lockRow(capacityMem.getId(), true);

      long usedCpu = capacityCpu.getUsedCapacity();
      long usedMem = capacityMem.getUsedCapacity();
      long reservedCpu = capacityCpu.getReservedCapacity();
      long reservedMem = capacityMem.getReservedCapacity();
      long actualTotalCpu = capacityCpu.getTotalCapacity();
      long actualTotalMem = capacityMem.getTotalCapacity();
      long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio);
      long totalMem = (long) (actualTotalMem * memoryOvercommitRatio);
      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "Hosts's actual total CPU: "
                + actualTotalCpu
                + " and CPU after applying overprovisioning: "
                + totalCpu);
      }

      long freeCpu = totalCpu - (reservedCpu + usedCpu);
      long freeMem = totalMem - (reservedMem + usedMem);

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("We are allocating VM, increasing the used capacity of this host:" + hostId);
        s_logger.debug(
            "Current Used CPU: " + usedCpu + " , Free CPU:" + freeCpu + " ,Requested CPU: " + cpu);
        s_logger.debug(
            "Current Used RAM: " + usedMem + " , Free RAM:" + freeMem + " ,Requested RAM: " + ram);
      }
      capacityCpu.setUsedCapacity(usedCpu + cpu);
      capacityMem.setUsedCapacity(usedMem + ram);

      if (fromLastHost) {
        /* alloc from reserved */
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(
              "We are allocating VM to the last host again, so adjusting the reserved capacity if it is not less than required");
          s_logger.debug("Reserved CPU: " + reservedCpu + " , Requested CPU: " + cpu);
          s_logger.debug("Reserved RAM: " + reservedMem + " , Requested RAM: " + ram);
        }
        if (reservedCpu >= cpu && reservedMem >= ram) {
          capacityCpu.setReservedCapacity(reservedCpu - cpu);
          capacityMem.setReservedCapacity(reservedMem - ram);
        }
      } else {
        /* alloc from free resource */
        if (!((reservedCpu + usedCpu + cpu <= totalCpu)
            && (reservedMem + usedMem + ram <= totalMem))) {
          if (s_logger.isDebugEnabled()) {
            s_logger.debug(
                "Host doesnt seem to have enough free capacity, but increasing the used capacity anyways, since the VM is already starting on this host ");
          }
        }
      }

      s_logger.debug(
          "CPU STATS after allocation: for host: "
              + hostId
              + ", old used: "
              + usedCpu
              + ", old reserved: "
              + reservedCpu
              + ", actual total: "
              + actualTotalCpu
              + ", total with overprovisioning: "
              + totalCpu
              + "; new used:"
              + capacityCpu.getUsedCapacity()
              + ", reserved:"
              + capacityCpu.getReservedCapacity()
              + "; requested cpu:"
              + cpu
              + ",alloc_from_last:"
              + fromLastHost);

      s_logger.debug(
          "RAM STATS after allocation: for host: "
              + hostId
              + ", old used: "
              + usedMem
              + ", old reserved: "
              + reservedMem
              + ", total: "
              + totalMem
              + "; new used: "
              + capacityMem.getUsedCapacity()
              + ", reserved: "
              + capacityMem.getReservedCapacity()
              + "; requested mem: "
              + ram
              + ",alloc_from_last:"
              + fromLastHost);

      _capacityDao.update(capacityCpu.getId(), capacityCpu);
      _capacityDao.update(capacityMem.getId(), capacityMem);
      txn.commit();
    } catch (Exception e) {
      txn.rollback();
      return;
    }
  }
  @DB
  @Override
  public boolean releaseVmCapacity(
      VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId) {
    ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId());
    CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU);
    CapacityVO capacityMemory =
        _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY);
    Long clusterId = null;
    if (hostId != null) {
      HostVO host = _hostDao.findById(hostId);
      clusterId = host.getClusterId();
    }
    if (capacityCpu == null || capacityMemory == null || svo == null) {
      return false;
    }

    Transaction txn = Transaction.currentTxn();
    try {
      txn.start();

      capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true);
      capacityMemory = _capacityDao.lockRow(capacityMemory.getId(), true);

      long usedCpu = capacityCpu.getUsedCapacity();
      long usedMem = capacityMemory.getUsedCapacity();
      long reservedCpu = capacityCpu.getReservedCapacity();
      long reservedMem = capacityMemory.getReservedCapacity();
      long actualTotalCpu = capacityCpu.getTotalCapacity();
      float cpuOvercommitRatio =
          Float.parseFloat(
              _clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue());
      float memoryOvercommitRatio =
          Float.parseFloat(
              _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue());
      int vmCPU = (int) (svo.getCpu() * svo.getSpeed());
      long vmMem = (long) (svo.getRamSize() * 1024L * 1024L);
      long actualTotalMem = capacityMemory.getTotalCapacity();
      long totalMem = (long) (actualTotalMem * memoryOvercommitRatio);
      long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio);
      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "Hosts's actual total CPU: "
                + actualTotalCpu
                + " and CPU after applying overprovisioning: "
                + totalCpu);
        s_logger.debug(
            "Hosts's actual total RAM: "
                + actualTotalMem
                + " and RAM after applying overprovisioning: "
                + totalMem);
      }

      if (!moveFromReserved) {
        /* move resource from used */
        if (usedCpu >= vmCPU) {
          capacityCpu.setUsedCapacity(usedCpu - vmCPU);
        }
        if (usedMem >= vmMem) {
          capacityMemory.setUsedCapacity(usedMem - vmMem);
        }

        if (moveToReservered) {
          if (reservedCpu + vmCPU <= totalCpu) {
            capacityCpu.setReservedCapacity(reservedCpu + vmCPU);
          }
          if (reservedMem + vmMem <= totalMem) {
            capacityMemory.setReservedCapacity(reservedMem + vmMem);
          }
        }
      } else {
        if (reservedCpu >= vmCPU) {
          capacityCpu.setReservedCapacity(reservedCpu - vmCPU);
        }
        if (reservedMem >= vmMem) {
          capacityMemory.setReservedCapacity(reservedMem - vmMem);
        }
      }

      s_logger.debug(
          "release cpu from host: "
              + hostId
              + ", old used: "
              + usedCpu
              + ",reserved: "
              + reservedCpu
              + ", actual total: "
              + actualTotalCpu
              + ", total with overprovisioning: "
              + totalCpu
              + "; new used: "
              + capacityCpu.getUsedCapacity()
              + ",reserved:"
              + capacityCpu.getReservedCapacity()
              + "; movedfromreserved: "
              + moveFromReserved
              + ",moveToReservered"
              + moveToReservered);

      s_logger.debug(
          "release mem from host: "
              + hostId
              + ", old used: "
              + usedMem
              + ",reserved: "
              + reservedMem
              + ", total: "
              + totalMem
              + "; new used: "
              + capacityMemory.getUsedCapacity()
              + ",reserved:"
              + capacityMemory.getReservedCapacity()
              + "; movedfromreserved: "
              + moveFromReserved
              + ",moveToReservered"
              + moveToReservered);

      _capacityDao.update(capacityCpu.getId(), capacityCpu);
      _capacityDao.update(capacityMemory.getId(), capacityMemory);
      txn.commit();
      return true;
    } catch (Exception e) {
      s_logger.debug("Failed to transit vm's state, due to " + e.getMessage());
      txn.rollback();
      return false;
    }
  }