bug 6680: constrain the snapshot list by domainId so that snapshots are listed only for the domain hierarchy that the admin has access to

status 6680: resolved fixed
This commit is contained in:
Kris McQueen 2010-10-20 15:23:58 -07:00
parent 314213e302
commit 2307255aab
3 changed files with 112 additions and 68 deletions

View File

@ -75,7 +75,9 @@ public class ListSnapshotsCmd extends BaseCmd {
Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
String keyword = (String)params.get(BaseCmd.Properties.KEYWORD.getName());
Integer page = (Integer)params.get(BaseCmd.Properties.PAGE.getName());
Integer pageSize = (Integer)params.get(BaseCmd.Properties.PAGESIZE.getName());
Integer pageSize = (Integer)params.get(BaseCmd.Properties.PAGESIZE.getName());
boolean isAdmin = false;
//Verify parameters
if(volumeId != null){
@ -95,6 +97,11 @@ public class ListSnapshotsCmd extends BaseCmd {
if( account != null && !isAdmin(account.getType())) {
accountId = account.getId();
} else {
isAdmin = true;
if (account != null) {
domainId = account.getDomainId();
}
}
Long startIndex = Long.valueOf(0);
@ -116,7 +123,10 @@ public class ListSnapshotsCmd extends BaseCmd {
c.addCriteria(Criteria.ID, id);
c.addCriteria(Criteria.KEYWORD, keyword);
c.addCriteria(Criteria.ACCOUNTID, accountId);
if (isAdmin) {
c.addCriteria(Criteria.DOMAINID, domainId);
}
List<SnapshotVO> snapshots = null;
try {
snapshots = getManagementServer().listSnapshots(c, interval);

View File

@ -17,7 +17,6 @@
*/
package com.cloud.server;
import java.io.IOException;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
@ -25,7 +24,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.rmi.ServerException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
@ -51,11 +49,6 @@ import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import netapp.manage.NaAPIFailedException;
import netapp.manage.NaAuthenticationException;
import netapp.manage.NaException;
import netapp.manage.NaProtocolException;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
@ -107,15 +100,15 @@ import com.cloud.async.executor.SecurityGroupParam;
import com.cloud.async.executor.UpdateLoadBalancerParam;
import com.cloud.async.executor.UpgradeVMParam;
import com.cloud.async.executor.VMOperationParam;
import com.cloud.async.executor.VolumeOperationParam;
import com.cloud.async.executor.VMOperationParam.VmOp;
import com.cloud.async.executor.VolumeOperationParam;
import com.cloud.async.executor.VolumeOperationParam.VolumeOp;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
@ -125,8 +118,8 @@ import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
@ -183,8 +176,8 @@ import com.cloud.pricing.dao.PricingDao;
import com.cloud.serializer.GsonHelper;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.ServiceOffering.GuestIpType;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.DiskTemplateVO;
@ -194,22 +187,22 @@ import com.cloud.storage.GuestOSVO;
import com.cloud.storage.InsufficientStorageCapacityException;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotScheduleVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.FileSystem;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.Storage.FileSystem;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.DiskTemplateDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
@ -219,9 +212,9 @@ import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
@ -242,12 +235,12 @@ import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.concurrency.NamedThreadFactory;
@ -271,9 +264,9 @@ import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.VmStats;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
@ -6367,7 +6360,7 @@ public class ManagementServerImpl implements ManagementServer {
@Override
public List<SnapshotVO> listSnapshots(Criteria c, String interval) throws InvalidParameterValueException {
Filter searchFilter = new Filter(SnapshotVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
SearchCriteria sc = _snapshotDao.createSearchCriteria();
SearchBuilder<SnapshotVO> sb = _snapshotDao.createSearchBuilder();
Object volumeId = c.getCriteria(Criteria.VOLUMEID);
Object name = c.getCriteria(Criteria.NAME);
@ -6375,44 +6368,9 @@ public class ManagementServerImpl implements ManagementServer {
Object keyword = c.getCriteria(Criteria.KEYWORD);
Object accountId = c.getCriteria(Criteria.ACCOUNTID);
Object snapshotTypeStr = c.getCriteria(Criteria.TYPE);
sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);
if(volumeId != null){
sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
Object domainId = c.getCriteria(Criteria.DOMAINID);
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (keyword != null) {
SearchCriteria ssc = _snapshotDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (snapshotTypeStr != null) {
SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
if (snapshotType == null) {
throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
}
sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
}
else {
// Show only MANUAL and RECURRING snapshot types
sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
}
if(interval != null && volumeId != null) {
if (interval != null && volumeId != null) {
IntervalType intervalType = DateUtil.IntervalType.getIntervalType(interval);
if(intervalType == null) {
throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
@ -6425,6 +6383,64 @@ public class ManagementServerImpl implements ManagementServer {
return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
}
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<AccountVO> accountSearch = _accountDao.createSearchBuilder();
sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId());
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId());
}
sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);
sb.and("volumeId", sb.entity().getVolumeId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("snapshotTypeEQ", sb.entity().getSnapshotType(), SearchCriteria.Op.EQ);
sb.and("snapshotTypeNEQ", sb.entity().getSnapshotType(), SearchCriteria.Op.NEQ);
SearchCriteria sc = sb.create();
sc.setParameters("status", Snapshot.Status.BackedUp);
if (volumeId != null) {
sc.setParameters("volumeId", volumeId);
}
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
if (id != null) {
sc.setParameters("id", id);
}
if (keyword != null) {
SearchCriteria ssc = _snapshotDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById((Long)domainId);
SearchCriteria joinSearch = sc.getJoin("accountSearch");
joinSearch.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
if (snapshotTypeStr != null) {
SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
if (snapshotType == null) {
throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
}
sc.setParameters("snapshotTypeEQ", snapshotType.ordinal());
} else {
// Show only MANUAL and RECURRING snapshot types
sc.setParameters("snapshotTypeNEQ", Snapshot.SnapshotType.TEMPLATE.ordinal());
}
return _snapshotDao.search(sc, searchFilter);
}

View File

@ -304,11 +304,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> implements Gene
}
}
if (joins != null) {
for (Ternary<SearchCriteria, Attribute, Attribute> join : joins) {
for (final Pair<Attribute, Object> value : join.first().getValues()) {
prepareAttribute(++i, pstmt, value.first(), value.second());
}
}
i = prepareJoins(i, pstmt, joins);
if (s_logger.isTraceEnabled()) {
s_logger.trace("join search statement is " + pstmt.toString());
}
@ -327,7 +323,25 @@ public abstract class GenericDaoBase<T, ID extends Serializable> implements Gene
throw new CloudRuntimeException("Caught: " + pstmt.toString(), e);
}
}
private int prepareJoins(int i, PreparedStatement pstmt, Collection<Ternary<SearchCriteria, Attribute, Attribute>> joins) throws SQLException {
int j = i;
for (Ternary<SearchCriteria, Attribute, Attribute> join : joins) {
for (final Pair<Attribute, Object> value : join.first().getValues()) {
prepareAttribute(++j, pstmt, value.first(), value.second());
}
}
for (Ternary<SearchCriteria, Attribute, Attribute> join : joins) {
if (join.first().getJoins() != null) {
j = prepareJoins(j, pstmt, join.first().getJoins());
}
}
// return the count of attributes just in case someone wants to prepare attributes after the joins are prepared
return j;
}
public List<Object[]> searchAll(SearchCriteria sc, final Filter filter) {
String clause = sc != null ? sc.getWhereClause() : null;
if (clause != null && clause.length() == 0) {
@ -782,16 +796,20 @@ public abstract class GenericDaoBase<T, ID extends Serializable> implements Gene
for (Ternary<SearchCriteria, Attribute, Attribute> join : joins) {
str.insert(fromIndex, join.third().table + ", ");
str.append(join.second().table).append(".").append(join.second().columnName).append("=").append(join.third().table).append(".").append(join.third().columnName);
str.append(" AND (").append(join.first().getWhereClause()).append(") AND ");
String whereClause = join.first().getWhereClause();
if (whereClause != null && whereClause.length() > 0) {
str.append(" AND (").append(whereClause).append(") ");
}
str.append("AND ");
}
str.delete(str.length() - 4, str.length());
for (Ternary<SearchCriteria, Attribute, Attribute> join : joins) {
if (join.first().getJoins() != null) {
addJoins(str, join.first().getJoins());
}
}
str.delete(str.length() - 4, str.length());
}
@Override @DB(txn=false)