Skip to content

Commit

Permalink
Implement PUBLISH_READONLY capability
Browse files Browse the repository at this point in the history
  • Loading branch information
jsafrane committed Nov 20, 2018
1 parent 515e1b4 commit 46d88ad
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 68 deletions.
4 changes: 2 additions & 2 deletions cmd/csi-attacher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func main() {
glog.V(2).Infof("CSI driver does not support Plugin Controller Service, using trivial handler")
} else {
// Find out if the driver supports attach/detach.
supportsAttach, err := csiConn.SupportsControllerPublish(ctx)
supportsAttach, supportsReadOnly, err := csiConn.SupportsControllerPublish(ctx)
if err != nil {
glog.Error(err.Error())
os.Exit(1)
Expand All @@ -148,7 +148,7 @@ func main() {
vaLister := factory.Storage().V1beta1().VolumeAttachments().Lister()
csiFactory := csiinformers.NewSharedInformerFactory(csiClientset, *resync)
nodeInfoLister := csiFactory.Csi().V1alpha1().CSINodeInfos().Lister()
handler = controller.NewCSIHandler(clientset, csiClientset, attacher, csiConn, pvLister, nodeLister, nodeInfoLister, vaLister, timeout)
handler = controller.NewCSIHandler(clientset, csiClientset, attacher, csiConn, pvLister, nodeLister, nodeInfoLister, vaLister, timeout, supportsReadOnly)
glog.V(2).Infof("CSI driver supports ControllerPublishUnpublish, using real CSI handler")
} else {
handler = controller.NewTrivialHandler(clientset)
Expand Down
16 changes: 11 additions & 5 deletions pkg/connection/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type CSIConnection interface {

// SupportsControllerPublish returns true if the CSI driver reports
// PUBLISH_UNPUBLISH_VOLUME in ControllerGetCapabilities() gRPC call.
SupportsControllerPublish(ctx context.Context) (bool, error)
SupportsControllerPublish(ctx context.Context) (supportsControllerPublish bool, supportsPublishReadOnly bool, err error)

// SupportsPluginControllerService return true if the CSI driver reports
// CONTROLLER_SERVICE in GetPluginCapabilities() gRPC call.
Expand Down Expand Up @@ -144,13 +144,16 @@ func (c *csiConnection) Probe(ctx context.Context) error {
return nil
}

func (c *csiConnection) SupportsControllerPublish(ctx context.Context) (bool, error) {
func (c *csiConnection) SupportsControllerPublish(ctx context.Context) (supportsControllerPublish bool, supportsPublishReadOnly bool, err error) {
supportsControllerPublish = false
supportsPublishReadOnly = false

client := csi.NewControllerClient(c.conn)
req := csi.ControllerGetCapabilitiesRequest{}

rsp, err := client.ControllerGetCapabilities(ctx, &req)
if err != nil {
return false, err
return false, false, err
}
caps := rsp.GetCapabilities()
for _, cap := range caps {
Expand All @@ -162,10 +165,13 @@ func (c *csiConnection) SupportsControllerPublish(ctx context.Context) (bool, er
continue
}
if rpc.GetType() == csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME {
return true, nil
supportsControllerPublish = true
}
if rpc.GetType() == csi.ControllerServiceCapability_RPC_PUBLISH_READONLY {
supportsPublishReadOnly = true
}
}
return false, nil
return supportsControllerPublish, supportsPublishReadOnly, nil
}

func (c *csiConnection) SupportsPluginControllerService(ctx context.Context) (bool, error) {
Expand Down
58 changes: 49 additions & 9 deletions pkg/connection/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,12 @@ func TestGetPluginInfo(t *testing.T) {

func TestSupportsControllerPublish(t *testing.T) {
tests := []struct {
name string
output *csi.ControllerGetCapabilitiesResponse
injectError bool
expectError bool
name string
output *csi.ControllerGetCapabilitiesResponse
injectError bool
expectSupportsPublish bool
expectSupportsReadOnly bool
expectError bool
}{
{
name: "success",
Expand All @@ -167,7 +169,33 @@ func TestSupportsControllerPublish(t *testing.T) {
},
},
},
expectError: false,
expectSupportsPublish: true,
expectSupportsReadOnly: false,
expectError: false,
},
{
name: "supports read only",
output: &csi.ControllerGetCapabilitiesResponse{
Capabilities: []*csi.ControllerServiceCapability{
{
Type: &csi.ControllerServiceCapability_Rpc{
Rpc: &csi.ControllerServiceCapability_RPC{
Type: csi.ControllerServiceCapability_RPC_PUBLISH_READONLY,
},
},
},
{
Type: &csi.ControllerServiceCapability_Rpc{
Rpc: &csi.ControllerServiceCapability_RPC{
Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
},
},
},
},
},
expectSupportsPublish: true,
expectSupportsReadOnly: true,
expectError: false,
},
{
name: "gRPC error",
Expand All @@ -188,7 +216,9 @@ func TestSupportsControllerPublish(t *testing.T) {
},
},
},
expectError: false,
expectSupportsPublish: false,
expectSupportsReadOnly: false,
expectError: false,
},
{
name: "empty capability",
Expand All @@ -199,14 +229,18 @@ func TestSupportsControllerPublish(t *testing.T) {
},
},
},
expectError: false,
expectSupportsPublish: false,
expectSupportsReadOnly: false,
expectError: false,
},
{
name: "no capabilities",
output: &csi.ControllerGetCapabilitiesResponse{
Capabilities: []*csi.ControllerServiceCapability{},
},
expectError: false,
expectSupportsPublish: false,
expectSupportsReadOnly: false,
expectError: false,
},
}

Expand All @@ -231,13 +265,19 @@ func TestSupportsControllerPublish(t *testing.T) {
// Setup expectation
controllerServer.EXPECT().ControllerGetCapabilities(gomock.Any(), pbMatch(in)).Return(out, injectedErr).Times(1)

_, err = csiConn.SupportsControllerPublish(context.Background())
supportsPublish, supportsReadOnly, err := csiConn.SupportsControllerPublish(context.Background())
if test.expectError && err == nil {
t.Errorf("test %q: Expected error, got none", test.name)
}
if !test.expectError && err != nil {
t.Errorf("test %q: got error: %v", test.name, err)
}
if test.expectSupportsPublish != supportsPublish {
t.Errorf("test %q: expected PUBLISH_UNPUBLISH_VOLUME %t, got %t", test.name, test.expectSupportsPublish, supportsPublish)
}
if test.expectSupportsReadOnly != supportsReadOnly {
t.Errorf("test %q: expected PUBLISH_READONLY %t, got %t", test.name, test.expectSupportsReadOnly, supportsReadOnly)
}
}
}

Expand Down
49 changes: 29 additions & 20 deletions pkg/controller/csi_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@ import (
// It adds finalizer to VolumeAttachment instance to make sure they're detached
// before deletion.
type csiHandler struct {
client kubernetes.Interface
csiClientSet csiclient.Interface
attacherName string
csiConnection connection.CSIConnection
pvLister corelisters.PersistentVolumeLister
nodeLister corelisters.NodeLister
nodeInfoLister csilisters.CSINodeInfoLister
vaLister storagelisters.VolumeAttachmentLister
vaQueue, pvQueue workqueue.RateLimitingInterface
timeout time.Duration
client kubernetes.Interface
csiClientSet csiclient.Interface
attacherName string
csiConnection connection.CSIConnection
pvLister corelisters.PersistentVolumeLister
nodeLister corelisters.NodeLister
nodeInfoLister csilisters.CSINodeInfoLister
vaLister storagelisters.VolumeAttachmentLister
vaQueue, pvQueue workqueue.RateLimitingInterface
timeout time.Duration
supportsPublishReadOnly bool
}

var _ Handler = &csiHandler{}
Expand All @@ -67,18 +68,20 @@ func NewCSIHandler(
nodeLister corelisters.NodeLister,
nodeInfoLister csilisters.CSINodeInfoLister,
vaLister storagelisters.VolumeAttachmentLister,
timeout *time.Duration) Handler {
timeout *time.Duration,
supportsPublishReadOnly bool) Handler {

return &csiHandler{
client: client,
csiClientSet: csiClientSet,
attacherName: attacherName,
csiConnection: csiConnection,
pvLister: pvLister,
nodeLister: nodeLister,
nodeInfoLister: nodeInfoLister,
vaLister: vaLister,
timeout: *timeout,
client: client,
csiClientSet: csiClientSet,
attacherName: attacherName,
csiConnection: csiConnection,
pvLister: pvLister,
nodeLister: nodeLister,
nodeInfoLister: nodeInfoLister,
vaLister: vaLister,
timeout: *timeout,
supportsPublishReadOnly: supportsPublishReadOnly,
}
}

Expand Down Expand Up @@ -289,6 +292,12 @@ func (h *csiHandler) csiAttach(va *storage.VolumeAttachment) (*storage.VolumeAtt
if err != nil {
return va, nil, err
}
if !h.supportsPublishReadOnly {
// "CO MUST set this field to false if SP does not have the
// PUBLISH_READONLY controller capability"
readOnly = false
}

volumeCapabilities, err := GetVolumeCapabilities(pv, csiSource)
if err != nil {
return va, nil, err
Expand Down
Loading

0 comments on commit 46d88ad

Please sign in to comment.