Let lookupVolume return NotFound when an invalid volume id is given

This commit is contained in:
Helen Zhang
2024-01-06 16:03:05 -08:00
parent b7e0b32f24
commit fa7f020c50

View File

@@ -6,9 +6,9 @@
package service package service
import ( import (
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/oracle/zfssa-csi-driver/pkg/utils" "github.com/oracle/zfssa-csi-driver/pkg/utils"
"github.com/oracle/zfssa-csi-driver/pkg/zfssarest" "github.com/oracle/zfssa-csi-driver/pkg/zfssarest"
"github.com/container-storage-interface/spec/lib/go/csi"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@@ -58,7 +58,7 @@ import (
// volume source. // volume source.
// //
type volumeState int type volumeState int
const ( const (
stateCreating volumeState = iota stateCreating volumeState = iota
@@ -71,7 +71,7 @@ type zVolumeInterface interface {
create(ctx context.Context, token *zfssarest.Token, create(ctx context.Context, token *zfssarest.Token,
req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error)
delete(ctx context.Context, token *zfssarest.Token, delete(ctx context.Context, token *zfssarest.Token,
) (*csi.DeleteVolumeResponse, error) ) (*csi.DeleteVolumeResponse, error)
controllerPublishVolume(ctx context.Context, token *zfssarest.Token, controllerPublishVolume(ctx context.Context, token *zfssarest.Token,
req *csi.ControllerPublishVolumeRequest, nodeName string) (*csi.ControllerPublishVolumeResponse, error) req *csi.ControllerPublishVolumeRequest, nodeName string) (*csi.ControllerPublishVolumeResponse, error)
controllerUnpublishVolume(ctx context.Context, token *zfssarest.Token, controllerUnpublishVolume(ctx context.Context, token *zfssarest.Token,
@@ -109,20 +109,18 @@ type zVolumeInterface interface {
isBlock() bool isBlock() bool
} }
// This method must be called when the possibility of the volume not existing yet exists. // This method must be called when the possibility of the volume not existing yet exists.
// The following 3 scenarios are possible: // The following 3 scenarios are possible:
// //
// * The volume doesn't exists yet or it exists in the appliance but is not in the // - The volume doesn't exists yet or it exists in the appliance but is not in the
// volume cache yet. Either way, a structure representing the volume is created // volume cache yet. Either way, a structure representing the volume is created
// in the stateCreating state, stored in the cache and a reference returned to the // in the stateCreating state, stored in the cache and a reference returned to the
// caller. // caller.
// * A structure representing the volume already exists in the cache and is in the // - A structure representing the volume already exists in the cache and is in the
// stateCreated state. A reference is returned to the caller. // stateCreated state. A reference is returned to the caller.
// * A structure representing the volume already exists in the cache and is NOT in // - A structure representing the volume already exists in the cache and is NOT in
// the stateCreated state. This means the CO probably lost state and submitted multiple // the stateCreated state. This means the CO probably lost state and submitted multiple
// simultaneous requests for this volume. In this case an error is returned. // simultaneous requests for this volume. In this case an error is returned.
//
func (zd *ZFSSADriver) newVolume(ctx context.Context, pool, project, name string, func (zd *ZFSSADriver) newVolume(ctx context.Context, pool, project, name string,
block bool) (zVolumeInterface, error) { block bool) (zVolumeInterface, error) {
@@ -140,7 +138,7 @@ func (zd *ZFSSADriver) newVolume(ctx context.Context, pool, project, name string
zvol := zd.vCache.lookup(ctx, name) zvol := zd.vCache.lookup(ctx, name)
if zvol != nil { if zvol != nil {
// Volume already known. // Volume already known.
utils.GetLogCTRL(ctx, 5).Println("zd.newVolume", "request", ) utils.GetLogCTRL(ctx, 5).Println("zd.newVolume", "request")
zvol.hold(ctx) zvol.hold(ctx)
zd.vCache.Unlock(ctx) zd.vCache.Unlock(ctx)
if zvol.lock(ctx) != stateCreated { if zvol.lock(ctx) != stateCreated {
@@ -167,7 +165,8 @@ func (zd *ZFSSADriver) lookupVolume(ctx context.Context, token *zfssarest.Token,
vid, err := utils.VolumeIdFromString(volumeId) vid, err := utils.VolumeIdFromString(volumeId)
if err != nil { if err != nil {
return nil, err utils.GetLogCTRL(ctx, 2).Println("Failed to get volumeId from String", err.Error())
return nil, status.Errorf(codes.NotFound, "Volume (%s) not found", volumeId)
} }
// Check first in the list of volumes if the volume is already known. // Check first in the list of volumes if the volume is already known.
@@ -194,21 +193,21 @@ func (zd *ZFSSADriver) lookupVolume(ctx context.Context, token *zfssarest.Token,
} }
switch zvol.getState() { switch zvol.getState() {
case stateCreating: // We check with the appliance. case stateCreating: // We check with the appliance.
httpStatus, err := zvol.getDetails(ctx, token) httpStatus, err := zvol.getDetails(ctx, token)
if err != nil { if err != nil {
zd.releaseVolume(ctx, zvol) zd.releaseVolume(ctx, zvol)
if httpStatus == http.StatusNotFound { if httpStatus == http.StatusNotFound {
return nil, status.Error(codes.NotFound, "Volume (%s) not found") return nil, status.Errorf(codes.NotFound, "Volume (%s) not found", volumeId)
} }
return nil, err return nil, err
} }
return zvol, nil return zvol, nil
case stateCreated: // Another Goroutine beat us to it. case stateCreated: // Another Goroutine beat us to it.
return zvol, nil return zvol, nil
default: default:
zd.releaseVolume(ctx, zvol) zd.releaseVolume(ctx, zvol)
return nil, status.Error(codes.NotFound, "Volume (%s) not found") return nil, status.Errorf(codes.NotFound, "Volume (%s) not found", volumeId)
} }
} }
@@ -234,15 +233,16 @@ func (zd *ZFSSADriver) releaseVolume(ctx context.Context, zvol zVolumeInterface)
// If a snapshot with the passed in name already exists, it is returned. If it doesn't exist, // If a snapshot with the passed in name already exists, it is returned. If it doesn't exist,
// a new snapshot structure is created and returned. This method could fail or reasons: // a new snapshot structure is created and returned. This method could fail or reasons:
// //
// 1) A snapshot with the passed in name already exists but the volume source // 1. A snapshot with the passed in name already exists but the volume source
// is not the volume source passed in. // is not the volume source passed in.
// 2) A snapshot with the passed in name already exists but is not in the stateCreated
// state (or stable state). As for volumes, This would mean the CO lost state and
// issued simultaneous requests for the same snapshot.
// //
// If the call is successful, that caller has exclusive access to the snapshot and its volume // 2. A snapshot with the passed in name already exists but is not in the stateCreated
// source. When the snapshot returned is not needed anymore, the method releaseSnapshot() // state (or stable state). As for volumes, This would mean the CO lost state and
// must be called. // issued simultaneous requests for the same snapshot.
//
// If the call is successful, that caller has exclusive access to the snapshot and its volume
// source. When the snapshot returned is not needed anymore, the method releaseSnapshot()
// must be called.
func (zd *ZFSSADriver) newSnapshot(ctx context.Context, token *zfssarest.Token, func (zd *ZFSSADriver) newSnapshot(ctx context.Context, token *zfssarest.Token,
name, sourceId string) (*zSnapshot, error) { name, sourceId string) (*zSnapshot, error) {
@@ -289,13 +289,13 @@ func (zd *ZFSSADriver) newSnapshot(ctx context.Context, token *zfssarest.Token,
// exclusive access to the returned snapshot and its volume source. This method could fail // exclusive access to the returned snapshot and its volume source. This method could fail
// for the following reasons: // for the following reasons:
// //
// 1) The source volume cannot be found locally or in the appliance. // 1. The source volume cannot be found locally or in the appliance.
// 2) The snapshot exists but is in an unstable state. This would mean the // 2. The snapshot exists but is in an unstable state. This would mean the
// CO lost state and issued multiple simultaneous requests for the same // CO lost state and issued multiple simultaneous requests for the same
// snapshot. // snapshot.
// 3) There's an inconsistency between what the appliance thinks the volume // 3. There's an inconsistency between what the appliance thinks the volume
// source is and what the existing snapshot says it is (a panic is issued). // source is and what the existing snapshot says it is (a panic is issued).
// 4) The snapshot cannot be found locally or in the appliance. // 4. The snapshot cannot be found locally or in the appliance.
func (zd *ZFSSADriver) lookupSnapshot(ctx context.Context, token *zfssarest.Token, func (zd *ZFSSADriver) lookupSnapshot(ctx context.Context, token *zfssarest.Token,
snapshotId string) (*zSnapshot, error) { snapshotId string) (*zSnapshot, error) {
@@ -346,14 +346,14 @@ func (zd *ZFSSADriver) lookupSnapshot(ctx context.Context, token *zfssarest.Toke
} }
switch zsnap.getState() { switch zsnap.getState() {
case stateCreating: // We check with the appliance. case stateCreating: // We check with the appliance.
_, err = zsnap.getDetails(ctx, token) _, err = zsnap.getDetails(ctx, token)
if err != nil { if err != nil {
zd.releaseSnapshot(ctx, zsnap) zd.releaseSnapshot(ctx, zsnap)
return nil, err return nil, err
} }
return zsnap, nil return zsnap, nil
case stateCreated: // Another Goroutine beat us to it. case stateCreated: // Another Goroutine beat us to it.
return zsnap, nil return zsnap, nil
default: default:
zd.releaseSnapshot(ctx, zsnap) zd.releaseSnapshot(ctx, zsnap)
@@ -398,8 +398,8 @@ func (zd *ZFSSADriver) getVolumesList(ctx context.Context) ([]*csi.ListVolumesRe
for _, zvol := range zd.vCache.vHash { for _, zvol := range zd.vCache.vHash {
entry := new(csi.ListVolumesResponse_Entry) entry := new(csi.ListVolumesResponse_Entry)
entry.Volume = &csi.Volume{ entry.Volume = &csi.Volume{
VolumeId: zvol.getVolumeID().String(), VolumeId: zvol.getVolumeID().String(),
CapacityBytes: zvol.getCapacity(), CapacityBytes: zvol.getCapacity(),
} }
entries = append(entries, entry) entries = append(entries, entry)
} }
@@ -416,8 +416,8 @@ func (zd *ZFSSADriver) updateVolumeList(ctx context.Context) error {
lunChan := make(chan error) lunChan := make(chan error)
go zd.updateFilesystemList(ctx, fsChan) go zd.updateFilesystemList(ctx, fsChan)
go zd.updateLunList(ctx, lunChan) go zd.updateLunList(ctx, lunChan)
errfs := <- fsChan errfs := <-fsChan
errlun := <- lunChan errlun := <-lunChan
if errfs != nil { if errfs != nil {
return errfs return errfs
@@ -496,12 +496,12 @@ func (zd *ZFSSADriver) getSnapshotList(ctx context.Context) ([]*csi.ListSnapshot
entries := make([]*csi.ListSnapshotsResponse_Entry, 0, len(zd.sCache.sHash)) entries := make([]*csi.ListSnapshotsResponse_Entry, 0, len(zd.sCache.sHash))
for _, zsnap := range zd.sCache.sHash { for _, zsnap := range zd.sCache.sHash {
entry := new(csi.ListSnapshotsResponse_Entry) entry := new(csi.ListSnapshotsResponse_Entry)
entry.Snapshot = &csi.Snapshot { entry.Snapshot = &csi.Snapshot{
SizeBytes: zsnap.getSize(), SizeBytes: zsnap.getSize(),
SnapshotId: zsnap.getStringId(), SnapshotId: zsnap.getStringId(),
SourceVolumeId: zsnap.getStringSourceId(), SourceVolumeId: zsnap.getStringSourceId(),
CreationTime: zsnap.getCreationTime(), CreationTime: zsnap.getCreationTime(),
ReadyToUse: zsnap.getState() == stateCreated, ReadyToUse: zsnap.getState() == stateCreated,
} }
entries = append(entries, entry) entries = append(entries, entry)
} }
@@ -583,8 +583,8 @@ func compareCapabilities(req []*csi.VolumeCapability, cur []csi.VolumeCapability
} }
type volumeHashTable struct { type volumeHashTable struct {
vMutex sync.RWMutex vMutex sync.RWMutex
vHash map[string]zVolumeInterface vHash map[string]zVolumeInterface
} }
func (h *volumeHashTable) add(ctx context.Context, key string, zvol zVolumeInterface) { func (h *volumeHashTable) add(ctx context.Context, key string, zvol zVolumeInterface) {
@@ -616,8 +616,8 @@ func (h *volumeHashTable) RUnlock(ctx context.Context) {
} }
type snapshotHashTable struct { type snapshotHashTable struct {
sMutex sync.RWMutex sMutex sync.RWMutex
sHash map[string]*zSnapshot sHash map[string]*zSnapshot
} }
func (h *snapshotHashTable) add(ctx context.Context, key string, zsnap *zSnapshot) { func (h *snapshotHashTable) add(ctx context.Context, key string, zsnap *zSnapshot) {