Change all occurences of content to group snapshot content

This commit is contained in:
Raunak Pradip Shah
2023-04-26 13:06:03 +05:30
parent 871312988b
commit d8d01a38e4
4 changed files with 182 additions and 181 deletions

View File

@@ -26,16 +26,16 @@ import (
"time" "time"
) )
// GroupSnapshotter implements CreateGroupSnapshot/DeleteGroupSnapshot operations against a remote CSI driver. // GroupSnapshotter implements CreateGroupSnapshot/DeleteGroupSnapshot operations against a CSI driver.
type GroupSnapshotter interface { type GroupSnapshotter interface {
// CreateGroupSnapshot creates a snapshot for a volume // CreateGroupSnapshot creates a group snapshot for multiple volumes
CreateGroupSnapshot(ctx context.Context, groupSnapshotName string, volumeIDs []string, parameters map[string]string, snapshotterCredentials map[string]string) (driverName string, snapshotId string, snapshots []*csi.Snapshot, timestamp time.Time, readyToUse bool, err error) CreateGroupSnapshot(ctx context.Context, groupSnapshotName string, volumeIDs []string, parameters map[string]string, snapshotterCredentials map[string]string) (driverName string, groupSnapshotId string, snapshots []*csi.Snapshot, timestamp time.Time, readyToUse bool, err error)
// DeleteGroupSnapshot deletes a snapshot from a volume // DeleteGroupSnapshot deletes a group snapshot of multiple volumes
DeleteGroupSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) (err error) DeleteGroupSnapshot(ctx context.Context, groupSnapshotID string, snapshotterCredentials map[string]string) (err error)
// GetGroupSnapshotStatus returns if a snapshot is ready to use, creation time, and restore size. // GetGroupSnapshotStatus returns if a group snapshot is ready to use, its creation time, etc
GetGroupSnapshotStatus(ctx context.Context, snapshotID string, snapshotterListCredentials map[string]string) (bool, time.Time, error) GetGroupSnapshotStatus(ctx context.Context, groupSnapshotID string, snapshotterListCredentials map[string]string) (bool, time.Time, error)
} }
type groupSnapshot struct { type groupSnapshot struct {
@@ -49,7 +49,7 @@ func NewGroupSnapshotter(conn *grpc.ClientConn) GroupSnapshotter {
} }
func (gs *groupSnapshot) CreateGroupSnapshot(ctx context.Context, groupSnapshotName string, volumeIDs []string, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, []*csi.Snapshot, time.Time, bool, error) { func (gs *groupSnapshot) CreateGroupSnapshot(ctx context.Context, groupSnapshotName string, volumeIDs []string, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, []*csi.Snapshot, time.Time, bool, error) {
klog.V(5).Infof("CSI CreateSnapshot: %s", groupSnapshotName) klog.V(5).Infof("CSI CreateGroupSnapshot: %s", groupSnapshotName)
client := csi.NewGroupControllerClient(gs.conn) client := csi.NewGroupControllerClient(gs.conn)
driverName, err := csirpc.GetDriverName(ctx, gs.conn) driverName, err := csirpc.GetDriverName(ctx, gs.conn)
@@ -69,7 +69,7 @@ func (gs *groupSnapshot) CreateGroupSnapshot(ctx context.Context, groupSnapshotN
return "", "", nil, time.Time{}, false, err return "", "", nil, time.Time{}, false, err
} }
klog.V(5).Infof("CSI CreateSnapshot: %s driver name [%s] snapshot ID [%s] time stamp [%v] snapshots [%v] readyToUse [%v]", groupSnapshotName, driverName, rsp.GroupSnapshot.GroupSnapshotId, rsp.GroupSnapshot.CreationTime, rsp.GroupSnapshot.Snapshots, rsp.GroupSnapshot.ReadyToUse) klog.V(5).Infof("CSI CreateGroupSnapshot: %s driver name [%s] group snapshot ID [%s] time stamp [%v] snapshots [%v] readyToUse [%v]", groupSnapshotName, driverName, rsp.GroupSnapshot.GroupSnapshotId, rsp.GroupSnapshot.CreationTime, rsp.GroupSnapshot.Snapshots, rsp.GroupSnapshot.ReadyToUse)
creationTime, err := ptypes.Timestamp(rsp.GroupSnapshot.CreationTime) creationTime, err := ptypes.Timestamp(rsp.GroupSnapshot.CreationTime)
if err != nil { if err != nil {
return "", "", nil, time.Time{}, false, err return "", "", nil, time.Time{}, false, err
@@ -78,12 +78,12 @@ func (gs *groupSnapshot) CreateGroupSnapshot(ctx context.Context, groupSnapshotN
} }
func (gs *groupSnapshot) DeleteGroupSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) error { func (gs *groupSnapshot) DeleteGroupSnapshot(ctx context.Context, groupSnapshotID string, snapshotterCredentials map[string]string) error {
// TODO: Implement DeleteGroupSnapshot // TODO: Implement DeleteGroupSnapshot
return nil return nil
} }
func (gs *groupSnapshot) GetGroupSnapshotStatus(ctx context.Context, snapshotID string, snapshotterListCredentials map[string]string) (bool, time.Time, error) { func (gs *groupSnapshot) GetGroupSnapshotStatus(ctx context.Context, groupSnapshotID string, snapshotterListCredentials map[string]string) (bool, time.Time, error) {
// TODO: Implement GetGroupSnapshotStatus // TODO: Implement GetGroupSnapshotStatus
return true, time.Now(), nil return true, time.Now(), nil
} }

View File

@@ -152,38 +152,38 @@ func (handler *csiHandler) CreateGroupSnapshot(content *crdv1alpha1.VolumeGroupS
return "", "", nil, time.Time{}, false, fmt.Errorf("cannot create group snapshot. PVCs to be snapshotted not found in group snapshot content %s", content.Name) return "", "", nil, time.Time{}, false, fmt.Errorf("cannot create group snapshot. PVCs to be snapshotted not found in group snapshot content %s", content.Name)
} }
snapshotName, err := makeGroupSnapshotName(handler.snapshotNamePrefix, string(content.Spec.VolumeGroupSnapshotRef.UID)) groupSnapshotName, err := makeGroupSnapshotName(handler.snapshotNamePrefix, string(content.Spec.VolumeGroupSnapshotRef.UID))
if err != nil { if err != nil {
return "", "", nil, time.Time{}, false, err return "", "", nil, time.Time{}, false, err
} }
return handler.groupSnapshotter.CreateGroupSnapshot(ctx, snapshotName, volumeIDs, parameters, snapshotterCredentials) return handler.groupSnapshotter.CreateGroupSnapshot(ctx, groupSnapshotName, volumeIDs, parameters, snapshotterCredentials)
} }
func (handler *csiHandler) GetGroupSnapshotStatus(content *crdv1alpha1.VolumeGroupSnapshotContent, snapshotterListCredentials map[string]string) (bool, time.Time, error) { func (handler *csiHandler) GetGroupSnapshotStatus(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent, snapshotterListCredentials map[string]string) (bool, time.Time, error) {
ctx, cancel := context.WithTimeout(context.Background(), handler.timeout) ctx, cancel := context.WithTimeout(context.Background(), handler.timeout)
defer cancel() defer cancel()
var snapshotHandle string var groupSnapshotHandle string
var err error var err error
if content.Status != nil && content.Status.VolumeGroupSnapshotHandle != nil { if groupSnapshotContent.Status != nil && groupSnapshotContent.Status.VolumeGroupSnapshotHandle != nil {
snapshotHandle = *content.Status.VolumeGroupSnapshotHandle groupSnapshotHandle = *groupSnapshotContent.Status.VolumeGroupSnapshotHandle
} else if content.Spec.Source.VolumeGroupSnapshotHandle != nil { } else if groupSnapshotContent.Spec.Source.VolumeGroupSnapshotHandle != nil {
snapshotHandle = *content.Spec.Source.VolumeGroupSnapshotHandle groupSnapshotHandle = *groupSnapshotContent.Spec.Source.VolumeGroupSnapshotHandle
} else { } else {
return false, time.Time{}, fmt.Errorf("failed to list snapshot for content %s: snapshotHandle is missing", content.Name) return false, time.Time{}, fmt.Errorf("failed to list group snapshot for group snapshot content %s: groupSnapshotHandle is missing", groupSnapshotContent.Name)
} }
csiSnapshotStatus, timestamp, err := handler.groupSnapshotter.GetGroupSnapshotStatus(ctx, snapshotHandle, snapshotterListCredentials) csiSnapshotStatus, timestamp, err := handler.groupSnapshotter.GetGroupSnapshotStatus(ctx, groupSnapshotHandle, snapshotterListCredentials)
if err != nil { if err != nil {
return false, time.Time{}, fmt.Errorf("failed to list snapshot for content %s: %q", content.Name, err) return false, time.Time{}, fmt.Errorf("failed to list group snapshot for group snapshot content %s: %q", groupSnapshotContent.Name, err)
} }
return csiSnapshotStatus, timestamp, nil return csiSnapshotStatus, timestamp, nil
} }
func makeGroupSnapshotName(prefix, groupSnapshotUID string) (string, error) { func makeGroupSnapshotName(groupSnapshotUID string) (string, error) {
if len(groupSnapshotUID) == 0 { if len(groupSnapshotUID) == 0 {
return "", fmt.Errorf("group snapshot object is missing UID") return "", fmt.Errorf("group snapshot object is missing UID")
} }
return fmt.Sprintf("%s-%s", prefix, strings.Replace(groupSnapshotUID, "-", "", -1)), nil return fmt.Sprintf("groupsnapshot-%s", strings.Replace(groupSnapshotUID, "-", "", -1)), nil
} }

