diff --git a/api/src/com/cloud/api/commands/ListDiskOfferingsCmd.java b/api/src/com/cloud/api/commands/ListDiskOfferingsCmd.java index 61645d06597..46cc202d0ee 100644 --- a/api/src/com/cloud/api/commands/ListDiskOfferingsCmd.java +++ b/api/src/com/cloud/api/commands/ListDiskOfferingsCmd.java @@ -40,7 +40,7 @@ public class ListDiskOfferingsCmd extends BaseListCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the domain of the disk offering. This information is not currently applicable, and should not be used as a parameter.") + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the domain of the disk offering.") private Long domainId; @Parameter(name=ApiConstants.ID, type=CommandType.LONG, description="ID of the disk offering") diff --git a/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java b/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java index cd765e6276f..0175f2bd9ed 100644 --- a/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java +++ b/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java @@ -93,6 +93,8 @@ public class UpdateServiceOfferingCmd extends BaseCmd { @Override public void execute(){ + //Note + //Once an offering is created, we cannot update the domainId field (keeping consistent with zones logic) ServiceOffering result = _configService.updateServiceOffering(this); if (result != null){ ServiceOfferingResponse response = _responseGenerator.createServiceOfferingResponse(result); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 98feff6fa85..170ae7f55ca 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1115,6 +1115,13 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering " + name + ": specify the memory value between 1 and 2147483647"); } + //check if valid domain + if(cmd.getDomainId() != null){ + DomainVO domain = _domainDao.findById(cmd.getDomainId()); + if(domain == null) + throw new InvalidParameterValueException("Please specify a valid domain id"); + } + boolean localStorageRequired = false; String storageType = cmd.getStorageType(); if (storageType == null) { diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 69e6702909b..a9dedba7524 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1603,16 +1603,17 @@ public class ManagementServerImpl implements ManagementServer { return _userAccountDao.search(sc, searchFilter); } - private boolean isPermissible(Long accountDomainId, Long serviceOfferingDomainId){ + //This method is used for permissions check for both disk and service offerings + private boolean isPermissible(Long accountDomainId, Long offeringDomainId){ - if(accountDomainId == serviceOfferingDomainId) + if(accountDomainId == offeringDomainId) return true; // account and service offering in same domain DomainVO domainRecord = _domainDao.findById(accountDomainId); if(domainRecord != null){ while(true){ - if(domainRecord.getId() == serviceOfferingDomainId) + if(domainRecord.getId() == offeringDomainId) return true; //try and move on to the next domain @@ -1662,7 +1663,7 @@ public class ManagementServerImpl implements ManagementServer { //For non-root users if((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)){ - return searchOfferingsInternal(account, name, id, vmId, keyword, searchFilter); + return searchServiceOfferingsInternal(account, name, id, vmId, keyword, searchFilter); } //for root users, the existing flow @@ -1703,7 +1704,7 @@ public class ManagementServerImpl implements ManagementServer { return _offeringsDao.search(sc, searchFilter); } - private List searchOfferingsInternal(Account account, Object name, Object id, Long vmId, Object keyword, Filter searchFilter){ + private List searchServiceOfferingsInternal(Account account, Object name, Object id, Long vmId, Object keyword, Filter searchFilter){ //it was decided to return all offerings for the user's domain, and everything above till root (for normal user or domain admin) //list all offerings belonging to this domain, and all of its parents @@ -4337,17 +4338,107 @@ public class ManagementServerImpl implements ManagementServer { return accountNames; } + private List searchDiskOfferingsInternal(Account account, Object name, Object id, Object keyword, Filter searchFilter){ + //it was decided to return all offerings for the user's domain, and everything above till root (for normal user or domain admin) + //list all offerings belonging to this domain, and all of its parents + //check the parent, if not null, add offerings for that parent to list + List dol = new ArrayList(); + DomainVO domainRecord = _domainDao.findById(account.getDomainId()); + boolean includePublicOfferings = true; + if(domainRecord != null) + { + while(true){ + SearchBuilder sb = _diskOfferingDao.createSearchBuilder(); + + sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + + SearchCriteria sc = sb.create(); + if (keyword != null) { + includePublicOfferings = false; + SearchCriteria ssc = _diskOfferingDao.createSearchCriteria(); + ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + + sc.addAnd("name", SearchCriteria.Op.SC, ssc); + } + + if (name != null) { + includePublicOfferings = false; + sc.setParameters("name", "%" + name + "%"); + } + + if (id != null) { + includePublicOfferings = false; + sc.setParameters("id", id); + } + + //for this domain + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainRecord.getId()); + + //search and add for this domain + dol.addAll(_diskOfferingDao.search(sc, searchFilter)); + + //try and move on to the next domain + if(domainRecord.getParent() != null) + domainRecord = _domainDao.findById(domainRecord.getParent()); + else + break;//now we got all the offerings for this user/dom adm + } + }else{ + s_logger.error("Could not find the domainId for account:"+account.getAccountName()); + throw new CloudAuthenticationException("Could not find the domainId for account:"+account.getAccountName()); + } + + //add all the public offerings to the sol list before returning + if(includePublicOfferings) + dol.addAll(_diskOfferingDao.findPublicDiskOfferings()); + + return dol; + + } + @Override public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) { + //Note + //The list method for offerings is being modified in accordance with discussion with Will/Kevin + //For now, we will be listing the following based on the usertype + //1. For root, we will list all offerings + //2. For domainAdmin and regular users, we will list everything in their domains+parent domains ... all the way till root + Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder sb = _diskOfferingDao.createSearchBuilder(); // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible // search terms and only those with criteria can be set. The proper SQL should be generated as a result. + Account account = UserContext.current().getAccount(); Object name = cmd.getDiskOfferingName(); Object id = cmd.getId(); Object keyword = cmd.getKeyword(); - + Long domainId = cmd.getDomainId(); + + //Keeping this logic consistent with domain specific zones + //if a domainId is provided, we just return the disk offering associated with this domain + if(domainId != null){ + if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){ + return _diskOfferingDao.listByDomainId(domainId);//no perm check + }else{ + //check if the user's domain == do's domain || user's domain is a child of so's domain + if(isPermissible(account.getDomainId(), domainId)){ + //perm check succeeded + return _diskOfferingDao.listByDomainId(domainId); + }else{ + throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account:"+account.getAccountName()+" does not fall in the same domain hierarchy as the disk offering"); + } + } + } + + //For non-root users + if((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)){ + return searchDiskOfferingsInternal(account, name, id, keyword, searchFilter); + } + + //For root users, preserving existing flow sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); diff --git a/server/src/com/cloud/storage/dao/DiskOfferingDao.java b/server/src/com/cloud/storage/dao/DiskOfferingDao.java index 0cfe20e3aea..70646ec7337 100644 --- a/server/src/com/cloud/storage/dao/DiskOfferingDao.java +++ b/server/src/com/cloud/storage/dao/DiskOfferingDao.java @@ -26,5 +26,6 @@ import com.cloud.utils.db.GenericDao; public interface DiskOfferingDao extends GenericDao { List listByDomainId(long domainId); List findPrivateDiskOffering(); + List findPublicDiskOfferings(); } diff --git a/server/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java b/server/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java index ae6f587d5fa..2e9c4591413 100644 --- a/server/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java +++ b/server/src/com/cloud/storage/dao/DiskOfferingDaoImpl.java @@ -24,6 +24,7 @@ import javax.ejb.Local; import org.apache.log4j.Logger; +import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.DiskOfferingVO.Type; import com.cloud.utils.db.Attribute; @@ -39,6 +40,7 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im private final SearchBuilder DomainIdSearch; private final SearchBuilder PrivateDiskOfferingSearch; + private final SearchBuilder PublicDiskOfferingSearch; private final Attribute _typeAttr; protected DiskOfferingDaoImpl() { @@ -50,6 +52,11 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im PrivateDiskOfferingSearch.and("diskSize", PrivateDiskOfferingSearch.entity().getDiskSize(), SearchCriteria.Op.EQ); PrivateDiskOfferingSearch.done(); + PublicDiskOfferingSearch = createSearchBuilder(); + PublicDiskOfferingSearch.and("domainId", PublicDiskOfferingSearch.entity().getDomainId(), SearchCriteria.Op.NULL); + PublicDiskOfferingSearch.and("system", PublicDiskOfferingSearch.entity().isSystemUse(), SearchCriteria.Op.EQ); + PublicDiskOfferingSearch.done(); + _typeAttr = _allAttributes.get("type"); } @@ -91,5 +98,12 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im } return super.executeList(sql, Type.Disk, params); + } + + @Override + public List findPublicDiskOfferings(){ + SearchCriteria sc = PublicDiskOfferingSearch.create(); + sc.setParameters("system", false); + return listBy(sc); } }