Skip to content

[release-1.14] Update root queue capability and enhance queue validation logic - #5080

Merged
volcano-sh-bot merged 4 commits into
volcano-sh:release-1.14from
volcano-sh-bot:cherry-pick-4973-to-release-1.14
Mar 5, 2026
Merged

[release-1.14] Update root queue capability and enhance queue validation logic#5080
volcano-sh-bot merged 4 commits into
volcano-sh:release-1.14from
volcano-sh-bot:cherry-pick-4973-to-release-1.14

Conversation

@volcano-sh-bot

Copy link
Copy Markdown
Contributor

This is an automated cherry-pick of #4973

1. When set the webhoook flag --enable-queue-allocated-pods-check=true, the queue cannot be deleted if it still contains running jobs/pods
2. A new flag "defaultMaxQueueDepth=5" has been added, with the default depth limit is set to 5 as a hard constraint to ensure scheduling efficiency. You can modify this parameter value to adjust the maximum depth of the hierarchical queue.
3. A new flag "enable-root-queue-protection" has been added and default is true, with the root queue's resource attributes (capability, deserved, guarantee) cannot be modified. Since we have set its quota to infinite by default in the capacity plugin, any display modifications by the user should be rejected. If you really want to modify the root's quota, you can set it to false.

Signed-off-by: guoqinwill <gq411will@163.com>
Signed-off-by: guoqinwill <gq411will@163.com>
Signed-off-by: guoqinwill <gq411will@163.com>
… flag enable-root-queue-protection to control if root queue can be modifeid; and fix somme comments

Signed-off-by: guoqinwill <gq411will@163.com>
@volcano-sh-bot volcano-sh-bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Mar 4, 2026
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and configurability of queue management within the system. It introduces new safeguards to prevent accidental data loss or misconfiguration, particularly concerning queue deletion and the modification of the critical root queue. Furthermore, it refines the validation logic for hierarchical queue resource attributes and introduces a configurable depth limit, leading to a more stable and efficient scheduling environment.

Highlights

  • Enhanced Queue Validation: Implemented stricter validation rules for hierarchical queues, ensuring that resource attributes (guarantee, deserved, capability) adhere to the guaranteed <= deserved <= capability hierarchy. Error messages for validation failures have been refined for clarity.
  • Root Queue Protection: Introduced a new flag, enable-root-queue-protection, which defaults to true. When enabled, it prevents modification of the root queue's resource attributes (capability, deserved, guarantee) to maintain system stability, as its quota is infinite by default.
  • Queue Deletion Safeguard: Added a new webhook flag, enable-queue-allocated-pods-check, which, when set to true, prevents the deletion of a queue if it still contains allocated pods, ensuring no active jobs are inadvertently disrupted.
  • Hierarchical Queue Depth Limit: A new flag, defaultMaxQueueDepth, has been introduced with a default value of 5. This sets a hard constraint on the maximum depth of hierarchical queues, which can be configured to manage scheduling efficiency.
  • Root Queue Capability Update: The root queue's capability is now set to an infinite resource by default if not explicitly defined, reflecting its role as the ultimate parent for all queues and removing artificial resource constraints.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • cmd/webhook-manager/app/options/options.go
    • Added defaultMaxQueueDepth constant.
    • Introduced EnableQueueAllocatedPodsCheck, MaxQueueDepth, and EnableRootQueueProtection fields to the Config struct.
    • Registered new command-line flags for EnableQueueAllocatedPodsCheck, MaxQueueDepth, and EnableRootQueueProtection.
  • cmd/webhook-manager/app/options/options_test.go
    • Updated TestAddFlags to include the new configuration fields in expected values.
  • cmd/webhook-manager/app/server.go
    • Propagated new configuration options (EnableQueueAllocatedPodsCheck, MaxQueueDepth, EnableRootQueueProtection) to the admission service configuration.
  • installer/helm/chart/volcano/policy/queues-validating.yaml
    • Simplified validation messages for queue resource constraints.
    • Removed redundant guarantee <= capability validation rule.
  • pkg/scheduler/api/resource_info.go
    • Added InfiniteResource function to create a resource object with maximum possible values for CPU, Memory, and MaxTaskNum.
  • pkg/scheduler/api/resource_info_test.go
    • Added TestInfiniteResource to verify the functionality of the InfiniteResource creation.
  • pkg/scheduler/cache/cache.go
    • Refactored newDefaultAndRootQueue to use a helper function createIfNotExists for creating root and default queues, improving error handling and retry logic.
  • pkg/scheduler/framework/session.go
    • Removed unused context and metav1 imports.
    • Removed TotalGuarantee and TotalDeserved fields from the Session struct.
    • Removed the updateRootQueueResources function and its invocation.
  • pkg/scheduler/plugins/capacity/capacity.go
    • Removed totalDeserved field from the capacityPlugin struct.
    • Modified root queue initialization to set its capability to an infinite resource if it's empty.
    • Removed updates to ssn.TotalGuarantee and ssn.TotalDeserved.
    • Changed klog.V(3).Infof to klog.Errorf for certain hierarchical queue validation failures.
    • Ensured childAttr.deserved is at least childAttr.guarantee during hierarchical queue checks.
    • Removed conditional setting of root queue's guarantee and deserved based on emptiness.
  • pkg/webhooks/admission/queues/validate/validate_queue.go
    • Imported resource package and removed metav1 import.
    • Modified AdmitQueues to return AdmissionResponse directly upon validation errors.
    • Implemented logic to block modifications to the root queue's resource attributes if config.EnableRootQueueProtection is true.
    • Renamed validateResourceOfQueue to validateResourceQuantityOfQueue and updated its logic to enforce guaranteed <= deserved <= capability with specific error messages.
    • Integrated config.EnableQueueAllocatedPodsCheck to prevent queue deletion if allocated pods exist.
    • Added validateQueueDepth function and integrated it into hierarchical queue validation.
    • Introduced helper functions: getSingleResource, findNearestAncestorCapability, findSubtreeMaxCapability, and formatResourceWithType.
    • Refactored validateChildAgainstParent to validateChildAgainstAncestor to check against all ancestor capabilities.
    • Updated validateChildrenConstraints to use findSubtreeMaxCapability for comprehensive capability checks.
    • Simplified validateSiblingsSum logic and removed validateResourceLimit.
  • pkg/webhooks/admission/queues/validate/validate_queue_test.go
    • Set config.MaxQueueDepth and config.EnableQueueAllocatedPodsCheck in test setup.
    • Updated expected error messages in various queue validation test cases.
    • Removed the capabilityLessGuarantee test case.
    • Added new test cases for validateQueueDepthDynamic, validateChildAgainstAncestorForCapability, and TestValidateChildrenConstraintsForCapability.
  • pkg/webhooks/router/interface.go
    • Added EnableQueueAllocatedPodsCheck, MaxQueueDepth, and EnableRootQueueProtection fields to the AdmissionServiceConfig struct.
  • test/e2e/admission/queue_validation_test.go
    • Updated expected error messages in E2E queue validation tests to match new validation logic.
    • Modified test descriptions for resource type validation to reflect that types not in capability are now allowed.
  • test/e2e/util/queue.go
    • Imported errors package.
    • Added logic to delete associated jobs within a queue before attempting to delete the queue itself in DeleteQueue.
    • Renamed queueClosed to queueClosedAndNoPod and enhanced it to also check for the absence of allocated pods.
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several valuable enhancements to queue validation and management. Key changes include adding flags to control queue deletion based on allocated pods, setting a maximum depth for hierarchical queues, and protecting the root queue's resource attributes from modification. The validation logic for hierarchical resources is significantly improved, with more robust checks and clearer error messages. The implementation thoughtfully moves complex validation from CEL expressions to Go code within the webhook, which enhances maintainability. The changes are well-supported by new unit and e2e tests. I have a couple of suggestions for minor code improvements to enhance efficiency and maintainability.

