/* Copyright (c) 2015 EMC Corporation * All Rights Reserved * */ package com.emc.storageos.api.service.impl.resource.cinder; import java.net.URI; import java.util.HashMap; import java.util.List; import javax.ws.rs.DELETE; 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.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.api.service.authorization.PermissionsHelper; import com.emc.storageos.api.service.impl.resource.TaskResourceService; import com.emc.storageos.api.service.impl.resource.utils.CinderApiUtils; import com.emc.storageos.api.service.impl.response.ProjOwnedResRepFilter; import com.emc.storageos.api.service.impl.response.ResRepFilter; import com.emc.storageos.cinder.model.VolumeType; import com.emc.storageos.cinder.model.VolumeTypeEncryption; import com.emc.storageos.cinder.model.VolumeTypeEncryptionResponse; import com.emc.storageos.cinder.model.VolumeTypesRestResp; import com.emc.storageos.cinder.CinderConstants; import com.emc.storageos.db.client.model.DataObject; import com.emc.storageos.db.client.model.VirtualPool; import com.emc.storageos.model.RelatedResourceRep; import com.emc.storageos.model.ResourceTypeEnum; 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; @Path("/v2/{tenant_id}/types") @DefaultPermissions(readRoles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR }, readAcls = { ACL.USE }, writeRoles = {}) @SuppressWarnings({ "unchecked", "rawtypes" }) public class TypeService extends TaskResourceService { private static final Logger _log = LoggerFactory.getLogger(TypeService.class); @Override public Class<VirtualPool> getResourceClass() { return VirtualPool.class; } /** * Get volume types * * * @prereq none * * @param tenant_id the URN of the tenant * * @brief List volume types * @return Volume types list */ @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response getVolumeTypes(@PathParam("tenant_id") URI openstack_tenant_id, @Context HttpHeaders header) { // Here we ignore the openstack tenant id _log.info("START get list of volume types"); VolumeTypesRestResp types = new VolumeTypesRestResp(); StorageOSUser user = getUserFromContext(); URI tenantId = URI.create(user.getTenantId()); List<URI> vpools = _dbClient.queryByType(VirtualPool.class, true); for (URI vpool : vpools) { VirtualPool pool = _dbClient.queryObject(VirtualPool.class, vpool); _log.debug("Looking up vpool {}", pool.getLabel()); if (pool != null && pool.getType().equalsIgnoreCase(VirtualPool.Type.block.name())) { if (_permissionsHelper.tenantHasUsageACL(tenantId, pool)) { _log.debug("Adding vpool {}", pool.getLabel()); VolumeType type = new VolumeType(); type.id = pool.getId().toString(); type.name = pool.getLabel(); type.extra_specs = new HashMap<String, String>(); types.getVolume_types().add(type); } } } _log.info("END get list of volume types"); return CinderApiUtils.getCinderResponse(types, header, false,CinderConstants.STATUS_OK); } /** * Get information about a specified volume type * * * @prereq none * * @param tenant_id the URN of the tenant * @param volume_type_id the URN of the volume type * * @brief Show volume type * @return Volume type details */ @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{volume_type_id}") @CheckPermission(roles = { Role.SYSTEM_MONITOR, Role.TENANT_ADMIN }, acls = { ACL.ANY }) public Response getVolumeType(@PathParam("tenant_id") URI openstacktenant_id, @PathParam("volume_type_id") URI volume_type_id, @Context HttpHeaders header) { _log.debug("START get volume types {}", volume_type_id); // Here we ignore the openstack tenant id VolumeType volType = new VolumeType(); VirtualPool pool = _dbClient.queryObject(VirtualPool.class, volume_type_id); if (pool != null) { if (pool.getType().equalsIgnoreCase(VirtualPool.Type.block.name())) { _log.debug("Found matching vpool {}", pool.getLabel()); StorageOSUser user = getUserFromContext(); URI tenantId = URI.create(user.getTenantId()); if (_permissionsHelper.tenantHasUsageACL(tenantId, pool)) { _log.debug("Has permissions for vpool {}", pool.getLabel()); volType.id = pool.getId().toString(); volType.name = pool.getLabel(); volType.extra_specs = new HashMap<String, String>(); } } } _log.debug("END get volume types {}", volume_type_id); return CinderApiUtils.getCinderResponse(volType, header, true,CinderConstants.STATUS_OK); } /** * Gets encryption information about a specified volume type * * * @prereq none * * @param tenant_id the URN of the tenant * @param volume_type_id the URN of the volume type * * @brief Show volume type * @return Volume type details */ @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{volume_type_id}/encryption") @CheckPermission(roles = { Role.SYSTEM_MONITOR, Role.TENANT_ADMIN }, acls = { ACL.ANY }) public Response getVolumeTypeEncryption(@PathParam("tenant_id") URI openstacktenant_id, @PathParam("volume_type_id") URI volume_type_id, @Context HttpHeaders header) { _log.debug("START get volume type encryption {}", volume_type_id); // TODO - Actual implementation needs to be added VolumeTypeEncryptionResponse encryptionRes = new VolumeTypeEncryptionResponse(); VolumeTypeEncryption volType = new VolumeTypeEncryption(); encryptionRes.setEncryption(volType); _log.debug("END get volume type encryption {}", volume_type_id); return CinderApiUtils.getCinderResponse(encryptionRes, header, true,CinderConstants.STATUS_OK); } /** * Set information about a specified volume type * * * @prereq none * * @param tenant_id the URN of the tenant * @param volume_type_id the URN of the volume type * * @brief Set volume type * @return error */ @POST @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{volume_type_id}/extra_specs") @CheckPermission(roles = { Role.SYSTEM_MONITOR, Role.TENANT_ADMIN }, acls = { ACL.ANY }) public Response setVolumeTypeKey(@PathParam("tenant_id") URI openstacktenant_id, @PathParam("volume_type_id") URI volumeTypeId, @Context HttpHeaders header) { _log.info("VolumeType updation is not supported"); return CinderApiUtils.createErrorResponse(400, "Bad Request: Update volume type not supported"); } /** * Delete a specific volume type * NOTE: This operation is not supported on current version of enterprise cinder. * * @prereq none * @param tenant_id the URN of the tenant * @param volume_type_id the URN of the volume type * @return error */ @DELETE @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/{volume_type_id}") @CheckPermission(roles = { Role.SYSTEM_MONITOR, Role.TENANT_ADMIN }, acls = { ACL.ANY }) public Response deleteVolumeType(@PathParam("tenant_id") String openstackTenantId, @PathParam("volume_type_id") String volumeTypeId) { _log.info("VolumeType deletion is not supported"); return CinderApiUtils.createErrorResponse(400, "Bad Request : Delete volume type not supported"); } /** * Type is a zone level resource */ @Override protected boolean isZoneLevelResource() { return true; } @Override protected ResourceTypeEnum getResourceType() { return ResourceTypeEnum.VPOOL; } /** * Get object specific permissions filter * */ @Override protected ResRepFilter<? extends RelatedResourceRep> getPermissionFilter(StorageOSUser user, PermissionsHelper permissionsHelper) { return new ProjOwnedResRepFilter(user, permissionsHelper, VirtualPool.class); } @Override protected DataObject queryResource(URI id) { return _dbClient.queryObject(VirtualPool.class, id); } @Override protected URI getTenantOwner(URI id) { throw new UnsupportedOperationException(); } }