add prune and remove unused packages
This commit is contained in:
22
vendor/github.com/kubernetes-csi/csi-test/mock/README.md
generated
vendored
22
vendor/github.com/kubernetes-csi/csi-test/mock/README.md
generated
vendored
@@ -1,22 +0,0 @@
|
||||
# Mock CSI Driver
|
||||
Extremely simple mock driver used to test `csi-sanity` based on `rexray/gocsi/mock`.
|
||||
It can be used for testing of Container Orchestrators that implement client side
|
||||
of CSI interface.
|
||||
|
||||
```
|
||||
Usage of mock:
|
||||
-disable-attach
|
||||
Disables RPC_PUBLISH_UNPUBLISH_VOLUME capability.
|
||||
-name string
|
||||
CSI driver name. (default "io.kubernetes.storage.mock")
|
||||
```
|
||||
|
||||
It prints all received CSI messages to stdout encoded as json, so a test can check that
|
||||
CO sent the right CSI message.
|
||||
|
||||
Example of such output:
|
||||
|
||||
```
|
||||
gRPCCall: {"Method":"/csi.v0.Controller/ControllerGetCapabilities","Request":{},"Response":{"capabilities":[{"Type":{"Rpc":{"type":1}}},{"Type":{"Rpc":{"type":3}}},{"Type":{"Rpc":{"type":4}}},{"Type":{"Rpc":{"type":6}}},{"Type":{"Rpc":{"type":5}}},{"Type":{"Rpc":{"type":2}}}]},"Error":""}
|
||||
gRPCCall: {"Method":"/csi.v0.Controller/ControllerPublishVolume","Request":{"volume_id":"12","node_id":"some-fake-node-id","volume_capability":{"AccessType":{"Mount":{}},"access_mode":{"mode":1}}},"Response":null,"Error":"rpc error: code = NotFound desc = Not matching Node ID some-fake-node-id to Mock Node ID io.kubernetes.storage.mock"}
|
||||
```
|
89
vendor/github.com/kubernetes-csi/csi-test/mock/cache/SnapshotCache.go
generated
vendored
89
vendor/github.com/kubernetes-csi/csi-test/mock/cache/SnapshotCache.go
generated
vendored
@@ -1,89 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
type SnapshotCache interface {
|
||||
Add(snapshot Snapshot)
|
||||
|
||||
Delete(i int)
|
||||
|
||||
List(ready bool) []csi.Snapshot
|
||||
|
||||
FindSnapshot(k, v string) (int, Snapshot)
|
||||
}
|
||||
|
||||
type Snapshot struct {
|
||||
Name string
|
||||
Parameters map[string]string
|
||||
SnapshotCSI csi.Snapshot
|
||||
}
|
||||
|
||||
type snapshotCache struct {
|
||||
snapshotsRWL sync.RWMutex
|
||||
snapshots []Snapshot
|
||||
}
|
||||
|
||||
func NewSnapshotCache() SnapshotCache {
|
||||
return &snapshotCache{
|
||||
snapshots: make([]Snapshot, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) Add(snapshot Snapshot) {
|
||||
snap.snapshotsRWL.Lock()
|
||||
defer snap.snapshotsRWL.Unlock()
|
||||
|
||||
snap.snapshots = append(snap.snapshots, snapshot)
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) Delete(i int) {
|
||||
snap.snapshotsRWL.Lock()
|
||||
defer snap.snapshotsRWL.Unlock()
|
||||
|
||||
copy(snap.snapshots[i:], snap.snapshots[i+1:])
|
||||
snap.snapshots = snap.snapshots[:len(snap.snapshots)-1]
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) List(ready bool) []csi.Snapshot {
|
||||
snap.snapshotsRWL.RLock()
|
||||
defer snap.snapshotsRWL.RUnlock()
|
||||
|
||||
snapshots := make([]csi.Snapshot, 0)
|
||||
for _, v := range snap.snapshots {
|
||||
if v.SnapshotCSI.GetReadyToUse() {
|
||||
snapshots = append(snapshots, v.SnapshotCSI)
|
||||
}
|
||||
}
|
||||
|
||||
return snapshots
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) FindSnapshot(k, v string) (int, Snapshot) {
|
||||
snap.snapshotsRWL.RLock()
|
||||
defer snap.snapshotsRWL.RUnlock()
|
||||
|
||||
snapshotIdx := -1
|
||||
for i, vi := range snap.snapshots {
|
||||
switch k {
|
||||
case "id":
|
||||
if strings.EqualFold(v, vi.SnapshotCSI.GetSnapshotId()) {
|
||||
return i, vi
|
||||
}
|
||||
case "sourceVolumeId":
|
||||
if strings.EqualFold(v, vi.SnapshotCSI.SourceVolumeId) {
|
||||
return i, vi
|
||||
}
|
||||
case "name":
|
||||
if vi.Name == v {
|
||||
return i, vi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return snapshotIdx, Snapshot{}
|
||||
}
|
95
vendor/github.com/kubernetes-csi/csi-test/mock/main.go
generated
vendored
95
vendor/github.com/kubernetes-csi/csi-test/mock/main.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 Kubernetes 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 main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/kubernetes-csi/csi-test/driver"
|
||||
"github.com/kubernetes-csi/csi-test/mock/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var config service.Config
|
||||
flag.BoolVar(&config.DisableAttach, "disable-attach", false, "Disables RPC_PUBLISH_UNPUBLISH_VOLUME capability.")
|
||||
flag.StringVar(&config.DriverName, "name", service.Name, "CSI driver name.")
|
||||
flag.Int64Var(&config.AttachLimit, "attach-limit", 0, "number of attachable volumes on a node")
|
||||
flag.Parse()
|
||||
|
||||
endpoint := os.Getenv("CSI_ENDPOINT")
|
||||
if len(endpoint) == 0 {
|
||||
fmt.Println("CSI_ENDPOINT must be defined and must be a path")
|
||||
os.Exit(1)
|
||||
}
|
||||
if strings.Contains(endpoint, ":") {
|
||||
fmt.Println("CSI_ENDPOINT must be a unix path")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create mock driver
|
||||
s := service.New(config)
|
||||
servers := &driver.CSIDriverServers{
|
||||
Controller: s,
|
||||
Identity: s,
|
||||
Node: s,
|
||||
}
|
||||
d := driver.NewCSIDriver(servers)
|
||||
|
||||
// If creds is enabled, set the default creds.
|
||||
setCreds := os.Getenv("CSI_ENABLE_CREDS")
|
||||
if len(setCreds) > 0 && setCreds == "true" {
|
||||
d.SetDefaultCreds()
|
||||
}
|
||||
|
||||
// Listen
|
||||
os.Remove(endpoint)
|
||||
l, err := net.Listen("unix", endpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Unable to listen on %s socket: %v\n",
|
||||
endpoint,
|
||||
err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer os.Remove(endpoint)
|
||||
|
||||
// Start server
|
||||
if err := d.Start(l); err != nil {
|
||||
fmt.Printf("Error: Unable to start mock CSI server: %v\n",
|
||||
err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("mock driver started")
|
||||
|
||||
// Wait for signal
|
||||
sigc := make(chan os.Signal, 1)
|
||||
sigs := []os.Signal{
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGQUIT,
|
||||
}
|
||||
signal.Notify(sigc, sigs...)
|
||||
|
||||
<-sigc
|
||||
d.Stop()
|
||||
fmt.Println("mock driver stopped")
|
||||
}
|
16
vendor/github.com/kubernetes-csi/csi-test/mock/mocksecret.yaml
generated
vendored
16
vendor/github.com/kubernetes-csi/csi-test/mock/mocksecret.yaml
generated
vendored
@@ -1,16 +0,0 @@
|
||||
CreateVolumeSecret:
|
||||
secretKey: secretval1
|
||||
DeleteVolumeSecret:
|
||||
secretKey: secretval2
|
||||
ControllerPublishVolumeSecret:
|
||||
secretKey: secretval3
|
||||
ControllerUnpublishVolumeSecret:
|
||||
secretKey: secretval4
|
||||
NodeStageVolumeSecret:
|
||||
secretKey: secretval5
|
||||
NodePublishVolumeSecret:
|
||||
secretKey: secretval6
|
||||
CreateSnapshotSecret:
|
||||
secretKey: secretval7
|
||||
DeleteSnapshotSecret:
|
||||
secretKey: secretval8
|
577
vendor/github.com/kubernetes-csi/csi-test/mock/service/controller.go
generated
vendored
577
vendor/github.com/kubernetes-csi/csi-test/mock/service/controller.go
generated
vendored
@@ -1,577 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxStorageCapacity = tib
|
||||
ReadOnlyKey = "readonly"
|
||||
)
|
||||
|
||||
func (s *service) CreateVolume(
|
||||
ctx context.Context,
|
||||
req *csi.CreateVolumeRequest) (
|
||||
*csi.CreateVolumeResponse, error) {
|
||||
|
||||
if len(req.Name) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Name cannot be empty")
|
||||
}
|
||||
if req.VolumeCapabilities == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capabilities cannot be empty")
|
||||
}
|
||||
|
||||
// Check to see if the volume already exists.
|
||||
if i, v := s.findVolByName(ctx, req.Name); i >= 0 {
|
||||
// Requested volume name already exists, need to check if the existing volume's
|
||||
// capacity is more or equal to new request's capacity.
|
||||
if v.GetCapacityBytes() < req.GetCapacityRange().GetRequiredBytes() {
|
||||
return nil, status.Error(codes.AlreadyExists,
|
||||
fmt.Sprintf("Volume with name %s already exists", req.GetName()))
|
||||
}
|
||||
return &csi.CreateVolumeResponse{Volume: &v}, nil
|
||||
}
|
||||
|
||||
// If no capacity is specified then use 100GiB
|
||||
capacity := gib100
|
||||
if cr := req.CapacityRange; cr != nil {
|
||||
if rb := cr.RequiredBytes; rb > 0 {
|
||||
capacity = rb
|
||||
}
|
||||
if lb := cr.LimitBytes; lb > 0 {
|
||||
capacity = lb
|
||||
}
|
||||
}
|
||||
// Check for maximum available capacity
|
||||
if capacity >= MaxStorageCapacity {
|
||||
return nil, status.Errorf(codes.OutOfRange, "Requested capacity %d exceeds maximum allowed %d", capacity, MaxStorageCapacity)
|
||||
}
|
||||
// Create the volume and add it to the service's in-mem volume slice.
|
||||
v := s.newVolume(req.Name, capacity)
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
s.vols = append(s.vols, v)
|
||||
MockVolumes[v.GetVolumeId()] = Volume{
|
||||
VolumeCSI: v,
|
||||
NodeID: "",
|
||||
ISStaged: false,
|
||||
ISPublished: false,
|
||||
StageTargetPath: "",
|
||||
TargetPath: "",
|
||||
}
|
||||
|
||||
return &csi.CreateVolumeResponse{Volume: &v}, nil
|
||||
}
|
||||
|
||||
func (s *service) DeleteVolume(
|
||||
ctx context.Context,
|
||||
req *csi.DeleteVolumeRequest) (
|
||||
*csi.DeleteVolumeResponse, error) {
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
// If the volume is not specified, return error
|
||||
if len(req.VolumeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
// If the volume does not exist then return an idempotent response.
|
||||
i, _ := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// This delete logic preserves order and prevents potential memory
|
||||
// leaks. The slice's elements may not be pointers, but the structs
|
||||
// themselves have fields that are.
|
||||
copy(s.vols[i:], s.vols[i+1:])
|
||||
s.vols[len(s.vols)-1] = csi.Volume{}
|
||||
s.vols = s.vols[:len(s.vols)-1]
|
||||
log.WithField("volumeID", req.VolumeId).Debug("mock delete volume")
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) ControllerPublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.ControllerPublishVolumeRequest) (
|
||||
*csi.ControllerPublishVolumeResponse, error) {
|
||||
|
||||
if s.config.DisableAttach {
|
||||
return nil, status.Error(codes.Unimplemented, "ControllerPublish is not supported")
|
||||
}
|
||||
|
||||
if len(req.VolumeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
if len(req.NodeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Node ID cannot be empty")
|
||||
}
|
||||
if req.VolumeCapability == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capabilities cannot be empty")
|
||||
}
|
||||
|
||||
if req.NodeId != s.nodeID {
|
||||
return nil, status.Errorf(codes.NotFound, "Not matching Node ID %s to Mock Node ID %s", req.NodeId, s.nodeID)
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// devPathKey is the key in the volume's attributes that is set to a
|
||||
// mock device path if the volume has been published by the controller
|
||||
// to the specified node.
|
||||
devPathKey := path.Join(req.NodeId, "dev")
|
||||
|
||||
// Check to see if the volume is already published.
|
||||
if device := v.VolumeContext[devPathKey]; device != "" {
|
||||
var volRo bool
|
||||
var roVal string
|
||||
if ro, ok := v.VolumeContext[ReadOnlyKey]; ok {
|
||||
roVal = ro
|
||||
}
|
||||
|
||||
if roVal == "true" {
|
||||
volRo = true
|
||||
} else {
|
||||
volRo = false
|
||||
}
|
||||
|
||||
// Check if readonly flag is compatible with the publish request.
|
||||
if req.GetReadonly() != volRo {
|
||||
return nil, status.Error(codes.AlreadyExists, "Volume published but has incompatible readonly flag")
|
||||
}
|
||||
|
||||
return &csi.ControllerPublishVolumeResponse{
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
"readonly": roVal,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
var roVal string
|
||||
if req.GetReadonly() {
|
||||
roVal = "true"
|
||||
} else {
|
||||
roVal = "false"
|
||||
}
|
||||
|
||||
// Publish the volume.
|
||||
device := "/dev/mock"
|
||||
v.VolumeContext[devPathKey] = device
|
||||
v.VolumeContext[ReadOnlyKey] = roVal
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.ControllerPublishVolumeResponse{
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
"readonly": roVal,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ControllerUnpublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.ControllerUnpublishVolumeRequest) (
|
||||
*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
|
||||
if s.config.DisableAttach {
|
||||
return nil, status.Error(codes.Unimplemented, "ControllerPublish is not supported")
|
||||
}
|
||||
|
||||
if len(req.VolumeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
nodeID := req.NodeId
|
||||
if len(nodeID) == 0 {
|
||||
// If node id is empty, no failure as per Spec
|
||||
nodeID = s.nodeID
|
||||
}
|
||||
|
||||
if req.NodeId != s.nodeID {
|
||||
return nil, status.Errorf(codes.NotFound, "Node ID %s does not match to expected Node ID %s", req.NodeId, s.nodeID)
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// devPathKey is the key in the volume's attributes that is set to a
|
||||
// mock device path if the volume has been published by the controller
|
||||
// to the specified node.
|
||||
devPathKey := path.Join(nodeID, "dev")
|
||||
|
||||
// Check to see if the volume is already unpublished.
|
||||
if v.VolumeContext[devPathKey] == "" {
|
||||
return &csi.ControllerUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Unpublish the volume.
|
||||
delete(v.VolumeContext, devPathKey)
|
||||
delete(v.VolumeContext, ReadOnlyKey)
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.ControllerUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) ValidateVolumeCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.ValidateVolumeCapabilitiesRequest) (
|
||||
*csi.ValidateVolumeCapabilitiesResponse, error) {
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
if len(req.VolumeCapabilities) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, req.VolumeId)
|
||||
}
|
||||
i, _ := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{
|
||||
Confirmed: &csi.ValidateVolumeCapabilitiesResponse_Confirmed{
|
||||
VolumeContext: req.GetVolumeContext(),
|
||||
VolumeCapabilities: req.GetVolumeCapabilities(),
|
||||
Parameters: req.GetParameters(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ListVolumes(
|
||||
ctx context.Context,
|
||||
req *csi.ListVolumesRequest) (
|
||||
*csi.ListVolumesResponse, error) {
|
||||
|
||||
// Copy the mock volumes into a new slice in order to avoid
|
||||
// locking the service's volume slice for the duration of the
|
||||
// ListVolumes RPC.
|
||||
var vols []csi.Volume
|
||||
func() {
|
||||
s.volsRWL.RLock()
|
||||
defer s.volsRWL.RUnlock()
|
||||
vols = make([]csi.Volume, len(s.vols))
|
||||
copy(vols, s.vols)
|
||||
}()
|
||||
|
||||
var (
|
||||
ulenVols = int32(len(vols))
|
||||
maxEntries = req.MaxEntries
|
||||
startingToken int32
|
||||
)
|
||||
|
||||
if v := req.StartingToken; v != "" {
|
||||
i, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"startingToken=%d !< int32=%d",
|
||||
startingToken, math.MaxUint32)
|
||||
}
|
||||
startingToken = int32(i)
|
||||
}
|
||||
|
||||
if startingToken > ulenVols {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"startingToken=%d > len(vols)=%d",
|
||||
startingToken, ulenVols)
|
||||
}
|
||||
|
||||
// Discern the number of remaining entries.
|
||||
rem := ulenVols - startingToken
|
||||
|
||||
// If maxEntries is 0 or greater than the number of remaining entries then
|
||||
// set maxEntries to the number of remaining entries.
|
||||
if maxEntries == 0 || maxEntries > rem {
|
||||
maxEntries = rem
|
||||
}
|
||||
|
||||
var (
|
||||
i int
|
||||
j = startingToken
|
||||
entries = make(
|
||||
[]*csi.ListVolumesResponse_Entry,
|
||||
maxEntries)
|
||||
)
|
||||
|
||||
for i = 0; i < len(entries); i++ {
|
||||
entries[i] = &csi.ListVolumesResponse_Entry{
|
||||
Volume: &vols[j],
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
var nextToken string
|
||||
if n := startingToken + int32(i); n < ulenVols {
|
||||
nextToken = fmt.Sprintf("%d", n)
|
||||
}
|
||||
|
||||
return &csi.ListVolumesResponse{
|
||||
Entries: entries,
|
||||
NextToken: nextToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) GetCapacity(
|
||||
ctx context.Context,
|
||||
req *csi.GetCapacityRequest) (
|
||||
*csi.GetCapacityResponse, error) {
|
||||
|
||||
return &csi.GetCapacityResponse{
|
||||
AvailableCapacity: MaxStorageCapacity,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ControllerGetCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.ControllerGetCapabilitiesRequest) (
|
||||
*csi.ControllerGetCapabilitiesResponse, error) {
|
||||
|
||||
caps := []*csi.ControllerServiceCapability{
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_GET_CAPACITY,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if !s.config.DisableAttach {
|
||||
caps = append(caps, &csi.ControllerServiceCapability{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return &csi.ControllerGetCapabilitiesResponse{
|
||||
Capabilities: caps,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) CreateSnapshot(ctx context.Context,
|
||||
req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) {
|
||||
// Check arguments
|
||||
if len(req.GetName()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Snapshot Name cannot be empty")
|
||||
}
|
||||
if len(req.GetSourceVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Snapshot SourceVolumeId cannot be empty")
|
||||
}
|
||||
|
||||
// Check to see if the snapshot already exists.
|
||||
if i, v := s.snapshots.FindSnapshot("name", req.GetName()); i >= 0 {
|
||||
// Requested snapshot name already exists
|
||||
if v.SnapshotCSI.GetSourceVolumeId() != req.GetSourceVolumeId() || !reflect.DeepEqual(v.Parameters, req.GetParameters()) {
|
||||
return nil, status.Error(codes.AlreadyExists,
|
||||
fmt.Sprintf("Snapshot with name %s already exists", req.GetName()))
|
||||
}
|
||||
return &csi.CreateSnapshotResponse{Snapshot: &v.SnapshotCSI}, nil
|
||||
}
|
||||
|
||||
// Create the snapshot and add it to the service's in-mem snapshot slice.
|
||||
snapshot := s.newSnapshot(req.GetName(), req.GetSourceVolumeId(), req.GetParameters())
|
||||
s.snapshots.Add(snapshot)
|
||||
|
||||
return &csi.CreateSnapshotResponse{Snapshot: &snapshot.SnapshotCSI}, nil
|
||||
}
|
||||
|
||||
func (s *service) DeleteSnapshot(ctx context.Context,
|
||||
req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) {
|
||||
|
||||
// If the snapshot is not specified, return error
|
||||
if len(req.SnapshotId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Snapshot ID cannot be empty")
|
||||
}
|
||||
|
||||
// If the snapshot does not exist then return an idempotent response.
|
||||
i, _ := s.snapshots.FindSnapshot("id", req.SnapshotId)
|
||||
if i < 0 {
|
||||
return &csi.DeleteSnapshotResponse{}, nil
|
||||
}
|
||||
|
||||
// This delete logic preserves order and prevents potential memory
|
||||
// leaks. The slice's elements may not be pointers, but the structs
|
||||
// themselves have fields that are.
|
||||
s.snapshots.Delete(i)
|
||||
log.WithField("SnapshotId", req.SnapshotId).Debug("mock delete snapshot")
|
||||
return &csi.DeleteSnapshotResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) ListSnapshots(ctx context.Context,
|
||||
req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
|
||||
// case 1: SnapshotId is not empty, return snapshots that match the snapshot id.
|
||||
if len(req.GetSnapshotId()) != 0 {
|
||||
return getSnapshotById(s, req)
|
||||
}
|
||||
|
||||
// case 2: SourceVolumeId is not empty, return snapshots that match the source volume id.
|
||||
if len(req.GetSourceVolumeId()) != 0 {
|
||||
return getSnapshotByVolumeId(s, req)
|
||||
}
|
||||
|
||||
// case 3: no parameter is set, so we return all the snapshots.
|
||||
return getAllSnapshots(s, req)
|
||||
}
|
||||
|
||||
func getSnapshotById(s *service, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
if len(req.GetSnapshotId()) != 0 {
|
||||
i, snapshot := s.snapshots.FindSnapshot("id", req.GetSnapshotId())
|
||||
if i < 0 {
|
||||
return &csi.ListSnapshotsResponse{}, nil
|
||||
}
|
||||
|
||||
if len(req.GetSourceVolumeId()) != 0 {
|
||||
if snapshot.SnapshotCSI.GetSourceVolumeId() != req.GetSourceVolumeId() {
|
||||
return &csi.ListSnapshotsResponse{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return &csi.ListSnapshotsResponse{
|
||||
Entries: []*csi.ListSnapshotsResponse_Entry{
|
||||
{
|
||||
Snapshot: &snapshot.SnapshotCSI,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getSnapshotByVolumeId(s *service, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
if len(req.GetSourceVolumeId()) != 0 {
|
||||
i, snapshot := s.snapshots.FindSnapshot("sourceVolumeId", req.SourceVolumeId)
|
||||
if i < 0 {
|
||||
return &csi.ListSnapshotsResponse{}, nil
|
||||
}
|
||||
return &csi.ListSnapshotsResponse{
|
||||
Entries: []*csi.ListSnapshotsResponse_Entry{
|
||||
{
|
||||
Snapshot: &snapshot.SnapshotCSI,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getAllSnapshots(s *service, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
// Copy the mock snapshots into a new slice in order to avoid
|
||||
// locking the service's snapshot slice for the duration of the
|
||||
// ListSnapshots RPC.
|
||||
readyToUse := true
|
||||
snapshots := s.snapshots.List(readyToUse)
|
||||
|
||||
var (
|
||||
ulenSnapshots = int32(len(snapshots))
|
||||
maxEntries = req.MaxEntries
|
||||
startingToken int32
|
||||
)
|
||||
|
||||
if v := req.StartingToken; v != "" {
|
||||
i, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(
|
||||
codes.Aborted,
|
||||
"startingToken=%d !< int32=%d",
|
||||
startingToken, math.MaxUint32)
|
||||
}
|
||||
startingToken = int32(i)
|
||||
}
|
||||
|
||||
if startingToken > ulenSnapshots {
|
||||
return nil, status.Errorf(
|
||||
codes.Aborted,
|
||||
"startingToken=%d > len(snapshots)=%d",
|
||||
startingToken, ulenSnapshots)
|
||||
}
|
||||
|
||||
// Discern the number of remaining entries.
|
||||
rem := ulenSnapshots - startingToken
|
||||
|
||||
// If maxEntries is 0 or greater than the number of remaining entries then
|
||||
// set maxEntries to the number of remaining entries.
|
||||
if maxEntries == 0 || maxEntries > rem {
|
||||
maxEntries = rem
|
||||
}
|
||||
|
||||
var (
|
||||
i int
|
||||
j = startingToken
|
||||
entries = make(
|
||||
[]*csi.ListSnapshotsResponse_Entry,
|
||||
maxEntries)
|
||||
)
|
||||
|
||||
for i = 0; i < len(entries); i++ {
|
||||
entries[i] = &csi.ListSnapshotsResponse_Entry{
|
||||
Snapshot: &snapshots[j],
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
var nextToken string
|
||||
if n := startingToken + int32(i); n < ulenSnapshots {
|
||||
nextToken = fmt.Sprintf("%d", n)
|
||||
}
|
||||
|
||||
return &csi.ListSnapshotsResponse{
|
||||
Entries: entries,
|
||||
NextToken: nextToken,
|
||||
}, nil
|
||||
}
|
48
vendor/github.com/kubernetes-csi/csi-test/mock/service/identity.go
generated
vendored
48
vendor/github.com/kubernetes-csi/csi-test/mock/service/identity.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
)
|
||||
|
||||
func (s *service) GetPluginInfo(
|
||||
ctx context.Context,
|
||||
req *csi.GetPluginInfoRequest) (
|
||||
*csi.GetPluginInfoResponse, error) {
|
||||
|
||||
return &csi.GetPluginInfoResponse{
|
||||
Name: s.config.DriverName,
|
||||
VendorVersion: VendorVersion,
|
||||
Manifest: Manifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) Probe(
|
||||
ctx context.Context,
|
||||
req *csi.ProbeRequest) (
|
||||
*csi.ProbeResponse, error) {
|
||||
|
||||
return &csi.ProbeResponse{
|
||||
Ready: &wrappers.BoolValue{Value: true},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) GetPluginCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.GetPluginCapabilitiesRequest) (
|
||||
*csi.GetPluginCapabilitiesResponse, error) {
|
||||
|
||||
return &csi.GetPluginCapabilitiesResponse{
|
||||
Capabilities: []*csi.PluginCapability{
|
||||
{
|
||||
Type: &csi.PluginCapability_Service_{
|
||||
Service: &csi.PluginCapability_Service{
|
||||
Type: csi.PluginCapability_Service_CONTROLLER_SERVICE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
244
vendor/github.com/kubernetes-csi/csi-test/mock/service/node.go
generated
vendored
244
vendor/github.com/kubernetes-csi/csi-test/mock/service/node.go
generated
vendored
@@ -1,244 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
func (s *service) NodeStageVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodeStageVolumeRequest) (
|
||||
*csi.NodeStageVolumeResponse, error) {
|
||||
|
||||
device, ok := req.PublishContext["device"]
|
||||
if !ok {
|
||||
if s.config.DisableAttach {
|
||||
device = "mock device"
|
||||
} else {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
"stage volume info 'device' key required")
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
if len(req.GetStagingTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Staging Target Path cannot be empty")
|
||||
}
|
||||
|
||||
if req.GetVolumeCapability() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capability cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeStgPathKey is the key in the volume's attributes that is set to a
|
||||
// mock stage path if the volume has been published by the node
|
||||
nodeStgPathKey := path.Join(s.nodeID, req.StagingTargetPath)
|
||||
|
||||
// Check to see if the volume has already been staged.
|
||||
if v.VolumeContext[nodeStgPathKey] != "" {
|
||||
// TODO: Check for the capabilities to be equal. Return "ALREADY_EXISTS"
|
||||
// if the capabilities don't match.
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Stage the volume.
|
||||
v.VolumeContext[nodeStgPathKey] = device
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeUnstageVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodeUnstageVolumeRequest) (
|
||||
*csi.NodeUnstageVolumeResponse, error) {
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
if len(req.GetStagingTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Staging Target Path cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeStgPathKey is the key in the volume's attributes that is set to a
|
||||
// mock stage path if the volume has been published by the node
|
||||
nodeStgPathKey := path.Join(s.nodeID, req.StagingTargetPath)
|
||||
|
||||
// Check to see if the volume has already been unstaged.
|
||||
if v.VolumeContext[nodeStgPathKey] == "" {
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Unpublish the volume.
|
||||
delete(v.VolumeContext, nodeStgPathKey)
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodePublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodePublishVolumeRequest) (
|
||||
*csi.NodePublishVolumeResponse, error) {
|
||||
|
||||
device, ok := req.PublishContext["device"]
|
||||
if !ok {
|
||||
if s.config.DisableAttach {
|
||||
device = "mock device"
|
||||
} else {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
"stage volume info 'device' key required")
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
if len(req.GetTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target Path cannot be empty")
|
||||
}
|
||||
|
||||
if req.GetVolumeCapability() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capability cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeMntPathKey is the key in the volume's attributes that is set to a
|
||||
// mock mount path if the volume has been published by the node
|
||||
nodeMntPathKey := path.Join(s.nodeID, req.TargetPath)
|
||||
|
||||
// Check to see if the volume has already been published.
|
||||
if v.VolumeContext[nodeMntPathKey] != "" {
|
||||
|
||||
// Requests marked Readonly fail due to volumes published by
|
||||
// the Mock driver supporting only RW mode.
|
||||
if req.Readonly {
|
||||
return nil, status.Error(codes.AlreadyExists, req.VolumeId)
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Publish the volume.
|
||||
if req.GetStagingTargetPath() != "" {
|
||||
v.VolumeContext[nodeMntPathKey] = req.GetStagingTargetPath()
|
||||
} else {
|
||||
v.VolumeContext[nodeMntPathKey] = device
|
||||
}
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeUnpublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodeUnpublishVolumeRequest) (
|
||||
*csi.NodeUnpublishVolumeResponse, error) {
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
if len(req.GetTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target Path cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeMntPathKey is the key in the volume's attributes that is set to a
|
||||
// mock mount path if the volume has been published by the node
|
||||
nodeMntPathKey := path.Join(s.nodeID, req.TargetPath)
|
||||
|
||||
// Check to see if the volume has already been unpublished.
|
||||
if v.VolumeContext[nodeMntPathKey] == "" {
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Unpublish the volume.
|
||||
delete(v.VolumeContext, nodeMntPathKey)
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeGetCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.NodeGetCapabilitiesRequest) (
|
||||
*csi.NodeGetCapabilitiesResponse, error) {
|
||||
|
||||
return &csi.NodeGetCapabilitiesResponse{
|
||||
Capabilities: []*csi.NodeServiceCapability{
|
||||
{
|
||||
Type: &csi.NodeServiceCapability_Rpc{
|
||||
Rpc: &csi.NodeServiceCapability_RPC{
|
||||
Type: csi.NodeServiceCapability_RPC_UNKNOWN,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.NodeServiceCapability_Rpc{
|
||||
Rpc: &csi.NodeServiceCapability_RPC{
|
||||
Type: csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeGetInfo(ctx context.Context,
|
||||
req *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) {
|
||||
csiNodeResponse := &csi.NodeGetInfoResponse{
|
||||
NodeId: s.nodeID,
|
||||
}
|
||||
if s.config.AttachLimit > 0 {
|
||||
csiNodeResponse.MaxVolumesPerNode = s.config.AttachLimit
|
||||
}
|
||||
return csiNodeResponse, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeGetVolumeStats(ctx context.Context,
|
||||
req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
|
||||
return &csi.NodeGetVolumeStatsResponse{}, nil
|
||||
|
||||
}
|
147
vendor/github.com/kubernetes-csi/csi-test/mock/service/service.go
generated
vendored
147
vendor/github.com/kubernetes-csi/csi-test/mock/service/service.go
generated
vendored
@@ -1,147 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/kubernetes-csi/csi-test/mock/cache"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
const (
|
||||
// Name is the name of the CSI plug-in.
|
||||
Name = "io.kubernetes.storage.mock"
|
||||
|
||||
// VendorVersion is the version returned by GetPluginInfo.
|
||||
VendorVersion = "0.3.0"
|
||||
)
|
||||
|
||||
// Manifest is the SP's manifest.
|
||||
var Manifest = map[string]string{
|
||||
"url": "https://github.com/kubernetes-csi/csi-test/mock",
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
DisableAttach bool
|
||||
DriverName string
|
||||
AttachLimit int64
|
||||
}
|
||||
|
||||
// Service is the CSI Mock service provider.
|
||||
type Service interface {
|
||||
csi.ControllerServer
|
||||
csi.IdentityServer
|
||||
csi.NodeServer
|
||||
}
|
||||
|
||||
type service struct {
|
||||
sync.Mutex
|
||||
nodeID string
|
||||
vols []csi.Volume
|
||||
volsRWL sync.RWMutex
|
||||
volsNID uint64
|
||||
snapshots cache.SnapshotCache
|
||||
snapshotsNID uint64
|
||||
config Config
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
sync.Mutex
|
||||
VolumeCSI csi.Volume
|
||||
NodeID string
|
||||
ISStaged bool
|
||||
ISPublished bool
|
||||
StageTargetPath string
|
||||
TargetPath string
|
||||
}
|
||||
|
||||
var MockVolumes map[string]Volume
|
||||
|
||||
// New returns a new Service.
|
||||
func New(config Config) Service {
|
||||
s := &service{
|
||||
nodeID: config.DriverName,
|
||||
config: config,
|
||||
}
|
||||
s.snapshots = cache.NewSnapshotCache()
|
||||
s.vols = []csi.Volume{
|
||||
s.newVolume("Mock Volume 1", gib100),
|
||||
s.newVolume("Mock Volume 2", gib100),
|
||||
s.newVolume("Mock Volume 3", gib100),
|
||||
}
|
||||
MockVolumes = map[string]Volume{}
|
||||
|
||||
s.snapshots.Add(s.newSnapshot("Mock Snapshot 1", "1", map[string]string{"Description": "snapshot 1"}))
|
||||
s.snapshots.Add(s.newSnapshot("Mock Snapshot 2", "2", map[string]string{"Description": "snapshot 2"}))
|
||||
s.snapshots.Add(s.newSnapshot("Mock Snapshot 3", "3", map[string]string{"Description": "snapshot 3"}))
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
const (
|
||||
kib int64 = 1024
|
||||
mib int64 = kib * 1024
|
||||
gib int64 = mib * 1024
|
||||
gib100 int64 = gib * 100
|
||||
tib int64 = gib * 1024
|
||||
tib100 int64 = tib * 100
|
||||
)
|
||||
|
||||
func (s *service) newVolume(name string, capcity int64) csi.Volume {
|
||||
return csi.Volume{
|
||||
VolumeId: fmt.Sprintf("%d", atomic.AddUint64(&s.volsNID, 1)),
|
||||
VolumeContext: map[string]string{"name": name},
|
||||
CapacityBytes: capcity,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) findVol(k, v string) (volIdx int, volInfo csi.Volume) {
|
||||
s.volsRWL.RLock()
|
||||
defer s.volsRWL.RUnlock()
|
||||
return s.findVolNoLock(k, v)
|
||||
}
|
||||
|
||||
func (s *service) findVolNoLock(k, v string) (volIdx int, volInfo csi.Volume) {
|
||||
volIdx = -1
|
||||
|
||||
for i, vi := range s.vols {
|
||||
switch k {
|
||||
case "id":
|
||||
if strings.EqualFold(v, vi.GetVolumeId()) {
|
||||
return i, vi
|
||||
}
|
||||
case "name":
|
||||
if n, ok := vi.VolumeContext["name"]; ok && strings.EqualFold(v, n) {
|
||||
return i, vi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *service) findVolByName(
|
||||
ctx context.Context, name string) (int, csi.Volume) {
|
||||
|
||||
return s.findVol("name", name)
|
||||
}
|
||||
|
||||
func (s *service) newSnapshot(name, sourceVolumeId string, parameters map[string]string) cache.Snapshot {
|
||||
|
||||
ptime := ptypes.TimestampNow()
|
||||
return cache.Snapshot{
|
||||
Name: name,
|
||||
Parameters: parameters,
|
||||
SnapshotCSI: csi.Snapshot{
|
||||
SnapshotId: fmt.Sprintf("%d", atomic.AddUint64(&s.snapshotsNID, 1)),
|
||||
CreationTime: ptime,
|
||||
SourceVolumeId: sourceVolumeId,
|
||||
ReadyToUse: true,
|
||||
},
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user