Skip to content

Refine scheduling for exclusive, cluster and hw spec configs - #71

Merged
avasilevskii merged 3 commits into
openshift-psap:mainfrom
avasilevskii:refine-exclusive-cluster-hw-spec
Apr 29, 2026
Merged

Refine scheduling for exclusive, cluster and hw spec configs#71
avasilevskii merged 3 commits into
openshift-psap:mainfrom
avasilevskii:refine-exclusive-cluster-hw-spec

Conversation

@avasilevskii

@avasilevskii avasilevskii commented Apr 28, 2026

Copy link
Copy Markdown

Closes #67

Summary by CodeRabbit

  • New Features

    • Exclusive cluster locking is now the default; set exclusive: false to allow shared cluster access.
    • When exclusively locking a cluster, hardware becomes optional (cluster-slot-only runs supported).
  • Bug Fixes / Behavior Changes

    • Jobs must now include exclusive (omitting it may cause validation failures); non-exclusive jobs continue to require hardware.
  • Documentation

    • Design doc and README updated to clarify new scheduling semantics and requirements.
  • Tests

    • Added and updated tests covering exclusive/non-exclusive and hardware scenarios.

Signed-off-by: avasilev <avasilev@redhat.com>
@openshift-ci

openshift-ci Bot commented Apr 28, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign kpouget for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@avasilevskii has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 6 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a15c1c60-85ba-4695-a1ce-833dae7db861

📥 Commits

Reviewing files that changed from the base of the PR and between 3554158 and 066bb6a.

📒 Files selected for processing (1)
  • fournos/handlers/resolving.py
📝 Walkthrough

Walkthrough

Defaults and validation for spec.exclusive, spec.cluster, and spec.hardware were changed: spec.exclusive now defaults to true; exclusive+cluster jobs may omit hardware (request cluster-slot resources only); non-exclusive jobs must explicitly set exclusive: false and provide hardware. Docs, CRD, handlers, Kueue client, and tests were updated accordingly.

Changes

Cohort / File(s) Summary
Documentation & Schema
Fournos_Design_Document.md, README.md, manifests/crd.yaml
Documented new default spec.exclusive: true, clarified that selecting spec.cluster locks the cluster by default, and updated hardware requirement semantics (hardware optional for exclusive+cluster jobs).
Core Client
fournos/core/kueue.py
Changed KueueClient.create_workload(..., exclusive: bool = True) default from False → requests MAX_CLUSTER_SLOTS when exclusive omitted.
Handler Logic
fournos/handlers/lifecycle.py, fournos/handlers/status.py
Removed fallback (spec.get("exclusive", False)) in favor of direct spec["exclusive"], making exclusive required in handled specs.
Resolution Logic
fournos/handlers/resolving.py
_resolve_hardware now distinguishes exclusive+cluster (returns (None, 0) and warns) vs non-exclusive (fails with reason="NoHardware"); callers updated to check gpu_count is None and pass exclusive=spec["exclusive"].
Tests
tests/... (test_exclusive.py, test_scheduling.py, test_resolving.py, test_validation.py, test_lifecycle.py, test_shutdown.py)
Updated many tests to set "exclusive": False where appropriate; added tests for exclusive-without-hardware, non-exclusive cluster-without-hardware failure, shared cluster-with-hardware, and implicit-exclusive-without-cluster failure.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant FournosController as Controller
  participant Resolving
  participant KueueClient as Kueue
  participant KueueServer as KueueServer

  User->>Controller: Create/Update FournosJob (spec.cluster?, spec.exclusive?, spec.hardware?)
  Controller->>Resolving: reconcile_resolving(job.spec)
  Resolving->>Resolving: _resolve_hardware(spec) -> (gpu_type, gpu_count) or (None,None) or (None,0)
  alt validation failure
    Resolving->>Controller: Patch job Failed (reason="NoHardware")
  else success
    Resolving->>Kueue: create_workload(..., exclusive=spec["exclusive"], slots=MAX or 1, gpu_type/count)
    Kueue->>KueueServer: Submit workload to scheduler
    KueueServer-->>Kueue: admission/queueing
    Kueue-->>Controller: Workload created / status
    Controller-->>User: Job transitions (Pending → Running → Succeeded/Failed)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

lgtm

Poem

🐇 I hopped in code where clusters sleep,

