func (controller *Controller) ControllerGetCapabilities(ctx context.Context, req *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) {
	var csc []*csi.ControllerServiceCapability
	cl := []csi.ControllerServiceCapability_RPC_Type{
		csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
		csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
		csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
		csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
		csi.ControllerServiceCapability_RPC_CLONE_VOLUME,
		csi.ControllerServiceCapability_RPC_EXPAND_VOLUME,
	}
	for _, cap := range cl {
		klog.V(4).Infof("enabled controller service capability: %v", cap.String())
		csc = append(csc, &csi.ControllerServiceCapability{
			Type: &csi.ControllerServiceCapability_Rpc{
				Rpc: &csi.ControllerServiceCapability_RPC{
					Type: cap,
				},
			},
		})
	}
	return &csi.ControllerGetCapabilitiesResponse{Capabilities: csc}, nil
}
ControllerGetCapabilities returns the capabilities of the controller service.
package controller
import (
	"context"
	"errors"
	"sync"
	"github.com/container-storage-interface/spec/lib/go/csi"
	"github.com/enix/dothill-api-go/v2"
	"github.com/enix/san-iscsi-csi/pkg/common"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"k8s.io/klog"
)
const (
	hostDoesNotExistsErrorCode    = -10386
	hostMapDoesNotExistsErrorCode = -10074
	unmapFailedErrorCode          = -10509
	volumeNotFoundErrorCode       = -10075
	volumeHasSnapshot             = -10183
	snapshotNotFoundErrorCode     = -10050
	snapshotAlreadyExists         = -10186
)
var volumeCapabilities = []*csi.VolumeCapability{
	{
		AccessType: &csi.VolumeCapability_Mount{
			Mount: &csi.VolumeCapability_MountVolume{},
		},
		AccessMode: &csi.VolumeCapability_AccessMode{
			Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
		},
	},
}
var csiMutexes = map[string]*sync.Mutex{
	"/csi.v1.Controller/CreateVolume":              {},
	"/csi.v1.Controller/ControllerPublishVolume":   {},
	"/csi.v1.Controller/DeleteVolume":              {},
	"/csi.v1.Controller/ControllerUnpublishVolume": {},
	"/csi.v1.Controller/ControllerExpandVolume":    {},
}
var nonAuthenticatedMethods = []string{
	"/csi.v1.Controller/ControllerGetCapabilities",
	"/csi.v1.Controller/ListVolumes",
	"/csi.v1.Controller/GetCapacity",
	"/csi.v1.Controller/ControllerGetVolume",
	"/csi.v1.Identity/Probe",
	"/csi.v1.Identity/GetPluginInfo",
	"/csi.v1.Identity/GetPluginCapabilities",
}
type Controller struct {
	*common.Driver
	dothillClient *dothill.Client
}
type DriverCtx struct {
	Credentials map[string]string
	Parameters  map[string]string
	VolumeCaps  *[]*csi.VolumeCapability
}
func New() *Controller {
	dothillClient := dothill.NewClient()
	controller := &Controller{
		Driver:        common.NewDriver(dothillClient.Collector),
		dothillClient: dothillClient,
	}
	controller.InitServer(
		func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
			if mutex, exists := csiMutexes[info.FullMethod]; exists {
				mutex.Lock()
				defer mutex.Unlock()
			}
			return handler(ctx, req)
		},
		common.NewLogRoutineServerInterceptor(func(string) bool {
			return true
		}),
		func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
			driverContext := DriverCtx{}
			if reqWithSecrets, ok := req.(common.WithSecrets); ok {
				driverContext.Credentials = reqWithSecrets.GetSecrets()
			}
			if reqWithParameters, ok := req.(common.WithParameters); ok {
				driverContext.Parameters = reqWithParameters.GetParameters()
			}
			if reqWithVolumeCaps, ok := req.(common.WithVolumeCaps); ok {
				driverContext.VolumeCaps = reqWithVolumeCaps.GetVolumeCapabilities()
			}
			err := controller.beginRoutine(&driverContext, info.FullMethod)
			defer controller.endRoutine()
			if err != nil {
				return nil, err
			}
			return handler(ctx, req)
		},
	)
	csi.RegisterIdentityServer(controller.Server, controller)
	csi.RegisterControllerServer(controller.Server, controller)
	return controller
}