/**
   * Deactivate Quota directory of file system, this will move the Quota directory to a
   * "marked-for-delete" state
   *
   * <p>NOTE: This is an asynchronous operation.
   *
   * @param id the URN of the QuotaDirectory
   * @param param QuotaDirectory delete param for optional force delete
   * @brief Delete file system Quota Dir
   * @return Task resource representation
   * @throws com.emc.storageos.svcs.errorhandling.resources.InternalException
   */
  @POST
  @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Path("/{id}/deactivate")
  @CheckPermission(
      roles = {Role.TENANT_ADMIN},
      acls = {ACL.OWN, ACL.ALL})
  public TaskResourceRep deactivateQuotaDirectory(
      @PathParam("id") URI id, QuotaDirectoryDeleteParam param) throws InternalException {

    _log.info("FileService::deactivateQtree Request recieved {}", id);
    String task = UUID.randomUUID().toString();
    ArgValidator.checkFieldUriType(id, QuotaDirectory.class, "id");
    QuotaDirectory quotaDirectory = queryResource(id);
    FileShare fs = queryFileShareResource(quotaDirectory.getParent().getURI());
    ArgValidator.checkFieldNotNull(fs, "filesystem");

    // <TODO> Implement Force delete option when shares and exports for Quota Directory are
    // supported

    Operation op = new Operation();
    op.setResourceType(ResourceOperationTypeEnum.DELETE_FILE_SYSTEM_QUOTA_DIR);
    quotaDirectory.getOpStatus().createTaskStatus(task, op);
    fs.setOpStatus(new OpStatusMap());
    fs.getOpStatus().createTaskStatus(task, op);
    _dbClient.persistObject(fs);
    _dbClient.persistObject(quotaDirectory);

    // Now get ready to make calls into the controller
    StorageSystem device = _dbClient.queryObject(StorageSystem.class, fs.getStorageDevice());
    FileController controller = getController(FileController.class, device.getSystemType());
    try {
      controller.deleteQuotaDirectory(device.getId(), quotaDirectory.getId(), fs.getId(), task);
      // If delete operation is successful, then remove obj from ViPR db by setting inactive=true
      quotaDirectory.setInactive(true);
      _dbClient.persistObject(quotaDirectory);

    } catch (InternalException e) {
      // treating all controller exceptions as internal error for now. controller
      // should discriminate between validation problems vs. internal errors

      throw e;
    }

    auditOp(
        OperationTypeEnum.DELETE_FILE_SYSTEM_QUOTA_DIR,
        true,
        AuditLogManager.AUDITOP_BEGIN,
        quotaDirectory.getLabel(),
        quotaDirectory.getId().toString(),
        fs.getId().toString());

    fs = _dbClient.queryObject(FileShare.class, fs.getId());
    _log.debug(
        "FileService::Quota directory Before sending response, FS ID : {}, Taks : {} ; Status {}",
        fs.getOpStatus().get(task),
        fs.getOpStatus().get(task).getStatus());

    return toTask(quotaDirectory, task, op);
  }
  /**
   * Creates a manual (fake) vcenter discover task, so that there wont be any vcenter discovery
   * happening because of this task.
   *
   * @param vcenter vcenter to create its manual/fake discovery task.
   * @return returns fake/manual vcenter discovery task.
   */
  private TaskResourceRep createManualReadyTask(Vcenter vcenter) {
    // if not discoverable, manually create a ready task
    Operation op = new Operation();
    op.setResourceType(ResourceOperationTypeEnum.DISCOVER_VCENTER);
    op.ready("Vcenter not discoverable.");

    String taskId = UUID.randomUUID().toString();
    _dbClient.createTaskOpStatus(Host.class, vcenter.getId(), taskId, op);

    return toTask(vcenter, taskId, op);
  }
  /**
   * Update Quota Directory for a file share
   *
   * <p>NOTE: This is an asynchronous operation.
   *
   * @param id the URN of a ViPR Quota directory
   * @param param File system Quota directory update parameters
   * @brief Update file system Quota directory
   * @return Task resource representation
   * @throws com.emc.storageos.svcs.errorhandling.resources.InternalException
   */
  @POST
  @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Path("/{id}")
  @CheckPermission(
      roles = {Role.TENANT_ADMIN},
      acls = {ACL.OWN, ACL.ALL})
  public TaskResourceRep updateQuotaDirectory(
      @PathParam("id") URI id, QuotaDirectoryUpdateParam param) throws InternalException {
    _log.info("FileService::Update Quota directory Request recieved {}", id);

    QuotaDirectory quotaDir = queryResource(id);

    String task = UUID.randomUUID().toString();

    if (param.getSecurityStyle() != null) {
      ArgValidator.checkFieldValueFromEnum(
          param.getSecurityStyle(),
          "security_style",
          EnumSet.allOf(QuotaDirectory.SecurityStyles.class));
    }

    // Get the FileSystem object
    FileShare fs = queryFileShareResource(quotaDir.getParent().getURI());
    ArgValidator.checkFieldNotNull(fs, "filesystem");

    // Update the quota directory object to store in ViPR database
    quotaDir.setOpStatus(new OpStatusMap());

    // Set all other optional parameters too.
    if (param.getOpLock() != null) {
      quotaDir.setOpLock(param.getOpLock());
    }

    if (param.getSecurityStyle() != null) {
      quotaDir.setSecurityStyle(param.getSecurityStyle());
    }

    if (param.getSize() != null) {
      Long quotaSize = SizeUtil.translateSize(param.getSize());
      if (quotaSize > 0) {
        ArgValidator.checkFieldMaximum(quotaSize, fs.getCapacity(), " Bytes", "size");
        quotaDir.setSize(quotaSize);
      }
    }

    Operation op = new Operation();
    op.setResourceType(ResourceOperationTypeEnum.UPDATE_FILE_SYSTEM_QUOTA_DIR);
    quotaDir.getOpStatus().createTaskStatus(task, op);
    fs.setOpStatus(new OpStatusMap());
    fs.getOpStatus().createTaskStatus(task, op);
    _dbClient.persistObject(fs);
    _dbClient.persistObject(quotaDir);

    // Create an object of type "FileShareQtree" to be passed into the south-bound layers.
    FileShareQuotaDirectory qt = new FileShareQuotaDirectory(quotaDir);

    // Now get ready to make calls into the controller
    StorageSystem device = _dbClient.queryObject(StorageSystem.class, fs.getStorageDevice());
    FileController controller = getController(FileController.class, device.getSystemType());
    try {
      controller.updateQuotaDirectory(device.getId(), qt, fs.getId(), task);
    } catch (InternalException e) {
      _log.error("Error during update of Quota Directory {}", e);

      // treating all controller exceptions as internal error for now. controller
      // should discriminate between validation problems vs. internal errors
      throw e;
    }

    auditOp(
        OperationTypeEnum.UPDATE_FILE_SYSTEM_QUOTA_DIR,
        true,
        AuditLogManager.AUDITOP_BEGIN,
        quotaDir.getLabel(),
        quotaDir.getId().toString(),
        fs.getId().toString());

    fs = _dbClient.queryObject(FileShare.class, fs.getId());
    _log.debug(
        "FileService::Quota directory Before sending response, FS ID : {}, Taks : {} ; Status {}",
        fs.getOpStatus().get(task),
        fs.getOpStatus().get(task).getStatus());

    return toTask(quotaDir, task, op);
  }