diff --git a/pkg/rbd/rbd_util.go b/pkg/rbd/rbd_util.go index 7112ba45c..94d9569d5 100644 --- a/pkg/rbd/rbd_util.go +++ b/pkg/rbd/rbd_util.go @@ -45,6 +45,12 @@ const ( rbdImageWatcherFactor = 1.4 rbdImageWatcherSteps = 10 rbdDefaultMounter = "rbd" + + // Output strings returned during invocation of "ceph rbd task add remove " when + // command is not supported by ceph manager. Used to check errors and recover when the command + // is unsupported. + rbdTaskRemoveCmdInvalidString1 = "no valid command found" + rbdTaskRemoveCmdInvalidString2 = "Error EINVAL: invalid command" ) // rbdVolume represents a CSI volume and its RBD image specifics @@ -166,6 +172,31 @@ func rbdStatus(pOpts *rbdVolume, cr *util.Credentials) (bool, string, error) { return false, output, nil } +// rbdManagerTaskDelete adds a ceph manager task to delete an rbd image, thus deleting +// it asynchronously. If command is not found returns a bool set to false +func rbdManagerTaskDeleteImage(pOpts *rbdVolume, cr *util.Credentials) (bool, error) { + var output []byte + + args := []string{"rbd", "task", "add", "remove", + pOpts.Pool + "/" + pOpts.RbdImageName, + "--id", cr.ID, + "--keyfile=" + cr.KeyFile, + "-m", pOpts.Monitors, + } + + output, err := execCommand("ceph", args) + if err != nil { + if strings.Contains(string(output), rbdTaskRemoveCmdInvalidString1) && + strings.Contains(string(output), rbdTaskRemoveCmdInvalidString2) { + klog.Infof("cluster with cluster ID (%s) does not support Ceph manager based rbd image"+ + " deletion (minimum ceph version required is v14.2.3)", pOpts.ClusterID) + return false, err + } + } + + return true, err +} + // deleteImage deletes a ceph image with provision and volume options. func deleteImage(pOpts *rbdVolume, cr *util.Credentials) error { var output []byte @@ -181,9 +212,16 @@ func deleteImage(pOpts *rbdVolume, cr *util.Credentials) error { } klog.V(4).Infof("rbd: rm %s using mon %s, pool %s", image, pOpts.Monitors, pOpts.Pool) - args := []string{"rm", image, "--pool", pOpts.Pool, "--id", cr.ID, "-m", pOpts.Monitors, - "--keyfile=" + cr.KeyFile} - output, err = execCommand("rbd", args) + + // attempt to use Ceph manager based deletion support if available + rbdCephMgrSupported, err := rbdManagerTaskDeleteImage(pOpts, cr) + if !rbdCephMgrSupported { + // attempt older style deletion + args := []string{"rm", image, "--pool", pOpts.Pool, "--id", cr.ID, "-m", pOpts.Monitors, + "--keyfile=" + cr.KeyFile} + output, err = execCommand("rbd", args) + } + if err != nil { klog.Errorf("failed to delete rbd image: %v, command output: %s", err, string(output)) }