From 2307255aab44330f10bbb2e9ab99bc10512d8ede Mon Sep 17 00:00:00 2001 From: Kris McQueen Date: Wed, 20 Oct 2010 15:23:58 -0700 Subject: [PATCH] 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 --- .../cloud/api/commands/ListSnapshotsCmd.java | 14 +- .../cloud/server/ManagementServerImpl.java | 128 ++++++++++-------- .../com/cloud/utils/db/GenericDaoBase.java | 38 ++++-- 3 files changed, 112 insertions(+), 68 deletions(-) diff --git a/server/src/com/cloud/api/commands/ListSnapshotsCmd.java b/server/src/com/cloud/api/commands/ListSnapshotsCmd.java index c3b5b2a21e4..0355bcab24b 100644 --- a/server/src/com/cloud/api/commands/ListSnapshotsCmd.java +++ b/server/src/com/cloud/api/commands/ListSnapshotsCmd.java @@ -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 snapshots = null; try { snapshots = getManagementServer().listSnapshots(c, interval); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index fd8e864d141..3ce7e892f21 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -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 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 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 accountSearch = _accountDao.createSearchBuilder(); + sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId()); + + SearchBuilder 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); } diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index e5d23190743..b3423817ebe 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -304,11 +304,7 @@ public abstract class GenericDaoBase implements Gene } } if (joins != null) { - for (Ternary join : joins) { - for (final Pair 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 implements Gene throw new CloudRuntimeException("Caught: " + pstmt.toString(), e); } } - + + private int prepareJoins(int i, PreparedStatement pstmt, Collection> joins) throws SQLException { + int j = i; + for (Ternary join : joins) { + for (final Pair value : join.first().getValues()) { + prepareAttribute(++j, pstmt, value.first(), value.second()); + } + } + + for (Ternary 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 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 implements Gene for (Ternary 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 join : joins) { if (join.first().getJoins() != null) { addJoins(str, join.first().getJoins()); } } - - str.delete(str.length() - 4, str.length()); } @Override @DB(txn=false)