Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6791056
Add multi-PVC VM e2e scaffolding for kubevirt-datamover
kaovilai Aug 4, 2026
c2cd28e
Add incremental-sequence e2e coverage for kubevirt-datamover
kaovilai Aug 4, 2026
db40ba2
Fix CodeRabbit findings on incremental-sequence e2e coverage
kaovilai Aug 4, 2026
d766a78
Use utilruntime.Must for e2e scheme registration
kaovilai Aug 5, 2026
178d1b3
Fail explicitly when VMB.status.type is not yet populated
kaovilai Aug 5, 2026
124d306
Pin kubevirt-datamover-controller image to unmerged DataDownload PR
kaovilai Aug 5, 2026
9d5199e
Add restore-from-CBT-backup e2e coverage, plus phase 4/5 scaffolds
kaovilai Aug 5, 2026
d05bd58
Fix CodeRabbit findings: rollout check, checkpointName, image-overrid…
kaovilai Aug 5, 2026
9b06540
Sync kubevirt-datamover-controller RBAC for DataDownload/restore support
kaovilai Aug 5, 2026
0291219
Add kubevirt#18724 VMB-finalizer workaround, fix VMB-status race, pin…
kaovilai Aug 5, 2026
c300f00
Regenerate bundle to fix RBAC drift from oadp-dev rebase conflict
kaovilai Aug 5, 2026
67e826f
Grant update on kubevirt.io/virtualmachines for kdm-controller RBAC
kaovilai Aug 6, 2026
917b6bc
Fix coderabbit findings in virt_helpers.go
kaovilai Aug 6, 2026
2f5dbf7
Bump kubevirt-datamover-plugin digest to latest pr-44 build
kaovilai Aug 6, 2026
de79f50
Assert Block volumeMode is actually exercised on CBT restore
kaovilai Aug 6, 2026
bc60755
Assert VM stays halted when its DataDownload is rejected
kaovilai Aug 6, 2026
30a3352
Confirm kubevirt-datamover PVCs carry no spec.selector
kaovilai Aug 6, 2026
91931ff
Bump plugin+controller digests to both PRs' latest tips
kaovilai Aug 6, 2026
15c992a
Add data-integrity checksum verification to CBT restore e2e, and #169…
kaovilai Aug 7, 2026
2a30320
Add useEmulation-based Fedora skip check for kubevirt-datamover CBT e2e
kaovilai Aug 7, 2026
eba3fb3
Add incremental CBT restore data-integrity test via Alpine guest-exec
kaovilai Aug 7, 2026
89517ef
Consolidate CBT restore data-integrity tests onto Alpine guest-exec f…
kaovilai Aug 7, 2026
73005d8
Promote Fedora CBT case from backup-only to full backup+restore test
kaovilai Aug 7, 2026
ac333fc
Add TEST_VIRT_KDM to run only kubevirt-datamover-specific e2e specs
kaovilai Aug 7, 2026
307d369
Update kubevirt-datamover-controller test image to e66317e build
kaovilai Aug 12, 2026
cf64841
Remove kubevirt-datamover plugin/controller test image overrides
kaovilai Aug 13, 2026
7c4a461
Address shubham-pampattiwar review feedback on PR #2350
kaovilai Aug 13, 2026
9beda53
Add curl/git retry resilience to CI/dev tool fetches
kaovilai Aug 13, 2026
8a602f6
Fix silent retry-loop failure and harden checksum-helper pod name
kaovilai Aug 17, 2026
eb5a661
Expose kubevirt-datamover --max-concurrent-data-movers via DPA CRD
kaovilai Aug 14, 2026
9be28a6
Merge remote-tracking branch 'upstream/oadp-dev' into worktree-kubevi…
kaovilai Aug 17, 2026
ffcab7d
Add e2e coverage for kubevirt-datamover max-concurrent-data-movers li…
kaovilai Aug 18, 2026
fe54f4d
Hardcode kdm concurrency-limiter test image so Prow actually runs it
kaovilai Aug 18, 2026
5a0a023
Drop personal quay.io override, test against default kdm image
kaovilai Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ ifneq ($(shell $(OPERATOR_SDK) version | cut -d'"' -f2),$(OPERATOR_SDK_VERSION))
set -e; \
mkdir -p $(dir $(OPERATOR_SDK)) ;\
OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \
curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\
curl --retry 5 --retry-delay 5 -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\
chmod +x $(OPERATOR_SDK);
endif
@if [ -L "$(LOCALBIN)/operator-sdk" ]; then \
Expand Down Expand Up @@ -370,7 +370,7 @@ ifneq ($(shell $(OPM) version | cut -d'"' -f2),$(OPM_VERSION))
set -e ;\
mkdir -p $(dir $(OPM)) ;\
OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \
curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/$(OPM_VERSION)/$${OS}-$${ARCH}-opm ;\
curl --retry 5 --retry-delay 5 -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/$(OPM_VERSION)/$${OS}-$${ARCH}-opm ;\
chmod +x $(OPM)
endif
@if [ -L "$(LOCALBIN)/opm" ]; then \
Expand Down Expand Up @@ -499,7 +499,7 @@ else
endif
endif
submit-coverage:
curl -Os https://uploader.codecov.io/latest/$(OS_String)/codecov
curl --retry 5 --retry-delay 5 -Os https://uploader.codecov.io/latest/$(OS_String)/codecov
chmod +x codecov
./codecov -C $(shell git rev-parse HEAD) -r openshift/oadp-operator --nonZero
rm -f codecov
Expand Down Expand Up @@ -965,6 +965,13 @@ ARTIFACT_DIR ?= /tmp
HCO_UPSTREAM ?= false
TEST_VIRT_GA ?= false
TEST_VIRT ?= false
# TEST_VIRT_KDM runs only the kubevirt-datamover-specific specs (ginkgo label
# "kdm", a subset of "virt") -- for CI jobs that build/test against the
# kubevirt-datamover-controller/-plugin repos specifically and don't need the
# full TEST_VIRT suite's runtime. TEST_VIRT=true already covers these specs
# too, since they carry both labels -- this only matters when TEST_VIRT_KDM
# is set WITHOUT TEST_VIRT.
TEST_VIRT_KDM ?= false
HCO_INDEX_TAG ?= 1.18.0
# hcp
TEST_HCP ?= false
Expand All @@ -989,9 +996,21 @@ ifeq ($(TEST_VIRT),true)
TEST_FILTER += && (virt)
else ifeq ($(TEST_VIRT_GA),true)
TEST_FILTER += && (virt)
else ifeq ($(TEST_VIRT_KDM),true)
TEST_FILTER += && (kdm)
else
TEST_FILTER += && (! virt)
endif
# kdm specs need the same community-HCO/KubeVirt setup as the rest of the virt
# suite (TEST_VIRT's own -hco_community wiring below) -- without this,
# TEST_VIRT_KDM=true alone (i.e. without TEST_VIRT=true) would leave
# -hco_community=false and skip installing HCO entirely, breaking the kdm-only
# run before any spec even gets a VM to test against.
ifeq ($(TEST_VIRT_KDM),true)
HCO_COMMUNITY := true
else
HCO_COMMUNITY := $(TEST_VIRT)
endif
ifeq ($(TEST_UPGRADE),true)
TEST_FILTER += && (upgrade)
else
Expand Down Expand Up @@ -1049,7 +1068,7 @@ test-e2e: test-e2e-setup install-ginkgo $(if $(MUST_GATHER_REPO),build-must-gath
-artifact_dir=$(ARTIFACT_DIR) \
-kvm_emulation=$(KVM_EMULATION) \
-hco_upstream=$(HCO_UPSTREAM) \
-hco_community=$(TEST_VIRT) \
-hco_community=$(HCO_COMMUNITY) \
-hco_index_tag=$(HCO_INDEX_TAG) \
-skipMustGather=$(SKIP_MUST_GATHER) \
$(HCP_EXTERNAL_ARGS) \
Expand Down
7 changes: 7 additions & 0 deletions api/v1alpha1/dataprotectionapplication_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,13 @@ type KubevirtDatamoverConfig struct {
// +optional
MaxIncrementalBackups *int32 `json:"maxIncrementalBackups,omitempty"`

// MaxConcurrentDataMovers is the maximum number of concurrent active
// DataUploads/DataDownloads per direction (DU and DD counted independently).
// 0 means unlimited (default behavior).
// +kubebuilder:validation:Minimum=0
// +optional
MaxConcurrentDataMovers *int32 `json:"maxConcurrentDataMovers,omitempty"`

// StaleDataUploadThreshold is the duration after which a DataUpload in an
// active phase is considered stale and will no longer block younger
// DataUploads for the same VM. Default is 2h.
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 28 additions & 7 deletions build/ci-Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,47 @@ RUN chmod +x tests/e2e/scripts/analyze_failures.sh

# Install kubectl (multi-arch)
ARG TARGETARCH
RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${TARGETARCH}/kubectl" && \
# --retry: curl's default retry set already covers exit 6 (could not resolve
# host) -- the exact transient DNS failure hit live in CI on this same class
# of fetch (see the virtctl step below) -- along with connect/read/5xx errors.
RUN curl --retry 5 --retry-delay 5 -LO "https://dl.k8s.io/release/$(curl --retry 5 --retry-delay 5 -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${TARGETARCH}/kubectl" && \
chmod +x kubectl && \
mv kubectl /usr/local/bin/

# Install virtctl for KubeVirt VM operations in E2E tests
RUN export KV_VERSION=$(curl -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt) && \
curl -L -o virtctl "https://github.com/kubevirt/kubevirt/releases/download/${KV_VERSION}/virtctl-${KV_VERSION}-linux-${TARGETARCH}" && \
# --retry: confirmed live in CI -- this exact curl failed with "Could not
# resolve host: github.com" (transient DNS blip in the build environment),
# failing the whole image build over a network hiccup unrelated to any code
# change. curl's default retry-on-error set already covers that failure mode
# (exit 6); no extra flags needed beyond --retry/--retry-delay.
RUN export KV_VERSION=$(curl --retry 5 --retry-delay 5 -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt) && \
curl --retry 5 --retry-delay 5 -L -o virtctl "https://github.com/kubevirt/kubevirt/releases/download/${KV_VERSION}/virtctl-${KV_VERSION}-linux-${TARGETARCH}" && \
chmod +x virtctl && \
mv virtctl /usr/local/bin/

# Install Claude CLI (native binary, no Node.js dependency)
RUN curl -fsSL https://claude.ai/install.sh | bash && \
RUN curl --retry 5 --retry-delay 5 -fsSL https://claude.ai/install.sh | bash && \
ln -sf ~/.local/bin/claude /usr/local/bin/claude && \
claude --version

# Clone openshift/velero source code for failure analysis
# Uses oadp-dev branch to match OADP operator development
RUN git clone --depth 1 --branch oadp-dev \
https://github.com/openshift/velero.git \
/go/src/github.com/openshift/velero
# Retried like the curl fetches above -- same category of transient
# network/DNS blip, just via git instead of curl (no built-in --retry flag).
# rm -rf before each attempt: a clone that fails partway through can leave a
# non-empty target directory behind, which would make the next attempt fail
# with "destination path already exists" instead of actually retrying.
# The trailing `test -d .../.git` is load-bearing, not decoration: without it,
# `&& break || sleep 5` makes the loop's own exit status the last `sleep`'s
# (always 0), so RUN succeeds even after all 3 clone attempts fail -- silently
# shipping an image with no velero checkout instead of failing the build here.
RUN for i in 1 2 3; do \

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.

This retry loop exits 0 even when all three clones fail. git clone ... && break || sleep 5: on failure the && break is skipped and || sleep 5 returns 0, so after three misses the loop's status is the last sleep, and the RUN succeeds with no velero checkout. The build then continues and only degrades failure-analysis later, instead of failing here.

Every other fetch in this file uses curl --retry, which does fail the build after exhausting retries. Worth making this one consistent, e.g. assert the result after the loop:

RUN for i in 1 2 3; do \
      rm -rf /go/src/github.com/openshift/velero && \
      git clone --depth 1 --branch oadp-dev \
        https://github.com/openshift/velero.git \
        /go/src/github.com/openshift/velero && break || sleep 5; \
    done; \
    test -d /go/src/github.com/openshift/velero/.git

rm -rf /go/src/github.com/openshift/velero && \
git clone --depth 1 --branch oadp-dev \
https://github.com/openshift/velero.git \
/go/src/github.com/openshift/velero && break || sleep 5; \
done; \
test -d /go/src/github.com/openshift/velero/.git

RUN go mod download && \
mkdir -p $(go env GOCACHE) && \
Expand Down
8 changes: 8 additions & 0 deletions bundle/manifests/oadp-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,13 @@ spec:
- get
- list
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- ""
resources:
Expand Down Expand Up @@ -1330,6 +1337,7 @@ spec:
verbs:
- get
- list
- update
- watch
- apiGroups:
- velero.io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ spec:
kubevirtDatamover:
description: KubevirtDatamover configures the kubevirt-datamover-controller for VM backup/restore.
properties:
maxConcurrentDataMovers:
description: |-
MaxConcurrentDataMovers is the maximum number of concurrent active
DataUploads/DataDownloads per direction (DU and DD counted independently).
0 means unlimited (default behavior).
format: int32
minimum: 0
type: integer
maxIncrementalBackups:
description: |-
MaxIncrementalBackups is the maximum number of incremental backups per VM
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ spec:
kubevirtDatamover:
description: KubevirtDatamover configures the kubevirt-datamover-controller for VM backup/restore.
properties:
maxConcurrentDataMovers:
description: |-
MaxConcurrentDataMovers is the maximum number of concurrent active
DataUploads/DataDownloads per direction (DU and DD counted independently).
0 means unlimited (default behavior).
format: int32
minimum: 0
type: integer
maxIncrementalBackups:
description: |-
MaxIncrementalBackups is the maximum number of incremental backups per VM
Expand Down
8 changes: 8 additions & 0 deletions config/kubevirt-datamover-controller_rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ kind: ClusterRole
metadata:
name: manager-role
rules:
- apiGroups:
- ""
resources:
- events

@shubham-pampattiwar shubham-pampattiwar Aug 13, 2026

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.

This events: create,patch rule isn't mentioned in the description, unlike the update on virtualmachines. Two things:

  1. Were role.yaml and the CSV regenerated via make update-kubevirt-datamover-manifests, or hand-edited? This file syncs from the controller repo, so hand edits drift on the next sync and can diverge from the CSV.
  2. Please add a line to the description explaining the events rule so the CSV grant is traceable.

verbs:
- create
- patch
- apiGroups:
- ""
resources:
Expand Down Expand Up @@ -85,6 +92,7 @@ rules:
verbs:
- get
- list
- update
- watch
- apiGroups:
- velero.io
Expand Down
4 changes: 4 additions & 0 deletions internal/controller/kubevirt_datamover_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ func ensureKubevirtDatamoverRequiredSpecs(
args = append(args, fmt.Sprintf("--max-incremental-backups=%d",
*dpa.Spec.Configuration.KubevirtDatamover.MaxIncrementalBackups))
}
if dpa.Spec.Configuration.KubevirtDatamover.MaxConcurrentDataMovers != nil {
args = append(args, fmt.Sprintf("--max-concurrent-data-movers=%d",
*dpa.Spec.Configuration.KubevirtDatamover.MaxConcurrentDataMovers))
}
if dpa.Spec.Configuration.KubevirtDatamover.StaleDataUploadThreshold != nil {
args = append(args, fmt.Sprintf("--stale-dataupload-threshold=%s",
dpa.Spec.Configuration.KubevirtDatamover.StaleDataUploadThreshold.Duration.String()))
Expand Down
Loading