Skip to content

Conversation

@upalatucci
Copy link
Member

@upalatucci upalatucci commented Feb 4, 2026

📝 Description

Uncheck sharable disks and non-cloned PVCs.

Non-cloned PVCs (volume.persistentVolumeClaim.claimName) can be also shared within other vms as they are not cloned during vm creation

🎥 Demo

Summary by CodeRabbit

  • New Features

    • Added detection and handling of shared disks and volumes during virtual machine deletion, enabling safer resource cleanup.
    • Enhanced deletion dialog with visual indicators to identify shared resources.
  • Chores

    • Simplified disk deletion labels across all supported languages for improved clarity.

@openshift-ci-robot
Copy link
Collaborator

openshift-ci-robot commented Feb 4, 2026

@upalatucci: This pull request references CNV-77372 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

📝 Description

Uncheck sharable disks and non-cloned PVCs.

Non-cloned PVCs (volume.persistentVolumeClaim.claimName) can be also shared within other vms as they are not cloned during vm creation

🎥 Demo

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 4, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: upalatucci

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

@openshift-ci openshift-ci bot added the approved This issue is something we want to fix label Feb 4, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

This PR simplifies disk deletion translation labels across multiple locales and introduces shared volume support to VM deletion workflows. It adds new selectors for detecting shared disks/volumes and updates the DeleteVMModal component tree to identify and preserve shared resources during deletion.

Changes

Cohort / File(s) Summary
Translation Updates
locales/en/plugin__kubevirt-plugin.json, locales/es/plugin__kubevirt-plugin.json, locales/fr/plugin__kubevirt-plugin.json, locales/ja/plugin__kubevirt-plugin.json, locales/ko/plugin__kubevirt-plugin.json, locales/zh/plugin__kubevirt-plugin.json
Simplified translation key from parameterized "Delete disk {{resourceName}} ({{kindAbbr}})" to generic "Delete disk" across all locales; English value used for non-matching locales.
VM Shared Resource Selectors
src/utils/resources/vm/utils/selectors.ts
Added two new public selectors: getSharedDisks() filters VM disks by shareable flag; getSharedVolumes() returns volumes matching shared disk names.
DeleteVMModal Core
src/views/virtualmachines/actions/components/DeleteVMModal/DeleteVMModal.tsx
Integrated shared volume detection via getSharedVolumes() and introduced useSaveSharedDisks() and useSavePVCs() hooks to preserve shared resources during deletion.
DeleteVMModal Sub-Components
src/views/virtualmachines/actions/components/DeleteVMModal/components/DeleteOwnedResourcesMessage.tsx, src/views/virtualmachines/actions/components/DeleteVMModal/components/DeleteResourceCheckbox.tsx
Added shared volume prop threading and enhanced UI to display resource icons, names, and "Shared" label badges for identified shared resources.
DeleteVMModal Hooks
src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useConvertedVolumeNames.ts, src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useDeleteVMResources.ts
Updated hook signatures: useConvertedVolumeNames() now accepts VM object directly; useDeleteVMResources() added memoization for filtered volumes and PVCs.
DeleteVMModal New Hooks
src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSavePVCs.ts, src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSaveSharedDisks.ts
Introduced two new hooks to manage PVC and shared disk preservation during VM deletion via state setters.
DeleteVMModal Helpers
src/views/virtualmachines/actions/components/DeleteVMModal/utils/helpers.ts
Added utility functions: getSharedDataVolumes() filters data volumes by shared names; isResourceShared() checks resource membership in shared volumes; getResourceModel() resolves resource-specific model classes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

lgtm

Suggested reviewers

  • rszwajko
  • adamviktora
  • Pedro-S-Abreu
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The description states the intent to uncheck sharable disks and non-cloned PVCs but lacks detail about implementation approach, testing, or expected behavior; the 'Demo' section is empty. Add details on how the changes implement the unchecking behavior, include a screenshot or demo showing the UI changes, and clarify the testing approach for shared disk detection.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title '[WIP] CNV-77372: uncheck shared disks on delete vm modal' clearly describes the main change: modifying the delete VM modal to uncheck shared disks, which aligns with the code changes that add shared disk detection and UI updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


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.

