@Override
  @Transactional(readOnly = true)
  public void preRecoverVm(VmInstanceInventory vm) {
    String rootVolUuid = vm.getRootVolumeUuid();

    String sql =
        "select ps.uuid from PrimaryStorageVO ps, VolumeVO vol where ps.uuid = vol.primaryStorageUuid"
            + " and vol.uuid = :uuid and ps.type = :pstype";
    TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class);
    q.setParameter("uuid", rootVolUuid);
    q.setParameter("pstype", LocalStorageConstants.LOCAL_STORAGE_TYPE);
    String psuuid = dbf.find(q);
    if (psuuid == null) {
      return;
    }

    sql =
        "select count(ref) from LocalStorageResourceRefVO ref where ref.resourceUuid = :uuid and ref.resourceType = :rtype";
    TypedQuery<Long> rq = dbf.getEntityManager().createQuery(sql, Long.class);
    rq.setParameter("uuid", rootVolUuid);
    rq.setParameter("rtype", VolumeVO.class.getSimpleName());
    long count = rq.getSingleResult();
    if (count == 0) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "unable to recover the vm[uuid:%s, name:%s]. The vm's root volume is on the local"
                      + " storage[uuid:%s]; however, the host on which the root volume is has been deleted",
                  vm.getUuid(), vm.getName(), psuuid)));
    }
  }
  @Override
  @Transactional(
      readOnly = true,
      noRollbackForClassName = {"org.zstack.header.errorcode.OperationFailureException"})
  public void preVmMigration(VmInstanceInventory vm) {
    List<String> volUuids =
        CollectionUtils.transformToList(
            vm.getAllVolumes(),
            new Function<String, VolumeInventory>() {
              @Override
              public String call(VolumeInventory arg) {
                return arg.getUuid();
              }
            });

    String sql =
        "select count(ps) from PrimaryStorageVO ps, VolumeVO vol where ps.uuid = vol.primaryStorageUuid and"
            + " vol.uuid in (:volUuids) and ps.type = :ptype";
    TypedQuery<Long> q = dbf.getEntityManager().createQuery(sql, Long.class);
    q.setParameter("volUuids", volUuids);
    q.setParameter("ptype", LocalStorageConstants.LOCAL_STORAGE_TYPE);
    q.setMaxResults(1);
    Long count = q.getSingleResult();
    if (count > 0) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "unable to live migrate with local storage. The vm[uuid:%s] has volumes on local storage,"
                      + "to protect your data, please stop the vm and do the volume migration",
                  vm.getUuid())));
    }
  }
  @Override
  public void preAttachVolume(VmInstanceInventory vm, final VolumeInventory volume) {
    SimpleQuery<LocalStorageResourceRefVO> q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.add(
        LocalStorageResourceRefVO_.resourceUuid,
        Op.IN,
        list(vm.getRootVolumeUuid(), volume.getUuid()));
    q.groupBy(LocalStorageResourceRefVO_.hostUuid);
    long count = q.count();

    if (count < 2) {
      return;
    }

    q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.select(LocalStorageResourceRefVO_.hostUuid);
    q.add(LocalStorageResourceRefVO_.resourceUuid, Op.EQ, vm.getRootVolumeUuid());
    String rootHost = q.findValue();

    q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.select(LocalStorageResourceRefVO_.hostUuid);
    q.add(LocalStorageResourceRefVO_.resourceUuid, Op.EQ, volume.getUuid());
    String dataHost = q.findValue();

    if (!rootHost.equals(dataHost)) {
      throw new OperationFailureException(
          errf.stringToOperationError(
              String.format(
                  "cannot attach the data volume[uuid:%s] to the vm[uuid:%s]. Both vm's root volume and the data volume are"
                      + " on local primary storage, but they are on different hosts. The root volume[uuid:%s] is on the host[uuid:%s] but the data volume[uuid: %s]"
                      + " is on the host[uuid: %s]",
                  volume.getUuid(),
                  vm.getUuid(),
                  vm.getRootVolumeUuid(),
                  rootHost,
                  volume.getUuid(),
                  dataHost)));
    }
  }