Skip to content

Commit

Permalink
rbd: add RegenerateVolumeGroupJournal method for Manager interface
Browse files Browse the repository at this point in the history
This commit adds `RegenerateVolumeGroupJournal` to Manager
interface. RegenerateVolumeGroupJournal regenerate the omap
data for the volume group.

This performs the following operations:
  - extracts clusterID and Mons from the cluster mapping
  - Retrieves pool and journalPool parameters from the VolumeGroupReplicationClass
  - Reserves omap data
  - Add volumeIDs mapping to the reserved volume group omap object
  - Generate new volume group handler

Returns the generated volume group handler.

Signed-off-by: Praveen M <[email protected]>
  • Loading branch information
iPraveenParihar committed Aug 14, 2024
1 parent 9080139 commit 6e8387d
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
133 changes: 133 additions & 0 deletions internal/rbd/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,136 @@ func (mgr *rbdManager) DeleteVolumeGroup(ctx context.Context, vg types.VolumeGro

return nil
}

// RegenerateVolumeGroupJournal regenerate the omap data for the volume group.
// This performs the following operations:
// - extracts clusterID and Mons from the cluster mapping
// - Retrieves pool and journalPool parameters from the VolumeGroupReplicationClass
// - Reserves omap data
// - Add volumeIDs mapping to the reserved volume group omap object
// - Generate new volume group handler
//
// Returns the generated volume group handler.
//
// Note: The new volume group handler will differ from the original as it includes
// poolID and clusterID, which vary between clusters.
//
//nolint:gocyclo,cyclop // TODO: reduce complexity
func (mgr *rbdManager) RegenerateVolumeGroupJournal(
ctx context.Context,
groupID, requestName string,
volumeIds []string,
) (string, error) {
var (
clusterID string
monitors string
pool string
journalPool string
namePrefix string
groupUUID string
vgName string

gi util.CSIIdentifier
ok bool
err error
)

err = gi.DecomposeCSIID(groupID)
if err != nil {
return "", fmt.Errorf("%w: error decoding volume group ID (%w) (%s)", ErrInvalidVolID, err, groupID)
}

monitors, clusterID, err = util.FetchMappedClusterIDAndMons(ctx, gi.ClusterID)
if err != nil {
return "", err
}

pool, ok = mgr.parameters["pool"]
if !ok {
return "", errors.New("required 'pool' parameter missing in volume attributes")
}

journalPool = mgr.parameters["journalPool"]
if journalPool == "" {
journalPool = pool
}

vgJournal, err := mgr.getVolumeGroupJournal(clusterID)
if err != nil {
return "", err
}
defer vgJournal.Destroy()

namePrefix = mgr.parameters["volumeNamePrefix"]
vgData, err := vgJournal.CheckReservation(ctx, journalPool, requestName, namePrefix)
if err != nil {
return "", err
}

if vgData != nil && vgData.GroupUUID != "" {
groupUUID = vgData.GroupUUID
vgName = vgData.GroupName
} else {
log.DebugLog(ctx, "the journal does not contain a reservation for a volume group with name %q yet", requestName)
groupUUID, vgName, err = vgJournal.ReserveName(ctx, journalPool, requestName, gi.ObjectUUID, namePrefix)
if err != nil {
return "", fmt.Errorf("failed to reserve volume group for name %q: %w", requestName, err)
}
defer func() {
if err != nil {
err = vgJournal.UndoReservation(ctx, journalPool, vgName, requestName)
if err != nil {
log.ErrorLog(ctx, "failed to undo the reservation for volume group %q: %w", requestName, err)
}
}
}()
}

volumes := make([]types.Volume, len(volumeIds))
var volume types.Volume
for i, id := range volumeIds {
volume, err = mgr.GetVolumeByID(ctx, id)
if err != nil {
// free up allocated volumes
for _, v := range volumes {
v.Destroy(ctx)
}

return "", fmt.Errorf("failed to find required volume %q for volume group id %q: %w", id, vgName, err)
}

volumes[i] = volume
}

var volID string
for _, vol := range volumes {
volID, err = vol.GetID(ctx)
if err != nil {
return "", fmt.Errorf("failed to get VolumeID for %q: %w", vol, err)
}

toAdd := map[string]string{
volID: "",
}
log.DebugLog(ctx, "adding volume mapping for volume %q to volume group %q", volID, vgName)
err = mgr.vgJournal.AddVolumesMapping(ctx, pool, gi.ObjectUUID, toAdd)
if err != nil {
return "", fmt.Errorf("failed to add mapping for volume %q to volume group %q: %w", volID, vgName, err)
}
}

_, poolID, err := util.GetPoolIDs(ctx, monitors, journalPool, pool, mgr.creds)
if err != nil {
return "", fmt.Errorf("failed to get poolID for %q: %w", groupUUID, err)
}

groupHandle, err := util.GenerateVolID(ctx, monitors, mgr.creds, poolID, pool, clusterID, groupUUID)
if err != nil {
return "", fmt.Errorf("failed to generate a unique CSI volume group with uuid for %q: %w", groupUUID, err)
}

log.DebugLog(ctx, "re-generated Group ID (%s) and Group Name (%s) for request name (%s)",
groupHandle, vgName, requestName)

return groupHandle, nil
}
4 changes: 4 additions & 0 deletions internal/rbd/types/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ type Manager interface {
// DeleteVolumeGroup removes VolumeGroup from the backend storage and
// any details from the journal.
DeleteVolumeGroup(ctx context.Context, vg VolumeGroup) error

// RegenerateVolumeGroupJournal regenerate the omap data for the volume group.
// returns the volume group handler
RegenerateVolumeGroupJournal(ctx context.Context, groupID, requestName string, volumeIds []string) (string, error)
}

0 comments on commit 6e8387d

Please sign in to comment.