CLOUDSTACK-355: create DB view for ServiceOfferingResponse to fix count

for ListServiceOfferingsCmd.
This commit is contained in:
Min Chen 2013-01-21 15:07:35 -08:00
parent a4c413bc13
commit 6e40c33628
15 changed files with 685 additions and 265 deletions

View File

@ -110,13 +110,6 @@ public interface ManagementService {
*/
Pair<List<? extends Configuration>, Integer> searchForConfigurations(ListCfgsByCmd c);
/**
* Searches for Service Offerings by the specified search criteria Can search by: "name"
*
* @param cmd
* @return List of ServiceOfferings
*/
List<? extends ServiceOffering> searchForServiceOfferings(ListServiceOfferingsCmd cmd);
/**
* Searches for Clusters by the specified search criteria

View File

@ -16,9 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.user.offering;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.ApiConstants;
@ -29,7 +26,6 @@ import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import com.cloud.offering.ServiceOffering;
@APICommand(name = "listServiceOfferings", description="Lists all available service offerings.", responseObject=ServiceOfferingResponse.class)
public class ListServiceOfferingsCmd extends BaseListCmd {
@ -102,17 +98,10 @@ public class ListServiceOfferingsCmd extends BaseListCmd {
@Override
public void execute(){
List<? extends ServiceOffering> offerings = _mgr.searchForServiceOfferings(this);
ListResponse<ServiceOfferingResponse> response = new ListResponse<ServiceOfferingResponse>();
List<ServiceOfferingResponse> offeringResponses = new ArrayList<ServiceOfferingResponse>();
for (ServiceOffering offering : offerings) {
ServiceOfferingResponse offeringResponse = _responseGenerator.createServiceOfferingResponse(offering);
offeringResponse.setObjectName("serviceoffering");
offeringResponses.add(offeringResponse);
}
response.setResponses(offeringResponses);
ListResponse<ServiceOfferingResponse> response = _queryService.searchForServiceOfferings(this);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}

View File

@ -27,6 +27,7 @@ import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@ -47,6 +48,7 @@ import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@ -96,4 +98,6 @@ public interface QueryService {
public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd cmd);
public ListResponse<DiskOfferingResponse> searchForDiskOfferings(ListDiskOfferingsCmd cmd);
public ListResponse<ServiceOfferingResponse> searchForServiceOfferings(ListServiceOfferingsCmd cmd);
}

View File

@ -36,6 +36,7 @@ import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@ -52,6 +53,7 @@ import com.cloud.api.query.dao.ProjectInvitationJoinDao;
import com.cloud.api.query.dao.ProjectJoinDao;
import com.cloud.api.query.dao.ResourceTagJoinDao;
import com.cloud.api.query.dao.SecurityGroupJoinDao;
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
import com.cloud.api.query.dao.StoragePoolJoinDao;
import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
@ -68,6 +70,7 @@ import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
@ -338,6 +341,7 @@ public class ApiDBUtils {
private static AccountJoinDao _accountJoinDao;
private static AsyncJobJoinDao _jobJoinDao;
private static DiskOfferingJoinDao _diskOfferingJoinDao;
private static ServiceOfferingJoinDao _srvOfferingJoinDao;
private static PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
private static PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@ -443,6 +447,7 @@ public class ApiDBUtils {
_snapshotPolicyDao = locator.getDao(SnapshotPolicyDao.class);
_asyncJobDao = locator.getDao(AsyncJobDao.class);
_diskOfferingJoinDao = locator.getDao(DiskOfferingJoinDao.class);
_srvOfferingJoinDao = locator.getDao(ServiceOfferingJoinDao.class);
// Note: stats collector should already have been initialized by this time, otherwise a null instance is returned
_statsCollector = StatsCollector.getInstance();
@ -1413,4 +1418,12 @@ public class ApiDBUtils {
public static DiskOfferingJoinVO newDiskOfferingView(DiskOffering offering){
return _diskOfferingJoinDao.newDiskOfferingView(offering);
}
public static ServiceOfferingResponse newServiceOfferingResponse(ServiceOfferingJoinVO offering) {
return _srvOfferingJoinDao.newServiceOfferingResponse(offering);
}
public static ServiceOfferingJoinVO newServiceOfferingView(ServiceOffering offering){
return _srvOfferingJoinDao.newServiceOfferingView(offering);
}
}

View File

@ -54,6 +54,7 @@ import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
@ -342,33 +343,8 @@ public class ApiResponseHelper implements ResponseGenerator {
@Override
public ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering) {
ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
offeringResponse.setId(offering.getUuid());
offeringResponse.setName(offering.getName());
offeringResponse.setIsSystemOffering(offering.getSystemUse());
offeringResponse.setDefaultUse(offering.getDefaultUse());
offeringResponse.setSystemVmType(offering.getSystemVmType());
offeringResponse.setDisplayText(offering.getDisplayText());
offeringResponse.setCpuNumber(offering.getCpu());
offeringResponse.setCpuSpeed(offering.getSpeed());
offeringResponse.setMemory(offering.getRamSize());
offeringResponse.setCreated(offering.getCreated());
offeringResponse.setStorageType(offering.getUseLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared.toString());
offeringResponse.setOfferHa(offering.getOfferHA());
offeringResponse.setLimitCpuUse(offering.getLimitCpuUse());
offeringResponse.setTags(offering.getTags());
if (offering.getDomainId() != null) {
Domain domain = ApiDBUtils.findDomainById(offering.getDomainId());
if (domain != null) {
offeringResponse.setDomain(domain.getName());
offeringResponse.setDomainId(domain.getUuid());
}
}
offeringResponse.setNetworkRate(offering.getRateMbps());
offeringResponse.setHostTag(offering.getHostTag());
offeringResponse.setObjectName("serviceoffering");
return offeringResponse;
ServiceOfferingJoinVO vOffering = ApiDBUtils.newServiceOfferingView(offering);
return ApiDBUtils.newServiceOfferingResponse(vOffering);
}
@Override

View File

@ -96,6 +96,7 @@ import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@ -516,6 +517,7 @@ public class ApiServer implements HttpRequestHandler {
&& !(cmdObj instanceof ListAccountsCmd)
&& !(cmdObj instanceof ListStoragePoolsCmd)
&& !(cmdObj instanceof ListDiskOfferingsCmd)
&& !(cmdObj instanceof ListServiceOfferingsCmd)
) {
buildAsyncListResponse((BaseListCmd) cmdObj, caller);
}

View File

@ -33,6 +33,7 @@ import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@ -53,6 +54,7 @@ import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@ -71,6 +73,7 @@ import com.cloud.api.query.dao.ProjectInvitationJoinDao;
import com.cloud.api.query.dao.ProjectJoinDao;
import com.cloud.api.query.dao.ResourceTagJoinDao;
import com.cloud.api.query.dao.SecurityGroupJoinDao;
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
import com.cloud.api.query.dao.StoragePoolJoinDao;
import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
@ -87,6 +90,7 @@ import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
@ -110,6 +114,8 @@ import com.cloud.projects.ProjectManager;
import com.cloud.projects.dao.ProjectAccountDao;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.server.Criteria;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
@ -221,6 +227,12 @@ public class QueryManagerImpl implements QueryService, Manager {
@Inject
private DiskOfferingJoinDao _diskOfferingJoinDao;
@Inject
private ServiceOfferingJoinDao _srvOfferingJoinDao;
@Inject
private ServiceOfferingDao _srvOfferingDao;
@Inject
private HighAvailabilityManager _haMgr;
@ -2033,6 +2045,148 @@ public class QueryManagerImpl implements QueryService, Manager {
}
@Override
public ListResponse<ServiceOfferingResponse> searchForServiceOfferings(ListServiceOfferingsCmd cmd) {
Pair<List<ServiceOfferingJoinVO>, Integer> result = searchForServiceOfferingsInternal(cmd);
ListResponse<ServiceOfferingResponse> response = new ListResponse<ServiceOfferingResponse>();
List<ServiceOfferingResponse> offeringResponses = ViewResponseHelper.createServiceOfferingResponse(result.first().toArray(new ServiceOfferingJoinVO[result.first().size()]));
response.setResponses(offeringResponses, result.second());
return response;
}
private Pair<List<ServiceOfferingJoinVO>, Integer> searchForServiceOfferingsInternal(ListServiceOfferingsCmd 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
Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm"));
isAscending = (isAscending == null ? true : isAscending);
Filter searchFilter = new Filter(ServiceOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
Account caller = UserContext.current().getCaller();
Object name = cmd.getServiceOfferingName();
Object id = cmd.getId();
Object keyword = cmd.getKeyword();
Long vmId = cmd.getVirtualMachineId();
Long domainId = cmd.getDomainId();
Boolean isSystem = cmd.getIsSystem();
String vmTypeStr = cmd.getSystemVmType();
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && isSystem) {
throw new InvalidParameterValueException("Only ROOT admins can access system's offering");
}
// 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 && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
// check if the user's domain == so's domain || user's domain is a
// child of so's domain
if (!isPermissible(caller.getDomainId(), domainId)) {
throw new PermissionDeniedException("The account:" + caller.getAccountName()
+ " does not fall in the same domain hierarchy as the service offering");
}
}
boolean includePublicOfferings = false;
if ((caller.getType() == Account.ACCOUNT_TYPE_NORMAL || caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
|| caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
// For non-root users
if (isSystem) {
throw new InvalidParameterValueException("Only root admins can access system's offering");
}
// find all domain Id up to root domain for this account
List<Long> domainIds = new ArrayList<Long>();
DomainVO domainRecord = _domainDao.findById(caller.getDomainId());
if ( domainRecord == null ){
s_logger.error("Could not find the domainId for account:" + caller.getAccountName());
throw new CloudAuthenticationException("Could not find the domainId for account:" + caller.getAccountName());
}
domainIds.add(domainRecord.getId());
while (domainRecord.getParent() != null ){
domainRecord = _domainDao.findById(domainRecord.getParent());
domainIds.add(domainRecord.getId());
}
sc.addAnd("domainIdIn", SearchCriteria.Op.IN, domainIds);
// include also public offering if no keyword, name and id specified
if ( keyword == null && name == null && id == null ){
includePublicOfferings = true;
}
}
else {
// for root users
if (caller.getDomainId() != 1 && isSystem) { // NON ROOT admin
throw new InvalidParameterValueException("Non ROOT admins cannot access system's offering");
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
}
if (keyword != null) {
SearchCriteria<ServiceOfferingJoinVO> ssc = _srvOfferingJoinDao.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) {
UserVmVO vmInstance = _userVmDao.findById(vmId);
if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a virtual machine with specified id");
ex.addProxyObject(vmInstance, vmId, "vmId");
throw ex;
}
_accountMgr.checkAccess(caller, null, true, vmInstance);
ServiceOfferingVO offering = _srvOfferingDao.findByIdIncludingRemoved(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) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (isSystem != null) {
sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (vmTypeStr != null) {
sc.addAnd("vm_type", SearchCriteria.Op.EQ, vmTypeStr);
}
if (includePublicOfferings){
SearchCriteria<ServiceOfferingJoinVO> spc = _srvOfferingJoinDao.createSearchCriteria();
spc.addAnd("domainId", SearchCriteria.Op.NULL);
spc.addAnd("systemUse", SearchCriteria.Op.EQ, false);
sc.addOr("systemUse", SearchCriteria.Op.SC, spc);
}
return _srvOfferingJoinDao.searchAndCount(sc, searchFilter);
}
// This method is used for permissions check for both disk and service
// offerings
private boolean isPermissible(Long accountDomainId, Long offeringDomainId) {

View File

@ -35,6 +35,7 @@ import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@ -54,6 +55,7 @@ import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
@ -284,4 +286,12 @@ public class ViewResponseHelper {
}
return respList;
}
public static List<ServiceOfferingResponse> createServiceOfferingResponse(ServiceOfferingJoinVO... offerings) {
List<ServiceOfferingResponse> respList = new ArrayList<ServiceOfferingResponse>();
for (ServiceOfferingJoinVO vt : offerings){
respList.add(ApiDBUtils.newServiceOfferingResponse(vt));
}
return respList;
}
}

View File

@ -0,0 +1,30 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.api.query.dao;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.offering.ServiceOffering;
import com.cloud.utils.db.GenericDao;
public interface ServiceOfferingJoinDao extends GenericDao<ServiceOfferingJoinVO, Long> {
ServiceOfferingResponse newServiceOfferingResponse(ServiceOfferingJoinVO offering);
ServiceOfferingJoinVO newServiceOfferingView(ServiceOffering offering);
}

View File

@ -0,0 +1,91 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.api.query.dao;
import java.util.List;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import com.cloud.offering.ServiceOffering;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Local(value={ServiceOfferingJoinDao.class})
public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJoinVO, Long> implements ServiceOfferingJoinDao {
public static final Logger s_logger = Logger.getLogger(ServiceOfferingJoinDaoImpl.class);
private SearchBuilder<ServiceOfferingJoinVO> sofIdSearch;
protected ServiceOfferingJoinDaoImpl() {
sofIdSearch = createSearchBuilder();
sofIdSearch.and("id", sofIdSearch.entity().getId(), SearchCriteria.Op.EQ);
sofIdSearch.done();
this._count = "select count(distinct id) from service_offering_view WHERE ";
}
@Override
public ServiceOfferingResponse newServiceOfferingResponse(ServiceOfferingJoinVO offering) {
ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
offeringResponse.setId(offering.getUuid());
offeringResponse.setName(offering.getName());
offeringResponse.setIsSystemOffering(offering.isSystemUse());
offeringResponse.setDefaultUse(offering.isDefaultUse());
offeringResponse.setSystemVmType(offering.getSystemVmType());
offeringResponse.setDisplayText(offering.getDisplayText());
offeringResponse.setCpuNumber(offering.getCpu());
offeringResponse.setCpuSpeed(offering.getSpeed());
offeringResponse.setMemory(offering.getRamSize());
offeringResponse.setCreated(offering.getCreated());
offeringResponse.setStorageType(offering.isUseLocalStorage() ? ServiceOffering.StorageType.local.toString()
: ServiceOffering.StorageType.shared.toString());
offeringResponse.setOfferHa(offering.isOfferHA());
offeringResponse.setLimitCpuUse(offering.isLimitCpuUse());
offeringResponse.setTags(offering.getTags());
offeringResponse.setDomain(offering.getDomainName());
offeringResponse.setDomainId(offering.getDomainUuid());
offeringResponse.setNetworkRate(offering.getRateMbps());
offeringResponse.setHostTag(offering.getHostTag());
offeringResponse.setObjectName("serviceoffering");
return offeringResponse;
}
@Override
public ServiceOfferingJoinVO newServiceOfferingView(ServiceOffering offering) {
SearchCriteria<ServiceOfferingJoinVO> sc = sofIdSearch.create();
sc.setParameters("id", offering.getId());
List<ServiceOfferingJoinVO> offerings = searchIncludingRemoved(sc, null, null, false);
assert offerings != null && offerings.size() == 1 : "No service offering found for offering id " + offering.getId();
return offerings.get(0);
}
}

View File

@ -0,0 +1,311 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.api.query.vo;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@Entity
@Table(name="service_offering_view")
public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentity, Identity {
@Id
@Column(name="id", updatable=false, nullable = false)
private long id;
@Column(name="uuid")
private String uuid;
@Column(name="name")
private String name;
@Column(name="display_text")
private String displayText;
@Column(name="tags", length=4096)
String tags;
@Column(name="use_local_storage")
private boolean useLocalStorage;
@Column(name="system_use")
private boolean systemUse;
@Column(name="cpu")
private int cpu;
@Column(name="speed")
private int speed;
@Column(name="ram_size")
private int ramSize;
@Column(name="nw_rate")
private Integer rateMbps;
@Column(name="mc_rate")
private Integer multicastRateMbps;
@Column(name="ha_enabled")
private boolean offerHA;
@Column(name="limit_cpu_use")
private boolean limitCpuUse;
@Column(name="host_tag")
private String hostTag;
@Column(name="default_use")
private boolean default_use;
@Column(name="vm_type")
private String vm_type;
@Column(name="sort_key")
int sortKey;
@Column(name=GenericDao.CREATED_COLUMN)
private Date created;
@Column(name=GenericDao.REMOVED_COLUMN)
private Date removed;
@Column(name="domain_id")
private long domainId;
@Column(name="domain_uuid")
private String domainUuid;
@Column(name="domain_name")
private String domainName = null;
@Column(name="domain_path")
private String domainPath = null;
public ServiceOfferingJoinVO() {
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDisplayText() {
return displayText;
}
public void setDisplayText(String displayText) {
this.displayText = displayText;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public boolean isUseLocalStorage() {
return useLocalStorage;
}
public void setUseLocalStorage(boolean useLocalStorage) {
this.useLocalStorage = useLocalStorage;
}
public boolean isSystemUse() {
return systemUse;
}
public void setSystemUse(boolean systemUse) {
this.systemUse = systemUse;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getRemoved() {
return removed;
}
public void setRemoved(Date removed) {
this.removed = removed;
}
public long getDomainId() {
return domainId;
}
public void setDomainId(long domainId) {
this.domainId = domainId;
}
public String getDomainUuid() {
return domainUuid;
}
public void setDomainUuid(String domainUuid) {
this.domainUuid = domainUuid;
}
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public String getDomainPath() {
return domainPath;
}
public void setDomainPath(String domainPath) {
this.domainPath = domainPath;
}
public int getSortKey() {
return sortKey;
}
public void setSortKey(int sortKey) {
this.sortKey = sortKey;
}
public int getCpu() {
return cpu;
}
public void setCpu(int cpu) {
this.cpu = cpu;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getRamSize() {
return ramSize;
}
public void setRamSize(int ramSize) {
this.ramSize = ramSize;
}
public Integer getRateMbps() {
return rateMbps;
}
public void setRateMbps(Integer rateMbps) {
this.rateMbps = rateMbps;
}
public Integer getMulticastRateMbps() {
return multicastRateMbps;
}
public void setMulticastRateMbps(Integer multicastRateMbps) {
this.multicastRateMbps = multicastRateMbps;
}
public boolean isOfferHA() {
return offerHA;
}
public void setOfferHA(boolean offerHA) {
this.offerHA = offerHA;
}
public boolean isLimitCpuUse() {
return limitCpuUse;
}
public void setLimitCpuUse(boolean limitCpuUse) {
this.limitCpuUse = limitCpuUse;
}
public String getHostTag() {
return hostTag;
}
public void setHostTag(String hostTag) {
this.hostTag = hostTag;
}
public boolean isDefaultUse() {
return default_use;
}
public void setDefaultUse(boolean default_use) {
this.default_use = default_use;
}
public String getSystemVmType() {
return vm_type;
}
public void setSystemVmType(String vm_type) {
this.vm_type = vm_type;
}
}

View File

@ -28,6 +28,7 @@ import com.cloud.api.query.QueryManagerImpl;
import com.cloud.api.query.dao.AccountJoinDaoImpl;
import com.cloud.api.query.dao.AsyncJobJoinDaoImpl;
import com.cloud.api.query.dao.DiskOfferingJoinDaoImpl;
import com.cloud.api.query.dao.ServiceOfferingJoinDaoImpl;
import com.cloud.api.query.dao.DomainRouterJoinDaoImpl;
import com.cloud.api.query.dao.InstanceGroupJoinDaoImpl;
import com.cloud.api.query.dao.ProjectAccountJoinDaoImpl;
@ -394,6 +395,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
addDao("AsyncJobJoinDao", AsyncJobJoinDaoImpl.class);
addDao("StoragePoolJoinDao", StoragePoolJoinDaoImpl.class);
addDao("DiskOfferingJoinDao", DiskOfferingJoinDaoImpl.class);
addDao("ServiceOfferingJoinDao", ServiceOfferingJoinDaoImpl.class);
}
@Override

View File

@ -54,7 +54,6 @@ import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd;
import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd;
import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
import org.apache.cloudstack.api.command.user.iso.UpdateIsoCmd;
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
@ -132,7 +131,6 @@ import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
@ -607,221 +605,6 @@ public class ManagementServerImpl implements ManagementServer {
return cal.getTime();
}
// This method is used for permissions check for both disk and service
// offerings
private boolean isPermissible(Long accountDomainId, Long offeringDomainId) {
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() == offeringDomainId) {
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<ServiceOfferingVO> searchForServiceOfferings(ListServiceOfferingsCmd 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
Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm"));
isAscending = (isAscending == null ? true : isAscending);
Filter searchFilter = new Filter(ServiceOfferingVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<ServiceOfferingVO> sc = _offeringsDao.createSearchCriteria();
Account caller = UserContext.current().getCaller();
Object name = cmd.getServiceOfferingName();
Object id = cmd.getId();
Object keyword = cmd.getKeyword();
Long vmId = cmd.getVirtualMachineId();
Long domainId = cmd.getDomainId();
Boolean isSystem = cmd.getIsSystem();
String vmTypeStr = cmd.getSystemVmType();
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && isSystem) {
throw new InvalidParameterValueException("Only ROOT admins can access system's offering");
}
// 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 && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
// check if the user's domain == so's domain || user's domain is a
// child of so's domain
if (!isPermissible(caller.getDomainId(), domainId)) {
throw new PermissionDeniedException("The account:" + caller.getAccountName()
+ " does not fall in the same domain hierarchy as the service offering");
}
}
// For non-root users
if ((caller.getType() == Account.ACCOUNT_TYPE_NORMAL || caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
|| caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
if (isSystem) {
throw new InvalidParameterValueException("Only root admins can access system's offering");
}
return searchServiceOfferingsInternal(caller, name, id, vmId, keyword, searchFilter);
}
// for root users, the existing flow
if (caller.getDomainId() != 1 && isSystem) { // NON ROOT admin
throw new InvalidParameterValueException("Non ROOT admins cannot access system's offering");
}
if (keyword != null) {
SearchCriteria<ServiceOfferingVO> 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) {
UserVmVO vmInstance = _userVmDao.findById(vmId);
if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a virtual machine with specified id");
ex.addProxyObject(vmInstance, vmId, "vmId");
throw ex;
}
_accountMgr.checkAccess(caller, null, true, vmInstance);
ServiceOfferingVO offering = _offeringsDao.findByIdIncludingRemoved(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) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (isSystem != null) {
sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if (vmTypeStr != null) {
sc.addAnd("vm_type", SearchCriteria.Op.EQ, vmTypeStr);
}
sc.addAnd("removed", SearchCriteria.Op.NULL);
return _offeringsDao.search(sc, searchFilter);
}
private List<ServiceOfferingVO> searchServiceOfferingsInternal(Account caller, 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<ServiceOfferingVO> sol = new ArrayList<ServiceOfferingVO>();
DomainVO domainRecord = _domainDao.findById(caller.getDomainId());
boolean includePublicOfferings = true;
if (domainRecord != null) {
while (true) {
if (id != null) {
ServiceOfferingVO so = _offeringsDao.findById((Long) id);
if (so != null) {
sol.add(so);
}
return sol;
}
SearchCriteria<ServiceOfferingVO> sc = _offeringsDao.createSearchCriteria();
if (keyword != null) {
includePublicOfferings = false;
SearchCriteria<ServiceOfferingVO> 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) {
UserVmVO vmInstance = _userVmDao.findById(vmId);
if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
ex.addProxyObject(vmInstance, vmId, "vmId");
throw ex;
}
_accountMgr.checkAccess(caller, null, false, vmInstance);
ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
}
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());
// don't return removed service offerings
sc.addAnd("removed", SearchCriteria.Op.NULL);
// 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:" + caller.getAccountName());
throw new CloudAuthenticationException("Could not find the domainId for account:" + caller.getAccountName());
}
// add all the public offerings to the sol list before returning
if (includePublicOfferings) {
sol.addAll(_offeringsDao.findPublicServiceOfferings());
}
return sol;
}
@Override
public List<? extends Cluster> searchForClusters(long zoneId, Long startIndex, Long pageSizeVal, String hypervisorType) {

View File

@ -841,4 +841,35 @@ domain.uuid domain_uuid,
domain.name domain_name,
domain.path domain_path
from disk_offering
left join domain on disk_offering.domain_id=domain.id;
left join domain on disk_offering.domain_id=domain.id;
DROP VIEW IF EXISTS `cloud`.`service_offering_view`;
CREATE VIEW service_offering_view AS
select
service_offering.id,
disk_offering.uuid,
disk_offering.name,
disk_offering.display_text,
disk_offering.created,
disk_offering.tags,
disk_offering.removed,
disk_offering.use_local_storage,
disk_offering.system_use,
service_offering.cpu,
service_offering.speed,
service_offering.ram_size,
service_offering.nw_rate,
service_offering.mc_rate,
service_offering.ha_enabled,
service_offering.limit_cpu_use,
service_offering.host_tag,
service_offering.default_use,
service_offering.vm_type,
service_offering.sort_key,
domain.id domain_id,
domain.uuid domain_uuid,
domain.name domain_name,
domain.path domain_path
from service_offering
inner join disk_offering on service_offering.id = disk_offering.id
left join domain on disk_offering.domain_id=domain.id;

View File

@ -968,5 +968,36 @@ domain.path domain_path
from disk_offering
left join domain on disk_offering.domain_id=domain.id;
DROP VIEW IF EXISTS `cloud`.`service_offering_view`;
CREATE VIEW service_offering_view AS
select
service_offering.id,
disk_offering.uuid,
disk_offering.name,
disk_offering.display_text,
disk_offering.created,
disk_offering.tags,
disk_offering.removed,
disk_offering.use_local_storage,
disk_offering.system_use,
service_offering.cpu,
service_offering.speed,
service_offering.ram_size,
service_offering.nw_rate,
service_offering.mc_rate,
service_offering.ha_enabled,
service_offering.limit_cpu_use,
service_offering.host_tag,
service_offering.default_use,
service_offering.vm_type,
service_offering.sort_key,
domain.id domain_id,
domain.uuid domain_uuid,
domain.name domain_name,
domain.path domain_path
from service_offering
inner join disk_offering on service_offering.id = disk_offering.id
left join domain on disk_offering.domain_id=domain.id;
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'direct.agent.pool.size', '500', 'Default size for DirectAgentPool');