├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── enhancement.md │ └── support.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── build.yaml │ └── codespell.yml ├── .gitignore ├── CCLA.pdf ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── OWNERS ├── README.md ├── VERSION ├── csi.proto ├── go.mod ├── go.sum ├── lib ├── README.md ├── cxx │ └── Makefile └── go │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── csi.go │ └── csi │ ├── csi.pb.go │ └── csi_grpc.pb.go ├── logo.png └── spec.md /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us improve this project 4 | 5 | --- 6 | 7 | 9 | 10 | 11 | **What happened**: 12 | 13 | **What you expected to happen**: 14 | 15 | **How to reproduce it**: 16 | 17 | **Anything else we need to know?**: 18 | 19 | **Environment**: 20 | - CSI Spec version: 21 | - Others: 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement Request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | 8 | **Is your feature request related to a problem?/Why is this needed** 9 | 10 | 11 | **Describe the solution you'd like in detail** 12 | 13 | 14 | **Describe alternatives you've considered** 15 | 16 | 17 | **Additional context** 18 | 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Support Request 3 | about: Ask questions about this project 4 | 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **What type of PR is this?** 2 | 3 | **What this PR does / why we need it**: 4 | 5 | **Which issue(s) this PR fixes**: 6 | 11 | Fixes # 12 | 13 | **Special notes for your reviewer**: 14 | 15 | **Does this PR introduce an API-breaking change?**: 16 | 21 | ```release-note 22 | none 23 | ``` 24 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build Test 2 | 3 | on: 4 | pull_request: {} 5 | push: {} 6 | 7 | jobs: 8 | 9 | build: 10 | name: Build 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Set up Go 1.x 15 | uses: actions/setup-go@v3 16 | with: 17 | go-version: ^1.19 18 | id: go 19 | 20 | - name: Check out code into the Go module directory 21 | uses: actions/checkout@v3 22 | 23 | - name: Build Test 24 | run: | 25 | touch spec.md # Ensure its timestamp is newer than any generated files 26 | make 27 | git diff --exit-code || (echo "Generated files are out of date. Please run 'make' and commit the changes." && exit 1) 28 | -------------------------------------------------------------------------------- /.github/workflows/codespell.yml: -------------------------------------------------------------------------------- 1 | # GitHub Action to automate the identification of common misspellings in text files. 2 | # https://github.com/codespell-project/actions-codespell 3 | # https://github.com/codespell-project/codespell 4 | name: codespell 5 | on: [push, pull_request] 6 | jobs: 7 | codespell: 8 | name: Check for spelling errors 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - uses: codespell-project/actions-codespell@master 13 | with: 14 | check_filenames: true 15 | skip: ./.git,./.github/workflows/codespell.yml,.git,*.png,*.jpg,*.svg,*.sum,go.sum 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tmp 2 | .DS_Store 3 | .build 4 | csi.a 5 | *.swp 6 | -------------------------------------------------------------------------------- /CCLA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/container-storage-interface/spec/a539b4f9fe4143eeefb8f3e3e069096fa00b61d1/CCLA.pdf -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | This document outlines some of the requirements and conventions for contributing to the Container Storage Interface, including development workflow, commit message formatting, contact points, and other resources to make it easier to get your contribution accepted. 4 | 5 | ## Licence and CLA 6 | 7 | CSI is under [Apache 2.0](LICENSE) and accepts contributions via GitHub pull requests. 8 | 9 | Before contributing to the Container Storage Interface, contributors MUST sign the CLA available [here](https://github.com/container-storage-interface/spec/blob/master/CCLA.pdf). 10 | The CLA MAY be signed on behalf of a company, possibly covering multiple contributors, or as an individual (put "Individual" for "Corporation name"). 11 | The completed CLA MUST be mailed to the CSI Approvers mailing list: container-storage-interface-approvers@googlegroups.com. 12 | 13 | ## Markdown style 14 | 15 | To keep consistency throughout the Markdown files in the CSI spec, all files should be formatted one sentence per line. 16 | This fixes two things: it makes diffing easier with git and it resolves fights about line wrapping length. 17 | For example, this paragraph will span three lines in the Markdown source. 18 | 19 | ## Code style 20 | 21 | This also applies to the code snippets in the markdown files. 22 | 23 | * Please wrap the code at 72 characters. 24 | 25 | ## Comments 26 | 27 | This also applies to the code snippets in the markdown files. 28 | 29 | * End each sentence within a comment with a punctuation mark (please note that we generally prefer periods); this applies to incomplete sentences as well. 30 | * For trailing comments, leave one space between the end of the code and the beginning of the comment. 31 | 32 | ## Git commit 33 | 34 | The "system of record" for the specification is the `spec.md` file and all hand-edits of the specification should happen there. 35 | **DO NOT** manually edit the generated protobufs or generated language bindings. 36 | Once changes to `spec.md` are complete, please run `make` to update generated files. 37 | 38 | **IMPORTANT:** Prior to committing code please run `make` to ensure that your specification changes have landed in all generated files. 39 | 40 | ### Commit Style 41 | 42 | Each commit should represent a single logical (atomic) change: this makes your changes easier to review. 43 | 44 | * Try to avoid unrelated cleanups (e.g., typo fixes or style nits) in the same commit that makes functional changes. 45 | While typo fixes are great, including them in the same commit as functional changes makes the commit history harder to read. 46 | * Developers often make incremental commits to save their progress when working on a change, and then “rewrite history” (e.g., using `git rebase -i`) to create a clean set of commits once the change is ready to be reviewed. 47 | 48 | Simple house-keeping for clean git history. 49 | Read more on [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/) or the Discussion section of [`git-commit(1)`](http://git-scm.com/docs/git-commit). 50 | 51 | * Separate the subject from body with a blank line. 52 | * Limit the subject line to 50 characters. 53 | * Capitalize the subject line. 54 | * Do not end the subject line with a period. 55 | * Use the imperative mood in the subject line. 56 | * Wrap the body at 72 characters. 57 | * Use the body to explain what and why vs. how. 58 | * If there was important/useful/essential conversation or information, copy or include a reference. 59 | * When possible, one keyword to scope the change in the subject (i.e. "README: ...", "tool: ..."). 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | CSI_SPEC := spec.md 4 | CSI_PROTO := csi.proto 5 | ## Build go language bindings 6 | CSI_A := csi.a 7 | CSI_PKG := lib/go/csi 8 | 9 | # This is the target for building the CSI protobuf file. 10 | $(CSI_PROTO): $(CSI_SPEC) Makefile 11 | echo "// Code generated by make; DO NOT EDIT." > "$@" 12 | sed -n -e '/```protobuf$$/,/^```$$/ {//!p;}' $< >> "$@" 13 | 14 | build: check build_cpp build_go 15 | 16 | build_cpp: 17 | $(MAKE) -C lib/cxx 18 | 19 | $(CSI_PKG)/%.pb.go: $(CSI_PROTO) 20 | $(MAKE) -C lib/go 21 | 22 | $(CSI_A): $(CSI_PKG)/*.go 23 | go mod download 24 | go install ./$(CSI_PKG) 25 | go build -o "$@" ./$(CSI_PKG) 26 | 27 | build_go: $(CSI_A) 28 | 29 | clean: 30 | rm $(CSI_A) 31 | $(MAKE) -C lib/go $@ 32 | 33 | clobber: clean 34 | $(MAKE) -C lib/go $@ 35 | rm -f $(CSI_PROTO) 36 | 37 | # check generated files for violation of standards 38 | check: $(CSI_PROTO) 39 | awk '{ if (length > 72) print NR, $$0 }' $? | diff - /dev/null 40 | 41 | .PHONY: clean clobber check build_go build_cpp 42 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - saad-ali # Representing Kubernetes 3 | - bswartz # Representing Kubernetes 4 | - jieyu # Representing Mesos 5 | - jdef # Representing Mesos 6 | - anusha-ragunathan # Representing Docker 7 | - ddebroy # Representing Docker 8 | - julian-hj # Representing Cloud Foundry 9 | - paulcwarren # Representing Cloud Foundry 10 | reviewers: 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Container Storage Interface (CSI) Specification ![build status](https://github.com/container-storage-interface/spec/actions/workflows/build.yaml/badge.svg) 2 | 3 | ![CSI Logo](logo.png) 4 | 5 | This project contains the CSI [specification](spec.md) and [protobuf](csi.proto) files. 6 | 7 | ## CSI Adoption 8 | 9 | ### Container Orchestrators (CO) 10 | 11 | * [Cloud Foundry](https://github.com/cloudfoundry/csi-plugins-release/blob/master/CSI_SUPPORT.md) 12 | * [Kubernetes](https://kubernetes-csi.github.io/docs/) 13 | * [Mesos](http://mesos.apache.org/documentation/latest/csi/) 14 | * [Nomad](https://nomadproject.io/docs/internals/plugins/csi/) 15 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.12.0 2 | -------------------------------------------------------------------------------- /csi.proto: -------------------------------------------------------------------------------- 1 | // Code generated by make; DO NOT EDIT. 2 | syntax = "proto3"; 3 | package csi.v1; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | option go_package = 10 | "github.com/container-storage-interface/spec/lib/go/csi"; 11 | 12 | extend google.protobuf.EnumOptions { 13 | // Indicates that this enum is OPTIONAL and part of an experimental 14 | // API that may be deprecated and eventually removed between minor 15 | // releases. 16 | bool alpha_enum = 1060; 17 | } 18 | extend google.protobuf.EnumValueOptions { 19 | // Indicates that this enum value is OPTIONAL and part of an 20 | // experimental API that may be deprecated and eventually removed 21 | // between minor releases. 22 | bool alpha_enum_value = 1060; 23 | } 24 | extend google.protobuf.FieldOptions { 25 | // Indicates that a field MAY contain information that is sensitive 26 | // and MUST be treated as such (e.g. not logged). 27 | bool csi_secret = 1059; 28 | 29 | // Indicates that this field is OPTIONAL and part of an experimental 30 | // API that may be deprecated and eventually removed between minor 31 | // releases. 32 | bool alpha_field = 1060; 33 | } 34 | extend google.protobuf.MessageOptions { 35 | // Indicates that this message is OPTIONAL and part of an experimental 36 | // API that may be deprecated and eventually removed between minor 37 | // releases. 38 | bool alpha_message = 1060; 39 | } 40 | extend google.protobuf.MethodOptions { 41 | // Indicates that this method is OPTIONAL and part of an experimental 42 | // API that may be deprecated and eventually removed between minor 43 | // releases. 44 | bool alpha_method = 1060; 45 | } 46 | extend google.protobuf.ServiceOptions { 47 | // Indicates that this service is OPTIONAL and part of an experimental 48 | // API that may be deprecated and eventually removed between minor 49 | // releases. 50 | bool alpha_service = 1060; 51 | } 52 | service Identity { 53 | rpc GetPluginInfo(GetPluginInfoRequest) 54 | returns (GetPluginInfoResponse) {} 55 | 56 | rpc GetPluginCapabilities(GetPluginCapabilitiesRequest) 57 | returns (GetPluginCapabilitiesResponse) {} 58 | 59 | rpc Probe (ProbeRequest) 60 | returns (ProbeResponse) {} 61 | } 62 | 63 | service Controller { 64 | rpc CreateVolume (CreateVolumeRequest) 65 | returns (CreateVolumeResponse) {} 66 | 67 | rpc DeleteVolume (DeleteVolumeRequest) 68 | returns (DeleteVolumeResponse) {} 69 | 70 | rpc ControllerPublishVolume (ControllerPublishVolumeRequest) 71 | returns (ControllerPublishVolumeResponse) {} 72 | 73 | rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest) 74 | returns (ControllerUnpublishVolumeResponse) {} 75 | 76 | rpc ValidateVolumeCapabilities (ValidateVolumeCapabilitiesRequest) 77 | returns (ValidateVolumeCapabilitiesResponse) {} 78 | 79 | rpc ListVolumes (ListVolumesRequest) 80 | returns (ListVolumesResponse) {} 81 | 82 | rpc GetCapacity (GetCapacityRequest) 83 | returns (GetCapacityResponse) {} 84 | 85 | rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest) 86 | returns (ControllerGetCapabilitiesResponse) {} 87 | 88 | rpc CreateSnapshot (CreateSnapshotRequest) 89 | returns (CreateSnapshotResponse) {} 90 | 91 | rpc DeleteSnapshot (DeleteSnapshotRequest) 92 | returns (DeleteSnapshotResponse) {} 93 | 94 | rpc ListSnapshots (ListSnapshotsRequest) 95 | returns (ListSnapshotsResponse) {} 96 | 97 | rpc GetSnapshot (GetSnapshotRequest) 98 | returns (GetSnapshotResponse) { 99 | option (alpha_method) = true; 100 | } 101 | 102 | rpc ControllerExpandVolume (ControllerExpandVolumeRequest) 103 | returns (ControllerExpandVolumeResponse) {} 104 | 105 | rpc ControllerGetVolume (ControllerGetVolumeRequest) 106 | returns (ControllerGetVolumeResponse) { 107 | option (alpha_method) = true; 108 | } 109 | 110 | rpc ControllerModifyVolume (ControllerModifyVolumeRequest) 111 | returns (ControllerModifyVolumeResponse) { 112 | option (alpha_method) = true; 113 | } 114 | } 115 | 116 | service GroupController { 117 | rpc GroupControllerGetCapabilities ( 118 | GroupControllerGetCapabilitiesRequest) 119 | returns (GroupControllerGetCapabilitiesResponse) {} 120 | 121 | rpc CreateVolumeGroupSnapshot(CreateVolumeGroupSnapshotRequest) 122 | returns (CreateVolumeGroupSnapshotResponse) { 123 | } 124 | 125 | rpc DeleteVolumeGroupSnapshot(DeleteVolumeGroupSnapshotRequest) 126 | returns (DeleteVolumeGroupSnapshotResponse) { 127 | } 128 | 129 | rpc GetVolumeGroupSnapshot( 130 | GetVolumeGroupSnapshotRequest) 131 | returns (GetVolumeGroupSnapshotResponse) { 132 | } 133 | } 134 | 135 | service SnapshotMetadata { 136 | option (alpha_service) = true; 137 | 138 | rpc GetMetadataAllocated(GetMetadataAllocatedRequest) 139 | returns (stream GetMetadataAllocatedResponse) {} 140 | 141 | rpc GetMetadataDelta(GetMetadataDeltaRequest) 142 | returns (stream GetMetadataDeltaResponse) {} 143 | } 144 | 145 | service Node { 146 | rpc NodeStageVolume (NodeStageVolumeRequest) 147 | returns (NodeStageVolumeResponse) {} 148 | 149 | rpc NodeUnstageVolume (NodeUnstageVolumeRequest) 150 | returns (NodeUnstageVolumeResponse) {} 151 | 152 | rpc NodePublishVolume (NodePublishVolumeRequest) 153 | returns (NodePublishVolumeResponse) {} 154 | 155 | rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest) 156 | returns (NodeUnpublishVolumeResponse) {} 157 | 158 | rpc NodeGetVolumeStats (NodeGetVolumeStatsRequest) 159 | returns (NodeGetVolumeStatsResponse) {} 160 | 161 | 162 | rpc NodeExpandVolume(NodeExpandVolumeRequest) 163 | returns (NodeExpandVolumeResponse) {} 164 | 165 | 166 | rpc NodeGetCapabilities (NodeGetCapabilitiesRequest) 167 | returns (NodeGetCapabilitiesResponse) {} 168 | 169 | rpc NodeGetInfo (NodeGetInfoRequest) 170 | returns (NodeGetInfoResponse) {} 171 | } 172 | message GetPluginInfoRequest { 173 | // Intentionally empty. 174 | } 175 | 176 | message GetPluginInfoResponse { 177 | // The name MUST follow domain name notation format 178 | // (https://tools.ietf.org/html/rfc1035#section-2.3.1). It SHOULD 179 | // include the plugin's host company name and the plugin name, 180 | // to minimize the possibility of collisions. It MUST be 63 181 | // characters or less, beginning and ending with an alphanumeric 182 | // character ([a-z0-9A-Z]) with dashes (-), dots (.), and 183 | // alphanumerics between. This field is REQUIRED. 184 | string name = 1; 185 | 186 | // This field is REQUIRED. Value of this field is opaque to the CO. 187 | string vendor_version = 2; 188 | 189 | // This field is OPTIONAL. Values are opaque to the CO. 190 | map manifest = 3; 191 | } 192 | message GetPluginCapabilitiesRequest { 193 | // Intentionally empty. 194 | } 195 | 196 | message GetPluginCapabilitiesResponse { 197 | // All the capabilities that the controller service supports. This 198 | // field is OPTIONAL. 199 | repeated PluginCapability capabilities = 1; 200 | } 201 | 202 | // Specifies a capability of the plugin. 203 | message PluginCapability { 204 | message Service { 205 | enum Type { 206 | UNKNOWN = 0; 207 | // CONTROLLER_SERVICE indicates that the Plugin provides RPCs for 208 | // the ControllerService. Plugins SHOULD provide this capability. 209 | // In rare cases certain plugins MAY wish to omit the 210 | // ControllerService entirely from their implementation, but such 211 | // SHOULD NOT be the common case. 212 | // The presence of this capability determines whether the CO will 213 | // attempt to invoke the REQUIRED ControllerService RPCs, as well 214 | // as specific RPCs as indicated by ControllerGetCapabilities. 215 | CONTROLLER_SERVICE = 1; 216 | 217 | // VOLUME_ACCESSIBILITY_CONSTRAINTS indicates that the volumes for 218 | // this plugin MAY NOT be equally accessible by all nodes in the 219 | // cluster. The CO MUST use the topology information returned by 220 | // CreateVolumeRequest along with the topology information 221 | // returned by NodeGetInfo to ensure that a given volume is 222 | // accessible from a given node when scheduling workloads. 223 | VOLUME_ACCESSIBILITY_CONSTRAINTS = 2; 224 | 225 | // GROUP_CONTROLLER_SERVICE indicates that the Plugin provides 226 | // RPCs for operating on groups of volumes. Plugins MAY provide 227 | // this capability. 228 | // The presence of this capability determines whether the CO will 229 | // attempt to invoke the REQUIRED GroupController service RPCs, as 230 | // well as specific RPCs as indicated by 231 | // GroupControllerGetCapabilities. 232 | GROUP_CONTROLLER_SERVICE = 3; 233 | 234 | // SNAPSHOT_METADATA_SERVICE indicates that the Plugin provides 235 | // RPCs to retrieve metadata on the allocated blocks of a single 236 | // snapshot, or the changed blocks between a pair of snapshots of 237 | // the same block volume. 238 | // The presence of this capability determines whether the CO will 239 | // attempt to invoke the OPTIONAL SnapshotMetadata service RPCs. 240 | SNAPSHOT_METADATA_SERVICE = 4 [(alpha_enum_value) = true]; 241 | } 242 | Type type = 1; 243 | } 244 | 245 | message VolumeExpansion { 246 | enum Type { 247 | UNKNOWN = 0; 248 | 249 | // ONLINE indicates that volumes may be expanded when published to 250 | // a node. When a Plugin implements this capability it MUST 251 | // implement either the EXPAND_VOLUME controller capability or the 252 | // EXPAND_VOLUME node capability or both. When a plugin supports 253 | // ONLINE volume expansion and also has the EXPAND_VOLUME 254 | // controller capability then the plugin MUST support expansion of 255 | // volumes currently published and available on a node. When a 256 | // plugin supports ONLINE volume expansion and also has the 257 | // EXPAND_VOLUME node capability then the plugin MAY support 258 | // expansion of node-published volume via NodeExpandVolume. 259 | // 260 | // Example 1: Given a shared filesystem volume (e.g. GlusterFs), 261 | // the Plugin may set the ONLINE volume expansion capability and 262 | // implement ControllerExpandVolume but not NodeExpandVolume. 263 | // 264 | // Example 2: Given a block storage volume type (e.g. EBS), the 265 | // Plugin may set the ONLINE volume expansion capability and 266 | // implement both ControllerExpandVolume and NodeExpandVolume. 267 | // 268 | // Example 3: Given a Plugin that supports volume expansion only 269 | // upon a node, the Plugin may set the ONLINE volume 270 | // expansion capability and implement NodeExpandVolume but not 271 | // ControllerExpandVolume. 272 | ONLINE = 1; 273 | 274 | // OFFLINE indicates that volumes currently published and 275 | // available on a node SHALL NOT be expanded via 276 | // ControllerExpandVolume. When a plugin supports OFFLINE volume 277 | // expansion it MUST implement either the EXPAND_VOLUME controller 278 | // capability or both the EXPAND_VOLUME controller capability and 279 | // the EXPAND_VOLUME node capability. 280 | // 281 | // Example 1: Given a block storage volume type (e.g. Azure Disk) 282 | // that does not support expansion of "node-attached" (i.e. 283 | // controller-published) volumes, the Plugin may indicate 284 | // OFFLINE volume expansion support and implement both 285 | // ControllerExpandVolume and NodeExpandVolume. 286 | OFFLINE = 2; 287 | } 288 | Type type = 1; 289 | } 290 | 291 | oneof type { 292 | // Service that the plugin supports. 293 | Service service = 1; 294 | VolumeExpansion volume_expansion = 2; 295 | } 296 | } 297 | message ProbeRequest { 298 | // Intentionally empty. 299 | } 300 | 301 | message ProbeResponse { 302 | // Readiness allows a plugin to report its initialization status back 303 | // to the CO. Initialization for some plugins MAY be time consuming 304 | // and it is important for a CO to distinguish between the following 305 | // cases: 306 | // 307 | // 1) The plugin is in an unhealthy state and MAY need restarting. In 308 | // this case a gRPC error code SHALL be returned. 309 | // 2) The plugin is still initializing, but is otherwise perfectly 310 | // healthy. In this case a successful response SHALL be returned 311 | // with a readiness value of `false`. Calls to the plugin's 312 | // Controller and/or Node services MAY fail due to an incomplete 313 | // initialization state. 314 | // 3) The plugin has finished initializing and is ready to service 315 | // calls to its Controller and/or Node services. A successful 316 | // response is returned with a readiness value of `true`. 317 | // 318 | // This field is OPTIONAL. If not present, the caller SHALL assume 319 | // that the plugin is in a ready state and is accepting calls to its 320 | // Controller and/or Node services (according to the plugin's reported 321 | // capabilities). 322 | .google.protobuf.BoolValue ready = 1; 323 | } 324 | message CreateVolumeRequest { 325 | // The suggested name for the storage space. This field is REQUIRED. 326 | // It serves two purposes: 327 | // 1) Idempotency - This name is generated by the CO to achieve 328 | // idempotency. The Plugin SHOULD ensure that multiple 329 | // `CreateVolume` calls for the same name do not result in more 330 | // than one piece of storage provisioned corresponding to that 331 | // name. If a Plugin is unable to enforce idempotency, the CO's 332 | // error recovery logic could result in multiple (unused) volumes 333 | // being provisioned. 334 | // In the case of error, the CO MUST handle the gRPC error codes 335 | // per the recovery behavior defined in the "CreateVolume Errors" 336 | // section below. 337 | // The CO is responsible for cleaning up volumes it provisioned 338 | // that it no longer needs. If the CO is uncertain whether a volume 339 | // was provisioned or not when a `CreateVolume` call fails, the CO 340 | // MAY call `CreateVolume` again, with the same name, to ensure the 341 | // volume exists and to retrieve the volume's `volume_id` (unless 342 | // otherwise prohibited by "CreateVolume Errors"). 343 | // 2) Suggested name - Some storage systems allow callers to specify 344 | // an identifier by which to refer to the newly provisioned 345 | // storage. If a storage system supports this, it can optionally 346 | // use this name as the identifier for the new volume. 347 | // Any Unicode string that conforms to the length limit is allowed 348 | // except those containing the following banned characters: 349 | // U+0000-U+0008, U+000B, U+000C, U+000E-U+001F, U+007F-U+009F. 350 | // (These are control characters other than commonly used whitespace.) 351 | string name = 1; 352 | 353 | // This field is OPTIONAL. This allows the CO to specify the capacity 354 | // requirement of the volume to be provisioned. If not specified, the 355 | // Plugin MAY choose an implementation-defined capacity range. If 356 | // specified it MUST always be honored, even when creating volumes 357 | // from a source; which MAY force some backends to internally extend 358 | // the volume after creating it. 359 | CapacityRange capacity_range = 2; 360 | 361 | // The capabilities that the provisioned volume MUST have. SP MUST 362 | // provision a volume that will satisfy ALL of the capabilities 363 | // specified in this list. Otherwise SP MUST return the appropriate 364 | // gRPC error code. 365 | // The Plugin MUST assume that the CO MAY use the provisioned volume 366 | // with ANY of the capabilities specified in this list. 367 | // For example, a CO MAY specify two volume capabilities: one with 368 | // access mode SINGLE_NODE_WRITER and another with access mode 369 | // MULTI_NODE_READER_ONLY. In this case, the SP MUST verify that the 370 | // provisioned volume can be used in either mode. 371 | // This also enables the CO to do early validation: If ANY of the 372 | // specified volume capabilities are not supported by the SP, the call 373 | // MUST return the appropriate gRPC error code. 374 | // This field is REQUIRED. 375 | repeated VolumeCapability volume_capabilities = 3; 376 | 377 | // Plugin specific creation-time parameters passed in as opaque 378 | // key-value pairs. This field is OPTIONAL. The Plugin is responsible 379 | // for parsing and validating these parameters. COs will treat 380 | // these as opaque. 381 | map parameters = 4; 382 | 383 | // Secrets required by plugin to complete volume creation request. 384 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 385 | // section on how to use this field. 386 | map secrets = 5 [(csi_secret) = true]; 387 | 388 | // If specified, the new volume will be pre-populated with data from 389 | // this source. This field is OPTIONAL. 390 | VolumeContentSource volume_content_source = 6; 391 | 392 | // Specifies where (regions, zones, racks, etc.) the provisioned 393 | // volume MUST be accessible from. 394 | // An SP SHALL advertise the requirements for topological 395 | // accessibility information in documentation. COs SHALL only specify 396 | // topological accessibility information supported by the SP. 397 | // This field is OPTIONAL. 398 | // This field SHALL NOT be specified unless the SP has the 399 | // VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability. 400 | // If this field is not specified and the SP has the 401 | // VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability, the SP MAY 402 | // choose where the provisioned volume is accessible from. 403 | TopologyRequirement accessibility_requirements = 7; 404 | 405 | // Plugin specific creation-time parameters passed in as opaque 406 | // key-value pairs. These mutable_parameteres MAY also be 407 | // changed during the lifetime of the volume via a subsequent 408 | // `ControllerModifyVolume` RPC. This field is OPTIONAL. 409 | // The Plugin is responsible for parsing and validating these 410 | // parameters. COs will treat these as opaque. 411 | 412 | // Plugins MUST treat these 413 | // as if they take precedence over the parameters field. 414 | // This field SHALL NOT be specified unless the SP has the 415 | // MODIFY_VOLUME plugin capability. 416 | map mutable_parameters = 8 [(alpha_field) = true]; 417 | } 418 | 419 | // Specifies what source the volume will be created from. One of the 420 | // type fields MUST be specified. 421 | message VolumeContentSource { 422 | message SnapshotSource { 423 | // Contains identity information for the existing source snapshot. 424 | // This field is REQUIRED. Plugin is REQUIRED to support creating 425 | // volume from snapshot if it supports the capability 426 | // CREATE_DELETE_SNAPSHOT. 427 | string snapshot_id = 1; 428 | } 429 | 430 | message VolumeSource { 431 | // Contains identity information for the existing source volume. 432 | // This field is REQUIRED. Plugins reporting CLONE_VOLUME 433 | // capability MUST support creating a volume from another volume. 434 | string volume_id = 1; 435 | } 436 | 437 | oneof type { 438 | SnapshotSource snapshot = 1; 439 | VolumeSource volume = 2; 440 | } 441 | } 442 | 443 | message CreateVolumeResponse { 444 | // Contains all attributes of the newly created volume that are 445 | // relevant to the CO along with information required by the Plugin 446 | // to uniquely identify the volume. This field is REQUIRED. 447 | Volume volume = 1; 448 | } 449 | 450 | // Specify a capability of a volume. 451 | message VolumeCapability { 452 | // Indicate that the volume will be accessed via the block device API. 453 | message BlockVolume { 454 | // Intentionally empty, for now. 455 | } 456 | 457 | // Indicate that the volume will be accessed via the filesystem API. 458 | message MountVolume { 459 | // The filesystem type. This field is OPTIONAL. 460 | // An empty string is equal to an unspecified field value. 461 | string fs_type = 1; 462 | 463 | // The mount options that can be used for the volume. This field is 464 | // OPTIONAL. `mount_flags` MAY contain sensitive information. 465 | // Therefore, the CO and the Plugin MUST NOT leak this information 466 | // to untrusted entities. The total size of this repeated field 467 | // SHALL NOT exceed 4 KiB. 468 | repeated string mount_flags = 2; 469 | 470 | // If SP has VOLUME_MOUNT_GROUP node capability and CO provides 471 | // this field then SP MUST ensure that the volume_mount_group 472 | // parameter is passed as the group identifier to the underlying 473 | // operating system mount system call, with the understanding 474 | // that the set of available mount call parameters and/or 475 | // mount implementations may vary across operating systems. 476 | // Additionally, new file and/or directory entries written to 477 | // the underlying filesystem SHOULD be permission-labeled in such a 478 | // manner, unless otherwise modified by a workload, that they are 479 | // both readable and writable by said mount group identifier. 480 | // This is an OPTIONAL field. 481 | string volume_mount_group = 3; 482 | } 483 | 484 | // Specify how a volume can be accessed. 485 | message AccessMode { 486 | enum Mode { 487 | UNKNOWN = 0; 488 | 489 | // Can only be published once as read/write on a single node, at 490 | // any given time. 491 | SINGLE_NODE_WRITER = 1; 492 | 493 | // Can only be published once as readonly on a single node, at 494 | // any given time. 495 | SINGLE_NODE_READER_ONLY = 2; 496 | 497 | // Can be published as readonly at multiple nodes simultaneously. 498 | MULTI_NODE_READER_ONLY = 3; 499 | 500 | // Can be published at multiple nodes simultaneously. Only one of 501 | // the node can be used as read/write. The rest will be readonly. 502 | MULTI_NODE_SINGLE_WRITER = 4; 503 | 504 | // Can be published as read/write at multiple nodes 505 | // simultaneously. 506 | MULTI_NODE_MULTI_WRITER = 5; 507 | 508 | // Can only be published once as read/write at a single workload 509 | // on a single node, at any given time. SHOULD be used instead of 510 | // SINGLE_NODE_WRITER for COs using the experimental 511 | // SINGLE_NODE_MULTI_WRITER capability. 512 | SINGLE_NODE_SINGLE_WRITER = 6 [(alpha_enum_value) = true]; 513 | 514 | // Can be published as read/write at multiple workloads on a 515 | // single node simultaneously. SHOULD be used instead of 516 | // SINGLE_NODE_WRITER for COs using the experimental 517 | // SINGLE_NODE_MULTI_WRITER capability. 518 | SINGLE_NODE_MULTI_WRITER = 7 [(alpha_enum_value) = true]; 519 | } 520 | 521 | // This field is REQUIRED. 522 | Mode mode = 1; 523 | } 524 | 525 | // Specifies what API the volume will be accessed using. One of the 526 | // following fields MUST be specified. 527 | oneof access_type { 528 | BlockVolume block = 1; 529 | MountVolume mount = 2; 530 | } 531 | 532 | // This is a REQUIRED field. 533 | AccessMode access_mode = 3; 534 | } 535 | 536 | // The capacity of the storage space in bytes. To specify an exact size, 537 | // `required_bytes` and `limit_bytes` SHALL be set to the same value. At 538 | // least one of the these fields MUST be specified. 539 | message CapacityRange { 540 | // Volume MUST be at least this big. This field is OPTIONAL. 541 | // A value of 0 is equal to an unspecified field value. 542 | // The value of this field MUST NOT be negative. 543 | int64 required_bytes = 1; 544 | 545 | // Volume MUST not be bigger than this. This field is OPTIONAL. 546 | // A value of 0 is equal to an unspecified field value. 547 | // The value of this field MUST NOT be negative. 548 | int64 limit_bytes = 2; 549 | } 550 | 551 | // Information about a specific volume. 552 | message Volume { 553 | // The capacity of the volume in bytes. This field is OPTIONAL. If not 554 | // set (value of 0), it indicates that the capacity of the volume is 555 | // unknown (e.g., NFS share). 556 | // The value of this field MUST NOT be negative. 557 | int64 capacity_bytes = 1; 558 | 559 | // The identifier for this volume, generated by the plugin. 560 | // This field is REQUIRED. 561 | // This field MUST contain enough information to uniquely identify 562 | // this specific volume vs all other volumes supported by this plugin. 563 | // This field SHALL be used by the CO in subsequent calls to refer to 564 | // this volume. 565 | // The SP is NOT responsible for global uniqueness of volume_id across 566 | // multiple SPs. 567 | string volume_id = 2; 568 | 569 | // Opaque static properties of the volume. SP MAY use this field to 570 | // ensure subsequent volume validation and publishing calls have 571 | // contextual information. 572 | // The contents of this field SHALL be opaque to a CO. 573 | // The contents of this field SHALL NOT be mutable. 574 | // The contents of this field SHALL be safe for the CO to cache. 575 | // The contents of this field SHOULD NOT contain sensitive 576 | // information. 577 | // The contents of this field SHOULD NOT be used for uniquely 578 | // identifying a volume. The `volume_id` alone SHOULD be sufficient to 579 | // identify the volume. 580 | // A volume uniquely identified by `volume_id` SHALL always report the 581 | // same volume_context. 582 | // This field is OPTIONAL and when present MUST be passed to volume 583 | // validation and publishing calls. 584 | map volume_context = 3; 585 | 586 | // If specified, indicates that the volume is not empty and is 587 | // pre-populated with data from the specified source. 588 | // This field is OPTIONAL. 589 | VolumeContentSource content_source = 4; 590 | 591 | // Specifies where (regions, zones, racks, etc.) the provisioned 592 | // volume is accessible from. 593 | // A plugin that returns this field MUST also set the 594 | // VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability. 595 | // An SP MAY specify multiple topologies to indicate the volume is 596 | // accessible from multiple locations. 597 | // COs MAY use this information along with the topology information 598 | // returned by NodeGetInfo to ensure that a given volume is accessible 599 | // from a given node when scheduling workloads. 600 | // This field is OPTIONAL. If it is not specified, the CO MAY assume 601 | // the volume is equally accessible from all nodes in the cluster and 602 | // MAY schedule workloads referencing the volume on any available 603 | // node. 604 | // 605 | // Example 1: 606 | // accessible_topology = {"region": "R1", "zone": "Z2"} 607 | // Indicates a volume accessible only from the "region" "R1" and the 608 | // "zone" "Z2". 609 | // 610 | // Example 2: 611 | // accessible_topology = 612 | // {"region": "R1", "zone": "Z2"}, 613 | // {"region": "R1", "zone": "Z3"} 614 | // Indicates a volume accessible from both "zone" "Z2" and "zone" "Z3" 615 | // in the "region" "R1". 616 | repeated Topology accessible_topology = 5; 617 | } 618 | 619 | message TopologyRequirement { 620 | // Specifies the list of topologies the provisioned volume MUST be 621 | // accessible from. 622 | // This field is OPTIONAL. If TopologyRequirement is specified either 623 | // requisite or preferred or both MUST be specified. 624 | // 625 | // If requisite is specified, the provisioned volume MUST be 626 | // accessible from at least one of the requisite topologies. 627 | // 628 | // Given 629 | // x = number of topologies provisioned volume is accessible from 630 | // n = number of requisite topologies 631 | // The CO MUST ensure n >= 1. The SP MUST ensure x >= 1 632 | // If x==n, then the SP MUST make the provisioned volume available to 633 | // all topologies from the list of requisite topologies. If it is 634 | // unable to do so, the SP MUST fail the CreateVolume call. 635 | // For example, if a volume should be accessible from a single zone, 636 | // and requisite = 637 | // {"region": "R1", "zone": "Z2"} 638 | // then the provisioned volume MUST be accessible from the "region" 639 | // "R1" and the "zone" "Z2". 640 | // Similarly, if a volume should be accessible from two zones, and 641 | // requisite = 642 | // {"region": "R1", "zone": "Z2"}, 643 | // {"region": "R1", "zone": "Z3"} 644 | // then the provisioned volume MUST be accessible from the "region" 645 | // "R1" and both "zone" "Z2" and "zone" "Z3". 646 | // 647 | // If xn, then the SP MUST make the provisioned volume available from 666 | // all topologies from the list of requisite topologies and MAY choose 667 | // the remaining x-n unique topologies from the list of all possible 668 | // topologies. If it is unable to do so, the SP MUST fail the 669 | // CreateVolume call. 670 | // For example, if a volume should be accessible from two zones, and 671 | // requisite = 672 | // {"region": "R1", "zone": "Z2"} 673 | // then the provisioned volume MUST be accessible from the "region" 674 | // "R1" and the "zone" "Z2" and the SP may select the second zone 675 | // independently, e.g. "R1/Z4". 676 | repeated Topology requisite = 1; 677 | 678 | // Specifies the list of topologies the CO would prefer the volume to 679 | // be provisioned in. 680 | // 681 | // This field is OPTIONAL. If TopologyRequirement is specified either 682 | // requisite or preferred or both MUST be specified. 683 | // 684 | // An SP MUST attempt to make the provisioned volume available using 685 | // the preferred topologies in order from first to last. 686 | // 687 | // If requisite is specified, all topologies in preferred list MUST 688 | // also be present in the list of requisite topologies. 689 | // 690 | // If the SP is unable to to make the provisioned volume available 691 | // from any of the preferred topologies, the SP MAY choose a topology 692 | // from the list of requisite topologies. 693 | // If the list of requisite topologies is not specified, then the SP 694 | // MAY choose from the list of all possible topologies. 695 | // If the list of requisite topologies is specified and the SP is 696 | // unable to to make the provisioned volume available from any of the 697 | // requisite topologies it MUST fail the CreateVolume call. 698 | // 699 | // Example 1: 700 | // Given a volume should be accessible from a single zone, and 701 | // requisite = 702 | // {"region": "R1", "zone": "Z2"}, 703 | // {"region": "R1", "zone": "Z3"} 704 | // preferred = 705 | // {"region": "R1", "zone": "Z3"} 706 | // then the SP SHOULD first attempt to make the provisioned volume 707 | // available from "zone" "Z3" in the "region" "R1" and fall back to 708 | // "zone" "Z2" in the "region" "R1" if that is not possible. 709 | // 710 | // Example 2: 711 | // Given a volume should be accessible from a single zone, and 712 | // requisite = 713 | // {"region": "R1", "zone": "Z2"}, 714 | // {"region": "R1", "zone": "Z3"}, 715 | // {"region": "R1", "zone": "Z4"}, 716 | // {"region": "R1", "zone": "Z5"} 717 | // preferred = 718 | // {"region": "R1", "zone": "Z4"}, 719 | // {"region": "R1", "zone": "Z2"} 720 | // then the SP SHOULD first attempt to make the provisioned volume 721 | // accessible from "zone" "Z4" in the "region" "R1" and fall back to 722 | // "zone" "Z2" in the "region" "R1" if that is not possible. If that 723 | // is not possible, the SP may choose between either the "zone" 724 | // "Z3" or "Z5" in the "region" "R1". 725 | // 726 | // Example 3: 727 | // Given a volume should be accessible from TWO zones (because an 728 | // opaque parameter in CreateVolumeRequest, for example, specifies 729 | // the volume is accessible from two zones, aka synchronously 730 | // replicated), and 731 | // requisite = 732 | // {"region": "R1", "zone": "Z2"}, 733 | // {"region": "R1", "zone": "Z3"}, 734 | // {"region": "R1", "zone": "Z4"}, 735 | // {"region": "R1", "zone": "Z5"} 736 | // preferred = 737 | // {"region": "R1", "zone": "Z5"}, 738 | // {"region": "R1", "zone": "Z3"} 739 | // then the SP SHOULD first attempt to make the provisioned volume 740 | // accessible from the combination of the two "zones" "Z5" and "Z3" in 741 | // the "region" "R1". If that's not possible, it should fall back to 742 | // a combination of "Z5" and other possibilities from the list of 743 | // requisite. If that's not possible, it should fall back to a 744 | // combination of "Z3" and other possibilities from the list of 745 | // requisite. If that's not possible, it should fall back to a 746 | // combination of other possibilities from the list of requisite. 747 | repeated Topology preferred = 2; 748 | } 749 | 750 | // Topology is a map of topological domains to topological segments. 751 | // A topological domain is a sub-division of a cluster, like "region", 752 | // "zone", "rack", etc. 753 | // A topological segment is a specific instance of a topological domain, 754 | // like "zone3", "rack3", etc. 755 | // For example {"com.company/zone": "Z1", "com.company/rack": "R3"} 756 | // Valid keys have two segments: an OPTIONAL prefix and name, separated 757 | // by a slash (/), for example: "com.company.example/zone". 758 | // The key name segment is REQUIRED. The prefix is OPTIONAL. 759 | // The key name MUST be 63 characters or less, begin and end with an 760 | // alphanumeric character ([a-z0-9A-Z]), and contain only dashes (-), 761 | // underscores (_), dots (.), or alphanumerics in between, for example 762 | // "zone". 763 | // The key prefix MUST be 63 characters or less, begin and end with a 764 | // lower-case alphanumeric character ([a-z0-9]), contain only 765 | // dashes (-), dots (.), or lower-case alphanumerics in between, and 766 | // follow domain name notation format 767 | // (https://tools.ietf.org/html/rfc1035#section-2.3.1). 768 | // The key prefix SHOULD include the plugin's host company name and/or 769 | // the plugin name, to minimize the possibility of collisions with keys 770 | // from other plugins. 771 | // If a key prefix is specified, it MUST be identical across all 772 | // topology keys returned by the SP (across all RPCs). 773 | // Keys MUST be case-insensitive. Meaning the keys "Zone" and "zone" 774 | // MUST not both exist. 775 | // Each value (topological segment) MUST contain 1 or more strings. 776 | // Each string MUST be 63 characters or less and begin and end with an 777 | // alphanumeric character with '-', '_', '.', or alphanumerics in 778 | // between. 779 | message Topology { 780 | map segments = 1; 781 | } 782 | message DeleteVolumeRequest { 783 | // The ID of the volume to be deprovisioned. 784 | // This field is REQUIRED. 785 | string volume_id = 1; 786 | 787 | // Secrets required by plugin to complete volume deletion request. 788 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 789 | // section on how to use this field. 790 | map secrets = 2 [(csi_secret) = true]; 791 | } 792 | 793 | message DeleteVolumeResponse { 794 | // Intentionally empty. 795 | } 796 | message ControllerPublishVolumeRequest { 797 | // The ID of the volume to be used on a node. 798 | // This field is REQUIRED. 799 | string volume_id = 1; 800 | 801 | // The ID of the node. This field is REQUIRED. The CO SHALL set this 802 | // field to match the node ID returned by `NodeGetInfo`. 803 | string node_id = 2; 804 | 805 | // Volume capability describing how the CO intends to use this volume. 806 | // SP MUST ensure the CO can use the published volume as described. 807 | // Otherwise SP MUST return the appropriate gRPC error code. 808 | // This is a REQUIRED field. 809 | VolumeCapability volume_capability = 3; 810 | 811 | // Indicates SP MUST publish the volume in readonly mode. 812 | // CO MUST set this field to false if SP does not have the 813 | // PUBLISH_READONLY controller capability. 814 | // This is a REQUIRED field. 815 | bool readonly = 4; 816 | 817 | // Secrets required by plugin to complete controller publish volume 818 | // request. This field is OPTIONAL. Refer to the 819 | // `Secrets Requirements` section on how to use this field. 820 | map secrets = 5 [(csi_secret) = true]; 821 | 822 | // Volume context as returned by SP in 823 | // CreateVolumeResponse.Volume.volume_context. 824 | // This field is OPTIONAL and MUST match the volume_context of the 825 | // volume identified by `volume_id`. 826 | map volume_context = 6; 827 | } 828 | 829 | message ControllerPublishVolumeResponse { 830 | // Opaque static publish properties of the volume. SP MAY use this 831 | // field to ensure subsequent `NodeStageVolume` or `NodePublishVolume` 832 | // calls calls have contextual information. 833 | // The contents of this field SHALL be opaque to a CO. 834 | // The contents of this field SHALL NOT be mutable. 835 | // The contents of this field SHALL be safe for the CO to cache. 836 | // The contents of this field SHOULD NOT contain sensitive 837 | // information. 838 | // The contents of this field SHOULD NOT be used for uniquely 839 | // identifying a volume. The `volume_id` alone SHOULD be sufficient to 840 | // identify the volume. 841 | // This field is OPTIONAL and when present MUST be passed to 842 | // subsequent `NodeStageVolume` or `NodePublishVolume` calls 843 | map publish_context = 1; 844 | } 845 | message ControllerUnpublishVolumeRequest { 846 | // The ID of the volume. This field is REQUIRED. 847 | string volume_id = 1; 848 | 849 | // The ID of the node. This field is OPTIONAL. The CO SHOULD set this 850 | // field to match the node ID returned by `NodeGetInfo` or leave it 851 | // unset. If the value is set, the SP MUST unpublish the volume from 852 | // the specified node. If the value is unset, the SP MUST unpublish 853 | // the volume from all nodes it is published to. 854 | string node_id = 2; 855 | 856 | // Secrets required by plugin to complete controller unpublish volume 857 | // request. This SHOULD be the same secrets passed to the 858 | // ControllerPublishVolume call for the specified volume. 859 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 860 | // section on how to use this field. 861 | map secrets = 3 [(csi_secret) = true]; 862 | } 863 | 864 | message ControllerUnpublishVolumeResponse { 865 | // Intentionally empty. 866 | } 867 | message ValidateVolumeCapabilitiesRequest { 868 | // The ID of the volume to check. This field is REQUIRED. 869 | string volume_id = 1; 870 | 871 | // Volume context as returned by SP in 872 | // CreateVolumeResponse.Volume.volume_context. 873 | // This field is OPTIONAL and MUST match the volume_context of the 874 | // volume identified by `volume_id`. 875 | map volume_context = 2; 876 | 877 | // The capabilities that the CO wants to check for the volume. This 878 | // call SHALL return "confirmed" only if all the volume capabilities 879 | // specified below are supported. This field is REQUIRED. 880 | repeated VolumeCapability volume_capabilities = 3; 881 | 882 | // See CreateVolumeRequest.parameters. 883 | // This field is OPTIONAL. 884 | map parameters = 4; 885 | 886 | // Secrets required by plugin to complete volume validation request. 887 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 888 | // section on how to use this field. 889 | map secrets = 5 [(csi_secret) = true]; 890 | 891 | // See CreateVolumeRequest.mutable_parameters. 892 | // This field is OPTIONAL. 893 | map mutable_parameters = 6 [(alpha_field) = true]; 894 | } 895 | 896 | message ValidateVolumeCapabilitiesResponse { 897 | message Confirmed { 898 | // Volume context validated by the plugin. 899 | // This field is OPTIONAL. 900 | map volume_context = 1; 901 | 902 | // Volume capabilities supported by the plugin. 903 | // This field is REQUIRED. 904 | repeated VolumeCapability volume_capabilities = 2; 905 | 906 | // The volume creation parameters validated by the plugin. 907 | // This field is OPTIONAL. 908 | map parameters = 3; 909 | 910 | // The volume creation mutable_parameters validated by the plugin. 911 | // This field is OPTIONAL. 912 | map mutable_parameters = 4 [(alpha_field) = true]; 913 | } 914 | 915 | // Confirmed indicates to the CO the set of capabilities that the 916 | // plugin has validated. This field SHALL only be set to a non-empty 917 | // value for successful validation responses. 918 | // For successful validation responses, the CO SHALL compare the 919 | // fields of this message to the originally requested capabilities in 920 | // order to guard against an older plugin reporting "valid" for newer 921 | // capability fields that it does not yet understand. 922 | // This field is OPTIONAL. 923 | Confirmed confirmed = 1; 924 | 925 | // Message to the CO if `confirmed` above is empty. This field is 926 | // OPTIONAL. 927 | // An empty string is equal to an unspecified field value. 928 | string message = 2; 929 | } 930 | message ListVolumesRequest { 931 | // If specified (non-zero value), the Plugin MUST NOT return more 932 | // entries than this number in the response. If the actual number of 933 | // entries is more than this number, the Plugin MUST set `next_token` 934 | // in the response which can be used to get the next page of entries 935 | // in the subsequent `ListVolumes` call. This field is OPTIONAL. If 936 | // not specified (zero value), it means there is no restriction on the 937 | // number of entries that can be returned. 938 | // The value of this field MUST NOT be negative. 939 | int32 max_entries = 1; 940 | 941 | // A token to specify where to start paginating. Set this field to 942 | // `next_token` returned by a previous `ListVolumes` call to get the 943 | // next page of entries. This field is OPTIONAL. 944 | // An empty string is equal to an unspecified field value. 945 | string starting_token = 2; 946 | } 947 | 948 | message ListVolumesResponse { 949 | message VolumeStatus{ 950 | // A list of all `node_id` of nodes that the volume in this entry 951 | // is controller published on. 952 | // This field is OPTIONAL. If it is not specified and the SP has 953 | // the LIST_VOLUMES_PUBLISHED_NODES controller capability, the CO 954 | // MAY assume the volume is not controller published to any nodes. 955 | // If the field is not specified and the SP does not have the 956 | // LIST_VOLUMES_PUBLISHED_NODES controller capability, the CO MUST 957 | // not interpret this field. 958 | // published_node_ids MAY include nodes not published to or 959 | // reported by the SP. The CO MUST be resilient to that. 960 | repeated string published_node_ids = 1; 961 | 962 | // Information about the current condition of the volume. 963 | // This field is OPTIONAL. 964 | // This field MUST be specified if the 965 | // VOLUME_CONDITION controller capability is supported. 966 | VolumeCondition volume_condition = 2 [(alpha_field) = true]; 967 | } 968 | 969 | message Entry { 970 | // This field is REQUIRED 971 | Volume volume = 1; 972 | 973 | // This field is OPTIONAL. This field MUST be specified if the 974 | // LIST_VOLUMES_PUBLISHED_NODES controller capability is 975 | // supported. 976 | VolumeStatus status = 2; 977 | } 978 | 979 | repeated Entry entries = 1; 980 | 981 | // This token allows you to get the next page of entries for 982 | // `ListVolumes` request. If the number of entries is larger than 983 | // `max_entries`, use the `next_token` as a value for the 984 | // `starting_token` field in the next `ListVolumes` request. This 985 | // field is OPTIONAL. 986 | // An empty string is equal to an unspecified field value. 987 | string next_token = 2; 988 | } 989 | message ControllerGetVolumeRequest { 990 | option (alpha_message) = true; 991 | 992 | // The ID of the volume to fetch current volume information for. 993 | // This field is REQUIRED. 994 | string volume_id = 1; 995 | } 996 | 997 | message ControllerGetVolumeResponse { 998 | option (alpha_message) = true; 999 | 1000 | message VolumeStatus{ 1001 | // A list of all the `node_id` of nodes that this volume is 1002 | // controller published on. 1003 | // This field is OPTIONAL. 1004 | // This field MUST be specified if the LIST_VOLUMES_PUBLISHED_NODES 1005 | // controller capability is supported. 1006 | // published_node_ids MAY include nodes not published to or 1007 | // reported by the SP. The CO MUST be resilient to that. 1008 | repeated string published_node_ids = 1; 1009 | 1010 | // Information about the current condition of the volume. 1011 | // This field is OPTIONAL. 1012 | // This field MUST be specified if the 1013 | // VOLUME_CONDITION controller capability is supported. 1014 | VolumeCondition volume_condition = 2; 1015 | } 1016 | 1017 | // This field is REQUIRED 1018 | Volume volume = 1; 1019 | 1020 | // This field is REQUIRED. 1021 | VolumeStatus status = 2; 1022 | } 1023 | message ControllerModifyVolumeRequest { 1024 | option (alpha_message) = true; 1025 | 1026 | // Contains identity information for the existing volume. 1027 | // This field is REQUIRED. 1028 | string volume_id = 1; 1029 | 1030 | // Secrets required by plugin to complete modify volume request. 1031 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1032 | // section on how to use this field. 1033 | map secrets = 2 [(csi_secret) = true]; 1034 | 1035 | // Plugin specific volume attributes to mutate, passed in as 1036 | // opaque key-value pairs. 1037 | // This field is REQUIRED. The Plugin is responsible for 1038 | // parsing and validating these parameters. COs will treat these 1039 | // as opaque. The CO SHOULD specify the intended values of all mutable 1040 | // parameters it intends to modify. SPs MUST NOT modify volumes based 1041 | // on the absence of keys, only keys that are specified should result 1042 | // in modifications to the volume. 1043 | map mutable_parameters = 3; 1044 | } 1045 | 1046 | message ControllerModifyVolumeResponse { 1047 | option (alpha_message) = true; 1048 | } 1049 | 1050 | message GetCapacityRequest { 1051 | // If specified, the Plugin SHALL report the capacity of the storage 1052 | // that can be used to provision volumes that satisfy ALL of the 1053 | // specified `volume_capabilities`. These are the same 1054 | // `volume_capabilities` the CO will use in `CreateVolumeRequest`. 1055 | // This field is OPTIONAL. 1056 | repeated VolumeCapability volume_capabilities = 1; 1057 | 1058 | // If specified, the Plugin SHALL report the capacity of the storage 1059 | // that can be used to provision volumes with the given Plugin 1060 | // specific `parameters`. These are the same `parameters` the CO will 1061 | // use in `CreateVolumeRequest`. This field is OPTIONAL. 1062 | map parameters = 2; 1063 | 1064 | // If specified, the Plugin SHALL report the capacity of the storage 1065 | // that can be used to provision volumes that in the specified 1066 | // `accessible_topology`. This is the same as the 1067 | // `accessible_topology` the CO returns in a `CreateVolumeResponse`. 1068 | // This field is OPTIONAL. This field SHALL NOT be set unless the 1069 | // plugin advertises the VOLUME_ACCESSIBILITY_CONSTRAINTS capability. 1070 | Topology accessible_topology = 3; 1071 | } 1072 | 1073 | message GetCapacityResponse { 1074 | // The available capacity, in bytes, of the storage that can be used 1075 | // to provision volumes. If `volume_capabilities` or `parameters` is 1076 | // specified in the request, the Plugin SHALL take those into 1077 | // consideration when calculating the available capacity of the 1078 | // storage. This field is REQUIRED. 1079 | // The value of this field MUST NOT be negative. 1080 | int64 available_capacity = 1; 1081 | 1082 | // The largest size that may be used in a 1083 | // CreateVolumeRequest.capacity_range.required_bytes field 1084 | // to create a volume with the same parameters as those in 1085 | // GetCapacityRequest. 1086 | // 1087 | // If `volume_capabilities` or `parameters` is 1088 | // specified in the request, the Plugin SHALL take those into 1089 | // consideration when calculating the minimum volume size of the 1090 | // storage. 1091 | // 1092 | // This field is OPTIONAL. MUST NOT be negative. 1093 | // The Plugin SHOULD provide a value for this field if it has 1094 | // a maximum size for individual volumes and leave it unset 1095 | // otherwise. COs MAY use it to make decision about 1096 | // where to create volumes. 1097 | google.protobuf.Int64Value maximum_volume_size = 2; 1098 | 1099 | // The smallest size that may be used in a 1100 | // CreateVolumeRequest.capacity_range.limit_bytes field 1101 | // to create a volume with the same parameters as those in 1102 | // GetCapacityRequest. 1103 | // 1104 | // If `volume_capabilities` or `parameters` is 1105 | // specified in the request, the Plugin SHALL take those into 1106 | // consideration when calculating the maximum volume size of the 1107 | // storage. 1108 | // 1109 | // This field is OPTIONAL. MUST NOT be negative. 1110 | // The Plugin SHOULD provide a value for this field if it has 1111 | // a minimum size for individual volumes and leave it unset 1112 | // otherwise. COs MAY use it to make decision about 1113 | // where to create volumes. 1114 | google.protobuf.Int64Value minimum_volume_size = 3 1115 | [(alpha_field) = true]; 1116 | } 1117 | message ControllerGetCapabilitiesRequest { 1118 | // Intentionally empty. 1119 | } 1120 | 1121 | message ControllerGetCapabilitiesResponse { 1122 | // All the capabilities that the controller service supports. This 1123 | // field is OPTIONAL. 1124 | repeated ControllerServiceCapability capabilities = 1; 1125 | } 1126 | 1127 | // Specifies a capability of the controller service. 1128 | message ControllerServiceCapability { 1129 | message RPC { 1130 | enum Type { 1131 | UNKNOWN = 0; 1132 | CREATE_DELETE_VOLUME = 1; 1133 | PUBLISH_UNPUBLISH_VOLUME = 2; 1134 | LIST_VOLUMES = 3; 1135 | GET_CAPACITY = 4; 1136 | // Currently the only way to consume a snapshot is to create 1137 | // a volume from it. Therefore plugins supporting 1138 | // CREATE_DELETE_SNAPSHOT MUST support creating volume from 1139 | // snapshot. 1140 | CREATE_DELETE_SNAPSHOT = 5; 1141 | LIST_SNAPSHOTS = 6; 1142 | 1143 | // Plugins supporting volume cloning at the storage level MAY 1144 | // report this capability. The source volume MUST be managed by 1145 | // the same plugin. Not all volume sources and parameters 1146 | // combinations MAY work. 1147 | CLONE_VOLUME = 7; 1148 | 1149 | // Indicates the SP supports ControllerPublishVolume.readonly 1150 | // field. 1151 | PUBLISH_READONLY = 8; 1152 | 1153 | // See VolumeExpansion for details. 1154 | EXPAND_VOLUME = 9; 1155 | 1156 | // Indicates the SP supports the 1157 | // ListVolumesResponse.entry.published_node_ids field and the 1158 | // ControllerGetVolumeResponse.published_node_ids field. 1159 | // The SP MUST also support PUBLISH_UNPUBLISH_VOLUME. 1160 | LIST_VOLUMES_PUBLISHED_NODES = 10; 1161 | 1162 | // Indicates that the Controller service can report volume 1163 | // conditions. 1164 | // An SP MAY implement `VolumeCondition` in only the Controller 1165 | // Plugin, only the Node Plugin, or both. 1166 | // If `VolumeCondition` is implemented in both the Controller and 1167 | // Node Plugins, it SHALL report from different perspectives. 1168 | // If for some reason Controller and Node Plugins report 1169 | // misaligned volume conditions, CO SHALL assume the worst case 1170 | // is the truth. 1171 | // Note that, for alpha, `VolumeCondition` is intended be 1172 | // informative for humans only, not for automation. 1173 | VOLUME_CONDITION = 11 [(alpha_enum_value) = true]; 1174 | 1175 | // Indicates the SP supports the ControllerGetVolume RPC. 1176 | // This enables COs to, for example, fetch per volume 1177 | // condition after a volume is provisioned. 1178 | GET_VOLUME = 12 [(alpha_enum_value) = true]; 1179 | 1180 | // Indicates the SP supports the SINGLE_NODE_SINGLE_WRITER and/or 1181 | // SINGLE_NODE_MULTI_WRITER access modes. 1182 | // These access modes are intended to replace the 1183 | // SINGLE_NODE_WRITER access mode to clarify the number of writers 1184 | // for a volume on a single node. Plugins MUST accept and allow 1185 | // use of the SINGLE_NODE_WRITER access mode when either 1186 | // SINGLE_NODE_SINGLE_WRITER and/or SINGLE_NODE_MULTI_WRITER are 1187 | // supported, in order to permit older COs to continue working. 1188 | SINGLE_NODE_MULTI_WRITER = 13 [(alpha_enum_value) = true]; 1189 | 1190 | // Indicates the SP supports modifying volume with mutable 1191 | // parameters. See ControllerModifyVolume for details. 1192 | MODIFY_VOLUME = 14 [(alpha_enum_value) = true]; 1193 | 1194 | // Indicates the SP supports the GetSnapshot RPC. 1195 | // This enables COs to fetch an existing snapshot. 1196 | GET_SNAPSHOT = 15 [(alpha_enum_value) = true]; 1197 | } 1198 | 1199 | Type type = 1; 1200 | } 1201 | 1202 | oneof type { 1203 | // RPC that the controller supports. 1204 | RPC rpc = 1; 1205 | } 1206 | } 1207 | message CreateSnapshotRequest { 1208 | // The ID of the source volume to be snapshotted. 1209 | // This field is REQUIRED. 1210 | string source_volume_id = 1; 1211 | 1212 | // The suggested name for the snapshot. This field is REQUIRED for 1213 | // idempotency. 1214 | // Any Unicode string that conforms to the length limit is allowed 1215 | // except those containing the following banned characters: 1216 | // U+0000-U+0008, U+000B, U+000C, U+000E-U+001F, U+007F-U+009F. 1217 | // (These are control characters other than commonly used whitespace.) 1218 | string name = 2; 1219 | 1220 | // Secrets required by plugin to complete snapshot creation request. 1221 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1222 | // section on how to use this field. 1223 | map secrets = 3 [(csi_secret) = true]; 1224 | 1225 | // Plugin specific parameters passed in as opaque key-value pairs. 1226 | // This field is OPTIONAL. The Plugin is responsible for parsing and 1227 | // validating these parameters. COs will treat these as opaque. 1228 | // Use cases for opaque parameters: 1229 | // - Specify a policy to automatically clean up the snapshot. 1230 | // - Specify an expiration date for the snapshot. 1231 | // - Specify whether the snapshot is readonly or read/write. 1232 | // - Specify if the snapshot should be replicated to some place. 1233 | // - Specify primary or secondary for replication systems that 1234 | // support snapshotting only on primary. 1235 | map parameters = 4; 1236 | } 1237 | 1238 | message CreateSnapshotResponse { 1239 | // Contains all attributes of the newly created snapshot that are 1240 | // relevant to the CO along with information required by the Plugin 1241 | // to uniquely identify the snapshot. This field is REQUIRED. 1242 | Snapshot snapshot = 1; 1243 | } 1244 | 1245 | // Information about a specific snapshot. 1246 | message Snapshot { 1247 | // This is the complete size of the snapshot in bytes. The purpose of 1248 | // this field is to give CO guidance on how much space is needed to 1249 | // create a volume from this snapshot. The size of the volume MUST NOT 1250 | // be less than the size of the source snapshot. This field is 1251 | // OPTIONAL. If this field is not set, it indicates that this size is 1252 | // unknown. The value of this field MUST NOT be negative and a size of 1253 | // zero means it is unspecified. 1254 | int64 size_bytes = 1; 1255 | 1256 | // The identifier for this snapshot, generated by the plugin. 1257 | // This field is REQUIRED. 1258 | // This field MUST contain enough information to uniquely identify 1259 | // this specific snapshot vs all other snapshots supported by this 1260 | // plugin. 1261 | // This field SHALL be used by the CO in subsequent calls to refer to 1262 | // this snapshot. 1263 | // The SP is NOT responsible for global uniqueness of snapshot_id 1264 | // across multiple SPs. 1265 | string snapshot_id = 2; 1266 | 1267 | // Identity information for the source volume. Note that creating a 1268 | // snapshot from a snapshot is not supported here so the source has to 1269 | // be a volume. This field is REQUIRED. 1270 | string source_volume_id = 3; 1271 | 1272 | // Timestamp when the point-in-time snapshot is taken on the storage 1273 | // system. This field is REQUIRED. 1274 | .google.protobuf.Timestamp creation_time = 4; 1275 | 1276 | // Indicates if a snapshot is ready to use as a 1277 | // `volume_content_source` in a `CreateVolumeRequest`. The default 1278 | // value is false. This field is REQUIRED. 1279 | bool ready_to_use = 5; 1280 | 1281 | // The ID of the volume group snapshot that this snapshot is part of. 1282 | // It uniquely identifies the group snapshot on the storage system. 1283 | // This field is OPTIONAL. 1284 | // If this snapshot is a member of a volume group snapshot, and it 1285 | // MUST NOT be deleted as a stand alone snapshot, then the SP 1286 | // MUST provide the ID of the volume group snapshot in this field. 1287 | // If provided, CO MUST use this field in subsequent volume group 1288 | // snapshot operations to indicate that this snapshot is part of the 1289 | // specified group snapshot. 1290 | // If not provided, CO SHALL treat the snapshot as independent, 1291 | // and SP SHALL allow it to be deleted separately. 1292 | // If this message is inside a VolumeGroupSnapshot message, the value 1293 | // MUST be the same as the group_snapshot_id in that message. 1294 | string group_snapshot_id = 6; 1295 | } 1296 | message DeleteSnapshotRequest { 1297 | // The ID of the snapshot to be deleted. 1298 | // This field is REQUIRED. 1299 | string snapshot_id = 1; 1300 | 1301 | // Secrets required by plugin to complete snapshot deletion request. 1302 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1303 | // section on how to use this field. 1304 | map secrets = 2 [(csi_secret) = true]; 1305 | } 1306 | 1307 | message DeleteSnapshotResponse {} 1308 | // List all snapshots on the storage system regardless of how they were 1309 | // created. 1310 | message ListSnapshotsRequest { 1311 | // If specified (non-zero value), the Plugin MUST NOT return more 1312 | // entries than this number in the response. If the actual number of 1313 | // entries is more than this number, the Plugin MUST set `next_token` 1314 | // in the response which can be used to get the next page of entries 1315 | // in the subsequent `ListSnapshots` call. This field is OPTIONAL. If 1316 | // not specified (zero value), it means there is no restriction on the 1317 | // number of entries that can be returned. 1318 | // The value of this field MUST NOT be negative. 1319 | int32 max_entries = 1; 1320 | 1321 | // A token to specify where to start paginating. Set this field to 1322 | // `next_token` returned by a previous `ListSnapshots` call to get the 1323 | // next page of entries. This field is OPTIONAL. 1324 | // An empty string is equal to an unspecified field value. 1325 | string starting_token = 2; 1326 | 1327 | // Identity information for the source volume. This field is OPTIONAL. 1328 | // It can be used to list snapshots by volume. 1329 | string source_volume_id = 3; 1330 | 1331 | // Identity information for a specific snapshot. This field is 1332 | // OPTIONAL. It can be used to list only a specific snapshot. 1333 | // ListSnapshots will return with current snapshot information 1334 | // and will not block if the snapshot is being processed after 1335 | // it is cut. 1336 | string snapshot_id = 4; 1337 | 1338 | // Secrets required by plugin to complete ListSnapshot request. 1339 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1340 | // section on how to use this field. 1341 | map secrets = 5 [(csi_secret) = true]; 1342 | } 1343 | 1344 | message ListSnapshotsResponse { 1345 | message Entry { 1346 | Snapshot snapshot = 1; 1347 | } 1348 | 1349 | repeated Entry entries = 1; 1350 | 1351 | // This token allows you to get the next page of entries for 1352 | // `ListSnapshots` request. If the number of entries is larger than 1353 | // `max_entries`, use the `next_token` as a value for the 1354 | // `starting_token` field in the next `ListSnapshots` request. This 1355 | // field is OPTIONAL. 1356 | // An empty string is equal to an unspecified field value. 1357 | string next_token = 2; 1358 | } 1359 | message GetSnapshotRequest { 1360 | option (alpha_message) = true; 1361 | 1362 | // The ID of the snapshot to fetch current snapshot information for. 1363 | // This field is REQUIRED. 1364 | string snapshot_id = 1; 1365 | 1366 | // Secrets required by plugin to complete GetSnapshot request. 1367 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1368 | // section on how to use this field. 1369 | map secrets = 2 [(csi_secret) = true]; 1370 | } 1371 | 1372 | message GetSnapshotResponse { 1373 | option (alpha_message) = true; 1374 | 1375 | // This field is REQUIRED 1376 | Snapshot snapshot = 1; 1377 | } 1378 | message ControllerExpandVolumeRequest { 1379 | // The ID of the volume to expand. This field is REQUIRED. 1380 | string volume_id = 1; 1381 | 1382 | // This allows CO to specify the capacity requirements of the volume 1383 | // after expansion. This field is REQUIRED. 1384 | CapacityRange capacity_range = 2; 1385 | 1386 | // Secrets required by the plugin for expanding the volume. 1387 | // This field is OPTIONAL. 1388 | map secrets = 3 [(csi_secret) = true]; 1389 | 1390 | // Volume capability describing how the CO intends to use this volume. 1391 | // This allows SP to determine if volume is being used as a block 1392 | // device or mounted file system. For example - if volume is 1393 | // being used as a block device - the SP MAY set 1394 | // node_expansion_required to false in ControllerExpandVolumeResponse 1395 | // to skip invocation of NodeExpandVolume on the node by the CO. 1396 | // This is an OPTIONAL field. 1397 | VolumeCapability volume_capability = 4; 1398 | } 1399 | 1400 | message ControllerExpandVolumeResponse { 1401 | // Capacity of volume after expansion. This field is REQUIRED. 1402 | int64 capacity_bytes = 1; 1403 | 1404 | // Whether node expansion is required for the volume. When true 1405 | // the CO MUST make NodeExpandVolume RPC call on the node. This field 1406 | // is REQUIRED. 1407 | bool node_expansion_required = 2; 1408 | } 1409 | message NodeStageVolumeRequest { 1410 | // The ID of the volume to publish. This field is REQUIRED. 1411 | string volume_id = 1; 1412 | 1413 | // The CO SHALL set this field to the value returned by 1414 | // `ControllerPublishVolume` if the corresponding Controller Plugin 1415 | // has `PUBLISH_UNPUBLISH_VOLUME` controller capability, and SHALL be 1416 | // left unset if the corresponding Controller Plugin does not have 1417 | // this capability. This is an OPTIONAL field. 1418 | map publish_context = 2; 1419 | 1420 | // The path to which the volume MAY be staged. It MUST be an 1421 | // absolute path in the root filesystem of the process serving this 1422 | // request, and MUST be a directory. The CO SHALL ensure that there 1423 | // is only one `staging_target_path` per volume. The CO SHALL ensure 1424 | // that the path is directory and that the process serving the 1425 | // request has `read` and `write` permission to that directory. The 1426 | // CO SHALL be responsible for creating the directory if it does not 1427 | // exist. 1428 | // This is a REQUIRED field. 1429 | // This field overrides the general CSI size limit. 1430 | // SP SHOULD support the maximum path length allowed by the operating 1431 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1432 | // length of at least 128 bytes. 1433 | string staging_target_path = 3; 1434 | 1435 | // Volume capability describing how the CO intends to use this volume. 1436 | // SP MUST ensure the CO can use the staged volume as described. 1437 | // Otherwise SP MUST return the appropriate gRPC error code. 1438 | // This is a REQUIRED field. 1439 | VolumeCapability volume_capability = 4; 1440 | 1441 | // Secrets required by plugin to complete node stage volume request. 1442 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1443 | // section on how to use this field. 1444 | map secrets = 5 [(csi_secret) = true]; 1445 | 1446 | // Volume context as returned by SP in 1447 | // CreateVolumeResponse.Volume.volume_context. 1448 | // This field is OPTIONAL and MUST match the volume_context of the 1449 | // volume identified by `volume_id`. 1450 | map volume_context = 6; 1451 | } 1452 | 1453 | message NodeStageVolumeResponse { 1454 | // Intentionally empty. 1455 | } 1456 | message NodeUnstageVolumeRequest { 1457 | // The ID of the volume. This field is REQUIRED. 1458 | string volume_id = 1; 1459 | 1460 | // The path at which the volume was staged. It MUST be an absolute 1461 | // path in the root filesystem of the process serving this request. 1462 | // This is a REQUIRED field. 1463 | // This field overrides the general CSI size limit. 1464 | // SP SHOULD support the maximum path length allowed by the operating 1465 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1466 | // length of at least 128 bytes. 1467 | string staging_target_path = 2; 1468 | } 1469 | 1470 | message NodeUnstageVolumeResponse { 1471 | // Intentionally empty. 1472 | } 1473 | message NodePublishVolumeRequest { 1474 | // The ID of the volume to publish. This field is REQUIRED. 1475 | string volume_id = 1; 1476 | 1477 | // The CO SHALL set this field to the value returned by 1478 | // `ControllerPublishVolume` if the corresponding Controller Plugin 1479 | // has `PUBLISH_UNPUBLISH_VOLUME` controller capability, and SHALL be 1480 | // left unset if the corresponding Controller Plugin does not have 1481 | // this capability. This is an OPTIONAL field. 1482 | map publish_context = 2; 1483 | 1484 | // The path to which the volume was staged by `NodeStageVolume`. 1485 | // It MUST be an absolute path in the root filesystem of the process 1486 | // serving this request. 1487 | // It MUST be set if the Node Plugin implements the 1488 | // `STAGE_UNSTAGE_VOLUME` node capability. 1489 | // This is an OPTIONAL field. 1490 | // This field overrides the general CSI size limit. 1491 | // SP SHOULD support the maximum path length allowed by the operating 1492 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1493 | // length of at least 128 bytes. 1494 | string staging_target_path = 3; 1495 | 1496 | // The path to which the volume will be published. It MUST be an 1497 | // absolute path in the root filesystem of the process serving this 1498 | // request. The CO SHALL ensure uniqueness of target_path per volume. 1499 | // The CO SHALL ensure that the parent directory of this path exists 1500 | // and that the process serving the request has `read` and `write` 1501 | // permissions to that parent directory. 1502 | // For volumes with an access type of block, the SP SHALL place the 1503 | // block device at target_path. 1504 | // For volumes with an access type of mount, the SP SHALL place the 1505 | // mounted directory at target_path. 1506 | // Creation of target_path is the responsibility of the SP. 1507 | // This is a REQUIRED field. 1508 | // This field overrides the general CSI size limit. 1509 | // SP SHOULD support the maximum path length allowed by the operating 1510 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1511 | // length of at least 128 bytes. 1512 | string target_path = 4; 1513 | 1514 | // Volume capability describing how the CO intends to use this volume. 1515 | // SP MUST ensure the CO can use the published volume as described. 1516 | // Otherwise SP MUST return the appropriate gRPC error code. 1517 | // This is a REQUIRED field. 1518 | VolumeCapability volume_capability = 5; 1519 | 1520 | // Indicates SP MUST publish the volume in readonly mode. 1521 | // This field is REQUIRED. 1522 | bool readonly = 6; 1523 | 1524 | // Secrets required by plugin to complete node publish volume request. 1525 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1526 | // section on how to use this field. 1527 | map secrets = 7 [(csi_secret) = true]; 1528 | 1529 | // Volume context as returned by SP in 1530 | // CreateVolumeResponse.Volume.volume_context. 1531 | // This field is OPTIONAL and MUST match the volume_context of the 1532 | // volume identified by `volume_id`. 1533 | map volume_context = 8; 1534 | } 1535 | 1536 | message NodePublishVolumeResponse { 1537 | // Intentionally empty. 1538 | } 1539 | message NodeUnpublishVolumeRequest { 1540 | // The ID of the volume. This field is REQUIRED. 1541 | string volume_id = 1; 1542 | 1543 | // The path at which the volume was published. It MUST be an absolute 1544 | // path in the root filesystem of the process serving this request. 1545 | // The SP MUST delete the file or directory it created at this path. 1546 | // This is a REQUIRED field. 1547 | // This field overrides the general CSI size limit. 1548 | // SP SHOULD support the maximum path length allowed by the operating 1549 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1550 | // length of at least 128 bytes. 1551 | string target_path = 2; 1552 | } 1553 | 1554 | message NodeUnpublishVolumeResponse { 1555 | // Intentionally empty. 1556 | } 1557 | message NodeGetVolumeStatsRequest { 1558 | // The ID of the volume. This field is REQUIRED. 1559 | string volume_id = 1; 1560 | 1561 | // It can be any valid path where volume was previously 1562 | // staged or published. 1563 | // It MUST be an absolute path in the root filesystem of 1564 | // the process serving this request. 1565 | // This is a REQUIRED field. 1566 | // This field overrides the general CSI size limit. 1567 | // SP SHOULD support the maximum path length allowed by the operating 1568 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1569 | // length of at least 128 bytes. 1570 | string volume_path = 2; 1571 | 1572 | // The path where the volume is staged, if the plugin has the 1573 | // STAGE_UNSTAGE_VOLUME capability, otherwise empty. 1574 | // If not empty, it MUST be an absolute path in the root 1575 | // filesystem of the process serving this request. 1576 | // This field is OPTIONAL. 1577 | // This field overrides the general CSI size limit. 1578 | // SP SHOULD support the maximum path length allowed by the operating 1579 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1580 | // length of at least 128 bytes. 1581 | string staging_target_path = 3; 1582 | } 1583 | 1584 | message NodeGetVolumeStatsResponse { 1585 | // This field is OPTIONAL. 1586 | repeated VolumeUsage usage = 1; 1587 | // Information about the current condition of the volume. 1588 | // This field is OPTIONAL. 1589 | // This field MUST be specified if the VOLUME_CONDITION node 1590 | // capability is supported. 1591 | VolumeCondition volume_condition = 2 [(alpha_field) = true]; 1592 | } 1593 | 1594 | message VolumeUsage { 1595 | enum Unit { 1596 | UNKNOWN = 0; 1597 | BYTES = 1; 1598 | INODES = 2; 1599 | } 1600 | // The available capacity in specified Unit. This field is OPTIONAL. 1601 | // The value of this field MUST NOT be negative. 1602 | int64 available = 1; 1603 | 1604 | // The total capacity in specified Unit. This field is REQUIRED. 1605 | // The value of this field MUST NOT be negative. 1606 | int64 total = 2; 1607 | 1608 | // The used capacity in specified Unit. This field is OPTIONAL. 1609 | // The value of this field MUST NOT be negative. 1610 | int64 used = 3; 1611 | 1612 | // Units by which values are measured. This field is REQUIRED. 1613 | Unit unit = 4; 1614 | } 1615 | 1616 | // VolumeCondition represents the current condition of a volume. 1617 | message VolumeCondition { 1618 | option (alpha_message) = true; 1619 | 1620 | // Normal volumes are available for use and operating optimally. 1621 | // An abnormal volume does not meet these criteria. 1622 | // This field is REQUIRED. 1623 | bool abnormal = 1; 1624 | 1625 | // The message describing the condition of the volume. 1626 | // This field is REQUIRED. 1627 | string message = 2; 1628 | } 1629 | message NodeGetCapabilitiesRequest { 1630 | // Intentionally empty. 1631 | } 1632 | 1633 | message NodeGetCapabilitiesResponse { 1634 | // All the capabilities that the node service supports. This field 1635 | // is OPTIONAL. 1636 | repeated NodeServiceCapability capabilities = 1; 1637 | } 1638 | 1639 | // Specifies a capability of the node service. 1640 | message NodeServiceCapability { 1641 | message RPC { 1642 | enum Type { 1643 | UNKNOWN = 0; 1644 | STAGE_UNSTAGE_VOLUME = 1; 1645 | // If Plugin implements GET_VOLUME_STATS capability 1646 | // then it MUST implement NodeGetVolumeStats RPC 1647 | // call for fetching volume statistics. 1648 | GET_VOLUME_STATS = 2; 1649 | // See VolumeExpansion for details. 1650 | EXPAND_VOLUME = 3; 1651 | // Indicates that the Node service can report volume conditions. 1652 | // An SP MAY implement `VolumeCondition` in only the Node 1653 | // Plugin, only the Controller Plugin, or both. 1654 | // If `VolumeCondition` is implemented in both the Node and 1655 | // Controller Plugins, it SHALL report from different 1656 | // perspectives. 1657 | // If for some reason Node and Controller Plugins report 1658 | // misaligned volume conditions, CO SHALL assume the worst case 1659 | // is the truth. 1660 | // Note that, for alpha, `VolumeCondition` is intended to be 1661 | // informative for humans only, not for automation. 1662 | VOLUME_CONDITION = 4 [(alpha_enum_value) = true]; 1663 | 1664 | // Indicates the SP supports the SINGLE_NODE_SINGLE_WRITER and/or 1665 | // SINGLE_NODE_MULTI_WRITER access modes. 1666 | // These access modes are intended to replace the 1667 | // SINGLE_NODE_WRITER access mode to clarify the number of writers 1668 | // for a volume on a single node. Plugins MUST accept and allow 1669 | // use of the SINGLE_NODE_WRITER access mode (subject to the 1670 | // processing rules for NodePublishVolume), when either 1671 | // SINGLE_NODE_SINGLE_WRITER and/or SINGLE_NODE_MULTI_WRITER are 1672 | // supported, in order to permit older COs to continue working. 1673 | SINGLE_NODE_MULTI_WRITER = 5 [(alpha_enum_value) = true]; 1674 | 1675 | // Indicates that Node service supports mounting volumes 1676 | // with provided volume group identifier during node stage 1677 | // or node publish RPC calls. 1678 | VOLUME_MOUNT_GROUP = 6; 1679 | } 1680 | 1681 | Type type = 1; 1682 | } 1683 | 1684 | oneof type { 1685 | // RPC that the controller supports. 1686 | RPC rpc = 1; 1687 | } 1688 | } 1689 | message NodeGetInfoRequest { 1690 | } 1691 | 1692 | message NodeGetInfoResponse { 1693 | // The identifier of the node as understood by the SP. 1694 | // This field is REQUIRED. 1695 | // This field MUST contain enough information to uniquely identify 1696 | // this specific node vs all other nodes supported by this plugin. 1697 | // This field SHALL be used by the CO in subsequent calls, including 1698 | // `ControllerPublishVolume`, to refer to this node. 1699 | // The SP is NOT responsible for global uniqueness of node_id across 1700 | // multiple SPs. 1701 | // This field overrides the general CSI size limit. 1702 | // The size of this field SHALL NOT exceed 256 bytes. The general 1703 | // CSI size limit, 128 byte, is RECOMMENDED for best backwards 1704 | // compatibility. 1705 | string node_id = 1; 1706 | 1707 | // Maximum number of volumes that controller can publish to the node. 1708 | // If value is not set or zero CO SHALL decide how many volumes of 1709 | // this type can be published by the controller to the node. The 1710 | // plugin MUST NOT set negative values here. 1711 | // This field is OPTIONAL. 1712 | int64 max_volumes_per_node = 2; 1713 | 1714 | // Specifies where (regions, zones, racks, etc.) the node is 1715 | // accessible from. 1716 | // A plugin that returns this field MUST also set the 1717 | // VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability. 1718 | // COs MAY use this information along with the topology information 1719 | // returned in CreateVolumeResponse to ensure that a given volume is 1720 | // accessible from a given node when scheduling workloads. 1721 | // This field is OPTIONAL. If it is not specified, the CO MAY assume 1722 | // the node is not subject to any topological constraint, and MAY 1723 | // schedule workloads that reference any volume V, such that there are 1724 | // no topological constraints declared for V. 1725 | // 1726 | // Example 1: 1727 | // accessible_topology = 1728 | // {"region": "R1", "zone": "Z2"} 1729 | // Indicates the node exists within the "region" "R1" and the "zone" 1730 | // "Z2". 1731 | Topology accessible_topology = 3; 1732 | } 1733 | message NodeExpandVolumeRequest { 1734 | // The ID of the volume. This field is REQUIRED. 1735 | string volume_id = 1; 1736 | 1737 | // The path on which volume is available. This field is REQUIRED. 1738 | // This field overrides the general CSI size limit. 1739 | // SP SHOULD support the maximum path length allowed by the operating 1740 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1741 | // length of at least 128 bytes. 1742 | string volume_path = 2; 1743 | 1744 | // This allows CO to specify the capacity requirements of the volume 1745 | // after expansion. If capacity_range is omitted then a plugin MAY 1746 | // inspect the file system of the volume to determine the maximum 1747 | // capacity to which the volume can be expanded. In such cases a 1748 | // plugin MAY expand the volume to its maximum capacity. 1749 | // This field is OPTIONAL. 1750 | CapacityRange capacity_range = 3; 1751 | 1752 | // The path where the volume is staged, if the plugin has the 1753 | // STAGE_UNSTAGE_VOLUME capability, otherwise empty. 1754 | // If not empty, it MUST be an absolute path in the root 1755 | // filesystem of the process serving this request. 1756 | // This field is OPTIONAL. 1757 | // This field overrides the general CSI size limit. 1758 | // SP SHOULD support the maximum path length allowed by the operating 1759 | // system/filesystem, but, at a minimum, SP MUST accept a max path 1760 | // length of at least 128 bytes. 1761 | string staging_target_path = 4; 1762 | 1763 | // Volume capability describing how the CO intends to use this volume. 1764 | // This allows SP to determine if volume is being used as a block 1765 | // device or mounted file system. For example - if volume is being 1766 | // used as a block device the SP MAY choose to skip expanding the 1767 | // filesystem in NodeExpandVolume implementation but still perform 1768 | // rest of the housekeeping needed for expanding the volume. If 1769 | // volume_capability is omitted the SP MAY determine 1770 | // access_type from given volume_path for the volume and perform 1771 | // node expansion. This is an OPTIONAL field. 1772 | VolumeCapability volume_capability = 5; 1773 | 1774 | // Secrets required by plugin to complete node expand volume request. 1775 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1776 | // section on how to use this field. 1777 | map secrets = 6 1778 | [(csi_secret) = true, (alpha_field) = true]; 1779 | } 1780 | 1781 | message NodeExpandVolumeResponse { 1782 | // The capacity of the volume in bytes. This field is OPTIONAL. 1783 | int64 capacity_bytes = 1; 1784 | } 1785 | message GroupControllerGetCapabilitiesRequest { 1786 | // Intentionally empty. 1787 | } 1788 | 1789 | message GroupControllerGetCapabilitiesResponse { 1790 | // All the capabilities that the group controller service supports. 1791 | // This field is OPTIONAL. 1792 | repeated GroupControllerServiceCapability capabilities = 1; 1793 | } 1794 | 1795 | // Specifies a capability of the group controller service. 1796 | message GroupControllerServiceCapability { 1797 | message RPC { 1798 | enum Type { 1799 | UNKNOWN = 0; 1800 | 1801 | // Indicates that the group controller plugin supports 1802 | // creating, deleting, and getting details of a volume 1803 | // group snapshot. 1804 | CREATE_DELETE_GET_VOLUME_GROUP_SNAPSHOT = 1; 1805 | } 1806 | 1807 | Type type = 1; 1808 | } 1809 | 1810 | oneof type { 1811 | // RPC that the controller supports. 1812 | RPC rpc = 1; 1813 | } 1814 | } 1815 | message CreateVolumeGroupSnapshotRequest { 1816 | // The suggested name for the group snapshot. This field is REQUIRED 1817 | // for idempotency. 1818 | // Any Unicode string that conforms to the length limit is allowed 1819 | // except those containing the following banned characters: 1820 | // U+0000-U+0008, U+000B, U+000C, U+000E-U+001F, U+007F-U+009F. 1821 | // (These are control characters other than commonly used whitespace.) 1822 | string name = 1; 1823 | 1824 | // volume IDs of the source volumes to be snapshotted together. 1825 | // This field is REQUIRED. 1826 | repeated string source_volume_ids = 2; 1827 | 1828 | // Secrets required by plugin to complete 1829 | // ControllerCreateVolumeGroupSnapshot request. 1830 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1831 | // section on how to use this field. 1832 | // The secrets provided in this field SHOULD be the same for 1833 | // all group snapshot operations on the same group snapshot. 1834 | map secrets = 3 [(csi_secret) = true]; 1835 | 1836 | // Plugin specific parameters passed in as opaque key-value pairs. 1837 | // This field is OPTIONAL. The Plugin is responsible for parsing and 1838 | // validating these parameters. COs will treat these as opaque. 1839 | map parameters = 4; 1840 | } 1841 | 1842 | message CreateVolumeGroupSnapshotResponse { 1843 | // Contains all attributes of the newly created group snapshot. 1844 | // This field is REQUIRED. 1845 | VolumeGroupSnapshot group_snapshot = 1; 1846 | } 1847 | 1848 | message VolumeGroupSnapshot { 1849 | // The identifier for this group snapshot, generated by the plugin. 1850 | // This field MUST contain enough information to uniquely identify 1851 | // this specific snapshot vs all other group snapshots supported by 1852 | // this plugin. 1853 | // This field SHALL be used by the CO in subsequent calls to refer to 1854 | // this group snapshot. 1855 | // The SP is NOT responsible for global uniqueness of 1856 | // group_snapshot_id across multiple SPs. 1857 | // This field is REQUIRED. 1858 | string group_snapshot_id = 1; 1859 | 1860 | // A list of snapshots belonging to this group. 1861 | // This field is REQUIRED. 1862 | repeated Snapshot snapshots = 2; 1863 | 1864 | // Timestamp of when the volume group snapshot was taken. 1865 | // This field is REQUIRED. 1866 | .google.protobuf.Timestamp creation_time = 3; 1867 | 1868 | // Indicates if all individual snapshots in the group snapshot 1869 | // are ready to use as a `volume_content_source` in a 1870 | // `CreateVolumeRequest`. The default value is false. 1871 | // If any snapshot in the list of snapshots in this message have 1872 | // ready_to_use set to false, the SP MUST set this field to false. 1873 | // If all of the snapshots in the list of snapshots in this message 1874 | // have ready_to_use set to true, the SP SHOULD set this field to 1875 | // true. 1876 | // This field is REQUIRED. 1877 | bool ready_to_use = 4; 1878 | } 1879 | message DeleteVolumeGroupSnapshotRequest { 1880 | // The ID of the group snapshot to be deleted. 1881 | // This field is REQUIRED. 1882 | string group_snapshot_id = 1; 1883 | 1884 | // A list of snapshot IDs that are part of this group snapshot. 1885 | // If SP does not need to rely on this field to delete the snapshots 1886 | // in the group, it SHOULD check this field and report an error 1887 | // if it has the ability to detect a mismatch. 1888 | // Some SPs require this list to delete the snapshots in the group. 1889 | // If SP needs to use this field to delete the snapshots in the 1890 | // group, it MUST report an error if it has the ability to detect 1891 | // a mismatch. 1892 | // This field is REQUIRED. 1893 | repeated string snapshot_ids = 2; 1894 | 1895 | // Secrets required by plugin to complete group snapshot deletion 1896 | // request. 1897 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1898 | // section on how to use this field. 1899 | // The secrets provided in this field SHOULD be the same for 1900 | // all group snapshot operations on the same group snapshot. 1901 | map secrets = 3 [(csi_secret) = true]; 1902 | } 1903 | 1904 | message DeleteVolumeGroupSnapshotResponse { 1905 | // Intentionally empty. 1906 | } 1907 | message GetVolumeGroupSnapshotRequest { 1908 | // The ID of the group snapshot to fetch current group snapshot 1909 | // information for. 1910 | // This field is REQUIRED. 1911 | string group_snapshot_id = 1; 1912 | 1913 | // A list of snapshot IDs that are part of this group snapshot. 1914 | // If SP does not need to rely on this field to get the snapshots 1915 | // in the group, it SHOULD check this field and report an error 1916 | // if it has the ability to detect a mismatch. 1917 | // Some SPs require this list to get the snapshots in the group. 1918 | // If SP needs to use this field to get the snapshots in the 1919 | // group, it MUST report an error if it has the ability to detect 1920 | // a mismatch. 1921 | // This field is REQUIRED. 1922 | repeated string snapshot_ids = 2; 1923 | 1924 | // Secrets required by plugin to complete 1925 | // GetVolumeGroupSnapshot request. 1926 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1927 | // section on how to use this field. 1928 | // The secrets provided in this field SHOULD be the same for 1929 | // all group snapshot operations on the same group snapshot. 1930 | map secrets = 3 [(csi_secret) = true]; 1931 | } 1932 | 1933 | message GetVolumeGroupSnapshotResponse { 1934 | // This field is REQUIRED 1935 | VolumeGroupSnapshot group_snapshot = 1; 1936 | } 1937 | // BlockMetadata specifies a data range. 1938 | message BlockMetadata { 1939 | // This is the zero based byte position in the volume or snapshot, 1940 | // measured from the start of the object. 1941 | // This field is REQUIRED. 1942 | int64 byte_offset = 1; 1943 | 1944 | // This is the size of the data range. 1945 | // size_bytes MUST be greater than zero. 1946 | // This field is REQUIRED. 1947 | int64 size_bytes = 2; 1948 | } 1949 | enum BlockMetadataType { 1950 | UNKNOWN = 0; 1951 | 1952 | // The FIXED_LENGTH value indicates that data ranges are 1953 | // returned in fixed size blocks. 1954 | FIXED_LENGTH = 1; 1955 | 1956 | // The VARIABLE_LENGTH value indicates that data ranges 1957 | // are returned in potentially variable sized extents. 1958 | VARIABLE_LENGTH = 2; 1959 | } 1960 | // The GetMetadataAllocatedRequest message is used to solicit metadata 1961 | // on the allocated blocks of a snapshot: i.e. this identifies the 1962 | // data ranges that have valid data as they were the target of some 1963 | // previous write operation on the volume. 1964 | message GetMetadataAllocatedRequest { 1965 | // This is the identifier of the snapshot. 1966 | // This field is REQUIRED. 1967 | string snapshot_id = 1; 1968 | 1969 | // This indicates the zero based starting byte position in the volume 1970 | // snapshot from which the result should be computed. 1971 | // It is intended to be used to continue a previously interrupted 1972 | // call. 1973 | // The CO SHOULD specify this value to be the offset of the byte 1974 | // position immediately after the last byte of the last data range 1975 | // received, if continuing an interrupted operation, or zero if not. 1976 | // The SP MUST ensure that the returned response stream does not 1977 | // contain BlockMetadata tuples that end before the requested 1978 | // starting_offset: i.e. if S is the requested starting_offset, and 1979 | // B0 is block_metadata[0] of the first message in the response 1980 | // stream, then (S < B0.byte_offset + B0.size_bytes) must be true. 1981 | // This field is REQUIRED. 1982 | int64 starting_offset = 2; 1983 | 1984 | // This is an optional parameter, and if non-zero it specifies the 1985 | // maximum number of tuples to be returned in each 1986 | // GetMetadataAllocatedResponse message returned by the RPC stream. 1987 | // The plugin will determine an appropriate value if 0, and is 1988 | // always free to send less than the requested value. 1989 | // This field is OPTIONAL. 1990 | int32 max_results = 3; 1991 | 1992 | // Secrets required by plugin to complete the request. 1993 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 1994 | // section on how to use this field. 1995 | map secrets = 4 [(csi_secret) = true]; 1996 | } 1997 | 1998 | // GetMetadataAllocatedResponse messages are returned in a gRPC stream. 1999 | // Cumulatively, they provide information on the allocated data 2000 | // ranges in the snapshot. 2001 | message GetMetadataAllocatedResponse { 2002 | // This specifies the style used in the BlockMetadata sequence. 2003 | // This value must be the same in all such messages returned by 2004 | // the stream. 2005 | // If block_metadata_type is FIXED_LENGTH, then the size_bytes field 2006 | // of each message in the block_metadata list MUST be constant. 2007 | // This field is REQUIRED. 2008 | BlockMetadataType block_metadata_type = 1; 2009 | 2010 | // This returns the capacity of the underlying volume in bytes. 2011 | // This value must be the same in all such messages returned by 2012 | // the stream. 2013 | // This field is REQUIRED. 2014 | int64 volume_capacity_bytes = 2; 2015 | 2016 | // This is a list of data range tuples. 2017 | // If the value of max_results in the GetMetadataAllocatedRequest 2018 | // message is greater than zero, then the number of entries in this 2019 | // list MUST be less than or equal to that value. 2020 | // The SP MUST respect the value of starting_offset in the request. 2021 | // The byte_offset fields of adjacent BlockMetadata messages 2022 | // MUST be strictly increasing and messages MUST NOT overlap: 2023 | // i.e. for any two BlockMetadata messages, A and B, if A is returned 2024 | // before B, then (A.byte_offset + A.size_bytes <= B.byte_offset) 2025 | // MUST be true. 2026 | // This MUST also be true if A and B are from block_metadata lists in 2027 | // different GetMetadataAllocatedResponse messages in the gRPC stream. 2028 | // This field is OPTIONAL. 2029 | repeated BlockMetadata block_metadata = 3; 2030 | } 2031 | // The GetMetadataDeltaRequest message is used to solicit metadata on 2032 | // the data ranges that have changed between two snapshots. 2033 | message GetMetadataDeltaRequest { 2034 | // This is the identifier of the snapshot against which changes 2035 | // are to be computed. 2036 | // This field is REQUIRED. 2037 | string base_snapshot_id = 1; 2038 | 2039 | // This is the identifier of a second snapshot in the same volume, 2040 | // created after the base snapshot. 2041 | // This field is REQUIRED. 2042 | string target_snapshot_id = 2; 2043 | 2044 | // This indicates the zero based starting byte position in the volume 2045 | // snapshot from which the result should be computed. 2046 | // It is intended to be used to continue a previously interrupted 2047 | // call. 2048 | // The CO SHOULD specify this value to be the offset of the byte 2049 | // position immediately after the last byte of the last data range 2050 | // received, if continuing an interrupted operation, or zero if not. 2051 | // The SP MUST ensure that the returned response stream does not 2052 | // contain BlockMetadata tuples that end before the requested 2053 | // starting_offset: i.e. if S is the requested starting_offset, and 2054 | // B0 is block_metadata[0] of the first message in the response 2055 | // stream, then (S < B0.byte_offset + B0.size_bytes) must be true. 2056 | // This field is REQUIRED. 2057 | int64 starting_offset = 3; 2058 | 2059 | // This is an optional parameter, and if non-zero it specifies the 2060 | // maximum number of tuples to be returned in each 2061 | // GetMetadataDeltaResponse message returned by the RPC stream. 2062 | // The plugin will determine an appropriate value if 0, and is 2063 | // always free to send less than the requested value. 2064 | // This field is OPTIONAL. 2065 | int32 max_results = 4; 2066 | 2067 | // Secrets required by plugin to complete the request. 2068 | // This field is OPTIONAL. Refer to the `Secrets Requirements` 2069 | // section on how to use this field. 2070 | map secrets = 5 [(csi_secret) = true]; 2071 | } 2072 | 2073 | // GetMetadataDeltaResponse messages are returned in a gRPC stream. 2074 | // Cumulatively, they provide information on the data ranges that 2075 | // have changed between the base and target snapshots specified 2076 | // in the GetMetadataDeltaRequest message. 2077 | message GetMetadataDeltaResponse { 2078 | // This specifies the style used in the BlockMetadata sequence. 2079 | // This value must be the same in all such messages returned by 2080 | // the stream. 2081 | // If block_metadata_type is FIXED_LENGTH, then the size_bytes field 2082 | // of each message in the block_metadata list MUST be constant. 2083 | // This field is REQUIRED. 2084 | BlockMetadataType block_metadata_type = 1; 2085 | 2086 | // This returns the capacity of the underlying volume in bytes. 2087 | // This value must be the same in all such messages returned by 2088 | // the stream. 2089 | // This field is REQUIRED. 2090 | int64 volume_capacity_bytes = 2; 2091 | 2092 | // This is a list of data range tuples. 2093 | // If the value of max_results in the GetMetadataDeltaRequest message 2094 | // is greater than zero, then the number of entries in this list MUST 2095 | // be less than or equal to that value. 2096 | // The SP MUST respect the value of starting_offset in the request. 2097 | // The byte_offset fields of adjacent BlockMetadata messages 2098 | // MUST be strictly increasing and messages MUST NOT overlap: 2099 | // i.e. for any two BlockMetadata messages, A and B, if A is returned 2100 | // before B, then (A.byte_offset + A.size_bytes <= B.byte_offset) 2101 | // MUST be true. 2102 | // This MUST also be true if A and B are from block_metadata lists in 2103 | // different GetMetadataDeltaResponse messages in the gRPC stream. 2104 | // This field is OPTIONAL. 2105 | repeated BlockMetadata block_metadata = 3; 2106 | } 2107 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/container-storage-interface/spec 2 | 3 | go 1.18 4 | 5 | require ( 6 | google.golang.org/grpc v1.57.1 7 | google.golang.org/protobuf v1.33.0 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.3 // indirect 12 | golang.org/x/net v0.23.0 // indirect 13 | golang.org/x/sys v0.18.0 // indirect 14 | golang.org/x/text v0.14.0 // indirect 15 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 2 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 3 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 4 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 6 | golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= 7 | golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 8 | golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= 9 | golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 10 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 11 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 12 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 13 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= 15 | google.golang.org/grpc v1.57.1 h1:upNTNqv0ES+2ZOOqACwVtS3Il8M12/+Hz41RCPzAjQg= 16 | google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= 17 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 18 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 19 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 20 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 21 | 22 | -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | # CSI Validation Libraries 2 | This directory contains language bindings generated from the CSI [protobuf file](../csi.proto) used to validate the model and workflows of the CSI specification. 3 | -------------------------------------------------------------------------------- /lib/cxx/Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | build: 4 | @echo "cxx bindings & validation" 5 | 6 | clean: 7 | @echo "clean cxx" 8 | 9 | .PHONY: clean 10 | -------------------------------------------------------------------------------- /lib/go/.gitignore: -------------------------------------------------------------------------------- 1 | /protoc 2 | /protoc-gen-go 3 | /csi.a 4 | /.protoc 5 | -------------------------------------------------------------------------------- /lib/go/Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | ######################################################################## 4 | ## GOLANG ## 5 | ######################################################################## 6 | 7 | # If GOPATH isn't defined then set its default location. 8 | ifeq (,$(strip $(GOPATH))) 9 | GOPATH := $(HOME)/go 10 | else 11 | # If GOPATH is already set then update GOPATH to be its own 12 | # first element. 13 | GOPATH := $(word 1,$(subst :, ,$(GOPATH))) 14 | endif 15 | export GOPATH 16 | 17 | GOBIN := $(shell go env GOBIN) 18 | ifeq (,$(strip $(GOBIN))) 19 | GOBIN := $(GOPATH)/bin 20 | endif 21 | 22 | 23 | ######################################################################## 24 | ## PROTOC ## 25 | ######################################################################## 26 | 27 | # Only set PROTOC_VER if it has an empty value. 28 | ifeq (,$(strip $(PROTOC_VER))) 29 | PROTOC_VER := 25.2 30 | endif 31 | 32 | PROTOC_OS := $(shell uname -s) 33 | ifeq (Darwin,$(PROTOC_OS)) 34 | PROTOC_OS := osx 35 | endif 36 | 37 | PROTOC_ARCH := $(shell uname -m) 38 | ifeq (i386,$(PROTOC_ARCH)) 39 | PROTOC_ARCH := x86_32 40 | else ifeq (arm64,$(PROTOC_ARCH)) 41 | PROTOC_ARCH := aarch_64 42 | endif 43 | 44 | PROTOC_ZIP := protoc-$(PROTOC_VER)-$(PROTOC_OS)-$(PROTOC_ARCH).zip 45 | PROTOC_URL := https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VER)/$(PROTOC_ZIP) 46 | PROTOC_TMP_DIR := .protoc 47 | PROTOC := $(PROTOC_TMP_DIR)/bin/protoc 48 | 49 | $(GOBIN)/protoc-gen-go: ../../go.mod 50 | go install google.golang.org/protobuf/cmd/protoc-gen-go 51 | $(GOBIN)/protoc-gen-go-grpc: 52 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 53 | 54 | $(PROTOC): 55 | -mkdir -p "$(PROTOC_TMP_DIR)" && \ 56 | curl -L $(PROTOC_URL) -o "$(PROTOC_TMP_DIR)/$(PROTOC_ZIP)" && \ 57 | unzip "$(PROTOC_TMP_DIR)/$(PROTOC_ZIP)" -d "$(PROTOC_TMP_DIR)" && \ 58 | chmod 0755 "$@" 59 | stat "$@" > /dev/null 2>&1 60 | 61 | PROTOC_ALL := $(GOBIN)/protoc-gen-go $(GOBIN)/protoc-gen-go-grpc $(PROTOC) 62 | 63 | ######################################################################## 64 | ## PATH ## 65 | ######################################################################## 66 | 67 | # Update PATH with GOBIN. This enables the protoc binary to discover 68 | # the protoc-gen-go binary 69 | export PATH := $(GOBIN):$(PATH) 70 | 71 | 72 | ######################################################################## 73 | ## BUILD ## 74 | ######################################################################## 75 | CSI_PROTO := ../../csi.proto 76 | CSI_PKG_SUB := csi 77 | CSI_GO := $(CSI_PKG_SUB)/csi.pb.go 78 | CSI_GRPC := $(CSI_PKG_SUB)/csi_grpc.pb.go 79 | 80 | # This recipe generates the go language bindings 81 | $(CSI_GO) $(CSI_GRPC): $(CSI_PROTO) $(PROTOC_ALL) 82 | @mkdir -p "$(@D)" 83 | $(PROTOC) -I../.. --go-grpc_out=$(CSI_PKG_SUB) --go_out=$(CSI_PKG_SUB) \ 84 | --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative \ 85 | "$(