@Override
  public void createAsync(
      DataStore dataStore, DataObject vol, AsyncCompletionCallback<CreateCmdResult> callback) {
    EndPoint ep = selector.select(vol);
    CreateObjectCommand createCmd = new CreateObjectCommand(null);

    CreateVolumeContext<CreateCmdResult> context =
        new CreateVolumeContext<CreateCmdResult>(callback, vol);
    AsyncCallbackDispatcher<SamplePrimaryDataStoreDriverImpl, Answer> caller =
        AsyncCallbackDispatcher.create(this);
    caller.setContext(context).setCallback(caller.getTarget().createAsyncCallback(null, null));

    ep.sendMessageAsync(createCmd, caller);
  }
  @Override
  public void createAsync(
      DataStore dataStore, DataObject vol, AsyncCompletionCallback<CreateCmdResult> callback) {
    EndPoint ep = selector.select(vol);
    if (ep == null) {
      String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
      s_logger.error(errMsg);
      throw new CloudRuntimeException(errMsg);
    }
    CreateObjectCommand createCmd = new CreateObjectCommand(null);

    CreateVolumeContext<CreateCmdResult> context =
        new CreateVolumeContext<CreateCmdResult>(callback, vol);
    AsyncCallbackDispatcher<SamplePrimaryDataStoreDriverImpl, Answer> caller =
        AsyncCallbackDispatcher.create(this);
    caller.setContext(context).setCallback(caller.getTarget().createAsyncCallback(null, null));

    ep.sendMessageAsync(createCmd, caller);
  }
  @Override
  public void downloadVolumeToStorage(
      DataObject volume, AsyncCompletionCallback<DownloadAnswer> callback) {
    boolean downloadJobExists = false;
    VolumeDataStoreVO volumeHost = null;
    DataStore store = volume.getDataStore();
    VolumeInfo volInfo = (VolumeInfo) volume;
    RegisterVolumePayload payload = (RegisterVolumePayload) volInfo.getpayload();
    String url = payload.getUrl();
    String checkSum = payload.getChecksum();
    ImageFormat format = ImageFormat.valueOf(payload.getFormat());

    volumeHost = _volumeStoreDao.findByStoreVolume(store.getId(), volume.getId());
    if (volumeHost == null) {
      volumeHost =
          new VolumeDataStoreVO(
              store.getId(),
              volume.getId(),
              new Date(),
              0,
              Status.NOT_DOWNLOADED,
              null,
              null,
              "jobid0000",
              null,
              url,
              checkSum);
      _volumeStoreDao.persist(volumeHost);
    } else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) {
      downloadJobExists = true;
    }

    Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes();
    if (volumeHost != null) {
      start();
      Volume vol = _volumeDao.findById(volume.getId());
      DownloadCommand dcmd =
          new DownloadCommand(
              (VolumeObjectTO) (volume.getTO()), maxVolumeSizeInBytes, checkSum, url, format);
      dcmd.setProxy(getHttpProxy());
      if (downloadJobExists) {
        dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART);
        dcmd.setResourceType(ResourceType.VOLUME);
      }

      EndPoint ep = _epSelector.select(volume);
      if (ep == null) {
        s_logger.warn("There is no secondary storage VM for image store " + store.getName());
        return;
      }
      DownloadListener dl = new DownloadListener(ep, store, volume, _timer, this, dcmd, callback);
      ComponentContext.inject(dl); // auto-wired those injected fields in DownloadListener

      if (downloadJobExists) {
        dl.setCurrState(volumeHost.getDownloadState());
      }

      try {
        ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl));
      } catch (Exception e) {
        s_logger.warn(
            "Unable to start /resume download of volume "
                + volume.getId()
                + " to "
                + store.getName(),
            e);
        dl.setDisconnected();
        dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
      }
    }
  }
  private void initiateTemplateDownload(
      DataObject template, AsyncCompletionCallback<DownloadAnswer> callback) {
    boolean downloadJobExists = false;
    TemplateDataStoreVO vmTemplateStore = null;
    DataStore store = template.getDataStore();

    vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId());
    if (vmTemplateStore == null) {
      vmTemplateStore =
          new TemplateDataStoreVO(
              store.getId(),
              template.getId(),
              new Date(),
              0,
              Status.NOT_DOWNLOADED,
              null,
              null,
              "jobid0000",
              null,
              template.getUri());
      vmTemplateStore.setDataStoreRole(store.getRole());
      vmTemplateStore = _vmTemplateStoreDao.persist(vmTemplateStore);
    } else if ((vmTemplateStore.getJobId() != null) && (vmTemplateStore.getJobId().length() > 2)) {
      downloadJobExists = true;
    }

    Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes();
    if (vmTemplateStore != null) {
      start();
      VirtualMachineTemplate tmpl = _templateDao.findById(template.getId());
      DownloadCommand dcmd =
          new DownloadCommand((TemplateObjectTO) (template.getTO()), maxTemplateSizeInBytes);
      dcmd.setProxy(getHttpProxy());
      if (downloadJobExists) {
        dcmd =
            new DownloadProgressCommand(
                dcmd, vmTemplateStore.getJobId(), RequestType.GET_OR_RESTART);
      }
      if (vmTemplateStore.isCopy()) {
        dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd);
      }
      EndPoint ep = _epSelector.select(template);
      if (ep == null) {
        String errMsg =
            "There is no secondary storage VM for downloading template to image store "
                + store.getName();
        s_logger.warn(errMsg);
        throw new CloudRuntimeException(errMsg);
      }
      DownloadListener dl = new DownloadListener(ep, store, template, _timer, this, dcmd, callback);
      ComponentContext.inject(dl); // initialize those auto-wired field in download listener.
      if (downloadJobExists) {
        // due to handling existing download job issues, we still keep
        // downloadState in template_store_ref to avoid big change in
        // DownloadListener to use
        // new ObjectInDataStore.State transition. TODO: fix this later
        // to be able to remove downloadState from template_store_ref.
        s_logger.info("found existing download job");
        dl.setCurrState(vmTemplateStore.getDownloadState());
      }

      try {
        ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl));
      } catch (Exception e) {
        s_logger.warn(
            "Unable to start /resume download of template "
                + template.getId()
                + " to "
                + store.getName(),
            e);
        dl.setDisconnected();
        dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
      }
    }
  }