Skip to content

Commit

Permalink
[controller] Add bench-tests for LVMLogicalVolume controller (#42)
Browse files Browse the repository at this point in the history
Signed-off-by: Viktor Kramarenko <[email protected]>
  • Loading branch information
ViktorKram authored Apr 15, 2024
1 parent 7e34db9 commit 14dc0d3
Showing 1 changed file with 250 additions and 0 deletions.
250 changes: 250 additions & 0 deletions images/agent/pkg/controller/lvm_logical_volume_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
package controller

import (
"context"
"fmt"
v1 "k8s.io/api/core/v1"
sv1 "k8s.io/api/storage/v1"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
apiruntime "k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"os"
"sds-node-configurator/api/v1alpha1"
"sds-node-configurator/internal"
"sds-node-configurator/pkg/kubutils"
"sigs.k8s.io/controller-runtime/pkg/client"
"testing"
)

var (
lvgName = "hdd-lvg-on-node-0"
poolName = "hhd-thin"
lvCount = 600
size, err = resource.ParseQuantity("1Gi")

resizeOn = false

ctx = context.Background()
cl client.Client

resourcesSchemeFuncs = []func(*apiruntime.Scheme) error{
v1alpha1.AddToScheme,
clientgoscheme.AddToScheme,
extv1.AddToScheme,
v1.AddToScheme,
sv1.AddToScheme,
}
)

func BenchmarkRunThickLLVCreationSingleThread(b *testing.B) {
b.Logf("starts the test")
llvNames := make(map[string]bool, lvCount)

b.StartTimer()
for i := 0; i < lvCount; i++ {
llv := configureTestThickLLV(fmt.Sprintf("test-llv-%d", i), lvgName)
err := cl.Create(ctx, llv)
if err != nil {
b.Logf("unable to create test LLV %s, err: %s", llv.Name, err.Error())
}
llvNames[llv.Name] = false
}
lvCreatedTime := b.Elapsed().Seconds()

succeeded := 0
for succeeded < len(llvNames) {
llvs, err := getAllLLV(ctx, cl)
if err != nil {
b.Error(err)
continue
}

for llvName, created := range llvNames {
if llv, found := llvs[llvName]; found {
if llv.Status != nil {
b.Logf("LV %s status %s", llvName, llv.Status.Phase)
}
if err != nil {
b.Logf("can't check LLV %s llv", llvName)
continue
}

if llv.Status != nil &&
llv.Status.Phase == createdStatusPhase &&
!created {
succeeded++
llvNames[llvName] = true

if resizeOn {
add, err := resource.ParseQuantity("1G")
if err != nil {
b.Logf(err.Error())
continue
}

llv.Spec.Size.Add(add)
err = cl.Update(ctx, &llv)
if err != nil {
b.Logf(err.Error())
continue
}

b.Logf("resize for LV %s succeeded", llvName)
}
}
}

}
}
b.Logf("[TIME] LLV resources were configured for %f", lvCreatedTime)
b.Logf("All LLV were created for %f. Ends the test", b.Elapsed().Seconds())
}

func BenchmarkRunThinLLVCreationSingleThread(b *testing.B) {
b.Logf("starts thin test")
llvNames := make(map[string]bool, lvCount)

b.StartTimer()
for i := 0; i < lvCount; i++ {
llv := configureTestThinLLV(fmt.Sprintf("test-llv-%d", i), lvgName, poolName)
err := cl.Create(ctx, llv)
if err != nil {
b.Logf("unable to create test LLV %s, err: %s", llv.Name, err.Error())
continue
}
llvNames[llv.Name] = false
}
createdTime := b.Elapsed().Seconds()

succeeded := 0
for succeeded < len(llvNames) {
llvs, err := getAllLLV(ctx, cl)
if err != nil {
b.Error(err)
continue
}

for llvName, visited := range llvNames {
if llv, found := llvs[llvName]; found {
if llv.Status != nil {
b.Logf("LV %s status %s", llvName, llv.Status.Phase)
}
if err != nil {
b.Logf("can't check LLV %s llv", llvName)
continue
}

if llv.Status != nil &&
llv.Status.Phase == createdStatusPhase &&
!visited {
succeeded++
llvNames[llvName] = true

if resizeOn {
add, err := resource.ParseQuantity("1G")
if err != nil {
b.Logf(err.Error())
continue
}

llv.Spec.Size.Add(add)
err = cl.Update(ctx, &llv)
if err != nil {
b.Logf(err.Error())
continue
}

b.Logf("resize for LV %s succeeded", llvName)
}
}
}

}
}
b.Logf("All LLV were configured for %f. Ends the test", createdTime)
b.Logf("All LLV were created in %f. Ends the test", b.Elapsed().Seconds())
}

func getAllLLV(ctx context.Context, cl client.Client) (map[string]v1alpha1.LVMLogicalVolume, error) {
list := &v1alpha1.LVMLogicalVolumeList{}
err := cl.List(ctx, list)
if err != nil {
return nil, err
}

res := make(map[string]v1alpha1.LVMLogicalVolume, len(list.Items))
for _, lv := range list.Items {
res[lv.Name] = lv
}

return res, nil
}

func configureTestThickLLV(name, lvgName string) *v1alpha1.LVMLogicalVolume {
return &v1alpha1.LVMLogicalVolume{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.LVMLogicalVolumeKind,
APIVersion: v1alpha1.TypeMediaAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Finalizers: []string{internal.SdsNodeConfiguratorFinalizer},
},
Spec: v1alpha1.LVMLogicalVolumeSpec{
ActualLVNameOnTheNode: name,
Type: Thick,
Size: size,
LvmVolumeGroupName: lvgName,
},
}
}

func configureTestThinLLV(name, lvgName, poolName string) *v1alpha1.LVMLogicalVolume {
return &v1alpha1.LVMLogicalVolume{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.LVMLogicalVolumeKind,
APIVersion: v1alpha1.TypeMediaAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Finalizers: []string{internal.SdsNodeConfiguratorFinalizer},
},
Spec: v1alpha1.LVMLogicalVolumeSpec{
ActualLVNameOnTheNode: name,
Type: Thin,
Size: size,
LvmVolumeGroupName: lvgName,
Thin: &v1alpha1.ThinLogicalVolumeSpec{PoolName: poolName},
},
}
}

func init() {
config, err := kubutils.KubernetesDefaultConfigCreate()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

scheme := runtime.NewScheme()
for _, f := range resourcesSchemeFuncs {
err := f(scheme)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
}

options := client.Options{
Scheme: scheme,
}

cl, err = client.New(config, options)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

0 comments on commit 14dc0d3

Please sign in to comment.