@openshift-ci-robot
Copy link
Collaborator

openshift-ci-robot commented Feb 4, 2026

@upalatucci: This pull request references CNV-77372 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

📝 Description

Uncheck sharable disks and non-cloned PVCs.

Non-cloned PVCs (volume.persistentVolumeClaim.claimName) can be also shared within other vms as they are not cloned during vm creation

🎥 Demo

Summary by CodeRabbit

  • New Features

  • Added detection and handling of shared disks and volumes during virtual machine deletion, enabling safer resource cleanup.

  • Enhanced deletion dialog with visual indicators to identify shared resources.

  • Chores

  • Simplified disk deletion labels across all supported languages for improved clarity.

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 openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@src/views/virtualmachines/actions/components/DeleteVMModal/components/DeleteResourceCheckbox.tsx`:
- Around line 38-44: The label JSX in DeleteResourceCheckbox.tsx currently
renders the literal text "Shared" without translation and too close to
resourceName; change it to use the translation function (e.g., t('Shared')) and
add spacing/separator so it doesn't run into resourceName. Locate the label
where ResourceIcon, modelToGroupVersionKind(getResourceModel(resource)),
resourceName and isShared are used and replace the {isShared ?
<Label>Shared</Label> : undefined} with a localized Label (e.g.,
<Label>{t('Shared')}</Label>) and ensure there is appropriate spacing or margin
between resourceName and the Label so the UI displays correctly.

In
`@src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSavePVCs.ts`:
- Around line 14-17: The useEffect in useSavePVCs is re-adding the entire pvcs
array on every pvcs/filteredPvcs change; change the effect to only append PVCs
that are not already present in PVCsToSave (compare by unique key like name/uid)
so user deselections and duplicates are preserved, and annotate the hook
signature with an explicit return type of void; update references to
setPVCsToSave and pvcs/filteredPvcs in the effect to perform a deduplicating
merge rather than spreading the whole array.
🧹 Nitpick comments (4)
src/utils/resources/vm/utils/selectors.ts (1)

59-82: Make shared selectors return typed, non-optional arrays.

This avoids nullable handling downstream and aligns with the explicit return-type guideline.

Proposed change
-export const getSharedDisks = (vm: V1VirtualMachine) =>
-  getDisks(vm)?.filter((disk) => disk.shareable);
+export const getSharedDisks = (vm: V1VirtualMachine): V1Disk[] =>
+  (getDisks(vm) ?? []).filter((disk) => Boolean(disk.shareable));

-export const getSharedVolumes = (vm: V1VirtualMachine) => {
-  const sharedDisks = getSharedDisks(vm)?.map((disk) => disk.name);
-  return getVolumes(vm)?.filter((volume) => sharedDisks?.includes(volume.name));
-};
+export const getSharedVolumes = (vm: V1VirtualMachine): V1Volume[] => {
+  const sharedDisks = getSharedDisks(vm).map((disk) => disk.name);
+  return (getVolumes(vm) ?? []).filter((volume) => sharedDisks.includes(volume.name));
+};

As per coding guidelines, Always explicitly define return types for functions rather than relying on TypeScript inference.

src/views/virtualmachines/actions/components/DeleteVMModal/utils/helpers.ts (1)

109-135: Add explicit return types (and guard nullish inputs) for shared helpers.

Proposed change
 export const getSharedDataVolumes = (
   sharedVolumes: V1Volume[],
   dataVolumes: V1beta1DataVolume[],
-) => {
-  const sharedDataVolumeNames = sharedVolumes
-    ?.map((volume) => volume?.dataVolume?.name)
-    ?.filter(Boolean);
-  return dataVolumes?.filter((dataVolume) => sharedDataVolumeNames?.includes(getName(dataVolume)));
-};
+): V1beta1DataVolume[] => {
+  const sharedDataVolumeNames = (sharedVolumes ?? [])
+    .map((volume) => volume?.dataVolume?.name)
+    .filter(Boolean);
+  return (dataVolumes ?? []).filter((dataVolume) =>
+    sharedDataVolumeNames.includes(getName(dataVolume)),
+  );
+};

-export const isResourceShared = (sharedVolumes: V1Volume[], resource: K8sResourceCommon) => {
-  return sharedVolumes.some(
-    (volume) =>
-      volume?.dataVolume?.name === getName(resource) ||
-      volume?.persistentVolumeClaim?.claimName === getName(resource),
-  );
-};
+export const isResourceShared = (
+  sharedVolumes: V1Volume[],
+  resource: K8sResourceCommon,
+): boolean =>
+  (sharedVolumes ?? []).some(
+    (volume) =>
+      volume?.dataVolume?.name === getName(resource) ||
+      volume?.persistentVolumeClaim?.claimName === getName(resource),
+  );

-export const getResourceModel = (resource: K8sResourceCommon) => {
+export const getResourceModel = (
+  resource: K8sResourceCommon,
+):
+  | typeof PersistentVolumeClaimModel
+  | typeof VirtualMachineSnapshotModel
+  | typeof DataVolumeModel => {
   if (resource.kind === PersistentVolumeClaimModel.kind) {
     return PersistentVolumeClaimModel;
   }
   if (resource.kind === VirtualMachineSnapshotModel.kind) {
     return VirtualMachineSnapshotModel;
   }
   return DataVolumeModel;
 };

As per coding guidelines, Always explicitly define return types for functions rather than relying on TypeScript inference.

src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSaveSharedDisks.ts (1)

15-31: Avoid duplicate saved volumes and add an explicit return type.

Proposed change
 const useSaveSharedDisks = (
   sharedVolumes: V1Volume[],
   setVolumesToSave: Dispatch<
     SetStateAction<(IoK8sApiCoreV1PersistentVolumeClaim | V1beta1DataVolume)[]>
   >,
   dataVolumes: V1beta1DataVolume[],
-) => {
+): void => {
   const sharedDataVolumes = useMemo(
     () => getSharedDataVolumes(sharedVolumes, dataVolumes),
     [sharedVolumes, dataVolumes],
   );

   useEffect(() => {
-    if (sharedDataVolumes) {
-      setVolumesToSave((prevVolumes) => [...prevVolumes, ...sharedDataVolumes]);
-    }
+    if (!sharedDataVolumes?.length) return;
+    setVolumesToSave((prevVolumes) => {
+      const next = [...prevVolumes];
+      sharedDataVolumes.forEach((dv) => {
+        if (!next.some((v) => v?.metadata?.uid === dv?.metadata?.uid)) {
+          next.push(dv);
+        }
+      });
+      return next;
+    });
   }, [setVolumesToSave, sharedDataVolumes]);
 };

As per coding guidelines, Always explicitly define return types for functions rather than relying on TypeScript inference.

src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSavePVCs.ts (1)

10-13: Add an explicit return type to useSavePVCs.

This hook currently relies on inference. As per coding guidelines, always explicitly define return types for functions rather than relying on TypeScript inference.

✍️ Suggested change
-const useSavePVCs = (
+const useSavePVCs = (
   setPVCsToSave: Dispatch<SetStateAction<IoK8sApiCoreV1PersistentVolumeClaim[]>>,
   pvcs: IoK8sApiCoreV1PersistentVolumeClaim[],
-) => {
+): void => {

Comment on lines +38 to +44
label={
<>
{t('Delete disk')}{' '}
<ResourceIcon groupVersionKind={modelToGroupVersionKind(getResourceModel(resource))} />{' '}
{resourceName}
{isShared ? <Label>Shared</Label> : undefined}
</>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Localize the “Shared” label and add spacing.

“Shared” is user‑visible text and should be translated; also add a separator so it doesn’t run into the resource name.

🌐 Suggested fix
-            {resourceName}
-            {isShared ? <Label>Shared</Label> : undefined}
+            {resourceName}
+            {isShared ? (
+              <>
+                {' '}
+                <Label>{t('Shared')}</Label>
+              </>
+            ) : undefined}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
label={
<>
{t('Delete disk')}{' '}
<ResourceIcon groupVersionKind={modelToGroupVersionKind(getResourceModel(resource))} />{' '}
{resourceName}
{isShared ? <Label>Shared</Label> : undefined}
</>
label={
<>
{t('Delete disk')}{' '}
<ResourceIcon groupVersionKind={modelToGroupVersionKind(getResourceModel(resource))} />{' '}
{resourceName}
{isShared ? (
<>
{' '}
<Label>{t('Shared')}</Label>
</>
) : undefined}
</>
🤖 Prompt for AI Agents
In
`@src/views/virtualmachines/actions/components/DeleteVMModal/components/DeleteResourceCheckbox.tsx`
around lines 38 - 44, The label JSX in DeleteResourceCheckbox.tsx currently
renders the literal text "Shared" without translation and too close to
resourceName; change it to use the translation function (e.g., t('Shared')) and
add spacing/separator so it doesn't run into resourceName. Locate the label
where ResourceIcon, modelToGroupVersionKind(getResourceModel(resource)),
resourceName and isShared are used and replace the {isShared ?
<Label>Shared</Label> : undefined} with a localized Label (e.g.,
<Label>{t('Shared')}</Label>) and ensure there is appropriate spacing or margin
between resourceName and the Label so the UI displays correctly.

Comment on lines +14 to +17
useEffect(() => {
if (pvcs.length > 0) {
setPVCsToSave((prevPVCs) => [...prevPVCs, ...pvcs]);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

rg -n "useSavePVCs" -C 5 --type=ts --type=tsx

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 98


🏁 Script executed:

rg -n "useSavePVCs" -C 5

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 4705


🏁 Script executed:

find . -name "useDeleteVMResources*" -type f

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 161


🏁 Script executed:

cat -n ./src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useDeleteVMResources.ts

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 4590


🏁 Script executed:

cat -n ./src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSavePVCs.ts

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 931


Prevent re‑adding PVCs on every pvcs change; add explicit return type.

The effect spreads the full PVC list each time the pvcs reference changes. Since filteredPvcs in useDeleteVMResources is memoized but creates a new reference whenever pvcs, dvVolumesNames, isDataVolumeGarbageCollector, or pvcVolumesNames changes, this effect re-runs frequently and re-adds all PVCs to the saved list, undoing user deselections and creating duplicates.

Additionally, the hook lacks an explicit return type annotation; it should be void.

🛠️ Suggested fix
-import { Dispatch, SetStateAction, useEffect } from 'react';
+import { Dispatch, SetStateAction, useEffect, useRef } from 'react';
+
+import { getName } from '@kubevirt-utils/resources/shared';
 import { IoK8sApiCoreV1PersistentVolumeClaim } from '@kubevirt-ui-ext/kubevirt-api/kubernetes';
 
-const useSavePVCs = (
+const useSavePVCs = (
   setPVCsToSave: Dispatch<SetStateAction<IoK8sApiCoreV1PersistentVolumeClaim[]>>,
   pvcs: IoK8sApiCoreV1PersistentVolumeClaim[],
-) => {
+): void => {
+  const autoAddedRef = useRef<Set<string>>(new Set());
+
   useEffect(() => {
-    if (pvcs.length > 0) {
-      setPVCsToSave((prevPVCs) => [...prevPVCs, ...pvcs]);
-    }
+    if (pvcs.length === 0) return;
+
+    setPVCsToSave((prevPVCs) => {
+      const nextPVCs = [...prevPVCs];
+
+      pvcs.forEach((pvc) => {
+        const key = pvc?.metadata?.uid || getName(pvc);
+        if (!autoAddedRef.current.has(key)) {
+          autoAddedRef.current.add(key);
+          nextPVCs.push(pvc);
+        }
+      });
+
+      return nextPVCs;
+    });
   }, [setPVCsToSave, pvcs]);
 };
🤖 Prompt for AI Agents
In
`@src/views/virtualmachines/actions/components/DeleteVMModal/hooks/useSavePVCs.ts`
around lines 14 - 17, The useEffect in useSavePVCs is re-adding the entire pvcs
array on every pvcs/filteredPvcs change; change the effect to only append PVCs
that are not already present in PVCsToSave (compare by unique key like name/uid)
so user deselections and duplicates are preserved, and annotate the hook
signature with an explicit return type of void; update references to
setPVCsToSave and pvcs/filteredPvcs in the effect to perform a deduplicating
merge rather than spreading the whole array.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 4, 2026

@upalatucci: The following test 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/kubevirt-e2e-aws cb4a31b link true /test kubevirt-e2e-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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants