////////
syntax = "proto3";
package csi;
////////
////////
service Identity {
  rpc GetSupportedVersions (GetSupportedVersionsRequest)
    returns (GetSupportedVersionsResponse) {}

  rpc GetPluginInfo(GetPluginInfoRequest)
    returns (GetPluginInfoResponse) {}
}

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 ControllerProbe (ControllerProbeRequest)
    returns (ControllerProbeResponse) {}

  rpc ControllerGetCapabilities (ControllerGetCapabilitiesRequest)
    returns (ControllerGetCapabilitiesResponse) {}  
}

service Node {
  rpc NodePublishVolume (NodePublishVolumeRequest)
    returns (NodePublishVolumeResponse) {}

  rpc NodeUnpublishVolume (NodeUnpublishVolumeRequest)
    returns (NodeUnpublishVolumeResponse) {}

  rpc NodeGetId (NodeGetIdRequest)
    returns (NodeGetIdResponse) {}

  rpc NodeProbe (NodeProbeRequest)
    returns (NodeProbeResponse) {}

  rpc NodeGetCapabilities (NodeGetCapabilitiesRequest)
    returns (NodeGetCapabilitiesResponse) {}
}
////////
////////
message GetSupportedVersionsRequest {
}

message GetSupportedVersionsResponse {
  // All the CSI versions that the Plugin supports. This field is
  // REQUIRED.
  repeated Version supported_versions = 1;
}

// Specifies a version in Semantic Version 2.0 format.
// (http://semver.org/spec/v2.0.0.html)
message Version {
  // The value of this field MUST NOT be negative.
  int32 major = 1;  // This field is REQUIRED.
  // The value of this field MUST NOT be negative.
  int32 minor = 2;  // This field is REQUIRED.
  // The value of this field MUST NOT be negative.
  int32 patch = 3;  // This field is REQUIRED.
}
////////
////////
message GetPluginInfoRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;
}