Note: Security Review did not run due to the size of the PR.

Comment on lines 601 to 628
for _, sibling := range siblings {
if sibling.Name != queue.Name {
totalGuarantee.Add(api.NewResource(sibling.Spec.Guarantee.Resource))
if parentGuarantee.LessPartly(totalGuarantee, api.Zero) {
return fmt.Errorf("parent queue %s validation failed: sum of children's guarantee (%s) exceeds parent's guarantee limit (%s)",
parent.Name, totalGuarantee, parentGuarantee)
}

totalDeserved.Add(api.NewResource(sibling.Spec.Deserved))
if parentDeserved.LessPartly(totalDeserved, api.Zero) {
return fmt.Errorf("parent queue %s validation failed: sum of children's deserved (%s) exceeds parent's deserved limit (%s)",
parent.Name, totalDeserved, parentDeserved)
}
}
}

// Add the current queue's resources
totalGuarantee.Add(api.NewResource(queue.Spec.Guarantee.Resource))
totalDeserved.Add(api.NewResource(queue.Spec.Deserved))

// Validate guarantee sum
if err := validateResourceLimit(parent, totalGuarantee, "guarantee", parent.Spec.Guarantee.Resource); err != nil {
return fmt.Errorf("parent queue %s validation failed: %v", parent.Name, err)
if parentGuarantee.LessPartly(totalGuarantee, api.Zero) {
return fmt.Errorf("parent queue %s validation failed: sum of children's guarantee (%s) exceeds parent's guarantee limit (%s)",
parent.Name, totalGuarantee, parentGuarantee)
}

// Validate deserved sum
if err := validateResourceLimit(parent, totalDeserved, "deserved", parent.Spec.Deserved); err != nil {
return fmt.Errorf("parent queue %s validation failed: %v", parent.Name, err)
totalDeserved.Add(api.NewResource(queue.Spec.Deserved))
if parentDeserved.LessPartly(totalDeserved, api.Zero) {
return fmt.Errorf("parent queue %s validation failed: sum of children's deserved (%s) exceeds parent's deserved limit (%s)",
parent.Name, totalDeserved, parentDeserved)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The checks for parentGuarantee.LessPartly and parentDeserved.LessPartly are performed inside the loop over siblings, and then again after adding the current queue's resources. This can be optimized. By accumulating all sibling and current queue resources first and then performing the checks once after the loop, you can reduce redundant computations and improve readability.

	for _, sibling := range siblings {
		if sibling.Name != queue.Name {
			totalGuarantee.Add(api.NewResource(sibling.Spec.Guarantee.Resource))
			totalDeserved.Add(api.NewResource(sibling.Spec.Deserved))
		}
	}

	// Add the current queue's resources
	totalGuarantee.Add(api.NewResource(queue.Spec.Guarantee.Resource))
	totalDeserved.Add(api.NewResource(queue.Spec.Deserved))

	if parentGuarantee.LessPartly(totalGuarantee, api.Zero) {
		return fmt.Errorf("parent queue %s validation failed: sum of children's guarantee (%s) exceeds parent's guarantee limit (%s)",
			parent.Name, totalGuarantee, parentGuarantee)
	}

	if parentDeserved.LessPartly(totalDeserved, api.Zero) {
		return fmt.Errorf("parent queue %s validation failed: sum of children's deserved (%s) exceeds parent's deserved limit (%s)",
			parent.Name, totalDeserved, parentDeserved)
	}

Comment on lines +669 to 682
for _, child := range children {
// Accumulate children's guarantee and deserved
totalGuarantee.Add(api.NewResource(child.Spec.Guarantee.Resource))
if parentGuarantee.LessPartly(totalGuarantee, api.Zero) {
return fmt.Errorf("queue %s validation failed: sum of children's guarantee (%s) exceeds parent's guarantee limit (%s)",
parent.Name, totalGuarantee, parentGuarantee)
}

// validateResourceLimit checks if children's sum exceeds parent's limit
// It checks against parent's explicit limit first, then falls back to capability
func validateResourceLimit(parent *schedulingv1beta1.Queue, childrenSum *api.Resource,
resourceType string, parentResource v1.ResourceList) error {
if len(parentResource) > 0 {
// Parent has explicit resource limit - check against it
parentLimit := api.NewResource(parentResource)
if parentLimit.LessPartly(childrenSum, api.Zero) {
return fmt.Errorf("sum of children's %s (%s) exceeds parent's %s limit (%s)",
resourceType, childrenSum, resourceType, parentLimit)
}
} else if len(parent.Spec.Capability) > 0 {
// Parent has no explicit limit but has capability - check against capability
parentCapability := api.NewResource(parent.Spec.Capability)
if parentCapability.LessPartly(childrenSum, api.Zero) {
return fmt.Errorf("sum of children's %s (%s) exceeds parent's capability (%s)",
resourceType, childrenSum, parentCapability)
totalDeserved.Add(api.NewResource(child.Spec.Deserved))
if parentDeserved.LessPartly(totalDeserved, api.Zero) {
return fmt.Errorf("queue %s validation failed: sum of children's deserved (%s) exceeds parent's deserved limit (%s)",
parent.Name, totalDeserved, parentDeserved)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to validateSiblingsSum, the checks for parentGuarantee.LessPartly and parentDeserved.LessPartly are inside a loop. This can be optimized by accumulating the total resources first and then performing the checks once after the loop. This improves efficiency and readability.

	for _, child := range children {
		// Accumulate children's guarantee and deserved
		totalGuarantee.Add(api.NewResource(child.Spec.Guarantee.Resource))
		totalDeserved.Add(api.NewResource(child.Spec.Deserved))
	}

	if parentGuarantee.LessPartly(totalGuarantee, api.Zero) {
		return fmt.Errorf("queue %s validation failed: sum of children's guarantee (%s) exceeds parent's guarantee limit (%s)",
			parent.Name, totalGuarantee, parentGuarantee)
	}

	if parentDeserved.LessPartly(totalDeserved, api.Zero) {
		return fmt.Errorf("queue %s validation failed: sum of children's deserved (%s) exceeds parent's deserved limit (%s)",
			parent.Name, totalDeserved, parentDeserved)
	}

Comment on lines +2678 to +2690
func contains(s, substr string) bool {
return len(s) >= len(substr) && (s == substr || len(substr) == 0 ||
(len(s) > 0 && len(substr) > 0 && searchSubstring(s, substr)))
}

func searchSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The helper functions contains and searchSubstring are custom implementations of strings.Contains. It's generally better to use functions from the standard library for simplicity and maintainability. You can replace the calls to contains(err.Error(), tt.errSubstr) with strings.Contains(err.Error(), tt.errSubstr) and remove these helper functions.

@hajnalmt hajnalmt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@volcano-sh-bot volcano-sh-bot added the lgtm Indicates that a PR is ready to be merged. label Mar 5, 2026
@JesseStutler

Copy link
Copy Markdown
Member

/approve

@volcano-sh-bot

Copy link
Copy Markdown
Contributor Author

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hajnalmt, JesseStutler

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@volcano-sh-bot volcano-sh-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 5, 2026
@volcano-sh-bot
volcano-sh-bot merged commit 7bcaeed into volcano-sh:release-1.14 Mar 5, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants