github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/cmd/ndm_daemonset/probe/addhandler.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 "fmt" 21 22 apis "github.com/openebs/node-disk-manager/api/v1alpha1" 23 "github.com/openebs/node-disk-manager/blockdevice" 24 "github.com/openebs/node-disk-manager/db/kubernetes" 25 "github.com/openebs/node-disk-manager/pkg/features" 26 "github.com/openebs/node-disk-manager/pkg/partition" 27 28 "k8s.io/apimachinery/pkg/api/errors" 29 "k8s.io/klog/v2" 30 ) 31 32 const ( 33 internalUUIDSchemeAnnotation = "internal.openebs.io/uuid-scheme" 34 legacyUUIDScheme = "legacy" 35 gptUUIDScheme = "gpt" 36 internalFSUUIDAnnotation = "internal.openebs.io/fsuuid" 37 internalPartitionUUIDAnnotation = "internal.openebs.io/partition-uuid" 38 ) 39 40 // addBlockDeviceToHierarchyCache adds the given block device to the hierarchy of devices. 41 // returns true if the device already existed in the cache. Else returns false 42 func (pe *ProbeEvent) addBlockDeviceToHierarchyCache(bd blockdevice.BlockDevice) bool { 43 var deviceAlreadyExistsInCache bool 44 // check if the device already exists in the cache 45 _, ok := pe.Controller.BDHierarchy[bd.DevPath] 46 if ok { 47 klog.V(4).Infof("device: %s already exists in cache, "+ 48 "the event was likely generated by a partition table re-read or "+ 49 "a change in some of the devices was detected", bd.DevPath) 50 deviceAlreadyExistsInCache = true 51 } 52 if !ok { 53 klog.V(4).Infof("device: %s does not exist in cache, "+ 54 "the device is now connected to this node", bd.DevPath) 55 deviceAlreadyExistsInCache = false 56 } 57 58 // in either case, whether it existed or not, we will update with the latest BD into the cache 59 pe.Controller.BDHierarchy[bd.DevPath] = bd 60 return deviceAlreadyExistsInCache 61 } 62 63 // addBlockDevice processed when an add event is received for a device 64 func (pe *ProbeEvent) addBlockDevice(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) error { 65 66 // handle devices that are not managed by NDM 67 // eg:devices in use by mayastor, zfs PV and jiva 68 // TODO jiva handling is still to be added. 69 if ok, err := pe.handleUnmanagedDevices(bd, bdAPIList); err != nil { 70 klog.Errorf("error handling unmanaged device %s. error: %v", bd.DevPath, err) 71 return err 72 } else if !ok { 73 klog.V(4).Infof("processed device: %s being used by mayastor/zfs-localPV", bd.DevPath) 74 return nil 75 } 76 77 // if parent device in use, no need to process further 78 if ok, err := pe.isParentDeviceInUse(bd); err != nil { 79 klog.Error(err) 80 return err 81 } else if ok { 82 klog.Infof("parent device of device: %s in use", bd.DevPath) 83 return nil 84 } 85 86 // upgrades the devices that are in use and used the legacy method 87 // for uuid generation. 88 if ok, err := pe.upgradeBD(bd, bdAPIList); err != nil { 89 klog.Errorf("upgrade of device: %s failed. Error: %v", bd.DevPath, err) 90 return err 91 } else if !ok { 92 klog.V(4).Infof("device: %s upgraded", bd.DevPath) 93 return nil 94 } 95 96 /* 97 Cases when an add event is generated 98 1. A new disk is added to the cluster to this node - the disk is first time in this cluster 99 2. A new disk is added to this node - the disk was already present in the cluster and it was moved to this node 100 3. A disk was detached and reconnected to this node 101 4. An add event due to partition table reread . This may cause events to be generated without the disk 102 being physically removed this node - (when a new partition is created on the device also, its the same case) 103 */ 104 105 // check if the disk can be uniquely identified. we try to generate the UUID for the device 106 klog.V(4).Infof("checking if device: %s can be uniquely identified", bd.DevPath) 107 uuid, ok := generateUUID(bd) 108 // if UUID cannot be generated create a GPT partition on the device 109 if !ok { 110 klog.V(4).Infof("device: %s cannot be uniquely identified", bd.DevPath) 111 if len(bd.DependentDevices.Partitions) > 0 || 112 len(bd.DependentDevices.Holders) > 0 { 113 klog.V(4).Infof("device: %s has holders/partitions. %+v", bd.DevPath, bd.DependentDevices) 114 } else { 115 d := partition.Disk{ 116 DevPath: bd.DevPath, 117 DiskSize: bd.Capacity.Storage, 118 LogicalBlockSize: uint64(bd.DeviceAttributes.LogicalBlockSize), 119 } 120 121 if features.FeatureGates.IsEnabled(features.PartitionTableUUID) { 122 klog.Infof("starting to create partition table on device: %s", bd.DevPath) 123 if err := d.CreatePartitionTable(); err != nil { 124 klog.Errorf("error create partition table for %s, %v", bd.DevPath, err) 125 return err 126 } 127 klog.Infof("created new partition table in %s", bd.DevPath) 128 return ErrNeedRescan 129 } else { 130 klog.Infof("starting to create partition on device: %s", bd.DevPath) 131 if err := d.CreateSinglePartition(); err != nil { 132 klog.Errorf("error creating partition for %s, %v", bd.DevPath, err) 133 return err 134 } 135 klog.Infof("created new partition in %s", bd.DevPath) 136 return nil 137 } 138 } 139 } else { 140 bd.UUID = uuid 141 klog.V(4).Infof("uuid: %s has been generated for device: %s", uuid, bd.DevPath) 142 // update cache after generating uuid 143 pe.addBlockDeviceToHierarchyCache(bd) 144 bdAPI, err := pe.Controller.GetBlockDevice(uuid) 145 146 if errors.IsNotFound(err) { 147 klog.V(4).Infof("device: %s, uuid: %s not found in etcd", bd.DevPath, uuid) 148 /* 149 Cases when the BlockDevice is not found in etcd 150 1. The device is appearing in this cluster for the first time 151 2. The device had partitions and BlockDevice was not created 152 */ 153 154 if bd.DeviceAttributes.DeviceType == blockdevice.BlockDeviceTypePartition { 155 klog.V(4).Infof("device: %s is partition", bd.DevPath) 156 klog.V(4).Info("checking if device has a parent") 157 // check if device has a parent that is claimed 158 parentBD, ok := pe.Controller.BDHierarchy[bd.DependentDevices.Parent] 159 if !ok { 160 klog.V(4).Infof("unable to find parent device for device: %s", bd.DevPath) 161 return fmt.Errorf("cannot get parent device for device: %s", bd.DevPath) 162 } 163 164 klog.V(4).Infof("parent device: %s found for device: %s", parentBD.DevPath, bd.DevPath) 165 klog.V(4).Infof("checking if parent device can be uniquely identified") 166 parentUUID, parentOK := generateUUID(parentBD) 167 if !parentOK { 168 klog.V(4).Infof("unable to generate UUID for parent device, may be a device without WWN") 169 // cannot generate UUID for parent, may be a device without WWN 170 // used the new algorithm to create partitions 171 return pe.createBlockDeviceResourceIfNoHolders(bd, bdAPIList) 172 } 173 174 klog.V(4).Infof("uuid: %s generated for parent device: %s", parentUUID, parentBD.DevPath) 175 176 parentBDAPI, err := pe.Controller.GetBlockDevice(parentUUID) 177 178 if errors.IsNotFound(err) { 179 // parent not present in etcd, may be device without wwn or had partitions/holders 180 klog.V(4).Infof("parent device: %s, uuid: %s not found in etcd", parentBD.DevPath, parentUUID) 181 return pe.createBlockDeviceResourceIfNoHolders(bd, bdAPIList) 182 } 183 184 if err != nil { 185 klog.Error(err) 186 return err 187 // get call failed 188 } 189 190 if parentBDAPI.Status.ClaimState != apis.BlockDeviceUnclaimed { 191 // device is in use, and the consumer is doing something 192 // do nothing 193 klog.V(4).Infof("parent device: %s is in use, device: %s can be ignored", parentBD.DevPath, bd.DevPath) 194 return nil 195 } else { 196 // the consumer created some partitions on the disk. 197 // So the parent BD need to be deactivated and partition BD need to be created. 198 // 1. deactivate parent 199 // 2. create resource for partition 200 201 pe.Controller.DeactivateBlockDevice(*parentBDAPI) 202 existingBlockDeviceResource := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, bd.UUID) 203 annotations := map[string]string{ 204 internalUUIDSchemeAnnotation: gptUUIDScheme, 205 } 206 207 err = pe.createOrUpdateWithAnnotation(annotations, bd, existingBlockDeviceResource) 208 if err != nil { 209 klog.Error(err) 210 return err 211 } 212 return nil 213 } 214 215 } 216 217 if bd.DeviceAttributes.DeviceType != blockdevice.BlockDeviceTypePartition && 218 len(bd.DependentDevices.Partitions) > 0 { 219 klog.V(4).Infof("device: %s has partitions: %+v", bd.DevPath, bd.DependentDevices.Partitions) 220 return nil 221 } 222 223 return pe.createBlockDeviceResourceIfNoHolders(bd, bdAPIList) 224 } 225 226 if err != nil { 227 klog.Errorf("querying etcd failed: %+v", err) 228 return err 229 } 230 231 if bdAPI.Status.ClaimState != apis.BlockDeviceUnclaimed { 232 klog.V(4).Infof("device: %s is in use. update the details of the blockdevice", bd.DevPath) 233 234 annotation := map[string]string{ 235 internalUUIDSchemeAnnotation: gptUUIDScheme, 236 } 237 238 err = pe.createOrUpdateWithAnnotation(annotation, bd, bdAPI) 239 if err != nil { 240 klog.Errorf("updating block device resource failed: %+v", err) 241 return err 242 } 243 return nil 244 } 245 246 klog.V(4).Infof("creating resource for device: %s with uuid: %s", bd.DevPath, bd.UUID) 247 existingBlockDeviceResource := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, bd.UUID) 248 annotations := map[string]string{ 249 internalUUIDSchemeAnnotation: gptUUIDScheme, 250 } 251 252 err = pe.createOrUpdateWithAnnotation(annotations, bd, existingBlockDeviceResource) 253 if err != nil { 254 klog.Errorf("creation of resource failed: %+v", err) 255 return err 256 } 257 return nil 258 } 259 return nil 260 } 261 262 // createBlockDeviceResourceIfNoHolders creates/updates a blockdevice resource if it does not have any 263 // holder devices 264 func (pe *ProbeEvent) createBlockDeviceResourceIfNoHolders(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) error { 265 if len(bd.DependentDevices.Holders) > 0 { 266 klog.V(4).Infof("device: %s has holder devices: %+v", bd.DevPath, bd.DependentDevices.Holders) 267 klog.V(4).Infof("skip creating BlockDevice resource") 268 return nil 269 } 270 271 klog.V(4).Infof("creating block device resource for device: %s with uuid: %s", bd.DevPath, bd.UUID) 272 273 existingBlockDeviceResource := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, bd.UUID) 274 275 annotations := map[string]string{ 276 internalUUIDSchemeAnnotation: gptUUIDScheme, 277 } 278 279 err := pe.createOrUpdateWithAnnotation(annotations, bd, existingBlockDeviceResource) 280 if err != nil { 281 klog.Error(err) 282 return err 283 } 284 return nil 285 } 286 287 // upgradeBD returns true if further processing required after upgrade 288 // NOTE: only cstor and localPV will be upgraded. upgrade of local PV raw block is not supported 289 func (pe *ProbeEvent) upgradeBD(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) (bool, error) { 290 if !bd.DevUse.InUse { 291 // device not in use 292 return true, nil 293 } 294 295 if bd.DevUse.UsedBy == blockdevice.LocalPV { 296 if ok, err := pe.upgradeDeviceInUseByLocalPV(bd, bdAPIList); err != nil { 297 return false, err 298 } else { 299 return ok, nil 300 } 301 302 } 303 304 if bd.DevUse.UsedBy == blockdevice.CStor { 305 if ok, err := pe.upgradeDeviceInUseByCStor(bd, bdAPIList); err != nil { 306 return false, err 307 } else { 308 return ok, nil 309 } 310 } 311 // device is not used by any storage engines. proceed with normal workflow 312 return true, nil 313 } 314 315 // handleUnmanagedDevices handles add event for devices that are currently not managed by the NDM daemon 316 // returns true, if further processing is required, else false 317 // TODO include jiva storage engine also 318 func (pe *ProbeEvent) handleUnmanagedDevices(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) (bool, error) { 319 // handle if the device is used by mayastor 320 if ok, err := pe.deviceInUseByMayastor(bd, bdAPIList); err != nil { 321 return ok, err 322 } else if !ok { 323 return false, nil 324 } 325 326 // handle if the device is used by zfs localPV 327 if ok, err := pe.deviceInUseByZFSLocalPV(bd, bdAPIList); err != nil { 328 return ok, err 329 } else if !ok { 330 return false, nil 331 } 332 return true, nil 333 } 334 335 // deviceInUseByMayastor checks if the device is in use by mayastor and returns true if further processing of the event 336 // is required 337 func (pe *ProbeEvent) deviceInUseByMayastor(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) (bool, error) { 338 if !bd.DevUse.InUse { 339 return true, nil 340 } 341 342 // not in use by mayastor 343 if bd.DevUse.UsedBy != blockdevice.Mayastor { 344 return true, nil 345 } 346 347 klog.V(4).Infof("Device: %s in use by mayastor. ignoring the event", bd.DevPath) 348 return false, nil 349 } 350 351 // deviceInUseByZFSLocalPV check if the device is in use by zfs localPV and returns true if further processing of 352 // event is required. If the device has ZFS pv on it, then a blockdevice resource will be created and zfs PV tag 353 // will be added on to the resource 354 func (pe *ProbeEvent) deviceInUseByZFSLocalPV(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) (bool, error) { 355 if bd.DeviceAttributes.DeviceType == blockdevice.BlockDeviceTypePartition { 356 parentBD, ok := pe.Controller.BDHierarchy[bd.DependentDevices.Parent] 357 if !ok { 358 klog.Errorf("unable to find parent device for %s", bd.DevPath) 359 return false, fmt.Errorf("error in getting parent device for %s from device hierarchy", bd.DevPath) 360 } 361 if parentBD.DevUse.InUse && parentBD.DevUse.UsedBy == blockdevice.ZFSLocalPV { 362 klog.V(4).Infof("ParentDevice: %s of device: %s in use by zfs-localPV", parentBD.DevPath, bd.DevPath) 363 return false, nil 364 } 365 366 } 367 if !bd.DevUse.InUse { 368 return true, nil 369 } 370 371 // not in use by zfs localpv 372 if bd.DevUse.UsedBy != blockdevice.ZFSLocalPV { 373 return true, nil 374 } 375 376 klog.Infof("device: %s in use by zfs-localPV", bd.DevPath) 377 378 uuid, ok := generateUUIDFromPartitionTable(bd) 379 if !ok { 380 klog.Errorf("unable to generate uuid for zfs-localPV device: %s", bd.DevPath) 381 return false, fmt.Errorf("error generating uuid for zfs-localPV disk: %s", bd.DevPath) 382 } 383 384 bd.UUID = uuid 385 386 deviceInfo := pe.Controller.NewDeviceInfoFromBlockDevice(&bd) 387 bdAPI, err := deviceInfo.ToDevice(pe.Controller) 388 if err != nil { 389 klog.Error("Failed to create a block device resource CR, Error: ", err) 390 return true, err 391 } 392 bdAPI.Labels[kubernetes.BlockDeviceTagLabel] = string(blockdevice.ZFSLocalPV) 393 394 err = pe.Controller.CreateBlockDevice(bdAPI) 395 if err != nil { 396 klog.Errorf("unable to push %s (%s) to etcd", bd.UUID, bd.DevPath) 397 return false, err 398 } 399 klog.Infof("Pushed zfs-localPV device: %s (%s) to etcd", bd.UUID, bd.DevPath) 400 return false, nil 401 } 402 403 // upgradeDeviceInUseByCStor handles the upgrade if the device is used by cstor. returns true if further processing 404 // is required 405 func (pe *ProbeEvent) upgradeDeviceInUseByCStor(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) (bool, error) { 406 uuid, ok := generateUUID(bd) 407 if ok { 408 existingBD := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, uuid) 409 if existingBD != nil { 410 if existingBD.Status.ClaimState != apis.BlockDeviceUnclaimed { 411 // device in use using gpt UUID 412 return true, nil 413 } else { 414 // should never reach this case 415 klog.Error("unreachable state") 416 return false, fmt.Errorf("unreachable state") 417 } 418 } 419 } 420 421 legacyUUID, isVirt := generateLegacyUUID(bd) 422 existingLegacyBD := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, legacyUUID) 423 424 // check if any blockdevice exist with the annotation, if yes, that will be used. 425 // This is to handle the case where device comes at the same path of an earlier device 426 if r := getExistingBDWithPartitionUUID(bd, bdAPIList); r != nil { 427 existingLegacyBD = r 428 } 429 430 if existingLegacyBD == nil { 431 // create device with partition annotation and legacy annotation 432 // the custom create / update method should be called here 433 // no further processing is required 434 bd.UUID = legacyUUID 435 err := pe.createOrUpdateWithPartitionUUID(bd, existingLegacyBD) 436 return false, err 437 } 438 439 if existingLegacyBD.Status.ClaimState != apis.BlockDeviceUnclaimed { 440 // update resource with legacy and partition table uuid annotation 441 // further processing is not required 442 bd.UUID = existingLegacyBD.Name 443 err := pe.createOrUpdateWithPartitionUUID(bd, existingLegacyBD) 444 return false, err 445 } 446 447 if isVirt { 448 // update the resource with partition and legacy annotation 449 bd.UUID = existingLegacyBD.Name 450 err := pe.createOrUpdateWithPartitionUUID(bd, existingLegacyBD) 451 return false, err 452 } else { 453 // should never reach this case. 454 klog.Error("unreachable state") 455 return false, fmt.Errorf("unreachable state") 456 } 457 } 458 459 // upgradeDeviceInUseByLocalPV handles upgrade for devices in use by localPV. returns true if further processing required. 460 // NOTE: localPV raw block upgrade is not supported 461 func (pe *ProbeEvent) upgradeDeviceInUseByLocalPV(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) (bool, error) { 462 uuid, ok := generateUUID(bd) 463 if ok { 464 existingBD := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, uuid) 465 if existingBD != nil { 466 if existingBD.Status.ClaimState != apis.BlockDeviceUnclaimed { 467 // device in use using gpt UUID 468 return true, nil 469 } else { 470 // should never reach this case 471 klog.Error("unreachable state") 472 return false, fmt.Errorf("unreachable state") 473 } 474 } 475 } 476 477 legacyUUID, isVirt := generateLegacyUUID(bd) 478 existingLegacyBD := pe.Controller.GetExistingBlockDeviceResource(bdAPIList, legacyUUID) 479 480 // check if any blockdevice exist with the annotation, if yes, that will be used. 481 // This is to handle the case where device comes at the same path of an earlier device 482 if r := getExistingBDWithFsUuid(bd, bdAPIList); r != nil { 483 existingLegacyBD = r 484 } 485 486 // if existingBD is nil. i.e no blockdevice exist with the uuid or fsuuid annotation, then we create 487 // the resource. 488 if existingLegacyBD == nil { 489 // create device with fs annotation and legacy annotation 490 // the custom create / update method should be called here 491 // no further processing is required 492 bd.UUID = legacyUUID 493 err := pe.createOrUpdateWithFSUUID(bd, existingLegacyBD) 494 return false, err 495 } 496 497 if existingLegacyBD.Status.ClaimState != apis.BlockDeviceUnclaimed { 498 // update resource with legacy and fsuuid annotation 499 // further processing is not required 500 bd.UUID = existingLegacyBD.Name 501 err := pe.createOrUpdateWithFSUUID(bd, existingLegacyBD) 502 return false, err 503 } 504 505 if isVirt { 506 // update the resource with fs and legacy annotation 507 bd.UUID = existingLegacyBD.Name 508 err := pe.createOrUpdateWithFSUUID(bd, existingLegacyBD) 509 return false, err 510 } else { 511 // should never reach this case. 512 klog.Error("unreachable state") 513 return false, fmt.Errorf("unreachable state") 514 } 515 } 516 517 // isParentDeviceInUse checks if the parent device of a given device is in use. 518 // The check is made only if the device is a partition 519 func (pe *ProbeEvent) isParentDeviceInUse(bd blockdevice.BlockDevice) (bool, error) { 520 if bd.DeviceAttributes.DeviceType != blockdevice.BlockDeviceTypePartition { 521 return false, nil 522 } 523 524 parentBD, ok := pe.Controller.BDHierarchy[bd.DependentDevices.Parent] 525 if !ok { 526 return false, fmt.Errorf("cannot find parent device of %s", bd.DevPath) 527 } 528 529 return parentBD.DevUse.InUse, nil 530 } 531 532 // getExistingBDWithFsUuid returns the blockdevice with matching FSUUID annotation from etcd 533 func getExistingBDWithFsUuid(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) *apis.BlockDevice { 534 if len(bd.FSInfo.FileSystemUUID) == 0 { 535 return nil 536 } 537 for _, bdAPI := range bdAPIList.Items { 538 fsUUID, ok := bdAPI.Annotations[internalFSUUIDAnnotation] 539 if !ok { 540 continue 541 } 542 if fsUUID == bd.FSInfo.FileSystemUUID { 543 return &bdAPI 544 } 545 } 546 return nil 547 } 548 549 // getExistingBDWithPartitionUUID returns the blockdevice with matching partition uuid annotation from etcd 550 func getExistingBDWithPartitionUUID(bd blockdevice.BlockDevice, bdAPIList *apis.BlockDeviceList) *apis.BlockDevice { 551 if len(bd.PartitionInfo.PartitionTableUUID) == 0 { 552 return nil 553 } 554 for _, bdAPI := range bdAPIList.Items { 555 partitionUUID, ok := bdAPI.Annotations[internalPartitionUUIDAnnotation] 556 if !ok { 557 continue 558 } 559 if partitionUUID == bd.PartitionInfo.PartitionTableUUID { 560 return &bdAPI 561 } 562 } 563 return nil 564 } 565 566 // createOrUpdateWithFSUUID creates/updates a resource in etcd. It additionally adds an annotation with the 567 // fs uuid of the blockdevice 568 func (pe *ProbeEvent) createOrUpdateWithFSUUID(bd blockdevice.BlockDevice, existingBD *apis.BlockDevice) error { 569 annotation := map[string]string{ 570 internalUUIDSchemeAnnotation: legacyUUIDScheme, 571 internalFSUUIDAnnotation: bd.FSInfo.FileSystemUUID, 572 } 573 err := pe.createOrUpdateWithAnnotation(annotation, bd, existingBD) 574 if err != nil { 575 klog.Errorf("could not push localPV device: %s (%s) to etcd", bd.UUID, bd.DevPath) 576 return err 577 } 578 klog.Infof("Pushed localPV device: %s (%s) to etcd", bd.UUID, bd.DevPath) 579 return nil 580 } 581 582 // createOrUpdateWithPartitionUUID create/update a resource in etcd. It additionally adds an annotation with the 583 // partition table uuid of the blockdevice 584 func (pe *ProbeEvent) createOrUpdateWithPartitionUUID(bd blockdevice.BlockDevice, existingBD *apis.BlockDevice) error { 585 annotation := map[string]string{ 586 internalUUIDSchemeAnnotation: legacyUUIDScheme, 587 internalPartitionUUIDAnnotation: bd.PartitionInfo.PartitionTableUUID, 588 } 589 err := pe.createOrUpdateWithAnnotation(annotation, bd, existingBD) 590 if err != nil { 591 klog.Errorf("could not push cstor device: %s (%s) to etcd", bd.UUID, bd.DevPath) 592 return err 593 } 594 klog.Infof("Pushed cstor device: %s (%s) to etcd", bd.UUID, bd.DevPath) 595 return nil 596 } 597 598 // createOrUpdateWithAnnotation creates or updates a resource in etcd with given annotation. 599 func (pe *ProbeEvent) createOrUpdateWithAnnotation(annotation map[string]string, bd blockdevice.BlockDevice, existingBD *apis.BlockDevice) error { 600 deviceInfo := pe.Controller.NewDeviceInfoFromBlockDevice(&bd) 601 bdAPI, err := deviceInfo.ToDevice(pe.Controller) 602 if err != nil { 603 klog.Error("Failed to create a block device resource CR, Error: ", err) 604 return err 605 } 606 bdAPI.Annotations = annotation 607 608 if existingBD != nil { 609 err = pe.Controller.UpdateBlockDevice(bdAPI, existingBD) 610 } else { 611 err = pe.Controller.CreateBlockDevice(bdAPI) 612 } 613 if err != nil { 614 klog.Errorf("unable to push %s (%s) to etcd", bd.UUID, bd.DevPath) 615 return err 616 } 617 return nil 618 }