Skip to content

Commit b448dd0

Browse files
committed
convert civo snapshot to CSI snapshot
1 parent a92a729 commit b448dd0

File tree

1 file changed

+90
-33
lines changed

1 file changed

+90
-33
lines changed

Diff for: pkg/driver/controller_server.go

+90-33
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,8 @@ func (d *Driver) ControllerGetCapabilities(context.Context, *csi.ControllerGetCa
586586
csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
587587
csi.ControllerServiceCapability_RPC_GET_CAPACITY,
588588
csi.ControllerServiceCapability_RPC_EXPAND_VOLUME,
589-
// csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT, TODO: Uncomment after client implementation is complete.
590-
// csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS, TODO: Uncomment after client implementation is complete.
589+
csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
590+
csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
591591
}
592592

593593
var csc []*csi.ControllerServiceCapability
@@ -651,13 +651,16 @@ func (d *Driver) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequ
651651
if err != nil {
652652
return nil, status.Error(codes.Internal, fmt.Sprintf("failed to parse creation time: %v", err))
653653
}
654+
655+
isReady := isSnapshotReady(snapshot.State)
656+
654657
return &csi.CreateSnapshotResponse{
655658
Snapshot: &csi.Snapshot{
656659
SnapshotId: snapshot.SnapshotID,
657660
SourceVolumeId: snapshot.VolumeID,
658-
CreationTime: creationTime, // TODO
659-
SizeBytes: int64(snapshot.RestoreSize),
660-
ReadyToUse: true, // TODO
661+
CreationTime: creationTime,
662+
SizeBytes: int64(snapshot.RestoreSize),
663+
ReadyToUse: isReady,
661664
},
662665
}, nil
663666
}
@@ -705,13 +708,16 @@ func (d *Driver) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequ
705708
if err != nil {
706709
return nil, status.Error(codes.Internal, fmt.Sprintf("failed to parse creation time: %v", err))
707710
}
711+
712+
isReady := isSnapshotReady(snapshot.State)
713+
708714
return &csi.CreateSnapshotResponse{
709715
Snapshot: &csi.Snapshot{
710716
SnapshotId: snapshot.SnapshotID,
711717
SourceVolumeId: snapshot.VolumeID,
712-
CreationTime: creationTime, // TODO:
713-
SizeBytes: int64(snapshot.RestoreSize),
714-
// ReadyToUse: true, // TODO:
718+
CreationTime: creationTime,
719+
SizeBytes: int64(snapshot.RestoreSize),
720+
ReadyToUse: isReady,
715721
},
716722
}, nil
717723
}
@@ -768,9 +774,7 @@ func (d *Driver) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsReques
768774