message GetPluginInfoResponse {
  // The name MUST follow reverse domain name notation format
  // (https://en.wikipedia.org/wiki/Reverse_domain_name_notation).
  // It SHOULD include the plugin's host company name and the plugin
  // name, to minimize the possibility of collisions. It MUST be 63
  // characters or less, beginning and ending with an alphanumeric
  // character ([a-z0-9A-Z]) with dashes (-), underscores (_),
  // dots (.), and alphanumerics between. This field is REQUIRED.
  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 CreateVolumeRequest {
  // The API version assumed by the CO. This field is REQUIRED.
  Version version = 1;

  // The suggested name for the storage space. This field is REQUIRED.
  // It serves two purposes:
  // 1) Idempotency - This name is generated by the CO to achieve
  //    idempotency. If `CreateVolume` fails, the volume may or may not
  //    be provisioned. In this case, the CO may call `CreateVolume`
  //    again, with the same name, to ensure the volume exists. The
  //    Plugin should ensure that multiple `CreateVolume` calls for the
  //    same name do not result in more than one piece of storage
  //    provisioned corresponding to that name. If a Plugin is unable to
  //    enforce idempotency, the CO's error recovery logic could result
  //    in multiple (unused) volumes being provisioned.
  // 2) Suggested name - Some storage systems allow callers to specify
  //    an identifier by which to refer to the newly provisioned
  //    storage. If a storage system supports this, it can optionally
  //    use this name as the identifier for the new volume.
  string name = 2;

  // This field is OPTIONAL. This allows the CO to specify the capacity
  // requirement of the volume to be provisioned. If not specified, the
  // Plugin MAY choose an implementation-defined capacity range.
  CapacityRange capacity_range = 3;

  // The capabilities that the provisioned volume MUST have: the Plugin
  // MUST provision a volume that could satisfy ALL of the
  // capabilities specified in this list. The Plugin MUST assume that
  // the CO MAY use the  provisioned volume later with ANY of the
  // capabilities specified in this list. This also enables the CO to do
  // early validation: if ANY of the specified volume capabilities are
  // not supported by the Plugin, the call SHALL fail. This field is
  // REQUIRED.
  repeated VolumeCapability volume_capabilities = 4;

  // 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 = 5;

  // Credentials used by Controller plugin to authenticate/authorize
  // volume creation request.
  // This field contains credential data, for example username and
  // password. Each key must consist of alphanumeric characters, '-',
  // '_' or '.'. Each value MUST contain a valid string. An SP MAY
  // choose to accept binary (non-string) data by using a binary-to-text
  // encoding scheme, like base64. An SP SHALL advertise the
  // requirements for credentials in documentation. COs SHALL permit
  // passing through the required credentials. This information is
  // sensitive and MUST be treated as such (not logged, etc.) by the CO.
  // This field is OPTIONAL.
  map<string, string> controller_create_credentials = 6;
}

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` can 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;
}

// The information about a provisioned 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;

  // Contains identity information for the created volume. This field is
  // REQUIRED. The identity information will be used by the CO in
  // subsequent calls to refer to the provisioned volume.
  string id = 2;

  // Attributes reflect static properties of a volume and MUST be passed
  // to volume validation and publishing calls.
  // Attributes SHALL be opaque to a CO. Attributes SHALL NOT be mutable
  // and SHALL be safe for the CO to cache. Attributes SHOULD NOT
  // contain sensitive information. Attributes MAY NOT uniquely identify
  // a volume. A volume uniquely identified by `id` SHALL always report
  // the same attributes. This field is OPTIONAL and when present MUST
  // be passed to volume validation and publishing calls.
  map<string,string> attributes = 3;
}
////////
////////
message DeleteVolumeRequest {
  // The API version assumed by the CO. This field is REQUIRED.
  Version version = 1;

  // The ID of the volume to be deprovisioned.
  // This field is REQUIRED.
  string volume_id = 2;

  // Credentials used by Controller plugin to authenticate/authorize
  // volume deletion request.
  // This field contains credential data, for example username and
  // password. Each key must consist of alphanumeric characters, '-',
  // '_' or '.'. Each value MUST contain a valid string. An SP MAY
  // choose to accept binary (non-string) data by using a binary-to-text
  // encoding scheme, like base64. An SP SHALL advertise the
  // requirements for credentials in documentation. COs SHALL permit
  // passing through the required credentials. This information is
  // sensitive and MUST be treated as such (not logged, etc.) by the CO.
  // This field is OPTIONAL.
  map<string, string> controller_delete_credentials = 3;
}

message DeleteVolumeResponse {}
////////
////////
message ControllerPublishVolumeRequest {
  // The API version assumed by the CO. This field is REQUIRED.
  Version version = 1;

  // The ID of the volume to be used on a node.
  // This field is REQUIRED.
  string volume_id = 2;

  // The ID of the node. This field is REQUIRED. The CO SHALL set this
  // field to match the node ID returned by `NodeGetId`.
  string node_id = 3;

  // The capability of the volume the CO expects the volume to have.
  // This is a REQUIRED field.
  VolumeCapability volume_capability = 4;

  // Whether to publish the volume in readonly mode. This field is
  // REQUIRED.
  bool readonly = 5;

  // Credentials used by Controller plugin to authenticate/authorize
  // controller publish request.
  // This field contains credential data, for example username and
  // password. Each key must consist of alphanumeric characters, '-',
  // '_' or '.'. Each value MUST contain a valid string. An SP MAY
  // choose to accept binary (non-string) data by using a binary-to-text
  // encoding scheme, like base64. An SP SHALL advertise the
  // requirements for credentials in documentation. COs SHALL permit
  // passing through the required credentials. This information is
  // sensitive and MUST be treated as such (not logged, etc.) by the CO.
  // This field is OPTIONAL.
  map<string, string> controller_publish_credentials = 6;

  // Attributes of the volume to be used on a node. This field is
  // OPTIONAL and MUST match the attributes of the Volume identified
  // by `volume_id`.
  map<string,string> volume_attributes = 7;
}

message ControllerPublishVolumeResponse {
  // The SP specific information that will be passed to the Plugin in
  // the subsequent `NodePublishVolume` call for the given volume.
  // This information is opaque to the CO. This field is OPTIONAL.
  map<string, string> publish_info = 1;
}
////////
////////
message ControllerUnpublishVolumeRequest {
  // The API version assumed by the CO. This field is REQUIRED.
  Version version = 1;

  // The ID of the volume. This field is REQUIRED.
  string volume_id = 2;

  // The ID of the node. This field is OPTIONAL. The CO SHOULD set this
  // field to match the node ID returned by `NodeGetId` 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 = 3;

  // Credentials used by Controller plugin to authenticate/authorize
  // controller unpublish request.
  // This field contains credential data, for example username and
  // password. Each key must consist of alphanumeric characters, '-',
  // '_' or '.'. Each value MUST contain a valid string. An SP MAY
  // choose to accept binary (non-string) data by using a binary-to-text
  // encoding scheme, like base64. An SP SHALL advertise the
  // requirements for credentials in documentation. COs SHALL permit
  // passing through the required credentials. This information is
  // sensitive and MUST be treated as such (not logged, etc.) by the CO.
  // This field is OPTIONAL.
  map<string, string> controller_unpublish_credentials = 4;
}

message ControllerUnpublishVolumeResponse {}
////////
////////
message ValidateVolumeCapabilitiesRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;

  // The ID of the volume to check. This field is REQUIRED.
  string volume_id = 2;

  // The capabilities that the CO wants to check for the volume. This
  // call SHALL return "supported" only if all the volume capabilities
  // specified below are supported. This field is REQUIRED.
  repeated VolumeCapability volume_capabilities = 3;

  // Attributes of the volume to check. This field is OPTIONAL and MUST
  // match the attributes of the Volume identified by `volume_id`.
  map<string,string> volume_attributes = 4;
}

message ValidateVolumeCapabilitiesResponse {
  // True if the Plugin supports the specified capabilities for the
  // given volume. This field is REQUIRED.
  bool supported = 1;

  // Message to the CO if `supported` above is false. This field is
  // OPTIONAL.
  // An empty string is equal to an unspecified field value.
  string message = 2;
}
////////
////////
message ListVolumesRequest {
  // The API version assumed by the CO. This field is REQUIRED.
  Version version = 1;

  // 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 = 2;

  // 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 = 3;
}

message ListVolumesResponse {
  message Entry {
    Volume volume = 1;
  }

  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 GetCapacityRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;

  // 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 = 2;

  // 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 = 3;
}

message GetCapacityResponse {
  // The available capacity of the storage that can be used to
  // provision volumes. If `volume_capabilities` or `parameters` is
  // specified in the request, the Plugin SHALL take those into
  // consideration when calculating the available capacity of the
  // storage. This field is REQUIRED.
  // The value of this field MUST NOT be negative. 
  int64 available_capacity = 1;
}
////////
////////
message ControllerProbeRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;
}

message ControllerProbeResponse {}
////////
////////
message ControllerGetCapabilitiesRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;
}

message ControllerGetCapabilitiesResponse {
  // All the capabilities that the controller service supports. This
  // field is OPTIONAL.
  repeated ControllerServiceCapability capabilities = 2;
}

// Specifies a capability of the controller service.
message ControllerServiceCapability {
  message RPC {
    enum Type {
      UNKNOWN = 0;
      CREATE_DELETE_VOLUME = 1;
      PUBLISH_UNPUBLISH_VOLUME = 2;
      LIST_VOLUMES = 3;
      GET_CAPACITY = 4;
    }

    Type type = 1;
  }

  oneof type {
    // RPC that the controller supports.
    RPC rpc = 1;
  }
}
////////
////////
message NodePublishVolumeRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;

  // The ID of the volume to publish. This field is REQUIRED.
  string volume_id = 2;

  // The CO SHALL set this field to the value returned by
  // `ControllerPublishVolume` if the corresponding Controller Plugin
  // has `PUBLISH_UNPUBLISH_VOLUME` controller capability, and SHALL be
  // left unset if the corresponding Controller Plugin does not have
  // this capability. This is an OPTIONAL field.
  map<string, string> publish_info = 3;

  // The path to which the volume will be published. It MUST be an
  // absolute path in the root filesystem of the process serving this
  // request. The CO SHALL ensure uniqueness of target_path per volume.
  // The CO SHALL ensure that the path exists, and that the process
  // serving the request has `read` and `write` permissions to the path.
  // This is a REQUIRED field.
  string target_path = 4;

  // The capability of the volume the CO expects the volume to have.
  // This is a REQUIRED field.
  VolumeCapability volume_capability = 5;

  // Whether to publish the volume in readonly mode. This field is
  // REQUIRED.
  bool readonly = 6;

  // Credentials used by Node plugin to authenticate/authorize node
  // publish request.
  // This field contains credential data, for example username and
  // password. Each key must consist of alphanumeric characters, '-',
  // '_' or '.'. Each value MUST contain a valid string. An SP MAY
  // choose to accept binary (non-string) data by using a binary-to-text
  // encoding scheme, like base64. An SP SHALL advertise the
  // requirements for credentials in documentation. COs SHALL permit
  // passing through the required credentials. This information is
  // sensitive and MUST be treated as such (not logged, etc.) by the CO.
  // This field is OPTIONAL.
  map<string, string> node_publish_credentials = 7;

  // Attributes of the volume to publish. This field is OPTIONAL and
  // MUST match the attributes of the Volume identified by
  // `volume_id`.
  map<string,string> volume_attributes = 8;
}

message NodePublishVolumeResponse {}
////////
////////
message NodeUnpublishVolumeRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;

  // The ID of the volume. This field is REQUIRED.
  string volume_id = 2;

  // The path at which the volume was published. It MUST be an absolute
  // path in the root filesystem of the process serving this request.
  // This is a REQUIRED field.
  string target_path = 3;

  // Credentials used by Node plugin to authenticate/authorize node
  // unpublish request.
  // This field contains credential data, for example username and
  // password. Each key must consist of alphanumeric characters, '-',
  // '_' or '.'. Each value MUST contain a valid string. An SP MAY
  // choose to accept binary (non-string) data by using a binary-to-text
  // encoding scheme, like base64. An SP SHALL advertise the
  // requirements for credentials in documentation. COs SHALL permit
  // passing through the required credentials. This information is
  // sensitive and MUST be treated as such (not logged, etc.) by the CO.
  // This field is OPTIONAL.
  map<string, string> node_unpublish_credentials = 4;
}

message NodeUnpublishVolumeResponse {}
////////
////////
message NodeGetIdRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;
}

message NodeGetIdResponse {
  // The ID of the node as understood by the SP which SHALL be used by
  // CO in subsequent `ControllerPublishVolume`.
  // This is a REQUIRED field.
  string node_id = 1;
}
////////
////////
message NodeProbeRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;
}

message NodeProbeResponse {}
////////
////////
message NodeGetCapabilitiesRequest {
  // The API version assumed by the CO. This is a REQUIRED field.
  Version version = 1;
}

message NodeGetCapabilitiesResponse {
  // All the capabilities that the node service supports. This field
  // is OPTIONAL.
  repeated NodeServiceCapability capabilities = 1;
}

// Specifies a capability of the node service.
message NodeServiceCapability {
  message RPC {
    enum Type {
      UNKNOWN = 0;
    }

    Type type = 1;
  }

  oneof type {
    // RPC that the controller supports.
    RPC rpc = 1;
  }
}
////////