diff --git a/internal/rbd/group_controller.go b/internal/rbd/group_controller.go index 6b1e421475a..1a10adef503 100644 --- a/internal/rbd/group_controller.go +++ b/internal/rbd/group_controller.go @@ -103,7 +103,7 @@ func getVolumesForGroup(ctx context.Context, volumeIDs []string, secrets map[str for i, id := range volumeIDs { volume, err := GenVolFromVolID(ctx, id, creds, secrets) if err != nil { - return nil, err + return nil, err } volumes[i] = volume @@ -142,11 +142,6 @@ func (cs *ControllerServer) CreateVolumeGroupSnapshot(ctx context.Context, req * // 5. remove all rbd-images from the RBDVolumeGroup // 6. return the RBDVolumeGroup-name and list of snapshots - config, err := getCephConfig(ctx, req.GetParameters(), req.GetSecrets()) - if err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - volumes, err := getVolumesForGroup(ctx, req.GetSourceVolumeIds(), req.GetSecrets()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -155,6 +150,11 @@ func (cs *ControllerServer) CreateVolumeGroupSnapshot(ctx context.Context, req * defer v.Destroy() } + config, err := getCephConfig(ctx, req.GetParameters(), req.GetSecrets()) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + group, err := initVolumeGroup(ctx, config, req.GetName(), req.GetSecrets()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -219,8 +219,6 @@ func (cs *ControllerServer) DeleteVolumeGroupSnapshot(ctx context.Context, req * return &csi.DeleteVolumeGroupSnapshotResponse{}, nil } -// TODO -// sortof optional, only used for static/pre-provisioned VolumeGroupSnapshots func (cs *ControllerServer) GetVolumeGroupSnapshot(ctx context.Context, req *csi.GetVolumeGroupSnapshotRequest) (*csi.GetVolumeGroupSnapshotResponse, error) { snapshot, err := rbd_group.GetVolumeGroupSnapshot(ctx, req.GetGroupSnapshotId(), req.GetSecrets()) if err != nil { diff --git a/internal/rbd_group/journal.go b/internal/rbd_group/journal.go new file mode 100644 index 00000000000..e702d50ecb4 --- /dev/null +++ b/internal/rbd_group/journal.go @@ -0,0 +1,167 @@ +/* +Copyright 2024 The Ceph-CSI Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rbd_group + +import ( + "context" + "errors" + + "github.com/ceph/go-ceph/rados" + + "github.com/ceph/ceph-csi/internal/journal" + "github.com/ceph/ceph-csi/internal/util" +) + +type groupObject struct { + clusterID string + + credentials *util.Credentials + secrets map[string]string + monitors string + pool string + + // temporary connection attributes + conn *util.ClusterConnection + ioctx *rados.IOContext + + // journalling related attributes + journal journal.VolumeGroupJournal + journalPool string + + // id is a unique value for this volume group in the Ceph cluster, it + // is used to find the group in the journal. + id string + + // name is used in RBD API calls as the name of this object + name string +} + +func (obj *groupObject) Destroy(ctx context.Context) { + if obj.journal != nil { + obj.journal.Destroy() + obj.journal = nil + } + + if obj.credentials != nil { + obj.credentials.DeleteCredentials() + obj.credentials = nil + } +} + +func (obj *groupObject) resolveByID(ctx context.Context, id string, secrets map[string]string) error { + csiID := util.CSIIdentifier{} + + err := csiID.DecomposeCSIID(id) + if err != nil { + return err + } + + mons, _, err := util.GetMonsAndClusterID(ctx, csiID.ClusterID, false) + if err != nil { + return err + } + + namespace, err := util.GetRadosNamespace(util.CsiConfigFile, csiID.ClusterID) + if err != nil { + return err + } + + obj.clusterID = csiID.ClusterID + obj.monitors = mons + obj.secrets = secrets + obj.id = id + + obj.credentials, err = util.NewUserCredentials(secrets) + if err != nil { + return err + } + defer func() { + if err != nil { + obj.Destroy(ctx) + } + }() + + pool, err := util.GetPoolName(mons, obj.credentials, csiID.LocationID) + if err != nil { + return err + } + + err = obj.SetJournalNamespace(ctx, pool, namespace) + if err != nil { + return err + } + + return nil +} + +// SetMonitors connects to the Ceph cluster. +func (obj *groupObject) SetMonitors(ctx context.Context, monitors string) error { + conn := &util.ClusterConnection{} + err := conn.Connect(monitors, obj.credentials) + if err != nil { + return err + } + + obj.conn = conn + obj.monitors = monitors + + return nil +} + +// SetPool uses the connection to the Ceph cluster to create an IOContext to +// the pool. +func (obj *groupObject) SetPool(ctx context.Context, pool string) error { + if obj.conn == nil { + return ErrRBDGroupNotConnected + } + + ioctx, err := obj.conn.GetIoctx(pool) + if err != nil { + return err + } + + obj.pool = pool + obj.ioctx = ioctx + + return nil +} + +func (obj *groupObject) SetJournalNamespace(ctx context.Context, pool, namespace string) error { + if obj.conn == nil { + return ErrRBDGroupNotConnected + } + + vgj := journal.NewCSIVolumeGroupJournal(groupSuffix) + vgj.SetNamespace(namespace) + err := vgj.Connect(obj.monitors, namespace, obj.credentials) + if err != nil { + return err + } + + obj.journal = vgj + obj.journalPool = pool + + return nil +} + +func (obj *groupObject) GetID(ctx context.Context) (string, error) { + if obj.id == "" { + return "", errors.New("BUG: ID is no set") + } + + return obj.id, nil +} diff --git a/internal/rbd_group/snapshot.go b/internal/rbd_group/snapshot.go index 10eff8ef4de..833becb6224 100644 --- a/internal/rbd_group/snapshot.go +++ b/internal/rbd_group/snapshot.go @@ -19,7 +19,6 @@ package rbd_group import ( "context" "fmt" - "time" "github.com/container-storage-interface/spec/lib/go/csi" @@ -27,45 +26,71 @@ import ( ) // verify that rbdSnapshot type implements the Snapshot interface -var _ types.Snapshot = &rbdGroupSnapshot{} +var _ types.Snapshot = &groupSnapshot{} -// rbdGroupSnapshot describes a single snapshot that was taken as part of a group. -type rbdGroupSnapshot struct { - parent types.Volume - snapName string - snapID uint64 // not needed now, may be used for cloning in the future +// groupSnapshot describes a single snapshot that was taken as part of a group. +type groupSnapshot struct { + *groupObject + + // parent is the parent RBD-image that was snapshotted + parent types.Volume + + // snapID is the (RBD) ID of the snapshot, may be used for cloning in the future + snapID uint64 // group is the optional value for a VolumeGroup that was used for - group types.VolumeGroup + group *volumeGroup } -func newGroupSnapshot(group, name string, snapID uint64) types.Snapshot { - return &rbdGroupSnapshot{ - //groupName: group, - snapName: name, - snapID: snapID, +func newGroupSnapshot(group *volumeGroup, parent types.Volume, name string, snapID uint64) types.Snapshot { + gs := &groupSnapshot{ + groupObject: &groupObject{ + name: name, + }, + parent: parent, + snapID: snapID, + group: group, } + + return gs } -func (rgs *rbdGroupSnapshot) Destroy(ctx context.Context) { - // nothing to do yet +// GetSnapshot returns a Snapshot by the given id. +func GetSnapshot(ctx context.Context, id string, secrets map[string]string) (types.Snapshot, error) { + // TODO: use the journal to resolve the groupSnapshot by ID + + gs := &groupSnapshot{} + err := gs.resolveByID(ctx, id, secrets) + if err != nil { + return nil, err + } + + // TODO: resolve more attributes from the journal + gs.parent = nil + gs.group = nil + + return gs, nil } // String returns the image-spec of the snapshot. -func (rgs *rbdGroupSnapshot) String() string { - return fmt.Sprintf("%s@%s", rgs.parent, rgs.snapName) +func (gs *groupSnapshot) String() string { + return fmt.Sprintf("%s@%s", gs.parent, gs.name) } -func (rgs *rbdGroupSnapshot) GetCreationTime(ctx context.Context) (*time.Time, error) { - return nil, nil +func (gs *groupSnapshot) Destroy(ctx context.Context) { + // nothing to do yet + + gs.groupObject.Destroy(ctx) } -func (rgs *rbdGroupSnapshot) GetReadyToUse(ctx context.Context) (bool, error) { - return false, nil +func (gs *groupSnapshot) Delete(ctx context.Context) error { + // TODO: fail in case the parent group still exists + // TODO: remove object from the journal + return nil } -func (rgs *rbdGroupSnapshot) ToCSISnapshot(ctx context.Context) (*csi.Snapshot, error) { - parentID, err := rgs.parent.GetID(ctx) +func (gs *groupSnapshot) ToCSISnapshot(ctx context.Context) (*csi.Snapshot, error) { + parentID, err := gs.parent.GetID(ctx) if err != nil { return nil, err } @@ -79,7 +104,3 @@ func (rgs *rbdGroupSnapshot) ToCSISnapshot(ctx context.Context) (*csi.Snapshot, GroupSnapshotId: parentID, }, nil } - -func (rgs *rbdGroupSnapshot) Map(ctx context.Context) (string, error) { - return "/dev/rbd123", nil -} diff --git a/internal/rbd_group/volume_group.go b/internal/rbd_group/volume_group.go index dda9aab9646..b75de0d86c9 100644 --- a/internal/rbd_group/volume_group.go +++ b/internal/rbd_group/volume_group.go @@ -20,10 +20,8 @@ import ( "context" "errors" - "github.com/ceph/go-ceph/rados" librbd "github.com/ceph/go-ceph/rbd" - "github.com/ceph/ceph-csi/internal/journal" types "github.com/ceph/ceph-csi/internal/rbd_types" "github.com/ceph/ceph-csi/internal/util" ) @@ -36,81 +34,43 @@ var ( ErrRBDGroupNotConnected = errors.New("RBD group is not connected") ) -type rbdVolumeGroup struct { - name string - clusterID string - credentials *util.Credentials - secrets map[string]string - - monitors string - pool string - poolID int64 - conn *util.ClusterConnection - ioctx *rados.IOContext - journal journal.VolumeGroupJournal - journalPool string - - id string +// volumeGroup handles all requests for 'rbd group' operations. +type volumeGroup struct { + *groupObject + + // required details to perform operations on the group + poolID int64 + + // volumes is a list of rbd-images that are part of the group. The ID + // of each volume is stored in the journal. volumes []types.Volume } -// verify that rbdVolumeGroup implements the VolumeGroup interface -var _ types.VolumeGroup = &rbdVolumeGroup{} +// verify that volumeGroup implements the VolumeGroup interface +var _ types.VolumeGroup = &volumeGroup{} // NewVolumeGroup initializes a new VolumeGroup object that can be used // to manage an `rbd group`. func NewVolumeGroup(ctx context.Context, name, clusterID string, secrets map[string]string) types.VolumeGroup { creds, _ := util.NewUserCredentials(secrets) - return &rbdVolumeGroup{ - name: name, - clusterID: clusterID, - credentials: creds, - secrets: secrets, + vg := &volumeGroup{ + groupObject: &groupObject{ + name: name, + clusterID: clusterID, + credentials: creds, + secrets: secrets, + }, } + + return vg } func GetVolumeGroup(ctx context.Context, id string, secrets map[string]string) (types.VolumeGroup, error) { - csiID := util.CSIIdentifier{} - - err := csiID.DecomposeCSIID(id) - if err != nil { - return nil, err - } - - mons, _, err := util.GetMonsAndClusterID(ctx, csiID.ClusterID, false) - if err != nil { - return nil, err - } - - namespace, err := util.GetRadosNamespace(util.CsiConfigFile, csiID.ClusterID) - if err != nil { - return nil, err - } - - vg := &rbdVolumeGroup{ - clusterID: csiID.ClusterID, - monitors: mons, - secrets: secrets, - id: id, - } - defer func() { - if err != nil { - vg.Destroy(ctx) - } - }() - - vg.credentials, err = util.NewUserCredentials(secrets) - if err != nil { - return nil, err - } - - pool, err := util.GetPoolName(mons, vg.credentials, csiID.LocationID) - if err != nil { - return nil, err - } + var err error - err = vg.SetJournalNamespace(ctx, pool, namespace) + vg := &volumeGroup{} + err = vg.resolveByID(ctx, id, secrets) if err != nil { return nil, err } @@ -118,166 +78,99 @@ func GetVolumeGroup(ctx context.Context, id string, secrets map[string]string) ( return vg, nil } -func (rvg *rbdVolumeGroup) validate() error { - if rvg.ioctx == nil { - return ErrRBDGroupNotConnected - } - - if rvg.journal == nil { +func (vg *volumeGroup) validate() error { + if vg.ioctx == nil { return ErrRBDGroupNotConnected } - return nil -} - -// Destroy frees the resources used by the rbdVolumeGroup. -func (rvg *rbdVolumeGroup) Destroy(ctx context.Context) { - if rvg.ioctx != nil { - rvg.ioctx.Destroy() - rvg.ioctx = nil - } - - if rvg.conn != nil { - rvg.conn.Destroy() - rvg.conn = nil - } - - if rvg.journal != nil { - rvg.journal.Destroy() - rvg.journal = nil - } - - if rvg.credentials != nil { - rvg.credentials.DeleteCredentials() - rvg.credentials = nil - } -} - -func (rvg *rbdVolumeGroup) GetID(ctx context.Context) (string, error) { - if rvg.id == "" { - // FIXME: rbdVolumeGroup need have called .Create() or GetVolumeGroup() - return "", errors.New("BUG: rbdVolumeGroup does not have ID set") - } - - return rvg.id, nil -} - -// SetMonitors connects to the Ceph cluster. -func (rvg *rbdVolumeGroup) SetMonitors(ctx context.Context, monitors string) error { - conn := &util.ClusterConnection{} - err := conn.Connect(monitors, rvg.credentials) - if err != nil { - return err - } - - rvg.conn = conn - rvg.monitors = monitors - - return nil -} - -// SetPool uses the connection to the Ceph cluster to create an IOContext to -// the pool. -func (rvg *rbdVolumeGroup) SetPool(ctx context.Context, pool string) error { - if rvg.conn == nil { + if vg.journal == nil { return ErrRBDGroupNotConnected } - ioctx, err := rvg.conn.GetIoctx(pool) - if err != nil { - return err - } - - rvg.pool = pool - rvg.ioctx = ioctx - return nil } -func (rvg *rbdVolumeGroup) SetJournalNamespace(ctx context.Context, pool, namespace string) error { - if rvg.conn == nil { - return ErrRBDGroupNotConnected +// Destroy frees the resources used by the volumeGroup. +func (vg *volumeGroup) Destroy(ctx context.Context) { + if vg.ioctx != nil { + vg.ioctx.Destroy() + vg.ioctx = nil } - vgj := journal.NewCSIVolumeGroupJournal(groupSuffix) - vgj.SetNamespace(namespace) - err := vgj.Connect(rvg.monitors, namespace, rvg.credentials) - if err != nil { - return err + if vg.conn != nil { + vg.conn.Destroy() + vg.conn = nil } - rvg.journal = vgj - rvg.journalPool = pool - - return nil + vg.groupObject.Destroy(ctx) } -func (rvg *rbdVolumeGroup) Create(ctx context.Context, prefix string) error { - if err := rvg.validate(); err != nil { +func (vg *volumeGroup) Create(ctx context.Context, prefix string) error { + if err := vg.validate(); err != nil { return err } journalPoolID, poolID, err := util.GetPoolIDs( ctx, - rvg.monitors, - rvg.journalPool, - rvg.pool, - rvg.credentials) + vg.monitors, + vg.journalPool, + vg.pool, + vg.credentials) if err != nil { return err } - id, uniqueName, err := rvg.journal.ReserveName( + id, uniqueName, err := vg.journal.ReserveName( ctx, - rvg.journalPool, + vg.journalPool, journalPoolID, - rvg.name, + vg.name, prefix) if err != nil { return err } - rvg.id = id - rvg.poolID = poolID + vg.id = id + vg.poolID = poolID // TODO: if the group already exists, resolve details and use that - return librbd.GroupCreate(rvg.ioctx, uniqueName) + return librbd.GroupCreate(vg.ioctx, uniqueName) } -func (rvg *rbdVolumeGroup) Delete(ctx context.Context) error { - if err := rvg.validate(); err != nil { +func (vg *volumeGroup) Delete(ctx context.Context) error { + if err := vg.validate(); err != nil { return err } - return librbd.GroupRemove(rvg.ioctx, rvg.name) + return librbd.GroupRemove(vg.ioctx, vg.name) } -func (rvg *rbdVolumeGroup) AddVolume(ctx context.Context, image types.Volume) error { - if err := rvg.validate(); err != nil { +func (vg *volumeGroup) AddVolume(ctx context.Context, image types.Volume) error { + if err := vg.validate(); err != nil { return err } - err := image.AddToGroup(ctx, rvg.ioctx, rvg.name) + err := image.AddToGroup(ctx, vg.ioctx, vg.name) if err != nil { return err } - rvg.volumes = append(rvg.volumes, image) + vg.volumes = append(vg.volumes, image) return nil } -func (rvg *rbdVolumeGroup) RemoveVolume(ctx context.Context, image types.Volume) error { - if err := rvg.validate(); err != nil { +func (vg *volumeGroup) RemoveVolume(ctx context.Context, image types.Volume) error { + if err := vg.validate(); err != nil { return err } // volume was already removed from the group - if len(rvg.volumes) == 0 { + if len(vg.volumes) == 0 { return nil } - err := image.RemoveFromGroup(ctx, rvg.ioctx, rvg.name) + err := image.RemoveFromGroup(ctx, vg.ioctx, vg.name) if err != nil { return err } @@ -290,7 +183,7 @@ func (rvg *rbdVolumeGroup) RemoveVolume(ctx context.Context, image types.Volume) // volumes is the updated list, without the volume that was removed volumes := make([]types.Volume, 0) - for _, v := range rvg.volumes { + for _, v := range vg.volumes { id, err := v.GetID(ctx) if err != nil { return err @@ -305,32 +198,32 @@ func (rvg *rbdVolumeGroup) RemoveVolume(ctx context.Context, image types.Volume) } // update the list of volumes - rvg.volumes = volumes + vg.volumes = volumes return nil } -func (rvg *rbdVolumeGroup) CreateSnapshot(ctx context.Context, snapName string) (types.VolumeGroupSnapshot, error) { - if err := rvg.validate(); err != nil { +func (vg *volumeGroup) CreateSnapshot(ctx context.Context, snapName string) (types.VolumeGroupSnapshot, error) { + if err := vg.validate(); err != nil { return nil, err } - err := librbd.GroupSnapCreate(rvg.ioctx, rvg.name, snapName) + err := librbd.GroupSnapCreate(vg.ioctx, vg.name, snapName) if err != nil { return nil, err } // TODO: if the snapName already exists, use that as return value - return newVolumeGroupSnapshot(ctx, rvg, snapName), nil + return newVolumeGroupSnapshot(ctx, vg, snapName), nil } -func (rvg *rbdVolumeGroup) DeleteSnapshot(ctx context.Context, snapName string) error { - if err := rvg.validate(); err != nil { +func (vg *volumeGroup) deleteSnapshot(ctx context.Context, snapName string) error { + if err := vg.validate(); err != nil { return err } - err := librbd.GroupSnapRemove(rvg.ioctx, rvg.name, snapName) + err := librbd.GroupSnapRemove(vg.ioctx, vg.name, snapName) if err != nil { return err } diff --git a/internal/rbd_group/volume_group_snapshot.go b/internal/rbd_group/volume_group_snapshot.go index 951896b9507..917250687b1 100644 --- a/internal/rbd_group/volume_group_snapshot.go +++ b/internal/rbd_group/volume_group_snapshot.go @@ -18,95 +18,84 @@ package rbd_group import ( "context" - "time" "github.com/container-storage-interface/spec/lib/go/csi" types "github.com/ceph/ceph-csi/internal/rbd_types" ) -// verify that rbdVolumeGroupSnapshot implements the VolumeGroupSnapshot interface -var _ types.VolumeGroupSnapshot = &rbdVolumeGroupSnapshot{} +// verify that volumeGroupSnapshot implements the VolumeGroupSnapshot interface +var _ types.VolumeGroupSnapshot = &volumeGroupSnapshot{} -// rbdVolumeGroupSnapshot is a description of a group snapshot that was taken +// volumeGroupSnapshot is a description of a group snapshot that was taken // at some point in time. The rbd-group still exists, but there are no // rbd-images in the group anymore. The list of snapshots that belongs to the // group is stored in the journal. -type rbdVolumeGroupSnapshot struct { - parentGroup *rbdVolumeGroup - name string +type volumeGroupSnapshot struct { + *groupObject - snapshots []types.Snapshot + parentGroup *volumeGroup + + snapshots []*groupSnapshot } -func newVolumeGroupSnapshot(ctx context.Context, parent *rbdVolumeGroup, name string) types.VolumeGroupSnapshot { - return &rbdVolumeGroupSnapshot{ +func newVolumeGroupSnapshot(ctx context.Context, parent *volumeGroup, name string) types.VolumeGroupSnapshot { + vgs := &volumeGroupSnapshot{ + groupObject: &groupObject{ + name: name, + }, parentGroup: parent, - name: name, } + + return vgs } func GetVolumeGroupSnapshot(ctx context.Context, id string, secrets map[string]string) (types.VolumeGroupSnapshot, error) { - // TODO: resolve the VolumeGroupSnapshot by id - return nil, nil + // TODO: use the journal to resolve the volumeGroupSnapshot by id + // TODO: for each snapshot ID in the group, use GetSnapshot() to resolve the ID to a Snapshot + + vgs := &volumeGroupSnapshot{} + err := vgs.resolveByID(ctx, id, secrets) + if err != nil { + return nil, err + } + + vgs.parentGroup = nil // TODO: use GetVolumeGroup(id) to get the volume group + + return vgs, nil } // Destroy frees the resources used by the rbdVolumeGroup. -func (rvgs *rbdVolumeGroupSnapshot) Destroy(ctx context.Context) { +func (vgs *volumeGroupSnapshot) Destroy(ctx context.Context) { // nothing to do (yet) -} -func (rvgs *rbdVolumeGroupSnapshot) Delete(ctx context.Context) error { - return nil + vgs.groupObject.Destroy(ctx) } -func (rvgs *rbdVolumeGroupSnapshot) GetID(ctx context.Context) (string, error) { - // FIXME: this should be the group-snapshot-handle - return "", nil +func (vgs *volumeGroupSnapshot) Delete(ctx context.Context) error { + return vgs.parentGroup.deleteSnapshot(ctx, vgs.name) } -func (rvgs *rbdVolumeGroupSnapshot) ListSnapshots(ctx context.Context) ([]types.Snapshot, error) { +func (vgs *volumeGroupSnapshot) ListSnapshots(ctx context.Context) ([]types.Snapshot, error) { // TODO: use parent.journal to fetch the list of snapshots return nil, nil } -func (rvgs *rbdVolumeGroupSnapshot) GetCreationTime(ctx context.Context) (*time.Time, error) { - // TODO: fetch the creation time of the group - // A group snapshot does not seem to have its own creation time. Use - // the time of the most recent created snapshot. - return nil, nil -} - -// GetReadyToUse checks if all snapshots that are part if the group are ready -// to use. -func (rvgs *rbdVolumeGroupSnapshot) GetReadyToUse(ctx context.Context) (bool, error) { - for _, snapshot := range rvgs.snapshots { - ready, err := snapshot.GetReadyToUse(ctx) - if err != nil { - return false, err - } - - if !ready { - // if this snapshot is not ready, no need to check - // other snapshots - return false, nil - } - } - - return true, nil -} - -func (rvgs *rbdVolumeGroupSnapshot) ToCSIVolumeGroupSnapshot(ctx context.Context) (*csi.VolumeGroupSnapshot, error) { - groupSnapshotID, err := rvgs.GetID(ctx) +func (vgs *volumeGroupSnapshot) ToCSIVolumeGroupSnapshot(ctx context.Context) (*csi.VolumeGroupSnapshot, error) { + groupSnapshotID, err := vgs.GetID(ctx) if err != nil { return nil, err } - snapshots, err := rvgs.ListSnapshots(ctx) + snapshots, err := vgs.ListSnapshots(ctx) if err != nil { return nil, err } + // assume all snapshots are ready, set to false in case a single + // snapshot is not ready yet + ready := true + csiSnapshots := make([]*csi.Snapshot, len(snapshots)) for i, snapshot := range snapshots { csiSnapshot, err := snapshot.ToCSISnapshot(ctx) @@ -115,11 +104,9 @@ func (rvgs *rbdVolumeGroupSnapshot) ToCSIVolumeGroupSnapshot(ctx context.Context } csiSnapshots[i] = csiSnapshot - } - ready, err := rvgs.GetReadyToUse(ctx) - if err != nil { - return nil, err + // in case the csiSnapshot is not ready, this vgs is not ready either + ready = ready && csiSnapshot.GetReadyToUse() } return &csi.VolumeGroupSnapshot{ diff --git a/internal/rbd_types/group.go b/internal/rbd_types/group.go index 5d31fda1a47..39d1a6f6e72 100644 --- a/internal/rbd_types/group.go +++ b/internal/rbd_types/group.go @@ -18,7 +18,6 @@ package rbd_types import ( "context" - "time" "github.com/container-storage-interface/spec/lib/go/csi" ) @@ -60,8 +59,5 @@ type VolumeGroupSnapshot interface { ListSnapshots(ctx context.Context) ([]Snapshot, error) - GetCreationTime(ctx context.Context) (*time.Time, error) - GetReadyToUse(ctx context.Context) (bool, error) - ToCSIVolumeGroupSnapshot(ctx context.Context) (*csi.VolumeGroupSnapshot, error) } diff --git a/internal/rbd_types/snapshot.go b/internal/rbd_types/snapshot.go index ab35eea7850..667977f5ce2 100644 --- a/internal/rbd_types/snapshot.go +++ b/internal/rbd_types/snapshot.go @@ -18,7 +18,6 @@ package rbd_types import ( "context" - "time" "github.com/container-storage-interface/spec/lib/go/csi" ) @@ -27,8 +26,7 @@ type Snapshot interface { // Destroy frees the resources used by the Snapshot. Destroy(ctx context.Context) - GetCreationTime(ctx context.Context) (*time.Time, error) - GetReadyToUse(ctx context.Context) (bool, error) + Delete(ctx context.Context) error ToCSISnapshot(ctx context.Context) (*csi.Snapshot, error) }