diff --git a/api/src/org/apache/cloudstack/api/Parameter.java b/api/src/org/apache/cloudstack/api/Parameter.java index 6f64737ab83..89178f200e7 100644 --- a/api/src/org/apache/cloudstack/api/Parameter.java +++ b/api/src/org/apache/cloudstack/api/Parameter.java @@ -22,6 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.BaseCmd.CommandType; @Retention(RetentionPolicy.RUNTIME) @@ -48,4 +49,6 @@ public @interface Parameter { String since() default ""; String retrieveMethod() default "getById"; + + RoleType[] authorized() default {}; } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java index e90643878ac..f6bdb3cd855 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -24,6 +25,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PodResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; @@ -66,6 +68,10 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd { @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, description="the ID of the availability zone") private Long zoneId; + + @Parameter(name=ApiConstants.STORAGE_ID, type=CommandType.UUID, entityType=StoragePoolResponse.class, + description="the ID of the storage pool, available to ROOT admin only", since="4.3", authorized = { RoleType.Admin }) + private Long storageId; ///////////////////////////////////////////////////// @@ -101,6 +107,9 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd { return zoneId; } + public Long getStorageId() { + return storageId; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java index 610c1bbdb99..9672ef1e837 100755 --- a/server/src/com/cloud/api/ApiDispatcher.java +++ b/server/src/com/cloud/api/ApiDispatcher.java @@ -33,10 +33,9 @@ import java.util.regex.Matcher; import javax.annotation.PostConstruct; import javax.inject.Inject; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.InfrastructureEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.ApiConstants; @@ -59,6 +58,7 @@ import org.apache.cloudstack.api.command.user.event.ListEventsCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobManager; +import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; @@ -192,7 +192,22 @@ public class ApiDispatcher { } //TODO: Annotate @Validate on API Cmd classes, FIXME how to process Validate - Validate validateAnnotation = field.getAnnotation(Validate.class); + RoleType[] allowedRoles = parameterAnnotation.authorized(); + if (allowedRoles.length > 0) { + boolean permittedParameter = false; + Account caller = CallContext.current().getCallingAccount(); + for (RoleType allowedRole : allowedRoles) { + if (allowedRole.getValue() == caller.getType()) { + permittedParameter = true; + break; + } + } + if (!permittedParameter) { + s_logger.debug("Ignoring paremeter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in"); + continue; + } + } + Object paramObj = unpackedParams.get(parameterAnnotation.name()); if (paramObj == null) { if (parameterAnnotation.required()) { diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index f9d9c4f4c7a..735bbc92295 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -1640,6 +1640,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { String type = cmd.getType(); Map tags = cmd.getTags(); boolean isRootAdmin = _accountMgr.isRootAdmin(caller.getType()); + Long storageId = cmd.getStorageId(); Long zoneId = cmd.getZoneId(); Long podId = null; @@ -1675,6 +1676,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("instanceId", sb.entity().getVmId(), SearchCriteria.Op.EQ); sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("storageId", sb.entity().getPoolId(), SearchCriteria.Op.EQ); // Only return volumes that are not destroyed sb.and("state", sb.entity().getState(), SearchCriteria.Op.NEQ); sb.and("systemUse", sb.entity().isSystemUse(), SearchCriteria.Op.NEQ); @@ -1733,6 +1735,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (podId != null) { sc.setParameters("podId", podId); } + + if (storageId != null) { + sc.setParameters("storageId", storageId); + } if(!isRootAdmin){ sc.setParameters("displayVolume", 1);