@@ -34,7 +34,6 @@ import {
34
34
A ,
35
35
Gap ,
36
36
HelpIcon ,
37
- NumberInput ,
38
37
Paragraph ,
39
38
TextInput ,
40
39
} from "@cocalc/frontend/components" ;
@@ -53,6 +52,7 @@ import {
53
52
import { User } from "@cocalc/util/licenses/purchase/types" ;
54
53
import { money } from "@cocalc/util/licenses/purchase/utils" ;
55
54
import { plural , round1 , test_valid_jsonpatch } from "@cocalc/util/misc" ;
55
+ import { extract_gpu , process_gpu_quota } from "@cocalc/util/types/gpu" ;
56
56
import { SiteLicenseQuota } from "@cocalc/util/types/site-licenses" ;
57
57
import { DEDICATED_VM_ONPREM_MACHINE } from "@cocalc/util/upgrades/consts" ;
58
58
import { Upgrades } from "@cocalc/util/upgrades/quota" ;
@@ -522,7 +522,7 @@ export const QuotaEditor: React.FC<Props> = (props: Props) => {
522
522
523
523
function render_gpu_help ( ) : JSX . Element {
524
524
return (
525
- < HelpIcon title = "GPU Support" >
525
+ < HelpIcon title = "GPU Support" style = { { float : "right" } } maxWidth = "500px" >
526
526
< Paragraph >
527
527
This configures a license, which will cause the project to run on a
528
528
GPU. You need to configure your VMs in your cluster in such a way,
@@ -533,73 +533,114 @@ export const QuotaEditor: React.FC<Props> = (props: Props) => {
533
533
< code > nvidia.com/gpu: 1</ code > .
534
534
</ Paragraph >
535
535
< Paragraph >
536
- On top of that, you can optionally specify a taint, which will be
537
- tolerated by that pod. This helps with keeping all other project pods
538
- away from your GPU enabled nodes:{ " " }
539
- < code >
540
- tolerations:{ " " }
541
- { JSON . stringify ( [
542
- {
543
- key : "gpu" ,
544
- operator : "Equal" ,
545
- value : "cocalc" ,
546
- effect : "NoSchedule" ,
547
- } ,
548
- ] ) }
549
- </ code >
550
- .
536
+ On top of that, you can optionally specify a{ " " }
537
+ < Text strong > taint toleration</ Text > . This helps with keeping all
538
+ other project pods away from your GPU enabled nodes. e.g.{ " " }
539
+ < Text code > gpu=cocalc</ Text > ends up as:{ " " }
540
+ < pre >
541
+ { JSON . stringify ( {
542
+ tolerations : [
543
+ {
544
+ key : "gpu" ,
545
+ operator : "Equal" ,
546
+ value : "cocalc" ,
547
+ effect : "NoSchedule" ,
548
+ } ,
549
+ ] ,
550
+ } ) }
551
+ </ pre >
552
+ </ Paragraph >
553
+ < Paragraph >
554
+ You can also specify a < Text strong > node selector</ Text > , useful if
555
+ you have several different types of GPU nodes in your cluster, and you
556
+ want to restrict where the project can run. E.g.{ " " }
557
+ < Text code > gpu-type=nvidia-tesla-v100</ Text > ends up as{ " " }
558
+ < pre >
559
+ { JSON . stringify ( {
560
+ nodeSelector : { "gpu-type" : "nvidia-tesla-v100" } ,
561
+ } ) }
562
+ </ pre >
551
563
</ Paragraph >
552
564
</ HelpIcon >
553
565
) ;
554
566
}
555
567
556
568
function render_gpu ( ) : JSX . Element {
557
- const { gpu } = quota ;
558
- const { num = 0 , toleration = "" } =
559
- typeof gpu === "object"
560
- ? gpu
561
- : typeof gpu === "number"
562
- ? { num : gpu }
563
- : { } ;
569
+ const { num = 0 , toleration = "" , nodeLabel = "" } = extract_gpu ( quota ) ;
570
+
571
+ const debug = process_gpu_quota ( quota ) ;
572
+
564
573
return (
565
574
< Row style = { ROW_STYLE } >
566
575
< Col md = { col . control } >
567
576
< Paragraph >
568
- < Text strong > Request a GPU</ Text >
569
- </ Paragraph > { " " }
570
- < Paragraph >
571
- < NumberInput
572
- number = { num }
573
- min = { 0 }
574
- max = { 8 }
575
- on_change = { ( num : number ) =>
576
- onChange ( { gpu : { num, toleration } } )
577
- }
578
- /> { " " }
579
- GPUs (< code > nvidia.com/gpu: { num } </ code > )
580
- </ Paragraph >
581
- < Paragraph >
582
- < Text > (optional) Tolerate a taint:</ Text > { " " }
583
- < TextInput
577
+ < Checkbox
578
+ checked = { num > 0 }
584
579
disabled = { disabled }
585
- type = { "text" }
586
- on_change = { ( tol ) =>
587
- onChange ( { gpu : { num, toleration : tol . trim ( ) } } )
580
+ style = { { fontWeight : "normal" } }
581
+ onChange = { ( e ) =>
582
+ e . target . checked
583
+ ? onChange ( {
584
+ gpu : { num : num > 0 ? num : 1 , toleration, nodeLabel } ,
585
+ } )
586
+ : onChange ( { gpu : { num } } )
588
587
}
589
- style = { {
590
- fontWeight : "normal" ,
591
- display : "inline-block" ,
592
- margin : "0 10px" ,
593
- } }
594
- text = { toleration }
595
- /> { " " }
596
- (Enter < code > key=value</ code > of a node taint. e.g.{ " " }
597
- < code > gpu=cocalc</ code > means to ignore nodes tatined with key{ " " }
598
- < code > gpu</ code > and value < code > cocalc</ code > . Keep empty if you do
599
- not use taints!)
588
+ >
589
+ < Text strong > Configure GPU</ Text > { render_gpu_help ( ) }
590
+ </ Checkbox >
600
591
</ Paragraph >
601
- { render_gpu_help ( ) }
602
592
</ Col >
593
+ { num > 0 ? (
594
+ < Col md = { col . desc } >
595
+ < Paragraph >
596
+ < Text strong > Number of GPUs</ Text > { " " }
597
+ < InputNumber
598
+ min = { 1 }
599
+ size = { "small" }
600
+ value = { num }
601
+ onChange = { ( num : number ) =>
602
+ onChange ( { gpu : { num, toleration, nodeLabel } } )
603
+ }
604
+ /> { " " }
605
+ (usually "1")
606
+ </ Paragraph >
607
+ < Paragraph >
608
+ < Text strong > Node selector:</ Text > { " " }
609
+ < TextInput
610
+ size = { "small" }
611
+ disabled = { disabled }
612
+ type = { "text" }
613
+ on_change = { ( label ) =>
614
+ onChange ( {
615
+ gpu : { nodeLabel : label . trim ( ) , toleration, num } ,
616
+ } )
617
+ }
618
+ style = { { display : "inline-block" } }
619
+ text = { nodeLabel }
620
+ /> { " " }
621
+ (optional, [1])
622
+ </ Paragraph >
623
+ < Paragraph >
624
+ < Text strong > Tolerate a taint:</ Text > { " " }
625
+ < TextInput
626
+ size = { "small" }
627
+ disabled = { disabled }
628
+ type = { "text" }
629
+ on_change = { ( tol ) =>
630
+ onChange ( { gpu : { toleration : tol . trim ( ) , nodeLabel, num } } )
631
+ }
632
+ style = { { display : "inline-block" } }
633
+ text = { toleration }
634
+ /> { " " }
635
+ (optional, [1])
636
+ </ Paragraph >
637
+ < Paragraph type = "secondary" >
638
+ [1] format: < code > key=value</ code > . Keep empty if you do not use
639
+ label selectors or taints. Specify mulitple ones via a "," comma.
640
+ </ Paragraph >
641
+ < pre > { JSON . stringify ( debug , null , 2 ) } </ pre >
642
+ </ Col >
643
+ ) : undefined }
603
644
</ Row >
604
645
) ;
605
646
}
0 commit comments