mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 05:25:14 +09:00
fix(csi): route RWX Block volumes to upstream hotplug detach
WrappedControllerService.ControllerUnpublishVolume decided between NFS cleanup and upstream hotplug detach using only hasRWXAccessMode(pvc). RWX Block volumes (KubeVirt live-migration disks) match that check and were routed to the NFS path, which only deletes a CiliumNetworkPolicy. For a block volume that CNP does not exist, so removeCNPOwnerReference returns successfully without doing anything, and the function reports success without ever calling upstream's hotplug detach. The DataVolume entry stays in VM.spec.template.spec.volumes; when the same PVC later attaches to a different VM, linstor-csi's anti-split-brain check sees pods from two different VMs referencing the same RWX block PVC and rejects the attach permanently. Introduce isNFSVolume(pvc) requiring both ReadWriteMany access mode and VolumeMode=Filesystem (always true for PVCs provisioned via our NFS CreateVolume path). RWX Block now delegates to upstream, which removes the entry from VM spec via RemoveVolumeFromVM. The same predicate replaces the access-mode check in ControllerExpandVolume - RWX Block volumes still need in-VM disk expansion. Fixes #2634 Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
This commit is contained in:
1 file changed
+23
-6
@@ -362,12 +362,15 @@ func (w *WrappedControllerService) ControllerPublishVolume(ctx context.Context,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ControllerUnpublishVolume for NFS volumes: deletes CiliumNetworkPolicy.
|
||||
// For RWO volumes, delegates to upstream (hotplug removal).
|
||||
// ControllerUnpublishVolume for NFS volumes (RWX Filesystem): deletes CiliumNetworkPolicy.
|
||||
// For everything else (RWO and RWX Block), delegates to upstream so the hotplug
|
||||
// DataVolume is removed from VM.spec.template.spec.volumes. RWX Block volumes used
|
||||
// for live migration must NOT be treated as NFS — their cleanup goes through upstream
|
||||
// hotplug removal, otherwise stale VM-spec entries permanently block re-attachment to
|
||||
// a different VM via the anti-split-brain check (issue #2634).
|
||||
func (w *WrappedControllerService) ControllerUnpublishVolume(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
dvName := req.GetVolumeId()
|
||||
|
||||
// Determine if NFS by checking infra PVC access modes
|
||||
pvc, err := w.infraClient.CoreV1().PersistentVolumeClaims(w.infraNamespace).Get(ctx, dvName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
@@ -376,7 +379,7 @@ func (w *WrappedControllerService) ControllerUnpublishVolume(ctx context.Context
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !hasRWXAccessMode(pvc) {
|
||||
if !isNFSVolume(pvc) {
|
||||
return w.ControllerService.ControllerUnpublishVolume(ctx, req)
|
||||
}
|
||||
|
||||
@@ -404,11 +407,12 @@ func (w *WrappedControllerService) ControllerExpandVolume(ctx context.Context, r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For NFS volumes, no node-side expansion is needed
|
||||
// For NFS volumes (RWX Filesystem), no node-side expansion is needed. RWX Block
|
||||
// volumes still require node-side expansion of the in-VM disk.
|
||||
pvc, err := w.infraClient.CoreV1().PersistentVolumeClaims(w.infraNamespace).Get(ctx, req.GetVolumeId(), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
klog.Warningf("Failed to check PVC access mode for %s/%s: %v", w.infraNamespace, req.GetVolumeId(), err)
|
||||
} else if hasRWXAccessMode(pvc) {
|
||||
} else if isNFSVolume(pvc) {
|
||||
resp.NodeExpansionRequired = false
|
||||
}
|
||||
|
||||
@@ -544,6 +548,19 @@ func hasRWXAccessMode(pvc *corev1.PersistentVolumeClaim) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// isNFSVolume reports whether the PVC was provisioned by our CreateVolume NFS path
|
||||
// (RWX + Filesystem). RWX Block volumes are upstream hotplug volumes used for live
|
||||
// migration and must NOT be handled as NFS.
|
||||
func isNFSVolume(pvc *corev1.PersistentVolumeClaim) bool {
|
||||
if !hasRWXAccessMode(pvc) {
|
||||
return false
|
||||
}
|
||||
if pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == corev1.PersistentVolumeBlock {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// getNFSExport extracts the NFS export URL from a PersistentVolume.
|
||||
// Supports both native NFS PVs and CSI PVs with nfs-export volume attribute.
|
||||
func getNFSExport(pv *corev1.PersistentVolume) (string, error) {
|
||||
|
||||
Reference in new issue
Block a user