github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/cmd/ndm_daemonset/probe/deletehandler_test.go (about) 1 /* 2 Copyright 2020 The OpenEBS Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package probe 18 19 import ( 20 "context" 21 "testing" 22 23 apis "github.com/openebs/node-disk-manager/api/v1alpha1" 24 "github.com/openebs/node-disk-manager/blockdevice" 25 "github.com/openebs/node-disk-manager/cmd/ndm_daemonset/controller" 26 "github.com/openebs/node-disk-manager/pkg/util" 27 28 "github.com/stretchr/testify/assert" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/client-go/kubernetes/scheme" 31 "sigs.k8s.io/controller-runtime/pkg/client/fake" 32 ) 33 34 func TestRemoveBlockDeviceFromHierarchyCache(t *testing.T) { 35 tests := map[string]struct { 36 cache blockdevice.Hierarchy 37 bd blockdevice.BlockDevice 38 wantCache blockdevice.Hierarchy 39 wantOk bool 40 }{ 41 "device present in cache": { 42 cache: map[string]blockdevice.BlockDevice{ 43 "/dev/sda": { 44 Identifier: blockdevice.Identifier{ 45 DevPath: "/dev/sda", 46 }, 47 }, 48 }, 49 bd: blockdevice.BlockDevice{ 50 Identifier: blockdevice.Identifier{ 51 DevPath: "/dev/sda", 52 }, 53 }, 54 wantCache: make(blockdevice.Hierarchy), 55 wantOk: true, 56 }, 57 "device not present in cache": { 58 cache: map[string]blockdevice.BlockDevice{ 59 "/dev/sda": { 60 Identifier: blockdevice.Identifier{ 61 DevPath: "/dev/sda", 62 }, 63 }, 64 }, 65 bd: blockdevice.BlockDevice{ 66 Identifier: blockdevice.Identifier{ 67 DevPath: "/dev/sdb", 68 }, 69 }, 70 wantCache: map[string]blockdevice.BlockDevice{ 71 "/dev/sda": { 72 Identifier: blockdevice.Identifier{ 73 DevPath: "/dev/sda", 74 }, 75 }, 76 }, 77 wantOk: false, 78 }, 79 } 80 for name, tt := range tests { 81 t.Run(name, func(t *testing.T) { 82 pe := &ProbeEvent{ 83 Controller: &controller.Controller{ 84 BDHierarchy: tt.cache, 85 }, 86 } 87 gotOk := pe.removeBlockDeviceFromHierarchyCache(tt.bd) 88 assert.Equal(t, tt.wantCache, pe.Controller.BDHierarchy) 89 assert.Equal(t, tt.wantOk, gotOk) 90 }) 91 } 92 } 93 94 func TestDeleteBlockDevice(t *testing.T) { 95 96 fakeWWN := "fake-wwn" 97 fakeSerial := "fake-serial" 98 fakePartEntry := "fake-part1" 99 fakeVendor := "fake-vendor" 100 fakePartTable := "fake-part-table" 101 fakeFSUUID := "fake-fs-uuid" 102 103 physicalDisk := blockdevice.BlockDevice{ 104 Identifier: blockdevice.Identifier{ 105 DevPath: "/dev/sda", 106 }, 107 DeviceAttributes: blockdevice.DeviceAttribute{ 108 WWN: fakeWWN, 109 Serial: fakeSerial, 110 Vendor: fakeVendor, 111 }, 112 } 113 physicalDiskPart1 := blockdevice.BlockDevice{ 114 Identifier: blockdevice.Identifier{ 115 DevPath: "/dev/sda1", 116 }, 117 DeviceAttributes: blockdevice.DeviceAttribute{ 118 WWN: fakeWWN, 119 Serial: fakeSerial, 120 DeviceType: blockdevice.BlockDeviceTypePartition, 121 }, 122 PartitionInfo: blockdevice.PartitionInformation{ 123 PartitionEntryUUID: fakePartEntry, 124 }, 125 } 126 physicalDiskUsedByZFSPV := blockdevice.BlockDevice{ 127 Identifier: blockdevice.Identifier{ 128 DevPath: "/dev/sda", 129 }, 130 DeviceAttributes: blockdevice.DeviceAttribute{ 131 WWN: fakeWWN, 132 Serial: fakeSerial, 133 }, 134 PartitionInfo: blockdevice.PartitionInformation{ 135 PartitionTableUUID: fakePartTable, 136 }, 137 } 138 virtualDiskUsedByCstor1 := blockdevice.BlockDevice{ 139 Identifier: blockdevice.Identifier{ 140 DevPath: "/dev/sda", 141 }, 142 NodeAttributes: blockdevice.NodeAttribute{ 143 blockdevice.NodeName: "node1", 144 }, 145 DeviceAttributes: blockdevice.DeviceAttribute{ 146 Model: "Virtual_disk", 147 }, 148 PartitionInfo: blockdevice.PartitionInformation{ 149 PartitionTableUUID: fakePartTable, 150 }, 151 } 152 virtualDiskUsedByCstor2 := blockdevice.BlockDevice{ 153 Identifier: blockdevice.Identifier{ 154 DevPath: "/dev/sdb", 155 }, 156 NodeAttributes: blockdevice.NodeAttribute{ 157 blockdevice.NodeName: "node1", 158 }, 159 DeviceAttributes: blockdevice.DeviceAttribute{ 160 Model: "Virtual_disk", 161 }, 162 PartitionInfo: blockdevice.PartitionInformation{ 163 PartitionTableUUID: fakePartTable, 164 }, 165 } 166 virtualDiskUsedByLocalPV1 := blockdevice.BlockDevice{ 167 Identifier: blockdevice.Identifier{ 168 DevPath: "/dev/sda", 169 }, 170 NodeAttributes: blockdevice.NodeAttribute{ 171 blockdevice.NodeName: "node1", 172 }, 173 FSInfo: blockdevice.FileSystemInformation{ 174 FileSystemUUID: fakeFSUUID, 175 }, 176 DeviceAttributes: blockdevice.DeviceAttribute{ 177 Model: "Virtual_disk", 178 }, 179 } 180 virtualDiskUsedByLocalPV2 := blockdevice.BlockDevice{ 181 Identifier: blockdevice.Identifier{ 182 DevPath: "/dev/sdb", 183 }, 184 NodeAttributes: blockdevice.NodeAttribute{ 185 blockdevice.NodeName: "node1", 186 }, 187 DeviceAttributes: blockdevice.DeviceAttribute{ 188 Model: "Virtual_disk", 189 }, 190 FSInfo: blockdevice.FileSystemInformation{ 191 FileSystemUUID: fakeFSUUID, 192 }, 193 } 194 195 fakePhysicalDiskGPTBasedUUID, _ := generateUUID(physicalDisk) 196 fakePhysicalDiskGPTBasedUUIDPart1, _ := generateUUID(physicalDiskPart1) 197 fakePhysicalDiskLegacyUUID, _ := generateLegacyUUID(physicalDisk) 198 fakecstorVirtualDiskLegacyUUID, _ := generateLegacyUUID(virtualDiskUsedByCstor1) 199 fakelocalpvVirtualDiskLegacyUUID, _ := generateLegacyUUID(virtualDiskUsedByLocalPV1) 200 fakezfspvPhysicalDiskUUID, _ := generateUUIDFromPartitionTable(physicalDiskUsedByZFSPV) 201 202 tests := map[string]struct { 203 bd blockdevice.BlockDevice 204 bdAPIList *apis.BlockDeviceList 205 // name of the deactivated BDs 206 deactivatedBDs []string 207 wantErr bool 208 }{ 209 "Type: disk, physical disk, has one partition": { 210 bd: physicalDisk, 211 bdAPIList: &apis.BlockDeviceList{ 212 Items: []apis.BlockDevice{ 213 { 214 ObjectMeta: metav1.ObjectMeta{ 215 Name: fakePhysicalDiskGPTBasedUUID, 216 }, 217 Spec: apis.DeviceSpec{ 218 Path: "/dev/sda", 219 }, 220 Status: apis.DeviceStatus{ 221 ClaimState: apis.BlockDeviceUnclaimed, 222 State: apis.BlockDeviceActive, 223 }, 224 }, 225 { 226 ObjectMeta: metav1.ObjectMeta{ 227 Name: fakePhysicalDiskGPTBasedUUIDPart1, 228 }, 229 Spec: apis.DeviceSpec{ 230 Path: "/dev/sda1", 231 }, 232 Status: apis.DeviceStatus{ 233 ClaimState: apis.BlockDeviceUnclaimed, 234 State: apis.BlockDeviceActive, 235 }, 236 }, 237 }, 238 }, 239 deactivatedBDs: []string{fakePhysicalDiskGPTBasedUUID}, 240 wantErr: false, 241 }, 242 "Type: partition, physical disk, parent BD resource also present": { 243 bd: physicalDiskPart1, 244 bdAPIList: &apis.BlockDeviceList{ 245 Items: []apis.BlockDevice{ 246 { 247 ObjectMeta: metav1.ObjectMeta{ 248 Name: fakePhysicalDiskGPTBasedUUID, 249 }, 250 Spec: apis.DeviceSpec{ 251 Path: "/dev/sda", 252 }, 253 Status: apis.DeviceStatus{ 254 ClaimState: apis.BlockDeviceUnclaimed, 255 State: apis.BlockDeviceActive, 256 }, 257 }, 258 { 259 ObjectMeta: metav1.ObjectMeta{ 260 Name: fakePhysicalDiskGPTBasedUUIDPart1, 261 }, 262 Spec: apis.DeviceSpec{ 263 Path: "/dev/sda1", 264 }, 265 Status: apis.DeviceStatus{ 266 ClaimState: apis.BlockDeviceUnclaimed, 267 State: apis.BlockDeviceActive, 268 }, 269 }, 270 }, 271 }, 272 deactivatedBDs: []string{fakePhysicalDiskGPTBasedUUIDPart1}, 273 }, 274 "Type: disk, physical disk, no partitions": { 275 bd: physicalDisk, 276 bdAPIList: &apis.BlockDeviceList{ 277 Items: []apis.BlockDevice{ 278 { 279 ObjectMeta: metav1.ObjectMeta{ 280 Name: fakePhysicalDiskGPTBasedUUID, 281 }, 282 Spec: apis.DeviceSpec{ 283 Path: "/dev/sda", 284 }, 285 Status: apis.DeviceStatus{ 286 ClaimState: apis.BlockDeviceUnclaimed, 287 State: apis.BlockDeviceActive, 288 }, 289 }, 290 }, 291 }, 292 deactivatedBDs: []string{fakePhysicalDiskGPTBasedUUID}, 293 wantErr: false, 294 }, 295 "Type: disk, physical disk, upgraded a claimed BD": { 296 bd: physicalDisk, 297 bdAPIList: &apis.BlockDeviceList{ 298 Items: []apis.BlockDevice{ 299 { 300 ObjectMeta: metav1.ObjectMeta{ 301 Name: fakePhysicalDiskLegacyUUID, 302 }, 303 Spec: apis.DeviceSpec{ 304 Path: "/dev/sda", 305 }, 306 Status: apis.DeviceStatus{ 307 ClaimState: apis.BlockDeviceClaimed, 308 State: apis.BlockDeviceActive, 309 }, 310 }, 311 }, 312 }, 313 deactivatedBDs: []string{fakePhysicalDiskLegacyUUID}, 314 wantErr: false, 315 }, 316 "Type: disk, virtual disk, upgraded a claimed BD used by cstor with no path change": { 317 bd: virtualDiskUsedByCstor1, 318 bdAPIList: &apis.BlockDeviceList{ 319 Items: []apis.BlockDevice{ 320 { 321 ObjectMeta: metav1.ObjectMeta{ 322 Name: fakecstorVirtualDiskLegacyUUID, 323 }, 324 Spec: apis.DeviceSpec{ 325 Path: "/dev/sda", 326 }, 327 Status: apis.DeviceStatus{ 328 ClaimState: apis.BlockDeviceClaimed, 329 State: apis.BlockDeviceActive, 330 }, 331 }, 332 }, 333 }, 334 deactivatedBDs: []string{fakecstorVirtualDiskLegacyUUID}, 335 wantErr: false, 336 }, 337 "Type: disk, virtual disk, upgraded a claimed BD used by cstor with path change": { 338 bd: virtualDiskUsedByCstor2, 339 bdAPIList: &apis.BlockDeviceList{ 340 Items: []apis.BlockDevice{ 341 { 342 ObjectMeta: metav1.ObjectMeta{ 343 Name: fakecstorVirtualDiskLegacyUUID, 344 Annotations: map[string]string{ 345 internalPartitionUUIDAnnotation: fakePartTable, 346 }, 347 }, 348 Spec: apis.DeviceSpec{ 349 Path: "/dev/sdb", 350 }, 351 Status: apis.DeviceStatus{ 352 ClaimState: apis.BlockDeviceClaimed, 353 State: apis.BlockDeviceActive, 354 }, 355 }, 356 }, 357 }, 358 deactivatedBDs: []string{fakecstorVirtualDiskLegacyUUID}, 359 wantErr: false, 360 }, 361 "Type: disk, virtual disk, upgraded a claimed BD used by localPV with no path change": { 362 bd: virtualDiskUsedByLocalPV1, 363 bdAPIList: &apis.BlockDeviceList{ 364 Items: []apis.BlockDevice{ 365 { 366 ObjectMeta: metav1.ObjectMeta{ 367 Name: fakelocalpvVirtualDiskLegacyUUID, 368 }, 369 Spec: apis.DeviceSpec{ 370 Path: "/dev/sda", 371 }, 372 Status: apis.DeviceStatus{ 373 ClaimState: apis.BlockDeviceClaimed, 374 State: apis.BlockDeviceActive, 375 }, 376 }, 377 }, 378 }, 379 deactivatedBDs: []string{fakelocalpvVirtualDiskLegacyUUID}, 380 wantErr: false, 381 }, 382 "Type: disk, virtual disk, upgraded a claimed BD used by localPV with path change": { 383 bd: virtualDiskUsedByLocalPV2, 384 bdAPIList: &apis.BlockDeviceList{ 385 Items: []apis.BlockDevice{ 386 { 387 ObjectMeta: metav1.ObjectMeta{ 388 Name: fakecstorVirtualDiskLegacyUUID, 389 Annotations: map[string]string{ 390 internalFSUUIDAnnotation: fakeFSUUID, 391 }, 392 }, 393 Spec: apis.DeviceSpec{ 394 Path: "/dev/sdb", 395 }, 396 Status: apis.DeviceStatus{ 397 ClaimState: apis.BlockDeviceClaimed, 398 State: apis.BlockDeviceActive, 399 }, 400 }, 401 }, 402 }, 403 deactivatedBDs: []string{fakelocalpvVirtualDiskLegacyUUID}, 404 wantErr: false, 405 }, 406 "Type: disk, physical disk, used by zfs localPV": { 407 bd: physicalDiskUsedByZFSPV, 408 bdAPIList: &apis.BlockDeviceList{ 409 Items: []apis.BlockDevice{ 410 { 411 ObjectMeta: metav1.ObjectMeta{ 412 Name: fakezfspvPhysicalDiskUUID, 413 }, 414 Spec: apis.DeviceSpec{ 415 Path: "/dev/sda", 416 }, 417 Status: apis.DeviceStatus{ 418 ClaimState: apis.BlockDeviceUnclaimed, 419 State: apis.BlockDeviceActive, 420 }, 421 }, 422 }, 423 }, 424 deactivatedBDs: []string{fakezfspvPhysicalDiskUUID}, 425 wantErr: false, 426 }, 427 } 428 for name, tt := range tests { 429 t.Run(name, func(t *testing.T) { 430 // pinning variables 431 bd := tt.bd 432 bdAPIList := tt.bdAPIList 433 s := scheme.Scheme 434 s.AddKnownTypes(apis.GroupVersion, &apis.BlockDevice{}) 435 s.AddKnownTypes(apis.GroupVersion, &apis.BlockDeviceList{}) 436 cl := fake.NewFakeClientWithScheme(s) 437 ctrl := &controller.Controller{ 438 Clientset: cl, 439 BDHierarchy: make(blockdevice.Hierarchy), 440 } 441 442 // add the bd to cache so that removing from cache does not error out. 443 ctrl.BDHierarchy[bd.DevPath] = bd 444 445 // initialize client with all the bd resources 446 for _, bdAPI := range bdAPIList.Items { 447 cl.Create(context.TODO(), &bdAPI) 448 } 449 450 err := cl.List(context.TODO(), tt.bdAPIList) 451 if err != nil { 452 t.Errorf("error updating the resource API List %v", err) 453 } 454 455 pe := &ProbeEvent{ 456 Controller: ctrl, 457 } 458 459 if err = pe.deleteBlockDevice(bd, bdAPIList); (err != nil) != tt.wantErr { 460 t.Errorf("deleteBlockDevice() error = %v, wantErr %v", err, tt.wantErr) 461 } 462 463 gotBDList := &apis.BlockDeviceList{} 464 if err := cl.List(context.TODO(), gotBDList); err != nil { 465 t.Errorf("List call failed error = %v", err) 466 } 467 468 noOfDeactivatedBDs := 0 469 for _, gotBDAPI := range gotBDList.Items { 470 if util.Contains(tt.deactivatedBDs, gotBDAPI.Name) { 471 assert.Equal(t, apis.BlockDeviceInactive, gotBDAPI.Status.State) 472 noOfDeactivatedBDs++ 473 } else { 474 assert.Equal(t, apis.BlockDeviceActive, gotBDAPI.Status.State) 475 } 476 } 477 478 assert.Equal(t, noOfDeactivatedBDs, len(tt.deactivatedBDs)) 479 480 }) 481 } 482 }