mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-22 06:10:22 +00:00
rbd: add VolumeGroup.CreateSnapshots() implementation
When the rbd.Manager creates a VolumeGroupSnapshot, each RBD-snapshot that is created as part of the RBD-group needs to be cloned into its own RBD-image that will be used as a CSI Snapshot. The VolumeGroup.CreateSnapshots() creates the RBD-group snapshot and returns a list of the Snapshot structs. Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
parent
20fadf2016
commit
efb7bccaea
@ -241,7 +241,8 @@ func (vg *volumeGroup) AddVolume(ctx context.Context, vol types.Volume) error {
|
|||||||
|
|
||||||
err = j.AddVolumesMapping(ctx, pool, csiID.ObjectUUID, toAdd)
|
err = j.AddVolumesMapping(ctx, pool, csiID.ObjectUUID, toAdd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to add mapping for volume %q to volume group id %q: %w", volID, id, err)
|
return fmt.Errorf("failed to add mapping for volume %q to volume group id %q: %w",
|
||||||
|
volID, id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -315,7 +316,8 @@ func (vg *volumeGroup) RemoveVolume(ctx context.Context, vol types.Volume) error
|
|||||||
|
|
||||||
err = j.RemoveVolumesMapping(ctx, pool, csiID.ObjectUUID, mapping)
|
err = j.RemoveVolumesMapping(ctx, pool, csiID.ObjectUUID, mapping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to remove mapping for volume %q to volume group id %q: %w", toRemove, id, err)
|
return fmt.Errorf("failed to remove mapping for volume %q to volume group id %q: %w",
|
||||||
|
toRemove, id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -324,3 +326,88 @@ func (vg *volumeGroup) RemoveVolume(ctx context.Context, vol types.Volume) error
|
|||||||
func (vg *volumeGroup) ListVolumes(ctx context.Context) ([]types.Volume, error) {
|
func (vg *volumeGroup) ListVolumes(ctx context.Context) ([]types.Volume, error) {
|
||||||
return vg.volumes, nil
|
return vg.volumes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateSnapshots makes consistent snapshots of all the volumes in the volume group.
|
||||||
|
func (vg *volumeGroup) CreateSnapshots(
|
||||||
|
ctx context.Context,
|
||||||
|
cr *util.Credentials,
|
||||||
|
name string,
|
||||||
|
) ([]types.Snapshot, error) {
|
||||||
|
group, err := vg.GetName(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctx, err := vg.GetIOContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = librbd.GroupSnapCreate(ioctx, group, name)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, librbd.ErrExist) {
|
||||||
|
return nil, fmt.Errorf("failed to create volume group snapshot %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.DebugLog(ctx, "ignoring error while creating volume group snapshot %q: %v", vg, err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
// always remove the groups-snapshot on function exit, it is not used anymore afterwards
|
||||||
|
cleanupErr := librbd.GroupSnapRemove(ioctx, group, name)
|
||||||
|
if cleanupErr != nil {
|
||||||
|
log.ErrorLog(ctx, "failed to remove temporary volume group snapshot %q: %v",
|
||||||
|
name, cleanupErr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
info, err := librbd.GroupSnapGetInfo(ioctx, group, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get info for volume group snapshot %q: %w",
|
||||||
|
vg.String()+"@"+name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshots := make([]types.Snapshot, len(info.Snapshots))
|
||||||
|
defer func() {
|
||||||
|
// free all created snapshot objects in case of a failure
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
snapshot.Destroy(ctx)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Loop though all the RBD-snapshots in the group, and find the volume
|
||||||
|
// that was used to create the snapshot. Once found, use the volume to
|
||||||
|
// create a new RBD-image from the RBD-snapshot.
|
||||||
|
for i, snap := range info.Snapshots {
|
||||||
|
for _, volume := range vg.volumes {
|
||||||
|
var volName string
|
||||||
|
|
||||||
|
volName, err = volume.GetName(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"failed to get name for volume %q: %w", volume, err)
|
||||||
|
}
|
||||||
|
if volName != snap.Name {
|
||||||
|
// the volume isn't the snapshot-source, continue with the next one
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// yay, volume for the RBD-snapshot found!
|
||||||
|
snapName := fmt.Sprintf("%s-snap-%d", group, i)
|
||||||
|
snapshots[i], err = volume.NewSnapshotByID(ctx, cr, snapName, snap.SnapID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"failed to create snapshot for image %q with snapshot id %d: %w",
|
||||||
|
snap.Name, snap.SnapID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// done, no need to try more volumes in the loop
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return snapshots, nil
|
||||||
|
}
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
|
|
||||||
"github.com/ceph/go-ceph/rados"
|
"github.com/ceph/go-ceph/rados"
|
||||||
"github.com/csi-addons/spec/lib/go/volumegroup"
|
"github.com/csi-addons/spec/lib/go/volumegroup"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type journalledObject interface {
|
type journalledObject interface {
|
||||||
@ -66,4 +68,9 @@ type VolumeGroup interface {
|
|||||||
|
|
||||||
// ListVolumes returns a slice with all Volumes in the VolumeGroup.
|
// ListVolumes returns a slice with all Volumes in the VolumeGroup.
|
||||||
ListVolumes(ctx context.Context) ([]Volume, error)
|
ListVolumes(ctx context.Context) ([]Volume, error)
|
||||||
|
|
||||||
|
// CreateSnapshots creates Snapshots of all Volume in the VolumeGroup.
|
||||||
|
// The Snapshots are crash consistent, and created as a consistency
|
||||||
|
// group.
|
||||||
|
CreateSnapshots(ctx context.Context, cr *util.Credentials, name string) ([]Snapshot, error)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user