View File

@@ -33,8 +33,8 @@ import (
"github.com/kubernetes-csi/external-snapshotter/v6/pkg/utils" "github.com/kubernetes-csi/external-snapshotter/v6/pkg/utils"
) )
func (ctrl *csiSnapshotSideCarController) storeGroupSnapshotContentUpdate(content interface{}) (bool, error) { func (ctrl *csiSnapshotSideCarController) storeGroupSnapshotContentUpdate(groupSnapshotContent interface{}) (bool, error) {
return utils.StoreObjectUpdate(ctrl.groupSnapshotContentStore, content, "groupsnapshotcontent") return utils.StoreObjectUpdate(ctrl.groupSnapshotContentStore, groupSnapshotContent, "groupsnapshotcontent")
} }
// enqueueGroupSnapshotContentWork adds group snapshot content to given work queue. // enqueueGroupSnapshotContentWork adds group snapshot content to given work queue.
@@ -43,10 +43,10 @@ func (ctrl *csiSnapshotSideCarController) enqueueGroupSnapshotContentWork(obj in
if unknown, ok := obj.(cache.DeletedFinalStateUnknown); ok && unknown.Obj != nil { if unknown, ok := obj.(cache.DeletedFinalStateUnknown); ok && unknown.Obj != nil {
obj = unknown.Obj obj = unknown.Obj
} }
if content, ok := obj.(*crdv1alpha1.VolumeGroupSnapshotContent); ok { if groupSnapshotContent, ok := obj.(*crdv1alpha1.VolumeGroupSnapshotContent); ok {
objName, err := cache.DeletionHandlingMetaNamespaceKeyFunc(content) objName, err := cache.DeletionHandlingMetaNamespaceKeyFunc(groupSnapshotContent)
if err != nil { if err != nil {
klog.Errorf("failed to get key from object: %v, %v", err, content) klog.Errorf("failed to get key from object: %v, %v", err, groupSnapshotContent)
return return
} }
klog.V(5).Infof("enqueued %q for sync", objName) klog.V(5).Infof("enqueued %q for sync", objName)
@@ -55,7 +55,7 @@ func (ctrl *csiSnapshotSideCarController) enqueueGroupSnapshotContentWork(obj in
} }
// groupSnapshotContentWorker processes items from groupSnapshotContentQueue. // groupSnapshotContentWorker processes items from groupSnapshotContentQueue.
// It must run only once, syncContent is not assured to be reentrant. // It must run only once, syncGroupSnapshotContent is not assured to be reentrant.
func (ctrl *csiSnapshotSideCarController) groupSnapshotContentWorker() { func (ctrl *csiSnapshotSideCarController) groupSnapshotContentWorker() {
keyObj, quit := ctrl.groupSnapshotContentQueue.Get() keyObj, quit := ctrl.groupSnapshotContentQueue.Get()
if quit { if quit {
@@ -85,12 +85,12 @@ func (ctrl *csiSnapshotSideCarController) syncGroupSnapshotContentByKey(key stri
klog.V(4).Infof("error getting name of groupSnapshotContent %q from informer: %v", key, err) klog.V(4).Infof("error getting name of groupSnapshotContent %q from informer: %v", key, err)
return nil return nil
} }
content, err := ctrl.groupSnapshotContentLister.Get(name) groupSnapshotContent, err := ctrl.groupSnapshotContentLister.Get(name)
// The group snapshot content still exists in informer cache, the event must // The group snapshot content still exists in informer cache, the event must
// have been add/update/sync // have been add/update/sync
if err == nil { if err == nil {
if ctrl.isDriverMatch(content) { if ctrl.isDriverMatch(groupSnapshotContent) {
err = ctrl.updateGroupSnapshotContentInInformerCache(content) err = ctrl.updateGroupSnapshotContentInInformerCache(groupSnapshotContent)
} }
if err != nil { if err != nil {
// If error occurs we add this item back to the queue // If error occurs we add this item back to the queue
@@ -103,9 +103,9 @@ func (ctrl *csiSnapshotSideCarController) syncGroupSnapshotContentByKey(key stri
return nil return nil
} }
// The content is not in informer cache, the event must have been // The groupSnapshotContent is not in informer cache, the event must have been
// "delete" // "delete"
contentObj, found, err := ctrl.groupSnapshotContentStore.GetByKey(key) groupSnapshotContentObj, found, err := ctrl.groupSnapshotContentStore.GetByKey(key)
if err != nil { if err != nil {
klog.V(2).Infof("error getting group snapshot content %q from cache: %v", key, err) klog.V(2).Infof("error getting group snapshot content %q from cache: %v", key, err)
return nil return nil
@@ -116,36 +116,36 @@ func (ctrl *csiSnapshotSideCarController) syncGroupSnapshotContentByKey(key stri
klog.V(2).Infof("deletion of group snapshot content %q was already processed", key) klog.V(2).Infof("deletion of group snapshot content %q was already processed", key)
return nil return nil
} }
content, ok := contentObj.(*crdv1alpha1.VolumeGroupSnapshotContent) groupSnapshotContent, ok := groupSnapshotContentObj.(*crdv1alpha1.VolumeGroupSnapshotContent)
if !ok { if !ok {
klog.Errorf("expected group snapshot content, got %+v", content) klog.Errorf("expected group snapshot content, got %+v", groupSnapshotContent)
return nil return nil
} }
ctrl.deleteGroupSnapshotContentInCacheStore(content) ctrl.deleteGroupSnapshotContentInCacheStore(groupSnapshotContent)
return nil return nil
} }
// updateGroupSnapshotContentInInformerCache runs in worker thread and handles // updateGroupSnapshotContentInInformerCache runs in worker thread and handles
// "group snapshot content added", "group snapshot content updated" and "periodic // "group snapshot content added", "group snapshot content updated" and "periodic
// sync" events. // sync" events.
func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentInInformerCache(content *crdv1alpha1.VolumeGroupSnapshotContent) error { func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentInInformerCache(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) error {
// Store the new group snapshot content version in the cache and do not process // Store the new group snapshot content version in the cache and do not process
// it if this is an old version. // it if this is an old version.
new, err := ctrl.storeGroupSnapshotContentUpdate(content) new, err := ctrl.storeGroupSnapshotContentUpdate(groupSnapshotContent)
if err != nil { if err != nil {
klog.Errorf("%v", err) klog.Errorf("%v", err)
} }
if !new { if !new {
return nil return nil
} }
err = ctrl.syncGroupSnapshotContent(content) err = ctrl.syncGroupSnapshotContent(groupSnapshotContent)
if err != nil { if err != nil {
if errors.IsConflict(err) { if errors.IsConflict(err) {
// Version conflict error happens quite often and the controller // Version conflict error happens quite often and the controller
// recovers from it easily. // recovers from it easily.
klog.V(3).Infof("could not sync group snapshot content %q: %+v", content.Name, err) klog.V(3).Infof("could not sync group snapshot content %q: %+v", groupSnapshotContent.Name, err)
} else { } else {
klog.Errorf("could not sync group snapshot content %q: %+v", content.Name, err) klog.Errorf("could not sync group snapshot content %q: %+v", groupSnapshotContent.Name, err)
} }
return err return err
} }
@@ -154,62 +154,62 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentInInformerCa
// deleteGroupSnapshotContentInCacheStore runs in worker thread and handles "group // deleteGroupSnapshotContentInCacheStore runs in worker thread and handles "group
// snapshot content deleted" event. // snapshot content deleted" event.
func (ctrl *csiSnapshotSideCarController) deleteGroupSnapshotContentInCacheStore(content *crdv1alpha1.VolumeGroupSnapshotContent) { func (ctrl *csiSnapshotSideCarController) deleteGroupSnapshotContentInCacheStore(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) {
_ = ctrl.groupSnapshotContentStore.Delete(content) _ = ctrl.groupSnapshotContentStore.Delete(groupSnapshotContent)
klog.V(4).Infof("group snapshot content %q deleted", content.Name) klog.V(4).Infof("group snapshot content %q deleted", groupSnapshotContent.Name)
} }
// syncGroupSnapshotContent deals with one key off the queue. It returns false when it's time to quit. // syncGroupSnapshotContent deals with one key off the queue. It returns false when it's time to quit.
func (ctrl *csiSnapshotSideCarController) syncGroupSnapshotContent(content *crdv1alpha1.VolumeGroupSnapshotContent) error { func (ctrl *csiSnapshotSideCarController) syncGroupSnapshotContent(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) error {
klog.V(5).Infof("synchronizing VolumeGroupSnapshotContent[%s]", content.Name) klog.V(5).Infof("synchronizing VolumeGroupSnapshotContent[%s]", groupSnapshotContent.Name)
/* /*
TODO: Check if the group snapshot content should be deleted TODO: Check if the group snapshot content should be deleted
*/ */
if len(content.Spec.Source.PersistentVolumeNames) != 0 && content.Status == nil { if len(groupSnapshotContent.Spec.Source.PersistentVolumeNames) != 0 && groupSnapshotContent.Status == nil {
klog.V(5).Infof("syncContent: Call CreateGroupSnapshot for group snapshot content %s", content.Name) klog.V(5).Infof("syncGroupSnapshotContent: Call CreateGroupSnapshot for group snapshot content %s", groupSnapshotContent.Name)
return ctrl.createGroupSnapshot(content) return ctrl.createGroupSnapshot(groupSnapshotContent)
} }
// Skip checkandUpdateGroupSnapshotContentStatus() if ReadyToUse is already // Skip checkandUpdateGroupSnapshotContentStatus() if ReadyToUse is already
// true. We don't want to keep calling CreateGroupSnapshot CSI methods over // true. We don't want to keep calling CreateGroupSnapshot CSI methods over
// and over again for performance reasons. // and over again for performance reasons.
var err error var err error
if content.Status != nil && content.Status.ReadyToUse != nil && *content.Status.ReadyToUse == true { if groupSnapshotContent.Status != nil && groupSnapshotContent.Status.ReadyToUse != nil && *groupSnapshotContent.Status.ReadyToUse == true {
// Try to remove AnnVolumeGroupSnapshotBeingCreated if it is not removed yet for some reason // Try to remove AnnVolumeGroupSnapshotBeingCreated if it is not removed yet for some reason
_, err = ctrl.removeAnnVolumeGroupSnapshotBeingCreated(content) _, err = ctrl.removeAnnVolumeGroupSnapshotBeingCreated(groupSnapshotContent)
return err return err
} }
return ctrl.checkandUpdateGroupSnapshotContentStatus(content) return ctrl.checkandUpdateGroupSnapshotContentStatus(groupSnapshotContent)
} }
// createGroupSnapshot starts new asynchronous operation to create group snapshot // createGroupSnapshot starts new asynchronous operation to create group snapshot
func (ctrl *csiSnapshotSideCarController) createGroupSnapshot(content *crdv1alpha1.VolumeGroupSnapshotContent) error { func (ctrl *csiSnapshotSideCarController) createGroupSnapshot(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) error {
klog.V(5).Infof("createGroupSnapshot for group snapshot content [%s]: started", content.Name) klog.V(5).Infof("createGroupSnapshot for group snapshot content [%s]: started", groupSnapshotContent.Name)
contentObj, err := ctrl.createGroupSnapshotWrapper(content) groupSnapshotContentObj, err := ctrl.createGroupSnapshotWrapper(groupSnapshotContent)
if err != nil { if err != nil {
ctrl.updateGroupSnapshotContentErrorStatusWithEvent(contentObj, v1.EventTypeWarning, "SnapshotCreationFailed", fmt.Sprintf("Failed to create group snapshot: %v", err)) ctrl.updateGroupSnapshotContentErrorStatusWithEvent(groupSnapshotContentObj, v1.EventTypeWarning, "GroupSnapshotCreationFailed", fmt.Sprintf("Failed to create group snapshot: %v", err))
klog.Errorf("createSnapshot for content [%s]: error occurred in createSnapshotWrapper: %v", content.Name, err) klog.Errorf("createGroupSnapshot for groupSnapshotContent [%s]: error occurred in createGroupSnapshotWrapper: %v", groupSnapshotContent.Name, err)
return err return err
} }
_, updateErr := ctrl.storeGroupSnapshotContentUpdate(contentObj) _, updateErr := ctrl.storeGroupSnapshotContentUpdate(groupSnapshotContentObj)
if updateErr != nil { if updateErr != nil {
// We will get a "group snapshot update" event soon, this is not a big error // We will get a "group snapshot update" event soon, this is not a big error
klog.V(4).Infof("createSnapshot for content [%s]: cannot update internal content cache: %v", content.Name, updateErr) klog.V(4).Infof("createGroupSnapshot for groupSnapshotContent [%s]: cannot update internal groupSnapshotContent cache: %v", groupSnapshotContent.Name, updateErr)
} }
return nil return nil
} }
// This is a wrapper function for the group snapshot creation process. // This is a wrapper function for the group snapshot creation process.
func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(content *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) { func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) {
klog.Infof("createGroupSnapshotWrapper: Creating group snapshot for group snapshot content %s through the plugin ...", content.Name) klog.Infof("createGroupSnapshotWrapper: Creating group snapshot for group snapshot content %s through the plugin ...", groupSnapshotContent.Name)
class, snapshotterCredentials, err := ctrl.getCSIGroupSnapshotInput(content) class, snapshotterCredentials, err := ctrl.getCSIGroupSnapshotInput(groupSnapshotContent)
if err != nil { if err != nil {
return content, fmt.Errorf("failed to get input parameters to create group snapshot for content %s: %q", content.Name, err) return groupSnapshotContent, fmt.Errorf("failed to get input parameters to create group snapshot for group snapshot content %s: %q", groupSnapshotContent.Name, err)
} }
// NOTE(xyang): handle create timeout // NOTE(xyang): handle create timeout
@@ -217,38 +217,38 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(content *cr
// sent to the storage system and the controller is waiting for a response. // sent to the storage system and the controller is waiting for a response.
// The annotation will be removed after the storage system has responded with // The annotation will be removed after the storage system has responded with
// success or permanent failure. If the request times out, annotation will // success or permanent failure. If the request times out, annotation will
// remain on the content to avoid potential leaking of a group snapshot resource on // remain on the groupSnapshotContent to avoid potential leaking of a group snapshot resource on
// the storage system. // the storage system.
content, err = ctrl.setAnnVolumeGroupSnapshotBeingCreated(content) groupSnapshotContent, err = ctrl.setAnnVolumeGroupSnapshotBeingCreated(groupSnapshotContent)
if err != nil { if err != nil {
return content, fmt.Errorf("failed to add VolumeGroupSnapshotBeingCreated annotation on the content %s: %q", content.Name, err) return groupSnapshotContent, fmt.Errorf("failed to add VolumeGroupSnapshotBeingCreated annotation on the group snapshot content %s: %q", groupSnapshotContent.Name, err)
} }
parameters, err := utils.RemovePrefixedParameters(class.Parameters) parameters, err := utils.RemovePrefixedParameters(class.Parameters)
if err != nil { if err != nil {
return content, fmt.Errorf("failed to remove CSI Parameters of prefixed keys: %v", err) return groupSnapshotContent, fmt.Errorf("failed to remove CSI Parameters of prefixed keys: %v", err)
} }
if ctrl.extraCreateMetadata { if ctrl.extraCreateMetadata {
parameters[utils.PrefixedVolumeGroupSnapshotNameKey] = content.Spec.VolumeGroupSnapshotRef.Name parameters[utils.PrefixedVolumeGroupSnapshotNameKey] = groupSnapshotContent.Spec.VolumeGroupSnapshotRef.Name
parameters[utils.PrefixedVolumeGroupSnapshotNamespaceKey] = content.Spec.VolumeGroupSnapshotRef.Namespace parameters[utils.PrefixedVolumeGroupSnapshotNamespaceKey] = groupSnapshotContent.Spec.VolumeGroupSnapshotRef.Namespace
parameters[utils.PrefixedVolumeGroupSnapshotContentNameKey] = content.Name parameters[utils.PrefixedVolumeGroupSnapshotContentNameKey] = groupSnapshotContent.Name
} }
volumeIDs, err := ctrl.getGroupSnapshotVolumeIDs(content) volumeIDs, err := ctrl.getGroupSnapshotVolumeIDs(groupSnapshotContent)
driverName, groupSnapshotID, snapshots, creationTime, readyToUse, err := ctrl.handler.CreateGroupSnapshot(content, volumeIDs, parameters, snapshotterCredentials) driverName, groupSnapshotID, snapshots, creationTime, readyToUse, err := ctrl.handler.CreateGroupSnapshot(groupSnapshotContent, volumeIDs, parameters, snapshotterCredentials)
if err != nil { if err != nil {
// NOTE(xyang): handle create timeout // NOTE(xyang): handle create timeout
// If it is a final error, remove annotation to indicate // If it is a final error, remove annotation to indicate
// storage system has responded with an error // storage system has responded with an error
klog.Infof("createSnapshotWrapper: CreateSnapshot for content %s returned error: %v", content.Name, err) klog.Infof("createGroupSnapshotWrapper: CreateGroupSnapshot for groupSnapshotContent %s returned error: %v", groupSnapshotContent.Name, err)
if isCSIFinalError(err) { if isCSIFinalError(err) {
var removeAnnotationErr error var removeAnnotationErr error
if content, removeAnnotationErr = ctrl.removeAnnVolumeGroupSnapshotBeingCreated(content); removeAnnotationErr != nil { if groupSnapshotContent, removeAnnotationErr = ctrl.removeAnnVolumeGroupSnapshotBeingCreated(groupSnapshotContent); removeAnnotationErr != nil {
return content, fmt.Errorf("failed to remove VolumeGroupSnapshotBeingCreated annotation from the content %s: %s", content.Name, removeAnnotationErr) return groupSnapshotContent, fmt.Errorf("failed to remove VolumeGroupSnapshotBeingCreated annotation from the group snapshot content %s: %s", groupSnapshotContent.Name, removeAnnotationErr)
} }
} }
return content, fmt.Errorf("failed to take group snapshot of the volumes %s: %q", content.Spec.Source.PersistentVolumeNames, err) return groupSnapshotContent, fmt.Errorf("failed to take group snapshot of the volumes %s: %q", groupSnapshotContent.Spec.Source.PersistentVolumeNames, err)
} }
klog.V(5).Infof("Created group snapshot: driver %s, groupSnapshotId %s, creationTime %v, readyToUse %t", driverName, groupSnapshotID, creationTime, readyToUse) klog.V(5).Infof("Created group snapshot: driver %s, groupSnapshotId %s, creationTime %v, readyToUse %t", driverName, groupSnapshotID, creationTime, readyToUse)
@@ -259,9 +259,9 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(content *cr
// Create individual snapshots and snapshot contents // Create individual snapshots and snapshot contents
for _, snapshot := range snapshots { for _, snapshot := range snapshots {
volumeSnapshotContentName := GetSnapshotContentNameForVolumeGroupSnapshotContent(content) volumeSnapshotContentName := GetSnapshotContentNameForVolumeGroupSnapshotContent(groupSnapshotContent)
volumeSnapshotName := GetSnapshotNameForVolumeGroupSnapshotContent(content) volumeSnapshotName := GetSnapshotNameForVolumeGroupSnapshotContent(groupSnapshotContent)
volumeSnapshotNamespace := content.Spec.VolumeGroupSnapshotRef.Namespace volumeSnapshotNamespace := groupSnapshotContent.Spec.VolumeGroupSnapshotRef.Namespace
volumeSnapshotContent := &crdv1.VolumeSnapshotContent{ volumeSnapshotContent := &crdv1.VolumeSnapshotContent{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: volumeSnapshotContentName, Name: volumeSnapshotContentName,
@@ -272,11 +272,12 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(content *cr
Name: volumeSnapshotName, Name: volumeSnapshotName,
Namespace: volumeSnapshotNamespace, Namespace: volumeSnapshotNamespace,
}, },
DeletionPolicy: content.Spec.DeletionPolicy, DeletionPolicy: groupSnapshotContent.Spec.DeletionPolicy,
Driver: content.Spec.Driver, Driver: groupSnapshotContent.Spec.Driver,
Source: crdv1.VolumeSnapshotContentSource{ Source: crdv1.VolumeSnapshotContentSource{
SnapshotHandle: &snapshot.SnapshotId, SnapshotHandle: &snapshot.SnapshotId,
}, },
// TODO: Populate this field when volume mode conversion is enabled by default
SourceVolumeMode: nil, SourceVolumeMode: nil,
}, },
} }
@@ -294,35 +295,35 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(content *cr
} }
_, err = ctrl.clientset.SnapshotV1().VolumeSnapshotContents().Create(context.TODO(), volumeSnapshotContent, metav1.CreateOptions{}) _, err = ctrl.clientset.SnapshotV1().VolumeSnapshotContents().Create(context.TODO(), volumeSnapshotContent, metav1.CreateOptions{})
if err != nil { if err != nil {
return content, err return groupSnapshotContent, err
} }
_, err = ctrl.clientset.SnapshotV1().VolumeSnapshots(volumeSnapshotNamespace).Create(context.TODO(), volumeSnapshot, metav1.CreateOptions{}) _, err = ctrl.clientset.SnapshotV1().VolumeSnapshots(volumeSnapshotNamespace).Create(context.TODO(), volumeSnapshot, metav1.CreateOptions{})
if err != nil { if err != nil {
return content, err return groupSnapshotContent, err
} }
} }
newContent, err := ctrl.updateGroupSnapshotContentStatus(content, groupSnapshotID, readyToUse, creationTime.UnixNano()) newGroupSnapshotContent, err := ctrl.updateGroupSnapshotContentStatus(groupSnapshotContent, groupSnapshotID, readyToUse, creationTime.UnixNano())
if err != nil { if err != nil {
klog.Errorf("error updating status for volume group snapshot content %s: %v.", content.Name, err) klog.Errorf("error updating status for volume group snapshot content %s: %v.", groupSnapshotContent.Name, err)
return content, fmt.Errorf("error updating status for volume group snapshot content %s: %v", content.Name, err) return groupSnapshotContent, fmt.Errorf("error updating status for volume group snapshot content %s: %v", groupSnapshotContent.Name, err)
} }
content = newContent groupSnapshotContent = newGroupSnapshotContent
// NOTE(xyang): handle create timeout // NOTE(xyang): handle create timeout
// Remove annotation to indicate storage system has successfully // Remove annotation to indicate storage system has successfully
// cut the group snapshot // cut the group snapshot
content, err = ctrl.removeAnnVolumeGroupSnapshotBeingCreated(content) groupSnapshotContent, err = ctrl.removeAnnVolumeGroupSnapshotBeingCreated(groupSnapshotContent)
if err != nil { if err != nil {
return content, fmt.Errorf("failed to remove VolumeGroupSnapshotBeingCreated annotation on the content %s: %q", content.Name, err) return groupSnapshotContent, fmt.Errorf("failed to remove VolumeGroupSnapshotBeingCreated annotation on the groupSnapshotContent %s: %q", groupSnapshotContent.Name, err)
} }
return content, nil return groupSnapshotContent, nil
} }
func (ctrl *csiSnapshotSideCarController) getCSIGroupSnapshotInput(content *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotClass, map[string]string, error) { func (ctrl *csiSnapshotSideCarController) getCSIGroupSnapshotInput(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotClass, map[string]string, error) {
className := content.Spec.VolumeGroupSnapshotClassName className := groupSnapshotContent.Spec.VolumeGroupSnapshotClassName
klog.V(5).Infof("getCSIGroupSnapshotInput for group snapshot content [%s]", content.Name) klog.V(5).Infof("getCSIGroupSnapshotInput for group snapshot content [%s]", groupSnapshotContent.Name)
var class *crdv1alpha1.VolumeGroupSnapshotClass var class *crdv1alpha1.VolumeGroupSnapshotClass
var err error var err error
if className != nil { if className != nil {
@@ -333,12 +334,12 @@ func (ctrl *csiSnapshotSideCarController) getCSIGroupSnapshotInput(content *crdv
} }
} else { } else {
// If dynamic provisioning, return failure if no group snapshot class // If dynamic provisioning, return failure if no group snapshot class
if len(content.Spec.Source.PersistentVolumeNames) != 0 { if len(groupSnapshotContent.Spec.Source.PersistentVolumeNames) != 0 {
klog.Errorf("failed to getCSISnapshotInput %s without a group snapshot class", content.Name) klog.Errorf("failed to getCSISnapshotInput %s without a group snapshot class", groupSnapshotContent.Name)
return nil, nil, fmt.Errorf("failed to take group snapshot %s without a group snapshot class", content.Name) return nil, nil, fmt.Errorf("failed to take group snapshot %s without a group snapshot class", groupSnapshotContent.Name)
} }
// For pre-provisioned group snapshot, group snapshot class is not required // For pre-provisioned group snapshot, group snapshot class is not required
klog.V(5).Infof("getCSISnapshotInput for content [%s]: no VolumeGroupSnapshotClassName provided for pre-provisioned group snapshot", content.Name) klog.V(5).Infof("getCSISnapshotInput for groupSnapshotContent [%s]: no VolumeGroupSnapshotClassName provided for pre-provisioned group snapshot", groupSnapshotContent.Name)
} }
// TODO: Resolve snapshotting secret credentials. // TODO: Resolve snapshotting secret credentials.
@@ -362,18 +363,18 @@ func (ctrl *csiSnapshotSideCarController) getGroupSnapshotClass(className string
// setAnnVolumeGroupSnapshotBeingCreated sets VolumeGroupSnapshotBeingCreated annotation // setAnnVolumeGroupSnapshotBeingCreated sets VolumeGroupSnapshotBeingCreated annotation
// on VolumeGroupSnapshotContent // on VolumeGroupSnapshotContent
// If set, it indicates group snapshot is being created // If set, it indicates group snapshot is being created
func (ctrl *csiSnapshotSideCarController) setAnnVolumeGroupSnapshotBeingCreated(content *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) { func (ctrl *csiSnapshotSideCarController) setAnnVolumeGroupSnapshotBeingCreated(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) {
if metav1.HasAnnotation(content.ObjectMeta, utils.AnnVolumeGroupSnapshotBeingCreated) { if metav1.HasAnnotation(groupSnapshotContent.ObjectMeta, utils.AnnVolumeGroupSnapshotBeingCreated) {
// the annotation already exists, return directly // the annotation already exists, return directly
return content, nil return groupSnapshotContent, nil
} }
// Set AnnVolumeGroupSnapshotBeingCreated // Set AnnVolumeGroupSnapshotBeingCreated
// Combine existing annotations with the new annotations. // Combine existing annotations with the new annotations.
// If there are no existing annotations, we create a new map. // If there are no existing annotations, we create a new map.
klog.V(5).Infof("setAnnVolumeGroupSnapshotBeingCreated: set annotation [%s:yes] on content [%s].", utils.AnnVolumeGroupSnapshotBeingCreated, content.Name) klog.V(5).Infof("setAnnVolumeGroupSnapshotBeingCreated: set annotation [%s:yes] on groupSnapshotContent [%s].", utils.AnnVolumeGroupSnapshotBeingCreated, groupSnapshotContent.Name)
patchedAnnotations := make(map[string]string) patchedAnnotations := make(map[string]string)
for k, v := range content.GetAnnotations() { for k, v := range groupSnapshotContent.GetAnnotations() {
patchedAnnotations[k] = v patchedAnnotations[k] = v
} }
patchedAnnotations[utils.AnnVolumeGroupSnapshotBeingCreated] = "yes" patchedAnnotations[utils.AnnVolumeGroupSnapshotBeingCreated] = "yes"
@@ -385,26 +386,26 @@ func (ctrl *csiSnapshotSideCarController) setAnnVolumeGroupSnapshotBeingCreated(
Value: patchedAnnotations, Value: patchedAnnotations,
}) })
patchedContent, err := utils.PatchVolumeGroupSnapshotContent(content, patches, ctrl.clientset) patchedGroupSnapshotContent, err := utils.PatchVolumeGroupSnapshotContent(groupSnapshotContent, patches, ctrl.clientset)
if err != nil { if err != nil {
return content, newControllerUpdateError(content.Name, err.Error()) return groupSnapshotContent, newControllerUpdateError(groupSnapshotContent.Name, err.Error())
} }
// update content if update is successful // update groupSnapshotContent if update is successful
content = patchedContent groupSnapshotContent = patchedGroupSnapshotContent
_, err = ctrl.storeContentUpdate(content) _, err = ctrl.storeContentUpdate(groupSnapshotContent)
if err != nil { if err != nil {
klog.V(4).Infof("setAnnVolumeGroupSnapshotBeingCreated for content [%s]: cannot update internal cache %v", content.Name, err) klog.V(4).Infof("setAnnVolumeGroupSnapshotBeingCreated for groupSnapshotContent [%s]: cannot update internal cache %v", groupSnapshotContent.Name, err)
} }
klog.V(5).Infof("setAnnVolumeGroupSnapshotBeingCreated: volume group snapshot content %+v", content) klog.V(5).Infof("setAnnVolumeGroupSnapshotBeingCreated: volume group snapshot content %+v", groupSnapshotContent)
return content, nil return groupSnapshotContent, nil
} }
func (ctrl *csiSnapshotSideCarController) getGroupSnapshotVolumeIDs(content *crdv1alpha1.VolumeGroupSnapshotContent) ([]string, error) { func (ctrl *csiSnapshotSideCarController) getGroupSnapshotVolumeIDs(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) ([]string, error) {
// TODO: Get add PV lister // TODO: Get add PV lister
var volumeIDs []string var volumeIDs []string
for _, pvName := range content.Spec.Source.PersistentVolumeNames { for _, pvName := range groupSnapshotContent.Spec.Source.PersistentVolumeNames {
pv, err := ctrl.client.CoreV1().PersistentVolumes().Get(context.TODO(), pvName, metav1.GetOptions{}) pv, err := ctrl.client.CoreV1().PersistentVolumes().Get(context.TODO(), pvName, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
@@ -417,43 +418,43 @@ func (ctrl *csiSnapshotSideCarController) getGroupSnapshotVolumeIDs(content *crd
} }
// removeAnnVolumeGroupSnapshotBeingCreated removes the VolumeGroupSnapshotBeingCreated // removeAnnVolumeGroupSnapshotBeingCreated removes the VolumeGroupSnapshotBeingCreated
// annotation from a content if there exists one. // annotation from a groupSnapshotContent if there exists one.
func (ctrl csiSnapshotSideCarController) removeAnnVolumeGroupSnapshotBeingCreated(content *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) { func (ctrl csiSnapshotSideCarController) removeAnnVolumeGroupSnapshotBeingCreated(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) {
if !metav1.HasAnnotation(content.ObjectMeta, utils.AnnVolumeGroupSnapshotBeingCreated) { if !metav1.HasAnnotation(groupSnapshotContent.ObjectMeta, utils.AnnVolumeGroupSnapshotBeingCreated) {
// the annotation does not exist, return directly // the annotation does not exist, return directly
return content, nil return groupSnapshotContent, nil
} }
contentClone := content.DeepCopy() groupSnapshotContentClone := groupSnapshotContent.DeepCopy()
delete(contentClone.ObjectMeta.Annotations, utils.AnnVolumeGroupSnapshotBeingCreated) delete(groupSnapshotContentClone.ObjectMeta.Annotations, utils.AnnVolumeGroupSnapshotBeingCreated)
updatedContent, err := ctrl.clientset.GroupsnapshotV1alpha1().VolumeGroupSnapshotContents().Update(context.TODO(), contentClone, metav1.UpdateOptions{}) updatedContent, err := ctrl.clientset.GroupsnapshotV1alpha1().VolumeGroupSnapshotContents().Update(context.TODO(), groupSnapshotContentClone, metav1.UpdateOptions{})
if err != nil { if err != nil {
return content, newControllerUpdateError(content.Name, err.Error()) return groupSnapshotContent, newControllerUpdateError(groupSnapshotContent.Name, err.Error())
} }
klog.V(5).Infof("Removed VolumeGroupSnapshotBeingCreated annotation from volume group snapshot content %s", content.Name) klog.V(5).Infof("Removed VolumeGroupSnapshotBeingCreated annotation from volume group snapshot content %s", groupSnapshotContent.Name)
_, err = ctrl.storeContentUpdate(updatedContent) _, err = ctrl.storeContentUpdate(updatedContent)
if err != nil { if err != nil {
klog.Errorf("failed to update content store %v", err) klog.Errorf("failed to update groupSnapshotContent store %v", err)
} }
return updatedContent, nil return updatedContent, nil
} }
func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus( func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus(
content *crdv1alpha1.VolumeGroupSnapshotContent, groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent,
groupSnapshotHandle string, groupSnapshotHandle string,
readyToUse bool, readyToUse bool,
createdAt int64) (*crdv1alpha1.VolumeGroupSnapshotContent, error) { createdAt int64) (*crdv1alpha1.VolumeGroupSnapshotContent, error) {
klog.V(5).Infof("updateSnapshotContentStatus: updating VolumeGroupSnapshotContent [%s], groupSnapshotHandle %s, readyToUse %v, createdAt %v", content.Name, groupSnapshotHandle, readyToUse, createdAt) klog.V(5).Infof("updateSnapshotContentStatus: updating VolumeGroupSnapshotContent [%s], groupSnapshotHandle %s, readyToUse %v, createdAt %v", groupSnapshotContent.Name, groupSnapshotHandle, readyToUse, createdAt)
contentObj, err := ctrl.clientset.GroupsnapshotV1alpha1().VolumeGroupSnapshotContents().Get(context.TODO(), content.Name, metav1.GetOptions{}) groupSnapshotContentObj, err := ctrl.clientset.GroupsnapshotV1alpha1().VolumeGroupSnapshotContents().Get(context.TODO(), groupSnapshotContent.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, fmt.Errorf("error get group snapshot content %s from api server: %v", content.Name, err) return nil, fmt.Errorf("error get group snapshot content %s from api server: %v", groupSnapshotContent.Name, err)
} }
var newStatus *crdv1alpha1.VolumeGroupSnapshotContentStatus var newStatus *crdv1alpha1.VolumeGroupSnapshotContentStatus
updated := false updated := false
if contentObj.Status == nil { if groupSnapshotContentObj.Status == nil {
newStatus = &crdv1alpha1.VolumeGroupSnapshotContentStatus{ newStatus = &crdv1alpha1.VolumeGroupSnapshotContentStatus{
VolumeGroupSnapshotHandle: &groupSnapshotHandle, VolumeGroupSnapshotHandle: &groupSnapshotHandle,
ReadyToUse: &readyToUse, ReadyToUse: &readyToUse,
@@ -461,7 +462,7 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus(
} }
updated = true updated = true
} else { } else {
newStatus = contentObj.Status.DeepCopy() newStatus = groupSnapshotContentObj.Status.DeepCopy()
if newStatus.VolumeGroupSnapshotHandle == nil { if newStatus.VolumeGroupSnapshotHandle == nil {
newStatus.VolumeGroupSnapshotHandle = &groupSnapshotHandle newStatus.VolumeGroupSnapshotHandle = &groupSnapshotHandle
updated = true updated = true
@@ -480,49 +481,49 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus(
} }
if updated { if updated {
contentClone := contentObj.DeepCopy() groupSnapshotContentClone := groupSnapshotContentObj.DeepCopy()
contentClone.Status = newStatus groupSnapshotContentClone.Status = newStatus
newContent, err := ctrl.clientset.GroupsnapshotV1alpha1().VolumeGroupSnapshotContents().UpdateStatus(context.TODO(), contentClone, metav1.UpdateOptions{}) newContent, err := ctrl.clientset.GroupsnapshotV1alpha1().VolumeGroupSnapshotContents().UpdateStatus(context.TODO(), groupSnapshotContentClone, metav1.UpdateOptions{})
if err != nil { if err != nil {
return contentObj, newControllerUpdateError(content.Name, err.Error()) return groupSnapshotContentObj, newControllerUpdateError(groupSnapshotContent.Name, err.Error())
} }
return newContent, nil return newContent, nil
} }
return contentObj, nil return groupSnapshotContentObj, nil
} }
// updateContentStatusWithEvent saves new content.Status to API server and emits // updateContentStatusWithEvent saves new groupSnapshotContent.Status to API server
// given event on the content. It saves the status and emits the event only when // and emits given event on the groupSnapshotContent. It saves the status and emits
// the status has actually changed from the version saved in API server. // the event only when the status has actually changed from the version saved in API server.
// Parameters: // Parameters:
// //
// * content - content to update // * groupSnapshotContent - group snapshot content to update
// * eventtype, reason, message - event to send, see EventRecorder.Event() // * eventtype, reason, message - event to send, see EventRecorder.Event()
func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentErrorStatusWithEvent(content *crdv1alpha1.VolumeGroupSnapshotContent, eventtype, reason, message string) error { func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentErrorStatusWithEvent(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent, eventtype, reason, message string) error {
klog.V(5).Infof("updateContentStatusWithEvent[%s]", content.Name) klog.V(5).Infof("updateGroupSnapshotContentStatusWithEvent[%s]", groupSnapshotContent.Name)
if content.Status != nil && content.Status.Error != nil && *content.Status.Error.Message == message { if groupSnapshotContent.Status != nil && groupSnapshotContent.Status.Error != nil && *groupSnapshotContent.Status.Error.Message == message {
klog.V(4).Infof("updateContentStatusWithEvent[%s]: the same error %v is already set", content.Name, content.Status.Error) klog.V(4).Infof("updateGroupSnapshotContentStatusWithEvent[%s]: the same error %v is already set", groupSnapshotContent.Name, groupSnapshotContent.Status.Error)
return nil return nil
} }
var patches []utils.PatchOp var patches []utils.PatchOp
ready := false ready := false
contentStatusError := &crdv1.VolumeSnapshotError{ groupSnapshotContentStatusError := &crdv1.VolumeSnapshotError{
Time: &metav1.Time{ Time: &metav1.Time{
Time: time.Now(), Time: time.Now(),
}, },
Message: &message, Message: &message,
} }
if content.Status == nil { if groupSnapshotContent.Status == nil {
// Initialize status if nil // Initialize status if nil
patches = append(patches, utils.PatchOp{ patches = append(patches, utils.PatchOp{
Op: "replace", Op: "replace",
Path: "/status", Path: "/status",
Value: &crdv1alpha1.VolumeGroupSnapshotContentStatus{ Value: &crdv1alpha1.VolumeGroupSnapshotContentStatus{
ReadyToUse: &ready, ReadyToUse: &ready,
Error: contentStatusError, Error: groupSnapshotContentStatusError,
}, },
}) })
} else { } else {
@@ -530,7 +531,7 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentErrorStatusW
patches = append(patches, utils.PatchOp{ patches = append(patches, utils.PatchOp{
Op: "replace", Op: "replace",
Path: "/status/error", Path: "/status/error",
Value: contentStatusError, Value: groupSnapshotContentStatusError,
}) })
patches = append(patches, utils.PatchOp{ patches = append(patches, utils.PatchOp{
Op: "replace", Op: "replace",
@@ -540,19 +541,19 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentErrorStatusW
} }
newContent, err := utils.PatchVolumeGroupSnapshotContent(content, patches, ctrl.clientset, "status") newContent, err := utils.PatchVolumeGroupSnapshotContent(groupSnapshotContent, patches, ctrl.clientset, "status")
// Emit the event even if the status update fails so that user can see the error // Emit the event even if the status update fails so that user can see the error
ctrl.eventRecorder.Event(newContent, eventtype, reason, message) ctrl.eventRecorder.Event(newContent, eventtype, reason, message)
if err != nil { if err != nil {
klog.V(4).Infof("updating VolumeGroupSnapshotContent[%s] error status failed %v", content.Name, err) klog.V(4).Infof("updating VolumeGroupSnapshotContent[%s] error status failed %v", groupSnapshotContent.Name, err)
return err return err
} }
_, err = ctrl.storeGroupSnapshotContentUpdate(newContent) _, err = ctrl.storeGroupSnapshotContentUpdate(newContent)
if err != nil { if err != nil {
klog.V(4).Infof("updating VolumeGroupSnapshotContent[%s] error status: cannot update internal cache %v", content.Name, err) klog.V(4).Infof("updating VolumeGroupSnapshotContent[%s] error status: cannot update internal cache %v", groupSnapshotContent.Name, err)
return err return err
} }
@@ -560,34 +561,34 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentErrorStatusW
} }
// GetSnapshotNameForVolumeGroupSnapshotContent returns a unique snapshot name for a VolumeGroupSnapshotContent. // GetSnapshotNameForVolumeGroupSnapshotContent returns a unique snapshot name for a VolumeGroupSnapshotContent.
func GetSnapshotNameForVolumeGroupSnapshotContent(content *crdv1alpha1.VolumeGroupSnapshotContent) string { func GetSnapshotNameForVolumeGroupSnapshotContent(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) string {
return fmt.Sprintf("groupsnapshot-%x-%d", sha256.Sum256([]byte(content.UID)), time.Duration(time.Now().UnixNano())/time.Millisecond) return fmt.Sprintf("groupsnapshot-%x-%d", sha256.Sum256([]byte(groupSnapshotContent.UID)), time.Duration(time.Now().UnixNano())/time.Millisecond)
} }
// GetSnapshotContentNameForVolumeGroupSnapshotContent returns a unique content name for the // GetSnapshotContentNameForVolumeGroupSnapshotContent returns a unique content name for the
// passed in VolumeGroupSnapshotContent. // passed in VolumeGroupSnapshotContent.
func GetSnapshotContentNameForVolumeGroupSnapshotContent(content *crdv1alpha1.VolumeGroupSnapshotContent) string { func GetSnapshotContentNameForVolumeGroupSnapshotContent(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) string {
return fmt.Sprintf("groupsnapcontent-%x-%d", sha256.Sum256([]byte(content.UID)), time.Duration(time.Now().UnixNano())/time.Millisecond) return fmt.Sprintf("groupsnapcontent-%x-%d", sha256.Sum256([]byte(groupSnapshotContent.UID)), time.Duration(time.Now().UnixNano())/time.Millisecond)
} }
func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStatus(content *crdv1alpha1.VolumeGroupSnapshotContent) error { func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStatus(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) error {
klog.V(5).Infof("checkandUpdateGroupSnapshotContentStatus[%s] started", content.Name) klog.V(5).Infof("checkandUpdateGroupSnapshotContentStatus[%s] started", groupSnapshotContent.Name)
contentObj, err := ctrl.checkandUpdateGroupSnapshotContentStatusOperation(content) groupSnapshotContentObj, err := ctrl.checkandUpdateGroupSnapshotContentStatusOperation(groupSnapshotContent)
if err != nil { if err != nil {
ctrl.updateGroupSnapshotContentErrorStatusWithEvent(contentObj, v1.EventTypeWarning, "GroupSnapshotContentCheckandUpdateFailed", fmt.Sprintf("Failed to check and update group snapshot content: %v", err)) ctrl.updateGroupSnapshotContentErrorStatusWithEvent(groupSnapshotContentObj, v1.EventTypeWarning, "GroupSnapshotContentCheckandUpdateFailed", fmt.Sprintf("Failed to check and update group snapshot content: %v", err))
klog.Errorf("checkandUpdateGroupSnapshotContentStatus [%s]: error occurred %v", content.Name, err) klog.Errorf("checkandUpdateGroupSnapshotContentStatus [%s]: error occurred %v", groupSnapshotContent.Name, err)
return err return err
} }
_, updateErr := ctrl.storeGroupSnapshotContentUpdate(contentObj) _, updateErr := ctrl.storeGroupSnapshotContentUpdate(groupSnapshotContentObj)
if updateErr != nil { if updateErr != nil {
// We will get a "group snapshot update" event soon, this is not a big error // We will get a "group snapshot update" event soon, this is not a big error
klog.V(4).Infof("checkandUpdateGroupSnapshotContentStatus [%s]: cannot update internal cache: %v", content.Name, updateErr) klog.V(4).Infof("checkandUpdateGroupSnapshotContentStatus [%s]: cannot update internal cache: %v", groupSnapshotContent.Name, updateErr)
} }
return nil return nil
} }
func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStatusOperation(content *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) { func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStatusOperation(groupSnapshotContent *crdv1alpha1.VolumeGroupSnapshotContent) (*crdv1alpha1.VolumeGroupSnapshotContent, error) {
var err error var err error
var creationTime time.Time var creationTime time.Time
readyToUse := false readyToUse := false
@@ -595,37 +596,37 @@ func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStat
var groupSnapshotID string var groupSnapshotID string
var snapshotterListCredentials map[string]string var snapshotterListCredentials map[string]string
if content.Spec.Source.VolumeGroupSnapshotHandle != nil { if groupSnapshotContent.Spec.Source.VolumeGroupSnapshotHandle != nil {
klog.V(5).Infof("checkandUpdateGroupSnapshotContentStatusOperation: call GetSnapshotStatus for group snapshot which is pre-bound to content [%s]", content.Name) klog.V(5).Infof("checkandUpdateGroupSnapshotContentStatusOperation: call GetGroupSnapshotStatus for group snapshot which is pre-bound to groupSnapshotContent [%s]", groupSnapshotContent.Name)
if content.Spec.VolumeGroupSnapshotClassName != nil { if groupSnapshotContent.Spec.VolumeGroupSnapshotClassName != nil {
class, err := ctrl.getGroupSnapshotClass(*content.Spec.VolumeGroupSnapshotClassName) class, err := ctrl.getGroupSnapshotClass(*groupSnapshotContent.Spec.VolumeGroupSnapshotClassName)
if err != nil { if err != nil {
klog.Errorf("Failed to get group snapshot class %s for group snapshot content %s: %v", *content.Spec.VolumeGroupSnapshotClassName, content.Name, err) klog.Errorf("Failed to get group snapshot class %s for group snapshot content %s: %v", *groupSnapshotContent.Spec.VolumeGroupSnapshotClassName, groupSnapshotContent.Name, err)
return content, fmt.Errorf("failed to get group snapshot class %s for group snapshot content %s: %v", *content.Spec.VolumeGroupSnapshotClassName, content.Name, err) return groupSnapshotContent, fmt.Errorf("failed to get group snapshot class %s for group snapshot content %s: %v", *groupSnapshotContent.Spec.VolumeGroupSnapshotClassName, groupSnapshotContent.Name, err)
} }
snapshotterListSecretRef, err := utils.GetSecretReference(utils.SnapshotterListSecretParams, class.Parameters, content.GetObjectMeta().GetName(), nil) snapshotterListSecretRef, err := utils.GetSecretReference(utils.SnapshotterListSecretParams, class.Parameters, groupSnapshotContent.GetObjectMeta().GetName(), nil)
if err != nil { if err != nil {
klog.Errorf("Failed to get secret reference for group snapshot content %s: %v", content.Name, err) klog.Errorf("Failed to get secret reference for group snapshot content %s: %v", groupSnapshotContent.Name, err)
return content, fmt.Errorf("failed to get secret reference for group snapshot content %s: %v", content.Name, err) return groupSnapshotContent, fmt.Errorf("failed to get secret reference for group snapshot content %s: %v", groupSnapshotContent.Name, err)
} }
snapshotterListCredentials, err = utils.GetCredentials(ctrl.client, snapshotterListSecretRef) snapshotterListCredentials, err = utils.GetCredentials(ctrl.client, snapshotterListSecretRef)
if err != nil { if err != nil {
// Continue with deletion, as the secret may have already been deleted. // Continue with deletion, as the secret may have already been deleted.
klog.Errorf("Failed to get credentials for group snapshot content %s: %v", content.Name, err) klog.Errorf("Failed to get credentials for group snapshot content %s: %v", groupSnapshotContent.Name, err)
return content, fmt.Errorf("failed to get credentials for group snapshot content %s: %v", content.Name, err) return groupSnapshotContent, fmt.Errorf("failed to get credentials for group snapshot content %s: %v", groupSnapshotContent.Name, err)
} }
} }
readyToUse, creationTime, err = ctrl.handler.GetGroupSnapshotStatus(content, snapshotterListCredentials) readyToUse, creationTime, err = ctrl.handler.GetGroupSnapshotStatus(groupSnapshotContent, snapshotterListCredentials)
if err != nil { if err != nil {
klog.Errorf("checkandUpdateGroupSnapshotContentStatusOperation: failed to call get group snapshot status to check whether group snapshot is ready to use %q", err) klog.Errorf("checkandUpdateGroupSnapshotContentStatusOperation: failed to call get group snapshot status to check whether group snapshot is ready to use %q", err)
return content, err return groupSnapshotContent, err
} }
driverName = content.Spec.Driver driverName = groupSnapshotContent.Spec.Driver
groupSnapshotID = *content.Spec.Source.VolumeGroupSnapshotHandle groupSnapshotID = *groupSnapshotContent.Spec.Source.VolumeGroupSnapshotHandle
klog.V(5).Infof("checkandUpdateGroupSnapshotContentStatusOperation: driver %s, groupSnapshotId %s, creationTime %v, size %d, readyToUse %t", driverName, groupSnapshotID, creationTime, readyToUse) klog.V(5).Infof("checkandUpdateGroupSnapshotContentStatusOperation: driver %s, groupSnapshotId %s, creationTime %v, size %d, readyToUse %t", driverName, groupSnapshotID, creationTime, readyToUse)
@@ -633,11 +634,11 @@ func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStat
creationTime = time.Now() creationTime = time.Now()
} }
updatedContent, err := ctrl.updateGroupSnapshotContentStatus(content, groupSnapshotID, readyToUse, creationTime.UnixNano()) updatedContent, err := ctrl.updateGroupSnapshotContentStatus(groupSnapshotContent, groupSnapshotID, readyToUse, creationTime.UnixNano())
if err != nil { if err != nil {
return content, err return groupSnapshotContent, err
} }
return updatedContent, nil return updatedContent, nil
} }
return ctrl.createGroupSnapshotWrapper(content) return ctrl.createGroupSnapshotWrapper(groupSnapshotContent)
} }

View File

@@ -111,7 +111,7 @@ const (
// This only applies to dynamic provisioning of group snapshots because // This only applies to dynamic provisioning of group snapshots because
// the create group snapshot CSI method will not be called for pre-provisioned // the create group snapshot CSI method will not be called for pre-provisioned
// group snapshots. // group snapshots.
AnnVolumeGroupSnapshotBeingCreated = "snapshot.storage.kubernetes.io/volumegroupsnapshot-being-created" AnnVolumeGroupSnapshotBeingCreated = "groupsnapshot.storage.kubernetes.io/volumegroupsnapshot-being-created"
// Annotation for secret name and namespace will be added to the content // Annotation for secret name and namespace will be added to the content
// and used at snapshot content deletion time. // and used at snapshot content deletion time.