Locks now snug, or shares to keep,
Hardware whispers, slots obey,
Defaults changed to lead the way,
Hooray — the jobs can dance and play! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: refining scheduling behavior for spec.exclusive, spec.cluster, and spec.hardware fields, which aligns with the PR's core objective.
Linked Issues check ✅ Passed The PR successfully implements both use-cases from issue #67: exclusive cluster access without hardware (spec.exclusive=true, spec.cluster set, hardware optional) and shared cluster access with hardware (spec.exclusive=false, spec.cluster set, hardware specified).
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the exclusive/cluster/hardware refinement: CRD defaults, handler logic, workload creation defaults, validation, and comprehensive test coverage. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
tests/test_scheduling.py (1)

175-180: Reduce pre-inspection race when asserting Workload fields.

At Line 175, the pre-check allows Phase.SUCCEEDED; if that happens first, Workload inspection at Lines 182-191 can become timing-sensitive.

Suggested stabilization
-    poll_phase(
+    phase = poll_phase(
         k8s,
         "test-shared-hw",
-        terminal={Phase.RUNNING, Phase.SUCCEEDED, Phase.FAILED},
+        terminal={Phase.PENDING, Phase.ADMITTED, Phase.RUNNING, Phase.FAILED},
         timeout=30,
     )
+    assert phase != Phase.FAILED, job_status_summary(k8s, "test-shared-hw")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_scheduling.py` around lines 175 - 180, The pre-check call to
poll_phase includes Phase.SUCCEEDED which can cause the test to observe a
finished Workload before the subsequent Workload inspection block runs, making
assertions flaky; change the poll_phase invocation to wait for the Workload to
reach an active state (e.g., only Phase.RUNNING and Phase.FAILED, or exclusively
Phase.RUNNING) instead of including Phase.SUCCEEDED so the test always inspects
the Workload while it is running, then proceed with the existing Workload
inspection/assertion code (the poll_phase call and the following Workload
inspection block should be updated accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/test_scheduling.py`:
- Around line 175-180: The pre-check call to poll_phase includes Phase.SUCCEEDED
which can cause the test to observe a finished Workload before the subsequent
Workload inspection block runs, making assertions flaky; change the poll_phase
invocation to wait for the Workload to reach an active state (e.g., only
Phase.RUNNING and Phase.FAILED, or exclusively Phase.RUNNING) instead of
including Phase.SUCCEEDED so the test always inspects the Workload while it is
running, then proceed with the existing Workload inspection/assertion code (the
poll_phase call and the following Workload inspection block should be updated
accordingly).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21b7511f-72b4-4bb3-9fd0-601bfdc36b98

📥 Commits

Reviewing files that changed from the base of the PR and between 103007c and 2d77f9c.

📒 Files selected for processing (13)
  • Fournos_Design_Document.md
  • README.md
  • fournos/core/kueue.py
  • fournos/handlers/lifecycle.py
  • fournos/handlers/resolving.py
  • fournos/handlers/status.py
  • manifests/crd.yaml
  • tests/test_exclusive.py
  • tests/test_lifecycle.py
  • tests/test_resolving.py
  • tests/test_scheduling.py
  • tests/test_shutdown.py
  • tests/test_validation.py

Comment thread fournos/handlers/resolving.py
Signed-off-by: avasilev <avasilev@redhat.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@fournos/handlers/resolving.py`:
- Around line 128-140: Update the function docstring in resolving.py to reflect
the new exclusive-only path that skips GPU validation: change the sentence that
currently says the GPU type is "always validated against Kueue" to clarify that
GPU validation is performed except when the function returns the exclusive-only
sentinel (gpu_type is None and gpu_count is 0), in which case GPU validation is
intentionally skipped; keep the return description showing "(gpu_type,
gpu_count)" for success and "(None, None)" for validation failure and explicitly
document that "(None, 0)" represents the exclusive-only cluster-lock path that
bypasses Kueue validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d232ae33-e77e-4e21-bcc6-1a9b323397d7

📥 Commits

Reviewing files that changed from the base of the PR and between 2d77f9c and 3554158.

📒 Files selected for processing (1)
  • fournos/handlers/resolving.py

Comment thread fournos/handlers/resolving.py
Signed-off-by: avasilev <avasilev@redhat.com>
@avasilevskii

Copy link
Copy Markdown
Author

/test deploy-fournos-wip

@psap-forge-bot

Copy link
Copy Markdown

🟢 Test of 'fournos_deploy --project-source' succeeded after 00 hours 09 minutes 52 seconds 🟢

• Link to the test results.

• No reports index generated...

Test configuration:

/test deploy-fournos-wip

Execution logs

@kpouget

kpouget commented Apr 29, 2026

Copy link
Copy Markdown
Collaborator

thanks @avasilevskii ,
/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Apr 29, 2026
@avasilevskii
avasilevskii merged commit 566ff8a into openshift-psap:main Apr 29, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TASK: refine the current behavior of the exclusive/cluster/hardware flags

2 participants