@Override
 protected QuotaDirectory queryResource(URI id) {
   ArgValidator.checkUri(id);
   QuotaDirectory qd = _permissionsHelper.getObjectById(id, QuotaDirectory.class);
   ArgValidator.checkEntityNotNull(qd, id, isIdEmbeddedInURL(id));
   return qd;
 }
  /**
   * 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);
  }
  /**
   * Validates vCenter user credentials from create or update parameters.
   *
   * @param param either vCenter create or update param.
   * @param vcenter vCenter object.
   */
  private void validateVcenterCredentials(VcenterParam param, Vcenter vcenter) {
    if (StringUtils.isBlank(param.getPassword()) && vcenter != null) {
      param.setPassword(StringUtils.trimToNull(vcenter.getPassword()));
    }

    if (StringUtils.isBlank(param.getUserName()) && vcenter != null) {
      param.setUserName(StringUtils.trimToNull(vcenter.getUsername()));
    }

    ArgValidator.checkFieldNotNull(param.getUserName(), "username");
    ArgValidator.checkFieldNotNull(param.getPassword(), "password");
  }
  /**
   * Validates the individual list of acl entries. It is not valid acl entries list, when an acl
   * entry contains more than one privilege or privileges other than USE and if the tenant provided
   * in the acl entry is not a valid tenant org.
   *
   * @param aclEntries acl entries to be validated.
   */
  private void validateAclEntries(List<ACLEntry> aclEntries) {
    if (CollectionUtils.isEmpty(aclEntries)) {
      return;
    }

    Iterator<ACLEntry> aclEntryIterator = aclEntries.iterator();
    while (aclEntryIterator.hasNext()) {
      ACLEntry aclEntry = aclEntryIterator.next();

      // If more than one privileges provided the ACL Entry, it is not supported
      // for vCenter ACL. Only USE ACL can be provided.
      if (aclEntry.getAces().size() != 1) {
        throw APIException.badRequests.unsupportedNumberOfPrivileges(
            URI.create(aclEntry.getTenant()), aclEntry.getAces());
      }

      if (!aclEntry.getAces().get(0).equalsIgnoreCase(ACL.USE.name())) {
        throw APIException.badRequests.unsupportedPrivilege(
            URI.create(aclEntry.getTenant()), aclEntry.getAces().get(0));
      }

      // Validate if the provided tenant is a valid tenant or not.
      URI tenantId = URI.create(aclEntry.getTenant());
      TenantOrg tenant = queryObject(TenantOrg.class, tenantId, true);
      ArgValidator.checkEntity(tenant, tenantId, isIdEmbeddedInURL(tenantId));
    }
  }
  /**
   * Gets the current acl assignments of the requested vCenter.
   *
   * @param vcenterId
   * @return the list of acl assignments of the requested vCenter.
   */
  private ACLAssignments getAclAssignmentsResponse(URI vcenterId) {
    Vcenter vcenter = queryObject(Vcenter.class, vcenterId, true);
    ArgValidator.checkEntity(vcenter, vcenterId, isIdEmbeddedInURL(vcenterId));

    ACLAssignments response = new ACLAssignments();
    response.setAssignments(_permissionsHelper.convertToACLEntries(vcenter.getAcls()));

    return response;
  }
  /**
   * Discovers (refreshes) a vCenter. This is an asynchronous call.
   *
   * @param id The URI of the vCenter.
   * @prereq none
   * @brief Discover vCenter
   * @return TaskResourceRep (asynchronous call)
   */
  @POST
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Path("/{id}/discover")
  @CheckPermission(roles = {Role.SYSTEM_ADMIN, Role.TENANT_ADMIN})
  public TaskResourceRep discoverVcenter(@PathParam("id") URI id) {
    ArgValidator.checkFieldUriType(id, Vcenter.class, "id");
    Vcenter vcenter = queryObject(Vcenter.class, id, true);

    return doDiscoverVcenter(vcenter);
  }
 /**
  * Get info for file system quota directory
  *
  * @param id the URN of a ViPR Quota directory
  * @brief Show file system quota directory
  * @return File system quota directory details
  */
 @GET
 @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 @Path("/{id}")
 @CheckPermission(
     roles = {Role.SYSTEM_MONITOR, Role.TENANT_ADMIN},
     acls = {ACL.ANY})
 public QuotaDirectoryRestRep getQuotaDirectory(@PathParam("id") URI id) {
   ArgValidator.checkFieldUriType(id, QuotaDirectory.class, "id");
   QuotaDirectory quotaDir = queryResource(id);
   return map(quotaDir);
 }
  /**
   * Lists the id and name of all the vCenters that belong to the given tenant organization if the
   * requesting user is a SysAdmin or SecAdmin. If the requested user is a TenantAdmin and user is a
   * tenant of the "tenant" given in the query param then all the vCenters of the tenant query param
   * will be returned otherwise returned only the vCenters that the user's tenant shares.
   *
   * @param tid tenant to filter the vCenters. "No-Filter" or "null" indicates, listing all the
   *     vCenters in the system. "Not-Assigned" indicates, list all the vCenters with no tenants
   *     assigned to it.
   * @return a list of vCenters that belong to the tenant organization.
   * @throws DatabaseException when a DB error occurs
   */
  @GET
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  public VcenterList listVcenters(@QueryParam("tenant") final URI tid) throws DatabaseException {
    VcenterList list = new VcenterList();
    List<Vcenter> vcenters = null;

    if (isSecurityAdmin() || isSystemAdmin()) {
      _log.debug("Fetching vCenters for {}", tid);
      if (NullColumnValueGetter.isNullURI(tid)
          || Vcenter.NO_TENANT_SELECTOR.equalsIgnoreCase(tid.toString())) {
        vcenters = getDataObjects(Vcenter.class);
        list.setVcenters(
            map(
                ResourceTypeEnum.VCENTER,
                getNamedElementsList(Vcenter.class, DATAOBJECT_NAME_FIELD, vcenters)));
      } else if (Vcenter.TENANT_SELECTOR_FOR_UNASSIGNED.equalsIgnoreCase(tid.toString())) {
        vcenters = getDataObjects(Vcenter.class);
        list.setVcenters(
            map(
                ResourceTypeEnum.VCENTER,
                getNamedElementsWithNoAcls(Vcenter.class, DATAOBJECT_NAME_FIELD, vcenters)));
      } else {
        ArgValidator.checkEntity(_dbClient.queryObject(tid), tid, isIdEmbeddedInURL(tid));
        list.setVcenters(
            map(
                ResourceTypeEnum.VCENTER,
                listChildrenWithAcls(tid, Vcenter.class, DATAOBJECT_NAME_FIELD)));
      }
      return list;
    }

    vcenters = getDataObjects(Vcenter.class);
    if (!CollectionUtils.isEmpty(vcenters)) {
      List<Vcenter> tenantVcenterList = null;
      if (shouldTenantAdminUseTenantParam(tid)) {
        // If the tenant admin can use the tid query param, then the filtering should
        // happen based on the tenant query param.
        tenantVcenterList = filterVcentersByTenant(vcenters, tid);
      } else {
        // Get the vCenters based on the User's tenant org. If the user is not a tenant admin,
        // insufficient
        // permission exception will be thrown.
        tenantVcenterList = filterVcentersByTenant(vcenters, NullColumnValueGetter.getNullURI());
      }
      list.setVcenters(
          map(
              ResourceTypeEnum.VCENTER,
              getNamedElementsList(Vcenter.class, DATAOBJECT_NAME_FIELD, tenantVcenterList)));
    }
    return list;
  }
  /**
   * Detaches storage from the vcenter.
   *
   * @param id the URN of a ViPR vcenter
   * @brief Detach storage from vcenter
   * @return task
   * @throws DatabaseException when a DB error occurs
   */
  @POST
  @Path("/{id}/detach-storage")
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @CheckPermission(roles = {Role.SYSTEM_ADMIN, Role.TENANT_ADMIN})
  public TaskResourceRep detachStorage(@PathParam("id") URI id) throws DatabaseException {
    Vcenter vcenter = queryObject(Vcenter.class, id, true);
    ArgValidator.checkEntity(vcenter, id, true);

    checkIfOtherTenantsUsingTheVcenter(vcenter);

    String taskId = UUID.randomUUID().toString();
    Operation op =
        _dbClient.createTaskOpStatus(
            Vcenter.class,
            vcenter.getId(),
            taskId,
            ResourceOperationTypeEnum.DETACH_VCENTER_DATACENTER_STORAGE);
    ComputeSystemController controller = getController(ComputeSystemController.class, null);
    controller.detachVcenterStorage(vcenter.getId(), false, taskId);
    return toTask(vcenter, taskId, op);
  }
  /**
   * Add or remove individual Access Control List entry(s). When the vCenter is created with no
   * shared access (Vcenter.shared = Boolean.FALSE), there cannot be multiple Access Control List
   * Entries associated with this vCenter.
   *
   * @param changes Access Control List assignment changes. Request body must include at least one
   *     add or remove operation
   * @param id the URN of a ViPR Project.
   * @return the vCenter discovery async task.
   */
  @PUT
  @Path("/{id}/acl")
  @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @CheckPermission(roles = {Role.SECURITY_ADMIN, Role.SYSTEM_ADMIN})
  public TaskResourceRep updateAclAssignments(
      @PathParam("id") URI id, ACLAssignmentChanges changes) {
    // Make sure the vCenter is a valid one.
    Vcenter vcenter = queryObject(Vcenter.class, id, true);
    ArgValidator.checkEntity(vcenter, id, isIdEmbeddedInURL(id));

    // Validate the acl assignment changes. It is not valid when an
    // acl entry contains more than one privilege or privileges
    // other than USE.
    validateAclAssignments(changes);

    // Make sure that the vCenter with respect to the tenants
    // that we are removing is not in use (means the datacenters
    // and its clusters and hosts with the removing tenant do not
    // have any exports).
    checkVcenterUsage(vcenter, changes);

    _permissionsHelper.updateACLs(
        vcenter, changes, new PermissionsHelper.UsageACLFilter(_permissionsHelper));

    _dbClient.updateAndReindexObject(vcenter);

    auditOp(
        OperationTypeEnum.UPDATE_VCENTER,
        true,
        null,
        vcenter.getId().toString(),
        vcenter.getLabel(),
        changes);

    // Rediscover the vCenter, this will update the updated
    // list of tenants based its latest acls to its datacenters
    // and hosts and clusters.
    return doDiscoverVcenter(queryObject(Vcenter.class, vcenter.getId(), true));
  }
  /**
   * List the vCenter data centers of the vCenter.
   *
   * @param id the URN of a ViPR vCenter
   * @param tid tenant to filter the vCenter data centers. "No-Filter" or "null" indicates, listing
   *     all the vCenters in the system. "Not-Assigned" indicates, list all the vCenters with no
   *     tenants assigned to it.
   * @prereq none
   * @brief List vCenter data centers
   * @return All the list of vCenter data centers.
   * @throws DatabaseException when a DB error occurs.
   */
  @GET
  @Path("/{id}/vcenter-data-centers")
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  public VcenterDataCenterList getVcenterDataCenters(
      @PathParam("id") URI id, @QueryParam("tenant") URI tid) throws DatabaseException {
    Vcenter vcenter = queryObject(Vcenter.class, id, false);
    ArgValidator.checkEntity(vcenter, id, isIdEmbeddedInURL(id));

    // check the user permissions for this tenant org
    verifyAuthorizedSystemOrTenantOrgUser(
        _permissionsHelper.convertToACLEntries(vcenter.getAcls()));

    URI tenantId;
    if (isSecurityAdmin() || isSystemAdmin()) {
      tenantId = tid;
    } else {
      if (shouldTenantAdminUseTenantParam(tid)) {
        tenantId = tid;
      } else {
        tenantId = URI.create(getUserFromContext().getTenantId());
      }
    }

    _log.debug("Fetching the vCenterDataCenters for the tenant {}", tenantId);

    // get the vcenters
    VcenterDataCenterList list = new VcenterDataCenterList();
    List<NamedElementQueryResultList.NamedElement> elements =
        listChildren(id, VcenterDataCenter.class, DATAOBJECT_NAME_FIELD, "vcenter");

    // Filter the vCenterDataCenters based on the tenant.
    list.setDataCenters(
        map(
            ResourceTypeEnum.VCENTERDATACENTER,
            id,
            filterTenantResourcesByTenant(tenantId, VcenterDataCenter.class, elements)));
    return list;
  }
  /**
   * List the clusters in a vCenter
   *
   * @param id the URN of a ViPR vCenter
   * @prereq none
   * @brief List vCenter clusters
   * @return The list of clusters of the vCenter.
   * @throws DatabaseException when a DB error occurs.
   */
  @GET
  @Path("/{id}/clusters")
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  public ClusterList getVcenterClusters(@PathParam("id") URI id) throws DatabaseException {
    Vcenter vcenter = queryObject(Vcenter.class, id, false);
    ArgValidator.checkEntity(vcenter, id, isIdEmbeddedInURL(id));

    // check the user permissions for this tenant org
    verifyAuthorizedInTenantOrg(_permissionsHelper.convertToACLEntries(vcenter.getAcls()));

    URI tenantId = URI.create(getUserFromContext().getTenantId());

    List<NamedElementQueryResultList.NamedElement> vCentersDataCenters =
        filterTenantResourcesByTenant(
            tenantId,
            VcenterDataCenter.class,
            listChildren(id, VcenterDataCenter.class, DATAOBJECT_NAME_FIELD, "vcenter"));

    ClusterList list = new ClusterList();
    Iterator<NamedElementQueryResultList.NamedElement> dataCentersIterator =
        vCentersDataCenters.iterator();
    while (dataCentersIterator.hasNext()) {
      NamedElementQueryResultList.NamedElement dataCenterElement = dataCentersIterator.next();
      list.getClusters()
          .addAll(
              map(
                  ResourceTypeEnum.CLUSTER,
                  listChildren(
                      dataCenterElement.getId(),
                      Cluster.class,
                      DATAOBJECT_NAME_FIELD,
                      "vcenterDataCenter")));
    }

    return list;
  }
  /**
   * 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);
  }
 protected FileShare queryFileShareResource(URI id) {
   ArgValidator.checkUri(id);
   FileShare fs = _permissionsHelper.getObjectById(id, FileShare.class);
   ArgValidator.checkEntityNotNull(fs, id, isIdEmbeddedInURL(id));
   return fs;
 }