Add service offering category management functionality

- Introduced new API commands for creating, updating, and deleting service offering categories.
- Added support for associating service offerings with categories.
- Updated database schema to include service offering categories.
- Enhanced existing service offering commands to handle category IDs.
This commit is contained in:
Landry JUGE 2025-11-26 19:23:28 +01:00
parent 8171d9568c
commit e1e902db45
29 changed files with 938 additions and 6 deletions

View File

@ -72,6 +72,7 @@ import com.cloud.network.Networks.TrafficType;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.offering.ServiceOfferingCategory;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
@ -127,6 +128,30 @@ public interface ConfigurationService {
*/
List<Long> getServiceOfferingZones(Long serviceOfferingId);
/**
* Creates a service offering category
*
* @param cmd - the command specifying name and sort key
* @return the newly created service offering category
*/
ServiceOfferingCategory createServiceOfferingCategory(org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd cmd);
/**
* Deletes a service offering category
*
* @param cmd - the command specifying category id
* @return true if successful, false otherwise
*/
boolean deleteServiceOfferingCategory(org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd cmd);
/**
* Updates a service offering category
*
* @param cmd - the command specifying category id, name, and/or sort key
* @return updated service offering category
*/
ServiceOfferingCategory updateServiceOfferingCategory(org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd cmd);
/**
* Updates a disk offering
*

View File

@ -146,4 +146,6 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
Long getVgpuProfileId();
Integer getGpuCount();
long getCategoryId();
}

View File

@ -0,0 +1,31 @@
// 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.offering;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface ServiceOfferingCategory extends Identity, InternalIdentity {
String getName();
void setName(String name);
int getSortKey();
void setSortKey(int sortKey);
}

View File

@ -529,6 +529,8 @@ public class ApiConstants {
public static final String SENT_BYTES = "sentbytes";
public static final String SERIAL = "serial";
public static final String SERVICE_IP = "serviceip";
public static final String SERVICE_OFFERING_CATEGORY_ID = "serviceofferingcategoryid";
public static final String SERVICE_OFFERING_CATEGORY_NAME = "serviceofferingcategoryname";
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
public static final String SERVICE_OFFERING_NAME = "serviceofferingname";
public static final String SESSIONKEY = "sessionkey";

View File

@ -267,6 +267,8 @@ public interface ResponseGenerator {
ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering);
org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse createServiceOfferingCategoryResponse(com.cloud.offering.ServiceOfferingCategory category);
ConfigurationResponse createConfigurationResponse(Configuration cfg);
ConfigurationGroupResponse createConfigurationGroupResponse(ConfigurationGroup cfgGroup);

View File

@ -0,0 +1,85 @@
// 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 org.apache.cloudstack.api.command.admin.offering;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
import com.cloud.offering.ServiceOfferingCategory;
import com.cloud.user.Account;
@APICommand(name = "createServiceOfferingCategory",
description = "Creates a service offering category.",
responseObject = ServiceOfferingCategoryResponse.class,
since = "4.23.0",
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false)
public class CreateServiceOfferingCategoryCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME,
type = CommandType.STRING,
required = true,
description = "the name of the service offering category")
private String name;
@Parameter(name = ApiConstants.SORT_KEY,
type = CommandType.INTEGER,
description = "sort key of the service offering category, default is 0")
private Integer sortKey;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getName() {
return name;
}
public Integer getSortKey() {
return sortKey;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
ServiceOfferingCategory result = _configService.createServiceOfferingCategory(this);
if (result != null) {
ServiceOfferingCategoryResponse response = _responseGenerator.createServiceOfferingCategoryResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create service offering category");
}
}
@Override
public long getEntityOwnerId() {
return Account.Type.ADMIN.ordinal();
}
}

View File

@ -289,6 +289,14 @@ public class CreateServiceOfferingCmd extends BaseCmd {
since = "4.21.0")
private Map externalDetails;
@Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID,
type = CommandType.UUID,
entityType = org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse.class,
required = false,
description = "the ID of the service offering category to associate with this offering",
since = "4.23")
private Long serviceOfferingCategoryId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -561,6 +569,10 @@ public class CreateServiceOfferingCmd extends BaseCmd {
return Boolean.TRUE.equals(gpuDisplay);
}
public Long getServiceOfferingCategoryId() {
return serviceOfferingCategoryId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,76 @@
// 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 org.apache.cloudstack.api.command.admin.offering;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import com.cloud.user.Account;
@APICommand(name = "deleteServiceOfferingCategory",
description = "Deletes a service offering category.",
responseObject = SuccessResponse.class,
since = "4.23.0",
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false)
public class DeleteServiceOfferingCategoryCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
entityType = ServiceOfferingCategoryResponse.class,
required = true,
description = "the ID of the service offering category")
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
boolean result = _configService.deleteServiceOfferingCategory(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete service offering category");
}
}
@Override
public long getEntityOwnerId() {
return Account.Type.ADMIN.ordinal();
}
}

View File

@ -0,0 +1,71 @@
// 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 org.apache.cloudstack.api.command.admin.offering;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
@APICommand(name = "listServiceOfferingCategories",
description = "Lists service offering categories.",
responseObject = ServiceOfferingCategoryResponse.class,
since = "4.23.0",
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false)
public class ListServiceOfferingCategoriesCmd extends BaseListCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
entityType = ServiceOfferingCategoryResponse.class,
description = "ID of the service offering category")
private Long id;
@Parameter(name = ApiConstants.NAME,
type = CommandType.STRING,
description = "name of the service offering category")
private String name;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public String getName() {
return name;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
ListResponse<ServiceOfferingCategoryResponse> response = _queryService.listServiceOfferingCategories(this);
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -0,0 +1,95 @@
// 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 org.apache.cloudstack.api.command.admin.offering;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
import com.cloud.offering.ServiceOfferingCategory;
import com.cloud.user.Account;
@APICommand(name = "updateServiceOfferingCategory",
description = "Updates a service offering category",
responseObject = ServiceOfferingCategoryResponse.class,
since = "4.23.0",
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false)
public class UpdateServiceOfferingCategoryCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
entityType = ServiceOfferingCategoryResponse.class,
required = true,
description = "the ID of the service offering category")
private Long id;
@Parameter(name = ApiConstants.NAME,
type = CommandType.STRING,
description = "the name of the service offering category")
private String name;
@Parameter(name = ApiConstants.SORT_KEY,
type = CommandType.INTEGER,
description = "sort key of the service offering category")
private Integer sortKey;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public String getName() {
return name;
}
public Integer getSortKey() {
return sortKey;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute() {
ServiceOfferingCategory result = _configService.updateServiceOfferingCategory(this);
if (result != null) {
ServiceOfferingCategoryResponse response = _responseGenerator.createServiceOfferingCategoryResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update service offering category");
}
}
}

View File

@ -109,6 +109,14 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
since = "4.22.0")
protected Boolean cleanupExternalDetails;
@Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID,
type = CommandType.UUID,
entityType = org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse.class,
required = false,
description = "the ID of the service offering category to associate",
since = "4.23")
private Long categoryId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -217,6 +225,8 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
return Boolean.TRUE.equals(cleanupExternalDetails);
}
public Long getCategoryId() { return categoryId; }
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -249,4 +259,4 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update service offering");
}
}
}
}

View File

@ -23,6 +23,7 @@ import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@ -124,6 +125,13 @@ public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesC
since = "4.21.0")
private Boolean gpuEnabled;
@Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID,
type = CommandType.UUID,
entityType = ServiceOfferingCategoryResponse .class,
description = "the ID of the service offering category",
since = "4.23.0")
private Long categoryId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -193,6 +201,10 @@ public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesC
return gpuEnabled;
}
public Long getCategoryId() {
return categoryId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,65 @@
// 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 org.apache.cloudstack.api.response;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.offering.ServiceOfferingCategory;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = ServiceOfferingCategory.class)
public class ServiceOfferingCategoryResponse extends BaseResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the service offering category")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "the name of the service offering category")
private String name;
@SerializedName(ApiConstants.SORT_KEY)
@Param(description = "sort key of the service offering category")
private Integer sortKey;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSortKey() {
return sortKey;
}
public void setSortKey(Integer sortKey) {
this.sortKey = sortKey;
}
}

View File

@ -286,6 +286,14 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "Action to be taken once lease is over", since = "4.21.0")
private String leaseExpiryAction;
@SerializedName("categoryid")
@Param(description = "the ID of the service offering category", since = "4.23")
private String categoryId;
@SerializedName("category")
@Param(description = "the name of the service offering category", since = "4.23")
private String categoryName;
public ServiceOfferingResponse() {
}
@ -707,4 +715,9 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
public void setPurgeResources(Boolean purgeResources) {
this.purgeResources = purgeResources;
}
public String getCategoryId() { return categoryId; }
public void setCategoryId(String categoryId) { this.categoryId = categoryId; }
public String getCategoryName() { return categoryName; }
public void setCategoryName(String categoryName) { this.categoryName = categoryName; }
}

View File

@ -185,6 +185,8 @@ public interface QueryService {
ListResponse<ServiceOfferingResponse> searchForServiceOfferings(ListServiceOfferingsCmd cmd);
ListResponse<org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse> listServiceOfferingCategories(org.apache.cloudstack.api.command.admin.offering.ListServiceOfferingCategoriesCmd cmd);
ListResponse<ZoneResponse> listDataCenters(ListZonesCmd cmd);
ListResponse<TemplateResponse> listTemplates(ListTemplatesCmd cmd);

View File

@ -0,0 +1,100 @@
// 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.service;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.offering.ServiceOfferingCategory;
@Entity
@Table(name = "service_offering_category")
public class ServiceOfferingCategoryVO implements ServiceOfferingCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "uuid")
private String uuid;
@Column(name = "sort_key")
private int sortKey;
public ServiceOfferingCategoryVO() {
this.uuid = UUID.randomUUID().toString();
}
public ServiceOfferingCategoryVO(String name) {
this.name = name;
this.uuid = UUID.randomUUID().toString();
}
public ServiceOfferingCategoryVO(String name, int sortKey) {
this.name = name;
this.sortKey = sortKey;
this.uuid = UUID.randomUUID().toString();
}
@Override
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
@Override
public int getSortKey() {
return sortKey;
}
@Override
public void setSortKey(int sortKey) {
this.sortKey = sortKey;
}
}

View File

@ -133,6 +133,9 @@ public class ServiceOfferingVO implements ServiceOffering {
@Column(name = "gpu_display")
private Boolean gpuDisplay;
@Column(name = "category_id")
private long categoryId = 1L; // Default category
// This is a delayed load value. If the value is null,
// then this field has not been loaded yet.
// Call service offering dao to load it.
@ -482,4 +485,13 @@ public class ServiceOfferingVO implements ServiceOffering {
public void setGpuDisplay(Boolean gpuDisplay) {
this.gpuDisplay = gpuDisplay;
}
@Override
public long getCategoryId() {
return categoryId;
}
public void setCategoryId(long categoryId) {
this.categoryId = categoryId;
}
}

View File

@ -0,0 +1,29 @@
// 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.service.dao;
import java.util.List;
import com.cloud.service.ServiceOfferingCategoryVO;
import com.cloud.utils.db.GenericDao;
public interface ServiceOfferingCategoryDao extends GenericDao<ServiceOfferingCategoryVO, Long> {
ServiceOfferingCategoryVO findByName(String name);
List<ServiceOfferingCategoryVO> listAll();
}

View File

@ -0,0 +1,52 @@
// 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.service.dao;
import java.util.List;
import org.springframework.stereotype.Component;
import com.cloud.service.ServiceOfferingCategoryVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.DB;
@Component
@DB()
public class ServiceOfferingCategoryDaoImpl extends GenericDaoBase<ServiceOfferingCategoryVO, Long> implements ServiceOfferingCategoryDao {
protected final SearchBuilder<ServiceOfferingCategoryVO> NameSearch;
protected ServiceOfferingCategoryDaoImpl() {
NameSearch = createSearchBuilder();
NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ);
NameSearch.done();
}
@Override
public ServiceOfferingCategoryVO findByName(String name) {
SearchCriteria<ServiceOfferingCategoryVO> sc = NameSearch.create();
sc.setParameters("name", name);
return findOneBy(sc);
}
@Override
public List<ServiceOfferingCategoryVO> listAll() {
return listAll(null);
}
}

View File

@ -56,6 +56,7 @@
<bean id="roleDaoImpl" class="org.apache.cloudstack.acl.dao.RoleDaoImpl" />
<bean id="serviceOfferingDaoImpl" class="com.cloud.service.dao.ServiceOfferingDaoImpl" />
<bean id="serviceOfferingDetailsDaoImpl" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl"/>
<bean id="serviceOfferingCategoryDaoImpl" class="com.cloud.service.dao.ServiceOfferingCategoryDaoImpl" />
<bean id="snapshotDaoImpl" class="com.cloud.storage.dao.SnapshotDaoImpl" />
<bean id="snapshotZoneDaoImpl" class="com.cloud.storage.dao.SnapshotZoneDaoImpl" />
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDaoImpl" />

View File

@ -18,3 +18,17 @@
--;
-- Schema upgrade from 4.22.0.0 to 4.23.0.0
--;
CREATE TABLE IF NOT EXISTS `cloud`.`service_offering_category` (
`id` bigint unsigned NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`uuid` varchar(40),
`sort_key` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
CONSTRAINT `uc_service_offering_category__uuid` UNIQUE (`uuid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `category_id` bigint unsigned NOT NULL DEFAULT 1;
ALTER TABLE `cloud`.`service_offering` ADD CONSTRAINT `fk_service_offering__category_id` FOREIGN KEY (`category_id`) REFERENCES `cloud`.`service_offering_category` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO `cloud`.`service_offering_category` (id, name, uuid) VALUES (1, 'Default', UUID());

View File

@ -85,6 +85,7 @@ SELECT
`vgpu_profile`.`max_resolution_y` AS `vgpu_profile_max_resolution_y`,
`service_offering`.`gpu_count` AS `gpu_count`,
`service_offering`.`gpu_display` AS `gpu_display`,
`service_offering`.`category_id` AS `category_id`,
GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id,
GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid,
GROUP_CONCAT(DISTINCT(domain.name)) AS domain_name,
@ -134,4 +135,4 @@ FROM
`cloud`.`service_offering_details` AS `lease_expiry_action_details` ON `lease_expiry_action_details`.`service_offering_id` = `service_offering`.`id`
AND `lease_expiry_action_details`.`name` = 'leaseexpiryaction'
GROUP BY
`service_offering`.`id`;
`service_offering`.`id`;

View File

@ -645,6 +645,16 @@ public class ApiResponseHelper implements ResponseGenerator {
return ApiDBUtils.newServiceOfferingResponse(vOffering);
}
@Override
public org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse createServiceOfferingCategoryResponse(com.cloud.offering.ServiceOfferingCategory category) {
org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse response = new org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse();
response.setId(category.getUuid());
response.setName(category.getName());
response.setSortKey(category.getSortKey());
response.setObjectName("serviceofferingcategory");
return response;
}
@Override
public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
ConfigurationResponse cfgResponse = new ConfigurationResponse();

View File

@ -476,6 +476,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject
ServiceOfferingDetailsDao _srvOfferingDetailsDao;
@Inject
com.cloud.service.dao.ServiceOfferingCategoryDao _serviceOfferingCategoryDao;
@Inject
DiskOfferingDao _diskOfferingDao;
@ -4011,6 +4014,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
ServiceOffering.State state = cmd.getState();
final Long vgpuProfileId = cmd.getVgpuProfileId();
final Boolean gpuEnabled = cmd.getGpuEnabled();
Long categoryId = cmd.getCategoryId();
final Account owner = accountMgr.finalizeOwner(caller, accountName, domainId, projectId);
@ -4058,6 +4062,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
_srvOfferingDao.addCheckForGpuEnabled(serviceOfferingSearch, gpuEnabled);
}
if (categoryId != null) {
serviceOfferingSearch.and("categoryId", serviceOfferingSearch.entity().getCategoryId(), Op.EQ);
}
if (vmId != null) {
currentVmOffering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
diskOffering = _diskOfferingDao.findByIdIncludingRemoved(currentVmOffering.getDiskOfferingId());
@ -4348,6 +4356,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.setParameters("vgpuProfileId", vgpuProfileId);
}
if (categoryId != null) {
sc.setParameters("categoryId", categoryId);
}
if (vmId != null) {
if (!currentVmOffering.isDynamic()) {
sc.setParameters("idNEQ", currentVmOffering.getId());
@ -6231,6 +6243,46 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return bucketDao.searchByIds(bktIds);
}
@Override
public ListResponse<org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse> listServiceOfferingCategories(org.apache.cloudstack.api.command.admin.offering.ListServiceOfferingCategoriesCmd cmd) {
Long id = cmd.getId();
String name = cmd.getName();
Filter searchFilter = new Filter(com.cloud.service.ServiceOfferingCategoryVO.class, "sortKey", true, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchBuilder<com.cloud.service.ServiceOfferingCategoryVO> sb = _serviceOfferingCategoryDao.createSearchBuilder();
if (id != null) {
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
}
if (name != null) {
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
}
sb.done();
SearchCriteria<com.cloud.service.ServiceOfferingCategoryVO> sc = sb.create();
if (id != null) {
sc.setParameters("id", id);
}
if (name != null) {
sc.setParameters("name", name);
}
Pair<List<com.cloud.service.ServiceOfferingCategoryVO>, Integer> result = _serviceOfferingCategoryDao.searchAndCount(sc, searchFilter);
ListResponse<org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse> response = new ListResponse<>();
List<org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse> responses = new ArrayList<>();
for (com.cloud.service.ServiceOfferingCategoryVO category : result.first()) {
org.apache.cloudstack.api.response.ServiceOfferingCategoryResponse categoryResponse = responseGenerator.createServiceOfferingCategoryResponse(category);
responses.add(categoryResponse);
}
response.setResponses(responses, result.second());
return response;
}
@Override
public String getConfigComponentName() {
return QueryService.class.getSimpleName();

View File

@ -64,6 +64,8 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
private ConfigurationDao configDao;
@Inject
private AccountManager accountManager;
@Inject
private com.cloud.service.dao.ServiceOfferingCategoryDao _serviceOfferingCategoryDao;
private SearchBuilder<ServiceOfferingJoinVO> sofIdSearch;
@ -147,6 +149,16 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
offeringResponse.setMaxResolutionY(offering.getMaxResolutionY());
offeringResponse.setGpuCount(offering.getGpuCount());
offeringResponse.setGpuDisplay(offering.getGpuDisplay());
// Set category information if available
if (offering.getCategoryId() != null) {
com.cloud.service.ServiceOfferingCategoryVO category = _serviceOfferingCategoryDao.findById(offering.getCategoryId());
if (category != null) {
offeringResponse.setCategoryId(category.getUuid());
offeringResponse.setCategoryName(category.getName());
}
}
offeringResponse.setNetworkRate(offering.getRateMbps());
offeringResponse.setHostTag(offering.getHostTag());
offeringResponse.setDeploymentPlanner(offering.getDeploymentPlanner());

View File

@ -263,6 +263,9 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
@Column(name = "gpu_display")
private Boolean gpuDisplay;
@Column(name = "category_id")
private Long categoryId;
public ServiceOfferingJoinVO() {
}
@ -557,4 +560,6 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
public Boolean getGpuDisplay() {
return gpuDisplay;
}
}
public Long getCategoryId() { return categoryId; }
}

View File

@ -77,11 +77,14 @@ import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
import org.apache.cloudstack.api.command.admin.network.UpdatePodManagementNetworkIpRangeCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd;
import org.apache.cloudstack.api.command.admin.offering.IsAccountAllowedToCreateOfferingsWithTagsCmd;
import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd;
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
import org.apache.cloudstack.api.command.admin.region.CreatePortableIpRangeCmd;
@ -254,6 +257,7 @@ import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Availability;
import com.cloud.offering.NetworkOffering.Detail;
import com.cloud.offering.ServiceOffering;
import com.cloud.offering.ServiceOfferingCategory;
import com.cloud.offerings.NetworkOfferingDetailsVO;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.NetworkOfferingVO;
@ -267,6 +271,8 @@ import com.cloud.projects.ProjectManager;
import com.cloud.server.ManagementService;
import com.cloud.service.ServiceOfferingDetailsVO;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.ServiceOfferingCategoryVO;
import com.cloud.service.dao.ServiceOfferingCategoryDao;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.DiskOfferingVO;
@ -363,6 +369,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Inject
ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
@Inject
ServiceOfferingCategoryDao _serviceOfferingCategoryDao;
@Inject
DiskOfferingDao _diskOfferingDao;
@Inject
DiskOfferingDetailsDao diskOfferingDetailsDao;
@ -3461,6 +3469,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
}
// validate optional category id
final Long serviceOfferingCategoryId = cmd.getServiceOfferingCategoryId();
if (serviceOfferingCategoryId != null && _serviceOfferingCategoryDao.findById(serviceOfferingCategoryId) == null) {
throw new InvalidParameterValueException("Please specify a valid service offering category id");
}
// validate lease properties and set leaseExpiryAction
Integer leaseDuration = cmd.getLeaseDuration();
VMLeaseManager.ExpiryAction leaseExpiryAction = validateAndGetLeaseExpiryAction(leaseDuration, cmd.getLeaseExpiryAction());
@ -3476,7 +3490,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
cmd.getIopsReadRate(), cmd.getIopsReadRateMax(), cmd.getIopsReadRateMaxLength(),
cmd.getIopsWriteRate(), cmd.getIopsWriteRateMax(), cmd.getIopsWriteRateMaxLength(),
cmd.getHypervisorSnapshotReserve(), cmd.getCacheMode(), storagePolicyId, cmd.getDynamicScalingEnabled(), diskOfferingId,
cmd.getDiskOfferingStrictness(), cmd.isCustomized(), cmd.getEncryptRoot(), vgpuProfileId, gpuCount, cmd.getGpuDisplay(), cmd.isPurgeResources(), leaseDuration, leaseExpiryAction);
cmd.getDiskOfferingStrictness(), cmd.isCustomized(), cmd.getEncryptRoot(), vgpuProfileId, gpuCount, cmd.getGpuDisplay(), cmd.isPurgeResources(), leaseDuration, leaseExpiryAction, serviceOfferingCategoryId);
}
private Integer validateVgpuProfileAndGetGpuCount(final Long vgpuProfileId, Integer gpuCount) {
@ -3506,7 +3520,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
Long iopsWriteRate, Long iopsWriteRateMax, Long iopsWriteRateMaxLength,
final Integer hypervisorSnapshotReserve, String cacheMode, final Long storagePolicyID,
final boolean dynamicScalingEnabled, final Long diskOfferingId, final boolean diskOfferingStrictness,
final boolean isCustomized, final boolean encryptRoot, Long vgpuProfileId, Integer gpuCount, Boolean gpuDisplay, final boolean purgeResources, Integer leaseDuration, VMLeaseManager.ExpiryAction leaseExpiryAction) {
final boolean isCustomized, final boolean encryptRoot, Long vgpuProfileId, Integer gpuCount, Boolean gpuDisplay, final boolean purgeResources, Integer leaseDuration, VMLeaseManager.ExpiryAction leaseExpiryAction, final Long categoryId) {
// Filter child domains when both parent and child domains are present
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
@ -3591,6 +3605,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
serviceOffering.setVgpuProfileId(vgpuProfileId);
serviceOffering.setGpuCount(gpuCount);
serviceOffering.setGpuDisplay(gpuDisplay);
// Set category if provided (categoryId was validated in caller)
if (categoryId != null) {
serviceOffering.setCategoryId(categoryId);
}
DiskOfferingVO diskOffering = null;
if (diskOfferingId == null) {
@ -3850,11 +3868,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
boolean purgeResources = cmd.isPurgeResources();
final Map<String, String> externalDetails = cmd.getExternalDetails();
final boolean cleanupExternalDetails = cmd.isCleanupExternalDetails();
final Long categoryId = cmd.getCategoryId();
if (userId == null) {
userId = Long.valueOf(User.UID_SYSTEM);
}
// Validate category if provided
if (categoryId != null && _serviceOfferingCategoryDao.findById(categoryId) == null) {
throw new InvalidParameterValueException("Please specify a valid service offering category id");
}
// Verify input parameters
final ServiceOffering offeringHandle = _entityMgr.findById(ServiceOffering.class, id);
if (offeringHandle == null) {
@ -3941,7 +3965,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException(String.format("Unable to update service offering: %s by id user: %s because it is not root-admin or domain-admin", offeringHandle, user));
}
final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null;
final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null || categoryId != null;
final boolean serviceOfferingExternalDetailsNeedUpdate =
serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, cleanupExternalDetails);
final boolean detailsUpdateNeeded = !filteredDomainIds.equals(existingDomainIds) ||
@ -3969,6 +3993,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
offering.setState(state);
}
if (categoryId != null) {
offering.setCategoryId(categoryId);
}
DiskOfferingVO diskOffering = _diskOfferingDao.findById(offeringHandle.getDiskOfferingId());
updateOfferingTagsIfIsNotNull(storageTags, diskOffering);
@ -8595,4 +8623,91 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
this.scope = scope;
}
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CREATE, eventDescription = "creating service offering category")
public ServiceOfferingCategory createServiceOfferingCategory(CreateServiceOfferingCategoryCmd cmd) {
String name = cmd.getName();
Integer sortKey = cmd.getSortKey();
// Check if category with same name already exists
ServiceOfferingCategoryVO existingCategory = _serviceOfferingCategoryDao.findByName(name);
if (existingCategory != null) {
throw new InvalidParameterValueException("Service offering category with name " + name + " already exists");
}
com.cloud.service.ServiceOfferingCategoryVO category = new ServiceOfferingCategoryVO(name);
if (sortKey != null) {
category.setSortKey(sortKey);
}
category = _serviceOfferingCategoryDao.persist(category);
CallContext.current().setEventDetails("Service offering category id=" + category.getId());
return category;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_DELETE, eventDescription = "deleting service offering category")
public boolean deleteServiceOfferingCategory(DeleteServiceOfferingCategoryCmd cmd) {
Long categoryId = cmd.getId();
com.cloud.service.ServiceOfferingCategoryVO category = _serviceOfferingCategoryDao.findById(categoryId);
if (category == null) {
throw new InvalidParameterValueException("Unable to find service offering category with id " + categoryId);
}
// Check if any service offering is using this category
// For now we'll just check if it's the default category (id=1)
if (categoryId == 1L) {
throw new InvalidParameterValueException("Cannot delete the default service offering category");
}
boolean result = _serviceOfferingCategoryDao.remove(categoryId);
if (result) {
CallContext.current().setEventDetails("Service offering category id=" + categoryId);
}
return result;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_EDIT, eventDescription = "updating service offering category")
public ServiceOfferingCategory updateServiceOfferingCategory(UpdateServiceOfferingCategoryCmd cmd) {
Long categoryId = cmd.getId();
String name = cmd.getName();
Integer sortKey = cmd.getSortKey();
// Validate category exists
ServiceOfferingCategoryVO category = _serviceOfferingCategoryDao.findById(categoryId);
if (category == null) {
throw new InvalidParameterValueException("Unable to find service offering category with id " + categoryId);
}
// Check if at least one parameter is being updated
if (name == null && sortKey == null) {
throw new InvalidParameterValueException("Please specify at least one parameter to update (name or sortKey)");
}
// If name is being updated, check for duplicates
if (name != null && !name.equals(category.getName())) {
ServiceOfferingCategoryVO existingCategory = _serviceOfferingCategoryDao.findByName(name);
if (existingCategory != null) {
throw new InvalidParameterValueException("A service offering category with name '" + name + "' already exists");
}
category.setName(name);
}
// Update sort key if provided
if (sortKey != null) {
category.setSortKey(sortKey);
}
// Persist changes
boolean updated = _serviceOfferingCategoryDao.update(categoryId, category);
if (!updated) {
throw new CloudRuntimeException("Failed to update service offering category");
}
CallContext.current().setEventDetails("Service offering category id=" + categoryId);
return _serviceOfferingCategoryDao.findById(categoryId);
}
}

View File

@ -162,11 +162,15 @@ import org.apache.cloudstack.api.command.admin.network.UpdatePodManagementNetwor
import org.apache.cloudstack.api.command.admin.network.UpdateStorageNetworkIpRangeCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd;
import org.apache.cloudstack.api.command.admin.offering.IsAccountAllowedToCreateOfferingsWithTagsCmd;
import org.apache.cloudstack.api.command.admin.offering.ListServiceOfferingCategoriesCmd;
import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd;
import org.apache.cloudstack.api.command.admin.outofbandmanagement.ChangeOutOfBandManagementPasswordCmd;
import org.apache.cloudstack.api.command.admin.outofbandmanagement.ConfigureOutOfBandManagementCmd;
import org.apache.cloudstack.api.command.admin.outofbandmanagement.DisableOutOfBandManagementForClusterCmd;
@ -3759,6 +3763,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(IsAccountAllowedToCreateOfferingsWithTagsCmd.class);
cmdList.add(UpdateDiskOfferingCmd.class);
cmdList.add(UpdateServiceOfferingCmd.class);
cmdList.add(CreateServiceOfferingCategoryCmd.class);
cmdList.add(ListServiceOfferingCategoriesCmd.class);
cmdList.add(UpdateServiceOfferingCategoryCmd.class);
cmdList.add(DeleteServiceOfferingCategoryCmd.class);
cmdList.add(CreatePodCmd.class);
cmdList.add(DeletePodCmd.class);
cmdList.add(ListPodsByCmd.class);

View File

@ -147,6 +147,24 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
return null;
}
@Override
public com.cloud.offering.ServiceOfferingCategory createServiceOfferingCategory(org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCategoryCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteServiceOfferingCategory(org.apache.cloudstack.api.command.admin.offering.DeleteServiceOfferingCategoryCmd cmd) {
// TODO Auto-generated method stub
return false;
}
@Override
public com.cloud.offering.ServiceOfferingCategory updateServiceOfferingCategory(org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCategoryCmd cmd) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.cloud.configuration.ConfigurationService#updateDiskOffering(org.apache.cloudstack.api.commands.UpdateDiskOfferingCmd)
*/