-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Service offering category feature #12144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- 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.
…e' into service_offering_category_feature
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #12144 +/- ##
============================================
- Coverage 17.57% 17.56% -0.01%
+ Complexity 15550 15549 -1
============================================
Files 5913 5920 +7
Lines 529427 529717 +290
Branches 64677 64708 +31
============================================
- Hits 93024 93023 -1
- Misses 425940 426232 +292
+ Partials 10463 10462 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
|
Dear @Hanarion, This is a nice feature to have. Are you considering extending it to allow a domain or account to be limited to one (or a specific list) of categories? For example, we distinguish between Core (higher-performance hardware) and Essentials (lower-performance hardware), in a tiered fashion (with different costs, of course). With "Offering Category", we could define which groups of offerings a client (domain/account) is allowed to use. What do you think? |
|
@daviftorres it could be interesting yes. |
Sounds great! |
|
@blueorangutan package |
|
@rajujith a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 15873 |
rajujith
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Hanarion I added service offering to a new category but it gets added the default one although the API has the correct one.
|
@rajujith thanks for the review. I'll check today in order to fix this issue |
Screen.Recording.2025-12-03.at.10.03.17.AM.mov |
…on/cloudstack into service_offering_category_feature
…breaking functionnality
|
@rajujith Indeed when refactoring the names of the fields before comitting, i broke the functionnality, i fixed it. Also, i dont know where i should put the SQL, currently i put it in schema-42200to42300.sql, but I think it should be moved to schema-42210to42300.sql Do you confirm ? |
Thanks for fixing it @Hanarion , regarding the schema lets ask a dev @DaanHoogland @harikrishna-patnala |
|
@blueorangutan package |
|
@rajujith a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result [SF]: ✖️ el8 ✖️ el9 ✔️ debian ✖️ suse15. SL-JID 15912 |
Yes @Hanarion , 42210 to 42300 seems appropriate. |
|
@blueorangutan package |
|
@rajujith a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 15925 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request introduces a "Service Offering Categories" feature to CloudStack, enabling administrators to organize and categorize service offerings for better user experience when deploying VMs. The feature adds complete CRUD API support for categories, database schema changes, and UI enhancements for category selection and filtering.
Key Changes:
- Added new database table
service_offering_categoryand foreign key relationship toservice_offeringtable - Implemented full CRUD API operations:
createServiceOfferingCategory,listServiceOfferingCategories,updateServiceOfferingCategory, anddeleteServiceOfferingCategory - Enhanced UI with category selection widgets in VM deployment and service offering management interfaces
Reviewed changes
Copilot reviewed 36 out of 36 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql | Database migration script adding the service_offering_category table and foreign key to service_offering |
| engine/schema/src/main/java/com/cloud/service/ServiceOfferingCategoryVO.java | Entity class for service offering category with name, UUID, and sort key |
| engine/schema/src/main/java/com/cloud/service/ServiceOfferingVO.java | Added categoryId field to associate service offerings with categories |
| engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingCategoryDao.java | DAO interface for category persistence operations |
| engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingCategoryDaoImpl.java | DAO implementation with name-based lookup and list operations |
| api/src/main/java/com/cloud/offering/ServiceOfferingCategory.java | Interface defining category properties and behaviors |
| api/src/main/java/com/cloud/offering/ServiceOffering.java | Added getCategoryId() method to the ServiceOffering interface |
| api/src/main/java/org/apache/cloudstack/api/ApiConstants.java | Added constants for category ID and name parameters |
| api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCategoryCmd.java | API command for creating service offering categories |
| api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCategoryCmd.java | API command for updating service offering categories |
| api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteServiceOfferingCategoryCmd.java | API command for deleting service offering categories |
| api/src/main/java/org/apache/cloudstack/api/command/admin/offering/ListServiceOfferingCategoriesCmd.java | API command for listing service offering categories |
| api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java | Extended to accept categoryId parameter |
| api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java | Extended to accept categoryId parameter for updates |
| api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java | Extended to filter by categoryId |
| api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java | Added categoryId and categoryName fields to API response |
| api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingCategoryResponse.java | Response object for service offering category with ID, name, and sort key |
| api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java | Added method to generate service offering category responses |
| api/src/main/java/com/cloud/configuration/ConfigurationService.java | Extended interface with category management methods |
| server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java | Implementation of create, update, and delete operations for categories with validation |
| server/src/main/java/com/cloud/api/ApiResponseHelper.java | Helper method to create category response objects |
| server/src/main/java/com/cloud/api/query/QueryManagerImpl.java | Query implementation for listing categories with filtering and added categoryId filtering to service offering queries |
| server/src/main/java/com/cloud/api/query/vo/ServiceOfferingJoinVO.java | Added categoryId field to the join view object |
| server/src/main/java/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java | Populates category information in service offering responses |
| server/src/main/java/com/cloud/server/ManagementServerImpl.java | Registered new category API commands |
| engine/schema/src/main/resources/META-INF/db/views/cloud.service_offering_view.sql | Added category_id to the service offering database view |
| engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml | Registered ServiceOfferingCategoryDaoImpl bean |
| ui/src/views/offering/AddComputeOffering.vue | Added category dropdown in compute offering creation form |
| ui/src/views/compute/wizard/ComputeOfferingSelection.vue | Added category filter widget for VM deployment wizard |
| ui/src/views/compute/DeployVM.vue | Fetches and handles category filtering in VM deployment flow |
| ui/src/config/section/offering.js | Added category to searchFilters, columns, details, and edit parameters |
| ui/src/config/section/config.js | Added new config section for service offering category management |
| ui/src/components/view/ListView.vue | Added category column with router-link and updateServiceOfferingCategory command mapping |
| ui/public/locales/en.json | Added localization strings for category features |
| server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java | Mock implementation stubs for category methods |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| CREATE TABLE IF NOT EXISTS `cloud`.`service_offering_category` ( | ||
| `id` bigint unsigned NOT NULL auto_increment, | ||
| `name` varchar(255) NOT NULL, |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name column should have a UNIQUE constraint to prevent duplicate category names, as the application logic in ConfigurationManagerImpl.java checks for duplicate names when creating/updating categories (lines 8634-8636 and 8692-8695).
| if (categoryId == 1L) { | ||
| throw new InvalidParameterValueException("Cannot delete the default service offering category"); | ||
| } | ||
|
|
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The delete validation is incomplete. The comment on line 8659 states "Check if any service offering is using this category", but the actual implementation only checks if it's the default category (id=1). Due to the foreign key constraint with ON DELETE RESTRICT in the schema, attempting to delete a category that's in use will cause a database error. The code should query for service offerings using this category and provide a clear error message before attempting deletion.
| // Check if any service offering is using this category | |
| List<ServiceOfferingVO> offeringsUsingCategory = _serviceOfferingDao.listByCategoryId(categoryId); | |
| if (offeringsUsingCategory != null && !offeringsUsingCategory.isEmpty()) { | |
| throw new InvalidParameterValueException("Cannot delete service offering category with id " + categoryId + | |
| " because it is in use by one or more service offerings."); | |
| } |
| width: 100%; | ||
| height: 100%; | ||
| .radio-opion__icon { |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a typo in the CSS class name: 'radio-opion__icon' should be 'radio-option__icon' (missing 't' in 'option').
|
|
||
| @Override | ||
| public long getEntityOwnerId() { | ||
| return Account.Type.ADMIN.ordinal(); |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getEntityOwnerId() method returns Account.Type.ADMIN.ordinal(), which is incorrect. The ordinal() of an enum returns its position (0 for ADMIN), not an account ID. This should return Account.ACCOUNT_ID_SYSTEM to match the pattern used in similar commands like UpdateServiceOfferingCategoryCmd (line 80-82).
| return Account.Type.ADMIN.ordinal(); | |
| return Account.ACCOUNT_ID_SYSTEM; |
| @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") |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version format should be consistent across the codebase. Most new features use "4.23.0" format (as seen in the API commands), but this uses "4.23". Please use "4.23.0" to maintain consistency.
| @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") | |
| @Param(description = "the ID of the service offering category", since = "4.23.0") | |
| private String categoryId; | |
| @SerializedName("category") | |
| @Param(description = "the name of the service offering category", since = "4.23.0") |
|
|
||
| @Override | ||
| public long getEntityOwnerId() { | ||
| return Account.Type.ADMIN.ordinal(); |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getEntityOwnerId() method returns Account.Type.ADMIN.ordinal(), which is incorrect. The ordinal() of an enum returns its position (0 for ADMIN), not an account ID. This should return Account.ACCOUNT_ID_SYSTEM to match the pattern used in other admin commands, such as CreateServiceOfferingCategoryCmd (line 82-83) and UpdateServiceOfferingCategoryCmd (line 80-82).
| return Account.Type.ADMIN.ordinal(); | |
| return Account.ACCOUNT_ID_SYSTEM; |
|
|
||
| @Parameter(name = ApiConstants.SERVICE_OFFERING_CATEGORY_ID, | ||
| type = CommandType.UUID, | ||
| entityType = ServiceOfferingCategoryResponse .class, |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an extra space before .class in the entityType parameter: 'ServiceOfferingCategoryResponse .class' should be 'ServiceOfferingCategoryResponse.class'.
| entityType = ServiceOfferingCategoryResponse .class, | |
| entityType = ServiceOfferingCategoryResponse.class, |
| entityType = ServiceOfferingCategoryResponse.class, | ||
| required = false, | ||
| description = "the ID of the service offering category to associate", | ||
| since = "4.23") |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version format should be consistent. This parameter uses "4.23" while most other API commands use "4.23.0" format. Please use "4.23.0" for consistency.
| since = "4.23") | |
| since = "4.23.0") |
| } else { | ||
| params.categoryid = null |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting params.categoryid = null may not properly remove the filter parameter. Instead, consider using delete params.categoryid or simply not setting it when categoryId is '-1', to avoid sending categoryid=null in the API request which may not be handled as "no filter".
| <template v-if="column.key === 'vgpuActions'"> | ||
| <slot name="actionButtons" :record="record" :actions="actions"></slot> | ||
| </template> | ||
| <template v-if="column.key === 'category' && $route.path.split('/')[1] === 'computeoffering'"> |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an extra space in the condition: column.key === 'category' && has two spaces before &&. Should be a single space for consistency.
Description
When using Cloudstack, when creating instance with a lot of offerings, it could be hard to differentiate between all of the offerings. For that, categories could be useful.
This pull request introduces the concept of "Service Offering Categories" to the API, allowing service offerings to be grouped, managed, and queried by category. It adds a new interface for categories, updates the API to support creating, updating, deleting, and listing categories, and enables associating service offerings with a category. The changes also extend existing API commands and responses to work with categories.
Service Offering Category API Support:
CreateServiceOfferingCategoryCmd,DeleteServiceOfferingCategoryCmd,UpdateServiceOfferingCategoryCmd, andListServiceOfferingCategoriesCmd, enabling full CRUD operations and listing for categories.ConfigurationServiceinterface to include methods for creating, deleting, and updating service offering categories.ServiceOfferingCategorythat defines category properties and behaviors.API Parameter and Response Enhancements:
SERVICE_OFFERING_CATEGORY_ID,SERVICE_OFFERING_CATEGORY_NAME) inApiConstants, and updated related commands (CreateServiceOfferingCmd,UpdateServiceOfferingCmd,ListServiceOfferingsCmd) to accept or filter by category.ResponseGeneratorto support generating responses for service offering categories.Service Offering Model Update:
getCategoryId()method to theServiceOfferinginterface, allowing offerings to be associated with a specific category.Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
On my dev environment, through the API and cloudmonkey
How did you try to break this feature and the system with this change?
Those changes should not break any features as it is only adding a new column to serviceoffering and adding a new table, it is only a way to filter and categorize.
--
I'm sorry if the formatting isn't perfect, i couldn't get the pre-commit to work, and it is my first code PR.
Warning, i put the SQL where i thought it made sense, but i think you will want to move it where it really should be.