/**
  * Returns one cloudlet to migrate to another vm.
  *
  * @return one running cloudlet
  * @pre $none
  * @post $none
  */
 @Override
 public Cloudlet migrateCloudlet() {
   ResCloudlet rcl = getCloudletExecList().remove(0);
   rcl.finalizeCloudlet();
   Cloudlet cl = rcl.getCloudlet();
   usedPes -= cl.getPesNumber();
   return cl;
 }
  /**
   * Receives an cloudlet to be executed in the VM managed by this scheduler.
   *
   * @param cloudlet the submited cloudlet
   * @param fileTransferTime time required to move the required files from the SAN to the VM
   * @return expected finish time of this cloudlet, or 0 if it is in the waiting queue
   * @pre gl != null
   * @post $none
   */
  @Override
  public double cloudletSubmit(Cloudlet cloudlet, double fileTransferTime) {
    if ((currentCpus - usedPes) >= cloudlet.getPesNumber()) { // it can go to the exec list
      ResCloudlet rcl = new ResCloudlet(cloudlet);
      rcl.setCloudletStatus(Cloudlet.INEXEC);
      for (int i = 0; i < cloudlet.getPesNumber(); i++) {
        rcl.setMachineAndPeId(0, i);
      }

      getCloudletExecList().add(rcl);
      usedPes += cloudlet.getPesNumber();
    } else { // no enough free PEs: go to the waiting queue
      ResCloudlet rcl = new ResCloudlet(cloudlet);
      rcl.setCloudletStatus(Cloudlet.QUEUED);
      getCloudletWaitingList().add(rcl);
      return 0.0;
    }

    // calculate the expected time for cloudlet completion
    double capacity = 0.0;
    int cpus = 0;
    for (Double mips : getCurrentMipsShare()) {
      capacity += mips;
      if (mips > 0) {
        cpus++;
      }
    }

    currentCpus = cpus;
    capacity /= cpus;

    // use the current capacity to estimate the extra amount of
    // time to file transferring. It must be added to the cloudlet length
    double extraSize = capacity * fileTransferTime;
    long length = cloudlet.getCloudletLength();
    length += extraSize;
    cloudlet.setCloudletLength(length);
    return cloudlet.getCloudletLength() / capacity;
  }