diff --git a/pkg/daemon/ceph/osd/volume.go b/pkg/daemon/ceph/osd/volume.go index 7fc170986..b4724c8b0 100644 --- a/pkg/daemon/ceph/osd/volume.go +++ b/pkg/daemon/ceph/osd/volume.go @@ -25,6 +25,7 @@ import ( "path" "path/filepath" "regexp" + "slices" "strconv" "strings" @@ -968,8 +969,12 @@ func getOSDDiskToBeWiped(context *clusterd.Context, existingOSDDevice string) (* var osdDisk *sys.LocalDisk for _, desiredDevice := range context.Devices { - if desiredDevice.RealPath == existingOSDDevice { + // Also check DevLinks since ceph-volume may report a symlink path + // (e.g. /dev/rhel/ceph-data) that differs from RealPath + // (e.g. /dev/mapper/rhel-ceph--data) + if desiredDevice.RealPath == existingOSDDevice || slices.Contains(strings.Split(desiredDevice.DevLinks, " "), existingOSDDevice) { osdDisk = desiredDevice + break } } return osdDisk, encryptedBlock, nil diff --git a/pkg/daemon/ceph/osd/volume_test.go b/pkg/daemon/ceph/osd/volume_test.go index 793206c0c..4edeed394 100644 --- a/pkg/daemon/ceph/osd/volume_test.go +++ b/pkg/daemon/ceph/osd/volume_test.go @@ -301,6 +301,19 @@ var cephVolumeRawPartitionTestResult = `{ } }` +// ceph-volume raw list reports the device via an LVM symlink (/dev/rhel/ceph-data) +// while the inventory RealPath is /dev/mapper/rhel-ceph--data. +var cephVolumeRAWLVMSymlinkTestResult = `{ + "0": { + "ceph_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89", + "device": "/dev/rhel/ceph-data", + "osd_id": 0, + "osd_uuid": "c03d7353-96e5-4a41-98de-830dfff97d06", + "type": "bluestore" + } +} +` + func createPVCAvailableDevices() *DeviceOsdMapping { devices := &DeviceOsdMapping{ Entries: map[string]*DeviceOsdIDEntry{ @@ -2226,4 +2239,35 @@ func TestWipeDevicesFromOtherClusters(t *testing.T) { context.Executor = executor err = agent.WipeDevicesFromOtherClusters(context) assert.NoError(t, err) + + // `ceph-volume raw list` returns an LVM symlink path (/dev/rhel/ceph-data) while + // the device RealPath is /dev/mapper/rhel-ceph--data. The device should still be + // matched via DevLinks and zapped. + executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) { + logger.Infof("%s %v", command, args) + if slices.Contains(args, "raw") && slices.Contains(args, "list") { + return cephVolumeRAWLVMSymlinkTestResult, nil + } + return "", errors.Errorf("unknown command %s %s", command, args) + } + executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) { + logger.Infof("%s %v", command, args) + devicePath := "/dev/mapper/rhel-ceph--data" + if slices.Contains(args, "zap") { + if !slices.Contains(args, devicePath) { + return "", errors.Errorf("expected device %s to be zapped but got %v", devicePath, args) + } + return "", nil + } + return "", errors.Errorf("unknown command %s %s", command, args) + } + context = &clusterd.Context{ + Devices: []*sys.LocalDisk{{ + RealPath: "/dev/mapper/rhel-ceph--data", + DevLinks: "/dev/rhel/ceph-data /dev/disk/by-id/dm-name-rhel-ceph--data /dev/mapper/rhel-ceph--data", + }}, + } + context.Executor = executor + err = agent.WipeDevicesFromOtherClusters(context) + assert.NoError(t, err) }