Skip to content

Commit

Permalink
restore unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Henriksen <[email protected]>
  • Loading branch information
mhenriks committed Sep 10, 2020
1 parent 77a4423 commit 33cd708
Show file tree
Hide file tree
Showing 13 changed files with 864 additions and 321 deletions.
3 changes: 0 additions & 3 deletions api/openapi-spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -11001,9 +11001,6 @@
"type": "string"
}
},
"error": {
"$ref": "#/definitions/v1alpha1.Error"
},
"restoreTime": {
"$ref": "#/definitions/v1.Time"
},
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down
3 changes: 3 additions & 0 deletions pkg/virt-controller/watch/snapshot/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"restore_test.go",
"snapshot_suite_test.go",
"snapshot_test.go",
],
embed = [":go_default_library"],
deps = [
"//pkg/testutils:go_default_library",
"//pkg/util/status:go_default_library",
"//staging/src/kubevirt.io/client-go/api/v1:go_default_library",
"//staging/src/kubevirt.io/client-go/apis/snapshot/v1alpha1:go_default_library",
"//staging/src/kubevirt.io/client-go/generated/containerized-data-importer/clientset/versioned/fake:go_default_library",
"//staging/src/kubevirt.io/client-go/generated/external-snapshotter/clientset/versioned/fake:go_default_library",
"//staging/src/kubevirt.io/client-go/generated/kubevirt/clientset/versioned/fake:go_default_library",
"//staging/src/kubevirt.io/client-go/kubecli:go_default_library",
Expand Down
198 changes: 92 additions & 106 deletions pkg/virt-controller/watch/snapshot/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,8 @@ func restoreDVName(vmRestore *snapshotv1.VirtualMachineRestore, name string) str
return restorePVCName(vmRestore, name)
}

func vmRestoreError(vmSnapshot *snapshotv1.VirtualMachineRestore) *snapshotv1.Error {
if vmSnapshot.Status != nil && vmSnapshot.Status.Error != nil {
return vmSnapshot.Status.Error
}
return nil
}

func vmRestoreProgressing(vmRestore *snapshotv1.VirtualMachineRestore) bool {
return vmRestoreError(vmRestore) == nil &&
(vmRestore.Status == nil || vmRestore.Status.Complete == nil || *vmRestore.Status.Complete == false)
return vmRestore.Status == nil || vmRestore.Status.Complete == nil || *vmRestore.Status.Complete == false
}

func (ctrl *VMRestoreController) updateVMRestore(vmRestoreIn *snapshotv1.VirtualMachineRestore) (time.Duration, error) {
Expand All @@ -101,66 +93,59 @@ func (ctrl *VMRestoreController) updateVMRestore(vmRestoreIn *snapshotv1.Virtual
vmRestoreOut.Status.Complete = &complete
vmRestoreOut.Status.RestoreTime = nil

if vmRestoreOut.DeletionTimestamp == nil {
var updated bool
updated, err := ctrl.reconcileVolumeRestores(vmRestoreOut)
var updated bool
updated, err := ctrl.reconcileVolumeRestores(vmRestoreOut)
if err != nil {
logger.Reason(err).Error("Error reconciling VolumeRestores")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}

if !updated {
var target restoreTarget
var ready bool
target, err = ctrl.getTarget(vmRestoreOut)
if err != nil {
logger.Reason(err).Error("Error reconciling VolumeRestores")
logger.Reason(err).Error("Error getting restore target")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}

if !updated {
var target restoreTarget
var ready bool
target, err = ctrl.getTarget(vmRestoreOut)
if err != nil {
logger.Reason(err).Error("Error getting restore target")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}
ready, err = target.Ready()
if err != nil {
logger.Reason(err).Error("Error checking target ready")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}

ready, err = target.Ready()
if ready {
updated, err = target.Reconcile()
if err != nil {
logger.Reason(err).Error("Error checking target ready")
return 5 * time.Second, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
logger.Reason(err).Error("Error reconciling target")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}

if ready {
updated, err = target.Reconcile()
if err != nil {
logger.Reason(err).Error("Error reconciling target")
if !updated {
if err = target.Cleanup(); err != nil {
logger.Reason(err).Error("Error cleaning up")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}

if !updated {
if err = target.Cleanup(); err != nil {
logger.Reason(err).Error("Error cleaning up")
return 0, ctrl.doUpdateError(vmRestoreIn, vmRestoreOut, err)
}

complete = true
vmRestoreOut.Status.RestoreTime = currentTime()
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionFalse, "Operation complete"))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionTrue, "Operation complete"))
} else {
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionTrue, "Updating target spec"))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, "Waiting for target update"))
}
complete = true
vmRestoreOut.Status.RestoreTime = currentTime()
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionFalse, "Operation complete"))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionTrue, "Operation complete"))
} else {
reason := "Waiting for target to be ready"
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionFalse, reason))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, reason))
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionTrue, "Updating target spec"))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, "Waiting for target update"))
}
} else {
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionTrue, "Creating new PVCs"))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, "Waiting for new PVCs"))
reason := "Waiting for target to be ready"
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionFalse, reason))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, reason))
// try again in 5 secs
return 5 * time.Second, ctrl.doUpdate(vmRestoreIn, vmRestoreOut)
}

} else {
// go into error state
reason := "Restore cancelled"
vmRestoreOut.Status.Error = newError(reason)
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionFalse, reason))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, reason))
updateRestoreCondition(vmRestoreOut, newProgressingCondition(corev1.ConditionTrue, "Creating new PVCs"))
updateRestoreCondition(vmRestoreOut, newReadyCondition(corev1.ConditionFalse, "Waiting for new PVCs"))
}