769775
snapshot, err := d.CivoClient.GetVolumeSnapshotByVolumeID(sourceVolumeID, snapshotID)
770776
if err != nil {
771-
// Todo: DatabaseSnapshotNotFoundError & DiskSnapshotNotFoundError are placeholders, it's still not clear what error will be returned by API (awaiting implementation - WIP)
772-
if strings.Contains(err.Error(), "DatabaseSnapshotNotFoundError") ||
773-
strings.Contains(err.Error(), "DiskSnapshotNotFoundError") {
777+
if strings.Contains(err.Error(), "DatabaseSnapshotNotFoundError") {
774778
log.Info().
775779
Str("snapshot_id", snapshotID).
776780
Str("source_volume_id", sourceVolumeID).
@@ -784,9 +788,19 @@ func (d *Driver) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsReques
784788
Msg("Failed to list snapshot from Civo API")
785789
return nil, status.Errorf(codes.Internal, "failed to list snapshot %q: %v", snapshotID, err)
786790
}
791+
entry, err := convertSnapshot(snapshot)
792+
if err != nil {
793+
log.Error().
794+
Err(err).
795+
Str("SnapshotID", snapshot.SnapshotID).
796+
Str("VolumeID", snapshot.VolumeID).
797+
Msg("Failed to convert civo snapshot to CSI snapshot")
798+
return nil, status.Errorf(codes.Internal, "failed to convert civo snapshot to CSI snapshot %s: %v", snapshot.SnapshotID, err)
799+
}
800+
787801
return &csi.ListSnapshotsResponse{
788802
Entries: []*csi.ListSnapshotsResponse_Entry{
789-
convertSnapshot(snapshot),
803+
entry,
790804
},
791805
}, nil
792806
}
@@ -798,9 +812,7 @@ func (d *Driver) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsReques
798812

799813
snapshot, err := d.CivoClient.GetVolumeSnapshot(snapshotID)
800814
if err != nil {
801-
// Todo: DatabaseSnapshotNotFoundError & DiskSnapshotNotFoundError are placeholders, it's still not clear what error will be returned by API (awaiting implementation - WIP)
802-
if strings.Contains(err.Error(), "DatabaseSnapshotNotFoundError") ||
803-
strings.Contains(err.Error(), "DiskSnapshotNotFoundError") {
815+
if strings.Contains(err.Error(), "DatabaseSnapshotNotFoundError") {
804816
log.Info().
805817
Str("snapshot_id", snapshotID).
806818
Msg("ListSnapshots: no snapshot found, returning with success")
@@ -812,9 +824,19 @@ func (d *Driver) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsReques
812824
Msg("Failed to list snapshot from Civo API")
813825
return nil, status.Errorf(codes.Internal, "failed to list snapshot %q: %v", snapshotID, err)
814826
}
827+
828+
entry, err := convertSnapshot(snapshot)
829+
if err != nil {
830+
log.Error().
831+
Err(err).
832+
Str("SnapshotID", snapshot.SnapshotID).
833+
Str("VolumeID", snapshot.VolumeID).
834+
Msg("Failed to convert civo snapshot to CSI snapshot")
835+
return nil, status.Errorf(codes.Internal, "failed to convert civo snapshot to CSI snapshot %s: %v", snapshot.SnapshotID, err)
836+
}
815837
return &csi.ListSnapshotsResponse{
816838
Entries: []*csi.ListSnapshotsResponse_Entry{
817-
convertSnapshot(snapshot),
839+
entry,
818840
},
819841
}, nil
820842
}
@@ -837,7 +859,16 @@ func (d *Driver) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsReques
837859
entries := []*csi.ListSnapshotsResponse_Entry{}
838860
for _, snapshot := range snapshots {
839861
if snapshot.VolumeID == sourceVolumeID {
840-
entries = append(entries, convertSnapshot(&snapshot))
862+
entry, err := convertSnapshot(&snapshot)
863+
if err != nil {
864+
log.Error().
865+
Err(err).
866+
Str("SnapshotID", snapshot.SnapshotID).
867+
Str("VolumeID", snapshot.VolumeID).
868+
Msg("Failed to convert civo snapshot to CSI snapshot")
869+
return nil, status.Errorf(codes.Internal, "failed to convert civo snapshot to CSI snapshot %s: %v", snapshot.SnapshotID, err)
870+
}
871+
entries = append(entries, entry)
841872
}
842873
}
843874
sort.Slice(entries, func(i, j int) bool {
@@ -862,8 +893,19 @@ func (d *Driver) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsReques
862893
})
863894

864895
entries := []*csi.ListSnapshotsResponse_Entry{}
896+
865897
for _, snap := range snapshots {
866-
entries = append(entries, convertSnapshot(&snap))
898+
entry, err := convertSnapshot(&snap)
899+
if err != nil {
900+
log.Error().
901+
Err(err).
902+
Str("SnapshotID", snap.SnapshotID).
903+
Str("VolumeID", snap.VolumeID).
904+
Msg("Failed to convert civo snapshot to CSI snapshot")
905+
return nil, status.Errorf(codes.Internal, "failed to convert civo snapshot to CSI snapshot %s: %v", snap.SnapshotID, err)
906+
}
907+
entries = append(entries, entry)
908+
867909
}
868910

869911
log.Info().
@@ -890,26 +932,41 @@ func getVolSizeInBytes(capRange *csi.CapacityRange) (int64, error) {
890932
}
891933

892934
// convertSnapshot function converts a civogo.Snapshot object(API response) into a CSI ListSnapshotsResponse_Entry
893-
func convertSnapshot(in *civogo.VolumeSnapshot) *csi.ListSnapshotsResponse_Entry {
894-
// creationTime, err := ParseTimeToProtoTimestamp(in.CreationTime)
895-
// if err != nil {
896-
// return nil, status.Error(codes.Internal, fmt.Sprintf("failed to parse creation time: %v", err))
897-
// }
935+
func convertSnapshot(in *civogo.VolumeSnapshot) (*csi.ListSnapshotsResponse_Entry, error) {
936+
creationTime, err := ParseTimeToProtoTimestamp(in.CreationTime)
937+
if err != nil {
938+
return nil, fmt.Errorf("failed to parse creation time for snapshot %s: %w", in.SnapshotID, err)
939+
}
940+
941+
// Explicitly define which state indicates the snapshot is ready for use
942+
isReady := isSnapshotReady(in.State)
943+
898944
return &csi.ListSnapshotsResponse_Entry{
899945
Snapshot: &csi.Snapshot{
900946
SnapshotId: in.SnapshotID,
901947
SourceVolumeId: in.VolumeID,
902-
// CreationTime: snap.CreationTime,
903-
SizeBytes: int64(in.RestoreSize),
904-
// ReadyToUse: snap.ReadyToUse,
948+
CreationTime: creationTime,
949+
SizeBytes: int64(in.RestoreSize),
950+
ReadyToUse: isReady,
905951
},
906-
}
952+
}, nil
907953
}
908954

955+
// ParseTimeToProtoTimestamp parses a time string in RFC3339 format to *timestamppb.Timestamp.
909956
func ParseTimeToProtoTimestamp(timeStr string) (*timestamppb.Timestamp, error) {
910-
t, err := time.Parse(time.RFC3339, timeStr)
911-
if err != nil {
912-
return nil, err
913-
}
914-
return timestamppb.New(t), nil
915-
}
957+
t, err := time.Parse(time.RFC3339, timeStr)
958+
if err != nil {
959+
return nil, err
960+
}
961+
return timestamppb.New(t), nil
962+
}
963+
964+
// isSnapshotReady determines if a snapshot is ready for use
965+
func isSnapshotReady(state string) bool {
966+
// Define the states that indicate the snapshot is ready
967+
readyStates := map[string]bool{
968+
"Ready": true,
969+
"Available": true, // Add other states if applicable
970+
}
971+
return readyStates[state]
972+
}

0 commit comments

Comments
 (0)