From 607129171d22e77f3ff44992ed935d27b89301be Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Fri, 23 Jul 2021 16:46:20 +0200 Subject: [PATCH] rbd: move image metadata key migration to its own function The new MigrateMetadata() function can be used to get the metadata of an image with a deprecated and new key. Renaming metadata keys can be done easily this way. A default value will be set in the image metadata when it is missing completely. But if the deprecated key was set, the data is stored under the new key and the deprecated key is removed. Signed-off-by: Niels de Vos --- internal/rbd/rbd_util.go | 81 +++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 1963cb971..51d927c96 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -1593,6 +1593,56 @@ func (ri *rbdImage) SetMetadata(key, value string) error { return image.SetMetadata(key, value) } +// RemoveMetadata deletes the key and data from the metadata of the image. +func (ri *rbdImage) RemoveMetadata(key string) error { + image, err := ri.open() + if err != nil { + return err + } + defer image.Close() + + return image.RemoveMetadata(key) +} + +// MigrateMetadata reads the metadata contents from oldKey and stores it in +// newKey. In case oldKey was not set, the defaultValue is stored in newKey. +// Once done, oldKey will be removed as well. +func (ri *rbdImage) MigrateMetadata(oldKey, newKey, defaultValue string) (string, error) { + value, err := ri.GetMetadata(newKey) + if err == nil { + return value, nil + } else if !errors.Is(err, librbd.ErrNotFound) { + return "", err + } + + // migrate contents from oldKey to newKey + removeOldKey := true + value, err = ri.GetMetadata(oldKey) + if errors.Is(err, librbd.ErrNotFound) { + // in case oldKey was not set, set newKey to defaultValue + value = defaultValue + removeOldKey = false + } else if err != nil { + return "", err + } + + // newKey was not set, set it now to prevent regular error cases for missing metadata + err = ri.SetMetadata(newKey, value) + if err != nil { + return "", err + } + + // the newKey was set with data from oldKey, oldKey is not needed anymore + if removeOldKey { + err = ri.RemoveMetadata(oldKey) + if err != nil { + return "", err + } + } + + return value, nil +} + // setThickProvisioned records in the image metadata that it has been // thick-provisioned. func (ri *rbdImage) setThickProvisioned() error { @@ -1604,40 +1654,11 @@ func (ri *rbdImage) setThickProvisioned() error { return nil } -// setThinProvisioned records in the image metadata that it has been -// thin-provisioned. -func (ri *rbdImage) setThinProvisioned() error { - err := ri.SetMetadata(thickProvisionMetaKey, thinProvisionMetaData) - if err != nil { - return fmt.Errorf("failed to set metadata %q for %q: %w", thinProvisionMetaData, ri, err) - } - - return nil -} - // isThickProvisioned checks in the image metadata if the image has been marked // as thick-provisioned. This can be used while expanding the image, so that // the expansion can be allocated too. func (ri *rbdImage) isThickProvisioned() (bool, error) { - value, err := ri.GetMetadata(thickProvisionMetaKey) - if errors.Is(err, librbd.ErrNotFound) { - // check if the image is having deprecated metadata key. - value, err = ri.GetMetadata(deprecatedthickProvisionMetaKey) - if errors.Is(err, librbd.ErrNotFound) { - return false, nil - } - // If we reach here means the image has deprecated metakey set. Set the - // new metakey so that we dont need to check for deprecated key again. - if value == thickProvisionMetaData { - err = ri.setThickProvisioned() - } else { - value = thinProvisionMetaData - // If we reach here means the image is thin provisioned. Set thin - // provisioned metadata on the image so that we dont need to check - // for thick metakey or deprecated thick metakey. - err = ri.setThinProvisioned() - } - } + value, err := ri.MigrateMetadata(deprecatedthickProvisionMetaKey, thickProvisionMetaKey, thinProvisionMetaData) if err != nil { return false, fmt.Errorf("failed to get metadata %q for %q: %w", thickProvisionMetaKey, ri, err) }