-
Notifications
You must be signed in to change notification settings - Fork 373
/
csi.proto
1584 lines (1400 loc) · 62.8 KB
/
csi.proto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Code generated by make; DO NOT EDIT.
syntax = "proto3";
package csi.v1;
import "google/protobuf/descriptor.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
option go_package = "csi";
extend google.protobuf.EnumOptions {
// Indicates that this enum is OPTIONAL and part of an experimental
// API that may be deprecated and eventually removed between minor
// releases.
bool alpha_enum = 1060;
}
extend google.protobuf.EnumValueOptions {
// Indicates that this enum value is OPTIONAL and part of an
// experimental API that may be deprecated and eventually removed
// between minor releases.
bool alpha_enum_value = 1060;
}
extend google.protobuf.FieldOptions {
// Indicates that a field MAY contain information that is sensitive
// and MUST be treated as such (e.g. not logged).
bool csi_secret = 1059;
// Indicates that this field is OPTIONAL and part of an experimental
// API that may be deprecated and eventually removed between minor
// releases.
bool alpha_field = 1060;
}
extend google.protobuf.MessageOptions {
// Indicates that this message is OPTIONAL and part of an experimental
// API that may be deprecated and eventually removed between minor
// releases.
bool alpha_message = 1060;
}
extend google.protobuf.MethodOptions {
// Indicates that this method is OPTIONAL and part of an experimental
// API that may be deprecated and eventually removed between minor
// releases.
bool alpha_method = 1060;
}
extend google.protobuf.ServiceOptions {
// Indicates that this service is OPTIONAL and part of an experimental
// API that may be deprecated and eventually removed between minor
// releases.
bool alpha_service = 1060;
}
service Identity {
rpc GetPluginInfo(GetPluginInfoRequest)
returns (GetPluginInfoResponse) {}
rpc GetPluginCapabilities(GetPluginCapabilitiesRequest)
returns (GetPluginCapabilitiesResponse) {}
rpc Probe (ProbeRequest)
returns (ProbeResponse) {}
}
service Controller {
rpc CreateVolume (CreateVolumeRequest)
returns (CreateVolumeResponse) {}
rpc DeleteVolume (DeleteVolumeRequest)
returns (DeleteVolumeResponse) {}
rpc ControllerPublishVolume (ControllerPublishVolumeRequest)
returns (ControllerPublishVolumeResponse) {}
rpc ControllerUnpublishVolume (ControllerUnpublishVolumeRequest)
returns (ControllerUnpublishVolumeResponse) {}
rpc ValidateVolumeCapabilities (ValidateVolumeCapabilitiesRequest)
returns (ValidateVolumeCapabilitiesResponse) {}
rpc ListVolumes (ListVolumesRequest)
returns (ListVolumesResponse) {}
rpc GetCapacity (GetCapacityRequest)
returns (GetCapacityResponse) {}
rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest)
returns (ControllerGetCapabilitiesResponse) {}
rpc CreateSnapshot (CreateSnapshotRequest)
returns (CreateSnapshotResponse) {}
rpc DeleteSnapshot (DeleteSnapshotRequest)
returns (DeleteSnapshotResponse) {}
rpc ListSnapshots (ListSnapshotsRequest)
returns (ListSnapshotsResponse) {}
rpc ControllerExpandVolume (ControllerExpandVolumeRequest)
returns (ControllerExpandVolumeResponse) {}
rpc ControllerGetVolume (ControllerGetVolumeRequest)
returns (ControllerGetVolumeResponse) {
option (alpha_method) = true;
}
}
service Node {
rpc NodeStageVolume (NodeStageVolumeRequest)
returns (NodeStageVolumeResponse) {}
rpc NodeUnstageVolume (NodeUnstageVolumeRequest)
returns (NodeUnstageVolumeResponse) {}
rpc NodePublishVolume (NodePublishVolumeRequest)
returns (NodePublishVolumeResponse) {}
rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest)
returns (NodeUnpublishVolumeResponse) {}
rpc NodeGetVolumeStats (NodeGetVolumeStatsRequest)
returns (NodeGetVolumeStatsResponse) {}
rpc NodeExpandVolume(NodeExpandVolumeRequest)
returns (NodeExpandVolumeResponse) {}
rpc NodeGetCapabilities (NodeGetCapabilitiesRequest)
returns (NodeGetCapabilitiesResponse) {}
rpc NodeGetInfo (NodeGetInfoRequest)
returns (NodeGetInfoResponse) {}
}
message GetPluginInfoRequest {
// Intentionally empty.
}
message GetPluginInfoResponse {
// The name MUST follow domain name notation format
// (https://tools.ietf.org/html/rfc1035#section-2.3.1). It SHOULD
// include the plugin's host company name and the plugin name,
// to minimize the possibility of collisions. It MUST be 63
// characters or less, beginning and ending with an alphanumeric
// character ([a-z0-9A-Z]) with dashes (-), dots (.), and
// alphanumerics between. This field is REQUIRED.
string name = 1;
// This field is REQUIRED. Value of this field is opaque to the CO.
string vendor_version = 2;
// This field is OPTIONAL. Values are opaque to the CO.
map<string, string> manifest = 3;
}
message GetPluginCapabilitiesRequest {
// Intentionally empty.
}
message GetPluginCapabilitiesResponse {
// All the capabilities that the controller service supports. This
// field is OPTIONAL.
repeated PluginCapability capabilities = 1;
}
// Specifies a capability of the plugin.
message PluginCapability {
message Service {
enum Type {
UNKNOWN = 0;
// CONTROLLER_SERVICE indicates that the Plugin provides RPCs for
// the ControllerService. Plugins SHOULD provide this capability.
// In rare cases certain plugins MAY wish to omit the
// ControllerService entirely from their implementation, but such
// SHOULD NOT be the common case.
// The presence of this capability determines whether the CO will
// attempt to invoke the REQUIRED ControllerService RPCs, as well
// as specific RPCs as indicated by ControllerGetCapabilities.
CONTROLLER_SERVICE = 1;
// VOLUME_ACCESSIBILITY_CONSTRAINTS indicates that the volumes for
// this plugin MAY NOT be equally accessible by all nodes in the
// cluster. The CO MUST use the topology information returned by
// CreateVolumeRequest along with the topology information
// returned by NodeGetInfo to ensure that a given volume is
// accessible from a given node when scheduling workloads.
VOLUME_ACCESSIBILITY_CONSTRAINTS = 2;
}
Type type = 1;
}
message VolumeExpansion {
enum Type {
UNKNOWN = 0;
// ONLINE indicates that volumes may be expanded when published to
// a node. When a Plugin implements this capability it MUST
// implement either the EXPAND_VOLUME controller capability or the
// EXPAND_VOLUME node capability or both. When a plugin supports
// ONLINE volume expansion and also has the EXPAND_VOLUME
// controller capability then the plugin MUST support expansion of
// volumes currently published and available on a node. When a
// plugin supports ONLINE volume expansion and also has the
// EXPAND_VOLUME node capability then the plugin MAY support
// expansion of node-published volume via NodeExpandVolume.
//
// Example 1: Given a shared filesystem volume (e.g. GlusterFs),
// the Plugin may set the ONLINE volume expansion capability and
// implement ControllerExpandVolume but not NodeExpandVolume.
//
// Example 2: Given a block storage volume type (e.g. EBS), the
// Plugin may set the ONLINE volume expansion capability and
// implement both ControllerExpandVolume and NodeExpandVolume.
//
// Example 3: Given a Plugin that supports volume expansion only
// upon a node, the Plugin may set the ONLINE volume
// expansion capability and implement NodeExpandVolume but not
// ControllerExpandVolume.
ONLINE = 1;
// OFFLINE indicates that volumes currently published and
// available on a node SHALL NOT be expanded via
// ControllerExpandVolume. When a plugin supports OFFLINE volume
// expansion it MUST implement either the EXPAND_VOLUME controller
// capability or both the EXPAND_VOLUME controller capability and
// the EXPAND_VOLUME node capability.
//
// Example 1: Given a block storage volume type (e.g. Azure Disk)
// that does not support expansion of "node-attached" (i.e.
// controller-published) volumes, the Plugin may indicate
// OFFLINE volume expansion support and implement both
// ControllerExpandVolume and NodeExpandVolume.
OFFLINE = 2;
}
Type type = 1;
}
oneof type {
// Service that the plugin supports.
Service service = 1;
VolumeExpansion volume_expansion = 2;
}
}
message ProbeRequest {
// Intentionally empty.
}
message ProbeResponse {
// Readiness allows a plugin to report its initialization status back
// to the CO. Initialization for some plugins MAY be time consuming
// and it is important for a CO to distinguish between the following
// cases:
//
// 1) The plugin is in an unhealthy state and MAY need restarting. In
// this case a gRPC error code SHALL be returned.
// 2) The plugin is still initializing, but is otherwise perfectly
// healthy. In this case a successful response SHALL be returned
// with a readiness value of `false`. Calls to the plugin's
// Controller and/or Node services MAY fail due to an incomplete
// initialization state.
// 3) The plugin has finished initializing and is ready to service
// calls to its Controller and/or Node services. A successful
// response is returned with a readiness value of `true`.
//
// This field is OPTIONAL. If not present, the caller SHALL assume
// that the plugin is in a ready state and is accepting calls to its
// Controller and/or Node services (according to the plugin's reported
// capabilities).
.google.protobuf.BoolValue ready = 1;
}
message CreateVolumeRequest {
// The suggested name for the storage space. This field is REQUIRED.
// It serves two purposes:
// 1) Idempotency - This name is generated by the CO to achieve
// idempotency. The Plugin SHOULD ensure that multiple
// `CreateVolume` calls for the same name do not result in more
// than one piece of storage provisioned corresponding to that
// name. If a Plugin is unable to enforce idempotency, the CO's
// error recovery logic could result in multiple (unused) volumes
// being provisioned.
// In the case of error, the CO MUST handle the gRPC error codes
// per the recovery behavior defined in the "CreateVolume Errors"
// section below.
// The CO is responsible for cleaning up volumes it provisioned
// that it no longer needs. If the CO is uncertain whether a volume
// was provisioned or not when a `CreateVolume` call fails, the CO
// MAY call `CreateVolume` again, with the same name, to ensure the
// volume exists and to retrieve the volume's `volume_id` (unless
// otherwise prohibited by "CreateVolume Errors").
// 2) Suggested name - Some storage systems allow callers to specify
// an identifier by which to refer to the newly provisioned
// storage. If a storage system supports this, it can optionally
// use this name as the identifier for the new volume.
// Any Unicode string that conforms to the length limit is allowed
// except those containing the following banned characters:
// U+0000-U+0008, U+000B, U+000C, U+000E-U+001F, U+007F-U+009F.
// (These are control characters other than commonly used whitespace.)
string name = 1;
// This field is OPTIONAL. This allows the CO to specify the capacity
// requirement of the volume to be provisioned. If not specified, the
// Plugin MAY choose an implementation-defined capacity range. If
// specified it MUST always be honored, even when creating volumes
// from a source; which MAY force some backends to internally extend
// the volume after creating it.
CapacityRange capacity_range = 2;
// The capabilities that the provisioned volume MUST have. SP MUST
// provision a volume that will satisfy ALL of the capabilities
// specified in this list. Otherwise SP MUST return the appropriate
// gRPC error code.
// The Plugin MUST assume that the CO MAY use the provisioned volume
// with ANY of the capabilities specified in this list.
// For example, a CO MAY specify two volume capabilities: one with
// access mode SINGLE_NODE_WRITER and another with access mode
// MULTI_NODE_READER_ONLY. In this case, the SP MUST verify that the
// provisioned volume can be used in either mode.
// This also enables the CO to do early validation: If ANY of the
// specified volume capabilities are not supported by the SP, the call
// MUST return the appropriate gRPC error code.
// This field is REQUIRED.
repeated VolumeCapability volume_capabilities = 3;
// Plugin specific parameters passed in as opaque key-value pairs.
// This field is OPTIONAL. The Plugin is responsible for parsing and
// validating these parameters. COs will treat these as opaque.
map<string, string> parameters = 4;
// Secrets required by plugin to complete volume creation request.
// This field is OPTIONAL. Refer to the `Secrets Requirements`
// section on how to use this field.
map<string, string> secrets = 5 [(csi_secret) = true];
// If specified, the new volume will be pre-populated with data from
// this source. This field is OPTIONAL.
VolumeContentSource volume_content_source = 6;
// Specifies where (regions, zones, racks, etc.) the provisioned
// volume MUST be accessible from.
// An SP SHALL advertise the requirements for topological
// accessibility information in documentation. COs SHALL only specify
// topological accessibility information supported by the SP.
// This field is OPTIONAL.
// This field SHALL NOT be specified unless the SP has the
// VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability.
// If this field is not specified and the SP has the
// VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability, the SP MAY
// choose where the provisioned volume is accessible from.
TopologyRequirement accessibility_requirements = 7;
}
// Specifies what source the volume will be created from. One of the
// type fields MUST be specified.
message VolumeContentSource {
message SnapshotSource {
// Contains identity information for the existing source snapshot.
// This field is REQUIRED. Plugin is REQUIRED to support creating
// volume from snapshot if it supports the capability
// CREATE_DELETE_SNAPSHOT.
string snapshot_id = 1;
}
message VolumeSource {
// Contains identity information for the existing source volume.
// This field is REQUIRED. Plugins reporting CLONE_VOLUME
// capability MUST support creating a volume from another volume.
string volume_id = 1;
}
oneof type {
SnapshotSource snapshot = 1;
VolumeSource volume = 2;
}
}
message CreateVolumeResponse {
// Contains all attributes of the newly created volume that are
// relevant to the CO along with information required by the Plugin
// to uniquely identify the volume. This field is REQUIRED.
Volume volume = 1;
}
// Specify a capability of a volume.
message VolumeCapability {
// Indicate that the volume will be accessed via the block device API.
message BlockVolume {
// Intentionally empty, for now.
}
// Indicate that the volume will be accessed via the filesystem API.
message MountVolume {
// The filesystem type. This field is OPTIONAL.
// An empty string is equal to an unspecified field value.
string fs_type = 1;
// The mount options that can be used for the volume. This field is
// OPTIONAL. `mount_flags` MAY contain sensitive information.
// Therefore, the CO and the Plugin MUST NOT leak this information
// to untrusted entities. The total size of this repeated field
// SHALL NOT exceed 4 KiB.
repeated string mount_flags = 2;
}
// Specify how a volume can be accessed.
message AccessMode {
enum Mode {
UNKNOWN = 0;
// Can only be published once as read/write on a single node, at
// any given time.
SINGLE_NODE_WRITER = 1;
// Can only be published once as readonly on a single node, at
// any given time.
SINGLE_NODE_READER_ONLY = 2;
// Can be published as readonly at multiple nodes simultaneously.
MULTI_NODE_READER_ONLY = 3;
// Can be published at multiple nodes simultaneously. Only one of
// the node can be used as read/write. The rest will be readonly.
MULTI_NODE_SINGLE_WRITER = 4;
// Can be published as read/write at multiple nodes
// simultaneously.
MULTI_NODE_MULTI_WRITER = 5;
}
// This field is REQUIRED.
Mode mode = 1;
}
// Specifies what API the volume will be accessed using. One of the
// following fields MUST be specified.
oneof access_type {
BlockVolume block = 1;
MountVolume mount = 2;
}
// This is a REQUIRED field.
AccessMode access_mode = 3;
}
// The capacity of the storage space in bytes. To specify an exact size,
// `required_bytes` and `limit_bytes` SHALL be set to the same value. At
// least one of the these fields MUST be specified.
message CapacityRange {
// Volume MUST be at least this big. This field is OPTIONAL.
// A value of 0 is equal to an unspecified field value.
// The value of this field MUST NOT be negative.
int64 required_bytes = 1;
// Volume MUST not be bigger than this. This field is OPTIONAL.
// A value of 0 is equal to an unspecified field value.
// The value of this field MUST NOT be negative.
int64 limit_bytes = 2;
}
// Information about a specific volume.
message Volume {
// The capacity of the volume in bytes. This field is OPTIONAL. If not
// set (value of 0), it indicates that the capacity of the volume is
// unknown (e.g., NFS share).
// The value of this field MUST NOT be negative.
int64 capacity_bytes = 1;
// The identifier for this volume, generated by the plugin.
// This field is REQUIRED.
// This field MUST contain enough information to uniquely identify
// this specific volume vs all other volumes supported by this plugin.
// This field SHALL be used by the CO in subsequent calls to refer to
// this volume.
// The SP is NOT responsible for global uniqueness of volume_id across
// multiple SPs.
string volume_id = 2;
// Opaque static properties of the volume. SP MAY use this field to
// ensure subsequent volume validation and publishing calls have
// contextual information.
// The contents of this field SHALL be opaque to a CO.
// The contents of this field SHALL NOT be mutable.
// The contents of this field SHALL be safe for the CO to cache.
// The contents of this field SHOULD NOT contain sensitive
// information.
// The contents of this field SHOULD NOT be used for uniquely
// identifying a volume. The `volume_id` alone SHOULD be sufficient to
// identify the volume.
// A volume uniquely identified by `volume_id` SHALL always report the
// same volume_context.
// This field is OPTIONAL and when present MUST be passed to volume
// validation and publishing calls.
map<string, string> volume_context = 3;
// If specified, indicates that the volume is not empty and is
// pre-populated with data from the specified source.
// This field is OPTIONAL.
VolumeContentSource content_source = 4;
// Specifies where (regions, zones, racks, etc.) the provisioned
// volume is accessible from.
// A plugin that returns this field MUST also set the
// VOLUME_ACCESSIBILITY_CONSTRAINTS plugin capability.
// An SP MAY specify multiple topologies to indicate the volume is
// accessible from multiple locations.
// COs MAY use this information along with the topology information
// returned by NodeGetInfo to ensure that a given volume is accessible
// from a given node when scheduling workloads.
// This field is OPTIONAL. If it is not specified, the CO MAY assume
// the volume is equally accessible from all nodes in the cluster and
// MAY schedule workloads referencing the volume on any available
// node.
//
// Example 1:
// accessible_topology = {"region": "R1", "zone": "Z2"}
// Indicates a volume accessible only from the "region" "R1" and the
// "zone" "Z2".
//
// Example 2:
// accessible_topology =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"}
// Indicates a volume accessible from both "zone" "Z2" and "zone" "Z3"
// in the "region" "R1".
repeated Topology accessible_topology = 5;
}
message TopologyRequirement {
// Specifies the list of topologies the provisioned volume MUST be
// accessible from.
// This field is OPTIONAL. If TopologyRequirement is specified either
// requisite or preferred or both MUST be specified.
//
// If requisite is specified, the provisioned volume MUST be
// accessible from at least one of the requisite topologies.
//
// Given
// x = number of topologies provisioned volume is accessible from
// n = number of requisite topologies
// The CO MUST ensure n >= 1. The SP MUST ensure x >= 1
// If x==n, then the SP MUST make the provisioned volume available to
// all topologies from the list of requisite topologies. If it is
// unable to do so, the SP MUST fail the CreateVolume call.
// For example, if a volume should be accessible from a single zone,
// and requisite =
// {"region": "R1", "zone": "Z2"}
// then the provisioned volume MUST be accessible from the "region"
// "R1" and the "zone" "Z2".
// Similarly, if a volume should be accessible from two zones, and
// requisite =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"}
// then the provisioned volume MUST be accessible from the "region"
// "R1" and both "zone" "Z2" and "zone" "Z3".
//
// If x<n, then the SP SHALL choose x unique topologies from the list
// of requisite topologies. If it is unable to do so, the SP MUST fail
// the CreateVolume call.
// For example, if a volume should be accessible from a single zone,
// and requisite =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"}
// then the SP may choose to make the provisioned volume available in
// either the "zone" "Z2" or the "zone" "Z3" in the "region" "R1".
// Similarly, if a volume should be accessible from two zones, and
// requisite =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"},
// {"region": "R1", "zone": "Z4"}
// then the provisioned volume MUST be accessible from any combination
// of two unique topologies: e.g. "R1/Z2" and "R1/Z3", or "R1/Z2" and
// "R1/Z4", or "R1/Z3" and "R1/Z4".
//
// If x>n, then the SP MUST make the provisioned volume available from
// all topologies from the list of requisite topologies and MAY choose
// the remaining x-n unique topologies from the list of all possible
// topologies. If it is unable to do so, the SP MUST fail the
// CreateVolume call.
// For example, if a volume should be accessible from two zones, and
// requisite =
// {"region": "R1", "zone": "Z2"}
// then the provisioned volume MUST be accessible from the "region"
// "R1" and the "zone" "Z2" and the SP may select the second zone
// independently, e.g. "R1/Z4".
repeated Topology requisite = 1;
// Specifies the list of topologies the CO would prefer the volume to
// be provisioned in.
//
// This field is OPTIONAL. If TopologyRequirement is specified either
// requisite or preferred or both MUST be specified.
//
// An SP MUST attempt to make the provisioned volume available using
// the preferred topologies in order from first to last.
//
// If requisite is specified, all topologies in preferred list MUST
// also be present in the list of requisite topologies.
//
// If the SP is unable to to make the provisioned volume available
// from any of the preferred topologies, the SP MAY choose a topology
// from the list of requisite topologies.
// If the list of requisite topologies is not specified, then the SP
// MAY choose from the list of all possible topologies.
// If the list of requisite topologies is specified and the SP is
// unable to to make the provisioned volume available from any of the
// requisite topologies it MUST fail the CreateVolume call.
//
// Example 1:
// Given a volume should be accessible from a single zone, and
// requisite =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"}
// preferred =
// {"region": "R1", "zone": "Z3"}
// then the the SP SHOULD first attempt to make the provisioned volume
// available from "zone" "Z3" in the "region" "R1" and fall back to
// "zone" "Z2" in the "region" "R1" if that is not possible.
//
// Example 2:
// Given a volume should be accessible from a single zone, and
// requisite =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"},
// {"region": "R1", "zone": "Z4"},
// {"region": "R1", "zone": "Z5"}
// preferred =
// {"region": "R1", "zone": "Z4"},
// {"region": "R1", "zone": "Z2"}
// then the the SP SHOULD first attempt to make the provisioned volume
// accessible from "zone" "Z4" in the "region" "R1" and fall back to
// "zone" "Z2" in the "region" "R1" if that is not possible. If that
// is not possible, the SP may choose between either the "zone"
// "Z3" or "Z5" in the "region" "R1".
//
// Example 3:
// Given a volume should be accessible from TWO zones (because an
// opaque parameter in CreateVolumeRequest, for example, specifies
// the volume is accessible from two zones, aka synchronously
// replicated), and
// requisite =
// {"region": "R1", "zone": "Z2"},
// {"region": "R1", "zone": "Z3"},
// {"region": "R1", "zone": "Z4"},
// {"region": "R1", "zone": "Z5"}
// preferred =
// {"region": "R1", "zone": "Z5"},
// {"region": "R1", "zone": "Z3"}
// then the the SP SHOULD first attempt to make the provisioned volume
// accessible from the combination of the two "zones" "Z5" and "Z3" in
// the "region" "R1". If that's not possible, it should fall back to
// a combination of "Z5" and other possibilities from the list of
// requisite. If that's not possible, it should fall back to a
// combination of "Z3" and other possibilities from the list of
// requisite. If that's not possible, it should fall back to a
// combination of other possibilities from the list of requisite.
repeated Topology preferred = 2;
}
// Topology is a map of topological domains to topological segments.
// A topological domain is a sub-division of a cluster, like "region",
// "zone", "rack", etc.
// A topological segment is a specific instance of a topological domain,
// like "zone3", "rack3", etc.
// For example {"com.company/zone": "Z1", "com.company/rack": "R3"}
// Valid keys have two segments: an OPTIONAL prefix and name, separated
// by a slash (/), for example: "com.company.example/zone".
// The key name segment is REQUIRED. The prefix is OPTIONAL.
// The key name MUST be 63 characters or less, begin and end with an
// alphanumeric character ([a-z0-9A-Z]), and contain only dashes (-),
// underscores (_), dots (.), or alphanumerics in between, for example
// "zone".
// The key prefix MUST be 63 characters or less, begin and end with a
// lower-case alphanumeric character ([a-z0-9]), contain only
// dashes (-), dots (.), or lower-case alphanumerics in between, and
// follow domain name notation format
// (https://tools.ietf.org/html/rfc1035#section-2.3.1).
// The key prefix SHOULD include the plugin's host company name and/or
// the plugin name, to minimize the possibility of collisions with keys
// from other plugins.
// If a key prefix is specified, it MUST be identical across all
// topology keys returned by the SP (across all RPCs).
// Keys MUST be case-insensitive. Meaning the keys "Zone" and "zone"
// MUST not both exist.
// Each value (topological segment) MUST contain 1 or more strings.
// Each string MUST be 63 characters or less and begin and end with an
// alphanumeric character with '-', '_', '.', or alphanumerics in
// between.
message Topology {
map<string, string> segments = 1;
}
message DeleteVolumeRequest {
// The ID of the volume to be deprovisioned.
// This field is REQUIRED.
string volume_id = 1;
// Secrets required by plugin to complete volume deletion request.
// This field is OPTIONAL. Refer to the `Secrets Requirements`
// section on how to use this field.
map<string, string> secrets = 2 [(csi_secret) = true];
}
message DeleteVolumeResponse {
// Intentionally empty.
}
message ControllerPublishVolumeRequest {
// The ID of the volume to be used on a node.
// This field is REQUIRED.
string volume_id = 1;
// The ID of the node. This field is REQUIRED. The CO SHALL set this
// field to match the node ID returned by `NodeGetInfo`.
string node_id = 2;
// Volume capability describing how the CO intends to use this volume.
// SP MUST ensure the CO can use the published volume as described.
// Otherwise SP MUST return the appropriate gRPC error code.
// This is a REQUIRED field.
VolumeCapability volume_capability = 3;
// Indicates SP MUST publish the volume in readonly mode.
// CO MUST set this field to false if SP does not have the
// PUBLISH_READONLY controller capability.
// This is a REQUIRED field.
bool readonly = 4;
// Secrets required by plugin to complete controller publish volume
// request. This field is OPTIONAL. Refer to the
// `Secrets Requirements` section on how to use this field.
map<string, string> secrets = 5 [(csi_secret) = true];
// Volume context as returned by SP in
// CreateVolumeResponse.Volume.volume_context.
// This field is OPTIONAL and MUST match the volume_context of the
// volume identified by `volume_id`.
map<string, string> volume_context = 6;
}
message ControllerPublishVolumeResponse {
// Opaque static publish properties of the volume. SP MAY use this
// field to ensure subsequent `NodeStageVolume` or `NodePublishVolume`
// calls calls have contextual information.
// The contents of this field SHALL be opaque to a CO.
// The contents of this field SHALL NOT be mutable.
// The contents of this field SHALL be safe for the CO to cache.
// The contents of this field SHOULD NOT contain sensitive
// information.
// The contents of this field SHOULD NOT be used for uniquely
// identifying a volume. The `volume_id` alone SHOULD be sufficient to
// identify the volume.
// This field is OPTIONAL and when present MUST be passed to
// subsequent `NodeStageVolume` or `NodePublishVolume` calls
map<string, string> publish_context = 1;
}
message ControllerUnpublishVolumeRequest {
// The ID of the volume. This field is REQUIRED.
string volume_id = 1;
// The ID of the node. This field is OPTIONAL. The CO SHOULD set this
// field to match the node ID returned by `NodeGetInfo` or leave it
// unset. If the value is set, the SP MUST unpublish the volume from
// the specified node. If the value is unset, the SP MUST unpublish
// the volume from all nodes it is published to.
string node_id = 2;
// Secrets required by plugin to complete controller unpublish volume
// request. This SHOULD be the same secrets passed to the
// ControllerPublishVolume call for the specified volume.
// This field is OPTIONAL. Refer to the `Secrets Requirements`
// section on how to use this field.
map<string, string> secrets = 3 [(csi_secret) = true];
}
message ControllerUnpublishVolumeResponse {
// Intentionally empty.
}
message ValidateVolumeCapabilitiesRequest {
// The ID of the volume to check. This field is REQUIRED.
string volume_id = 1;
// Volume context as returned by SP in
// CreateVolumeResponse.Volume.volume_context.
// This field is OPTIONAL and MUST match the volume_context of the
// volume identified by `volume_id`.
map<string, string> volume_context = 2;
// The capabilities that the CO wants to check for the volume. This
// call SHALL return "confirmed" only if all the volume capabilities
// specified below are supported. This field is REQUIRED.
repeated VolumeCapability volume_capabilities = 3;
// See CreateVolumeRequest.parameters.
// This field is OPTIONAL.
map<string, string> parameters = 4;
// Secrets required by plugin to complete volume validation request.
// This field is OPTIONAL. Refer to the `Secrets Requirements`
// section on how to use this field.
map<string, string> secrets = 5 [(csi_secret) = true];
}
message ValidateVolumeCapabilitiesResponse {
message Confirmed {
// Volume context validated by the plugin.
// This field is OPTIONAL.
map<string, string> volume_context = 1;
// Volume capabilities supported by the plugin.
// This field is REQUIRED.
repeated VolumeCapability volume_capabilities = 2;
// The volume creation parameters validated by the plugin.
// This field is OPTIONAL.
map<string, string> parameters = 3;
}
// Confirmed indicates to the CO the set of capabilities that the
// plugin has validated. This field SHALL only be set to a non-empty
// value for successful validation responses.
// For successful validation responses, the CO SHALL compare the
// fields of this message to the originally requested capabilities in
// order to guard against an older plugin reporting "valid" for newer
// capability fields that it does not yet understand.
// This field is OPTIONAL.
Confirmed confirmed = 1;
// Message to the CO if `confirmed` above is empty. This field is
// OPTIONAL.
// An empty string is equal to an unspecified field value.
string message = 2;
}
message ListVolumesRequest {
// If specified (non-zero value), the Plugin MUST NOT return more
// entries than this number in the response. If the actual number of
// entries is more than this number, the Plugin MUST set `next_token`
// in the response which can be used to get the next page of entries
// in the subsequent `ListVolumes` call. This field is OPTIONAL. If
// not specified (zero value), it means there is no restriction on the
// number of entries that can be returned.
// The value of this field MUST NOT be negative.
int32 max_entries = 1;
// A token to specify where to start paginating. Set this field to
// `next_token` returned by a previous `ListVolumes` call to get the
// next page of entries. This field is OPTIONAL.
// An empty string is equal to an unspecified field value.
string starting_token = 2;
}
message ListVolumesResponse {
message VolumeStatus{
// A list of all `node_id` of nodes that the volume in this entry
// is controller published on.
// This field is OPTIONAL. If it is not specified and the SP has
// the LIST_VOLUMES_PUBLISHED_NODES controller capability, the CO
// MAY assume the volume is not controller published to any nodes.
// If the field is not specified and the SP does not have the
// LIST_VOLUMES_PUBLISHED_NODES controller capability, the CO MUST
// not interpret this field.
// published_node_ids MAY include nodes not published to or
// reported by the SP. The CO MUST be resilient to that.
repeated string published_node_ids = 1;
// Information about the current condition of the volume.
// This field is OPTIONAL.
// This field MUST be specified if the
// VOLUME_CONDITION controller capability is supported.
VolumeCondition volume_condition = 2 [(alpha_field) = true];
}
message Entry {
// This field is REQUIRED
Volume volume = 1;
// This field is OPTIONAL. This field MUST be specified if the
// LIST_VOLUMES_PUBLISHED_NODES controller capability is
// supported.
VolumeStatus status = 2;
}
repeated Entry entries = 1;
// This token allows you to get the next page of entries for
// `ListVolumes` request. If the number of entries is larger than
// `max_entries`, use the `next_token` as a value for the
// `starting_token` field in the next `ListVolumes` request. This
// field is OPTIONAL.
// An empty string is equal to an unspecified field value.
string next_token = 2;
}
message ControllerGetVolumeRequest {
option (alpha_message) = true;
// The ID of the volume to fetch current volume information for.
// This field is REQUIRED.
string volume_id = 1;
}
message ControllerGetVolumeResponse {
option (alpha_message) = true;
message VolumeStatus{
// A list of all the `node_id` of nodes that this volume is
// controller published on.
// This field is OPTIONAL.
// This field MUST be specified if the PUBLISH_UNPUBLISH_VOLUME
// controller capability is supported.
// published_node_ids MAY include nodes not published to or
// reported by the SP. The CO MUST be resilient to that.
repeated string published_node_ids = 1;
// Information about the current condition of the volume.
// This field is OPTIONAL.
// This field MUST be specified if the
// VOLUME_CONDITION controller capability is supported.
VolumeCondition volume_condition = 2;
}
// This field is REQUIRED
Volume volume = 1;
// This field is REQUIRED.
VolumeStatus status = 2;
}
message GetCapacityRequest {
// If specified, the Plugin SHALL report the capacity of the storage
// that can be used to provision volumes that satisfy ALL of the
// specified `volume_capabilities`. These are the same
// `volume_capabilities` the CO will use in `CreateVolumeRequest`.
// This field is OPTIONAL.
repeated VolumeCapability volume_capabilities = 1;
// If specified, the Plugin SHALL report the capacity of the storage
// that can be used to provision volumes with the given Plugin
// specific `parameters`. These are the same `parameters` the CO will
// use in `CreateVolumeRequest`. This field is OPTIONAL.
map<string, string> parameters = 2;
// If specified, the Plugin SHALL report the capacity of the storage
// that can be used to provision volumes that in the specified
// `accessible_topology`. This is the same as the
// `accessible_topology` the CO returns in a `CreateVolumeResponse`.
// This field is OPTIONAL. This field SHALL NOT be set unless the
// plugin advertises the VOLUME_ACCESSIBILITY_CONSTRAINTS capability.
Topology accessible_topology = 3;
}
message GetCapacityResponse {
// The available capacity, in bytes, of the storage that can be used
// to provision volumes. If `volume_capabilities` or `parameters` is
// specified in the request, the Plugin SHALL take those into
// consideration when calculating the available capacity of the
// storage. This field is REQUIRED.
// The value of this field MUST NOT be negative.
int64 available_capacity = 1;
// The largest size that may be used in a
// CreateVolumeRequest.capacity_range.required_bytes field
// to create a volume with the same parameters as those in
// GetCapacityRequest.
//
// If `volume_capabilities` or `parameters` is
// specified in the request, the Plugin SHALL take those into
// consideration when calculating the minimum volume size of the
// storage.
//
// This field is OPTIONAL. MUST NOT be negative.
// The Plugin SHOULD provide a value for this field if it has
// a maximum size for individual volumes and leave it unset
// otherwise. COs MAY use it to make decision about
// where to create volumes.
google.protobuf.Int64Value maximum_volume_size = 2
[(alpha_field) = true];
// The smallest size that may be used in a
// CreateVolumeRequest.capacity_range.limit_bytes field
// to create a volume with the same parameters as those in
// GetCapacityRequest.
//
// If `volume_capabilities` or `parameters` is
// specified in the request, the Plugin SHALL take those into
// consideration when calculating the maximum volume size of the
// storage.
//
// This field is OPTIONAL. MUST NOT be negative.
// The Plugin SHOULD provide a value for this field if it has
// a minimum size for individual volumes and leave it unset
// otherwise. COs MAY use it to make decision about
// where to create volumes.
google.protobuf.Int64Value minimum_volume_size = 3
[(alpha_field) = true];
}
message ControllerGetCapabilitiesRequest {
// Intentionally empty.
}
message ControllerGetCapabilitiesResponse {
// All the capabilities that the controller service supports. This
// field is OPTIONAL.
repeated ControllerServiceCapability capabilities = 1;
}
// Specifies a capability of the controller service.
message ControllerServiceCapability {
message RPC {
enum Type {