From 9a6eaaf21fe2a74c4dcd5872093f03153f38497b Mon Sep 17 00:00:00 2001 From: abhishek Date: Tue, 30 Nov 2010 12:26:50 -0800 Subject: [PATCH] this is a good point to commit the code; have the basic domain specific service offering working --- .../commands/CreateServiceOfferingCmd.java | 10 +- .../api/commands/ListServiceOfferingsCmd.java | 7 + .../api/response/ServiceOfferingResponse.java | 12 ++ .../com/cloud/offering/ServiceOffering.java | 2 + .../src/com/cloud/storage/DiskOfferingVO.java | 15 ++ .../src/com/cloud/api/ApiResponseHelper.java | 1 + .../configuration/ConfigurationManager.java | 3 +- .../ConfigurationManagerImpl.java | 6 +- .../cloud/server/ManagementServerImpl.java | 133 +++++++++++++++++- .../com/cloud/service/ServiceOfferingVO.java | 14 +- .../cloud/service/dao/ServiceOfferingDao.java | 6 +- .../service/dao/ServiceOfferingDaoImpl.java | 35 ++++- 12 files changed, 232 insertions(+), 12 deletions(-) diff --git a/api/src/com/cloud/api/commands/CreateServiceOfferingCmd.java b/api/src/com/cloud/api/commands/CreateServiceOfferingCmd.java index 0ab12647b60..99bd1955d1b 100644 --- a/api/src/com/cloud/api/commands/CreateServiceOfferingCmd.java +++ b/api/src/com/cloud/api/commands/CreateServiceOfferingCmd.java @@ -25,6 +25,7 @@ import com.cloud.api.BaseCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ServiceOfferingResponse; import com.cloud.offering.ServiceOffering; @@ -64,6 +65,9 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name=ApiConstants.USE_VIRTUAL_NETWORK, type=CommandType.BOOLEAN, description="if true, the VM created will use default virtual networking. If false, the VM created will use a direct attached networking model. The default value is true.") private Boolean useVirtualNetwork; + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the containing domain, null for public offerings") + private Long domainId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -100,7 +104,11 @@ public class CreateServiceOfferingCmd extends BaseCmd { return tags; } - public Boolean getUseVirtualNetwork() { + public Long getDomainId() { + return domainId; + } + + public Boolean getUseVirtualNetwork() { return useVirtualNetwork; } diff --git a/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java b/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java index 37aa4b01276..1c81a02c9f2 100644 --- a/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java +++ b/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java @@ -26,6 +26,7 @@ import com.cloud.api.ApiConstants; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ListResponse; import com.cloud.api.response.ServiceOfferingResponse; import com.cloud.offering.ServiceOffering; @@ -48,6 +49,9 @@ public class ListServiceOfferingsCmd extends BaseListCmd { @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, description="the ID of the virtual machine. Pass this in if you want to see the available service offering that a virtual machine can be changed to.") private Long virtualMachineId; + + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the domain associated with the service offering") + private Long domainId; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -65,6 +69,9 @@ public class ListServiceOfferingsCmd extends BaseListCmd { return virtualMachineId; } + public Long getDomainId(){ + return domainId; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/response/ServiceOfferingResponse.java b/api/src/com/cloud/api/response/ServiceOfferingResponse.java index 16cd432f1a9..3b4e45c66e9 100644 --- a/api/src/com/cloud/api/response/ServiceOfferingResponse.java +++ b/api/src/com/cloud/api/response/ServiceOfferingResponse.java @@ -56,6 +56,9 @@ public class ServiceOfferingResponse extends BaseResponse { @SerializedName("tags") @Param(description="the tags for the service offering") private String tags; + @SerializedName("domainId") @Param(description="the domain id of the service offering") + private Long domainId; + public Long getId() { return id; } @@ -143,4 +146,13 @@ public class ServiceOfferingResponse extends BaseResponse { public void setTags(String tags) { this.tags = tags; } + + public Long getDomainId() { + return domainId; + } + + public void setDomainId(Long domainId) { + this.domainId = domainId; + } + } diff --git a/api/src/com/cloud/offering/ServiceOffering.java b/api/src/com/cloud/offering/ServiceOffering.java index 357715f59cc..aa9c97c1b8c 100755 --- a/api/src/com/cloud/offering/ServiceOffering.java +++ b/api/src/com/cloud/offering/ServiceOffering.java @@ -77,4 +77,6 @@ public interface ServiceOffering { */ boolean getUseLocalStorage(); + Long getDomainId(); + } diff --git a/core/src/com/cloud/storage/DiskOfferingVO.java b/core/src/com/cloud/storage/DiskOfferingVO.java index 591f609fd67..4c52e1bc9d3 100644 --- a/core/src/com/cloud/storage/DiskOfferingVO.java +++ b/core/src/com/cloud/storage/DiskOfferingVO.java @@ -120,6 +120,21 @@ public class DiskOfferingVO implements DiskOffering { this.systemUse = systemUse; this.customized = customized; } + + //domain specific offerings constructor (null domainId implies public offering) + public DiskOfferingVO(String name, String displayText, boolean mirrored, String tags, boolean recreatable, boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) { + this.domainId = null; + this.type = Type.Service; + this.name = name; + this.displayText = displayText; + this.mirrored = mirrored; + this.tags = tags; + this.recreatable = recreatable; + this.useLocalStorage = useLocalStorage; + this.systemUse = systemUse; + this.customized = customized; + this.domainId = domainId; + } @Override public long getId() { diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 4c8252be2d9..32e49738370 100644 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -345,6 +345,7 @@ public class ApiResponseHelper implements ResponseGenerator { offeringResponse.setOfferHa(offering.getOfferHA()); offeringResponse.setUseVirtualNetwork(offering.getGuestIpType().equals(GuestIpType.Virtualized)); offeringResponse.setTags(offering.getTags()); + offeringResponse.setDomainId(offering.getDomainId()); offeringResponse.setObjectName("serviceoffering"); return offeringResponse; diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index cad2d478858..75df0ec0b95 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -56,9 +56,10 @@ public interface ConfigurationManager extends Manager { * @param localStorageRequired * @param offerHA * @param useVirtualNetwork + * @param domainId * @return ID */ - ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean useVirtualNetwork, String tags); + ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean useVirtualNetwork, String tags, Long domainId); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 35949b11b41..4fefb4683ba 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1138,18 +1138,18 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } return createServiceOffering(userId, cmd.getServiceOfferingName(), cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(), - localStorageRequired, offerHA, useVirtualNetwork, cmd.getTags()); + localStorageRequired, offerHA, useVirtualNetwork, cmd.getTags(),cmd.getDomainId()); } @Override - public ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean useVirtualNetwork, String tags) { + public ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean useVirtualNetwork, String tags, Long domainId) { String networkRateStr = _configDao.getValue("network.throttling.rate"); String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); int networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr)); int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); NetworkOffering.GuestIpType guestIpType = useVirtualNetwork ? NetworkOffering.GuestIpType.Virtualized : NetworkOffering.GuestIpType.DirectSingle; tags = cleanupTags(tags); - ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, multicastRate, offerHA, displayText, guestIpType, localStorageRequired, false, tags, false); + ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, multicastRate, offerHA, displayText, guestIpType, localStorageRequired, false, tags, false,domainId); if ((offering = _serviceOfferingDao.persist(offering)) != null) { saveConfigurationEvent(userId, null, EventTypes.EVENT_SERVICE_OFFERING_CREATE, "Successfully created new service offering with name: " + name + ".", "soId=" + offering.getId(), "name=" + name, "numCPUs=" + cpu, "ram=" + ramSize, "cpuSpeed=" + speed, diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 31df6ab1c93..5167de6d50a 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1592,17 +1592,70 @@ public class ManagementServerImpl implements ManagementServer { return _userAccountDao.search(sc, searchFilter); } + + private boolean isPermissible(Long accountDomainId, Long serviceOfferingDomainId){ + + if(accountDomainId == serviceOfferingDomainId) + return true; // account and service offering in same domain + + DomainVO domainRecord = _domainDao.findById(accountDomainId); + + if(domainRecord != null){ + while(true){ + if(domainRecord.getId() == serviceOfferingDomainId) + return true; + + //try and move on to the next domain + if(domainRecord.getParent() != null) + domainRecord = _domainDao.findById(domainRecord.getParent()); + else + break; + } + } + + return false; + } @Override public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException { - Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + + //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(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchCriteria sc = _offeringsDao.createSearchCriteria(); + Account account = UserContext.current().getAccount(); Object name = cmd.getServiceOfferingName(); Object id = cmd.getId(); Object keyword = cmd.getKeyword(); Long vmId = cmd.getVirtualMachineId(); - + Long domainId = cmd.getDomainId(); + + //Keeping this logic consistent with domain specific zones + //if a domainId is provided, we just return the so associated with this domain + if(domainId != null){ + if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){ + return _offeringsDao.findServiceOfferingByDomainId(domainId);//no perm check + }else{ + //check if the user's domain == so's domain || user's domain is a child of so's domain + if(isPermissible(account.getDomainId(), domainId)){ + //perm check succeeded + return _offeringsDao.findServiceOfferingByDomainId(domainId); + }else{ + throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account:"+account.getAccountName()+" does not fall in the same domain hierarchy as the service offering"); + } + } + } + + //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); + } + + //for root users, the existing flow if (keyword != null) { SearchCriteria ssc = _offeringsDao.createSearchCriteria(); ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -1610,8 +1663,6 @@ public class ManagementServerImpl implements ManagementServer { sc.addAnd("name", SearchCriteria.Op.SC, ssc); } else if (vmId != null) { - Account account = UserContext.current().getAccount(); - UserVmVO vmInstance = _userVmDao.findById(vmId); if ((vmInstance == null) || (vmInstance.getRemoved() != null)) { throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); @@ -1642,6 +1693,80 @@ 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){ + + //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 sol = new ArrayList(); + DomainVO domainRecord = _domainDao.findById(account.getDomainId()); + boolean includePublicOfferings = true; + if(domainRecord != null) + { + while(true){ + SearchCriteria sc = _offeringsDao.createSearchCriteria(); + + if (keyword != null) { + includePublicOfferings = false; + SearchCriteria ssc = _offeringsDao.createSearchCriteria(); + ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + + sc.addAnd("name", SearchCriteria.Op.SC, ssc); + } else if (vmId != null) { + includePublicOfferings = false; + UserVmVO vmInstance = _userVmDao.findById(vmId); + if ((vmInstance == null) || (vmInstance.getRemoved() != null)) { + throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); + } + if ((account != null) && !isAdmin(account.getType())) { + if (account.getId() != vmInstance.getAccountId()) { + throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account"); + } + } + + ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId()); + sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId()); + + // Only return offerings with the same Guest IP type and storage pool preference + sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType()); + sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage()); + } + + if (id != null) { + includePublicOfferings = false; + sc.addAnd("id", SearchCriteria.Op.EQ, id); + } + + if (name != null) { + includePublicOfferings = false; + sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); + } + sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); + + //for this domain + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainRecord.getId()); + + //search and add for this domain + sol.addAll(_offeringsDao.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) + sol.addAll(_offeringsDao.findPublicServiceOfferings()); + + return sol; + } @Override public List searchForClusters(ListClustersCmd cmd) { Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); diff --git a/server/src/com/cloud/service/ServiceOfferingVO.java b/server/src/com/cloud/service/ServiceOfferingVO.java index d4e48cfbe51..9591f6c8b57 100644 --- a/server/src/com/cloud/service/ServiceOfferingVO.java +++ b/server/src/com/cloud/service/ServiceOfferingVO.java @@ -72,6 +72,17 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.offerHA = offerHA; this.guestIpType = guestIpType; } + + public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, NetworkOffering.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, Long domainId) { + super(name, displayText, false, tags, recreatable, useLocalStorage, systemUse,false,domainId); + this.cpu = cpu; + this.ramSize = ramSize; + this.speed = speed; + this.rateMbps = rateMbps; + this.multicastRateMbps = multicastRateMbps; + this.offerHA = offerHA; + this.guestIpType = guestIpType; + } @Override public boolean getOfferHA() { @@ -145,5 +156,6 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering @Override public NetworkOffering.GuestIpType getGuestIpType() { return guestIpType; - } + } + } diff --git a/server/src/com/cloud/service/dao/ServiceOfferingDao.java b/server/src/com/cloud/service/dao/ServiceOfferingDao.java index 3eee286fadb..9e823c2a01c 100644 --- a/server/src/com/cloud/service/dao/ServiceOfferingDao.java +++ b/server/src/com/cloud/service/dao/ServiceOfferingDao.java @@ -18,6 +18,8 @@ package com.cloud.service.dao; +import java.util.List; + import com.cloud.service.ServiceOfferingVO; import com.cloud.utils.db.GenericDao; @@ -26,5 +28,7 @@ import com.cloud.utils.db.GenericDao; */ public interface ServiceOfferingDao extends GenericDao { ServiceOfferingVO findByName(String name); - ServiceOfferingVO persistSystemServiceOffering(ServiceOfferingVO vo); + ServiceOfferingVO persistSystemServiceOffering(ServiceOfferingVO vo); + List findPublicServiceOfferings(); + List findServiceOfferingByDomainId(Long domainId); } diff --git a/server/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/server/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java index 7d73f09161c..710c2c18520 100644 --- a/server/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java +++ b/server/src/com/cloud/service/dao/ServiceOfferingDaoImpl.java @@ -25,6 +25,7 @@ import javax.persistence.EntityExistsException; import org.apache.log4j.Logger; +import com.cloud.dc.DataCenterVO; import com.cloud.service.ServiceOfferingVO; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; @@ -35,7 +36,11 @@ import com.cloud.utils.db.SearchCriteria; public class ServiceOfferingDaoImpl extends GenericDaoBase implements ServiceOfferingDao { protected static final Logger s_logger = Logger.getLogger(ServiceOfferingDaoImpl.class); - protected final SearchBuilder UniqueNameSearch; + protected final SearchBuilder UniqueNameSearch; + protected final SearchBuilder ServiceOfferingsByDomainIdSearch; + protected final SearchBuilder ServiceOfferingsByKeywordSearch; + protected final SearchBuilder PublicServiceOfferingSearch; + protected ServiceOfferingDaoImpl() { super(); @@ -43,6 +48,20 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase findServiceOfferingByDomainId(Long domainId){ + SearchCriteria sc = ServiceOfferingsByDomainIdSearch.create(); + sc.setParameters("domainId", domainId); + return listBy(sc); + } + + @Override + public List findPublicServiceOfferings(){ + SearchCriteria sc = PublicServiceOfferingSearch.create(); + sc.setParameters("system", false); + return listBy(sc); } }