rbd: check if an image is part of a group before adding it

A RBD image can only be part of a single group. While an image is added
to a group, check if the image is already part of a group, and return an
error in case it is.

Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
Niels de Vos 2024-07-22 18:18:26 +02:00 committed by mergify[bot]
parent 4acffb5548
commit f9ab14e826
2 changed files with 22 additions and 7 deletions

View File

@ -38,7 +38,28 @@ func (rv *rbdVolume) AddToGroup(ctx context.Context, vg types.VolumeGroup) error
return fmt.Errorf("could not get name for volume group %q: %w", vg, err) return fmt.Errorf("could not get name for volume group %q: %w", vg, err)
} }
return librbd.GroupImageAdd(ioctx, name, rv.ioctx, rv.RbdImageName) // check if the image is already part of a group
// "rbd: ret=-17, File exists" is returned if the image is part of ANY group
image, err := rv.open()
if err != nil {
return fmt.Errorf("failed to open image %q: %w", rv, err)
}
info, err := image.GetGroup()
if err != nil {
return fmt.Errorf("could not get group information for image %q: %w", rv, err)
}
if info.Name != "" && info.Name != name {
return fmt.Errorf("image %q is already part of volume group %q", rv, info.Name)
}
err = librbd.GroupImageAdd(ioctx, name, rv.ioctx, rv.RbdImageName)
if err != nil {
return fmt.Errorf("failed to add image %q to volume group %q: %w", rv, vg, err)
}
return nil
} }
// RemoveFromGroup removes the image from the group. This is called from the // RemoveFromGroup removes the image from the group. This is called from the

View File

@ -356,12 +356,6 @@ func (vg *volumeGroup) Delete(ctx context.Context) error {
func (vg *volumeGroup) AddVolume(ctx context.Context, vol types.Volume) error { func (vg *volumeGroup) AddVolume(ctx context.Context, vol types.Volume) error {
err := vol.AddToGroup(ctx, vg) err := vol.AddToGroup(ctx, vg)
if err != nil { if err != nil {
// rados.ErrObjectExists does not match the rbd error (there is no EEXISTS error)
if errors.Is(rados.ErrObjectExists, err) || strings.Contains(err.Error(), "ret=-17") {
log.DebugLog(ctx, "volume %q is already part of volume group %q: %v", vol, vg, err)
return nil
}
return fmt.Errorf("failed to add volume %q to volume group %q: %w", vol, vg, err) return fmt.Errorf("failed to add volume %q to volume group %q: %w", vol, vg, err)
} }