[WIP] feature: boot group - #144
Conversation
eee28b0 to
18effeb
Compare
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
aba0b98 to
7b93141
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces the Instance Boot Group feature across the CloudStack stack (DB schema + API/manager layer + UI), including boot-order management and readiness-check plumbing (VR ping/port checks and KVM guest-agent liveness).
Changes:
- Adds new Instance Boot Group entities, schema migrations/views, DAOs, API commands, and responses.
- Implements readiness-check infrastructure (VR-executed ping/port checks + KVM qemu-guest-agent “guest-ping” support).
- Extends the UI with list/detail integration, membership management, boot-order editing, and i18n strings.
Reviewed changes
Copilot reviewed 82 out of 83 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/src/views/compute/UpdateInstanceBootGroupMemberOrder.vue | UI modal to update member boot order |
| ui/src/views/compute/InstanceBootGroupMembersTab.vue | UI tab to list/manage boot group members/readiness |
| ui/src/views/compute/AddInstanceBootGroupMember.vue | UI modal to add VM/InstanceGroup members |
| ui/src/core/lazy_lib/icons_use.js | Registers additional Ant Design icon |
| ui/src/config/section/compute.js | Adds compute-section navigation/resource config |
| ui/src/components/view/ListView.vue | Enables quick-view routing for boot groups |
| ui/public/locales/en.json | Adds UI labels/messages for boot groups |
| tools/apidoc/gen_toc.py | Adds boot group category mapping in API docs |
| systemvm/debian/opt/cloud/bin/instance_readiness_check.py | VR helper script for readiness checks |
| server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml | Wires boot group/readiness beans in Spring |
| server/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/VrPingChecker.java | Readiness checker dispatching ping via VR |
| server/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/PortCheckChecker.java | Readiness checker dispatching TCP port check via VR |
| server/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/InstanceBootGroupReadinessRuleService.java | Service interface for readiness rule mutation/eval |
| server/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/GuestAgentLivenessChecker.java | Readiness checker using host-side qemu guest agent |
| server/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupMembershipGuard.java | Centralized eligibility validation for membership |
| server/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupManager.java | Manager interface for boot-group orchestration |
| server/src/main/java/org/apache/cloudstack/api/query/vo/InstanceBootGroupJoinVO.java | Join VO for boot group query view |
| server/src/main/java/org/apache/cloudstack/api/query/dao/InstanceBootGroupJoinDaoImpl.java | DAO impl for boot group join view |
| server/src/main/java/org/apache/cloudstack/api/query/dao/InstanceBootGroupJoinDao.java | DAO interface for boot group join view |
| server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | Hooks membership guard into VM group add flow |
| server/src/main/java/com/cloud/api/ApiResponseHelper.java | Adds boot-group-related DAO injections (response plumbing) |
| plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuCommand.java | Adds qemu guest-agent ping command constant |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckGuestAgentLivenessCommandWrapper.java | Implements CheckGuestAgentLivenessCommand handling |
| engine/schema/src/main/resources/META-INF/db/views/cloud.instance_boot_group_view.sql | Adds DB view for boot group join |
| engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql | Adds boot group + readiness tables to migration |
| engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml | Registers new DAOs in schema module |
| engine/schema/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupVO.java | Boot group entity VO |
| engine/schema/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupReadinessRuleVO.java | Readiness rule entity VO |
| engine/schema/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupReadinessRuleDetailsVO.java | Readiness rule details entity VO |
| engine/schema/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupReadinessCheckResultVO.java | Cached readiness check result entity VO |
| engine/schema/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupMemberVO.java | Boot group member entity VO |
| engine/schema/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupDetailsVO.java | Boot group per-group config override VO |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupReadinessRuleDetailsDaoImpl.java | DAO impl for rule details (+ encryption) |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupReadinessRuleDetailsDao.java | DAO interface for rule details |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupReadinessRuleDaoImpl.java | DAO impl for readiness rules |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupReadinessRuleDao.java | DAO interface for readiness rules |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupReadinessCheckResultDaoImpl.java | DAO impl for cached readiness results |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupReadinessCheckResultDao.java | DAO interface for cached readiness results |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupMemberDaoImpl.java | DAO impl for boot group members |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupMemberDao.java | DAO interface for boot group members |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupDetailsDaoImpl.java | DAO impl for boot group details |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupDetailsDao.java | DAO interface for boot group details |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupDaoImpl.java | DAO impl for boot groups |
| engine/schema/src/main/java/com/cloud/vm/dao/InstanceBootGroupDao.java | DAO interface for boot groups |
| core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml | Registers readiness checker extension registry |
| core/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/InstanceReadinessCheckCommand.java | VR command for readiness checks |
| core/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/InstanceReadinessCheckAnswer.java | Parses VR execution results for readiness checks |
| core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java | Adds readiness-check script constant |
| core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java | Executes readiness check in VR and returns answer |
| core/src/main/java/com/cloud/agent/api/CheckGuestAgentLivenessCommand.java | Adds agent command for guest liveness |
| core/src/main/java/com/cloud/agent/api/CheckGuestAgentLivenessAnswer.java | Adds agent answer for guest liveness |
| api/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/ReadinessChecker.java | SPI for readiness rule evaluation |
| api/src/main/java/org/apache/cloudstack/vm/bootgroup/readiness/InstanceBootGroupReadinessRule.java | API model for readiness rules/types/status |
| api/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupService.java | API-facing boot group service contract |
| api/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroupMember.java | API model for boot group members |
| api/src/main/java/org/apache/cloudstack/vm/bootgroup/InstanceBootGroup.java | API model for boot group entity |
| api/src/main/java/org/apache/cloudstack/api/response/InstanceBootGroupResponse.java | API response model for boot groups |
| api/src/main/java/org/apache/cloudstack/api/response/InstanceBootGroupReadinessRuleResponse.java | API response model for readiness rules |
| api/src/main/java/org/apache/cloudstack/api/response/InstanceBootGroupMemberResponse.java | API response model for members |
| api/src/main/java/org/apache/cloudstack/api/response/InstanceBootGroupMemberChildResponse.java | API response for InstanceGroup child VMs |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/UpdateInstanceBootGroupReadinessRuleCmd.java | Updates readiness rule API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/UpdateInstanceBootGroupMemberCmd.java | Updates member boot order API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/UpdateInstanceBootGroupCmd.java | Updates boot group API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/StopInstanceBootGroupCmd.java | Stops boot group API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/StartInstanceBootGroupCmd.java | Starts boot group API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/RemoveInstanceBootGroupMemberCmd.java | Removes member API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/RebootInstanceBootGroupCmd.java | Reboots boot group API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/ListInstanceBootGroupsCmd.java | Lists boot groups API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/ListInstanceBootGroupReadinessRulesCmd.java | Lists readiness rules API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/ListInstanceBootGroupMembersCmd.java | Lists members API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/DeleteInstanceBootGroupReadinessRuleCmd.java | Deletes readiness rule API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/DeleteInstanceBootGroupCmd.java | Deletes boot group API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/CreateInstanceBootGroupReadinessRuleCmd.java | Creates readiness rule API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/CreateInstanceBootGroupCmd.java | Creates boot group API command |
| api/src/main/java/org/apache/cloudstack/api/command/user/bootgroup/AddMemberToInstanceBootGroupCmd.java | Adds member API command |
| api/src/main/java/org/apache/cloudstack/api/ApiConstants.java | Adds boot-group/readiness API constants |
| api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java | Adds resource types for boot groups/rules |
| api/src/main/java/com/cloud/event/EventTypes.java | Adds boot group event type constants |
Suppressed comments (1)
ui/src/views/compute/AddInstanceBootGroupMember.vue:57
- The Instance Group selector is not bound to the form model (no v-model), so validation and submission can proceed with instancegroupid unset, producing an API request without a member id.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| public static final String EVENT_INSTANCE_BOOT_GROUP_MEMBER_ADD = "INSTANCE.BOOT.GROUP.MEMBER.ADD"; | ||
| public static final String EVENT_INSTANCE_BOOT_GROUP_MEMBER_REMOVE = "INSTANCE.BOOT.GROUP.MEMBER.REMOVE"; | ||
| public static final String EVENT_INSTANCE_BOOT_GROUP_MEMBER_REORDER = "INSTANCE.BOOT.GROUP.MEMBER.REODER"; |
| switch (mode) { | ||
| case 'None': return this.$t('label.readiness.mode.no.readiness') | ||
| case 'MemberDependent': return this.$t('label.readiness.mode.member.dependent') | ||
| case 'RuleBased': return this.$t('label.readiness.mode.rule.based') | ||
| default: return '' | ||
| } |
| @Parameter(name = ApiConstants.RULE_TYPE, type = CommandType.STRING, required = true, | ||
| description = "The readiness rule type: GuestAgentLiveness, Ping, PortCheck, InstanceQuorum or CustomScript") | ||
| private String ruleType; |
| <infinite-scroll-select | ||
| api="listVirtualMachines" | ||
| :apiParams="{ listall: true }" | ||
| resourceType="virtualmachine" | ||
| defaultIcon="desktop-outlined" | ||
| @change-option-value="onMemberSelected" /> |
| initForm () { | ||
| this.formRef = ref() | ||
| this.form = reactive({ | ||
| membertype: 'VirtualMachine', | ||
| order: 0 | ||
| }) | ||
| this.rules = reactive({ | ||
| order: [{ required: true, type: 'number', message: `${this.$t('message.error.required.input')}` }] | ||
| }) | ||
| }, |
| handleSubmit (e) { | ||
| e.preventDefault() | ||
| if (this.loading) return |
| handleSubmit (e) { | ||
| e.preventDefault() | ||
| if (this.loading) return |
| 'ImportVmTask': 'Import VM Task', | ||
| 'Dns': 'DNS' | ||
| 'Dns': 'DNS', | ||
| 'InstanceBootGroup': 'InstanceBootGroup', |
| if (cmd.getOrder() < 0) { | ||
| throw new InvalidParameterValueException("Order value must be 0 or greater"); | ||
| } | ||
|
|
||
| InstanceBootGroupMember.MemberType memberType; | ||
| long memberId; | ||
|
|
||
| if (cmd.getVirtualMachineId() != null && cmd.getInstanceGroupId() != null) { | ||
| throw new InvalidParameterValueException("Only one of virtualmachineid or instancegroupid may be specified"); | ||
| } | ||
| if (cmd.getVirtualMachineId() == null && cmd.getInstanceGroupId() == null) { | ||
| throw new InvalidParameterValueException("Either virtualmachineid or instancegroupid must be specified"); | ||
| } |
There was a problem hiding this comment.
Can these be extracted to a new method? Looks like they could be reused
|
|
||
| if (cmd.getVirtualMachineId() != null) { | ||
| UserVm vm = userVmDao.findById(cmd.getVirtualMachineId()); | ||
| if (vm == null) { |
There was a problem hiding this comment.
Similarly to the check below, should we check here for the VM state?
| if (cmd.getVirtualMachineId() != null) { | ||
| UserVm vm = userVmDao.findById(cmd.getVirtualMachineId()); | ||
| if (vm == null) { | ||
| throw new InvalidParameterValueException("Unable to find virtual machine with ID: " + cmd.getVirtualMachineId()); | ||
| } | ||
| validateMemberAccount(vm.getAccountId(), group.getAccountId()); | ||
| instanceBootGroupMembershipGuard.validateVmEligibleForGroupMembership(vm.getId()); | ||
| memberType = InstanceBootGroupMember.MemberType.VirtualMachine; | ||
| memberId = vm.getId(); | ||
| } else { | ||
| InstanceGroupVO instanceGroup = instanceGroupDao.findById(cmd.getInstanceGroupId()); | ||
| if (instanceGroup == null || instanceGroup.getRemoved() != null) { | ||
| throw new InvalidParameterValueException("Unable to find instance group with ID: " + cmd.getInstanceGroupId()); | ||
| } | ||
| validateMemberAccount(instanceGroup.getAccountId(), group.getAccountId()); | ||
| instanceBootGroupMembershipGuard.validateInstanceGroupEligibleForBootGroupMembership(instanceGroup.getId()); | ||
| memberType = InstanceBootGroupMember.MemberType.InstanceGroup; | ||
| memberId = instanceGroup.getId(); | ||
| } |
There was a problem hiding this comment.
Can this also be extracted to a new method that returns the memberId and memberType? The logic seems to be the same and could be branched depending on the memberType
|
|
||
| if (directRules.isEmpty() && inheritedRules.isEmpty()) { | ||
| UserVmVO vm = userVmDao.findById(vmId); | ||
| boolean running = vm != null && vm.getState() == com.cloud.vm.VirtualMachine.State.Running; |
There was a problem hiding this comment.
Why not excluding null vm here?
| * its owning InstanceGroup (marked {@code inherited=true}), not just its own direct rules. | ||
| */ | ||
| @Override | ||
| public ListResponse<InstanceBootGroupReadinessRuleResponse> listInstanceBootGroupReadinessRules(ListInstanceBootGroupReadinessRulesCmd cmd) { |
There was a problem hiding this comment.
This method and similar listing methods in this class seem to be adding a complex logic for listing. Why not moving that logic to the dao classes and invoking it from here?
|
|
||
| public interface InstanceBootGroupReadinessRuleDao extends GenericDao<InstanceBootGroupReadinessRuleVO, Long> { | ||
|
|
||
| List<InstanceBootGroupReadinessRuleVO> listByBootGroupId(long bootGroupId); |
| * no FK path for this (item_id doesn't reference instance_boot_group_member/instance_group_vm_map), | ||
| * so it's enforced here in code instead of a DB cascade. | ||
| */ | ||
| void deleteByItem(InstanceBootGroupMember.MemberType itemType, long itemId); |
| } | ||
|
|
||
| /** In-memory-only per-VM progress for a single start attempt — never persisted. */ | ||
| private static final class VmProgress { |
There was a problem hiding this comment.
How would the feature behave in case VMs are started within the boot group and management server restarts? Even though services are then up then would this logic detect it after the management server is back?
| CallContext callerContext = CallContext.current(); | ||
| ExecutorService readinessExecutor = Executors.newFixedThreadPool(concurrency, new NamedThreadFactory("InstanceBootGroup-readiness-" + tierOrder)); | ||
| try { | ||
| while (true) { |
There was a problem hiding this comment.
Should we add another exit method, like a timeout?
Description
TBA
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
How did you try to break this feature and the system with this change?