/* * Copyright (c) 2012 EMC Corporation * All Rights Reserved */ package com.emc.storageos.api.service.impl.resource; import java.net.URI; import java.util.Iterator; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import com.emc.storageos.api.mapper.functions.MapBlockSnapshotSession; import com.emc.storageos.api.service.authorization.PermissionsHelper; import com.emc.storageos.api.service.impl.resource.snapshot.BlockSnapshotSessionManager; import com.emc.storageos.api.service.impl.response.BulkList; import com.emc.storageos.api.service.impl.response.BulkList.PermissionsEnforcingResourceFilter; import com.emc.storageos.api.service.impl.response.BulkList.ResourceFilter; import com.emc.storageos.api.service.impl.response.ProjOwnedSnapResRepFilter; import com.emc.storageos.api.service.impl.response.ResRepFilter; import com.emc.storageos.api.service.impl.response.SearchedResRepList; import com.emc.storageos.db.client.constraint.ContainmentConstraint; import com.emc.storageos.db.client.constraint.ContainmentPrefixConstraint; import com.emc.storageos.db.client.constraint.PrefixConstraint; import com.emc.storageos.db.client.model.BlockSnapshotSession; import com.emc.storageos.db.client.model.NamedURI; import com.emc.storageos.db.client.model.Project; import com.emc.storageos.model.BulkIdParam; import com.emc.storageos.model.BulkRestRep; import com.emc.storageos.model.RelatedResourceRep; import com.emc.storageos.model.ResourceTypeEnum; import com.emc.storageos.model.TaskList; import com.emc.storageos.model.TaskResourceRep; import com.emc.storageos.model.block.BlockSnapshotSessionBulkRep; import com.emc.storageos.model.block.BlockSnapshotSessionRestRep; import com.emc.storageos.model.block.SnapshotSessionLinkTargetsParam; import com.emc.storageos.model.block.SnapshotSessionRelinkTargetsParam; import com.emc.storageos.model.block.SnapshotSessionUnlinkTargetsParam; import com.emc.storageos.security.authentication.StorageOSUser; import com.emc.storageos.security.authorization.ACL; import com.emc.storageos.security.authorization.CheckPermission; import com.emc.storageos.security.authorization.DefaultPermissions; import com.emc.storageos.security.authorization.Role; /** * Service class that implements APIs on instances of BlockSnapshotSession. */ @Path("/block/snapshot-sessions") @DefaultPermissions(readRoles = { Role.SYSTEM_MONITOR, Role.TENANT_ADMIN }, readAcls = { ACL.ANY }, writeRoles = { Role.TENANT_ADMIN }, writeAcls = { ACL.ANY }) public class BlockSnapshotSessionService extends TaskResourceService { /** * The method implements the API to create and link new target * volumes to an existing BlockSnapshotSession instance. * * @brief Link target volumes to a snapshot session. * * @prereq The block snapshot session has been created and the maximum * number of targets has not already been linked to the snapshot sessions * for the source object. * * @param id The URI of the BlockSnapshotSession instance to which the * new targets will be linked. * @param param The linked target information. * * @return A TaskResourceRep representing the snapshot session task. */ @POST @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{id}/link-targets") @CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY }) public TaskList linkTargetVolumes(@PathParam("id") URI id, SnapshotSessionLinkTargetsParam param) { return getSnapshotSessionManager().linkTargetVolumesToSnapshotSession(id, param); } /** * This method implements the API to re-link a target to either its current * snapshot session or to a different snapshot session of the same source. * * @brief Relink target volumes to snapshot sessions. * * @prereq The target volumes are linked to a snapshot session of the same source object. * * @param id The URI of the BlockSnapshotSession instance to which the * the targets will be re-linked. * @param param The linked target information. * * @return A TaskList representing the snapshot session tasks. */ @POST @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{id}/relink-targets") @CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY }) public TaskList relinkTargetVolumes(@PathParam("id") URI id, SnapshotSessionRelinkTargetsParam param) { return getSnapshotSessionManager().relinkTargetVolumesToSnapshotSession(id, param); } /** * The method implements the API to unlink target volumes from an existing * BlockSnapshotSession instance and optionally delete those target volumes. * * @brief Unlink target volumes from a snapshot session. * * @prereq A snapshot session is created and target volumes have previously * been linked to that snapshot session. * * @param id The URI of the BlockSnapshotSession instance to which the targets are linked. * @param param The linked target information. * * @return A TaskResourceRep representing the snapshot session task. */ @POST @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{id}/unlink-targets") @CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY }) public TaskResourceRep unlinkTargetVolumesForSession(@PathParam("id") URI id, SnapshotSessionUnlinkTargetsParam param) { return getSnapshotSessionManager().unlinkTargetVolumesFromSnapshotSession(id, param); } /** * Restores the data on the array snapshot point-in-time copy represented by the * BlockSnapshotSession instance with the passed id, to the snapshot session source * object. * * @brief Restore snapshot session to source * * @prereq None * * @param id The URI of the BlockSnapshotSession instance to be restored. * * @return TaskResourceRep representing the snapshot session task. */ @POST @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{id}/restore") @CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY }) public TaskResourceRep restoreSnapshotSession(@PathParam("id") URI id) { return getSnapshotSessionManager().restoreSnapshotSession(id); } /** * Deletes the BlockSnapshotSession, will result in permanent deletion of the requested snapshot session from the storage system it was * created on and will move the snapshot session to a "marked-for-delete" state after the deletion happens on the array side. * * If "?type=VIPR_ONLY" is added to the path, it will delete snapshot session only from ViPR data base and leaves the snapshot session * on storage array as it is. * * Possible value for attribute type : FULL, VIPR_ONLY * FULL : Deletes the snapshot session permanently on storage array and ViPR data base. * VIPR_ONLY : Deletes the snapshot session only from ViPR data base and leaves the snapshot on storage array as it is. * * * @brief Delete a block snapshot session. * * @prereq The block snapshot session has no linked target volumes. * * @param id The URI of the BlockSnapshotSession instance to be deleted. * @param type The type of deletion VIPR_ONLY or FULL. * {@link DefaultValue} FULL * @return TaskList representing the tasks for deleting snapshot sessions. */ @POST @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{id}/deactivate") @CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.ANY }) public TaskList deactivateSnapshotSession(@PathParam("id") URI id, @DefaultValue("FULL") @QueryParam("type") String type) { return getSnapshotSessionManager().deleteSnapshotSession(id, type); } /** * Get the details of the BlockSnapshotSession instance with the passed id. * * @brief Get snapshot session details. * * @prereq none * * @param id The URI of the BlockSnapshotSession instance. * * @return BlockSnapshotSessionRestRep specifying the snapshot session details. */ @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{id}") @CheckPermission(roles = { Role.SYSTEM_MONITOR, Role.TENANT_ADMIN }, acls = { ACL.ANY }) public BlockSnapshotSessionRestRep getSnapshotSession(@PathParam("id") URI id) { return getSnapshotSessionManager().getSnapshotSession(id); } /** * Gets the details of the BlockSnapshotSession instances with the ids * specified in the passed data. * * @brief Gets details for requested block snapshot sessions. * * @prereq none * * @param param The ids of the desired BlockSnapshotSession instances. * * @return A BlockSnapshotSessionBulkRep with the snapshot session details. */ @POST @Path("/bulk") @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public BlockSnapshotSessionBulkRep getBulkResources(BulkIdParam param) { return (BlockSnapshotSessionBulkRep) super.getBulkResources(param); } /** * {@inheritDoc} */ @Override public BulkRestRep queryBulkResourceReps(List<URI> ids) { Iterator<BlockSnapshotSession> _dbIterator = _dbClient.queryIterativeObjects(getResourceClass(), ids); return new BlockSnapshotSessionBulkRep(BulkList.wrapping(_dbIterator, MapBlockSnapshotSession.getInstance(_dbClient))); } /** * {@inheritDoc} */ @Override protected BulkRestRep queryFilteredBulkResourceReps(List<URI> ids) { Iterator<BlockSnapshotSession> _dbIterator = _dbClient.queryIterativeObjects(getResourceClass(), ids); ResourceFilter<BlockSnapshotSession> filter = new BlockSnapshotSessionFilter(getUserFromContext(), _permissionsHelper); return new BlockSnapshotSessionBulkRep(BulkList.wrapping(_dbIterator, MapBlockSnapshotSession.getInstance(_dbClient), filter)); } /** * Private class defined filter for bulk resources. */ private class BlockSnapshotSessionFilter extends PermissionsEnforcingResourceFilter<BlockSnapshotSession> { /** * Constructor. * * @param user A reference to a user. * @param permissionsHelper A reference to a permissions helper. */ protected BlockSnapshotSessionFilter(StorageOSUser user, PermissionsHelper permissionsHelper) { super(user, permissionsHelper); } /** * {@inheritDoc} */ @Override public boolean isAccessible(BlockSnapshotSession snapSession) { boolean isAccesible = false; isAccesible = isTenantAccessible(getTenantOwner(snapSession.getId())); if (!isAccesible) { NamedURI project = snapSession.getProject(); if (project != null) { isAccesible = isProjectAccessible(project.getURI()); } } return isAccesible; } } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public Class<BlockSnapshotSession> getResourceClass() { return BlockSnapshotSession.class; } /** * {@inheritDoc} */ @Override protected BlockSnapshotSession queryResource(URI id) { ArgValidator.checkUri(id); BlockSnapshotSession blockSnapshotSession = _permissionsHelper.getObjectById(id, BlockSnapshotSession.class); ArgValidator.checkEntityNotNull(blockSnapshotSession, id, isIdEmbeddedInURL(id)); return blockSnapshotSession; } /** * {@inheritDoc} */ @Override protected URI getTenantOwner(URI id) { BlockSnapshotSession snapshotSession = queryResource(id); URI projectUri = snapshotSession.getProject().getURI(); ArgValidator.checkUri(projectUri); Project project = _permissionsHelper.getObjectById(projectUri, Project.class); ArgValidator.checkEntityNotNull(project, projectUri, isIdEmbeddedInURL(projectUri)); return project.getTenantOrg().getURI(); } /** * {@inheritDoc} */ @Override protected ResourceTypeEnum getResourceType() { return ResourceTypeEnum.BLOCK_SNAPSHOT_SESSION; } /** * Get search results by project alone. * * @return SearchedResRepList */ @Override protected SearchedResRepList getProjectSearchResults(URI projectId) { SearchedResRepList resRepList = new SearchedResRepList(getResourceType()); _dbClient.queryByConstraint( ContainmentConstraint.Factory.getProjectBlockSnapshotSessionConstraint(projectId), resRepList); return resRepList; } /** * Get search results by name in zone or project. * * @return SearchedResRepList */ @Override protected SearchedResRepList getNamedSearchResults(String name, URI projectId) { SearchedResRepList resRepList = new SearchedResRepList(getResourceType()); if (projectId == null) { _dbClient.queryByConstraint( PrefixConstraint.Factory.getLabelPrefixConstraint(getResourceClass(), name), resRepList); } else { _dbClient.queryByConstraint( ContainmentPrefixConstraint.Factory.getBlockSnapshotSessionUnderProjectConstraint( projectId, name), resRepList); } return resRepList; } /** * Get object specific permissions filter * */ @Override public ResRepFilter<? extends RelatedResourceRep> getPermissionFilter(StorageOSUser user, PermissionsHelper permissionsHelper) { return new ProjOwnedSnapResRepFilter(user, permissionsHelper, BlockSnapshotSession.class); } /** * Block snapshot session is not a zone level resource */ @Override protected boolean isZoneLevelResource() { return false; } /** * Creates and returns an instance of the block snapshot session manager to handle * a snapshot session requests. * * @return BlockSnapshotSessionManager */ private BlockSnapshotSessionManager getSnapshotSessionManager() { BlockSnapshotSessionManager snapshotSessionManager = new BlockSnapshotSessionManager(_dbClient, _permissionsHelper, _auditMgr, _coordinator, sc, uriInfo, _request); return snapshotSessionManager; } }