@@ -5,6 +5,7 @@ package controller
55
66import (
77 "context"
8+ "crypto/md5"
89 "crypto/rand"
910 "crypto/rsa"
1011 "encoding/json"
@@ -812,6 +813,7 @@ func (r *ServerReconciler) extractServerDetailsFromRegistry(ctx context.Context,
812813 }
813814
814815 serverBase := server .DeepCopy ()
816+
815817 // update network interfaces
816818 nics := make ([]metalv1alpha1.NetworkInterface , 0 , len (serverDetails .NetworkInterfaces ))
817819 for _ , s := range serverDetails .NetworkInterfaces {
@@ -888,6 +890,23 @@ func (r *ServerReconciler) patchServerState(ctx context.Context, server *metalv1
888890 return true , nil
889891}
890892
893+ // generatePseudoUUID generates a deterministic UUID from an input string.
894+ // Format: 99999999-xxxx-3xxx-8xxx-xxxxxxxxxxxx (prefix identifies generated UUIDs)
895+ func generatePseudoUUID (input string ) string {
896+ hash := md5 .Sum ([]byte (input ))
897+ hashHex := fmt .Sprintf ("%x" , hash [:])
898+
899+ // Build UUID with version (3) and variant (8) bits set
900+ uuid := fmt .Sprintf ("99999999-%s-%s3%s-8%s-%s" ,
901+ hashHex [0 :4 ],
902+ hashHex [4 :8 ],
903+ hashHex [8 :11 ],
904+ hashHex [11 :14 ],
905+ hashHex [14 :32 ],
906+ )
907+ return uuid
908+ }
909+
891910func (r * ServerReconciler ) patchServerURI (ctx context.Context , log logr.Logger , bmcClient bmc.BMC , server * metalv1alpha1.Server ) (bool , error ) {
892911 if len (server .Spec .SystemURI ) != 0 {
893912 return false , nil
@@ -899,21 +918,55 @@ func (r *ServerReconciler) patchServerURI(ctx context.Context, log logr.Logger,
899918 return false , err
900919 }
901920
902- for _ , system := range systems {
903- if strings .EqualFold (system .UUID , server .Spec .SystemUUID ) {
904- serverBase := server .DeepCopy ()
905- server .Spec .SystemURI = system .URI
906- if err := r .Patch (ctx , server , client .MergeFrom (serverBase )); err != nil {
907- return false , fmt .Errorf ("failed to patch server URI: %w" , err )
921+ // Try to find system by UUID if one is provided
922+ if len (server .Spec .SystemUUID ) > 0 {
923+ for _ , system := range systems {
924+ if strings .EqualFold (system .UUID , server .Spec .SystemUUID ) {
925+ serverBase := server .DeepCopy ()
926+ server .Spec .SystemURI = system .URI
927+ if err := r .Patch (ctx , server , client .MergeFrom (serverBase )); err != nil {
928+ return false , fmt .Errorf ("failed to patch server URI: %w" , err )
929+ }
930+ return true , nil
908931 }
909932 }
910933 }
911- if len (server .Spec .SystemURI ) == 0 {
912- log .V (1 ).Info ("Patching systemURI failed" , "no system found for UUID" , server .Spec .SystemUUID )
934+
935+ // If no system found by UUID or UUID is empty, and we only have one system, use it
936+ // This handles cases where the Redfish implementation doesn't provide System.UUID
937+ if len (systems ) == 1 {
938+ system := systems [0 ]
939+ serverBase := server .DeepCopy ()
940+ server .Spec .SystemURI = system .URI
941+
942+ // If SystemUUID is empty, use system UUID if available, otherwise generate from SerialNumber
943+ if len (server .Spec .SystemUUID ) == 0 {
944+ if len (system .UUID ) > 0 {
945+ server .Spec .SystemUUID = system .UUID
946+ } else if len (system .SerialNumber ) > 0 {
947+ server .Spec .SystemUUID = generatePseudoUUID (system .SerialNumber )
948+ log .V (1 ).Info ("Generated pseudo-UUID from system serial number" ,
949+ "serialNumber" , system .SerialNumber , "pseudoUUID" , server .Spec .SystemUUID )
950+ } else {
951+ return false , fmt .Errorf ("system does not provide UUID or SerialNumber; cannot generate a unique identifier" )
952+ }
953+ }
954+
955+ if err := r .Patch (ctx , server , client .MergeFrom (serverBase )); err != nil {
956+ return false , fmt .Errorf ("failed to patch server URI: %w" , err )
957+ }
958+ return true , nil
959+ }
960+
961+ // Multiple systems available but couldn't match by UUID
962+ if len (server .Spec .SystemUUID ) > 0 {
963+ log .V (1 ).Info ("No system found for UUID, and multiple systems available" , "requestedUUID" , server .Spec .SystemUUID )
913964 return false , fmt .Errorf ("unable to find system URI for UUID: %v" , server .Spec .SystemUUID )
914965 }
915966
916- return true , nil
967+ // No SystemUUID provided and multiple systems available - cannot determine which to use
968+ log .V (1 ).Info ("No SystemUUID provided and multiple systems available, cannot determine target system" )
969+ return false , fmt .Errorf ("SystemUUID must be provided when multiple systems are available" )
917970}
918971
919972func (r * ServerReconciler ) ensureServerPowerState (ctx context.Context , log logr.Logger , bmcClient bmc.BMC , server * metalv1alpha1.Server ) error {
0 commit comments