osd: clean encrypted disks from other clusters

Clean encrypted disks from other clusters by checking the cephFSID in
the luks header.

Signed-off-by: Santosh Pillai <sapillai@redhat.com>
(cherry picked from commit ec271bdde3)
This commit is contained in:
Santosh Pillai authored and Mergify committed 2025-09-23 20:03:59 +00:00
1 parent a2054ef9c9
commit 2478073d2d
2 files changed
+59 -1

No files matched your search

+40 -1
View File
@@ -870,7 +870,13 @@ func (a *OsdAgent) WipeDevicesFromOtherClusters(context *clusterd.Context) error
}
if len(existingOSDs) == 0 {
logger.Info("no existing OSDs were found. No disks to be wiped")
// ceph-volume raw list didn't return any existing OSDs. Its possible that /dev/mapper entry of the encrypted disks were removed.
// Check for cephFSID in the luks header of the disk and clean the disk if does not match the cephFSID of the current cluster.
logger.Infof("ceph-volume didn't return any existing OSDs. Checking for cephFSID of a different cluster in the luks header of the disk")
err := wipeEncryptedDevicesFromOtherClusters(context, a.clusterInfo.FSID)
if err != nil {
return errors.Wrapf(err, "failed to clean up encrypted disks from other clusters")
}
return nil
}
@@ -912,6 +918,39 @@ func (a *OsdAgent) WipeDevicesFromOtherClusters(context *clusterd.Context) error
return nil
}
func wipeEncryptedDevicesFromOtherClusters(context *clusterd.Context, currentClusterFSID string) error {
for _, disk := range context.Devices {
if disk.Filesystem == "crypto_LUKS" {
metadata, err := dumpLUKS(context, disk.Name)
if err != nil {
logger.Debugf("failed to determine if the encrypted block %q is from our cluster. %v", disk.Name, err)
return nil
}
ceph_fsid := luksLabelCephFSID.FindString(metadata)
if ceph_fsid == "" {
logger.Error("ceph_fsid not found in the LUKS header, the encrypted disk is not from a ceph cluster")
return nil
}
// is it an OSD from our cluster?
currentDiskCephFSID := strings.SplitAfter(ceph_fsid, "=")[1]
if currentDiskCephFSID != currentClusterFSID {
logger.Infof("cleaning encrypted disk %q (%q) that is part of a different ceph cluster %q", disk.Name, disk.RealPath, currentDiskCephFSID)
output, err := context.Executor.ExecuteCommandWithCombinedOutput("stdbuf", "-oL", cephVolumeCmd, "lvm", "zap", disk.RealPath)
if err != nil {
return errors.Wrapf(err, "failed to zap encrypted disk with different ceph cluster %q. %s.", disk.RealPath, output)
}
logger.Infof("completed wiping device %q belonging to a different ceph cluster", disk.RealPath)
// Since the device is wiped clean, clear the stale filesystem reference on the disk so that the wiped disk is not filtered out for filesystem check.
disk.Filesystem = ""
}
}
}
return nil
}
// getOSDDiskToBeWiped returns OSD disk path and the dmcrypt block in case of encrypted OSDs
func getOSDDiskToBeWiped(context *clusterd.Context, existingOSDDevice string) (*sys.LocalDisk, string, error) {
var err error
+19
View File
@@ -2175,6 +2175,10 @@ func TestWipeDevicesFromOtherClusters(t *testing.T) {
devicePath := "/dev/vdb"
logger.Infof("%s %v", command, args)
if command == cryptsetupBinary && args[0] == "luksDump" {
return luksDump, nil
}
if contains(args, "zap") {
if !contains(args, devicePath) {
return "", errors.Errorf("device %s should not be zapped", devicePath)
@@ -2215,4 +2219,19 @@ func TestWipeDevicesFromOtherClusters(t *testing.T) {
context.Executor = executor
err = agent.WipeDevicesFromOtherClusters(context)
assert.NoError(t, err)
// `ceph-volume raw list` returns empty but the expected device still has luks header with cephFSID from another cluster.
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if contains(args, "raw") && contains(args, "list") {
return `{}`, nil // return empty
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
context = &clusterd.Context{
Devices: []*sys.LocalDisk{{RealPath: "/dev/vdb", Filesystem: "crypto_LUKS"}},
}
context.Executor = executor
err = agent.WipeDevicesFromOtherClusters(context)
assert.NoError(t, err)
}