return 0, ctrl.doUpdate(vmRestoreIn, vmRestoreOut)
Expand Down Expand Up @@ -282,59 +267,74 @@ func (t *vmRestoreTarget) Reconcile() (bool, error) {

var newTemplates = make([]cdiv1.DataVolume, len(snapshotVM.Spec.DataVolumeTemplates))
var newVolumes = make([]kubevirtv1.Volume, len(snapshotVM.Spec.Template.Spec.Volumes))
var deletedDataVolumes []string
updatedStatus := false

copy(newTemplates, snapshotVM.Spec.DataVolumeTemplates)
copy(newVolumes, snapshotVM.Spec.Template.Spec.Volumes)

for i, dvt := range snapshotVM.Spec.DataVolumeTemplates {
for j, v := range snapshotVM.Spec.Template.Spec.Volumes {
if v.DataVolume != nil && v.DataVolume.Name == dvt.Name {
for k := range t.vmRestore.Status.Restores {
vr := &t.vmRestore.Status.Restores[k]
if vr.VolumeName == v.Name {
if vr.DataVolumeName == nil {
dvName := restoreDVName(t.vmRestore, vr.VolumeName)

pvc, err := t.controller.getPVC(t.vmRestore.Namespace, vr.PersistentVolumeClaimName)
if err != nil {
return false, err
}

if pvc == nil {
return false, fmt.Errorf("pvc %s/%s does not exist and should", t.vmRestore.Namespace, vr.PersistentVolumeClaimName)
}

_, ok := pvc.Annotations[populatedForPVCAnnotation]
if !ok {
pvc.Annotations[populatedForPVCAnnotation] = dvName
_, err := t.controller.Client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Update(pvc)
if err != nil {
return false, err
}
}

vr.DataVolumeName = &dvName
updatedStatus = true
} else {
dv := dvt.DeepCopy()
dv.Name = *vr.DataVolumeName
newTemplates[i] = *dv

nv := v.DeepCopy()
nv.DataVolume.Name = *vr.DataVolumeName
newVolumes[j] = *nv
if v.DataVolume == nil || v.DataVolume.Name != dvt.Name {
continue
}
for k := range t.vmRestore.Status.Restores {
vr := &t.vmRestore.Status.Restores[k]
if vr.VolumeName != v.Name {
continue
}

pvc, err := t.controller.getPVC(t.vmRestore.Namespace, vr.PersistentVolumeClaimName)
if err != nil {
return false, err
}

if pvc == nil {
return false, fmt.Errorf("pvc %s/%s does not exist and should", t.vmRestore.Namespace, vr.PersistentVolumeClaimName)
}

if vr.DataVolumeName == nil {
dvName := restoreDVName(t.vmRestore, vr.VolumeName)

if pvc.Annotations[populatedForPVCAnnotation] != dvName {
if pvc.Annotations == nil {
pvc.Annotations = make(map[string]string)
}
pvc.Annotations[populatedForPVCAnnotation] = dvName
_, err := t.controller.Client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Update(pvc)
if err != nil {
return false, err
}
}

vr.DataVolumeName = &dvName
updatedStatus = true
}

dv := dvt.DeepCopy()
dv.Name = *vr.DataVolumeName
newTemplates[i] = *dv

nv := v.DeepCopy()
nv.DataVolume.Name = *vr.DataVolumeName
newVolumes[j] = *nv
}
}
}

if updatedStatus {
var deletedDataVolumes []string
for _, dvt := range t.vm.Spec.DataVolumeTemplates {
deletedDataVolumes = append(deletedDataVolumes, dvt.Name)
// find DataVolumes that will no longer exist
for _, cdv := range t.vm.Spec.DataVolumeTemplates {
found := false
for _, ndv := range newTemplates {
if cdv.Name == ndv.Name {
found = true
break
}
}
if !found {
deletedDataVolumes = append(deletedDataVolumes, cdv.Name)
}
}
t.vmRestore.Status.DeletedDataVolumes = deletedDataVolumes

Expand Down Expand Up @@ -444,20 +444,6 @@ func (ctrl *VMRestoreController) getPVC(namespace, name string) (*corev1.Persist
return obj.(*corev1.PersistentVolumeClaim), nil
}

func (ctrl *VMRestoreController) getDataVolume(namespace, name string) (*cdiv1.DataVolume, error) {
objKey := cacheKeyFunc(namespace, name)
obj, exists, err := ctrl.DataVolumeInformer.GetStore().GetByKey(objKey)
if err != nil {
return nil, err
}

if !exists {
return nil, nil
}

return obj.(*cdiv1.DataVolume), nil
}

func (ctrl *VMRestoreController) getTarget(vmRestore *snapshotv1.VirtualMachineRestore) (restoreTarget, error) {
vmRestore.Spec.Target.DeepCopy()
switch vmRestore.Spec.Target.Kind {
Expand Down Expand Up @@ -527,5 +513,5 @@ func (ctrl *VMRestoreController) createRestorePVC(
}

func updateRestoreCondition(r *snapshotv1.VirtualMachineRestore, c snapshotv1.Condition) {
r.Status.Conditions = updateCondition(r.Status.Conditions, c)
r.Status.Conditions = updateCondition(r.Status.Conditions, c, true)
}
26 changes: 0 additions & 26 deletions pkg/virt-controller/watch/snapshot/restore_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (
snapshotv1 "kubevirt.io/client-go/apis/snapshot/v1alpha1"
"kubevirt.io/client-go/kubecli"
"kubevirt.io/client-go/log"
cdiv1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1"
)

// VMRestoreController is resonsible for restoring VMs
Expand Down Expand Up @@ -73,13 +72,6 @@ func (ctrl *VMRestoreController) Init() {
},
)

ctrl.DataVolumeInformer.AddEventHandler(
cache.ResourceEventHandlerFuncs{
AddFunc: ctrl.handleDataVolume,
UpdateFunc: func(oldObj, newObj interface{}) { ctrl.handleDataVolume(newObj) },
},
)

ctrl.VMInformer.AddEventHandler(
cache.ResourceEventHandlerFuncs{
AddFunc: ctrl.handleVM,
Expand Down Expand Up @@ -176,24 +168,6 @@ func (ctrl *VMRestoreController) handlePVC(obj interface{}) {
}
}

func (ctrl *VMRestoreController) handleDataVolume(obj interface{}) {
if unknown, ok := obj.(cache.DeletedFinalStateUnknown); ok && unknown.Obj != nil {
obj = unknown.Obj
}

if dv, ok := obj.(*cdiv1.DataVolume); ok {
restoreName, ok := dv.Annotations[pvcRestoreAnnotation]
if !ok {
return
}

objName := cacheKeyFunc(dv.Namespace, restoreName)

log.Log.V(3).Infof("Handling DV %s/%s, Restore %s", dv.Namespace, dv.Name, objName)
ctrl.vmRestoreQueue.Add(objName)
}
}

func (ctrl *VMRestoreController) handleVM(obj interface{}) {
if unknown, ok := obj.(cache.DeletedFinalStateUnknown); ok && unknown.Obj != nil {
obj = unknown.Obj
Expand Down
Loading

0 comments on commit 33cd708

Please sign in to comment.