Skip to content

Commit

Permalink
Fixed volumeSnapshot Error Issue (#819)
Browse files Browse the repository at this point in the history
* add all

* go fmt
  • Loading branch information
suaas21 authored and tamalsaha committed Jul 3, 2019
1 parent 08b0f50 commit f96852f
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 39 deletions.
109 changes: 70 additions & 39 deletions pkg/cmds/restore_volumesnapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/appscode/go/types"
vs_cs "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
core "k8s.io/api/core/v1"
storage_api_v1 "k8s.io/api/storage/v1"
kerr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -24,12 +24,6 @@ import (
"stash.appscode.dev/stash/pkg/util"
)

type PVC struct {
podOrdinal *int32
pvcName string
pvc corev1.PersistentVolumeClaim
}

func NewCmdRestoreVolumeSnapshot() *cobra.Command {
var (
masterURL string
Expand Down Expand Up @@ -85,40 +79,56 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
return fmt.Errorf("restoreSession Target is nil")
}

pvcData := []PVC{}
pvcList := make([]core.PersistentVolumeClaim, 0)

if restoreSession.Spec.Target.Replicas == nil {
for _, vol := range restoreSession.Spec.Target.VolumeClaimTemplates {
pvcData = append(pvcData, PVC{pvcName: vol.Name, pvc: vol})

pvcs, err := opt.getPVCFromVolumeClaimTemplates(-1, restoreSession.Spec.Target.VolumeClaimTemplates, startTime)
if err != nil {
return err
}
pvcList = append(pvcList, pvcs...)
} else {
for i := int32(0); i < *restoreSession.Spec.Target.Replicas; i++ {
for _, vol := range restoreSession.Spec.Target.VolumeClaimTemplates {
pvcData = append(pvcData, PVC{pvcName: vol.Name, podOrdinal: types.Int32P(i), pvc: vol})
for ordinal := int32(0); ordinal < *restoreSession.Spec.Target.Replicas; ordinal++ {
pvcs, err := opt.getPVCFromVolumeClaimTemplates(ordinal, restoreSession.Spec.Target.VolumeClaimTemplates, startTime)
if err != nil {
return err
}
pvcList = append(pvcList, pvcs...)
}

}

objectMeta := []metav1.ObjectMeta{}
pvcAllReadyExists := false
volumeSnapshotExists := false

for _, data := range pvcData {
pvc := opt.getPVCDefinition(data)
for _, pvc := range pvcList {

_, err = opt.snapshotClient.VolumesnapshotV1alpha1().VolumeSnapshots(opt.namespace).Get(pvc.Spec.DataSource.Name, metav1.GetOptions{})
if err != nil {
volumeSnapshotExists = true
// write failure event for not existing volumeSnapshot
restoreOutput := restic.RestoreOutput{
HostRestoreStats: v1beta1.HostRestoreStats{
Hostname: pvc.Name,
Phase: v1beta1.HostRestoreFailed,
Error: fmt.Sprintf("%s not exixts", pvc.Spec.DataSource.Name),
},
}
err := opt.updateRestoreSessionStatus(restoreOutput, startTime)
if err != nil {
return err
}
continue
}
_, err = opt.kubeClient.CoreV1().PersistentVolumeClaims(opt.namespace).Get(pvc.Name, metav1.GetOptions{})
if err != nil {
if kerr.IsNotFound(err) {
pvc, err := opt.kubeClient.CoreV1().PersistentVolumeClaims(opt.namespace).Create(pvc)
_, err := opt.kubeClient.CoreV1().PersistentVolumeClaims(opt.namespace).Create(&pvc)
if err != nil {
return err
}
objectMeta = append(objectMeta, pvc.ObjectMeta)
} else {
return err
}

} else {
// write failure event for existing PVC
pvcAllReadyExists = true
Expand All @@ -135,20 +145,21 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
}
}
}
if pvcAllReadyExists {

if pvcAllReadyExists || volumeSnapshotExists {
return nil
}

for i, data := range pvcData {
storageClass, err := opt.kubeClient.StorageV1().StorageClasses().Get(types.String(data.pvc.Spec.StorageClassName), metav1.GetOptions{})
for _, pvc := range pvcList {
storageClass, err := opt.kubeClient.StorageV1().StorageClasses().Get(types.String(pvc.Spec.StorageClassName), metav1.GetOptions{})
if err != nil {
return err
}
if *storageClass.VolumeBindingMode != storage_api_v1.VolumeBindingImmediate {
// write failure event because of VolumeBindingMode is WaitForFirstConsumer
restoreOutput := restic.RestoreOutput{
HostRestoreStats: v1beta1.HostRestoreStats{
Hostname: objectMeta[i].Name,
Hostname: pvc.Name,
Phase: v1beta1.HostRestoreUnknown,
Error: fmt.Sprintf("VolumeBindingMode is 'WaitForFirstConsumer'. Stash is unable to decide wheather the restore has succeeded or not as the PVC will not bind with respective PV until any workload mount it."),
},
Expand All @@ -160,13 +171,13 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
continue
}

err = util.WaitUntilPVCReady(opt.kubeClient, objectMeta[i])
err = util.WaitUntilPVCReady(opt.kubeClient, pvc.ObjectMeta)
if err != nil {
return err
}
restoreOutput := restic.RestoreOutput{
HostRestoreStats: v1beta1.HostRestoreStats{
Hostname: objectMeta[i].Name,
Hostname: pvc.Name,
Phase: v1beta1.HostRestoreSucceeded,
},
}
Expand All @@ -178,20 +189,40 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
return nil
}

func (opt *VSoption) getPVCDefinition(data PVC) *corev1.PersistentVolumeClaim {
inputs := make(map[string]string)
if data.podOrdinal == nil {
data.pvc.Name = data.pvcName
} else {
data.pvc.Name = fmt.Sprintf("%v-%v", data.pvcName, *data.podOrdinal)
inputs["POD_ORDINAL"] = strconv.Itoa(int(*data.podOrdinal))
func (opt *VSoption) getPVCFromVolumeClaimTemplates(ordinal int32, claimTemplates []core.PersistentVolumeClaim, startTime time.Time) ([]core.PersistentVolumeClaim, error) {
pvcList := make([]core.PersistentVolumeClaim, 0)

for _, claim := range claimTemplates {
pvc, err := opt.getPVCDefinition(ordinal, claim)
if err != nil {
// write failure event
restoreOutput := restic.RestoreOutput{
HostRestoreStats: v1beta1.HostRestoreStats{
Hostname: pvc.Name,
Phase: v1beta1.HostRestoreFailed,
Error: err.Error(),
},
}
err := opt.updateRestoreSessionStatus(restoreOutput, startTime)
return pvcList, err
}
pvc.Namespace = opt.namespace
pvcList = append(pvcList, pvc)
}
inputs["CLAIM_NAME"] = data.pvcName
err := resolve.ResolvePVCSpec(&data.pvc, inputs)
if err != nil {
return nil
return pvcList, nil
}

func (opt *VSoption) getPVCDefinition(ordinal int32, claim core.PersistentVolumeClaim) (core.PersistentVolumeClaim, error) {
inputs := make(map[string]string)
inputs["POD_ORDINAL"] = strconv.Itoa(int(ordinal))
inputs["CLAIM_NAME"] = claim.Name
if ordinal != int32(-1) {
claim.Name = fmt.Sprintf("%v-%v", claim.Name, ordinal)
}
return &data.pvc
dataSource := claim.Spec.DataSource
err := resolve.ResolvePVCSpec(&claim, inputs)
claim.Spec.DataSource = dataSource
return claim, err
}

func (opt *VSoption) updateRestoreSessionStatus(restoreOutput restic.RestoreOutput, startTime time.Time) error {
Expand Down
10 changes: 10 additions & 0 deletions pkg/rbac/volume_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ func ensureVolumeSnapshotRestorerJobClusterRole(kubeClient kubernetes.Interface,
Resources: []string{"storageclasses"},
Verbs: []string{"get"},
},
{
APIGroups: []string{crdv1.GroupName},
Resources: []string{"volumesnapshots"},
Verbs: []string{"get"},
},
}
return in

Expand Down Expand Up @@ -226,6 +231,11 @@ func ensureStorageReaderClassClusterRole(kubeClient kubernetes.Interface, labels
Resources: []string{"storageclasses"},
Verbs: []string{"get"},
},
{
APIGroups: []string{crdv1.GroupName},
Resources: []string{"volumesnapshots"},
Verbs: []string{"get"},
},
}
return in

Expand Down

0 comments on commit f96852f

Please sign in to comment.