@@ -316,7 +316,7 @@ proposal will be implemented, this is the place to discuss them.
316316
317317The proposed design involves extending CSI with the ` VolumeSnapshotDelta ` CRD.
318318Storage providers can opt in to support this feature by implementing the
319- ` VOLUME_SNAPSHOT_DELTA_SERVICE ` capability in their CSI drivers.
319+ ` SNAPSHOT_DELTA ` capability in their CSI drivers.
320320
321321The ` VolumeSnapshotDelta ` resource is a namespace-scoped resource. It must be
322322created in the same namespace as the base and target CSI ` VolumeSnapshot ` s.
@@ -398,72 +398,190 @@ The section describes the specification of proposed API. The Go types of the CRD
398398are defined as follows:
399399
400400``` go
401- // VolumeSnapshotDelta is a specification for a VolumeSnapshotDelta resource
401+ // VolumeSnapshotDelta represents a VolumeSnapshotDelta resource.
402402type VolumeSnapshotDelta struct {
403- metav1.TypeMeta ` json:",inline"`
403+ metav1.TypeMeta ` json:",inline"`
404404
405+ // Standard object's metadata.
406+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
405407 // +optional
406408 metav1.ObjectMeta ` json:"metadata,omitempty"`
407409
408- Spec VolumeSnapshotDeltaSpec ` json:"spec"`
410+ // spec defines the desired characteristics of a snapshot delta requested by a user.
411+ // More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots
412+ // Required.
413+ Spec VolumeSnapshotDeltaSpec ` json:"spec"`
409414
415+ // status represents the current information of a snapshot delta.
410416 // +optional
411417 Status VolumeSnapshotDeltaStatus ` json:"status,omitempty"`
412418}
413419
414- // VolumeSnapshotDeltaSpec is the spec for a VolumeSnapshotDelta resource
420+ // VolumeSnapshotDeltaSpec is the spec of a VolumeSnapshotDelta resource.
415421type VolumeSnapshotDeltaSpec struct {
416- BaseVolumeSnapshotName string ` json:"baseVolumeSnapshotName,omitempty"` // name of the base VolumeSnapshot; optional
417- TargetVolumeSnapshotName string ` json:"targetVolumeSnapshotName"` // name of the target VolumeSnapshot; required
418- Mode string ` json:"mode,omitempty"` // default to "block"
422+ // The name of the base CSI volume snapshot to use for comparison.
423+ // If not specified, return all changed blocks.
424+ // +optional
425+ BaseVolumeSnapshotName string ` json:"baseVolumeSnapshotName,omitempty"`
426+
427+ // The name of the target CSI volume snapshot to use for comparison.
428+ // Required.
429+ TargetVolumeSnapshotName string ` json:"targetVolumeSnapshotName"`
430+
431+ // Defines the type of volume. Default to "block".
432+ // Required.
433+ Mode string ` json:"mode,omitempty"`
419434}
420435
421436// VolumeSnapshotDeltaStatus is the status for a VolumeSnapshotDelta resource
422437type VolumeSnapshotDeltaStatus struct {
423- Error string ` json:"error,omitempty"`
424- State string ` json:"state"`
425- CallbackURL string ` json:"callbackURL"`
438+ // Captures any error encountered.
439+ Error string ` json:"error,omitempty"`
440+
441+ // The Callback URL to send the CBT requests to.
442+ CallbackURL string ` json:"callbackURL"`
443+
444+ // A very brief description to communicate the current state of the CBT
445+ // operation.
446+ State VolumeSnapshotDeltaState ` json:"state"`
447+ }
448+
449+ type VolumeSnaphotDeltaState int
450+
451+ const (
452+ TransferringData VolumeSnapshotDeltaState = iota
453+ Failed
454+ Pending
455+ URLReady
456+ )
457+
458+ func (s VolumeSnapshotDeltaState ) String () string {
459+ switch s {
460+ case TransferringData:
461+ return " transferring-data"
462+ case Failed:
463+ return " failed"
464+ case URLReady:
465+ return " url-ready"
466+ case Pending:
467+ fallthrough
468+ default :
469+ return " pending"
470+ }
426471}
427472
428473// VolumeSnapshotDeltaList is a list of VolumeSnapshotDelta resources
429474type VolumeSnapshotDeltaList struct {
430- metav1.TypeMeta ` json:",inline"`
431- metav1.ListMeta ` json:"metadata"`
475+ metav1.TypeMeta ` json:",inline"`
476+
477+ // +optional
478+ metav1.ListMeta ` json:"metadata"`
479+
480+ // list of VolumeSnapshotDeltas.
432481 Items []VolumeSnapshotDelta ` json:"items"`
433482}
434483```
435484
436- The corresponding GRPC service definition is as follows:
485+ The corresponding GRPC service and message definition are as follows:
437486
438487``` grpc
488+ syntax = "proto3";
489+
490+ import "google/protobuf/timestamp.proto";
491+ import "google/protobuf/duration.proto";
492+
439493service VolumeSnapshotDelta {
440- rpc GetVolumeSnapshotDelta (VolumeSnapshotDeltaRequest)
494+ rpc ListVolumeSnapshotDeltas (VolumeSnapshotDeltaRequest)
441495 returns (VolumeSnapshotDeltaResponse) {}
442496}
443497
444- type VolumeSnapshotDeltaRequest struct {
445- // If SnapshotBase is not specified, return all used blocks.
446- SnapshotBase string // Snapshot handle, optional.
447- SnapshotTarget string // Snapshot handle, required.
448- Mode string // Volume mode, default "Block"
449- StartOffset string // Logical offset from beginning of disk/volume.
450- // Use string instead of uint64 to give vendor
451- // the flexibility of implementing it either
452- // string "token" or a number.
453- MaxEntries uint64 // Maximum number of entries in the response
498+ message VolumeSnapshotDeltaRequest {
499+ // The name of the base snapshot handle to use for comparison.
500+ // If not specified, return all changed blocks.
501+ // This field is OPTIONAL.
502+ string snapshot_base = 1;
503+
504+ // The name of the target snapshot handle to use for comparison.
505+ // If not specified, an error is returned.
506+ // This field is REQUIRED.
507+ string snapshot_target = 2;
508+
509+ // Defines the type of volume. Default to "block".
510+ // This field is REQUIRED.
511+ string mode = 3;
512+
513+ // A token to specify where to start paginating. Set this field to
514+ // `next_token` returned by a previous `ListVolumeSnapshotDeltas` call to get
515+ // the next page of entries. An empty string is equal to an unspecified field
516+ // value.
517+ // This field is OPTIONAL.
518+ string starting_token = 4;
519+
520+ // If specified (non-zero value), the Plugin MUST NOT return more entries than
521+ // this number in the response. If the actual number of entries is more than
522+ // this number, the Plugin MUST set `next_token` in the response which can be
523+ // used to get the next page of entries in the subsequent
524+ // `ListVolumeSnapshotDeltas` call. If not specified (zero value), it will be
525+ // default to 256 entries. The value of this field MUST NOT be negative.
526+ // This field is REQUIRED.
527+ int32 max_entries = 5;
528+ }
529+
530+ message VolumeSnapshotDeltaResponse {
531+ // Snapshot deltas for block volume snapshots. An empty list means there are
532+ // no block deltas between the base and target snapshots. If unspecified, it
533+ // means the volume isn't of block type.
534+ // This field is OPTIONAL.
535+ BlockVolumeSnapshotDelta block_delta = 1;
536+
537+ // The volume size in bytes.
538+ // This field is OPTIONAL.
539+ uint64 volume_size_bytes = 2;
540+
541+ // This token allows you to get the next page of entries for
542+ // `ListVolumeSnapshotDeltas` request. If the number of entries is larger than
543+ // `max_entries`, use the `next_token` as a value for the
544+ // `starting_token` field in the next `ListVolumeSnapshotDeltas` request.
545+ // An empty string is equal to an unspecified field value.
546+ // This field is OPTIONAL.
547+ string next_token = 3;
454548}
455549
456- type VolumeSnapshotDeltaResponse struct {
457- ChangeBlockList []ChangedBlock // array of ChangedBlock (for "Block" mode)
458- NextOffset string // StartOffset of the next “page”.
459- VolumeSize uint64 // size of volume in bytes
460- Timeout uint64 // Time when the result of this differential snapshot is
461- // available in the backend storage. Seconds since epoch.
462- }
463-
464- type ChangedBlock struct {
465- Offset uint64 // logical offset
466- Size uint64 // size of the block data
550+ message BlockVolumeSnapshotDelta {
551+ // The list of changed blocks deltas. If empty, it means there are no
552+ // differences between the base and target snapshots.
553+ // This field is OPTIONAL.
554+ repeated ChangedBlockDelta changed_block_deltas = 1;
555+ }
556+
557+ message ChangedBlockDelta {
558+ // The block logical offset on the volume.
559+ // This field is REQUIRED.
560+ uint64 offset = 1;
561+
562+ // The size of the block in bytes.
563+ // This field is REQUIRED.
564+ uint64 block_size_bytes = 2;
565+
566+ // The token and other information needed to retrieve the actual data block
567+ // at the given offset. If the provider doesn't support token-based data
568+ // blocks retrieval, this should be left unspecified.
569+ // This field is OPTIONAL.
570+ DataToken data_token = 3;
571+ }
572+
573+ message DataToken {
574+ // The token to use to retrieve the actual data block at the given offset.
575+ // This field is REQUIRED.
576+ string token = 1;
577+
578+ // Timestamp when the token is issued.
579+ // This field is REQUIRED.
580+ .google.protobuf.Timestamp issuance_time = 4;
581+
582+ // The TTL of the token in seconds. The expiry time is calculated by adding
583+ // the time of issuance with this value.
584+ .google.protobuf.Duration ttl_seconds = 2;
467585}
468586```
469587
@@ -1033,7 +1151,7 @@ associated with these GVRs:
10331151- apiGroups : ["snapshot.storage.k8s.io"]
10341152 resources : ["volumesnapshotdeltas"]
10351153- apiGroups : ["snapshot.storage.k8s.io"]
1036- resources : ["volumesnapshotcontents", "volumesnapshots"]
1154+ resources : ["volumesnapshotcontents", "volumesnapshots", "volumesnapshotclasses" ]
10371155 verbs : ["get", "list"]
10381156 verbs : ["get", "list", "watch"]
10391157- apiGroups : ["authorization.k8s.io"]
0 commit comments