-
Notifications
You must be signed in to change notification settings - Fork 377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call CreateSnapshot to check if snapshot is processed #61
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -421,13 +421,65 @@ func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.V | |
return nil | ||
} | ||
|
||
func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshotClass, *v1.PersistentVolume, string, map[string]string, error) { | ||
className := snapshot.Spec.VolumeSnapshotClassName | ||
glog.V(5).Infof("getCreateSnapshotInput [%s]: VolumeSnapshotClassName [%s]", snapshot.Name, *className) | ||
var class *crdv1.VolumeSnapshotClass | ||
var err error | ||
if className != nil { | ||
class, err = ctrl.GetSnapshotClass(*className) | ||
if err != nil { | ||
glog.Errorf("getCreateSnapshotInput failed to getClassFromVolumeSnapshot %s", err) | ||
return nil, nil, "", nil, err | ||
} | ||
} else { | ||
glog.Errorf("failed to getCreateSnapshotInput %s without a snapshot class", snapshot.Name) | ||
return nil, nil, "", nil, fmt.Errorf("failed to take snapshot %s without a snapshot class", snapshot.Name) | ||
} | ||
|
||
volume, err := ctrl.getVolumeFromVolumeSnapshot(snapshot) | ||
if err != nil { | ||
glog.Errorf("getCreateSnapshotInput failed to get PersistentVolume object [%s]: Error: [%#v]", snapshot.Name, err) | ||
return nil, nil, "", nil, err | ||
} | ||
|
||
// Create VolumeSnapshotContent name | ||
contentName := GetSnapshotContentNameForSnapshot(snapshot) | ||
|
||
// Resolve snapshotting secret credentials. | ||
snapshotterSecretRef, err := GetSecretReference(class.Parameters, contentName, snapshot) | ||
if err != nil { | ||
return nil, nil, "", nil, err | ||
} | ||
snapshotterCredentials, err := GetCredentials(ctrl.client, snapshotterSecretRef) | ||
if err != nil { | ||
return nil, nil, "", nil, err | ||
} | ||
|
||
return class, volume, contentName, snapshotterCredentials, nil | ||
} | ||
|
||
func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) (*crdv1.VolumeSnapshot, error) { | ||
status, _, size, err := ctrl.handler.GetSnapshotStatus(content) | ||
var err error | ||
var timestamp int64 = 0 | ||
var size int64 = 0 | ||
var readyToUse bool = false | ||
class, volume, _, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to check snapshot status %s with error %v", snapshot.Name, err) | ||
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err) | ||
} | ||
timestamp := time.Now().UnixNano() | ||
newSnapshot, err := ctrl.updateSnapshotStatus(snapshot, status, timestamp, size, IsSnapshotBound(snapshot, content)) | ||
driverName, snapshotID, timestamp, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials) | ||
if err != nil { | ||
glog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think we should return error after calling CreateSnapshot, then the called of this function checkandUpdateBoundSnapshotStatus will update the error status with event. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right. Snapshot error is updated by the caller if we return error here. |
||
return nil, err | ||
} else { | ||
glog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: driver %s, snapshotId %s, timestamp %d, size %d, readyToUse %t", driverName, snapshotID, timestamp, size, readyToUse) | ||
} | ||
|
||
if timestamp == 0 { | ||
timestamp = time.Now().UnixNano() | ||
} | ||
newSnapshot, err := ctrl.updateSnapshotStatus(snapshot, readyToUse, timestamp, size, IsSnapshotBound(snapshot, content)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
@@ -451,51 +503,22 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum | |
return snapshot, nil | ||
} | ||
|
||
className := snapshot.Spec.VolumeSnapshotClassName | ||
glog.V(5).Infof("createSnapshotOperation [%s]: VolumeSnapshotClassName [%s]", snapshot.Name, *className) | ||
var class *crdv1.VolumeSnapshotClass | ||
var err error | ||
if className != nil { | ||
class, err = ctrl.GetSnapshotClass(*className) | ||
if err != nil { | ||
glog.Errorf("createSnapshotOperation failed to getClassFromVolumeSnapshot %s", err) | ||
return nil, err | ||
} | ||
} else { | ||
glog.Errorf("failed to take snapshot %s without a snapshot class", snapshot.Name) | ||
return nil, fmt.Errorf("failed to take snapshot %s without a snapshot class", snapshot.Name) | ||
} | ||
|
||
volume, err := ctrl.getVolumeFromVolumeSnapshot(snapshot) | ||
class, volume, contentName, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot) | ||
if err != nil { | ||
glog.Errorf("createSnapshotOperation failed to get PersistentVolume object [%s]: Error: [%#v]", snapshot.Name, err) | ||
return nil, err | ||
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err) | ||
} | ||
|
||
// Create VolumeSnapshotContent name | ||
contentName := GetSnapshotContentNameForSnapshot(snapshot) | ||
|
||
// Resolve snapshotting secret credentials. | ||
snapshotterSecretRef, err := GetSecretReference(class.Parameters, contentName, snapshot) | ||
if err != nil { | ||
return nil, err | ||
} | ||
snapshotterCredentials, err := GetCredentials(ctrl.client, snapshotterSecretRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
driverName, snapshotID, timestamp, size, csiSnapshotStatus, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials) | ||
driverName, snapshotID, timestamp, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to take snapshot of the volume, %s: %q", volume.Name, err) | ||
} | ||
glog.V(5).Infof("Created snapshot: driver %s, snapshotId %s, timestamp %d, size %d, csiSnapshotStatus %v", driverName, snapshotID, timestamp, size, csiSnapshotStatus) | ||
glog.V(5).Infof("Created snapshot: driver %s, snapshotId %s, timestamp %d, size %d, readyToUse %t", driverName, snapshotID, timestamp, size, readyToUse) | ||
|
||
var newSnapshot *crdv1.VolumeSnapshot | ||
// Update snapshot status with timestamp | ||
for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ { | ||
glog.V(5).Infof("createSnapshot [%s]: trying to update snapshot creation timestamp", snapshotKey(snapshot)) | ||
newSnapshot, err = ctrl.updateSnapshotStatus(snapshot, csiSnapshotStatus, timestamp, size, false) | ||
newSnapshot, err = ctrl.updateSnapshotStatus(snapshot, readyToUse, timestamp, size, false) | ||
if err == nil { | ||
break | ||
} | ||
|
@@ -682,42 +705,12 @@ func (ctrl *csiSnapshotController) updateSnapshotStatus(snapshot *crdv1.VolumeSn | |
status.Error = nil | ||
change = true | ||
} | ||
if status.CreationTime == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why remove this from the code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is moved to line 718 below. |
||
status.CreationTime = timeAt | ||
change = true | ||
} | ||
} | ||
|
||
/* TODO FIXME | ||
switch csistatus.Type { | ||
case csi.SnapshotStatus_READY: | ||
if bound { | ||
status.Ready = true | ||
// Remove the error if checking snapshot is already bound and ready | ||
status.Error = nil | ||
change = true | ||
} | ||
if status.CreationTime == nil { | ||
status.CreationTime = timeAt | ||
change = true | ||
} | ||
case csi.SnapshotStatus_ERROR_UPLOADING: | ||
if status.Error == nil { | ||
status.Error = &storage.VolumeError{ | ||
Time: *timeAt, | ||
Message: "Failed to upload the snapshot", | ||
} | ||
change = true | ||
ctrl.eventRecorder.Event(snapshot, v1.EventTypeWarning, "SnapshotUploadError", "Failed to upload the snapshot") | ||
|
||
} | ||
case csi.SnapshotStatus_UPLOADING: | ||
if status.CreationTime == nil { | ||
status.CreationTime = timeAt | ||
change = true | ||
} | ||
if status.CreationTime == nil { | ||
status.CreationTime = timeAt | ||
change = true | ||
} | ||
*/ | ||
|
||
if change { | ||
if size > 0 { | ||
status.RestoreSize = resource.NewQuantity(size, resource.BinarySI) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe put this function outside of this function since it is not used when called by checkandUpdateBoundSnapshotStatusOperation?
maybe call prepareCreateSnapshotInput to getCreateSnapshotInfo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we need to have contentName here because it is used to retrieve secrets on the next line.
How about getCreateSnapshotInput? "Info" would be confusing here because "Info" includes other information belonging to a snapshot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetSnapshotContentNameForSnapshot is actually construct content name if using dynamic provisioning. Here if we use this function, statically binding case won't work? If snapshot is already bound, we can get reference name directly from snapshot object, right?
I am not familiar with the secrete ref function. Why it needs contentName?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
contentName is used to construct secret namespace parameters. The secret is also needed at delete snapshot time when the snapshot object may not exist any more so we can't rely on the snapshot object. The implementation to support secrets here is consistent with how it is done for persistent volumes.
I don't know if static binding can support secrets because snapshot class (and storage class) is not required for static binding so there may not be a way to pass in the secrets. I'll need to do more investigation on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this, change the logic to
if snapshot object already has a snapshotContentRef, use it, otherwise, construct the content name. Could you change the name from GetSnapshotContentNameForSnapshot to makeSnapshotContentName....?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.