Skip to content

feat: expose staleDataUploadThreshold in DPA KubevirtDatamoverConfig - #2361

Open
shubham-pampattiwar wants to merge 1 commit into
openshift:oadp-devfrom
shubham-pampattiwar:feat/stale-du-threshold-config
Open

feat: expose staleDataUploadThreshold in DPA KubevirtDatamoverConfig#2361
shubham-pampattiwar wants to merge 1 commit into
openshift:oadp-devfrom
shubham-pampattiwar:feat/stale-du-threshold-config

Conversation

@shubham-pampattiwar

@shubham-pampattiwar shubham-pampattiwar commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds staleDataUploadThreshold field to KubevirtDatamoverConfig in the DPA spec
  • Operator passes --stale-dataupload-threshold to the kubevirt-datamover-controller deployment when configured
  • DPA YAML path: spec.configuration.kubevirtDatamover.staleDataUploadThreshold

Companion to migtools/kubevirt-datamover-controller#172 (adds the controller flag).
Fixes migtools/kubevirt-datamover-controller#30.

Example DPA Config

spec:
  configuration:
    kubevirtDatamover:
      staleDataUploadThreshold: 2h

Files Changed

  • api/v1alpha1/dataprotectionapplication_types.go -- new StaleDataUploadThreshold *metav1.Duration field
  • api/v1alpha1/zz_generated.deepcopy.go -- regenerated
  • config/crd/bases/ + bundle/manifests/ -- CRD schema updated
  • internal/controller/kubevirt_datamover_controller.go -- arg wiring
  • internal/controller/kubevirt_datamover_controller_test.go -- 3 test cases (configured, not configured, update existing)

Test plan

  • go build ./... passes
  • go test ./internal/controller/ -run TestEnsureKubevirtDatamoverRequiredSpecs -v -- all 14 tests pass
  • go vet ./... clean
  • Deploy on cluster with staleDataUploadThreshold: 1h in DPA, verify controller pod has --stale-dataupload-threshold=1h0m0s arg

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added an optional stale data upload threshold for KubeVirt DataMover configurations.
    • Active data uploads exceeding the configured duration can now be treated as stale; the default is 2 hours.
    • The setting is available through the DataProtectionApplication configuration.

Add staleDataUploadThreshold field to KubevirtDatamoverConfig so
the OADP operator passes --stale-dataupload-threshold to the
kubevirt-datamover-controller deployment. This allows users to
configure how long a stuck DataUpload can block future backups
for the same VM before being skipped.

Companion to migtools/kubevirt-datamover-controller#172.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

The change adds an optional stale DataUpload threshold to KubeVirt DataMover configuration, exposes it in the CRD schemas, passes it to the DataMover container, and adds controller tests for argument handling.

Changes

KubeVirt stale threshold

Layer / File(s) Summary
Threshold configuration contract
api/v1alpha1/dataprotectionapplication_types.go, config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml, bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml
Adds the optional StaleDataUploadThreshold API field and the staleDataUploadThreshold CRD fields. The documented default is 2 hours.
DataMover argument wiring and tests
internal/controller/kubevirt_datamover_controller.go, internal/controller/kubevirt_datamover_controller_test.go
Adds the --stale-dataupload-threshold container argument when configured. Tests cover omission, replacement, and duplicate prevention.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: sseago

