-
Notifications
You must be signed in to change notification settings - Fork 6
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
Fix checkup inconsistencies #42
Changes from 3 commits
930250b
f49001b
1d3ffbd
29fe754
1f7eff0
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 |
---|---|---|
|
@@ -67,6 +67,7 @@ type kubeVirtStorageClient interface { | |
ListDataImportCrons(ctx context.Context, namespace string) (*cdiv1.DataImportCronList, error) | ||
ListVirtualMachinesInstances(ctx context.Context, namespace string) (*kvcorev1.VirtualMachineInstanceList, error) | ||
ListCDIs(ctx context.Context) (*cdiv1.CDIList, error) | ||
GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) | ||
GetPersistentVolumeClaim(ctx context.Context, namespace, name string) (*corev1.PersistentVolumeClaim, error) | ||
GetPersistentVolume(ctx context.Context, name string) (*corev1.PersistentVolume, error) | ||
GetVolumeSnapshot(ctx context.Context, namespace, name string) (*snapshotv1.VolumeSnapshot, error) | ||
|
@@ -79,8 +80,10 @@ const ( | |
VMIUnderTestNamePrefix = "vmi-under-test" | ||
hotplugVolumeName = "hotplug-volume" | ||
pvcName = "checkup-pvc" | ||
strTrue = "true" | ||
|
||
AnnDefaultStorageClass = "storageclass.kubernetes.io/is-default-class" | ||
AnnDefaultVirtStorageClass = "storageclass.kubevirt.io/is-default-virt-class" | ||
AnnDefaultStorageClass = "storageclass.kubernetes.io/is-default-class" | ||
|
||
ErrNoDefaultStorageClass = "no default storage class" | ||
ErrPvcNotBound = "pvc failed to bound" | ||
|
@@ -89,14 +92,15 @@ const ( | |
// FIXME: need to decide of we want to return errors in this cases | ||
// errMissingVolumeSnapshotClass = "there are StorageProfiles missing VolumeSnapshotClass" | ||
// errVMsWithNonVirtRbdStorageClass = "there are VMs using the plain RBD storageclass when the virtualization storageclass exists" | ||
ErrVMsWithUnsetEfsStorageClass = "there are VMs using an EFS storageclass where the gid and uid are not set in the storageclass" | ||
ErrGoldenImagesNotUpToDate = "there are golden images whose DataImportCron is not up to date or DataSource is not ready" | ||
ErrGoldenImageNoDataSource = "dataSource has no PVC or Snapshot source" | ||
ErrBootFailedOnSomeVMs = "some of the VMs failed to complete boot on time" | ||
MessageBootCompletedOnAllVMs = "Boot completed on all VMs on time" | ||
MessageSkipNoGoldenImage = "Skip check - no golden image PVC or Snapshot" | ||
MessageSkipNoVMI = "Skip check - no VMI" | ||
MessageSkipSingleNode = "Skip check - single node" | ||
ErrVMsWithUnsetEfsStorageClass = "there are VMs using an EFS storageclass where the gid and uid are not set in the storageclass" | ||
ErrGoldenImagesNotUpToDate = "there are golden images whose DataImportCron is not up to date or DataSource is not ready" | ||
ErrGoldenImageNoDataSource = "dataSource has no PVC or Snapshot source" | ||
ErrBootFailedOnSomeVMs = "some of the VMs failed to complete boot on time" | ||
MessageBootCompletedOnAllVMs = "Boot completed on all VMs on time" | ||
MessageSkipNoDefaultStorageClass = "Skip check - no default storage class" | ||
MessageSkipNoGoldenImage = "Skip check - no golden image PVC or Snapshot" | ||
MessageSkipNoVMI = "Skip check - no VMI" | ||
MessageSkipSingleNode = "Skip check - single node" | ||
|
||
pollInterval = 5 * time.Second | ||
) | ||
|
@@ -111,14 +115,15 @@ var UnsupportedProvisioners = map[string]struct{}{ | |
} | ||
|
||
type Checkup struct { | ||
client kubeVirtStorageClient | ||
namespace string | ||
checkupConfig config.Config | ||
goldenImageScs []string | ||
goldenImagePvc *corev1.PersistentVolumeClaim | ||
goldenImageSnap *snapshotv1.VolumeSnapshot | ||
vmUnderTest *kvcorev1.VirtualMachine | ||
results status.Results | ||
client kubeVirtStorageClient | ||
namespace string | ||
checkupConfig config.Config | ||
defaultStorageClass string | ||
goldenImageScs []string | ||
goldenImagePvc *corev1.PersistentVolumeClaim | ||
goldenImageSnap *snapshotv1.VolumeSnapshot | ||
vmUnderTest *kvcorev1.VirtualMachine | ||
results status.Results | ||
} | ||
|
||
type goldenImagesCheckState struct { | ||
|
@@ -243,14 +248,23 @@ func (c *Checkup) checkVersions(ctx context.Context) error { | |
func (c *Checkup) checkGoldenImages(ctx context.Context, namespaces *corev1.NamespaceList, errStr *string) error { | ||
log.Print("checkGoldenImages") | ||
|
||
const defaultGoldenImagesNamespace = "openshift-virtualization-os-images" | ||
var cs goldenImagesCheckState | ||
for i := range namespaces.Items { | ||
ns := namespaces.Items[i].Name | ||
if err := c.checkDataImportCrons(ctx, ns, &cs); err != nil { | ||
|
||
if ns, err := c.client.GetNamespace(ctx, defaultGoldenImagesNamespace); err == nil { | ||
if err := c.checkDataImportCrons(ctx, ns.Name, &cs); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
for i := range namespaces.Items { | ||
if ns := namespaces.Items[i].Name; ns != defaultGoldenImagesNamespace { | ||
if err := c.checkDataImportCrons(ctx, ns, &cs); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
if c.goldenImagePvc == nil { | ||
if cs.fallbackPvcDefaultSC != nil { | ||
c.goldenImagePvc = cs.fallbackPvcDefaultSC | ||
|
@@ -392,18 +406,35 @@ func (c *Checkup) updateGoldenImageSnapshot(snap *snapshotv1.VolumeSnapshot) { | |
func (c *Checkup) checkDefaultStorageClass(scs *storagev1.StorageClassList, errStr *string) { | ||
log.Print("checkDefaultStorageClass") | ||
|
||
var multipleDefaultStorageClasses, hasDefaultVirtStorageClass, hasDefaultStorageClass bool | ||
for i := range scs.Items { | ||
sc := scs.Items[i] | ||
if sc.Annotations[AnnDefaultStorageClass] == "true" { | ||
if c.results.DefaultStorageClass != "" { | ||
c.results.DefaultStorageClass = ErrMultipleDefaultStorageClasses | ||
appendSep(errStr, ErrMultipleDefaultStorageClasses) | ||
break | ||
if sc.Annotations[AnnDefaultVirtStorageClass] == strTrue { | ||
if !hasDefaultVirtStorageClass { | ||
hasDefaultVirtStorageClass = true | ||
c.defaultStorageClass = sc.Name | ||
} else { | ||
multipleDefaultStorageClasses = true | ||
} | ||
} | ||
if sc.Annotations[AnnDefaultStorageClass] == strTrue { | ||
if !hasDefaultStorageClass { | ||
hasDefaultStorageClass = true | ||
if !hasDefaultVirtStorageClass { | ||
c.defaultStorageClass = sc.Name | ||
} | ||
} else { | ||
multipleDefaultStorageClasses = true | ||
} | ||
c.results.DefaultStorageClass = sc.Name | ||
} | ||
} | ||
if c.results.DefaultStorageClass == "" { | ||
|
||
if multipleDefaultStorageClasses { | ||
c.results.DefaultStorageClass = ErrMultipleDefaultStorageClasses | ||
appendSep(errStr, ErrMultipleDefaultStorageClasses) | ||
} else if c.defaultStorageClass != "" { | ||
c.results.DefaultStorageClass = c.defaultStorageClass | ||
} else { | ||
c.results.DefaultStorageClass = ErrNoDefaultStorageClass | ||
appendSep(errStr, ErrNoDefaultStorageClass) | ||
} | ||
|
@@ -412,6 +443,12 @@ func (c *Checkup) checkDefaultStorageClass(scs *storagev1.StorageClassList, errS | |
func (c *Checkup) checkPVCCreationAndBinding(ctx context.Context, errStr *string) error { | ||
log.Print("checkPVCCreationAndBinding") | ||
|
||
if c.defaultStorageClass == "" && c.checkupConfig.StorageClass == "" { | ||
log.Print(MessageSkipNoDefaultStorageClass) | ||
c.results.PVCBound = MessageSkipNoDefaultStorageClass | ||
return nil | ||
} | ||
|
||
dv := &cdiv1.DataVolume{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: pvcName, | ||
|
@@ -422,7 +459,7 @@ func (c *Checkup) checkPVCCreationAndBinding(ctx context.Context, errStr *string | |
UID: types.UID(c.checkupConfig.PodUID), | ||
}}, | ||
Annotations: map[string]string{ | ||
"cdi.kubevirt.io/storage.bind.immediate.requested": "true", | ||
"cdi.kubevirt.io/storage.bind.immediate.requested": strTrue, | ||
}, | ||
}, | ||
Spec: cdiv1.DataVolumeSpec{ | ||
|
@@ -786,6 +823,13 @@ func (c *Checkup) Config() config.Config { | |
|
||
func (c *Checkup) checkVMIBoot(ctx context.Context, errStr *string) error { | ||
log.Print("checkVMIBoot") | ||
|
||
if c.defaultStorageClass == "" { | ||
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. here you dont need to also check: 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. Right! |
||
log.Print(MessageSkipNoDefaultStorageClass) | ||
c.results.VMBootFromGoldenImage = MessageSkipNoDefaultStorageClass | ||
return nil | ||
} | ||
|
||
if c.goldenImagePvc == nil && c.goldenImageSnap == nil { | ||
log.Print(MessageSkipNoGoldenImage) | ||
c.results.VMBootFromGoldenImage = MessageSkipNoGoldenImage | ||
|
@@ -803,6 +847,11 @@ func (c *Checkup) checkVMIBoot(ctx context.Context, errStr *string) error { | |
return err | ||
} | ||
|
||
if c.goldenImageSnap != nil { | ||
c.results.VMVolumeClone = "DV cloneType: snapshot" | ||
return nil | ||
} | ||
|
||
pvc, err := c.client.GetPersistentVolumeClaim(ctx, c.namespace, getVMDvName(vmName)) | ||
if err != nil { | ||
return err | ||
|
@@ -980,6 +1029,12 @@ func (c *Checkup) checkConcurrentVMIBoot(ctx context.Context, errStr *string) er | |
numOfVMs := c.checkupConfig.NumOfVMs | ||
log.Printf("checkConcurrentVMIBoot numOfVMs:%d", numOfVMs) | ||
|
||
if c.defaultStorageClass == "" { | ||
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. same question 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. Same answer:) |
||
log.Print(MessageSkipNoDefaultStorageClass) | ||
c.results.ConcurrentVMBoot = MessageSkipNoDefaultStorageClass | ||
return nil | ||
} | ||
|
||
if c.goldenImagePvc == nil && c.goldenImageSnap == nil { | ||
log.Print(MessageSkipNoGoldenImage) | ||
c.results.ConcurrentVMBoot = MessageSkipNoGoldenImage | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,14 +89,24 @@ var tests = map[string]struct { | |
expectedErr string | ||
}{ | ||
"noStorageClasses": { | ||
clientConfig: clientConfig{noStorageClasses: true}, | ||
expectedResults: map[string]string{reporter.DefaultStorageClassKey: checkup.ErrNoDefaultStorageClass}, | ||
expectedErr: checkup.ErrNoDefaultStorageClass, | ||
clientConfig: clientConfig{noStorageClasses: true, expectNoVMI: true}, | ||
expectedResults: map[string]string{ | ||
reporter.DefaultStorageClassKey: checkup.ErrNoDefaultStorageClass, | ||
reporter.PVCBoundKey: checkup.MessageSkipNoDefaultStorageClass, | ||
reporter.VMBootFromGoldenImageKey: checkup.MessageSkipNoDefaultStorageClass, | ||
reporter.ConcurrentVMBootKey: checkup.MessageSkipNoDefaultStorageClass, | ||
}, | ||
expectedErr: checkup.ErrNoDefaultStorageClass, | ||
}, | ||
"noDefaultStorageClass": { | ||
clientConfig: clientConfig{noDefaultStorageClass: true}, | ||
expectedResults: map[string]string{reporter.DefaultStorageClassKey: checkup.ErrNoDefaultStorageClass}, | ||
expectedErr: checkup.ErrNoDefaultStorageClass, | ||
clientConfig: clientConfig{noDefaultStorageClass: true, expectNoVMI: true}, | ||
expectedResults: map[string]string{ | ||
reporter.DefaultStorageClassKey: checkup.ErrNoDefaultStorageClass, | ||
reporter.PVCBoundKey: checkup.MessageSkipNoDefaultStorageClass, | ||
reporter.VMBootFromGoldenImageKey: checkup.MessageSkipNoDefaultStorageClass, | ||
reporter.ConcurrentVMBootKey: checkup.MessageSkipNoDefaultStorageClass, | ||
}, | ||
expectedErr: checkup.ErrNoDefaultStorageClass, | ||
}, | ||
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. shouldnt you add also virt storage class tests? 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. Yes I should :) |
||
"multipleDefaultStorageClasses": { | ||
clientConfig: clientConfig{multipleDefaultStorageClasses: true}, | ||
|
@@ -527,6 +537,10 @@ func (cs *clientStub) ListVolumeSnapshotClasses(ctx context.Context) (*snapshotv | |
} | ||
|
||
func (cs *clientStub) ListDataImportCrons(ctx context.Context, namespace string) (*cdiv1.DataImportCronList, error) { | ||
if namespace != testNamespace { | ||
return &cdiv1.DataImportCronList{}, nil | ||
} | ||
|
||
dicList := &cdiv1.DataImportCronList{ | ||
Items: []cdiv1.DataImportCron{ | ||
{ | ||
|
@@ -592,6 +606,15 @@ func (cs *clientStub) ListVirtualMachinesInstances(ctx context.Context, namespac | |
return vmiList, nil | ||
} | ||
|
||
func (cs *clientStub) GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) { | ||
ns := &corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
}, | ||
} | ||
return ns, nil | ||
} | ||
|
||
func (cs *clientStub) GetPersistentVolumeClaim(ctx context.Context, namespace, name string) (*corev1.PersistentVolumeClaim, error) { | ||
blockMode := corev1.PersistentVolumeBlock | ||
pvc := &corev1.PersistentVolumeClaim{ | ||
|
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.
question, dont you get in the namespaces list also "openshift-virtualization-os-images"? if so why do you need this commit?
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.
I want to prefer it over other namespaces if we have DataImportCrons there, but use DICs from the other namespaces if not. It can be written as a single loop but it will be a bit more clumsy.
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.
ah I see that inside checkDataImportCrons you eventually update some values so now I understand