Skip to content

Commit

Permalink
Call CreateSnapshot to check if snapshot is processed
Browse files Browse the repository at this point in the history
This PR calls CreateSnapshot to check if the snapshot post-cut
processing (uploading) is complete and update status accordingly.
  • Loading branch information
xing-yang committed Nov 19, 2018
1 parent 3054071 commit d8c7c45
Showing 1 changed file with 71 additions and 68 deletions.
139 changes: 71 additions & 68 deletions pkg/controller/snapshot_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,13 +421,65 @@ func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.V
return nil
}

func (ctrl *csiSnapshotController) prepareCreateSnapshotInput(snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshotClass, *v1.PersistentVolume, string, map[string]string, error) {
className := snapshot.Spec.VolumeSnapshotClassName
glog.V(5).Infof("prepareCreateSnapshotInput [%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("prepareCreateSnapshotInput failed to getClassFromVolumeSnapshot %s", err)
return nil, nil, "", nil, err
}
} else {
glog.Errorf("failed to prepareCreateSnapshotInput %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("prepareCreateSnapshotInput 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.prepareCreateSnapshotInput(snapshot)
if err != nil {
return nil, fmt.Errorf("failed to prepare input parameters to call create snapshot of the volume, %s: %q", volume.Name, err)
}
driverName, snapshotID, timestamp, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
if err != nil {
return nil, fmt.Errorf("failed to check snapshot status %s with error %v", snapshot.Name, err)
// Don't return here. Update status by calling updateSnapshotStatus below
glog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", 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()
}
timestamp := time.Now().UnixNano()
newSnapshot, err := ctrl.updateSnapshotStatus(snapshot, status, timestamp, size, IsSnapshotBound(snapshot, content))
newSnapshot, err := ctrl.updateSnapshotStatus(snapshot, readyToUse, timestamp, size, IsSnapshotBound(snapshot, content), err)
if err != nil {
return nil, err
}
Expand All @@ -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)
if err != nil {
glog.Errorf("createSnapshotOperation failed to get PersistentVolume object [%s]: Error: [%#v]", snapshot.Name, err)
return nil, 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)
class, volume, contentName, snapshotterCredentials, err := ctrl.prepareCreateSnapshotInput(snapshot)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to prepare input parameters to call create snapshot of the volume, %s: %q", volume.Name, 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, nil)
if err == nil {
break
}
Expand Down Expand Up @@ -666,7 +689,7 @@ func (ctrl *csiSnapshotController) updateSnapshotContentSize(content *crdv1.Volu
}

// UpdateSnapshotStatus converts snapshot status to crdv1.VolumeSnapshotCondition
func (ctrl *csiSnapshotController) updateSnapshotStatus(snapshot *crdv1.VolumeSnapshot, readyToUse bool, createdAt, size int64, bound bool) (*crdv1.VolumeSnapshot, error) {
func (ctrl *csiSnapshotController) updateSnapshotStatus(snapshot *crdv1.VolumeSnapshot, readyToUse bool, createdAt, size int64, bound bool, inErr error) (*crdv1.VolumeSnapshot, error) {
glog.V(5).Infof("updating VolumeSnapshot[]%s, readyToUse %v, timestamp %v", snapshotKey(snapshot), readyToUse, createdAt)
status := snapshot.Status
change := false
Expand All @@ -682,42 +705,22 @@ func (ctrl *csiSnapshotController) updateSnapshotStatus(snapshot *crdv1.VolumeSn
status.Error = nil
change = true
}
if status.CreationTime == nil {
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 inErr != nil {
status.Error = &storage.VolumeError{
Time: *timeAt,
Message: "Failed to process the snapshot",
}
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:
status.Ready = false
change = true
ctrl.eventRecorder.Event(snapshot, v1.EventTypeWarning, "SnapshotProcessError", "Failed to process the snapshot")
} else {
if status.CreationTime == nil {
status.CreationTime = timeAt
change = true
}
}
*/

if change {
if size > 0 {
status.RestoreSize = resource.NewQuantity(size, resource.BinarySI)
Expand Down

0 comments on commit d8c7c45

Please sign in to comment.