From dd08d1b489894de6e51952c752f4cfadfa1c4499 Mon Sep 17 00:00:00 2001 From: Vladimir Vivien Date: Tue, 24 Oct 2017 22:44:48 -0400 Subject: [PATCH 1/3] CSI - API source code implementation This commit tracks source code update for the CSI volume plugin implementation. --- cmd/kube-controller-manager/app/plugins.go | 10 + cmd/kubelet/app/plugins.go | 7 + pkg/volume/csi/OWNERS | 4 + pkg/volume/csi/csi_attacher.go | 268 +++++++++++++++++++ pkg/volume/csi/csi_attacher_test.go | 277 +++++++++++++++++++ pkg/volume/csi/csi_client.go | 233 ++++++++++++++++ pkg/volume/csi/csi_client_test.go | 126 +++++++++ pkg/volume/csi/csi_mounter.go | 194 ++++++++++++++ pkg/volume/csi/csi_mounter_test.go | 152 +++++++++++ pkg/volume/csi/csi_plugin.go | 257 ++++++++++++++++++ pkg/volume/csi/csi_plugin_test.go | 297 +++++++++++++++++++++ pkg/volume/csi/fake/fake_client.go | 224 ++++++++++++++++ 12 files changed, 2049 insertions(+) create mode 100644 pkg/volume/csi/OWNERS create mode 100644 pkg/volume/csi/csi_attacher.go create mode 100644 pkg/volume/csi/csi_attacher_test.go create mode 100644 pkg/volume/csi/csi_client.go create mode 100644 pkg/volume/csi/csi_client_test.go create mode 100644 pkg/volume/csi/csi_mounter.go create mode 100644 pkg/volume/csi/csi_mounter_test.go create mode 100644 pkg/volume/csi/csi_plugin.go create mode 100644 pkg/volume/csi/csi_plugin_test.go create mode 100644 pkg/volume/csi/fake/fake_client.go diff --git a/cmd/kube-controller-manager/app/plugins.go b/cmd/kube-controller-manager/app/plugins.go index 716539b9fe0..9851816bd6f 100644 --- a/cmd/kube-controller-manager/app/plugins.go +++ b/cmd/kube-controller-manager/app/plugins.go @@ -41,6 +41,7 @@ import ( "k8s.io/kubernetes/pkg/volume/azure_dd" "k8s.io/kubernetes/pkg/volume/azure_file" "k8s.io/kubernetes/pkg/volume/cinder" + "k8s.io/kubernetes/pkg/volume/csi" "k8s.io/kubernetes/pkg/volume/fc" "k8s.io/kubernetes/pkg/volume/flexvolume" "k8s.io/kubernetes/pkg/volume/flocker" @@ -58,6 +59,9 @@ import ( "k8s.io/kubernetes/pkg/volume/storageos" volumeutil "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/vsphere_volume" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) // ProbeAttachableVolumePlugins collects all volume plugins for the attach/ @@ -79,6 +83,9 @@ func ProbeAttachableVolumePlugins() []volume.VolumePlugin { allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...) allPlugins = append(allPlugins, iscsi.ProbeVolumePlugins()...) allPlugins = append(allPlugins, rbd.ProbeVolumePlugins()...) + if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { + allPlugins = append(allPlugins, csi.ProbeVolumePlugins()...) + } return allPlugins } @@ -105,6 +112,9 @@ func ProbeExpandableVolumePlugins(config componentconfig.VolumeConfiguration) [] allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...) allPlugins = append(allPlugins, storageos.ProbeVolumePlugins()...) allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...) + if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { + allPlugins = append(allPlugins, csi.ProbeVolumePlugins()...) + } return allPlugins } diff --git a/cmd/kubelet/app/plugins.go b/cmd/kubelet/app/plugins.go index e14513a18b2..002b5de8c5d 100644 --- a/cmd/kubelet/app/plugins.go +++ b/cmd/kubelet/app/plugins.go @@ -35,6 +35,7 @@ import ( "k8s.io/kubernetes/pkg/volume/cephfs" "k8s.io/kubernetes/pkg/volume/cinder" "k8s.io/kubernetes/pkg/volume/configmap" + "k8s.io/kubernetes/pkg/volume/csi" "k8s.io/kubernetes/pkg/volume/downwardapi" "k8s.io/kubernetes/pkg/volume/empty_dir" "k8s.io/kubernetes/pkg/volume/fc" @@ -58,6 +59,9 @@ import ( "k8s.io/kubernetes/pkg/volume/vsphere_volume" // Cloud providers _ "k8s.io/kubernetes/pkg/cloudprovider/providers" + // features check + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) // ProbeVolumePlugins collects all volume plugins into an easy to use list. @@ -96,6 +100,9 @@ func ProbeVolumePlugins() []volume.VolumePlugin { allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...) allPlugins = append(allPlugins, local.ProbeVolumePlugins()...) allPlugins = append(allPlugins, storageos.ProbeVolumePlugins()...) + if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { + allPlugins = append(allPlugins, csi.ProbeVolumePlugins()...) + } return allPlugins } diff --git a/pkg/volume/csi/OWNERS b/pkg/volume/csi/OWNERS new file mode 100644 index 00000000000..7d0605ba3dd --- /dev/null +++ b/pkg/volume/csi/OWNERS @@ -0,0 +1,4 @@ +approvers: +- jsafrane +- saad-ali +- vladimirvivien diff --git a/pkg/volume/csi/csi_attacher.go b/pkg/volume/csi/csi_attacher.go new file mode 100644 index 00000000000..11ca86e66f5 --- /dev/null +++ b/pkg/volume/csi/csi_attacher.go @@ -0,0 +1,268 @@ +/* +Copyright 2017 The 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 csi + +import ( + "crypto/sha256" + "errors" + "fmt" + "strings" + "time" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + storage "k8s.io/api/storage/v1alpha1" + apierrs "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/volume" +) + +type csiAttacher struct { + plugin *csiPlugin + k8s kubernetes.Interface + waitSleepTime time.Duration +} + +// volume.Attacher methods +var _ volume.Attacher = &csiAttacher{} + +func (c *csiAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { + if spec == nil { + glog.Error(log("attacher.Attach missing volume.Spec")) + return "", errors.New("missing spec") + } + + csiSource, err := getCSISourceFromSpec(spec) + if err != nil { + glog.Error(log("attacher.Attach failed to get CSI persistent source: %v", err)) + return "", errors.New("missing CSI persistent volume") + } + + pvName := spec.PersistentVolume.GetName() + attachID := getAttachmentName(csiSource.VolumeHandle, string(nodeName)) + + attachment := &storage.VolumeAttachment{ + ObjectMeta: meta.ObjectMeta{ + Name: attachID, + }, + Spec: storage.VolumeAttachmentSpec{ + NodeName: string(nodeName), + Attacher: csiPluginName, + Source: storage.VolumeAttachmentSource{ + PersistentVolumeName: &pvName, + }, + }, + Status: storage.VolumeAttachmentStatus{Attached: false}, + } + + attach, err := c.k8s.StorageV1alpha1().VolumeAttachments().Create(attachment) + alreadyExist := false + if err != nil { + if !apierrs.IsAlreadyExists(err) { + glog.Error(log("attacher.Attach failed: %v", err)) + return "", err + } + alreadyExist = true + } + + if alreadyExist { + glog.V(4).Info(log("attachment [%v] for volume [%v] already exists (will not be recreated)", attach.GetName(), csiSource.VolumeHandle)) + } else { + glog.V(4).Info(log("attachment [%v] for volume [%v] created successfully, will start probing for updates", attach.GetName(), csiSource.VolumeHandle)) + } + + // probe for attachment update here + // NOTE: any error from waiting for attachment is logged only. This is because + // the primariy intent of the enclosing method is to create VolumeAttachment. + // DONOT return that error here as it is mitigated in attacher.WaitForAttach. + if _, err := c.waitForVolumeAttachment(csiSource.VolumeHandle, attachID, csiTimeout); err != nil { + glog.Error(log("attacher.Attach encountered error during attachment probing: %v", err)) + } + + return attachID, nil +} + +func (c *csiAttacher) WaitForAttach(spec *volume.Spec, attachID string, pod *v1.Pod, timeout time.Duration) (string, error) { + source, err := getCSISourceFromSpec(spec) + if err != nil { + glog.Error(log("attacher.WaitForAttach failed to extract CSI volume source: %v", err)) + return "", err + } + + return c.waitForVolumeAttachment(source.VolumeHandle, attachID, timeout) +} + +func (c *csiAttacher) waitForVolumeAttachment(volumeHandle, attachID string, timeout time.Duration) (string, error) { + glog.V(4).Info(log("probing for updates from CSI driver for [attachment.ID=%v]", attachID)) + + ticker := time.NewTicker(c.waitSleepTime) + defer ticker.Stop() + + timer := time.NewTimer(timeout) // TODO (vladimirvivien) investigate making this configurable + defer timer.Stop() + + //TODO (vladimirvivien) instead of polling api-server, change to a api-server watch + for { + select { + case <-ticker.C: + glog.V(4).Info(log("probing VolumeAttachment [id=%v]", attachID)) + attach, err := c.k8s.StorageV1alpha1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + glog.Error(log("attacher.WaitForAttach failed (will continue to try): %v", err)) + continue + } + // if being deleted, fail fast + if attach.GetDeletionTimestamp() != nil { + glog.Error(log("VolumeAttachment [%s] has deletion timestamp, will not continue to wait for attachment", attachID)) + return "", errors.New("volume attachment is being deleted") + } + // attachment OK + if attach.Status.Attached { + return attachID, nil + } + // driver reports attach error + attachErr := attach.Status.AttachError + if attachErr != nil { + glog.Error(log("attachment for %v failed: %v", volumeHandle, attachErr.Message)) + return "", errors.New(attachErr.Message) + } + case <-timer.C: + glog.Error(log("attacher.WaitForAttach timeout after %v [volume=%v; attachment.ID=%v]", timeout, volumeHandle, attachID)) + return "", fmt.Errorf("attachment timeout for volume %v", volumeHandle) + } + } +} + +func (c *csiAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) { + glog.V(4).Info(log("probing attachment status for %d volumes ", len(specs))) + + attached := make(map[*volume.Spec]bool) + + for _, spec := range specs { + if spec == nil { + glog.Error(log("attacher.VolumesAreAttached missing volume.Spec")) + return nil, errors.New("missing spec") + } + source, err := getCSISourceFromSpec(spec) + if err != nil { + glog.Error(log("attacher.VolumesAreAttached failed: %v", err)) + continue + } + attachID := getAttachmentName(source.VolumeHandle, string(nodeName)) + glog.V(4).Info(log("probing attachment status for VolumeAttachment %v", attachID)) + attach, err := c.k8s.StorageV1alpha1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + glog.Error(log("attacher.VolumesAreAttached failed for attach.ID=%v: %v", attachID, err)) + continue + } + attached[spec] = attach.Status.Attached + } + + return attached, nil +} + +func (c *csiAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) { + glog.V(4).Info(log("attacher.GetDeviceMountPath is not implemented")) + return "", nil +} + +func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error { + glog.V(4).Info(log("attacher.MountDevice is not implemented")) + return nil +} + +var _ volume.Detacher = &csiAttacher{} + +func (c *csiAttacher) Detach(volumeName string, nodeName types.NodeName) error { + // volumeName in format driverNamevolumeHandle generated by plugin.GetVolumeName() + if volumeName == "" { + glog.Error(log("detacher.Detach missing value for parameter volumeName")) + return errors.New("missing exepected parameter volumeName") + } + parts := strings.Split(volumeName, volNameSep) + if len(parts) != 2 { + glog.Error(log("detacher.Detach insufficient info encoded in volumeName")) + return errors.New("volumeName missing expected data") + } + volID := parts[1] + attachID := getAttachmentName(volID, string(nodeName)) + err := c.k8s.StorageV1alpha1().VolumeAttachments().Delete(attachID, nil) + if err != nil { + glog.Error(log("detacher.Detach failed to delete VolumeAttachment [%s]: %v", attachID, err)) + return err + } + + glog.V(4).Info(log("detacher deleted ok VolumeAttachment.ID=%s", attachID)) + return c.waitForVolumeDetachment(volID, attachID) +} + +func (c *csiAttacher) waitForVolumeDetachment(volumeHandle, attachID string) error { + glog.V(4).Info(log("probing for updates from CSI driver for [attachment.ID=%v]", attachID)) + + ticker := time.NewTicker(c.waitSleepTime) + defer ticker.Stop() + + timeout := c.waitSleepTime * 10 + timer := time.NewTimer(timeout) // TODO (vladimirvivien) investigate making this configurable + defer timer.Stop() + + //TODO (vladimirvivien) instead of polling api-server, change to a api-server watch + for { + select { + case <-ticker.C: + glog.V(4).Info(log("probing VolumeAttachment [id=%v]", attachID)) + attach, err := c.k8s.StorageV1alpha1().VolumeAttachments().Get(attachID, meta.GetOptions{}) + if err != nil { + if apierrs.IsNotFound(err) { + //object deleted or never existed, done + glog.V(4).Info(log("VolumeAttachment object [%v] for volume [%v] not found, object deleted", attachID, volumeHandle)) + return nil + } + glog.Error(log("detacher.WaitForDetach failed for volume [%s] (will continue to try): %v", volumeHandle, err)) + continue + } + + // driver reports attach error + detachErr := attach.Status.DetachError + if detachErr != nil { + glog.Error(log("detachment for VolumeAttachment [%v] for volume [%s] failed: %v", attachID, volumeHandle, detachErr.Message)) + return errors.New(detachErr.Message) + } + case <-timer.C: + glog.Error(log("detacher.WaitForDetach timeout after %v [volume=%v; attachment.ID=%v]", timeout, volumeHandle, attachID)) + return fmt.Errorf("detachment timed out for volume %v", volumeHandle) + } + } +} + +func (c *csiAttacher) UnmountDevice(deviceMountPath string) error { + glog.V(4).Info(log("detacher.UnmountDevice is not implemented")) + return nil +} + +func hashAttachmentName(volName, nodeName string) string { + result := sha256.Sum256([]byte(fmt.Sprintf("%s%s", volName, nodeName))) + return fmt.Sprintf("%x", result) +} + +func getAttachmentName(volName, nodeName string) string { + // TODO consider using a different prefix for attachment + return fmt.Sprintf("pv-%s", hashAttachmentName(volName, nodeName)) +} diff --git a/pkg/volume/csi/csi_attacher_test.go b/pkg/volume/csi/csi_attacher_test.go new file mode 100644 index 00000000000..2e1cb3fc61f --- /dev/null +++ b/pkg/volume/csi/csi_attacher_test.go @@ -0,0 +1,277 @@ +/* +Copyright 2017 The 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 csi + +import ( + "crypto/sha256" + "fmt" + "os" + "testing" + "time" + + "k8s.io/api/core/v1" + storage "k8s.io/api/storage/v1alpha1" + apierrs "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/volume" +) + +func makeTestAttachment(attachID, nodeName, pvName string) *storage.VolumeAttachment { + return &storage.VolumeAttachment{ + ObjectMeta: meta.ObjectMeta{ + Name: attachID, + }, + Spec: storage.VolumeAttachmentSpec{ + NodeName: nodeName, + Attacher: csiPluginName, + Source: storage.VolumeAttachmentSource{ + PersistentVolumeName: &pvName, + }, + }, + Status: storage.VolumeAttachmentStatus{ + Attached: false, + AttachError: nil, + DetachError: nil, + }, + } +} + +func TestAttacherAttach(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + attacher, err := plug.NewAttacher() + if err != nil { + t.Fatalf("failed to create new attacher: %v", err) + } + + csiAttacher := attacher.(*csiAttacher) + + testCases := []struct { + name string + pv *v1.PersistentVolume + nodeName string + attachHash [32]byte + shouldFail bool + }{ + { + name: "test ok 1", + pv: makeTestPV("test-pv-001", 10, testDriver, "test-vol-1"), + nodeName: "test-node", + attachHash: sha256.Sum256([]byte(fmt.Sprintf("%s%s", "test-vol-1", "test-node"))), + }, + { + name: "test ok 2", + pv: makeTestPV("test-pv-002", 10, testDriver, "test-vol-002"), + nodeName: "test-node", + attachHash: sha256.Sum256([]byte(fmt.Sprintf("%s%s", "test-vol-002", "test-node"))), + }, + { + name: "missing spec", + pv: nil, + nodeName: "test-node", + attachHash: sha256.Sum256([]byte(fmt.Sprintf("%s%s", "test-vol-3", "test-node"))), + shouldFail: true, + }, + } + + for _, tc := range testCases { + var spec *volume.Spec + if tc.pv != nil { + spec = volume.NewSpecFromPersistentVolume(tc.pv, tc.pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + } + + attachID, err := csiAttacher.Attach(spec, types.NodeName(tc.nodeName)) + if tc.shouldFail && err == nil { + t.Error("expected failure, but got nil err") + } + if attachID != "" { + expectedID := fmt.Sprintf("pv-%x", tc.attachHash) + if attachID != expectedID { + t.Errorf("expecting attachID %v, got %v", expectedID, attachID) + } + } + } +} + +func TestAttacherWaitForVolumeAttachment(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + attacher, err := plug.NewAttacher() + if err != nil { + t.Fatalf("failed to create new attacher: %v", err) + } + csiAttacher := attacher.(*csiAttacher) + nodeName := "test-node" + + testCases := []struct { + name string + attached bool + attachErr *storage.VolumeError + sleepTime time.Duration + timeout time.Duration + shouldFail bool + }{ + {name: "attach ok", attached: true, sleepTime: 10 * time.Millisecond, timeout: 50 * time.Millisecond}, + {name: "attachment error", attachErr: &storage.VolumeError{Message: "missing volume"}, sleepTime: 10 * time.Millisecond, timeout: 30 * time.Millisecond}, + {name: "time ran out", attached: false, sleepTime: 5 * time.Millisecond}, + } + + for i, tc := range testCases { + t.Logf("running test: %v", tc.name) + pvName := fmt.Sprintf("test-pv-%d", i) + attachID := fmt.Sprintf("pv-%s", hashAttachmentName(pvName, nodeName)) + + attachment := makeTestAttachment(attachID, nodeName, pvName) + attachment.Status.Attached = tc.attached + attachment.Status.AttachError = tc.attachErr + csiAttacher.waitSleepTime = tc.sleepTime + + go func() { + _, err := csiAttacher.k8s.StorageV1alpha1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to attach: %v", err) + } + }() + + retID, err := csiAttacher.waitForVolumeAttachment("test-vol", attachID, tc.timeout) + if tc.shouldFail && err == nil { + t.Error("expecting failure, but err is nil") + } + if tc.attachErr != nil { + if tc.attachErr.Message != err.Error() { + t.Errorf("expecting error [%v], got [%v]", tc.attachErr.Message, err.Error()) + } + } + if err == nil && retID != attachID { + t.Errorf("attacher.WaitForAttach not returning attachment ID") + } + } +} + +func TestAttacherVolumesAreAttached(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + attacher, err := plug.NewAttacher() + if err != nil { + t.Fatalf("failed to create new attacher: %v", err) + } + csiAttacher := attacher.(*csiAttacher) + nodeName := "test-node" + + testCases := []struct { + name string + attachedStats map[string]bool + }{ + {"attach + detach", map[string]bool{"vol-01": true, "vol-02": true, "vol-03": false, "vol-04": false, "vol-05": true}}, + {"all detached", map[string]bool{"vol-11": false, "vol-12": false, "vol-13": false, "vol-14": false, "vol-15": false}}, + {"all attached", map[string]bool{"vol-21": true, "vol-22": true, "vol-23": true, "vol-24": true, "vol-25": true}}, + } + + for _, tc := range testCases { + var specs []*volume.Spec + // create and save volume attchments + for volName, stat := range tc.attachedStats { + pv := makeTestPV("test-pv", 10, testDriver, volName) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + specs = append(specs, spec) + attachID := getAttachmentName(volName, nodeName) + attachment := makeTestAttachment(attachID, nodeName, pv.GetName()) + attachment.Status.Attached = stat + _, err := csiAttacher.k8s.StorageV1alpha1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to attach: %v", err) + } + } + + // retrieve attached status + stats, err := csiAttacher.VolumesAreAttached(specs, types.NodeName(nodeName)) + if err != nil { + t.Fatal(err) + } + if len(tc.attachedStats) != len(stats) { + t.Errorf("expecting %d attachment status, got %d", len(tc.attachedStats), len(stats)) + } + + // compare attachment status for each spec + for spec, stat := range stats { + source, err := getCSISourceFromSpec(spec) + if err != nil { + t.Error(err) + } + if stat != tc.attachedStats[source.VolumeHandle] { + t.Errorf("expecting volume attachment %t, got %t", tc.attachedStats[source.VolumeHandle], stat) + } + } + } +} + +func TestAttacherDetach(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + attacher, err := plug.NewAttacher() + if err != nil { + t.Fatalf("failed to create new attacher: %v", err) + } + csiAttacher := attacher.(*csiAttacher) + nodeName := "test-node" + testCases := []struct { + name string + volID string + attachID string + shouldFail bool + }{ + {name: "normal test", volID: "vol-001", attachID: fmt.Sprintf("pv-%s", hashAttachmentName("vol-001", nodeName))}, + {name: "normal test 2", volID: "vol-002", attachID: fmt.Sprintf("pv-%s", hashAttachmentName("vol-002", nodeName))}, + {name: "object not found", volID: "vol-001", attachID: fmt.Sprintf("pv-%s", hashAttachmentName("vol-002", nodeName)), shouldFail: true}, + } + + for _, tc := range testCases { + pv := makeTestPV("test-pv", 10, testDriver, tc.volID) + spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly) + attachment := makeTestAttachment(tc.attachID, nodeName, "test-pv") + _, err := csiAttacher.k8s.StorageV1alpha1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to attach: %v", err) + } + volumeName, err := plug.GetVolumeName(spec) + if err != nil { + t.Errorf("test case %s failed: %v", tc.name, err) + } + err = csiAttacher.Detach(volumeName, types.NodeName(nodeName)) + if tc.shouldFail && err == nil { + t.Fatal("expecting failure, but err = nil") + } + if !tc.shouldFail && err != nil { + t.Fatalf("unexpected err: %v", err) + } + attach, err := csiAttacher.k8s.StorageV1alpha1().VolumeAttachments().Get(tc.attachID, meta.GetOptions{}) + if err != nil { + if !apierrs.IsNotFound(err) { + t.Fatalf("unexpected err: %v", err) + } + } else { + if attach == nil { + t.Errorf("expecting attachment not to be nil, but it is") + } + } + } +} diff --git a/pkg/volume/csi/csi_client.go b/pkg/volume/csi/csi_client.go new file mode 100644 index 00000000000..22b4d5bae6b --- /dev/null +++ b/pkg/volume/csi/csi_client.go @@ -0,0 +1,233 @@ +/* +Copyright 2017 The 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 csi + +import ( + "bytes" + "errors" + "fmt" + "net" + "time" + + csipb "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/golang/glog" + grpctx "golang.org/x/net/context" + "google.golang.org/grpc" + api "k8s.io/api/core/v1" +) + +type csiClient interface { + AssertSupportedVersion(ctx grpctx.Context, ver *csipb.Version) error + NodePublishVolume( + ctx grpctx.Context, + volumeid string, + readOnly bool, + targetPath string, + accessMode api.PersistentVolumeAccessMode, + volumeInfo map[string]string, + fsType string, + ) error + NodeUnpublishVolume(ctx grpctx.Context, volID string, targetPath string) error +} + +// csiClient encapsulates all csi-plugin methods +type csiDriverClient struct { + network string + addr string + conn *grpc.ClientConn + idClient csipb.IdentityClient + nodeClient csipb.NodeClient + ctrlClient csipb.ControllerClient + versionAsserted bool + versionSupported bool + publishAsserted bool + publishCapable bool +} + +func newCsiDriverClient(network, addr string) *csiDriverClient { + return &csiDriverClient{network: network, addr: addr} +} + +// assertConnection ensures a valid connection has been established +// if not, it creates a new connection and associated clients +func (c *csiDriverClient) assertConnection() error { + if c.conn == nil { + conn, err := grpc.Dial( + c.addr, + grpc.WithInsecure(), + grpc.WithDialer(func(target string, timeout time.Duration) (net.Conn, error) { + return net.Dial(c.network, target) + }), + ) + if err != nil { + return err + } + c.conn = conn + c.idClient = csipb.NewIdentityClient(conn) + c.nodeClient = csipb.NewNodeClient(conn) + c.ctrlClient = csipb.NewControllerClient(conn) + + // set supported version + } + + return nil +} + +// AssertSupportedVersion ensures driver supports specified spec version. +// If version is not supported, the assertion fails with an error. +// This test should be done early during the storage operation flow to avoid +// unnecessary calls later. +func (c *csiDriverClient) AssertSupportedVersion(ctx grpctx.Context, ver *csipb.Version) error { + if c.versionAsserted { + if !c.versionSupported { + return fmt.Errorf("version %s not supported", verToStr(ver)) + } + return nil + } + + if err := c.assertConnection(); err != nil { + c.versionAsserted = false + return err + } + + glog.V(4).Info(log("asserting version supported by driver")) + rsp, err := c.idClient.GetSupportedVersions(ctx, &csipb.GetSupportedVersionsRequest{}) + if err != nil { + c.versionAsserted = false + return err + } + + supported := false + vers := rsp.GetSupportedVersions() + glog.V(4).Info(log("driver reports %d versions supported: %s", len(vers), versToStr(vers))) + + for _, v := range vers { + //TODO (vladimirvivien) use more lenient/heuristic for exact or match of ranges etc + if verToStr(v) == verToStr(ver) { + supported = true + break + } + } + + c.versionAsserted = true + c.versionSupported = supported + + if !supported { + return fmt.Errorf("version %s not supported", verToStr(ver)) + } + + glog.V(4).Info(log("version %s supported", verToStr(ver))) + return nil +} + +func (c *csiDriverClient) NodePublishVolume( + ctx grpctx.Context, + volID string, + readOnly bool, + targetPath string, + accessMode api.PersistentVolumeAccessMode, + volumeInfo map[string]string, + fsType string, +) error { + + if volID == "" { + return errors.New("missing volume id") + } + if targetPath == "" { + return errors.New("missing target path") + } + if err := c.assertConnection(); err != nil { + glog.Errorf("%v: failed to assert a connection: %v", csiPluginName, err) + return err + } + + req := &csipb.NodePublishVolumeRequest{ + Version: csiVersion, + VolumeId: volID, + TargetPath: targetPath, + Readonly: readOnly, + PublishVolumeInfo: volumeInfo, + + VolumeCapability: &csipb.VolumeCapability{ + AccessMode: &csipb.VolumeCapability_AccessMode{ + Mode: asCSIAccessMode(accessMode), + }, + AccessType: &csipb.VolumeCapability_Mount{ + Mount: &csipb.VolumeCapability_MountVolume{ + FsType: fsType, + }, + }, + }, + } + + _, err := c.nodeClient.NodePublishVolume(ctx, req) + return err +} + +func (c *csiDriverClient) NodeUnpublishVolume(ctx grpctx.Context, volID string, targetPath string) error { + + if volID == "" { + return errors.New("missing volume id") + } + if targetPath == "" { + return errors.New("missing target path") + } + if err := c.assertConnection(); err != nil { + glog.Error(log("failed to assert a connection: %v", err)) + return err + } + + req := &csipb.NodeUnpublishVolumeRequest{ + Version: csiVersion, + VolumeId: volID, + TargetPath: targetPath, + } + + _, err := c.nodeClient.NodeUnpublishVolume(ctx, req) + return err +} + +func asCSIAccessMode(am api.PersistentVolumeAccessMode) csipb.VolumeCapability_AccessMode_Mode { + switch am { + case api.ReadWriteOnce: + return csipb.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + case api.ReadOnlyMany: + return csipb.VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER + case api.ReadWriteMany: + return csipb.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER + } + return csipb.VolumeCapability_AccessMode_UNKNOWN +} + +func verToStr(ver *csipb.Version) string { + if ver == nil { + return "" + } + return fmt.Sprintf("%d.%d.%d", ver.GetMajor(), ver.GetMinor(), ver.GetPatch()) +} + +func versToStr(vers []*csipb.Version) string { + if vers == nil { + return "" + } + str := bytes.NewBufferString("[") + for _, v := range vers { + str.WriteString(fmt.Sprintf("{%s};", verToStr(v))) + } + str.WriteString("]") + return str.String() +} diff --git a/pkg/volume/csi/csi_client_test.go b/pkg/volume/csi/csi_client_test.go new file mode 100644 index 00000000000..54605cdb483 --- /dev/null +++ b/pkg/volume/csi/csi_client_test.go @@ -0,0 +1,126 @@ +/* +Copyright 2017 The 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 csi + +import ( + "errors" + "testing" + + csipb "github.com/container-storage-interface/spec/lib/go/csi" + grpctx "golang.org/x/net/context" + "google.golang.org/grpc" + api "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/volume/csi/fake" +) + +func setupClient(t *testing.T) *csiDriverClient { + client := newCsiDriverClient("unix", "/tmp/test.sock") + client.conn = new(grpc.ClientConn) //avoids creating conn object + + // setup mock grpc clients + client.idClient = fake.NewIdentityClient() + client.nodeClient = fake.NewNodeClient() + client.ctrlClient = fake.NewControllerClient() + + return client +} + +func TestClientAssertSupportedVersion(t *testing.T) { + testCases := []struct { + testName string + ver *csipb.Version + mustFail bool + err error + }{ + {testName: "supported version", ver: &csipb.Version{Major: 0, Minor: 1, Patch: 0}}, + {testName: "unsupported version", ver: &csipb.Version{Major: 0, Minor: 0, Patch: 0}, mustFail: true}, + {testName: "grpc error", ver: &csipb.Version{Major: 0, Minor: 1, Patch: 0}, mustFail: true, err: errors.New("grpc error")}, + } + + for _, tc := range testCases { + t.Log("case: ", tc.testName) + client := setupClient(t) + client.idClient.(*fake.IdentityClient).SetNextError(tc.err) + err := client.AssertSupportedVersion(grpctx.Background(), tc.ver) + if tc.mustFail && err == nil { + t.Error("must fail, but err = nil") + } + } +} + +func TestClientNodePublishVolume(t *testing.T) { + testCases := []struct { + name string + volID string + targetPath string + fsType string + mustFail bool + err error + }{ + {name: "test ok", volID: "vol-test", targetPath: "/test/path"}, + {name: "missing volID", targetPath: "/test/path", mustFail: true}, + {name: "missing target path", volID: "vol-test", mustFail: true}, + {name: "bad fs", volID: "vol-test", targetPath: "/test/path", fsType: "badfs", mustFail: true}, + {name: "grpc error", volID: "vol-test", targetPath: "/test/path", mustFail: true, err: errors.New("grpc error")}, + } + + client := setupClient(t) + + for _, tc := range testCases { + t.Log("case: ", tc.name) + client.nodeClient.(*fake.NodeClient).SetNextError(tc.err) + err := client.NodePublishVolume( + grpctx.Background(), + tc.volID, + false, + tc.targetPath, + api.ReadWriteOnce, + map[string]string{"device": "/dev/null"}, + tc.fsType, + ) + + if tc.mustFail && err == nil { + t.Error("must fail, but err is nil: ", err) + } + } +} + +func TestClientNodeUnpublishVolume(t *testing.T) { + testCases := []struct { + name string + volID string + targetPath string + mustFail bool + err error + }{ + {name: "test ok", volID: "vol-test", targetPath: "/test/path"}, + {name: "missing volID", targetPath: "/test/path", mustFail: true}, + {name: "missing target path", volID: "vol-test", mustFail: true}, + {name: "grpc error", volID: "vol-test", targetPath: "/test/path", mustFail: true, err: errors.New("grpc error")}, + } + + client := setupClient(t) + + for _, tc := range testCases { + t.Log("case: ", tc.name) + client.nodeClient.(*fake.NodeClient).SetNextError(tc.err) + err := client.NodeUnpublishVolume(grpctx.Background(), tc.volID, tc.targetPath) + if tc.mustFail && err == nil { + t.Error("must fail, but err is nil: ", err) + } + } +} diff --git a/pkg/volume/csi/csi_mounter.go b/pkg/volume/csi/csi_mounter.go new file mode 100644 index 00000000000..8645752ad24 --- /dev/null +++ b/pkg/volume/csi/csi_mounter.go @@ -0,0 +1,194 @@ +/* +Copyright 2017 The 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 csi + +import ( + "errors" + "fmt" + "path" + + "github.com/golang/glog" + grpctx "golang.org/x/net/context" + api "k8s.io/api/core/v1" + storage "k8s.io/api/storage/v1alpha1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + kstrings "k8s.io/kubernetes/pkg/util/strings" + "k8s.io/kubernetes/pkg/volume" +) + +type csiMountMgr struct { + k8s kubernetes.Interface + csiClient csiClient + plugin *csiPlugin + driverName string + volumeID string + readOnly bool + spec *volume.Spec + pod *api.Pod + podUID types.UID + options volume.VolumeOptions + volumeInfo map[string]string + volume.MetricsNil +} + +// volume.Volume methods +var _ volume.Volume = &csiMountMgr{} + +func (c *csiMountMgr) GetPath() string { + return getTargetPath(c.podUID, c.driverName, c.volumeID, c.plugin.host) +} + +func getTargetPath(uid types.UID, driverName string, volID string, host volume.VolumeHost) string { + // driverName validated at Mounter creation + // sanitize (replace / with ~) in volumeID before it's appended to path:w + driverPath := fmt.Sprintf("%s/%s", driverName, kstrings.EscapeQualifiedNameForDisk(volID)) + return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(csiPluginName), driverPath) +} + +// volume.Mounter methods +var _ volume.Mounter = &csiMountMgr{} + +func (c *csiMountMgr) CanMount() error { + //TODO (vladimirvivien) use this method to probe controller using CSI.NodeProbe() call + // to ensure Node service is ready in the CSI plugin + return nil +} + +func (c *csiMountMgr) SetUp(fsGroup *int64) error { + return c.SetUpAt(c.GetPath(), fsGroup) +} + +func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { + glog.V(4).Infof(log("Mounter.SetUpAt(%s)", dir)) + + ctx, cancel := grpctx.WithTimeout(grpctx.Background(), csiTimeout) + defer cancel() + + csi := c.csiClient + pvName := c.spec.PersistentVolume.GetName() + + // ensure version is supported + if err := csi.AssertSupportedVersion(ctx, csiVersion); err != nil { + glog.Errorf(log("failed to assert version: %v", err)) + return err + } + + // search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName + if c.volumeInfo == nil { + + //TODO (vladimirvivien) consider using VolumesAttachments().Get() to retrieve + //the object directly. This requires the ability to reconstruct the ID using volumeName+nodeName (nodename may not be avilable) + attachList, err := c.k8s.StorageV1alpha1().VolumeAttachments().List(meta.ListOptions{}) + if err != nil { + glog.Error(log("failed to get volume attachments: %v", err)) + return err + } + + var attachment *storage.VolumeAttachment + for _, attach := range attachList.Items { + if attach.Spec.Source.PersistentVolumeName != nil && + *attach.Spec.Source.PersistentVolumeName == pvName { + attachment = &attach + break + } + } + + if attachment == nil { + glog.Error(log("unable to find VolumeAttachment with PV.name = %s", pvName)) + return errors.New("no existing VolumeAttachment found") + } + c.volumeInfo = attachment.Status.AttachmentMetadata + } + + //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI + accessMode := api.ReadWriteOnce + if c.spec.PersistentVolume.Spec.AccessModes != nil { + accessMode = c.spec.PersistentVolume.Spec.AccessModes[0] + } + + err := csi.NodePublishVolume( + ctx, + c.volumeID, + c.readOnly, + dir, + accessMode, + c.volumeInfo, + "ext4", //TODO needs to be sourced from PV or somewhere else + ) + + if err != nil { + glog.Errorf(log("Mounter.Setup failed: %v", err)) + return err + } + glog.V(4).Infof(log("successfully mounted %s", dir)) + + return nil +} + +func (c *csiMountMgr) GetAttributes() volume.Attributes { + return volume.Attributes{ + ReadOnly: c.readOnly, + Managed: !c.readOnly, + SupportsSELinux: false, + } +} + +// volume.Unmounter methods +var _ volume.Unmounter = &csiMountMgr{} + +func (c *csiMountMgr) TearDown() error { + return c.TearDownAt(c.GetPath()) +} +func (c *csiMountMgr) TearDownAt(dir string) error { + glog.V(4).Infof(log("Unmounter.TearDown(%s)", dir)) + + // extract driverName and volID from path + base, volID := path.Split(dir) + volID = kstrings.UnescapeQualifiedNameForDisk(volID) + driverName := path.Base(base) + + if c.csiClient == nil { + addr := fmt.Sprintf(csiAddrTemplate, driverName) + client := newCsiDriverClient("unix", addr) + glog.V(4).Infof(log("unmounter csiClient setup [volume=%v,driver=%v]", volID, driverName)) + c.csiClient = client + } + + ctx, cancel := grpctx.WithTimeout(grpctx.Background(), csiTimeout) + defer cancel() + + csi := c.csiClient + + // TODO make all assertion calls private within the client itself + if err := csi.AssertSupportedVersion(ctx, csiVersion); err != nil { + glog.Errorf(log("failed to assert version: %v", err)) + return err + } + + err := csi.NodeUnpublishVolume(ctx, volID, dir) + + if err != nil { + glog.Errorf(log("Mounter.Setup failed: %v", err)) + return err + } + + glog.V(4).Infof(log("successfully unmounted %s", dir)) + + return nil +} diff --git a/pkg/volume/csi/csi_mounter_test.go b/pkg/volume/csi/csi_mounter_test.go new file mode 100644 index 00000000000..5e7f6083b60 --- /dev/null +++ b/pkg/volume/csi/csi_mounter_test.go @@ -0,0 +1,152 @@ +/* +Copyright 2017 The 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 csi + +import ( + "fmt" + "os" + "path" + "testing" + + api "k8s.io/api/core/v1" + storage "k8s.io/api/storage/v1alpha1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/volume" + "k8s.io/kubernetes/pkg/volume/csi/fake" +) + +var ( + testDriver = "test-driver" + testVol = "vol-123" + testns = "test-ns" + testPodUID = types.UID("test-pod") +) + +func TestMounterGetPath(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + + mounter, err := plug.NewMounter( + volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly), + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new Mounter: %v", err) + } + csiMounter := mounter.(*csiMountMgr) + expectedPath := path.Join(tmpDir, fmt.Sprintf( + "pods/%s/volumes/kubernetes.io~csi/%s/%s", + testPodUID, + csiMounter.driverName, + csiMounter.volumeID, + )) + mountPath := csiMounter.GetPath() + if mountPath != expectedPath { + t.Errorf("Got unexpected path: %s", mountPath) + } + +} + +func TestMounterSetUp(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + pvName := pv.GetName() + + mounter, err := plug.NewMounter( + volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly), + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new Mounter: %v", err) + } + + if mounter == nil { + t.Fatal("failed to create CSI mounter") + } + + csiMounter := mounter.(*csiMountMgr) + csiMounter.csiClient = setupClient(t) + + attachment := &storage.VolumeAttachment{ + ObjectMeta: meta.ObjectMeta{ + Name: "pv-1234556775313", + }, + Spec: storage.VolumeAttachmentSpec{ + NodeName: "test-node", + Attacher: csiPluginName, + Source: storage.VolumeAttachmentSource{ + PersistentVolumeName: &pvName, + }, + }, + Status: storage.VolumeAttachmentStatus{ + Attached: false, + AttachError: nil, + DetachError: nil, + }, + } + _, err = csiMounter.k8s.StorageV1alpha1().VolumeAttachments().Create(attachment) + if err != nil { + t.Fatalf("failed to setup VolumeAttachment: %v", err) + } + + // Mounter.SetUp() + if err := csiMounter.SetUp(nil); err != nil { + t.Fatalf("mounter.Setup failed: %v", err) + } + + // ensure call went all the way + pubs := csiMounter.csiClient.(*csiDriverClient).nodeClient.(*fake.NodeClient).GetNodePublishedVolumes() + if pubs[csiMounter.volumeID] != csiMounter.GetPath() { + t.Error("csi server may not have received NodePublishVolume call") + } +} + +func TestUnmounterTeardown(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + + unmounter, err := plug.NewUnmounter(pv.ObjectMeta.Name, testPodUID) + if err != nil { + t.Fatalf("failed to make a new Unmounter: %v", err) + } + + csiUnmounter := unmounter.(*csiMountMgr) + csiUnmounter.csiClient = setupClient(t) + + dir := csiUnmounter.GetPath() + + err = csiUnmounter.TearDownAt(dir) + if err != nil { + t.Fatal(err) + } + + // ensure csi client call + pubs := csiUnmounter.csiClient.(*csiDriverClient).nodeClient.(*fake.NodeClient).GetNodePublishedVolumes() + if _, ok := pubs[csiUnmounter.volumeID]; ok { + t.Error("csi server may not have received NodeUnpublishVolume call") + } + +} diff --git a/pkg/volume/csi/csi_plugin.go b/pkg/volume/csi/csi_plugin.go new file mode 100644 index 00000000000..876de2281bc --- /dev/null +++ b/pkg/volume/csi/csi_plugin.go @@ -0,0 +1,257 @@ +/* +Copyright 2017 The 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 csi + +import ( + "errors" + "fmt" + "path" + "regexp" + "time" + + csipb "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/golang/glog" + api "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/util/mount" + kstrings "k8s.io/kubernetes/pkg/util/strings" + "k8s.io/kubernetes/pkg/volume" +) + +const ( + csiName = "csi" + csiPluginName = "kubernetes.io/csi" + + // TODO (vladimirvivien) implement a more dynamic way to discover + // the unix domain socket path for each installed csi driver. + // TODO (vladimirvivien) would be nice to name socket with a .sock extension + // for consistency. + csiAddrTemplate = "/var/lib/kubelet/plugins/%v" + csiTimeout = 15 * time.Second + volNameSep = "^" +) + +var ( + // csiVersion supported csi version + csiVersion = &csipb.Version{Major: 0, Minor: 1, Patch: 0} + driverNameRexp = regexp.MustCompile(`^[A-Za-z]+(\.?-?_?[A-Za-z0-9-])+$`) +) + +type csiPlugin struct { + host volume.VolumeHost +} + +// ProbeVolumePlugins returns implemented plugins +func ProbeVolumePlugins() []volume.VolumePlugin { + p := &csiPlugin{ + host: nil, + } + return []volume.VolumePlugin{p} +} + +// volume.VolumePlugin methods +var _ volume.VolumePlugin = &csiPlugin{} + +func (p *csiPlugin) Init(host volume.VolumeHost) error { + glog.Info(log("plugin initializing...")) + p.host = host + return nil +} + +func (p *csiPlugin) GetPluginName() string { + return csiPluginName +} + +// GetvolumeName returns a concatenated string of CSIVolumeSource.DriverCSIVolumeSource.VolumeHandle +// That string value is used in Detach() to extract driver name and volumeName. +func (p *csiPlugin) GetVolumeName(spec *volume.Spec) (string, error) { + csi, err := getCSISourceFromSpec(spec) + if err != nil { + glog.Error(log("plugin.GetVolumeName failed to extract volume source from spec: %v", err)) + return "", err + } + + //TODO (vladimirvivien) this validation should be done at the API validation check + if !isDriverNameValid(csi.Driver) { + glog.Error(log("plugin.GetVolumeName failed to create volume name: invalid csi driver name %s", csi.Driver)) + return "", errors.New("invalid csi driver name") + } + + // return driverNamevolumeHandle + return fmt.Sprintf("%s%s%s", csi.Driver, volNameSep, csi.VolumeHandle), nil +} + +func (p *csiPlugin) CanSupport(spec *volume.Spec) bool { + // TODO (vladimirvivien) CanSupport should also take into account + // the availability/registration of specified Driver in the volume source + return spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CSI != nil +} + +func (p *csiPlugin) RequiresRemount() bool { + return false +} + +func (p *csiPlugin) NewMounter( + spec *volume.Spec, + pod *api.Pod, + _ volume.VolumeOptions) (volume.Mounter, error) { + pvSource, err := getCSISourceFromSpec(spec) + if err != nil { + return nil, err + } + + // TODO (vladimirvivien) consider moving this check in API validation + // check Driver name to conform to CSI spec + if !isDriverNameValid(pvSource.Driver) { + glog.Error(log("driver name does not conform to CSI spec: %s", pvSource.Driver)) + return nil, errors.New("driver name is invalid") + } + + // before it is used in any paths such as socket etc + addr := fmt.Sprintf(csiAddrTemplate, pvSource.Driver) + glog.V(4).Infof(log("setting up mounter for [volume=%v,driver=%v]", pvSource.VolumeHandle, pvSource.Driver)) + client := newCsiDriverClient("unix", addr) + + k8s := p.host.GetKubeClient() + if k8s == nil { + glog.Error(log("failed to get a kubernetes client")) + return nil, errors.New("failed to get a Kubernetes client") + } + + mounter := &csiMountMgr{ + plugin: p, + k8s: k8s, + spec: spec, + pod: pod, + podUID: pod.UID, + driverName: pvSource.Driver, + volumeID: pvSource.VolumeHandle, + csiClient: client, + } + return mounter, nil +} + +func (p *csiPlugin) NewUnmounter(specName string, podUID types.UID) (volume.Unmounter, error) { + glog.V(4).Infof(log("setting up unmounter for [name=%v, podUID=%v]", specName, podUID)) + unmounter := &csiMountMgr{ + plugin: p, + podUID: podUID, + } + return unmounter, nil +} + +func (p *csiPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) { + glog.V(4).Infof(log("constructing volume spec [pv.Name=%v, path=%v]", volumeName, mountPath)) + + // extract driverName/volumeId from end of mountPath + dir, volID := path.Split(mountPath) + volID = kstrings.UnescapeQualifiedNameForDisk(volID) + driverName := path.Base(dir) + + // TODO (vladimirvivien) consider moving this check in API validation + if !isDriverNameValid(driverName) { + glog.Error(log("failed while reconstructing volume spec csi: driver name extracted from path is invalid: [path=%s; driverName=%s]", mountPath, driverName)) + return nil, errors.New("invalid csi driver name from path") + } + + glog.V(4).Info(log("plugin.ConstructVolumeSpec extracted [volumeID=%s; driverName=%s]", volID, driverName)) + + pv := &api.PersistentVolume{ + ObjectMeta: meta.ObjectMeta{ + Name: volumeName, + }, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + CSI: &api.CSIPersistentVolumeSource{ + Driver: driverName, + VolumeHandle: volID, + }, + }, + }, + } + + return volume.NewSpecFromPersistentVolume(pv, false), nil +} + +func (p *csiPlugin) SupportsMountOption() bool { + // TODO (vladimirvivien) use CSI VolumeCapability.MountVolume.mount_flags + // to probe for the result for this method:w + return false +} + +func (p *csiPlugin) SupportsBulkVolumeVerification() bool { + return false +} + +// volume.AttachableVolumePlugin methods +var _ volume.AttachableVolumePlugin = &csiPlugin{} + +func (p *csiPlugin) NewAttacher() (volume.Attacher, error) { + k8s := p.host.GetKubeClient() + if k8s == nil { + glog.Error(log("unable to get kubernetes client from host")) + return nil, errors.New("unable to get Kubernetes client") + } + + return &csiAttacher{ + plugin: p, + k8s: k8s, + waitSleepTime: 1 * time.Second, + }, nil +} + +func (p *csiPlugin) NewDetacher() (volume.Detacher, error) { + k8s := p.host.GetKubeClient() + if k8s == nil { + glog.Error(log("unable to get kubernetes client from host")) + return nil, errors.New("unable to get Kubernetes client") + } + + return &csiAttacher{ + plugin: p, + k8s: k8s, + waitSleepTime: 1 * time.Second, + }, nil +} + +func (p *csiPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) { + m := p.host.GetMounter(p.GetPluginName()) + return mount.GetMountRefs(m, deviceMountPath) +} + +func getCSISourceFromSpec(spec *volume.Spec) (*api.CSIPersistentVolumeSource, error) { + if spec.PersistentVolume != nil && + spec.PersistentVolume.Spec.CSI != nil { + return spec.PersistentVolume.Spec.CSI, nil + } + + return nil, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") +} + +// log prepends log string with `kubernetes.io/csi` +func log(msg string, parts ...interface{}) string { + return fmt.Sprintf(fmt.Sprintf("%s: %s", csiPluginName, msg), parts...) +} + +// isDriverNameValid validates the driverName using CSI spec +func isDriverNameValid(name string) bool { + if len(name) == 0 || len(name) > 63 { + return false + } + return driverNameRexp.MatchString(name) +} diff --git a/pkg/volume/csi/csi_plugin_test.go b/pkg/volume/csi/csi_plugin_test.go new file mode 100644 index 00000000000..020430bb313 --- /dev/null +++ b/pkg/volume/csi/csi_plugin_test.go @@ -0,0 +1,297 @@ +/* +Copyright 2017 The 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 csi + +import ( + "fmt" + "os" + "testing" + + api "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + fakeclient "k8s.io/client-go/kubernetes/fake" + utiltesting "k8s.io/client-go/util/testing" + kstrings "k8s.io/kubernetes/pkg/util/strings" + "k8s.io/kubernetes/pkg/volume" + volumetest "k8s.io/kubernetes/pkg/volume/testing" +) + +// create a plugin mgr to load plugins and setup a fake client +func newTestPlugin(t *testing.T) (*csiPlugin, string) { + tmpDir, err := utiltesting.MkTmpdir("csi-test") + if err != nil { + t.Fatalf("can't create temp dir: %v", err) + } + + fakeClient := fakeclient.NewSimpleClientset() + host := volumetest.NewFakeVolumeHost( + tmpDir, + fakeClient, + nil, + ) + plugMgr := &volume.VolumePluginMgr{} + plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) + + plug, err := plugMgr.FindPluginByName(csiPluginName) + if err != nil { + t.Fatalf("can't find plugin %v", csiPluginName) + } + + csiPlug, ok := plug.(*csiPlugin) + if !ok { + t.Fatalf("cannot assert plugin to be type csiPlugin") + } + + return csiPlug, tmpDir +} + +func makeTestPV(name string, sizeGig int, driverName, volID string) *api.PersistentVolume { + return &api.PersistentVolume{ + ObjectMeta: meta.ObjectMeta{ + Name: name, + Namespace: testns, + }, + Spec: api.PersistentVolumeSpec{ + AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, + Capacity: api.ResourceList{ + api.ResourceName(api.ResourceStorage): resource.MustParse( + fmt.Sprintf("%dGi", sizeGig), + ), + }, + PersistentVolumeSource: api.PersistentVolumeSource{ + CSI: &api.CSIPersistentVolumeSource{ + Driver: driverName, + VolumeHandle: volID, + ReadOnly: false, + }, + }, + }, + } +} + +func TestPluginGetPluginName(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + if plug.GetPluginName() != "kubernetes.io/csi" { + t.Errorf("unexpected plugin name %v", plug.GetPluginName()) + } +} + +func TestPluginGetVolumeName(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + testCases := []struct { + name string + driverName string + volName string + shouldFail bool + }{ + {"alphanum names", "testdr", "testvol", false}, + {"mixchar driver", "test.dr.cc", "testvol", false}, + {"mixchar volume", "testdr", "test-vol-name", false}, + {"mixchars all", "test-driver", "test.vol.name", false}, + } + + for _, tc := range testCases { + t.Logf("testing: %s", tc.name) + pv := makeTestPV("test-pv", 10, tc.driverName, tc.volName) + spec := volume.NewSpecFromPersistentVolume(pv, false) + name, err := plug.GetVolumeName(spec) + if tc.shouldFail && err == nil { + t.Fatal("GetVolumeName should fail, but got err=nil") + } + if name != fmt.Sprintf("%s%s%s", tc.driverName, volNameSep, tc.volName) { + t.Errorf("unexpected volume name %s", name) + } + } +} + +func TestPluginCanSupport(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + spec := volume.NewSpecFromPersistentVolume(pv, false) + + if !plug.CanSupport(spec) { + t.Errorf("should support CSI spec") + } +} + +func TestPluginConstructVolumeSpec(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + testCases := []struct { + name string + driverName string + volID string + shouldFail bool + }{ + {"valid driver and vol", "test.csi-driver", "abc-cde", false}, + {"valid driver + vol with slash", "test.csi-driver", "a/b/c/d", false}, + {"invalid driver name", "_test.csi.driver>", "a/b/c/d", true}, + } + + for _, tc := range testCases { + dir := getTargetPath(testPodUID, tc.driverName, tc.volID, plug.host) + + // rebuild spec + spec, err := plug.ConstructVolumeSpec("test-pv", dir) + if tc.shouldFail { + if err == nil { + t.Fatal("expecting ConstructVolumeSpec to fail, but got nil error") + } + continue + } + + volID := spec.PersistentVolume.Spec.CSI.VolumeHandle + unsanitizedVolID := kstrings.UnescapeQualifiedNameForDisk(tc.volID) + if volID != unsanitizedVolID { + t.Errorf("expected unsanitized volID %s, got volID %s", unsanitizedVolID, volID) + } + + if spec.Name() != "test-pv" { + t.Errorf("Unexpected spec name %s", spec.Name()) + } + } +} + +func TestPluginNewMounter(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + mounter, err := plug.NewMounter( + volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly), + &api.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}}, + volume.VolumeOptions{}, + ) + if err != nil { + t.Fatalf("Failed to make a new Mounter: %v", err) + } + + if mounter == nil { + t.Fatal("failed to create CSI mounter") + } + csiMounter := mounter.(*csiMountMgr) + + // validate mounter fields + if csiMounter.driverName != testDriver { + t.Error("mounter driver name not set") + } + if csiMounter.volumeID != testVol { + t.Error("mounter volume id not set") + } + if csiMounter.pod == nil { + t.Error("mounter pod not set") + } + if csiMounter.podUID == types.UID("") { + t.Error("mounter podUID mot set") + } +} + +func TestPluginNewUnmounter(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + pv := makeTestPV("test-pv", 10, testDriver, testVol) + + unmounter, err := plug.NewUnmounter(pv.ObjectMeta.Name, testPodUID) + csiUnmounter := unmounter.(*csiMountMgr) + + if err != nil { + t.Fatalf("Failed to make a new Mounter: %v", err) + } + + if csiUnmounter == nil { + t.Fatal("failed to create CSI mounter") + } + + if csiUnmounter.podUID != testPodUID { + t.Error("podUID not set") + } + +} + +func TestValidateDriverName(t *testing.T) { + testCases := []struct { + name string + driverName string + valid bool + }{ + + {"ok no punctuations", "comgooglestoragecsigcepd", true}, + {"ok dot only", "io.kubernetes.storage.csi.flex", true}, + {"ok dash only", "io-kubernetes-storage-csi-flex", true}, + {"ok underscore only", "io_kubernetes_storage_csi_flex", true}, + {"ok dot underscores", "io.kubernetes.storage_csi.flex", true}, + {"ok dot dash underscores", "io.kubernetes-storage.csi_flex", true}, + + {"invalid length 0", "", false}, + {"invalid length > 63", "comgooglestoragecsigcepdcomgooglestoragecsigcepdcomgooglestoragecsigcepdcomgooglestoragecsigcepd", false}, + {"invalid start char", "_comgooglestoragecsigcepd", false}, + {"invalid end char", "comgooglestoragecsigcepd/", false}, + {"invalid separators", "com/google/storage/csi~gcepd", false}, + } + + for _, tc := range testCases { + t.Logf("test case: %v", tc.name) + drValid := isDriverNameValid(tc.driverName) + if tc.valid != drValid { + t.Errorf("expecting driverName %s as valid=%t, but got valid=%t", tc.driverName, tc.valid, drValid) + } + } +} + +func TestPluginNewAttacher(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + attacher, err := plug.NewAttacher() + if err != nil { + t.Fatalf("failed to create new attacher: %v", err) + } + + csiAttacher := attacher.(*csiAttacher) + if csiAttacher.plugin == nil { + t.Error("plugin not set for attacher") + } + if csiAttacher.k8s == nil { + t.Error("Kubernetes client not set for attacher") + } +} + +func TestPluginNewDetacher(t *testing.T) { + plug, tmpDir := newTestPlugin(t) + defer os.RemoveAll(tmpDir) + + detacher, err := plug.NewDetacher() + if err != nil { + t.Fatalf("failed to create new detacher: %v", err) + } + + csiDetacher := detacher.(*csiAttacher) + if csiDetacher.plugin == nil { + t.Error("plugin not set for detacher") + } + if csiDetacher.k8s == nil { + t.Error("Kubernetes client not set for attacher") + } +} diff --git a/pkg/volume/csi/fake/fake_client.go b/pkg/volume/csi/fake/fake_client.go new file mode 100644 index 00000000000..0d790cc9e58 --- /dev/null +++ b/pkg/volume/csi/fake/fake_client.go @@ -0,0 +1,224 @@ +/* +Copyright 2017 The 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 fake + +import ( + "context" + "errors" + "strings" + + "google.golang.org/grpc" + + csipb "github.com/container-storage-interface/spec/lib/go/csi" + grpctx "golang.org/x/net/context" +) + +// IdentityClient is a CSI identity client used for testing +type IdentityClient struct { + nextErr error +} + +// NewIdentityClient returns a new IdentityClient +func NewIdentityClient() *IdentityClient { + return &IdentityClient{} +} + +// SetNextError injects expected error +func (f *IdentityClient) SetNextError(err error) { + f.nextErr = err +} + +// GetSupportedVersions returns supported version +func (f *IdentityClient) GetSupportedVersions(ctx grpctx.Context, req *csipb.GetSupportedVersionsRequest, opts ...grpc.CallOption) (*csipb.GetSupportedVersionsResponse, error) { + // short circuit with an error + if f.nextErr != nil { + return nil, f.nextErr + } + + rsp := &csipb.GetSupportedVersionsResponse{ + SupportedVersions: []*csipb.Version{ + {Major: 0, Minor: 0, Patch: 1}, + {Major: 0, Minor: 1, Patch: 0}, + {Major: 1, Minor: 0, Patch: 0}, + {Major: 1, Minor: 0, Patch: 1}, + {Major: 1, Minor: 1, Patch: 1}, + }, + } + return rsp, nil +} + +// GetPluginInfo returns plugin info +func (f *IdentityClient) GetPluginInfo(ctx context.Context, in *csipb.GetPluginInfoRequest, opts ...grpc.CallOption) (*csipb.GetPluginInfoResponse, error) { + return nil, nil +} + +// NodeClient returns CSI node client +type NodeClient struct { + nodePublishedVolumes map[string]string + nextErr error +} + +// NewNodeClient returns fake node client +func NewNodeClient() *NodeClient { + return &NodeClient{nodePublishedVolumes: make(map[string]string)} +} + +// SetNextError injects next expected error +func (f *NodeClient) SetNextError(err error) { + f.nextErr = err +} + +// GetNodePublishedVolumes returns node published volumes +func (f *NodeClient) GetNodePublishedVolumes() map[string]string { + return f.nodePublishedVolumes +} + +// NodePublishVolume implements CSI NodePublishVolume +func (f *NodeClient) NodePublishVolume(ctx grpctx.Context, req *csipb.NodePublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodePublishVolumeResponse, error) { + + if f.nextErr != nil { + return nil, f.nextErr + } + + if req.GetVolumeId() == "" { + return nil, errors.New("missing volume id") + } + if req.GetTargetPath() == "" { + return nil, errors.New("missing target path") + } + fsTypes := "ext4|xfs|zfs" + fsType := req.GetVolumeCapability().GetMount().GetFsType() + if !strings.Contains(fsTypes, fsType) { + return nil, errors.New("invlid fstype") + } + f.nodePublishedVolumes[req.GetVolumeId()] = req.GetTargetPath() + return &csipb.NodePublishVolumeResponse{}, nil +} + +// NodeUnpublishVolume implements csi method +func (f *NodeClient) NodeUnpublishVolume(ctx context.Context, req *csipb.NodeUnpublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeUnpublishVolumeResponse, error) { + if f.nextErr != nil { + return nil, f.nextErr + } + + if req.GetVolumeId() == "" { + return nil, errors.New("missing volume id") + } + if req.GetTargetPath() == "" { + return nil, errors.New("missing target path") + } + delete(f.nodePublishedVolumes, req.GetVolumeId()) + return &csipb.NodeUnpublishVolumeResponse{}, nil +} + +// GetNodeID implements method +func (f *NodeClient) GetNodeID(ctx context.Context, in *csipb.GetNodeIDRequest, opts ...grpc.CallOption) (*csipb.GetNodeIDResponse, error) { + return nil, nil +} + +// NodeProbe implements csi method +func (f *NodeClient) NodeProbe(ctx context.Context, in *csipb.NodeProbeRequest, opts ...grpc.CallOption) (*csipb.NodeProbeResponse, error) { + return nil, nil +} + +// NodeGetCapabilities implements csi method +func (f *NodeClient) NodeGetCapabilities(ctx context.Context, in *csipb.NodeGetCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.NodeGetCapabilitiesResponse, error) { + return nil, nil +} + +// ControllerClient represents a CSI Controller client +type ControllerClient struct { + nextCapabilities []*csipb.ControllerServiceCapability + nextErr error +} + +// NewControllerClient returns a ControllerClient +func NewControllerClient() *ControllerClient { + return &ControllerClient{} +} + +// SetNextError injects next expected error +func (f *ControllerClient) SetNextError(err error) { + f.nextErr = err +} + +// SetNextCapabilities injects next expected capabilities +func (f *ControllerClient) SetNextCapabilities(caps []*csipb.ControllerServiceCapability) { + f.nextCapabilities = caps +} + +// ControllerGetCapabilities implements csi method +func (f *ControllerClient) ControllerGetCapabilities(ctx context.Context, in *csipb.ControllerGetCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.ControllerGetCapabilitiesResponse, error) { + if f.nextErr != nil { + return nil, f.nextErr + } + + if f.nextCapabilities == nil { + f.nextCapabilities = []*csipb.ControllerServiceCapability{ + { + Type: &csipb.ControllerServiceCapability_Rpc{ + Rpc: &csipb.ControllerServiceCapability_RPC{ + Type: csipb.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME, + }, + }, + }, + } + } + return &csipb.ControllerGetCapabilitiesResponse{ + Capabilities: f.nextCapabilities, + }, nil +} + +// CreateVolume implements csi method +func (f *ControllerClient) CreateVolume(ctx context.Context, in *csipb.CreateVolumeRequest, opts ...grpc.CallOption) (*csipb.CreateVolumeResponse, error) { + return nil, nil +} + +// DeleteVolume implements csi method +func (f *ControllerClient) DeleteVolume(ctx context.Context, in *csipb.DeleteVolumeRequest, opts ...grpc.CallOption) (*csipb.DeleteVolumeResponse, error) { + return nil, nil +} + +// ControllerPublishVolume implements csi method +func (f *ControllerClient) ControllerPublishVolume(ctx context.Context, in *csipb.ControllerPublishVolumeRequest, opts ...grpc.CallOption) (*csipb.ControllerPublishVolumeResponse, error) { + return nil, nil +} + +// ControllerUnpublishVolume implements csi method +func (f *ControllerClient) ControllerUnpublishVolume(ctx context.Context, in *csipb.ControllerUnpublishVolumeRequest, opts ...grpc.CallOption) (*csipb.ControllerUnpublishVolumeResponse, error) { + return nil, nil +} + +// ValidateVolumeCapabilities implements csi method +func (f *ControllerClient) ValidateVolumeCapabilities(ctx context.Context, in *csipb.ValidateVolumeCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.ValidateVolumeCapabilitiesResponse, error) { + return nil, nil +} + +// ListVolumes implements csi method +func (f *ControllerClient) ListVolumes(ctx context.Context, in *csipb.ListVolumesRequest, opts ...grpc.CallOption) (*csipb.ListVolumesResponse, error) { + return nil, nil +} + +// GetCapacity implements csi method +func (f *ControllerClient) GetCapacity(ctx context.Context, in *csipb.GetCapacityRequest, opts ...grpc.CallOption) (*csipb.GetCapacityResponse, error) { + return nil, nil +} + +// ControllerProbe implements csi method +func (f *ControllerClient) ControllerProbe(ctx context.Context, in *csipb.ControllerProbeRequest, opts ...grpc.CallOption) (*csipb.ControllerProbeResponse, error) { + return nil, nil +} From c90a68c133183ad9235642d56c812e767629af02 Mon Sep 17 00:00:00 2001 From: Vladimir Vivien Date: Tue, 24 Oct 2017 22:48:13 -0400 Subject: [PATCH 2/3] CSI - Generated source code This commit tracks all auto-generated sources. --- cmd/kube-controller-manager/app/BUILD | 1 + cmd/kubelet/app/BUILD | 1 + pkg/volume/csi/fake/BUILD | 27 +++++++++++++++++++++++++++ pkg/volume/csi/proto/csi/BUILD | 27 +++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 pkg/volume/csi/fake/BUILD create mode 100644 pkg/volume/csi/proto/csi/BUILD diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index 42436a545db..013a8b724c7 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -90,6 +90,7 @@ go_library( "//pkg/volume/azure_dd:go_default_library", "//pkg/volume/azure_file:go_default_library", "//pkg/volume/cinder:go_default_library", + "//pkg/volume/csi:go_default_library", "//pkg/volume/fc:go_default_library", "//pkg/volume/flexvolume:go_default_library", "//pkg/volume/flocker:go_default_library", diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index 7848b0b7a09..c7e482f49ea 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -77,6 +77,7 @@ go_library( "//pkg/volume/cephfs:go_default_library", "//pkg/volume/cinder:go_default_library", "//pkg/volume/configmap:go_default_library", + "//pkg/volume/csi:go_default_library", "//pkg/volume/downwardapi:go_default_library", "//pkg/volume/empty_dir:go_default_library", "//pkg/volume/fc:go_default_library", diff --git a/pkg/volume/csi/fake/BUILD b/pkg/volume/csi/fake/BUILD new file mode 100644 index 00000000000..b4935c1239a --- /dev/null +++ b/pkg/volume/csi/fake/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["fake_client.go"], + importpath = "k8s.io/kubernetes/pkg/volume/csi/fake", + visibility = ["//visibility:public"], + deps = [ + "//pkg/volume/csi/proto/csi:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/volume/csi/proto/csi/BUILD b/pkg/volume/csi/proto/csi/BUILD new file mode 100644 index 00000000000..87cbaa30e8b --- /dev/null +++ b/pkg/volume/csi/proto/csi/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["csi.pb.go"], + importpath = "k8s.io/kubernetes/pkg/volume/csi/proto/csi", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/golang/protobuf/proto:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) From e489629895ffa82eb7cd8281f0a2b7e788a29812 Mon Sep 17 00:00:00 2001 From: Vladimir Vivien Date: Sat, 18 Nov 2017 12:57:23 -0500 Subject: [PATCH 3/3] CSI - GoDeps dependency updates --- Godeps/Godeps.json | 149 +- Godeps/LICENSES | 209 ++ pkg/volume/csi/BUILD | 45 +- pkg/volume/csi/fake/BUILD | 2 +- vendor/BUILD | 1 + .../container-storage-interface/spec/LICENSE | 201 ++ .../spec/lib/go}/csi/BUILD | 2 +- .../spec/lib/go/csi/csi.pb.go | 2525 +++++++++++++++++ 8 files changed, 3059 insertions(+), 75 deletions(-) create mode 100644 vendor/github.com/container-storage-interface/spec/LICENSE rename {pkg/volume/csi/proto => vendor/github.com/container-storage-interface/spec/lib/go}/csi/BUILD (89%) create mode 100644 vendor/github.com/container-storage-interface/spec/lib/go/csi/csi.pb.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index fef5d7e1dc4..40f7bd094a1 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -436,6 +436,10 @@ "Comment": "v0.1.0-62-g8d75e11", "Rev": "8d75e11374a1928608c906fe745b538483e7aeb2" }, + { + "ImportPath": "github.com/container-storage-interface/spec/lib/go/csi", + "Rev": "ec298903f94e1d6d954de121b28044a2e1fdbf48" + }, { "ImportPath": "github.com/containernetworking/cni/libcni", "Comment": "v0.6.0", @@ -854,152 +858,152 @@ }, { "ImportPath": "github.com/docker/distribution/digestset", - "Comment": "v2.6.0-rc.1-209-gedc3ab29", + "Comment": "v2.6.0-rc.1-209-gedc3ab2", "Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c" }, { "ImportPath": "github.com/docker/distribution/reference", - "Comment": "v2.6.0-rc.1-209-gedc3ab29", + "Comment": "v2.6.0-rc.1-209-gedc3ab2", "Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c" }, { "ImportPath": "github.com/docker/docker/api", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/blkiodev", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/container", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/events", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/filters", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/image", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/mount", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/network", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/registry", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/strslice", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/swarm", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/swarm/runtime", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/time", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/versions", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/api/types/volume", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/client", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/ioutils", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/jsonlog", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/jsonmessage", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/longpath", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/mount", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/stdcopy", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/symlink", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/system", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/term", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/term/windows", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { "ImportPath": "github.com/docker/docker/pkg/tlsconfig", - "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", + "Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616f", "Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" }, { @@ -1024,7 +1028,7 @@ }, { "ImportPath": "github.com/docker/libnetwork/ipvs", - "Comment": "v0.8.0-dev.2-910-gba46b928", + "Comment": "v0.8.0-dev.2-910-gba46b92", "Rev": "ba46b928444931e6865d8618dc03622cac79aa6f" }, { @@ -1151,127 +1155,127 @@ }, { "ImportPath": "github.com/gogo/protobuf/gogoproto", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/compare", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/defaultcheck", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/description", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/embedcheck", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/enumstringer", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/equal", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/face", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/gostring", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/marshalto", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/oneofcheck", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/populate", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/size", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/stringer", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/testgen", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/union", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/plugin/unmarshal", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/proto", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/descriptor", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/generator", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/grpc", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/plugin", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/sortkeys", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/vanity", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { "ImportPath": "github.com/gogo/protobuf/vanity/command", - "Comment": "v0.4-3-gc0656edd", + "Comment": "v0.4-3-gc0656ed", "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" }, { @@ -1783,6 +1787,7 @@ }, { "ImportPath": "github.com/inconshreveable/mousetrap", + "Comment": "v1.0", "Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" }, { @@ -2167,77 +2172,77 @@ }, { "ImportPath": "github.com/opencontainers/runc/libcontainer", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/apparmor", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/rootless", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/systemd", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/configs", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/configs/validate", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/criurpc", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/keys", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/seccomp", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/stacktrace", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/system", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/user", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/utils", - "Comment": "v1.0.0-rc4-50-g4d6e6720", + "Comment": "v1.0.0-rc4-50-g4d6e672", "Rev": "4d6e6720a7c885c37b4cb083c0d372dda3425120" }, { @@ -2261,6 +2266,7 @@ }, { "ImportPath": "github.com/pelletier/go-buffruneio", + "Comment": "v0.1.0", "Rev": "df1e16fde7fc330a0ca68167c23bf7ed6ac31d6d" }, { @@ -2579,6 +2585,7 @@ }, { "ImportPath": "github.com/xiang90/probing", + "Comment": "0.0.1", "Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2" }, { diff --git a/Godeps/LICENSES b/Godeps/LICENSES index 3ceafc27582..9439e2d999d 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -12333,6 +12333,215 @@ SOFTWARE. ================================================================================ +================================================================================ += vendor/github.com/container-storage-interface/spec/lib/go/csi licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + += vendor/github.com/container-storage-interface/spec/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + ================================================================================ = vendor/github.com/containernetworking/cni/libcni licensed under: = diff --git a/pkg/volume/csi/BUILD b/pkg/volume/csi/BUILD index e6383b51dfe..8f829cfaa93 100644 --- a/pkg/volume/csi/BUILD +++ b/pkg/volume/csi/BUILD @@ -1,9 +1,10 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ "csi_attacher.go", + "csi_client.go", "csi_mounter.go", "csi_plugin.go", ], @@ -13,8 +14,45 @@ go_library( "//pkg/util/mount:go_default_library", "//pkg/util/strings:go_default_library", "//pkg/volume:go_default_library", + "//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "csi_attacher_test.go", + "csi_client_test.go", + "csi_mounter_test.go", + "csi_plugin_test.go", + ], + importpath = "k8s.io/kubernetes/pkg/volume/csi", + library = ":go_default_library", + deps = [ + "//pkg/util/strings:go_default_library", + "//pkg/volume:go_default_library", + "//pkg/volume/csi/fake:go_default_library", + "//pkg/volume/testing:go_default_library", + "//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/google.golang.org/grpc:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/storage/v1alpha1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/util/testing:go_default_library", ], ) @@ -27,7 +65,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/volume/csi/fake:all-srcs", + ], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/pkg/volume/csi/fake/BUILD b/pkg/volume/csi/fake/BUILD index b4935c1239a..49a9c80ccc0 100644 --- a/pkg/volume/csi/fake/BUILD +++ b/pkg/volume/csi/fake/BUILD @@ -6,7 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/volume/csi/fake", visibility = ["//visibility:public"], deps = [ - "//pkg/volume/csi/proto/csi:go_default_library", + "//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", "//vendor/google.golang.org/grpc:go_default_library", ], diff --git a/vendor/BUILD b/vendor/BUILD index 5f62de0637b..53bc93a3cce 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -61,6 +61,7 @@ filegroup( "//vendor/github.com/clusterhq/flocker-go:all-srcs", "//vendor/github.com/codedellemc/goscaleio:all-srcs", "//vendor/github.com/codegangsta/negroni:all-srcs", + "//vendor/github.com/container-storage-interface/spec/lib/go/csi:all-srcs", "//vendor/github.com/containernetworking/cni/libcni:all-srcs", "//vendor/github.com/containernetworking/cni/pkg/invoke:all-srcs", "//vendor/github.com/containernetworking/cni/pkg/types:all-srcs", diff --git a/vendor/github.com/container-storage-interface/spec/LICENSE b/vendor/github.com/container-storage-interface/spec/LICENSE new file mode 100644 index 00000000000..8dada3edaf5 --- /dev/null +++ b/vendor/github.com/container-storage-interface/spec/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/pkg/volume/csi/proto/csi/BUILD b/vendor/github.com/container-storage-interface/spec/lib/go/csi/BUILD similarity index 89% rename from pkg/volume/csi/proto/csi/BUILD rename to vendor/github.com/container-storage-interface/spec/lib/go/csi/BUILD index 87cbaa30e8b..c9708f927b9 100644 --- a/pkg/volume/csi/proto/csi/BUILD +++ b/vendor/github.com/container-storage-interface/spec/lib/go/csi/BUILD @@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["csi.pb.go"], - importpath = "k8s.io/kubernetes/pkg/volume/csi/proto/csi", + importpath = "github.com/container-storage-interface/spec/lib/go/csi", visibility = ["//visibility:public"], deps = [ "//vendor/github.com/golang/protobuf/proto:go_default_library", diff --git a/vendor/github.com/container-storage-interface/spec/lib/go/csi/csi.pb.go b/vendor/github.com/container-storage-interface/spec/lib/go/csi/csi.pb.go new file mode 100644 index 00000000000..6158a4870cc --- /dev/null +++ b/vendor/github.com/container-storage-interface/spec/lib/go/csi/csi.pb.go @@ -0,0 +1,2525 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: csi.proto + +/* +Package csi is a generated protocol buffer package. + +It is generated from these files: + csi.proto + +It has these top-level messages: + GetSupportedVersionsRequest + GetSupportedVersionsResponse + Version + GetPluginInfoRequest + GetPluginInfoResponse + CreateVolumeRequest + CreateVolumeResponse + VolumeCapability + CapacityRange + VolumeInfo + DeleteVolumeRequest + DeleteVolumeResponse + ControllerPublishVolumeRequest + ControllerPublishVolumeResponse + ControllerUnpublishVolumeRequest + ControllerUnpublishVolumeResponse + ValidateVolumeCapabilitiesRequest + ValidateVolumeCapabilitiesResponse + ListVolumesRequest + ListVolumesResponse + GetCapacityRequest + GetCapacityResponse + ControllerProbeRequest + ControllerProbeResponse + ControllerGetCapabilitiesRequest + ControllerGetCapabilitiesResponse + ControllerServiceCapability + NodePublishVolumeRequest + NodePublishVolumeResponse + NodeUnpublishVolumeRequest + NodeUnpublishVolumeResponse + GetNodeIDRequest + GetNodeIDResponse + NodeProbeRequest + NodeProbeResponse + NodeGetCapabilitiesRequest + NodeGetCapabilitiesResponse + NodeServiceCapability +*/ +package csi + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type VolumeCapability_AccessMode_Mode int32 + +const ( + VolumeCapability_AccessMode_UNKNOWN VolumeCapability_AccessMode_Mode = 0 + // Can be published as read/write at one node at a time. + VolumeCapability_AccessMode_SINGLE_NODE_WRITER VolumeCapability_AccessMode_Mode = 1 + // Can be published as readonly at one node at a time. + VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY VolumeCapability_AccessMode_Mode = 2 + // Can be published as readonly at multiple nodes simultaneously. + VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY VolumeCapability_AccessMode_Mode = 3 + // Can be published at multiple nodes simultaneously. Only one of + // the node can be used as read/write. The rest will be readonly. + VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER VolumeCapability_AccessMode_Mode = 4 + // Can be published as read/write at multiple nodes + // simultaneously. + VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER VolumeCapability_AccessMode_Mode = 5 +) + +var VolumeCapability_AccessMode_Mode_name = map[int32]string{ + 0: "UNKNOWN", + 1: "SINGLE_NODE_WRITER", + 2: "SINGLE_NODE_READER_ONLY", + 3: "MULTI_NODE_READER_ONLY", + 4: "MULTI_NODE_SINGLE_WRITER", + 5: "MULTI_NODE_MULTI_WRITER", +} +var VolumeCapability_AccessMode_Mode_value = map[string]int32{ + "UNKNOWN": 0, + "SINGLE_NODE_WRITER": 1, + "SINGLE_NODE_READER_ONLY": 2, + "MULTI_NODE_READER_ONLY": 3, + "MULTI_NODE_SINGLE_WRITER": 4, + "MULTI_NODE_MULTI_WRITER": 5, +} + +func (x VolumeCapability_AccessMode_Mode) String() string { + return proto.EnumName(VolumeCapability_AccessMode_Mode_name, int32(x)) +} +func (VolumeCapability_AccessMode_Mode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{7, 2, 0} +} + +type ControllerServiceCapability_RPC_Type int32 + +const ( + ControllerServiceCapability_RPC_UNKNOWN ControllerServiceCapability_RPC_Type = 0 + ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME ControllerServiceCapability_RPC_Type = 1 + ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME ControllerServiceCapability_RPC_Type = 2 + ControllerServiceCapability_RPC_LIST_VOLUMES ControllerServiceCapability_RPC_Type = 3 + ControllerServiceCapability_RPC_GET_CAPACITY ControllerServiceCapability_RPC_Type = 4 +) + +var ControllerServiceCapability_RPC_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "CREATE_DELETE_VOLUME", + 2: "PUBLISH_UNPUBLISH_VOLUME", + 3: "LIST_VOLUMES", + 4: "GET_CAPACITY", +} +var ControllerServiceCapability_RPC_Type_value = map[string]int32{ + "UNKNOWN": 0, + "CREATE_DELETE_VOLUME": 1, + "PUBLISH_UNPUBLISH_VOLUME": 2, + "LIST_VOLUMES": 3, + "GET_CAPACITY": 4, +} + +func (x ControllerServiceCapability_RPC_Type) String() string { + return proto.EnumName(ControllerServiceCapability_RPC_Type_name, int32(x)) +} +func (ControllerServiceCapability_RPC_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{26, 0, 0} +} + +type NodeServiceCapability_RPC_Type int32 + +const ( + NodeServiceCapability_RPC_UNKNOWN NodeServiceCapability_RPC_Type = 0 +) + +var NodeServiceCapability_RPC_Type_name = map[int32]string{ + 0: "UNKNOWN", +} +var NodeServiceCapability_RPC_Type_value = map[string]int32{ + "UNKNOWN": 0, +} + +func (x NodeServiceCapability_RPC_Type) String() string { + return proto.EnumName(NodeServiceCapability_RPC_Type_name, int32(x)) +} +func (NodeServiceCapability_RPC_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{37, 0, 0} +} + +// ////// +// ////// +type GetSupportedVersionsRequest struct { +} + +func (m *GetSupportedVersionsRequest) Reset() { *m = GetSupportedVersionsRequest{} } +func (m *GetSupportedVersionsRequest) String() string { return proto.CompactTextString(m) } +func (*GetSupportedVersionsRequest) ProtoMessage() {} +func (*GetSupportedVersionsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type GetSupportedVersionsResponse struct { + // All the CSI versions that the Plugin supports. This field is + // REQUIRED. + SupportedVersions []*Version `protobuf:"bytes,1,rep,name=supported_versions,json=supportedVersions" json:"supported_versions,omitempty"` +} + +func (m *GetSupportedVersionsResponse) Reset() { *m = GetSupportedVersionsResponse{} } +func (m *GetSupportedVersionsResponse) String() string { return proto.CompactTextString(m) } +func (*GetSupportedVersionsResponse) ProtoMessage() {} +func (*GetSupportedVersionsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *GetSupportedVersionsResponse) GetSupportedVersions() []*Version { + if m != nil { + return m.SupportedVersions + } + return nil +} + +// Specifies a version in Semantic Version 2.0 format. +// (http://semver.org/spec/v2.0.0.html) +type Version struct { + Major uint32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"` + Minor uint32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"` + Patch uint32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"` +} + +func (m *Version) Reset() { *m = Version{} } +func (m *Version) String() string { return proto.CompactTextString(m) } +func (*Version) ProtoMessage() {} +func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Version) GetMajor() uint32 { + if m != nil { + return m.Major + } + return 0 +} + +func (m *Version) GetMinor() uint32 { + if m != nil { + return m.Minor + } + return 0 +} + +func (m *Version) GetPatch() uint32 { + if m != nil { + return m.Patch + } + return 0 +} + +// ////// +// ////// +type GetPluginInfoRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` +} + +func (m *GetPluginInfoRequest) Reset() { *m = GetPluginInfoRequest{} } +func (m *GetPluginInfoRequest) String() string { return proto.CompactTextString(m) } +func (*GetPluginInfoRequest) ProtoMessage() {} +func (*GetPluginInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *GetPluginInfoRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +type GetPluginInfoResponse struct { + // The name MUST follow reverse domain name notation format + // (https://en.wikipedia.org/wiki/Reverse_domain_name_notation). + // It SHOULD include the plugin's host company name and the plugin + // name, to minimize the possibility of collisions. It MUST be 63 + // characters or less, beginning and ending with an alphanumeric + // character ([a-z0-9A-Z]) with dashes (-), underscores (_), + // dots (.), and alphanumerics between. This field is REQUIRED. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // This field is REQUIRED. Value of this field is opaque to the CO. + VendorVersion string `protobuf:"bytes,2,opt,name=vendor_version,json=vendorVersion" json:"vendor_version,omitempty"` + // This field is OPTIONAL. Values are opaque to the CO. + Manifest map[string]string `protobuf:"bytes,3,rep,name=manifest" json:"manifest,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *GetPluginInfoResponse) Reset() { *m = GetPluginInfoResponse{} } +func (m *GetPluginInfoResponse) String() string { return proto.CompactTextString(m) } +func (*GetPluginInfoResponse) ProtoMessage() {} +func (*GetPluginInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *GetPluginInfoResponse) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *GetPluginInfoResponse) GetVendorVersion() string { + if m != nil { + return m.VendorVersion + } + return "" +} + +func (m *GetPluginInfoResponse) GetManifest() map[string]string { + if m != nil { + return m.Manifest + } + return nil +} + +// ////// +// ////// +type CreateVolumeRequest struct { + // The API version assumed by the CO. This field is REQUIRED. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The suggested name for the storage space. This field is REQUIRED. + // It serves two purposes: + // 1) Idempotency - This name is generated by the CO to achieve + // idempotency. If `CreateVolume` fails, the volume may or may not + // be provisioned. In this case, the CO may call `CreateVolume` + // again, with the same name, to ensure the volume exists. The + // Plugin should ensure that multiple `CreateVolume` calls for the + // same name do not result in more than one piece of storage + // provisioned corresponding to that name. If a Plugin is unable to + // enforce idempotency, the CO's error recovery logic could result + // in multiple (unused) volumes being provisioned. + // 2) Suggested name - Some storage systems allow callers to specify + // an identifier by which to refer to the newly provisioned + // storage. If a storage system supports this, it can optionally + // use this name as the identifier for the new volume. + Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + // This field is OPTIONAL. This allows the CO to specify the capacity + // requirement of the volume to be provisioned. If not specified, the + // Plugin MAY choose an implementation-defined capacity range. + CapacityRange *CapacityRange `protobuf:"bytes,3,opt,name=capacity_range,json=capacityRange" json:"capacity_range,omitempty"` + // The capabilities that the provisioned volume MUST have: the Plugin + // MUST provision a volume that could satisfy ALL of the + // capabilities specified in this list. The Plugin MUST assume that + // the CO MAY use the provisioned volume later with ANY of the + // capabilities specified in this list. This also enables the CO to do + // early validation: if ANY of the specified volume capabilities are + // not supported by the Plugin, the call SHALL fail. This field is + // REQUIRED. + VolumeCapabilities []*VolumeCapability `protobuf:"bytes,4,rep,name=volume_capabilities,json=volumeCapabilities" json:"volume_capabilities,omitempty"` + // Plugin specific parameters passed in as opaque key-value pairs. + // This field is OPTIONAL. The Plugin is responsible for parsing and + // validating these parameters. COs will treat these as opaque. + Parameters map[string]string `protobuf:"bytes,5,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // End user credentials used to authenticate/authorize volume creation + // request. + // This field contains credential data, for example username and + // password. Each key must consist of alphanumeric characters, '-', + // '_' or '.'. Each value MUST contain a valid string. An SP MAY + // choose to accept binary (non-string) data by using a binary-to-text + // encoding scheme, like base64. An SP SHALL advertise the + // requirements for credentials in documentation. COs SHALL permit + // users to pass through the required credentials. This information is + // sensitive and MUST be treated as such (not logged, etc.) by the CO. + // This field is OPTIONAL. + UserCredentials map[string]string `protobuf:"bytes,6,rep,name=user_credentials,json=userCredentials" json:"user_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *CreateVolumeRequest) Reset() { *m = CreateVolumeRequest{} } +func (m *CreateVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*CreateVolumeRequest) ProtoMessage() {} +func (*CreateVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *CreateVolumeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *CreateVolumeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *CreateVolumeRequest) GetCapacityRange() *CapacityRange { + if m != nil { + return m.CapacityRange + } + return nil +} + +func (m *CreateVolumeRequest) GetVolumeCapabilities() []*VolumeCapability { + if m != nil { + return m.VolumeCapabilities + } + return nil +} + +func (m *CreateVolumeRequest) GetParameters() map[string]string { + if m != nil { + return m.Parameters + } + return nil +} + +func (m *CreateVolumeRequest) GetUserCredentials() map[string]string { + if m != nil { + return m.UserCredentials + } + return nil +} + +type CreateVolumeResponse struct { + // Contains all attributes of the newly created volume that are + // relevant to the CO along with information required by the Plugin + // to uniquely identify the volume. This field is REQUIRED. + VolumeInfo *VolumeInfo `protobuf:"bytes,1,opt,name=volume_info,json=volumeInfo" json:"volume_info,omitempty"` +} + +func (m *CreateVolumeResponse) Reset() { *m = CreateVolumeResponse{} } +func (m *CreateVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*CreateVolumeResponse) ProtoMessage() {} +func (*CreateVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *CreateVolumeResponse) GetVolumeInfo() *VolumeInfo { + if m != nil { + return m.VolumeInfo + } + return nil +} + +// Specify a capability of a volume. +type VolumeCapability struct { + // Specifies what API the volume will be accessed using. One of the + // following fields MUST be specified. + // + // Types that are valid to be assigned to AccessType: + // *VolumeCapability_Block + // *VolumeCapability_Mount + AccessType isVolumeCapability_AccessType `protobuf_oneof:"access_type"` + // This is a REQUIRED field. + AccessMode *VolumeCapability_AccessMode `protobuf:"bytes,3,opt,name=access_mode,json=accessMode" json:"access_mode,omitempty"` +} + +func (m *VolumeCapability) Reset() { *m = VolumeCapability{} } +func (m *VolumeCapability) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability) ProtoMessage() {} +func (*VolumeCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +type isVolumeCapability_AccessType interface { + isVolumeCapability_AccessType() +} + +type VolumeCapability_Block struct { + Block *VolumeCapability_BlockVolume `protobuf:"bytes,1,opt,name=block,oneof"` +} +type VolumeCapability_Mount struct { + Mount *VolumeCapability_MountVolume `protobuf:"bytes,2,opt,name=mount,oneof"` +} + +func (*VolumeCapability_Block) isVolumeCapability_AccessType() {} +func (*VolumeCapability_Mount) isVolumeCapability_AccessType() {} + +func (m *VolumeCapability) GetAccessType() isVolumeCapability_AccessType { + if m != nil { + return m.AccessType + } + return nil +} + +func (m *VolumeCapability) GetBlock() *VolumeCapability_BlockVolume { + if x, ok := m.GetAccessType().(*VolumeCapability_Block); ok { + return x.Block + } + return nil +} + +func (m *VolumeCapability) GetMount() *VolumeCapability_MountVolume { + if x, ok := m.GetAccessType().(*VolumeCapability_Mount); ok { + return x.Mount + } + return nil +} + +func (m *VolumeCapability) GetAccessMode() *VolumeCapability_AccessMode { + if m != nil { + return m.AccessMode + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*VolumeCapability) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _VolumeCapability_OneofMarshaler, _VolumeCapability_OneofUnmarshaler, _VolumeCapability_OneofSizer, []interface{}{ + (*VolumeCapability_Block)(nil), + (*VolumeCapability_Mount)(nil), + } +} + +func _VolumeCapability_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*VolumeCapability) + // access_type + switch x := m.AccessType.(type) { + case *VolumeCapability_Block: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Block); err != nil { + return err + } + case *VolumeCapability_Mount: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Mount); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("VolumeCapability.AccessType has unexpected type %T", x) + } + return nil +} + +func _VolumeCapability_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*VolumeCapability) + switch tag { + case 1: // access_type.block + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(VolumeCapability_BlockVolume) + err := b.DecodeMessage(msg) + m.AccessType = &VolumeCapability_Block{msg} + return true, err + case 2: // access_type.mount + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(VolumeCapability_MountVolume) + err := b.DecodeMessage(msg) + m.AccessType = &VolumeCapability_Mount{msg} + return true, err + default: + return false, nil + } +} + +func _VolumeCapability_OneofSizer(msg proto.Message) (n int) { + m := msg.(*VolumeCapability) + // access_type + switch x := m.AccessType.(type) { + case *VolumeCapability_Block: + s := proto.Size(x.Block) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *VolumeCapability_Mount: + s := proto.Size(x.Mount) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Indicate that the volume will be accessed via the block device API. +type VolumeCapability_BlockVolume struct { +} + +func (m *VolumeCapability_BlockVolume) Reset() { *m = VolumeCapability_BlockVolume{} } +func (m *VolumeCapability_BlockVolume) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability_BlockVolume) ProtoMessage() {} +func (*VolumeCapability_BlockVolume) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 0} } + +// Indicate that the volume will be accessed via the filesystem API. +type VolumeCapability_MountVolume struct { + // The filesystem type. This field is OPTIONAL. + // An empty string is equal to an unspecified field value. + FsType string `protobuf:"bytes,1,opt,name=fs_type,json=fsType" json:"fs_type,omitempty"` + // The mount options that can be used for the volume. This field is + // OPTIONAL. `mount_flags` MAY contain sensitive information. + // Therefore, the CO and the Plugin MUST NOT leak this information + // to untrusted entities. The total size of this repeated field + // SHALL NOT exceed 4 KiB. + MountFlags []string `protobuf:"bytes,2,rep,name=mount_flags,json=mountFlags" json:"mount_flags,omitempty"` +} + +func (m *VolumeCapability_MountVolume) Reset() { *m = VolumeCapability_MountVolume{} } +func (m *VolumeCapability_MountVolume) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability_MountVolume) ProtoMessage() {} +func (*VolumeCapability_MountVolume) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 1} } + +func (m *VolumeCapability_MountVolume) GetFsType() string { + if m != nil { + return m.FsType + } + return "" +} + +func (m *VolumeCapability_MountVolume) GetMountFlags() []string { + if m != nil { + return m.MountFlags + } + return nil +} + +// Specify how a volume can be accessed. +type VolumeCapability_AccessMode struct { + // This field is REQUIRED. + Mode VolumeCapability_AccessMode_Mode `protobuf:"varint,1,opt,name=mode,enum=csi.VolumeCapability_AccessMode_Mode" json:"mode,omitempty"` +} + +func (m *VolumeCapability_AccessMode) Reset() { *m = VolumeCapability_AccessMode{} } +func (m *VolumeCapability_AccessMode) String() string { return proto.CompactTextString(m) } +func (*VolumeCapability_AccessMode) ProtoMessage() {} +func (*VolumeCapability_AccessMode) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 2} } + +func (m *VolumeCapability_AccessMode) GetMode() VolumeCapability_AccessMode_Mode { + if m != nil { + return m.Mode + } + return VolumeCapability_AccessMode_UNKNOWN +} + +// The capacity of the storage space in bytes. To specify an exact size, +// `required_bytes` and `limit_bytes` can be set to the same value. At +// least one of the these fields MUST be specified. +type CapacityRange struct { + // Volume must be at least this big. This field is OPTIONAL. + // A value of 0 is equal to an unspecified field value. + RequiredBytes uint64 `protobuf:"varint,1,opt,name=required_bytes,json=requiredBytes" json:"required_bytes,omitempty"` + // Volume must not be bigger than this. This field is OPTIONAL. + // A value of 0 is equal to an unspecified field value. + LimitBytes uint64 `protobuf:"varint,2,opt,name=limit_bytes,json=limitBytes" json:"limit_bytes,omitempty"` +} + +func (m *CapacityRange) Reset() { *m = CapacityRange{} } +func (m *CapacityRange) String() string { return proto.CompactTextString(m) } +func (*CapacityRange) ProtoMessage() {} +func (*CapacityRange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *CapacityRange) GetRequiredBytes() uint64 { + if m != nil { + return m.RequiredBytes + } + return 0 +} + +func (m *CapacityRange) GetLimitBytes() uint64 { + if m != nil { + return m.LimitBytes + } + return 0 +} + +// The information about a provisioned volume. +type VolumeInfo struct { + // The capacity of the volume in bytes. This field is OPTIONAL. If not + // set (value of 0), it indicates that the capacity of the volume is + // unknown (e.g., NFS share). + CapacityBytes uint64 `protobuf:"varint,1,opt,name=capacity_bytes,json=capacityBytes" json:"capacity_bytes,omitempty"` + // Contains identity information for the created volume. This field is + // REQUIRED. The identity information will be used by the CO in + // subsequent calls to refer to the provisioned volume. + Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"` + // Attributes reflect static properties of a volume and MUST be passed + // to volume validation and publishing calls. + // Attributes SHALL be opaque to a CO. Attributes SHALL NOT be mutable + // and SHALL be safe for the CO to cache. Attributes SHOULD NOT + // contain sensitive information. Attributes MAY NOT uniquely identify + // a volume. A volume uniquely identified by `id` SHALL always report + // the same attributes. This field is OPTIONAL and when present MUST + // be passed to volume validation and publishing calls. + Attributes map[string]string `protobuf:"bytes,3,rep,name=attributes" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *VolumeInfo) Reset() { *m = VolumeInfo{} } +func (m *VolumeInfo) String() string { return proto.CompactTextString(m) } +func (*VolumeInfo) ProtoMessage() {} +func (*VolumeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *VolumeInfo) GetCapacityBytes() uint64 { + if m != nil { + return m.CapacityBytes + } + return 0 +} + +func (m *VolumeInfo) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *VolumeInfo) GetAttributes() map[string]string { + if m != nil { + return m.Attributes + } + return nil +} + +// ////// +// ////// +type DeleteVolumeRequest struct { + // The API version assumed by the CO. This field is REQUIRED. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The ID of the volume to be deprovisioned. + // This field is REQUIRED. + VolumeId string `protobuf:"bytes,2,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` + // End user credentials used to authenticate/authorize volume deletion + // request. + // This field contains credential data, for example username and + // password. Each key must consist of alphanumeric characters, '-', + // '_' or '.'. Each value MUST contain a valid string. An SP MAY + // choose to accept binary (non-string) data by using a binary-to-text + // encoding scheme, like base64. An SP SHALL advertise the + // requirements for credentials in documentation. COs SHALL permit + // users to pass through the required credentials. This information is + // sensitive and MUST be treated as such (not logged, etc.) by the CO. + // This field is OPTIONAL. + UserCredentials map[string]string `protobuf:"bytes,3,rep,name=user_credentials,json=userCredentials" json:"user_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *DeleteVolumeRequest) Reset() { *m = DeleteVolumeRequest{} } +func (m *DeleteVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteVolumeRequest) ProtoMessage() {} +func (*DeleteVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +func (m *DeleteVolumeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *DeleteVolumeRequest) GetVolumeId() string { + if m != nil { + return m.VolumeId + } + return "" +} + +func (m *DeleteVolumeRequest) GetUserCredentials() map[string]string { + if m != nil { + return m.UserCredentials + } + return nil +} + +type DeleteVolumeResponse struct { +} + +func (m *DeleteVolumeResponse) Reset() { *m = DeleteVolumeResponse{} } +func (m *DeleteVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteVolumeResponse) ProtoMessage() {} +func (*DeleteVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +// ////// +// ////// +type ControllerPublishVolumeRequest struct { + // The API version assumed by the CO. This field is REQUIRED. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The ID of the volume to be used on a node. + // This field is REQUIRED. + VolumeId string `protobuf:"bytes,2,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` + // The ID of the node. This field is REQUIRED. The CO SHALL set this + // field to match the node ID returned by `GetNodeID`. + NodeId string `protobuf:"bytes,3,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` + // The capability of the volume the CO expects the volume to have. + // This is a REQUIRED field. + VolumeCapability *VolumeCapability `protobuf:"bytes,4,opt,name=volume_capability,json=volumeCapability" json:"volume_capability,omitempty"` + // Whether to publish the volume in readonly mode. This field is + // REQUIRED. + Readonly bool `protobuf:"varint,5,opt,name=readonly" json:"readonly,omitempty"` + // End user credentials used to authenticate/authorize controller + // publish request. + // This field contains credential data, for example username and + // password. Each key must consist of alphanumeric characters, '-', + // '_' or '.'. Each value MUST contain a valid string. An SP MAY + // choose to accept binary (non-string) data by using a binary-to-text + // encoding scheme, like base64. An SP SHALL advertise the + // requirements for credentials in documentation. COs SHALL permit + // users to pass through the required credentials. This information is + // sensitive and MUST be treated as such (not logged, etc.) by the CO. + // This field is OPTIONAL. + UserCredentials map[string]string `protobuf:"bytes,6,rep,name=user_credentials,json=userCredentials" json:"user_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Attributes of the volume to be used on a node. This field is + // OPTIONAL and MUST match the attributes of the VolumeInfo identified + // by `volume_id`. + VolumeAttributes map[string]string `protobuf:"bytes,7,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ControllerPublishVolumeRequest) Reset() { *m = ControllerPublishVolumeRequest{} } +func (m *ControllerPublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*ControllerPublishVolumeRequest) ProtoMessage() {} +func (*ControllerPublishVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +func (m *ControllerPublishVolumeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *ControllerPublishVolumeRequest) GetVolumeId() string { + if m != nil { + return m.VolumeId + } + return "" +} + +func (m *ControllerPublishVolumeRequest) GetNodeId() string { + if m != nil { + return m.NodeId + } + return "" +} + +func (m *ControllerPublishVolumeRequest) GetVolumeCapability() *VolumeCapability { + if m != nil { + return m.VolumeCapability + } + return nil +} + +func (m *ControllerPublishVolumeRequest) GetReadonly() bool { + if m != nil { + return m.Readonly + } + return false +} + +func (m *ControllerPublishVolumeRequest) GetUserCredentials() map[string]string { + if m != nil { + return m.UserCredentials + } + return nil +} + +func (m *ControllerPublishVolumeRequest) GetVolumeAttributes() map[string]string { + if m != nil { + return m.VolumeAttributes + } + return nil +} + +type ControllerPublishVolumeResponse struct { + // The SP specific information that will be passed to the Plugin in + // the subsequent `NodePublishVolume` call for the given volume. + // This information is opaque to the CO. This field is OPTIONAL. + PublishVolumeInfo map[string]string `protobuf:"bytes,1,rep,name=publish_volume_info,json=publishVolumeInfo" json:"publish_volume_info,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ControllerPublishVolumeResponse) Reset() { *m = ControllerPublishVolumeResponse{} } +func (m *ControllerPublishVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*ControllerPublishVolumeResponse) ProtoMessage() {} +func (*ControllerPublishVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{13} +} + +func (m *ControllerPublishVolumeResponse) GetPublishVolumeInfo() map[string]string { + if m != nil { + return m.PublishVolumeInfo + } + return nil +} + +// ////// +// ////// +type ControllerUnpublishVolumeRequest struct { + // The API version assumed by the CO. This field is REQUIRED. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The ID of the volume. This field is REQUIRED. + VolumeId string `protobuf:"bytes,2,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` + // The ID of the node. This field is OPTIONAL. The CO SHOULD set this + // field to match the node ID returned by `GetNodeID` or leave it + // unset. If the value is set, the SP MUST unpublish the volume from + // the specified node. If the value is unset, the SP MUST unpublish + // the volume from all nodes it is published to. + NodeId string `protobuf:"bytes,3,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` + // End user credentials used to authenticate/authorize controller + // unpublish request. + // This field contains credential data, for example username and + // password. Each key must consist of alphanumeric characters, '-', + // '_' or '.'. Each value MUST contain a valid string. An SP MAY + // choose to accept binary (non-string) data by using a binary-to-text + // encoding scheme, like base64. An SP SHALL advertise the + // requirements for credentials in documentation. COs SHALL permit + // users to pass through the required credentials. This information is + // sensitive and MUST be treated as such (not logged, etc.) by the CO. + // This field is OPTIONAL. + UserCredentials map[string]string `protobuf:"bytes,4,rep,name=user_credentials,json=userCredentials" json:"user_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ControllerUnpublishVolumeRequest) Reset() { *m = ControllerUnpublishVolumeRequest{} } +func (m *ControllerUnpublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*ControllerUnpublishVolumeRequest) ProtoMessage() {} +func (*ControllerUnpublishVolumeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{14} +} + +func (m *ControllerUnpublishVolumeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *ControllerUnpublishVolumeRequest) GetVolumeId() string { + if m != nil { + return m.VolumeId + } + return "" +} + +func (m *ControllerUnpublishVolumeRequest) GetNodeId() string { + if m != nil { + return m.NodeId + } + return "" +} + +func (m *ControllerUnpublishVolumeRequest) GetUserCredentials() map[string]string { + if m != nil { + return m.UserCredentials + } + return nil +} + +type ControllerUnpublishVolumeResponse struct { +} + +func (m *ControllerUnpublishVolumeResponse) Reset() { *m = ControllerUnpublishVolumeResponse{} } +func (m *ControllerUnpublishVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*ControllerUnpublishVolumeResponse) ProtoMessage() {} +func (*ControllerUnpublishVolumeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{15} +} + +// ////// +// ////// +type ValidateVolumeCapabilitiesRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The ID of the volume to check. This field is REQUIRED. + VolumeId string `protobuf:"bytes,2,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` + // The capabilities that the CO wants to check for the volume. This + // call SHALL return "supported" only if all the volume capabilities + // specified below are supported. This field is REQUIRED. + VolumeCapabilities []*VolumeCapability `protobuf:"bytes,3,rep,name=volume_capabilities,json=volumeCapabilities" json:"volume_capabilities,omitempty"` + // Attributes of the volume to check. This field is OPTIONAL and MUST + // match the attributes of the VolumeInfo identified by `volume_id`. + VolumeAttributes map[string]string `protobuf:"bytes,4,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ValidateVolumeCapabilitiesRequest) Reset() { *m = ValidateVolumeCapabilitiesRequest{} } +func (m *ValidateVolumeCapabilitiesRequest) String() string { return proto.CompactTextString(m) } +func (*ValidateVolumeCapabilitiesRequest) ProtoMessage() {} +func (*ValidateVolumeCapabilitiesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{16} +} + +func (m *ValidateVolumeCapabilitiesRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *ValidateVolumeCapabilitiesRequest) GetVolumeId() string { + if m != nil { + return m.VolumeId + } + return "" +} + +func (m *ValidateVolumeCapabilitiesRequest) GetVolumeCapabilities() []*VolumeCapability { + if m != nil { + return m.VolumeCapabilities + } + return nil +} + +func (m *ValidateVolumeCapabilitiesRequest) GetVolumeAttributes() map[string]string { + if m != nil { + return m.VolumeAttributes + } + return nil +} + +type ValidateVolumeCapabilitiesResponse struct { + // True if the Plugin supports the specified capabilities for the + // given volume. This field is REQUIRED. + Supported bool `protobuf:"varint,1,opt,name=supported" json:"supported,omitempty"` + // Message to the CO if `supported` above is false. This field is + // OPTIONAL. + // An empty string is equal to an unspecified field value. + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` +} + +func (m *ValidateVolumeCapabilitiesResponse) Reset() { *m = ValidateVolumeCapabilitiesResponse{} } +func (m *ValidateVolumeCapabilitiesResponse) String() string { return proto.CompactTextString(m) } +func (*ValidateVolumeCapabilitiesResponse) ProtoMessage() {} +func (*ValidateVolumeCapabilitiesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{17} +} + +func (m *ValidateVolumeCapabilitiesResponse) GetSupported() bool { + if m != nil { + return m.Supported + } + return false +} + +func (m *ValidateVolumeCapabilitiesResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +// ////// +// ////// +type ListVolumesRequest struct { + // The API version assumed by the CO. This field is REQUIRED. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // If specified (non-zero value), the Plugin MUST NOT return more + // entries than this number in the response. If the actual number of + // entries is more than this number, the Plugin MUST set `next_token` + // in the response which can be used to get the next page of entries + // in the subsequent `ListVolumes` call. This field is OPTIONAL. If + // not specified (zero value), it means there is no restriction on the + // number of entries that can be returned. + MaxEntries uint32 `protobuf:"varint,2,opt,name=max_entries,json=maxEntries" json:"max_entries,omitempty"` + // A token to specify where to start paginating. Set this field to + // `next_token` returned by a previous `ListVolumes` call to get the + // next page of entries. This field is OPTIONAL. + // An empty string is equal to an unspecified field value. + StartingToken string `protobuf:"bytes,3,opt,name=starting_token,json=startingToken" json:"starting_token,omitempty"` +} + +func (m *ListVolumesRequest) Reset() { *m = ListVolumesRequest{} } +func (m *ListVolumesRequest) String() string { return proto.CompactTextString(m) } +func (*ListVolumesRequest) ProtoMessage() {} +func (*ListVolumesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +func (m *ListVolumesRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *ListVolumesRequest) GetMaxEntries() uint32 { + if m != nil { + return m.MaxEntries + } + return 0 +} + +func (m *ListVolumesRequest) GetStartingToken() string { + if m != nil { + return m.StartingToken + } + return "" +} + +type ListVolumesResponse struct { + Entries []*ListVolumesResponse_Entry `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"` + // This token allows you to get the next page of entries for + // `ListVolumes` request. If the number of entries is larger than + // `max_entries`, use the `next_token` as a value for the + // `starting_token` field in the next `ListVolumes` request. This + // field is OPTIONAL. + // An empty string is equal to an unspecified field value. + NextToken string `protobuf:"bytes,2,opt,name=next_token,json=nextToken" json:"next_token,omitempty"` +} + +func (m *ListVolumesResponse) Reset() { *m = ListVolumesResponse{} } +func (m *ListVolumesResponse) String() string { return proto.CompactTextString(m) } +func (*ListVolumesResponse) ProtoMessage() {} +func (*ListVolumesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +func (m *ListVolumesResponse) GetEntries() []*ListVolumesResponse_Entry { + if m != nil { + return m.Entries + } + return nil +} + +func (m *ListVolumesResponse) GetNextToken() string { + if m != nil { + return m.NextToken + } + return "" +} + +type ListVolumesResponse_Entry struct { + VolumeInfo *VolumeInfo `protobuf:"bytes,1,opt,name=volume_info,json=volumeInfo" json:"volume_info,omitempty"` +} + +func (m *ListVolumesResponse_Entry) Reset() { *m = ListVolumesResponse_Entry{} } +func (m *ListVolumesResponse_Entry) String() string { return proto.CompactTextString(m) } +func (*ListVolumesResponse_Entry) ProtoMessage() {} +func (*ListVolumesResponse_Entry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } + +func (m *ListVolumesResponse_Entry) GetVolumeInfo() *VolumeInfo { + if m != nil { + return m.VolumeInfo + } + return nil +} + +// ////// +// ////// +type GetCapacityRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // If specified, the Plugin SHALL report the capacity of the storage + // that can be used to provision volumes that satisfy ALL of the + // specified `volume_capabilities`. These are the same + // `volume_capabilities` the CO will use in `CreateVolumeRequest`. + // This field is OPTIONAL. + VolumeCapabilities []*VolumeCapability `protobuf:"bytes,2,rep,name=volume_capabilities,json=volumeCapabilities" json:"volume_capabilities,omitempty"` + // If specified, the Plugin SHALL report the capacity of the storage + // that can be used to provision volumes with the given Plugin + // specific `parameters`. These are the same `parameters` the CO will + // use in `CreateVolumeRequest`. This field is OPTIONAL. + Parameters map[string]string `protobuf:"bytes,3,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *GetCapacityRequest) Reset() { *m = GetCapacityRequest{} } +func (m *GetCapacityRequest) String() string { return proto.CompactTextString(m) } +func (*GetCapacityRequest) ProtoMessage() {} +func (*GetCapacityRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } + +func (m *GetCapacityRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *GetCapacityRequest) GetVolumeCapabilities() []*VolumeCapability { + if m != nil { + return m.VolumeCapabilities + } + return nil +} + +func (m *GetCapacityRequest) GetParameters() map[string]string { + if m != nil { + return m.Parameters + } + return nil +} + +type GetCapacityResponse struct { + // The available capacity of the storage that can be used to + // provision volumes. If `volume_capabilities` or `parameters` is + // specified in the request, the Plugin SHALL take those into + // consideration when calculating the available capacity of the + // storage. This field is REQUIRED. + AvailableCapacity uint64 `protobuf:"varint,1,opt,name=available_capacity,json=availableCapacity" json:"available_capacity,omitempty"` +} + +func (m *GetCapacityResponse) Reset() { *m = GetCapacityResponse{} } +func (m *GetCapacityResponse) String() string { return proto.CompactTextString(m) } +func (*GetCapacityResponse) ProtoMessage() {} +func (*GetCapacityResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } + +func (m *GetCapacityResponse) GetAvailableCapacity() uint64 { + if m != nil { + return m.AvailableCapacity + } + return 0 +} + +// ////// +// ////// +type ControllerProbeRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` +} + +func (m *ControllerProbeRequest) Reset() { *m = ControllerProbeRequest{} } +func (m *ControllerProbeRequest) String() string { return proto.CompactTextString(m) } +func (*ControllerProbeRequest) ProtoMessage() {} +func (*ControllerProbeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } + +func (m *ControllerProbeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +type ControllerProbeResponse struct { +} + +func (m *ControllerProbeResponse) Reset() { *m = ControllerProbeResponse{} } +func (m *ControllerProbeResponse) String() string { return proto.CompactTextString(m) } +func (*ControllerProbeResponse) ProtoMessage() {} +func (*ControllerProbeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } + +// ////// +// ////// +type ControllerGetCapabilitiesRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` +} + +func (m *ControllerGetCapabilitiesRequest) Reset() { *m = ControllerGetCapabilitiesRequest{} } +func (m *ControllerGetCapabilitiesRequest) String() string { return proto.CompactTextString(m) } +func (*ControllerGetCapabilitiesRequest) ProtoMessage() {} +func (*ControllerGetCapabilitiesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{24} +} + +func (m *ControllerGetCapabilitiesRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +type ControllerGetCapabilitiesResponse struct { + // All the capabilities that the controller service supports. This + // field is OPTIONAL. + Capabilities []*ControllerServiceCapability `protobuf:"bytes,2,rep,name=capabilities" json:"capabilities,omitempty"` +} + +func (m *ControllerGetCapabilitiesResponse) Reset() { *m = ControllerGetCapabilitiesResponse{} } +func (m *ControllerGetCapabilitiesResponse) String() string { return proto.CompactTextString(m) } +func (*ControllerGetCapabilitiesResponse) ProtoMessage() {} +func (*ControllerGetCapabilitiesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{25} +} + +func (m *ControllerGetCapabilitiesResponse) GetCapabilities() []*ControllerServiceCapability { + if m != nil { + return m.Capabilities + } + return nil +} + +// Specifies a capability of the controller service. +type ControllerServiceCapability struct { + // Types that are valid to be assigned to Type: + // *ControllerServiceCapability_Rpc + Type isControllerServiceCapability_Type `protobuf_oneof:"type"` +} + +func (m *ControllerServiceCapability) Reset() { *m = ControllerServiceCapability{} } +func (m *ControllerServiceCapability) String() string { return proto.CompactTextString(m) } +func (*ControllerServiceCapability) ProtoMessage() {} +func (*ControllerServiceCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } + +type isControllerServiceCapability_Type interface { + isControllerServiceCapability_Type() +} + +type ControllerServiceCapability_Rpc struct { + Rpc *ControllerServiceCapability_RPC `protobuf:"bytes,1,opt,name=rpc,oneof"` +} + +func (*ControllerServiceCapability_Rpc) isControllerServiceCapability_Type() {} + +func (m *ControllerServiceCapability) GetType() isControllerServiceCapability_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *ControllerServiceCapability) GetRpc() *ControllerServiceCapability_RPC { + if x, ok := m.GetType().(*ControllerServiceCapability_Rpc); ok { + return x.Rpc + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ControllerServiceCapability) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ControllerServiceCapability_OneofMarshaler, _ControllerServiceCapability_OneofUnmarshaler, _ControllerServiceCapability_OneofSizer, []interface{}{ + (*ControllerServiceCapability_Rpc)(nil), + } +} + +func _ControllerServiceCapability_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ControllerServiceCapability) + // type + switch x := m.Type.(type) { + case *ControllerServiceCapability_Rpc: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Rpc); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("ControllerServiceCapability.Type has unexpected type %T", x) + } + return nil +} + +func _ControllerServiceCapability_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ControllerServiceCapability) + switch tag { + case 1: // type.rpc + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ControllerServiceCapability_RPC) + err := b.DecodeMessage(msg) + m.Type = &ControllerServiceCapability_Rpc{msg} + return true, err + default: + return false, nil + } +} + +func _ControllerServiceCapability_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ControllerServiceCapability) + // type + switch x := m.Type.(type) { + case *ControllerServiceCapability_Rpc: + s := proto.Size(x.Rpc) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type ControllerServiceCapability_RPC struct { + Type ControllerServiceCapability_RPC_Type `protobuf:"varint,1,opt,name=type,enum=csi.ControllerServiceCapability_RPC_Type" json:"type,omitempty"` +} + +func (m *ControllerServiceCapability_RPC) Reset() { *m = ControllerServiceCapability_RPC{} } +func (m *ControllerServiceCapability_RPC) String() string { return proto.CompactTextString(m) } +func (*ControllerServiceCapability_RPC) ProtoMessage() {} +func (*ControllerServiceCapability_RPC) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{26, 0} +} + +func (m *ControllerServiceCapability_RPC) GetType() ControllerServiceCapability_RPC_Type { + if m != nil { + return m.Type + } + return ControllerServiceCapability_RPC_UNKNOWN +} + +// ////// +// ////// +type NodePublishVolumeRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The ID of the volume to publish. This field is REQUIRED. + VolumeId string `protobuf:"bytes,2,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` + // The CO SHALL set this field to the value returned by + // `ControllerPublishVolume` if the corresponding Controller Plugin + // has `PUBLISH_UNPUBLISH_VOLUME` controller capability, and SHALL be + // left unset if the corresponding Controller Plugin does not have + // this capability. This is an OPTIONAL field. + PublishVolumeInfo map[string]string `protobuf:"bytes,3,rep,name=publish_volume_info,json=publishVolumeInfo" json:"publish_volume_info,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // The path to which the volume will be published. It MUST be an + // absolute path in the root filesystem of the process serving this + // request. The CO SHALL ensure uniqueness of target_path per volume. + // This is a REQUIRED field. + TargetPath string `protobuf:"bytes,4,opt,name=target_path,json=targetPath" json:"target_path,omitempty"` + // The capability of the volume the CO expects the volume to have. + // This is a REQUIRED field. + VolumeCapability *VolumeCapability `protobuf:"bytes,5,opt,name=volume_capability,json=volumeCapability" json:"volume_capability,omitempty"` + // Whether to publish the volume in readonly mode. This field is + // REQUIRED. + Readonly bool `protobuf:"varint,6,opt,name=readonly" json:"readonly,omitempty"` + // End user credentials used to authenticate/authorize node + // publish request. + // This field contains credential data, for example username and + // password. Each key must consist of alphanumeric characters, '-', + // '_' or '.'. Each value MUST contain a valid string. An SP MAY + // choose to accept binary (non-string) data by using a binary-to-text + // encoding scheme, like base64. An SP SHALL advertise the + // requirements for credentials in documentation. COs SHALL permit + // users to pass through the required credentials. This information is + // sensitive and MUST be treated as such (not logged, etc.) by the CO. + // This field is OPTIONAL. + UserCredentials map[string]string `protobuf:"bytes,7,rep,name=user_credentials,json=userCredentials" json:"user_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Attributes of the volume to publish. This field is OPTIONAL and + // MUST match the attributes of the VolumeInfo identified by + // `volume_id`. + VolumeAttributes map[string]string `protobuf:"bytes,8,rep,name=volume_attributes,json=volumeAttributes" json:"volume_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *NodePublishVolumeRequest) Reset() { *m = NodePublishVolumeRequest{} } +func (m *NodePublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*NodePublishVolumeRequest) ProtoMessage() {} +func (*NodePublishVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } + +func (m *NodePublishVolumeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *NodePublishVolumeRequest) GetVolumeId() string { + if m != nil { + return m.VolumeId + } + return "" +} + +func (m *NodePublishVolumeRequest) GetPublishVolumeInfo() map[string]string { + if m != nil { + return m.PublishVolumeInfo + } + return nil +} + +func (m *NodePublishVolumeRequest) GetTargetPath() string { + if m != nil { + return m.TargetPath + } + return "" +} + +func (m *NodePublishVolumeRequest) GetVolumeCapability() *VolumeCapability { + if m != nil { + return m.VolumeCapability + } + return nil +} + +func (m *NodePublishVolumeRequest) GetReadonly() bool { + if m != nil { + return m.Readonly + } + return false +} + +func (m *NodePublishVolumeRequest) GetUserCredentials() map[string]string { + if m != nil { + return m.UserCredentials + } + return nil +} + +func (m *NodePublishVolumeRequest) GetVolumeAttributes() map[string]string { + if m != nil { + return m.VolumeAttributes + } + return nil +} + +type NodePublishVolumeResponse struct { +} + +func (m *NodePublishVolumeResponse) Reset() { *m = NodePublishVolumeResponse{} } +func (m *NodePublishVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*NodePublishVolumeResponse) ProtoMessage() {} +func (*NodePublishVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } + +// ////// +// ////// +type NodeUnpublishVolumeRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + // The ID of the volume. This field is REQUIRED. + VolumeId string `protobuf:"bytes,2,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` + // The path at which the volume was published. It MUST be an absolute + // path in the root filesystem of the process serving this request. + // This is a REQUIRED field. + TargetPath string `protobuf:"bytes,3,opt,name=target_path,json=targetPath" json:"target_path,omitempty"` + // End user credentials used to authenticate/authorize node + // unpublish request. + // This field contains credential data, for example username and + // password. Each key must consist of alphanumeric characters, '-', + // '_' or '.'. Each value MUST contain a valid string. An SP MAY + // choose to accept binary (non-string) data by using a binary-to-text + // encoding scheme, like base64. An SP SHALL advertise the + // requirements for credentials in documentation. COs SHALL permit + // users to pass through the required credentials. This information is + // sensitive and MUST be treated as such (not logged, etc.) by the CO. + // This field is OPTIONAL. + UserCredentials map[string]string `protobuf:"bytes,4,rep,name=user_credentials,json=userCredentials" json:"user_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *NodeUnpublishVolumeRequest) Reset() { *m = NodeUnpublishVolumeRequest{} } +func (m *NodeUnpublishVolumeRequest) String() string { return proto.CompactTextString(m) } +func (*NodeUnpublishVolumeRequest) ProtoMessage() {} +func (*NodeUnpublishVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *NodeUnpublishVolumeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *NodeUnpublishVolumeRequest) GetVolumeId() string { + if m != nil { + return m.VolumeId + } + return "" +} + +func (m *NodeUnpublishVolumeRequest) GetTargetPath() string { + if m != nil { + return m.TargetPath + } + return "" +} + +func (m *NodeUnpublishVolumeRequest) GetUserCredentials() map[string]string { + if m != nil { + return m.UserCredentials + } + return nil +} + +type NodeUnpublishVolumeResponse struct { +} + +func (m *NodeUnpublishVolumeResponse) Reset() { *m = NodeUnpublishVolumeResponse{} } +func (m *NodeUnpublishVolumeResponse) String() string { return proto.CompactTextString(m) } +func (*NodeUnpublishVolumeResponse) ProtoMessage() {} +func (*NodeUnpublishVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } + +// ////// +// ////// +type GetNodeIDRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` +} + +func (m *GetNodeIDRequest) Reset() { *m = GetNodeIDRequest{} } +func (m *GetNodeIDRequest) String() string { return proto.CompactTextString(m) } +func (*GetNodeIDRequest) ProtoMessage() {} +func (*GetNodeIDRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } + +func (m *GetNodeIDRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +type GetNodeIDResponse struct { + // The ID of the node as understood by the SP which SHALL be used by + // CO in subsequent `ControllerPublishVolume`. + // This is a REQUIRED field. + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId" json:"node_id,omitempty"` +} + +func (m *GetNodeIDResponse) Reset() { *m = GetNodeIDResponse{} } +func (m *GetNodeIDResponse) String() string { return proto.CompactTextString(m) } +func (*GetNodeIDResponse) ProtoMessage() {} +func (*GetNodeIDResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } + +func (m *GetNodeIDResponse) GetNodeId() string { + if m != nil { + return m.NodeId + } + return "" +} + +// ////// +// ////// +type NodeProbeRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` +} + +func (m *NodeProbeRequest) Reset() { *m = NodeProbeRequest{} } +func (m *NodeProbeRequest) String() string { return proto.CompactTextString(m) } +func (*NodeProbeRequest) ProtoMessage() {} +func (*NodeProbeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } + +func (m *NodeProbeRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +type NodeProbeResponse struct { +} + +func (m *NodeProbeResponse) Reset() { *m = NodeProbeResponse{} } +func (m *NodeProbeResponse) String() string { return proto.CompactTextString(m) } +func (*NodeProbeResponse) ProtoMessage() {} +func (*NodeProbeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } + +// ////// +// ////// +type NodeGetCapabilitiesRequest struct { + // The API version assumed by the CO. This is a REQUIRED field. + Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` +} + +func (m *NodeGetCapabilitiesRequest) Reset() { *m = NodeGetCapabilitiesRequest{} } +func (m *NodeGetCapabilitiesRequest) String() string { return proto.CompactTextString(m) } +func (*NodeGetCapabilitiesRequest) ProtoMessage() {} +func (*NodeGetCapabilitiesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } + +func (m *NodeGetCapabilitiesRequest) GetVersion() *Version { + if m != nil { + return m.Version + } + return nil +} + +type NodeGetCapabilitiesResponse struct { + // All the capabilities that the node service supports. This field + // is OPTIONAL. + Capabilities []*NodeServiceCapability `protobuf:"bytes,1,rep,name=capabilities" json:"capabilities,omitempty"` +} + +func (m *NodeGetCapabilitiesResponse) Reset() { *m = NodeGetCapabilitiesResponse{} } +func (m *NodeGetCapabilitiesResponse) String() string { return proto.CompactTextString(m) } +func (*NodeGetCapabilitiesResponse) ProtoMessage() {} +func (*NodeGetCapabilitiesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } + +func (m *NodeGetCapabilitiesResponse) GetCapabilities() []*NodeServiceCapability { + if m != nil { + return m.Capabilities + } + return nil +} + +// Specifies a capability of the node service. +type NodeServiceCapability struct { + // Types that are valid to be assigned to Type: + // *NodeServiceCapability_Rpc + Type isNodeServiceCapability_Type `protobuf_oneof:"type"` +} + +func (m *NodeServiceCapability) Reset() { *m = NodeServiceCapability{} } +func (m *NodeServiceCapability) String() string { return proto.CompactTextString(m) } +func (*NodeServiceCapability) ProtoMessage() {} +func (*NodeServiceCapability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } + +type isNodeServiceCapability_Type interface { + isNodeServiceCapability_Type() +} + +type NodeServiceCapability_Rpc struct { + Rpc *NodeServiceCapability_RPC `protobuf:"bytes,1,opt,name=rpc,oneof"` +} + +func (*NodeServiceCapability_Rpc) isNodeServiceCapability_Type() {} + +func (m *NodeServiceCapability) GetType() isNodeServiceCapability_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *NodeServiceCapability) GetRpc() *NodeServiceCapability_RPC { + if x, ok := m.GetType().(*NodeServiceCapability_Rpc); ok { + return x.Rpc + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*NodeServiceCapability) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _NodeServiceCapability_OneofMarshaler, _NodeServiceCapability_OneofUnmarshaler, _NodeServiceCapability_OneofSizer, []interface{}{ + (*NodeServiceCapability_Rpc)(nil), + } +} + +func _NodeServiceCapability_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*NodeServiceCapability) + // type + switch x := m.Type.(type) { + case *NodeServiceCapability_Rpc: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Rpc); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("NodeServiceCapability.Type has unexpected type %T", x) + } + return nil +} + +func _NodeServiceCapability_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*NodeServiceCapability) + switch tag { + case 1: // type.rpc + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(NodeServiceCapability_RPC) + err := b.DecodeMessage(msg) + m.Type = &NodeServiceCapability_Rpc{msg} + return true, err + default: + return false, nil + } +} + +func _NodeServiceCapability_OneofSizer(msg proto.Message) (n int) { + m := msg.(*NodeServiceCapability) + // type + switch x := m.Type.(type) { + case *NodeServiceCapability_Rpc: + s := proto.Size(x.Rpc) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type NodeServiceCapability_RPC struct { + Type NodeServiceCapability_RPC_Type `protobuf:"varint,1,opt,name=type,enum=csi.NodeServiceCapability_RPC_Type" json:"type,omitempty"` +} + +func (m *NodeServiceCapability_RPC) Reset() { *m = NodeServiceCapability_RPC{} } +func (m *NodeServiceCapability_RPC) String() string { return proto.CompactTextString(m) } +func (*NodeServiceCapability_RPC) ProtoMessage() {} +func (*NodeServiceCapability_RPC) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37, 0} } + +func (m *NodeServiceCapability_RPC) GetType() NodeServiceCapability_RPC_Type { + if m != nil { + return m.Type + } + return NodeServiceCapability_RPC_UNKNOWN +} + +func init() { + proto.RegisterType((*GetSupportedVersionsRequest)(nil), "csi.GetSupportedVersionsRequest") + proto.RegisterType((*GetSupportedVersionsResponse)(nil), "csi.GetSupportedVersionsResponse") + proto.RegisterType((*Version)(nil), "csi.Version") + proto.RegisterType((*GetPluginInfoRequest)(nil), "csi.GetPluginInfoRequest") + proto.RegisterType((*GetPluginInfoResponse)(nil), "csi.GetPluginInfoResponse") + proto.RegisterType((*CreateVolumeRequest)(nil), "csi.CreateVolumeRequest") + proto.RegisterType((*CreateVolumeResponse)(nil), "csi.CreateVolumeResponse") + proto.RegisterType((*VolumeCapability)(nil), "csi.VolumeCapability") + proto.RegisterType((*VolumeCapability_BlockVolume)(nil), "csi.VolumeCapability.BlockVolume") + proto.RegisterType((*VolumeCapability_MountVolume)(nil), "csi.VolumeCapability.MountVolume") + proto.RegisterType((*VolumeCapability_AccessMode)(nil), "csi.VolumeCapability.AccessMode") + proto.RegisterType((*CapacityRange)(nil), "csi.CapacityRange") + proto.RegisterType((*VolumeInfo)(nil), "csi.VolumeInfo") + proto.RegisterType((*DeleteVolumeRequest)(nil), "csi.DeleteVolumeRequest") + proto.RegisterType((*DeleteVolumeResponse)(nil), "csi.DeleteVolumeResponse") + proto.RegisterType((*ControllerPublishVolumeRequest)(nil), "csi.ControllerPublishVolumeRequest") + proto.RegisterType((*ControllerPublishVolumeResponse)(nil), "csi.ControllerPublishVolumeResponse") + proto.RegisterType((*ControllerUnpublishVolumeRequest)(nil), "csi.ControllerUnpublishVolumeRequest") + proto.RegisterType((*ControllerUnpublishVolumeResponse)(nil), "csi.ControllerUnpublishVolumeResponse") + proto.RegisterType((*ValidateVolumeCapabilitiesRequest)(nil), "csi.ValidateVolumeCapabilitiesRequest") + proto.RegisterType((*ValidateVolumeCapabilitiesResponse)(nil), "csi.ValidateVolumeCapabilitiesResponse") + proto.RegisterType((*ListVolumesRequest)(nil), "csi.ListVolumesRequest") + proto.RegisterType((*ListVolumesResponse)(nil), "csi.ListVolumesResponse") + proto.RegisterType((*ListVolumesResponse_Entry)(nil), "csi.ListVolumesResponse.Entry") + proto.RegisterType((*GetCapacityRequest)(nil), "csi.GetCapacityRequest") + proto.RegisterType((*GetCapacityResponse)(nil), "csi.GetCapacityResponse") + proto.RegisterType((*ControllerProbeRequest)(nil), "csi.ControllerProbeRequest") + proto.RegisterType((*ControllerProbeResponse)(nil), "csi.ControllerProbeResponse") + proto.RegisterType((*ControllerGetCapabilitiesRequest)(nil), "csi.ControllerGetCapabilitiesRequest") + proto.RegisterType((*ControllerGetCapabilitiesResponse)(nil), "csi.ControllerGetCapabilitiesResponse") + proto.RegisterType((*ControllerServiceCapability)(nil), "csi.ControllerServiceCapability") + proto.RegisterType((*ControllerServiceCapability_RPC)(nil), "csi.ControllerServiceCapability.RPC") + proto.RegisterType((*NodePublishVolumeRequest)(nil), "csi.NodePublishVolumeRequest") + proto.RegisterType((*NodePublishVolumeResponse)(nil), "csi.NodePublishVolumeResponse") + proto.RegisterType((*NodeUnpublishVolumeRequest)(nil), "csi.NodeUnpublishVolumeRequest") + proto.RegisterType((*NodeUnpublishVolumeResponse)(nil), "csi.NodeUnpublishVolumeResponse") + proto.RegisterType((*GetNodeIDRequest)(nil), "csi.GetNodeIDRequest") + proto.RegisterType((*GetNodeIDResponse)(nil), "csi.GetNodeIDResponse") + proto.RegisterType((*NodeProbeRequest)(nil), "csi.NodeProbeRequest") + proto.RegisterType((*NodeProbeResponse)(nil), "csi.NodeProbeResponse") + proto.RegisterType((*NodeGetCapabilitiesRequest)(nil), "csi.NodeGetCapabilitiesRequest") + proto.RegisterType((*NodeGetCapabilitiesResponse)(nil), "csi.NodeGetCapabilitiesResponse") + proto.RegisterType((*NodeServiceCapability)(nil), "csi.NodeServiceCapability") + proto.RegisterType((*NodeServiceCapability_RPC)(nil), "csi.NodeServiceCapability.RPC") + proto.RegisterEnum("csi.VolumeCapability_AccessMode_Mode", VolumeCapability_AccessMode_Mode_name, VolumeCapability_AccessMode_Mode_value) + proto.RegisterEnum("csi.ControllerServiceCapability_RPC_Type", ControllerServiceCapability_RPC_Type_name, ControllerServiceCapability_RPC_Type_value) + proto.RegisterEnum("csi.NodeServiceCapability_RPC_Type", NodeServiceCapability_RPC_Type_name, NodeServiceCapability_RPC_Type_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Identity service + +type IdentityClient interface { + GetSupportedVersions(ctx context.Context, in *GetSupportedVersionsRequest, opts ...grpc.CallOption) (*GetSupportedVersionsResponse, error) + GetPluginInfo(ctx context.Context, in *GetPluginInfoRequest, opts ...grpc.CallOption) (*GetPluginInfoResponse, error) +} + +type identityClient struct { + cc *grpc.ClientConn +} + +func NewIdentityClient(cc *grpc.ClientConn) IdentityClient { + return &identityClient{cc} +} + +func (c *identityClient) GetSupportedVersions(ctx context.Context, in *GetSupportedVersionsRequest, opts ...grpc.CallOption) (*GetSupportedVersionsResponse, error) { + out := new(GetSupportedVersionsResponse) + err := grpc.Invoke(ctx, "/csi.Identity/GetSupportedVersions", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *identityClient) GetPluginInfo(ctx context.Context, in *GetPluginInfoRequest, opts ...grpc.CallOption) (*GetPluginInfoResponse, error) { + out := new(GetPluginInfoResponse) + err := grpc.Invoke(ctx, "/csi.Identity/GetPluginInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Identity service + +type IdentityServer interface { + GetSupportedVersions(context.Context, *GetSupportedVersionsRequest) (*GetSupportedVersionsResponse, error) + GetPluginInfo(context.Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error) +} + +func RegisterIdentityServer(s *grpc.Server, srv IdentityServer) { + s.RegisterService(&_Identity_serviceDesc, srv) +} + +func _Identity_GetSupportedVersions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSupportedVersionsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IdentityServer).GetSupportedVersions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Identity/GetSupportedVersions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IdentityServer).GetSupportedVersions(ctx, req.(*GetSupportedVersionsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Identity_GetPluginInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPluginInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IdentityServer).GetPluginInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Identity/GetPluginInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IdentityServer).GetPluginInfo(ctx, req.(*GetPluginInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Identity_serviceDesc = grpc.ServiceDesc{ + ServiceName: "csi.Identity", + HandlerType: (*IdentityServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetSupportedVersions", + Handler: _Identity_GetSupportedVersions_Handler, + }, + { + MethodName: "GetPluginInfo", + Handler: _Identity_GetPluginInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "csi.proto", +} + +// Client API for Controller service + +type ControllerClient interface { + CreateVolume(ctx context.Context, in *CreateVolumeRequest, opts ...grpc.CallOption) (*CreateVolumeResponse, error) + DeleteVolume(ctx context.Context, in *DeleteVolumeRequest, opts ...grpc.CallOption) (*DeleteVolumeResponse, error) + ControllerPublishVolume(ctx context.Context, in *ControllerPublishVolumeRequest, opts ...grpc.CallOption) (*ControllerPublishVolumeResponse, error) + ControllerUnpublishVolume(ctx context.Context, in *ControllerUnpublishVolumeRequest, opts ...grpc.CallOption) (*ControllerUnpublishVolumeResponse, error) + ValidateVolumeCapabilities(ctx context.Context, in *ValidateVolumeCapabilitiesRequest, opts ...grpc.CallOption) (*ValidateVolumeCapabilitiesResponse, error) + ListVolumes(ctx context.Context, in *ListVolumesRequest, opts ...grpc.CallOption) (*ListVolumesResponse, error) + GetCapacity(ctx context.Context, in *GetCapacityRequest, opts ...grpc.CallOption) (*GetCapacityResponse, error) + ControllerProbe(ctx context.Context, in *ControllerProbeRequest, opts ...grpc.CallOption) (*ControllerProbeResponse, error) + ControllerGetCapabilities(ctx context.Context, in *ControllerGetCapabilitiesRequest, opts ...grpc.CallOption) (*ControllerGetCapabilitiesResponse, error) +} + +type controllerClient struct { + cc *grpc.ClientConn +} + +func NewControllerClient(cc *grpc.ClientConn) ControllerClient { + return &controllerClient{cc} +} + +func (c *controllerClient) CreateVolume(ctx context.Context, in *CreateVolumeRequest, opts ...grpc.CallOption) (*CreateVolumeResponse, error) { + out := new(CreateVolumeResponse) + err := grpc.Invoke(ctx, "/csi.Controller/CreateVolume", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) DeleteVolume(ctx context.Context, in *DeleteVolumeRequest, opts ...grpc.CallOption) (*DeleteVolumeResponse, error) { + out := new(DeleteVolumeResponse) + err := grpc.Invoke(ctx, "/csi.Controller/DeleteVolume", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ControllerPublishVolume(ctx context.Context, in *ControllerPublishVolumeRequest, opts ...grpc.CallOption) (*ControllerPublishVolumeResponse, error) { + out := new(ControllerPublishVolumeResponse) + err := grpc.Invoke(ctx, "/csi.Controller/ControllerPublishVolume", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ControllerUnpublishVolume(ctx context.Context, in *ControllerUnpublishVolumeRequest, opts ...grpc.CallOption) (*ControllerUnpublishVolumeResponse, error) { + out := new(ControllerUnpublishVolumeResponse) + err := grpc.Invoke(ctx, "/csi.Controller/ControllerUnpublishVolume", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ValidateVolumeCapabilities(ctx context.Context, in *ValidateVolumeCapabilitiesRequest, opts ...grpc.CallOption) (*ValidateVolumeCapabilitiesResponse, error) { + out := new(ValidateVolumeCapabilitiesResponse) + err := grpc.Invoke(ctx, "/csi.Controller/ValidateVolumeCapabilities", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ListVolumes(ctx context.Context, in *ListVolumesRequest, opts ...grpc.CallOption) (*ListVolumesResponse, error) { + out := new(ListVolumesResponse) + err := grpc.Invoke(ctx, "/csi.Controller/ListVolumes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) GetCapacity(ctx context.Context, in *GetCapacityRequest, opts ...grpc.CallOption) (*GetCapacityResponse, error) { + out := new(GetCapacityResponse) + err := grpc.Invoke(ctx, "/csi.Controller/GetCapacity", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ControllerProbe(ctx context.Context, in *ControllerProbeRequest, opts ...grpc.CallOption) (*ControllerProbeResponse, error) { + out := new(ControllerProbeResponse) + err := grpc.Invoke(ctx, "/csi.Controller/ControllerProbe", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controllerClient) ControllerGetCapabilities(ctx context.Context, in *ControllerGetCapabilitiesRequest, opts ...grpc.CallOption) (*ControllerGetCapabilitiesResponse, error) { + out := new(ControllerGetCapabilitiesResponse) + err := grpc.Invoke(ctx, "/csi.Controller/ControllerGetCapabilities", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Controller service + +type ControllerServer interface { + CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error) + DeleteVolume(context.Context, *DeleteVolumeRequest) (*DeleteVolumeResponse, error) + ControllerPublishVolume(context.Context, *ControllerPublishVolumeRequest) (*ControllerPublishVolumeResponse, error) + ControllerUnpublishVolume(context.Context, *ControllerUnpublishVolumeRequest) (*ControllerUnpublishVolumeResponse, error) + ValidateVolumeCapabilities(context.Context, *ValidateVolumeCapabilitiesRequest) (*ValidateVolumeCapabilitiesResponse, error) + ListVolumes(context.Context, *ListVolumesRequest) (*ListVolumesResponse, error) + GetCapacity(context.Context, *GetCapacityRequest) (*GetCapacityResponse, error) + ControllerProbe(context.Context, *ControllerProbeRequest) (*ControllerProbeResponse, error) + ControllerGetCapabilities(context.Context, *ControllerGetCapabilitiesRequest) (*ControllerGetCapabilitiesResponse, error) +} + +func RegisterControllerServer(s *grpc.Server, srv ControllerServer) { + s.RegisterService(&_Controller_serviceDesc, srv) +} + +func _Controller_CreateVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateVolumeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).CreateVolume(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/CreateVolume", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).CreateVolume(ctx, req.(*CreateVolumeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_DeleteVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteVolumeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).DeleteVolume(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/DeleteVolume", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).DeleteVolume(ctx, req.(*DeleteVolumeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ControllerPublishVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ControllerPublishVolumeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ControllerPublishVolume(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/ControllerPublishVolume", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ControllerPublishVolume(ctx, req.(*ControllerPublishVolumeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ControllerUnpublishVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ControllerUnpublishVolumeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ControllerUnpublishVolume(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/ControllerUnpublishVolume", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ControllerUnpublishVolume(ctx, req.(*ControllerUnpublishVolumeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ValidateVolumeCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ValidateVolumeCapabilitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ValidateVolumeCapabilities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/ValidateVolumeCapabilities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ValidateVolumeCapabilities(ctx, req.(*ValidateVolumeCapabilitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ListVolumes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListVolumesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ListVolumes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/ListVolumes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ListVolumes(ctx, req.(*ListVolumesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_GetCapacity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCapacityRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).GetCapacity(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/GetCapacity", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).GetCapacity(ctx, req.(*GetCapacityRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ControllerProbe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ControllerProbeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ControllerProbe(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/ControllerProbe", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ControllerProbe(ctx, req.(*ControllerProbeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Controller_ControllerGetCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ControllerGetCapabilitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControllerServer).ControllerGetCapabilities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Controller/ControllerGetCapabilities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControllerServer).ControllerGetCapabilities(ctx, req.(*ControllerGetCapabilitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Controller_serviceDesc = grpc.ServiceDesc{ + ServiceName: "csi.Controller", + HandlerType: (*ControllerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateVolume", + Handler: _Controller_CreateVolume_Handler, + }, + { + MethodName: "DeleteVolume", + Handler: _Controller_DeleteVolume_Handler, + }, + { + MethodName: "ControllerPublishVolume", + Handler: _Controller_ControllerPublishVolume_Handler, + }, + { + MethodName: "ControllerUnpublishVolume", + Handler: _Controller_ControllerUnpublishVolume_Handler, + }, + { + MethodName: "ValidateVolumeCapabilities", + Handler: _Controller_ValidateVolumeCapabilities_Handler, + }, + { + MethodName: "ListVolumes", + Handler: _Controller_ListVolumes_Handler, + }, + { + MethodName: "GetCapacity", + Handler: _Controller_GetCapacity_Handler, + }, + { + MethodName: "ControllerProbe", + Handler: _Controller_ControllerProbe_Handler, + }, + { + MethodName: "ControllerGetCapabilities", + Handler: _Controller_ControllerGetCapabilities_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "csi.proto", +} + +// Client API for Node service + +type NodeClient interface { + NodePublishVolume(ctx context.Context, in *NodePublishVolumeRequest, opts ...grpc.CallOption) (*NodePublishVolumeResponse, error) + NodeUnpublishVolume(ctx context.Context, in *NodeUnpublishVolumeRequest, opts ...grpc.CallOption) (*NodeUnpublishVolumeResponse, error) + GetNodeID(ctx context.Context, in *GetNodeIDRequest, opts ...grpc.CallOption) (*GetNodeIDResponse, error) + NodeProbe(ctx context.Context, in *NodeProbeRequest, opts ...grpc.CallOption) (*NodeProbeResponse, error) + NodeGetCapabilities(ctx context.Context, in *NodeGetCapabilitiesRequest, opts ...grpc.CallOption) (*NodeGetCapabilitiesResponse, error) +} + +type nodeClient struct { + cc *grpc.ClientConn +} + +func NewNodeClient(cc *grpc.ClientConn) NodeClient { + return &nodeClient{cc} +} + +func (c *nodeClient) NodePublishVolume(ctx context.Context, in *NodePublishVolumeRequest, opts ...grpc.CallOption) (*NodePublishVolumeResponse, error) { + out := new(NodePublishVolumeResponse) + err := grpc.Invoke(ctx, "/csi.Node/NodePublishVolume", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeClient) NodeUnpublishVolume(ctx context.Context, in *NodeUnpublishVolumeRequest, opts ...grpc.CallOption) (*NodeUnpublishVolumeResponse, error) { + out := new(NodeUnpublishVolumeResponse) + err := grpc.Invoke(ctx, "/csi.Node/NodeUnpublishVolume", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeClient) GetNodeID(ctx context.Context, in *GetNodeIDRequest, opts ...grpc.CallOption) (*GetNodeIDResponse, error) { + out := new(GetNodeIDResponse) + err := grpc.Invoke(ctx, "/csi.Node/GetNodeID", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeClient) NodeProbe(ctx context.Context, in *NodeProbeRequest, opts ...grpc.CallOption) (*NodeProbeResponse, error) { + out := new(NodeProbeResponse) + err := grpc.Invoke(ctx, "/csi.Node/NodeProbe", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeClient) NodeGetCapabilities(ctx context.Context, in *NodeGetCapabilitiesRequest, opts ...grpc.CallOption) (*NodeGetCapabilitiesResponse, error) { + out := new(NodeGetCapabilitiesResponse) + err := grpc.Invoke(ctx, "/csi.Node/NodeGetCapabilities", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Node service + +type NodeServer interface { + NodePublishVolume(context.Context, *NodePublishVolumeRequest) (*NodePublishVolumeResponse, error) + NodeUnpublishVolume(context.Context, *NodeUnpublishVolumeRequest) (*NodeUnpublishVolumeResponse, error) + GetNodeID(context.Context, *GetNodeIDRequest) (*GetNodeIDResponse, error) + NodeProbe(context.Context, *NodeProbeRequest) (*NodeProbeResponse, error) + NodeGetCapabilities(context.Context, *NodeGetCapabilitiesRequest) (*NodeGetCapabilitiesResponse, error) +} + +func RegisterNodeServer(s *grpc.Server, srv NodeServer) { + s.RegisterService(&_Node_serviceDesc, srv) +} + +func _Node_NodePublishVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodePublishVolumeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodePublishVolume(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Node/NodePublishVolume", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodePublishVolume(ctx, req.(*NodePublishVolumeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Node_NodeUnpublishVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeUnpublishVolumeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodeUnpublishVolume(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Node/NodeUnpublishVolume", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodeUnpublishVolume(ctx, req.(*NodeUnpublishVolumeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Node_GetNodeID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNodeIDRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).GetNodeID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Node/GetNodeID", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).GetNodeID(ctx, req.(*GetNodeIDRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Node_NodeProbe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeProbeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodeProbe(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Node/NodeProbe", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodeProbe(ctx, req.(*NodeProbeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Node_NodeGetCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeGetCapabilitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodeGetCapabilities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/csi.Node/NodeGetCapabilities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodeGetCapabilities(ctx, req.(*NodeGetCapabilitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Node_serviceDesc = grpc.ServiceDesc{ + ServiceName: "csi.Node", + HandlerType: (*NodeServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "NodePublishVolume", + Handler: _Node_NodePublishVolume_Handler, + }, + { + MethodName: "NodeUnpublishVolume", + Handler: _Node_NodeUnpublishVolume_Handler, + }, + { + MethodName: "GetNodeID", + Handler: _Node_GetNodeID_Handler, + }, + { + MethodName: "NodeProbe", + Handler: _Node_NodeProbe_Handler, + }, + { + MethodName: "NodeGetCapabilities", + Handler: _Node_NodeGetCapabilities_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "csi.proto", +} + +func init() { proto.RegisterFile("csi.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 1993 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0x4b, 0x73, 0xe3, 0x58, + 0x15, 0xb6, 0x6c, 0xe7, 0xe1, 0xe3, 0x38, 0xed, 0x5c, 0xe7, 0xa1, 0x28, 0xfd, 0x70, 0xab, 0xa7, + 0x7b, 0x42, 0x15, 0xe3, 0xa2, 0x3c, 0x54, 0xd1, 0xe9, 0x9e, 0x19, 0x48, 0x6c, 0x4f, 0x62, 0x26, + 0x71, 0xa7, 0x14, 0xa7, 0x9b, 0x01, 0xa6, 0x84, 0x62, 0xdf, 0xa4, 0x45, 0xcb, 0x92, 0x47, 0x92, + 0x5d, 0xed, 0x3d, 0x4b, 0x16, 0xec, 0xd8, 0xc1, 0x72, 0xa0, 0x58, 0x02, 0xbf, 0x80, 0xbf, 0x00, + 0xac, 0xd9, 0xf2, 0x0f, 0xa8, 0x62, 0x43, 0xdd, 0x87, 0x64, 0x49, 0x96, 0x1c, 0x3b, 0x93, 0x1e, + 0x66, 0x27, 0x9d, 0xc7, 0x77, 0xcf, 0xe3, 0xde, 0x73, 0xce, 0x95, 0x20, 0xd7, 0x71, 0xf4, 0x4a, + 0xdf, 0xb6, 0x5c, 0x0b, 0x65, 0x3a, 0x8e, 0x2e, 0xdf, 0x83, 0x9d, 0x43, 0xec, 0x9e, 0x0d, 0xfa, + 0x7d, 0xcb, 0x76, 0x71, 0xf7, 0x25, 0xb6, 0x1d, 0xdd, 0x32, 0x1d, 0x05, 0x7f, 0x39, 0xc0, 0x8e, + 0x2b, 0xff, 0x0c, 0xee, 0xc6, 0xb3, 0x9d, 0xbe, 0x65, 0x3a, 0x18, 0x3d, 0x07, 0xe4, 0x78, 0x4c, + 0x75, 0xc8, 0xb9, 0xa2, 0x50, 0xce, 0xec, 0xe6, 0xab, 0x2b, 0x15, 0xb2, 0x16, 0x57, 0x51, 0xd6, + 0x9c, 0x28, 0x88, 0xfc, 0x19, 0x2c, 0xf1, 0x67, 0xb4, 0x0e, 0x0b, 0x3d, 0xed, 0x97, 0x96, 0x2d, + 0x0a, 0x65, 0x61, 0xb7, 0xa0, 0xb0, 0x17, 0x4a, 0xd5, 0x4d, 0xcb, 0x16, 0xd3, 0x9c, 0x4a, 0x5e, + 0x08, 0xb5, 0xaf, 0xb9, 0x9d, 0xd7, 0x62, 0x86, 0x51, 0xe9, 0x8b, 0xfc, 0x09, 0xac, 0x1f, 0x62, + 0xf7, 0xd4, 0x18, 0x5c, 0xe9, 0x66, 0xd3, 0xbc, 0xb4, 0xb8, 0x07, 0xe8, 0x09, 0x2c, 0x71, 0xbb, + 0x28, 0x76, 0xd4, 0x2c, 0x8f, 0x29, 0xff, 0x43, 0x80, 0x8d, 0x08, 0x00, 0xf7, 0x11, 0x41, 0xd6, + 0xd4, 0x7a, 0x98, 0xaa, 0xe7, 0x14, 0xfa, 0x8c, 0x1e, 0xc3, 0xea, 0x10, 0x9b, 0x5d, 0xcb, 0xf6, + 0x9c, 0xa6, 0x26, 0xe6, 0x94, 0x02, 0xa3, 0x7a, 0x6e, 0xd5, 0x61, 0xb9, 0xa7, 0x99, 0xfa, 0x25, + 0x76, 0x5c, 0x31, 0x43, 0x83, 0xb2, 0x4b, 0x57, 0x8f, 0x5d, 0xa8, 0x72, 0xc2, 0x45, 0x1b, 0xa6, + 0x6b, 0x8f, 0x14, 0x5f, 0x53, 0x7a, 0x0e, 0x85, 0x10, 0x0b, 0x15, 0x21, 0xf3, 0x06, 0x8f, 0xb8, + 0x41, 0xe4, 0x91, 0xc4, 0x64, 0xa8, 0x19, 0x03, 0xcc, 0xcd, 0x60, 0x2f, 0xcf, 0xd2, 0x4f, 0x05, + 0xf9, 0xbf, 0x19, 0x28, 0xd5, 0x6c, 0xac, 0xb9, 0xf8, 0xa5, 0x65, 0x0c, 0x7a, 0x78, 0xce, 0xb8, + 0xf8, 0xde, 0xa7, 0x03, 0xde, 0xef, 0xc1, 0x6a, 0x47, 0xeb, 0x6b, 0x1d, 0xdd, 0x1d, 0xa9, 0xb6, + 0x66, 0x5e, 0x61, 0x9a, 0x8a, 0x7c, 0x15, 0x51, 0x88, 0x1a, 0x67, 0x29, 0x84, 0xa3, 0x14, 0x3a, + 0xc1, 0x57, 0xf4, 0x29, 0x94, 0x86, 0xd4, 0x0e, 0x95, 0xd0, 0x2f, 0x74, 0x43, 0x77, 0x75, 0xec, + 0x88, 0x59, 0x1a, 0x9c, 0x0d, 0x66, 0x02, 0xe5, 0xd7, 0x3c, 0xf6, 0x48, 0x41, 0xc3, 0x30, 0x45, + 0xc7, 0x0e, 0x3a, 0x02, 0xe8, 0x6b, 0xb6, 0xd6, 0xc3, 0x2e, 0xb6, 0x1d, 0x71, 0x21, 0x10, 0xdb, + 0x18, 0x67, 0x2b, 0xa7, 0xbe, 0x28, 0x8b, 0x6d, 0x40, 0x17, 0xfd, 0x04, 0x8a, 0x03, 0x07, 0xdb, + 0x6a, 0xc7, 0xc6, 0x5d, 0x6c, 0xba, 0xba, 0x66, 0x38, 0xe2, 0x22, 0xc5, 0xfb, 0x20, 0x11, 0xef, + 0xdc, 0xc1, 0x76, 0x6d, 0x2c, 0xcf, 0x40, 0xef, 0x0c, 0xc2, 0x54, 0xe9, 0x63, 0xb8, 0x13, 0x59, + 0x78, 0x9e, 0xcc, 0x49, 0x07, 0xb0, 0x1e, 0xb7, 0xce, 0x5c, 0xd9, 0x3f, 0x82, 0xf5, 0xb0, 0xfd, + 0x7c, 0x4f, 0x7f, 0x0f, 0xf2, 0x3c, 0x0d, 0xba, 0x79, 0x69, 0xf1, 0x1d, 0x70, 0x27, 0x10, 0x7e, + 0xba, 0x31, 0x61, 0xe8, 0x3f, 0xcb, 0xbf, 0xcb, 0x42, 0x31, 0x9a, 0x19, 0xb4, 0x07, 0x0b, 0x17, + 0x86, 0xd5, 0x79, 0xc3, 0x01, 0x1e, 0xc6, 0xe6, 0xaf, 0x72, 0x40, 0x44, 0x18, 0xf5, 0x28, 0xa5, + 0x30, 0x0d, 0xa2, 0xda, 0xb3, 0x06, 0xa6, 0x4b, 0x6d, 0x4e, 0x54, 0x3d, 0x21, 0x22, 0x63, 0x55, + 0xaa, 0x81, 0xf6, 0x21, 0xaf, 0x75, 0x3a, 0xd8, 0x71, 0xd4, 0x9e, 0xd5, 0xf5, 0xf6, 0x5e, 0x39, + 0x1e, 0x60, 0x9f, 0x0a, 0x9e, 0x58, 0x5d, 0xac, 0x80, 0xe6, 0x3f, 0x4b, 0x05, 0xc8, 0x07, 0xac, + 0x92, 0x0e, 0x21, 0x1f, 0x58, 0x09, 0x6d, 0xc1, 0xd2, 0xa5, 0xa3, 0xba, 0xa3, 0xbe, 0x77, 0xe8, + 0x17, 0x2f, 0x9d, 0xf6, 0xa8, 0x8f, 0xd1, 0x03, 0xc8, 0x53, 0x13, 0xd4, 0x4b, 0x43, 0xbb, 0x72, + 0xc4, 0x74, 0x39, 0xb3, 0x9b, 0x53, 0x80, 0x92, 0x3e, 0x25, 0x14, 0xe9, 0xdf, 0x02, 0xc0, 0x78, + 0x49, 0xb4, 0x07, 0x59, 0x6a, 0x22, 0x41, 0x59, 0xad, 0x3e, 0xbe, 0xce, 0xc4, 0x0a, 0xb5, 0x93, + 0xaa, 0xc8, 0xbf, 0x17, 0x20, 0x4b, 0x31, 0xf2, 0xb0, 0x74, 0xde, 0xfa, 0xac, 0xf5, 0xe2, 0x55, + 0xab, 0x98, 0x42, 0x9b, 0x80, 0xce, 0x9a, 0xad, 0xc3, 0xe3, 0x86, 0xda, 0x7a, 0x51, 0x6f, 0xa8, + 0xaf, 0x94, 0x66, 0xbb, 0xa1, 0x14, 0x05, 0xb4, 0x03, 0x5b, 0x41, 0xba, 0xd2, 0xd8, 0xaf, 0x37, + 0x14, 0xf5, 0x45, 0xeb, 0xf8, 0xf3, 0x62, 0x1a, 0x49, 0xb0, 0x79, 0x72, 0x7e, 0xdc, 0x6e, 0x4e, + 0xf2, 0x32, 0xe8, 0x2e, 0x88, 0x01, 0x1e, 0xc7, 0xe0, 0xb0, 0x59, 0x02, 0x1b, 0xe0, 0xb2, 0x47, + 0xce, 0x5c, 0x38, 0x28, 0xf8, 0x69, 0x20, 0x91, 0x92, 0x5f, 0x41, 0x21, 0x74, 0xf2, 0x49, 0x8d, + 0xb4, 0xf1, 0x97, 0x03, 0xdd, 0xc6, 0x5d, 0xf5, 0x62, 0xe4, 0x62, 0x87, 0x86, 0x21, 0xab, 0x14, + 0x3c, 0xea, 0x01, 0x21, 0x92, 0x98, 0x1a, 0x7a, 0x4f, 0x77, 0xb9, 0x4c, 0x9a, 0xca, 0x00, 0x25, + 0x51, 0x01, 0xf9, 0x6f, 0x02, 0xc0, 0x78, 0x53, 0x12, 0x58, 0xbf, 0xf8, 0x84, 0x60, 0x3d, 0x2a, + 0x83, 0x5d, 0x85, 0xb4, 0xde, 0xe5, 0x07, 0x22, 0xad, 0x77, 0xd1, 0x0f, 0x01, 0x34, 0xd7, 0xb5, + 0xf5, 0x8b, 0x01, 0x51, 0x61, 0xc5, 0xf8, 0x41, 0x64, 0xc3, 0x57, 0xf6, 0x7d, 0x09, 0x5e, 0x27, + 0xc6, 0x2a, 0xe4, 0x34, 0x47, 0xd8, 0x73, 0x9d, 0xc4, 0xff, 0x08, 0x50, 0xaa, 0x63, 0x03, 0xdf, + 0xb4, 0x0e, 0xef, 0x40, 0xce, 0x3b, 0xb1, 0x9e, 0x5b, 0xcb, 0xfc, 0x78, 0x76, 0x63, 0x6b, 0x58, + 0x26, 0x50, 0xc3, 0x62, 0x16, 0x9e, 0xb1, 0x86, 0xdd, 0x46, 0x11, 0xda, 0x84, 0xf5, 0xb0, 0x01, + 0xac, 0x08, 0xc9, 0x7f, 0xc9, 0xc2, 0xfd, 0x9a, 0x65, 0xba, 0xb6, 0x65, 0x18, 0xd8, 0x3e, 0x1d, + 0x5c, 0x18, 0xba, 0xf3, 0xfa, 0x1d, 0x44, 0x67, 0x0b, 0x96, 0x4c, 0xab, 0x4b, 0x59, 0x19, 0x76, + 0x9c, 0xc9, 0x6b, 0xb3, 0x8b, 0x0e, 0x60, 0x2d, 0xda, 0x8c, 0x46, 0x62, 0x96, 0xae, 0x93, 0xd0, + 0x8a, 0x8a, 0xc3, 0x68, 0x09, 0x94, 0x60, 0xd9, 0xc6, 0x5a, 0xd7, 0x32, 0x8d, 0x91, 0xb8, 0x50, + 0x16, 0x76, 0x97, 0x15, 0xff, 0x1d, 0x75, 0x12, 0x5b, 0xcb, 0x53, 0xd6, 0x5a, 0xa6, 0x3a, 0x3f, + 0x5b, 0x86, 0xd0, 0xa5, 0xef, 0x44, 0x60, 0x7f, 0x2f, 0xd1, 0x55, 0xf6, 0x66, 0x59, 0x85, 0xbd, + 0x45, 0x77, 0x3e, 0x77, 0x74, 0x4c, 0xbe, 0x8d, 0x9d, 0x20, 0xd5, 0x60, 0x23, 0x76, 0xb9, 0xb9, + 0xb6, 0xd3, 0xdf, 0x05, 0x78, 0x90, 0xe8, 0x13, 0xef, 0x6f, 0x6f, 0xa0, 0xd4, 0x67, 0x0c, 0x35, + 0xdc, 0xe7, 0x48, 0x58, 0x9e, 0x4f, 0x0f, 0x0b, 0x9f, 0xc6, 0x42, 0x54, 0x52, 0x1d, 0x58, 0x60, + 0xd6, 0xfa, 0x51, 0xba, 0x54, 0x87, 0xcd, 0x78, 0xe1, 0xb9, 0xdc, 0xfa, 0x53, 0x1a, 0xca, 0x63, + 0x9b, 0xce, 0xcd, 0xfe, 0x37, 0x7f, 0x1e, 0x70, 0xcc, 0x7e, 0x65, 0x93, 0xd9, 0xb3, 0x48, 0xc8, + 0xe2, 0xcd, 0xfb, 0x06, 0x6b, 0xca, 0x23, 0x78, 0x38, 0xc5, 0x1a, 0x5e, 0x60, 0xfe, 0x95, 0x86, + 0x87, 0x2f, 0x35, 0x43, 0xef, 0xfa, 0x03, 0x50, 0x70, 0x86, 0xbc, 0xd5, 0x98, 0x26, 0xcc, 0xb5, + 0x99, 0x79, 0xe7, 0x5a, 0x3d, 0xee, 0x34, 0xb3, 0x1c, 0x7c, 0xc4, 0x50, 0xae, 0xf3, 0x67, 0xe6, + 0x03, 0x7d, 0x2b, 0x87, 0xf1, 0xe7, 0x20, 0x4f, 0xb3, 0x88, 0x1f, 0xc7, 0xbb, 0x90, 0xf3, 0xaf, + 0x7f, 0x14, 0x77, 0x59, 0x19, 0x13, 0x90, 0x08, 0x4b, 0x3d, 0xec, 0x38, 0xda, 0x95, 0x87, 0xef, + 0xbd, 0xca, 0xbf, 0x12, 0x00, 0x1d, 0xeb, 0x0e, 0x9f, 0xcb, 0xe6, 0xce, 0x18, 0x19, 0xd7, 0xb4, + 0xb7, 0x2a, 0x36, 0x5d, 0x5b, 0xe7, 0xa3, 0x45, 0x41, 0x81, 0x9e, 0xf6, 0xb6, 0xc1, 0x28, 0x64, + 0x96, 0x70, 0x5c, 0xcd, 0x76, 0x75, 0xf3, 0x4a, 0x75, 0xad, 0x37, 0xd8, 0xe4, 0x07, 0xa2, 0xe0, + 0x51, 0xdb, 0x84, 0x28, 0xff, 0x51, 0x80, 0x52, 0xc8, 0x0c, 0xee, 0xd6, 0x53, 0x58, 0xf2, 0xb0, + 0x59, 0x65, 0xb9, 0x4f, 0xed, 0x88, 0x11, 0xad, 0xb0, 0x24, 0x78, 0xe2, 0xe8, 0x1e, 0x80, 0x89, + 0xdf, 0xba, 0x7c, 0x51, 0xe6, 0x75, 0x8e, 0x50, 0xe8, 0x82, 0xd2, 0x1e, 0x2c, 0xb0, 0x54, 0xcc, + 0x3f, 0xa7, 0xff, 0x3a, 0x0d, 0xe8, 0x10, 0xbb, 0xfe, 0x28, 0x36, 0x67, 0xc8, 0x12, 0xf6, 0x71, + 0x7a, 0xde, 0x7d, 0x7c, 0x18, 0xba, 0x9f, 0xb1, 0x63, 0xf0, 0xbe, 0x77, 0xf7, 0x8d, 0x18, 0x37, + 0xed, 0x7a, 0xf6, 0x35, 0x2f, 0x51, 0x72, 0x1d, 0x4a, 0xa1, 0x05, 0x79, 0xe6, 0x3e, 0x00, 0xa4, + 0x0d, 0x35, 0xdd, 0xd0, 0x2e, 0x0c, 0xe6, 0x29, 0xe1, 0xf2, 0x41, 0x72, 0xcd, 0xe7, 0x78, 0x6a, + 0xf2, 0x8f, 0x60, 0x33, 0xd0, 0x2e, 0x6c, 0xeb, 0x62, 0xde, 0x82, 0x2c, 0x6f, 0xc3, 0xd6, 0x04, + 0x02, 0xaf, 0x52, 0x3f, 0x0e, 0xd6, 0x7d, 0x6e, 0xec, 0x0d, 0x6b, 0x94, 0xac, 0x07, 0xcb, 0xe2, + 0x04, 0x16, 0x77, 0xbe, 0x0e, 0x2b, 0x31, 0xc9, 0x2d, 0x47, 0x4a, 0xfc, 0x19, 0xb6, 0x87, 0x7a, + 0x27, 0x98, 0xe7, 0x90, 0x96, 0xfc, 0xdb, 0x34, 0xec, 0x4c, 0x91, 0x46, 0x4f, 0x21, 0x63, 0xf7, + 0x3b, 0xdc, 0xdc, 0xf7, 0xae, 0x03, 0xaf, 0x28, 0xa7, 0xb5, 0xa3, 0x94, 0x42, 0x54, 0xa4, 0xbf, + 0x0a, 0x90, 0x51, 0x4e, 0x6b, 0xe8, 0x63, 0xc8, 0xfa, 0x77, 0xb0, 0xd5, 0xea, 0x77, 0x66, 0x81, + 0xa8, 0x90, 0x6b, 0x9a, 0x42, 0xd5, 0x64, 0x0b, 0xb2, 0xf4, 0xd2, 0x16, 0xba, 0x40, 0x89, 0xb0, + 0x5e, 0x53, 0x1a, 0xfb, 0xed, 0x86, 0x5a, 0x6f, 0x1c, 0x37, 0xda, 0x0d, 0xf5, 0xe5, 0x8b, 0xe3, + 0xf3, 0x93, 0x46, 0x51, 0x20, 0x37, 0xa1, 0xd3, 0xf3, 0x83, 0xe3, 0xe6, 0xd9, 0x91, 0x7a, 0xde, + 0xf2, 0x9e, 0x38, 0x37, 0x8d, 0x8a, 0xb0, 0x72, 0xdc, 0x3c, 0x6b, 0x73, 0xc2, 0x59, 0x31, 0x43, + 0x28, 0x87, 0x8d, 0xb6, 0x5a, 0xdb, 0x3f, 0xdd, 0xaf, 0x35, 0xdb, 0x9f, 0x17, 0xb3, 0x07, 0x8b, + 0xcc, 0x5e, 0xf9, 0x9f, 0x0b, 0x20, 0xb6, 0xac, 0x2e, 0x7e, 0x77, 0x13, 0x6d, 0x37, 0x7e, 0xbc, + 0x61, 0xc7, 0xec, 0xfb, 0x14, 0x30, 0xc9, 0x80, 0xd9, 0xe7, 0x1a, 0x52, 0x3e, 0x5d, 0xcd, 0xbe, + 0xc2, 0xae, 0xda, 0xd7, 0xdc, 0xd7, 0x74, 0x30, 0xce, 0x29, 0xc0, 0x48, 0xa7, 0x9a, 0xfb, 0x3a, + 0x7e, 0x7e, 0x5e, 0xb8, 0xf9, 0xfc, 0xbc, 0x18, 0x99, 0x9f, 0xbf, 0x88, 0x99, 0x47, 0xd8, 0x64, + 0x5b, 0x9d, 0xee, 0xe3, 0x6c, 0x93, 0xf3, 0x2f, 0xe2, 0x7a, 0xed, 0x32, 0xc5, 0xff, 0x70, 0x3a, + 0xfe, 0xac, 0x2d, 0xf6, 0x56, 0x26, 0xc3, 0x6f, 0xcf, 0xe4, 0xbd, 0x03, 0xdb, 0x31, 0x21, 0xe1, + 0x65, 0xec, 0xab, 0x34, 0x48, 0x84, 0xfb, 0x2e, 0x27, 0xd7, 0xc8, 0x8e, 0xcc, 0x4c, 0xec, 0x48, + 0x35, 0x71, 0x82, 0x1d, 0x9f, 0x8a, 0xff, 0xfb, 0xec, 0x7a, 0x0f, 0x76, 0x62, 0xed, 0xe0, 0x81, + 0x7c, 0x06, 0xc5, 0x43, 0xec, 0x12, 0x89, 0x66, 0x7d, 0xde, 0xfa, 0xff, 0x5d, 0x58, 0x0b, 0xe8, + 0xf2, 0x7a, 0x1f, 0x98, 0xf7, 0x85, 0xe0, 0xbc, 0x4f, 0x56, 0xa2, 0xf9, 0xbc, 0x49, 0x43, 0x2b, + 0xc1, 0x5a, 0x40, 0x97, 0x9b, 0x5e, 0x67, 0x5b, 0xe0, 0x6b, 0x36, 0xb1, 0x2f, 0x58, 0x7c, 0x92, + 0xda, 0xd7, 0x27, 0x91, 0xf6, 0xc5, 0x46, 0x2f, 0xc9, 0xcf, 0xef, 0x75, 0x8d, 0xeb, 0x0f, 0x02, + 0x6c, 0xc4, 0xca, 0xa1, 0x6a, 0xb0, 0x65, 0xdd, 0x4f, 0x06, 0x0c, 0x36, 0xab, 0x33, 0xd6, 0xab, + 0x7e, 0x10, 0xea, 0x55, 0x8f, 0xa6, 0xeb, 0x06, 0xbb, 0x54, 0x29, 0xa6, 0x4b, 0x79, 0x9d, 0xa4, + 0xfa, 0x67, 0x01, 0x96, 0x9b, 0x74, 0xa3, 0xb9, 0xa4, 0x1a, 0xae, 0xc7, 0xfd, 0x8b, 0x41, 0x65, + 0x6f, 0xac, 0x4a, 0xfa, 0x8b, 0x23, 0x3d, 0x9c, 0x22, 0xc1, 0x33, 0x97, 0x42, 0x47, 0x50, 0x08, + 0xfd, 0x96, 0x40, 0xdb, 0x71, 0xbf, 0x2a, 0x18, 0xa0, 0x94, 0xfc, 0x17, 0x43, 0x4e, 0x55, 0xbf, + 0x5a, 0x04, 0x18, 0xf7, 0x69, 0xd4, 0x80, 0x95, 0xe0, 0x37, 0x68, 0x24, 0x26, 0x7d, 0x56, 0x97, + 0xb6, 0x63, 0x38, 0xbe, 0x7d, 0x0d, 0x58, 0x09, 0x7e, 0x45, 0xe2, 0x30, 0x31, 0x5f, 0xb6, 0x38, + 0x4c, 0xec, 0x27, 0xa7, 0x14, 0xba, 0x0c, 0x0d, 0x62, 0xc1, 0x03, 0x88, 0x1e, 0xcd, 0xf0, 0xb9, + 0x44, 0x7a, 0x6f, 0x96, 0x8f, 0x07, 0x72, 0x0a, 0x19, 0xb0, 0x9d, 0x78, 0x41, 0x45, 0x8f, 0x67, + 0xba, 0x4e, 0x4b, 0x4f, 0xae, 0x13, 0xf3, 0x57, 0xb3, 0x40, 0x4a, 0xbe, 0x86, 0xa1, 0x27, 0xb3, + 0xdd, 0x1c, 0xa5, 0xf7, 0xaf, 0x95, 0xf3, 0x17, 0x3c, 0x80, 0x7c, 0xe0, 0x9a, 0x83, 0xb6, 0x26, + 0x2f, 0x3e, 0x0c, 0x52, 0x4c, 0xba, 0x11, 0x31, 0x8c, 0xc0, 0x6c, 0xce, 0x31, 0x26, 0xaf, 0x07, + 0x1c, 0x23, 0x66, 0x8c, 0x97, 0x53, 0xa8, 0x05, 0x77, 0x22, 0x73, 0x35, 0xda, 0x89, 0x66, 0x28, + 0x50, 0xde, 0xa4, 0xbb, 0xf1, 0xcc, 0xf8, 0xb4, 0x45, 0x2a, 0xd0, 0x44, 0xda, 0xe2, 0xeb, 0xdc, + 0x44, 0xda, 0x12, 0x0a, 0x99, 0x9c, 0xaa, 0xfe, 0x26, 0x03, 0x59, 0x52, 0x25, 0x50, 0x9b, 0x57, + 0xd3, 0xd0, 0x2e, 0xb9, 0x37, 0x75, 0x08, 0x91, 0xee, 0x27, 0xb1, 0x7d, 0x67, 0x7e, 0x0a, 0xa5, + 0x98, 0x46, 0x83, 0x1e, 0x5c, 0xd3, 0x0a, 0xa5, 0x72, 0xb2, 0x80, 0x8f, 0xfd, 0x11, 0xe4, 0xfc, + 0x4e, 0x83, 0x36, 0xbc, 0x0c, 0x85, 0xba, 0x96, 0xb4, 0x19, 0x25, 0x07, 0xb5, 0xfd, 0xee, 0xc1, + 0xb5, 0xa3, 0x9d, 0x88, 0x6b, 0x4f, 0x36, 0x19, 0xdf, 0xaf, 0x68, 0x7a, 0xc6, 0x7e, 0x25, 0x24, + 0xa6, 0x9c, 0x2c, 0xe0, 0x61, 0x5f, 0x2c, 0xd2, 0x9f, 0xe3, 0x1f, 0xfe, 0x2f, 0x00, 0x00, 0xff, + 0xff, 0x17, 0x25, 0x65, 0xbe, 0x29, 0x1f, 0x00, 0x00, +}