@@ -2,6 +2,8 @@ package storage
22
33import (
44 "context"
5+ "fmt"
6+ "strings"
57 "time"
68
79 g "github.com/onsi/ginkgo/v2"
@@ -10,6 +12,7 @@ import (
1012 imageregistry "github.com/openshift/client-go/imageregistry/clientset/versioned"
1113 clusteroperatorhelpers "github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers"
1214 exutil "github.com/openshift/origin/test/extended/util"
15+ v1 "k8s.io/api/core/v1"
1316 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1417 e2e "k8s.io/kubernetes/test/e2e/framework"
1518 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
@@ -65,3 +68,94 @@ func skipIfNotS3Storage(oc *exutil.CLI) {
6568 e2eskipper .Skipf ("No S3 storage detected" )
6669 }
6770}
71+
72+ // GetSchedulableLinuxWorkerNodes returns a list of nodes that match the requirements:
73+ // os: linux, role: worker, status: ready, schedulable
74+ func GetSchedulableLinuxWorkerNodes (oc * exutil.CLI ) ([]v1.Node , error ) {
75+ var nodes , workers []v1.Node
76+ linuxNodes , err := oc .AdminKubeClient ().CoreV1 ().Nodes ().List (context .Background (), metav1.ListOptions {LabelSelector : "kubernetes.io/os=linux" })
77+ // get schedulable linux worker nodes
78+ for _ , node := range linuxNodes .Items {
79+ if _ , ok := node .Labels ["node-role.kubernetes.io/worker" ]; ok && ! node .Spec .Unschedulable {
80+ workers = append (workers , node )
81+ }
82+ }
83+ // get ready nodes
84+ for _ , worker := range workers {
85+ for _ , con := range worker .Status .Conditions {
86+ if con .Type == "Ready" && con .Status == "True" {
87+ nodes = append (nodes , worker )
88+ break
89+ }
90+ }
91+ }
92+ return nodes , err
93+ }
94+
95+ // getCSINodeAllocatableCount gets the allocatable count for a specific CSI driver from a CSINode
96+ func getCSINodeAllocatableCountByDriver (ctx context.Context , oc * exutil.CLI , nodeName , driverName string ) int32 {
97+ csiNode , err := oc .AdminKubeClient ().StorageV1 ().CSINodes ().Get (ctx , nodeName , metav1.GetOptions {})
98+ o .Expect (err ).NotTo (o .HaveOccurred (), fmt .Sprintf ("failed to get CSINode for node %s" , nodeName ))
99+
100+ for _ , driver := range csiNode .Spec .Drivers {
101+ if driver .Name == driverName {
102+ if driver .Allocatable != nil && driver .Allocatable .Count != nil {
103+ return * driver .Allocatable .Count
104+ }
105+ }
106+ }
107+ e2e .Failf ("CSI driver %s not found in CSINode %s" , driverName , nodeName )
108+ return 0
109+ }
110+
111+ // getAWSInstanceIDFromNode extracts the AWS instance ID from a node's providerID
112+ func getAWSInstanceIDFromNode (ctx context.Context , oc * exutil.CLI , nodeName string ) string {
113+ node , err := oc .AdminKubeClient ().CoreV1 ().Nodes ().Get (ctx , nodeName , metav1.GetOptions {})
114+ o .Expect (err ).NotTo (o .HaveOccurred (), fmt .Sprintf ("failed to get node %s" , nodeName ))
115+
116+ providerID := node .Spec .ProviderID
117+ o .Expect (providerID ).NotTo (o .BeEmpty (), "node providerID should not be empty" )
118+
119+ parts := strings .Split (providerID , "/" )
120+ o .Expect (len (parts )).To (o .BeNumerically (">=" , 5 ), "invalid AWS providerID format" )
121+
122+ instanceID := parts [len (parts )- 1 ]
123+ o .Expect (instanceID ).To (o .HavePrefix ("i-" ), "instance ID should start with 'i-'" )
124+
125+ return instanceID
126+ }
127+
128+ // getAttachedVolumeCountFromVolumeAttachments returns how many VolumeAttachments
129+ // currently target the given node.
130+ func getAttachedVolumeCountFromVolumeAttachments (ctx context.Context , oc * exutil.CLI , nodeName string ) int32 {
131+ vaList , err := oc .AdminKubeClient ().
132+ StorageV1 ().
133+ VolumeAttachments ().
134+ List (ctx , metav1.ListOptions {})
135+ o .Expect (err ).NotTo (o .HaveOccurred (), "failed to list VolumeAttachments" )
136+
137+ var count int32 = 0
138+ for _ , va := range vaList .Items {
139+ if va .Spec .NodeName == nodeName && va .Status .Attached {
140+ count ++
141+ }
142+ }
143+ return count
144+ }
145+
146+ // GetCSIStorageClassByProvisioner finds a StorageClass that uses the CSI driver provisioner
147+ // it will return the name of the first matched StorageClass if found, otherwise it will fail the test
148+ func GetCSIStorageClassByProvisioner (ctx context.Context , oc * exutil.CLI , provisioner string ) string {
149+ storageClasses , err := oc .AdminKubeClient ().StorageV1 ().StorageClasses ().List (ctx , metav1.ListOptions {})
150+ o .Expect (err ).NotTo (o .HaveOccurred (), "failed to list StorageClasses" )
151+
152+ for _ , sc := range storageClasses .Items {
153+ if sc .Provisioner == ebsCSIDriverName {
154+ e2e .Logf ("Found CSI StorageClass: %s" , sc .Name )
155+ return sc .Name
156+ }
157+ }
158+
159+ e2e .Failf ("No StorageClass found with provisioner %s" , ebsCSIDriverName )
160+ return ""
161+ }
0 commit comments