@@ -30,28 +30,54 @@ func (g *GKEOrchestrator) isNAPEnabledForMachineType(machineType, zone string) (
3030 resolvedType := config .ResolveMachineType (machineType )
3131
3232 if config .IsTPU (resolvedType ) {
33- key := strings .ToLower (g .GenerateGKENodeSelectorLabel (resolvedType ))
34- return g .napLimits [key ] > 0 || g .napLimits ["google.com/tpu" ] > 0 , nil
33+ return g .validateTPUNAPLimit (resolvedType )
3534 }
3635
3736 cap , err := g .FetchMachineCapabilities (resolvedType , zone )
3837 if err != nil {
3938 return false , err
4039 }
4140 if len (cap .Accelerators ) > 0 {
42- key := strings .ToLower (g .GenerateGKENodeSelectorLabel (resolvedType ))
43- if strings .EqualFold (key , resolvedType ) {
44- key = strings .ToLower (g .GenerateGKENodeSelectorLabel (cap .Accelerators [0 ].Type ))
45- }
46- if ! isKnownGKEAccelerator (key ) {
47- return false , fmt .Errorf ("unknown accelerator label: %q" , cap .Accelerators [0 ].Type )
48- }
49- return g .napLimits [key ] > 0 || g .napLimits ["nvidia.com/gpu" ] > 0 , nil
41+ return g .validateGPUNAPLimit (resolvedType , cap )
5042 }
5143
5244 return g .napLimits ["cpu" ] > 0 , nil
5345}
5446
47+ func (g * GKEOrchestrator ) validateTPUNAPLimit (resolvedType string ) (bool , error ) {
48+ key := strings .ToLower (g .GenerateGKENodeSelectorLabel (resolvedType ))
49+ if limit , exists := g .napLimits [key ]; exists {
50+ return limit > 0 , nil
51+ }
52+ // Fallback to generic TPU limit ONLY if no specific TPU limits are configured.
53+ for k := range g .napLimits {
54+ if isSpecificTPUKey (k ) {
55+ return false , nil
56+ }
57+ }
58+ return g .napLimits ["google.com/tpu" ] > 0 , nil
59+ }
60+
61+ func (g * GKEOrchestrator ) validateGPUNAPLimit (resolvedType string , cap MachineTypeCap ) (bool , error ) {
62+ key := strings .ToLower (g .GenerateGKENodeSelectorLabel (resolvedType ))
63+ if strings .EqualFold (key , resolvedType ) {
64+ key = strings .ToLower (g .GenerateGKENodeSelectorLabel (cap .Accelerators [0 ].Type ))
65+ }
66+ if ! isKnownGKEAccelerator (key ) {
67+ return false , fmt .Errorf ("unknown accelerator label: %q" , cap .Accelerators [0 ].Type )
68+ }
69+ if limit , exists := g .napLimits [key ]; exists {
70+ return limit > 0 , nil
71+ }
72+ // Fallback to generic GPU limit ONLY if no specific GPU limits are configured.
73+ for k := range g .napLimits {
74+ if isSpecificGPUKey (k ) {
75+ return false , nil
76+ }
77+ }
78+ return g .napLimits ["nvidia.com/gpu" ] > 0 , nil
79+ }
80+
5581func (g * GKEOrchestrator ) checkNAPFlagsSupported (hasNAPFlags bool , job * orchestrator.JobDefinition ) error {
5682 if ! g .napEnabled && hasNAPFlags {
5783 return fmt .Errorf ("GKE NAP provisioning options (--gke-nap-provisioning %q, --gke-nap-reservation %q) are only supported on GKE clusters with Node Auto-Provisioning (NAP) enabled. The current cluster does not have NAP enabled.\n Remediation: Enable Node Auto-Provisioning on your cluster to use these options, or submit your job without them" , job .GKENAPProvisioning , job .GKENAPReservation )
@@ -126,6 +152,14 @@ func extractShortReservationName(resName string) string {
126152 return parts [len (parts )- 1 ]
127153}
128154
155+ func isSpecificGPUKey (key string ) bool {
156+ return strings .HasPrefix (key , "nvidia-" )
157+ }
158+
159+ func isSpecificTPUKey (key string ) bool {
160+ return strings .HasPrefix (key , "tpu-" )
161+ }
162+
129163func isKnownGKEAccelerator (key string ) bool {
130164 switch key {
131165 case "nvidia-tesla-t4" , "nvidia-tesla-v100" :
0 commit comments