🚥 Pre-merge checks | ✅ 13 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR exposes and wires the threshold but does not implement the staleness check in hasOlderActiveDUForVM required by issue #30. Implement stale active DataUpload handling in hasOlderActiveDUForVM and provide evidence that the controller consumes this configuration.
Test Structure And Quality ⚠️ Warning The three threshold cases share TestEnsureKubevirtDatamoverRequiredSpecs, whose each t.Run also asserts unrelated replicas, env, security, probes, volumes, labels, and annotations. Move threshold argument checks into focused table tests or isolate shared deployment invariants so each test covers one behavior.
✅ Passed checks (13 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies exposing staleDataUploadThreshold in the DPA KubevirtDatamoverConfig, which is the main change.
Description check ✅ Passed The description explains the change, references linked issues, shows configuration syntax, lists affected areas, and provides a concrete test plan.
Out of Scope Changes check ✅ Passed The reviewed changes are limited to the API field, CRD schemas, controller argument wiring, and related tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Stable And Deterministic Test Names ✅ Passed The added test cases use static literal names; the changed file's Ginkgo titles are also static, with no timestamps, generated identifiers, namespaces, nodes, or runtime-built titles.
Microshift Test Compatibility ✅ Passed The PR adds no new Ginkgo e2e tests. Its three cases are table-driven Go unit tests using local Kubernetes objects and no MicroShift-unsupported APIs or assumptions.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The PR adds only table-driven unit cases in internal/controller; it adds no new Ginkgo e2e tests or multi-node/HA assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The patch adds only API/CRD fields and a container argument; no new affinity, topology spread, node selector, toleration, PDB, rollout, or topology-derived replica constraint is introduced.
Ote Binary Stdout Contract ✅ Passed The PR adds no stdout or logging calls. Added Go code uses fmt.Sprintf and test assertions only; controller suite logging already targets GinkgoWriter.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR adds only table-driven Go unit cases; the existing Ginkgo block is unchanged, and new additions contain no IPv4 assumptions or external network operations.
No-Weak-Crypto ✅ Passed The PR adds only duration configuration, deepcopy logic, Kubernetes arguments, schemas, and tests; no weak crypto primitive, custom crypto, or secret/token comparison was introduced.
Container-Privileges ✅ Passed The PR adds only a duration field and container argument. The KubeVirt DataMover pod remains non-root, drops ALL capabilities, and sets allowPrivilegeEscalation=false; no prohibited host or SYS_ADM...
No-Sensitive-Data-In-Logs ✅ Passed The PR adds no production logging. The new value is placed in container args, and test diagnostics print only non-sensitive deployment arguments.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci
openshift-ci Bot requested review from Joeavaikath and sseago August 6, 2026 20:52
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/controller/kubevirt_datamover_controller.go`:
- Around line 243-246: The controller currently appends the unsupported
--stale-dataupload-threshold argument in the DPA argument-building flow; remove
this append block unless the kubevirt-datamover-controller manager is updated to
declare the flag and its 2h default first. Ensure configured
StaleDataUploadThreshold values no longer produce an unknown manager flag.
🪄 Autofix

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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 64d44322-69f8-478a-b35f-2358e55d489e

📥 Commits

Reviewing files that changed from the base of the PR and between 5b6f637 and 81bd044.

⛔ Files ignored due to path filters (1)
  • api/v1alpha1/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (5)
  • api/v1alpha1/dataprotectionapplication_types.go
  • bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml
  • config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml
  • internal/controller/kubevirt_datamover_controller.go
  • internal/controller/kubevirt_datamover_controller_test.go

Comment on lines +243 to +246
if dpa.Spec.Configuration.KubevirtDatamover.StaleDataUploadThreshold != nil {
args = append(args, fmt.Sprintf("--stale-dataupload-threshold=%s",
dpa.Spec.Configuration.KubevirtDatamover.StaleDataUploadThreshold.Duration.String()))
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Locate the flag declaration and all operator-side references.
rg -n -C 5 --glob '*.go' \
  -e 'stale-dataupload-threshold|staleDataUploadThreshold|StaleDataUploadThreshold' .

# Locate the manager image/version source used by this operator.
rg -n -C 3 \
  --glob '*.go' --glob '*.yaml' --glob '*.yml' --glob 'go.mod' --glob 'go.sum' \
  -e 'kubevirt-datamover' .

Repository: openshift/oadp-operator

Length of output: 50379


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect the exact deployment argument wiring and image resolution without
# emitting the repository-wide search results that were truncated.
sed -n '200,275p' internal/controller/kubevirt_datamover_controller.go
sed -n '350,395p' internal/controller/kubevirt_datamover_controller.go
rg -n -C 4 --glob '*.go' --glob '*.yaml' --glob '*.yml' \
  -e 'RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER|kubevirt-datamover-controller:[^[:space:]]+' .

# Check whether the manager source is vendored or referenced through a
# dependency, and query the public source tree for the flag declaration.
git ls-files | rg '(^|/)(vendor|go.mod|go.sum|Dockerfile|Makefile|Containerfile|.*kubevirt.*datamover.*)$' || true
for url in \
  'https://api.github.com/search/code?q=stale-dataupload-threshold+in:file' \
  'https://api.github.com/repos/konveyor/kubevirt-datamover/contents' \
  'https://api.github.com/repos/kubevirt/kubevirt-datamover/contents'
do
  echo "=== $url"
  curl -LfsS --max-time 20 "$url" 2>/dev/null | head -c 12000 || true
  printf '\n'
done

Repository: openshift/oadp-operator

Length of output: 14654


🌐 Web query:

kubevirt-datamover-controller "stale-dataupload-threshold"

💡 Result:

The stale-dataupload-threshold refers to a proposed configuration mechanism within the kubevirt-datamover-controller designed to identify and ignore "stuck" DataUpload (DU) resources [1]. Because Velero does not apply its standard DataUpload timeout to custom data movers, an orphaned or stalled DataUpload that remains indefinitely in an active phase (e.g., Accepted, Prepared, or InProgress) can block all subsequent backups for the same Virtual Machine [1]. To resolve this, a staleness threshold was proposed to allow the controller to recognize when a blocking DataUpload has exceeded a configurable duration—such as 30 minutes—and subsequently ignore it [1]. This ensures that younger, potentially healthy DataUploads are not permanently blocked by a stale process [1]. It is important to distinguish this from standard Velero timeouts: - The kubevirt-datamover-controller mechanism targets specific issues with per-VM serialization where one stuck DU prevents others from proceeding [1]. - Standard Velero backups use parameters like --item-operation-timeout (default 4 hours) and data-mover-prepare-timeout (default 30 minutes) to manage general DataUpload lifecycle timeouts [2]. As of the current development context, this threshold is identified as a solution to prevent indefinite backup blocking for VMs [1]. Users managing KubeVirt backups via this controller should be aware that this specific threshold is intended to provide a safety net where Velero's default mechanisms do not apply [1].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

repo='migtools/kubevirt-datamover-controller'
echo '=== repository metadata ==='
curl -LfsS --max-time 20 "https://api.github.com/repos/$repo" |
  jq '{full_name,default_branch,archived,updated_at}'

branch=$(curl -LfsS --max-time 20 "https://api.github.com/repos/$repo" |
  jq -r '.default_branch')
echo "=== tree: $branch ==="
curl -LfsS --max-time 20 \
  "https://api.github.com/repos/$repo/git/trees/$branch?recursive=1" |
  jq -r '.tree[] | select(.path|test("\\.(go|yaml|yml|md)$")) | .path' |
  head -200

echo '=== flag references in default-branch source ==='
curl -LfsS --max-time 20 \
  "https://api.github.com/repos/$repo/git/trees/$branch?recursive=1" |
  jq -r '.tree[] | select(.type=="blob" and (.path|test("\\.go$"))) | .url' |
  while read -r blob; do
    curl -LfsS --max-time 20 "$blob" |
      jq -r '.content // empty' | base64 -d 2>/dev/null |
      grep -n -C 5 -E 'stale-dataupload-threshold|staleDataUploadThreshold' || true
  done

echo '=== issue 30 ==='
curl -LfsS --max-time 20 "https://api.github.com/repos/$repo/issues/30" |
  jq '{title,state,body,html_url}'

Repository: openshift/oadp-operator

Length of output: 240


🌐 Web query:

site:github.com/migtools/kubevirt-datamover-controller "stale-dataupload-threshold"

💡 Result:

The term stale-dataupload-threshold refers to a proposed or implemented configuration parameter within the kubevirt-datamover-controller project [1][2]. It is used to define a duration of time after which an active DataUpload resource that appears stuck is considered stale [1]. In the context of the kubevirt-datamover-controller, the controller implements per-VM serialization of DataUploads, where newer DataUploads are requeued if an older one for the same VM is already in an active phase [1]. If a DataUpload becomes stuck in an active phase (for example, due to a controller crash or an orphaned process), it can indefinitely block all future backups for that VM because Velero's built-in DataUpload timeouts do not apply to these custom data movers [1]. To mitigate this, the stale-dataupload-threshold allows the controller to ignore such blocking DataUploads if they have remained in their current active phase longer than the configured duration [1]. When a DataUpload is identified as having exceeded this threshold, the controller can proceed to ignore or transition it to a terminal state, such as Failed, thereby preventing it from blocking subsequent backups [1]. The implementation suggested in technical discussions uses this threshold to skip DataUploads whose creation timestamp plus the defined duration is older than the current time [1].

Citations:


🌐 Web query:

site:github.com/migtools/kubevirt-datamover-controller "StaleDataUploadThreshold"

💡 Result:

StaleDataUploadThreshold is a configuration parameter (typically a duration) proposed for the migtools/kubevirt-datamover-controller [1][2]. It is intended to manage the lifecycle of DataUpload resources by identifying and handling potentially orphaned or stuck operations [1]. In the context of the KubeVirt Data Mover for Velero, the controller implements per-VM serialization of DataUploads to prevent concurrent operations on the same virtual machine [1]. If an older DataUpload remains stuck in an active phase (such as Accepted, Prepared, or InProgress) indefinitely—potentially due to a controller crash or orphaned process—subsequent younger DataUploads for that same VM would be requeued indefinitely [1]. The StaleDataUploadThreshold is proposed as a mechanism to address this by allowing the controller to ignore a blocking DataUpload if it has remained in its current active phase for longer than this specified threshold [1]. By treating such operations as "stale," the controller can bypass the blockage and potentially transition the stuck resource to a failed state, thereby preventing future backups for that VM from being blocked indefinitely [1].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Use read-only Git transport and raw file retrieval because the GitHub API
# rate limit rejected the metadata request.
for remote in \
  https://github.com/migtools/kubevirt-datamover-controller.git \
  https://github.com/konveyor/kubevirt-datamover-controller.git
do
  echo "=== $remote refs ==="
  git ls-remote --heads --tags "$remote" 2>&1 | head -80 || true
done

for path in \
  cmd/main.go \
  main.go \
  controller/main.go \
  internal/controller/main.go \
  pkg/controller/main.go
do
  for branch in main master; do
    url="https://raw.githubusercontent.com/migtools/kubevirt-datamover-controller/$branch/$path"
    body=$(curl -LfsS --max-time 20 "$url" 2>/dev/null || true)
    if [ -n "$body" ]; then
      echo "=== $url ==="
      printf '%s\n' "$body" | grep -n -C 8 \
        -E 'stale-dataupload-threshold|staleDataUploadThreshold|flag\.Duration|2h' || true
    fi
  done
done

Repository: openshift/oadp-operator

Length of output: 2335


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

repo='https://github.com/migtools/kubevirt-datamover-controller.git'
echo '=== default branch and tags ==='
git ls-remote --symref "$repo" HEAD
git ls-remote --tags "$repo" | tail -40

branch=$(git ls-remote --symref "$repo" HEAD | awk '$1=="ref:" {sub("refs/heads/","",$2); print $2}')
[ -n "$branch" ] || branch=oadp-dev
echo "=== source files in $branch ==="
curl -LfsS --max-time 30 \
  "https://codeload.github.com/migtools/kubevirt-datamover-controller/tar.gz/refs/heads/$branch" |
  tar -tzf - | grep -E '\.(go|yaml|yml|md)$' | head -250

echo "=== flag and default references in $branch ==="
curl -LfsS --max-time 30 \
  "https://codeload.github.com/migtools/kubevirt-datamover-controller/tar.gz/refs/heads/$branch" |
  tar -xzf - --to-stdout --wildcards '*/go.mod' '*/main.go' '*/cmd/*.go' '*/internal/**/*.go' '*/pkg/**/*.go' 2>/dev/null |
  grep -n -C 8 -E \
    'stale-dataupload-threshold|staleDataUploadThreshold|flag\.Duration|2h' || true

Repository: openshift/oadp-operator

Length of output: 5167


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

repo='https://github.com/migtools/kubevirt-datamover-controller.git'
branch='oadp-dev'

echo '=== manager entry point ==='
curl -LfsS --max-time 30 \
  "https://codeload.github.com/migtools/kubevirt-datamover-controller/tar.gz/refs/heads/$branch" |
  tar -xzf - --to-stdout "kubevirt-datamover-controller-$branch/cmd/main.go" |
  cat -n

echo '=== all Go-source references on the default branch ==='
curl -LfsS --max-time 30 \
  "https://codeload.github.com/migtools/kubevirt-datamover-controller/tar.gz/refs/heads/$branch" |
  tar -xzf - --to-stdout --wildcards \
    "kubevirt-datamover-controller-$branch/*.go" \
    "kubevirt-datamover-controller-$branch/**/*.go" 2>/dev/null |
  grep -n -C 5 -E \
    'stale-dataupload-threshold|staleDataUploadThreshold|flag\.Duration|2h' || true

echo '=== flag references across all remote branches ==='
git ls-remote --heads "$repo" |
  awk '{sub("refs/heads/","",$2); print $2}' |
  while IFS= read -r branch; do
    encoded_branch=$(printf '%s' "$branch" | sed 's#/#%2F#g')
    matches=$(
      curl -LfsS --max-time 30 \
        "https://codeload.github.com/migtools/kubevirt-datamover-controller/tar.gz/refs/heads/$encoded_branch" |
      tar -xzf - --to-stdout --wildcards \
        "kubevirt-datamover-controller-$branch/*.go" \
        "kubevirt-datamover-controller-$branch/**/*.go" 2>/dev/null |
      grep -n -E 'stale-dataupload-threshold|staleDataUploadThreshold|flag\.Duration|2h' || true
    )
    if [ -n "$matches" ]; then
      echo "=== branch: $branch ==="
      printf '%s\n' "$matches"
    fi
  done

Repository: openshift/oadp-operator

Length of output: 13396


Do not pass an unsupported manager flag.

The kubevirt-datamover-controller manager does not declare --stale-dataupload-threshold or a 2h default. When configured, this argument causes manager startup to fail with an unknown-flag error. Add the flag and default to the manager first, or remove this operator argument.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/kubevirt_datamover_controller.go` around lines 243 - 246,
The controller currently appends the unsupported --stale-dataupload-threshold
argument in the DPA argument-building flow; remove this append block unless the
kubevirt-datamover-controller manager is updated to declare the flag and its 2h
default first. Ensure configured StaleDataUploadThreshold values no longer
produce an unknown manager flag.

@openshift-ci

openshift-ci Bot commented Aug 7, 2026

Copy link
Copy Markdown

@shubham-pampattiwar: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/5.1-images 81bd044 link true /test 5.1-images
ci/prow/5.1-e2e-test-aws 81bd044 link true /test 5.1-e2e-test-aws
ci/prow/5.1-ci-index 81bd044 link true /test 5.1-ci-index
ci/prow/5.1-e2e-test-cli-aws 81bd044 link true /test 5.1-e2e-test-cli-aws

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-ci

openshift-ci Bot commented Aug 7, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: shubham-pampattiwar, sseago

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:
  • OWNERS [shubham-pampattiwar,sseago]

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

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add staleness check for per-VM DataUpload serialization

2 participants