Skip to content

Commit 7930560

Browse files
authored
Merge pull request #7621 from sagemathinc/onprem-gpu
on-prem: gpu support
2 parents 41ce5f9 + 1fe7a72 commit 7930560

File tree

15 files changed

+609
-129
lines changed

15 files changed

+609
-129
lines changed

src/packages/database/postgres/site-license/hook.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@ test("allow for much larger max_upgrades", () => {
7070
{},
7171
{ userX: {} },
7272
{ a: site_licenses.a },
73-
site_settings
73+
site_settings,
7474
);
7575
expect(q1).toEqual({
7676
quota: {
7777
network: true,
7878
member_host: false,
7979
privileged: false,
80+
gpu: false,
8081
memory_request: 1000,
8182
cpu_request: 0.1,
8283
disk_quota: 3000,
@@ -94,7 +95,7 @@ test("allow for much larger max_upgrades", () => {
9495
{},
9596
{ userX: {} },
9697
site_licenses,
97-
site_settings
98+
site_settings,
9899
);
99100
expect(q2).toEqual({
100101
quota: {
@@ -110,6 +111,7 @@ test("allow for much larger max_upgrades", () => {
110111
memory_request: 1000,
111112
network: true,
112113
privileged: false,
114+
gpu: false,
113115
},
114116
reasons: {},
115117
});
@@ -155,13 +157,14 @@ test("two licenses", () => {
155157
{},
156158
{ userX: {} },
157159
{ a: site_licenses.a },
158-
site_settings
160+
site_settings,
159161
);
160162
expect(q1).toEqual({
161163
quota: {
162164
network: true,
163165
member_host: false,
164166
privileged: false,
167+
gpu: false,
165168
memory_request: 1000,
166169
cpu_request: 0.05,
167170
disk_quota: 3000,
@@ -179,13 +182,14 @@ test("two licenses", () => {
179182
{},
180183
{ userX: {} },
181184
site_licenses,
182-
site_settings
185+
site_settings,
183186
);
184187
expect(q1).toEqual({
185188
quota: {
186189
network: true,
187190
member_host: false,
188191
privileged: false,
192+
gpu: false,
189193
memory_request: 1000,
190194
cpu_request: 0.05,
191195
disk_quota: 3000,
@@ -213,6 +217,7 @@ test("two licenses", () => {
213217
memory_request: 1000,
214218
network: true,
215219
privileged: false,
220+
gpu: false,
216221
},
217222
reasons: {},
218223
});
@@ -311,7 +316,7 @@ test("two licenses", () => {
311316
// memory_limit: 1000,
312317
// memory_request: 200,
313318
// network: false,
314-
// privileged: false,
319+
// privileged: false,gpu:false,
315320
// },
316321
// reasons: {},
317322
// });

src/packages/frontend/components/text-input.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface Props {
2020
onBlur?: () => void;
2121
disabled?: boolean;
2222
style?: CSS;
23+
size?: "small";
2324
}
2425

2526
export const TextInput: React.FC<Props> = React.memo(
@@ -34,6 +35,7 @@ export const TextInput: React.FC<Props> = React.memo(
3435
onBlur,
3536
disabled = false,
3637
style,
38+
size,
3739
} = props;
3840

3941
const inputRef = React.useRef<any>(null);
@@ -65,6 +67,7 @@ export const TextInput: React.FC<Props> = React.memo(
6567
style={{ marginBottom: "15px" }}
6668
bsStyle="success"
6769
onClick={saveChange}
70+
bsSize={size === "small" ? "xsmall" : undefined}
6871
>
6972
<Icon name="save" /> Save
7073
</Button>
@@ -87,6 +90,7 @@ export const TextInput: React.FC<Props> = React.memo(
8790
onFocus={onFocus}
8891
onBlur={onBlur}
8992
disabled={disabled}
93+
size={size === "small" ? "small" : undefined}
9094
/>
9195
</Form.Item>
9296
);
@@ -98,5 +102,5 @@ export const TextInput: React.FC<Props> = React.memo(
98102
{render_save_button()}
99103
</Form>
100104
);
101-
}
105+
},
102106
);

src/packages/frontend/project/settings/quota-editor/admin-quotas.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import { useEffect, useState } from "react";
77
import { Button, Card, Popconfirm, Popover } from "antd";
8+
import { isEqual } from "lodash";
9+
810
import { alert_message } from "@cocalc/frontend/alerts";
911
import { Icon, Loading } from "@cocalc/frontend/components";
1012
import { webapp_client } from "@cocalc/frontend/webapp-client";
@@ -13,16 +15,16 @@ import { PROJECT_UPGRADES } from "@cocalc/util/schema";
1315
import type { ProjectSettings } from "../types";
1416
import QuotaRow from "./quota-row";
1517
import type { QuotaParams } from "./types";
16-
import { isEqual } from "lodash";
17-
import { useRedux } from "@cocalc/frontend/app-framework";
18+
import { CSS, useRedux } from "@cocalc/frontend/app-framework";
1819

1920
const QUOTA_PARAMS = PROJECT_UPGRADES.params;
2021

2122
interface Props {
2223
project_id: string;
24+
style?: CSS;
2325
}
2426

25-
export default function AdminQuotas({ project_id }: Props) {
27+
export default function AdminQuotas({ project_id, style }: Props) {
2628
const projectSettings: ProjectSettings | undefined = useRedux([
2729
"projects",
2830
"project_map",
@@ -114,6 +116,7 @@ export default function AdminQuotas({ project_id }: Props) {
114116

115117
return (
116118
<Card
119+
style={style}
117120
title={
118121
<>
119122
<Icon name="user-plus" /> Admin Quota Editor

src/packages/frontend/project/settings/run-quota/hooks.tsx

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,39 @@
33
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
44
*/
55

6-
import { Map, List } from "immutable";
6+
import { List, Map } from "immutable";
77
import { fromPairs, isEqual } from "lodash";
88

9+
import { ProjectStatus } from "@cocalc/comm/project-status/types";
910
import {
11+
TypedMap,
1012
useEffect,
1113
useMemo,
1214
useState,
1315
useTypedRedux,
1416
} from "@cocalc/frontend/app-framework";
15-
import { ProjectStatus } from "@cocalc/comm/project-status/types";
1617
import {
1718
KUCALC_COCALC_COM,
1819
KUCALC_DISABLED,
1920
KUCALC_ON_PREMISES,
2021
} from "@cocalc/util/db-schema/site-defaults";
2122
import { round1, seconds2hms, server_time } from "@cocalc/util/misc";
2223
import { PROJECT_UPGRADES } from "@cocalc/util/schema";
24+
import { GPU } from "@cocalc/util/types/site-licenses";
2325
import {
26+
Upgrades,
2427
quota2upgrade_key,
2528
upgrade2quota_key,
26-
Upgrades,
2729
} from "@cocalc/util/upgrades/quota";
2830
import { IdleTimeoutPct, PercentBar, renderBoolean } from "./components";
2931
import {
30-
booleanValueStr,
3132
CurrentUsage,
3233
DisplayQuota,
3334
MAX_UPGRADES,
3435
PARAMS,
35-
renderValueUnit,
3636
Usage,
37+
booleanValueStr,
38+
renderValueUnit,
3739
} from "./misc";
3840

3941
export function useRunQuota(
@@ -53,7 +55,14 @@ export function useRunQuota(
5355
} else {
5456
return rq
5557
.map((val, key) => {
56-
if (typeof val !== "number") {
58+
if (key === "gpu") {
59+
const v = val as boolean | TypedMap<GPU>;
60+
if (typeof v === "boolean") {
61+
return v ? 1 : null;
62+
} else {
63+
return v?.get("num", 0);
64+
}
65+
} else if (typeof val !== "number") {
5766
return val;
5867
} else if (key == "idle_timeout") {
5968
return seconds2hms(val, false, false);
@@ -120,9 +129,9 @@ export function useCurrentUsage({
120129
const last_edited: Date | undefined = project_map
121130
?.get(project_id)
122131
?.get("last_edited");
123-
const runQuota: Map<string, number | List<object>> | undefined = project_map
124-
?.get(project_id)
125-
?.get("run_quota");
132+
const runQuota:
133+
| Map<string, number | Map<string, number | string> | List<object>>
134+
| undefined = project_map?.get(project_id)?.get("run_quota");
126135

127136
const [currentUsage, setCurrentUsage] = useState<CurrentUsage>({});
128137

@@ -233,6 +242,14 @@ export function useCurrentUsage({
233242
const p = runQuota?.get(key);
234243
const x = List.isList(p) ? p?.size : "N/A";
235244
return [key, { display: `${x}`, element: <>{x}</> }];
245+
case "gpu":
246+
const gpu = runQuota?.get(key);
247+
if (!gpu) return [key, { display: "N/A", element: <>N/A</> }];
248+
const num = Map.isMap(gpu) ? gpu.get("num", 1) : 1;
249+
return [
250+
key,
251+
{ display: `${num}`, element: <>{JSON.stringify(num)}</> },
252+
];
236253
default:
237254
return [key, { display: name, element: <>{name}</> }];
238255
}
@@ -258,9 +275,9 @@ export function useDisplayedFields(): string[] {
258275
// we have to make a copy, because we might modify it below
259276
const fields: string[] = [...PROJECT_UPGRADES.field_order];
260277

261-
// on kucalc on-prem, we add ext_rw and patch
278+
// on kucalc on-prem, we add ext_rw, patch and gpu
262279
if (kucalc === KUCALC_ON_PREMISES) {
263-
fields.push(...["ext_rw", "patch"]);
280+
fields.push(...["ext_rw", "patch", "gpu"]);
264281
}
265282

266283
return fields.filter((key: keyof Upgrades) => {

src/packages/frontend/project/settings/run-quota/run-quota.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ export const RunQuota: React.FC<Props> = React.memo(
166166
const { key, quota, quotaDedicated, usage } = record;
167167
if (QUOTAS_BOOLEAN.includes(key as any)) {
168168
return `This quota is ${booleanValueStr(quota)}.`;
169+
} else if (key === "gpu") {
170+
return usage != null
171+
? `There are ${usage.display} GPU(s) requested.`
172+
: ``;
169173
} else if (key === "patch") {
170174
return usage != null
171175
? `There are ${usage.display} patch(es) in total.`
@@ -221,6 +225,7 @@ export const RunQuota: React.FC<Props> = React.memo(
221225
// the usage of a boolean quota is always the same as its value
222226
if (QUOTAS_BOOLEAN.includes(record.key as any)) return;
223227
if (record.key === "patch") return;
228+
if (record.key === "gpu") return;
224229
const usage: Usage = record.usage;
225230
if (usage == null) return;
226231
const { element } = usage;
@@ -243,15 +248,13 @@ export const RunQuota: React.FC<Props> = React.memo(
243248

244249
if (typeof val === "boolean") {
245250
return renderBoolean(val, projectIsRunning);
246-
} else if (typeof val === "number") {
247-
if (record.key === "idle_timeout") {
248-
return val;
249-
}
251+
} else if (record.key === "idle_timeout") {
252+
return val;
250253
} else if (Array.isArray(val)) {
251254
return val.length;
252255
} else {
253256
return (
254-
<Text strong={true} style={style}>
257+
<Text strong style={style}>
255258
<NoWrap>{val}</NoWrap>
256259
</Text>
257260
);

0 commit comments

Comments
 (0)