@Override
  public void deployVirtualMachine(
      String reservationId, String caller, Map<VirtualMachineProfile.Param, Object> params)
      throws InsufficientCapacityException, ResourceUnavailableException {
    // grab the VM Id and destination using the reservationId.

    VMReservationVO vmReservation = _reservationDao.findByReservationId(reservationId);
    long vmId = vmReservation.getVmId();

    VMInstanceVO vm = _vmDao.findById(vmId);
    // Pass it down
    Long poolId = null;
    Map<Long, Long> storage = vmReservation.getVolumeReservation();
    if (storage != null) {
      List<Long> volIdList = new ArrayList<Long>(storage.keySet());
      if (volIdList != null && !volIdList.isEmpty()) {
        poolId = storage.get(volIdList.get(0));
      }
    }

    DataCenterDeployment reservedPlan =
        new DataCenterDeployment(
            vm.getDataCenterId(),
            vmReservation.getPodId(),
            vmReservation.getClusterId(),
            vmReservation.getHostId(),
            null,
            null);
    try {
      VMInstanceVO vmDeployed =
          _itMgr.start(
              vm,
              params,
              _userDao.findById(new Long(caller)),
              _accountDao.findById(vm.getAccountId()),
              reservedPlan);
    } catch (Exception ex) {
      // Retry the deployment without using the reservation plan
      DataCenterDeployment plan =
          new DataCenterDeployment(vm.getDataCenterId(), null, null, null, null, null);
      _itMgr.start(
          vm,
          params,
          _userDao.findById(new Long(caller)),
          _accountDao.findById(vm.getAccountId()),
          plan);
    }
  }
  @Override
  public String reserveVirtualMachine(
      VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude)
      throws InsufficientCapacityException, ResourceUnavailableException {

    // call planner and get the deployDestination.
    // load vm instance and offerings and call virtualMachineManagerImpl
    // FIXME: profile should work on VirtualMachineEntity
    VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
    VirtualMachineProfileImpl<VMInstanceVO> vmProfile =
        new VirtualMachineProfileImpl<VMInstanceVO>(vm);
    DataCenterDeployment plan =
        new DataCenterDeployment(
            vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null);
    if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
      plan =
          new DataCenterDeployment(
              planToDeploy.getDataCenterId(),
              planToDeploy.getPodId(),
              planToDeploy.getClusterId(),
              planToDeploy.getHostId(),
              planToDeploy.getPoolId(),
              planToDeploy.getPhysicalNetworkId());
    }

    List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
    if (!vols.isEmpty()) {
      VolumeVO vol = vols.get(0);
      StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
      if (!pool.isInMaintenance()) {
        long rootVolDcId = pool.getDataCenterId();
        Long rootVolPodId = pool.getPodId();
        Long rootVolClusterId = pool.getClusterId();
        if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
          Long clusterIdSpecified = planToDeploy.getClusterId();
          if (clusterIdSpecified != null && rootVolClusterId != null) {
            if (rootVolClusterId.longValue() != clusterIdSpecified.longValue()) {
              // cannot satisfy the plan passed in to the
              // planner
              throw new ResourceUnavailableException(
                  "Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for "
                      + vm,
                  Cluster.class,
                  clusterIdSpecified);
            }
          }
          plan =
              new DataCenterDeployment(
                  planToDeploy.getDataCenterId(),
                  planToDeploy.getPodId(),
                  planToDeploy.getClusterId(),
                  planToDeploy.getHostId(),
                  vol.getPoolId(),
                  null,
                  null);
        } else {
          plan =
              new DataCenterDeployment(
                  rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, null);
        }
      }
    }

    DeploymentPlanner planner = ComponentContext.getComponent(plannerToUse);
    DeployDestination dest = null;

    if (planner.canHandle(vmProfile, plan, exclude)) {
      dest = planner.plan(vmProfile, plan, exclude);
    }

    if (dest != null) {
      // save destination with VMEntityVO
      VMReservationVO vmReservation =
          new VMReservationVO(
              vm.getId(),
              dest.getDataCenter().getId(),
              dest.getPod().getId(),
              dest.getCluster().getId(),
              dest.getHost().getId());
      Map<Long, Long> volumeReservationMap = new HashMap<Long, Long>();
      for (Volume vo : dest.getStorageForDisks().keySet()) {
        volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId());
      }
      vmReservation.setVolumeReservation(volumeReservationMap);

      vmEntityVO.setVmReservation(vmReservation);
      _vmEntityDao.persist(vmEntityVO);

      return vmReservation.getUuid();
    } else {
      throw new InsufficientServerCapacityException(
          "Unable to create a deployment for " + vmProfile,
          DataCenter.class,
          plan.getDataCenterId());
    }
  }