41347d7ede5c3de16a69e7bf7fb23bdb353301d8
[arvados-workbench2.git] / src / views / process-panel / process-resource-card.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import {
7     StyleRulesCallback,
8     WithStyles,
9     withStyles,
10     Card,
11     CardHeader,
12     IconButton,
13     CardContent,
14     Tooltip,
15     Typography,
16     Grid,
17     CircularProgress,
18 } from '@material-ui/core';
19 import { ArvadosTheme } from 'common/custom-theme';
20 import {
21     CloseIcon,
22     MaximizeIcon,
23     MemoryIcon,
24     UnMaximizeIcon,
25     ProcessIcon
26 } from 'components/icon/icon';
27 import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
28 import { connect } from 'react-redux';
29 import { Process } from 'store/processes/process';
30 import { NodeInstanceType } from 'store/process-panel/process-panel';
31 import { DefaultView } from 'components/default-view/default-view';
32 import { DetailsAttribute } from "components/details-attribute/details-attribute";
33 import { formatFileSize } from "common/formatters";
34 import { InputCollectionMount } from 'store/processes/processes-actions';
35 import { MountKind, TemporaryDirectoryMount } from 'models/mount-types';
36
37 interface ProcessResourceCardDataProps {
38     process: Process;
39     nodeInfo: NodeInstanceType | null;
40 }
41
42 type CssRules = "card" | "header" | "title" | "avatar" | "iconHeader" | "content" | "sectionH3";
43
44 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
45     card: {
46         height: '100%'
47     },
48     header: {
49         paddingBottom: "0px"
50     },
51     title: {
52         paddingTop: theme.spacing.unit * 0.5
53     },
54     avatar: {
55         paddingTop: theme.spacing.unit * 0.5
56     },
57     iconHeader: {
58         fontSize: '1.875rem',
59         color: theme.customs.colors.greyL,
60     },
61     content: {
62         paddingTop: "0px",
63         maxHeight: `calc(100% - ${theme.spacing.unit * 7.5}px)`,
64         overflow: "auto"
65     },
66     sectionH3: {
67         margin: "0.5em",
68         color: theme.customs.colors.greyD,
69         fontSize: "0.8125rem",
70         textTransform: "uppercase",
71     }
72 });
73
74 type ProcessResourceCardProps = ProcessResourceCardDataProps & WithStyles<CssRules> & MPVPanelProps;
75
76 export const ProcessResourceCard = withStyles(styles)(connect()(
77     ({ classes, nodeInfo, doHidePanel, doMaximizePanel, doUnMaximizePanel, panelMaximized, panelName, process, }: ProcessResourceCardProps) => {
78
79         const loading = false;
80
81         let diskRequest = 0;
82         if (process.container?.mounts) {
83             for (const mnt in process.container.mounts) {
84                 const mp = process.container.mounts[mnt];
85                 if (mp.kind === MountKind.TEMPORARY_DIRECTORY) {
86                     diskRequest += mp.capacity;
87                 }
88             }
89         }
90
91         return <Card className={classes.card} data-cy="process-resources-card">
92             <CardHeader
93                 className={classes.header}
94                 classes={{
95                     content: classes.title,
96                     avatar: classes.avatar,
97                 }}
98                 avatar={<MemoryIcon className={classes.iconHeader} />}
99                 title={
100                     <Typography noWrap variant='h6' color='inherit'>
101                         Resources
102                     </Typography>
103                 }
104                 action={
105                     <div>
106                         {doUnMaximizePanel && panelMaximized &&
107                             <Tooltip title={`Unmaximize ${panelName || 'panel'}`} disableFocusListener>
108                                 <IconButton onClick={doUnMaximizePanel}><UnMaximizeIcon /></IconButton>
109                             </Tooltip>}
110                         {doMaximizePanel && !panelMaximized &&
111                             <Tooltip title={`Maximize ${panelName || 'panel'}`} disableFocusListener>
112                                 <IconButton onClick={doMaximizePanel}><MaximizeIcon /></IconButton>
113                             </Tooltip>}
114                         {doHidePanel &&
115                             <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
116                                 <IconButton disabled={panelMaximized} onClick={doHidePanel}><CloseIcon /></IconButton>
117                             </Tooltip>}
118                     </div>
119                 } />
120             <CardContent className={classes.content}>
121                 <Grid container>
122                     <Grid item xs={4}>
123                         <h3 className={classes.sectionH3}>Requested Resources</h3>
124                         <Grid container>
125                             <Grid item xs={12}>
126                                 <DetailsAttribute label="Cores" value={process.container?.runtimeConstraints.vcpus} />
127                             </Grid>
128                             <Grid item xs={12}>
129                                 <DetailsAttribute label="RAM" value={formatFileSize(process.container?.runtimeConstraints.ram)} />
130                             </Grid>
131                             <Grid item xs={12}>
132                                 <DetailsAttribute label="Disk" value={formatFileSize(diskRequest)} />
133                             </Grid>
134
135                             {process.container?.runtimeConstraints.keep_cache_ram &&
136                                 process.container?.runtimeConstraints.keep_cache_ram > 0 ?
137                                 <Grid item xs={12}>
138                                     <DetailsAttribute label="Keep cache (RAM)" value={formatFileSize(process.container?.runtimeConstraints.keep_cache_ram)} />
139                                 </Grid> : null}
140
141                             {process.container?.runtimeConstraints.keep_cache_disk &&
142                                 process.container?.runtimeConstraints.keep_cache_disk > 0 ?
143                                 <Grid item xs={12}>
144                                     <DetailsAttribute label="Keep cache (disk)" value={formatFileSize(process.container?.runtimeConstraints.keep_cache_disk)} />
145                                 </Grid> : null}
146
147                             {process.container?.runtimeConstraints.API ? <Grid item xs={12}>
148                                 <DetailsAttribute label="API access" value={process.container?.runtimeConstraints.API.toString()} />
149                             </Grid> : null}
150
151                             {process.container?.runtimeConstraints.cuda &&
152                                 process.container?.runtimeConstraints.cuda.device_count > 0 ?
153                                 <>
154                                     <Grid item xs={12}>
155                                         <DetailsAttribute label="CUDA devices" value={process.container?.runtimeConstraints.cuda.device_count} />
156                                     </Grid>
157                                     <Grid item xs={12}>
158                                         <DetailsAttribute label="CUDA driver version" value={process.container?.runtimeConstraints.cuda.driver_version} />
159                                     </Grid>
160                                     <Grid item xs={12}>
161                                         <DetailsAttribute label="CUDA hardware capability" value={process.container?.runtimeConstraints.cuda.hardware_capability} />
162                                     </Grid>
163                                 </> : null}
164                         </Grid>
165                     </Grid>
166
167
168                     <Grid item xs={8}>
169                         <h3 className={classes.sectionH3}>Assigned Instance Type</h3>
170                         {nodeInfo === null ? <Grid item xs={8}>
171                             No instance type recorded
172                         </Grid>
173                             :
174                             <Grid container>
175                                 <Grid item xs={6}>
176                                     <DetailsAttribute label="Cores" value={nodeInfo.VCPUs} />
177                                 </Grid>
178
179                                 <Grid item xs={6}>
180                                     <DetailsAttribute label="Provider type" value={nodeInfo.ProviderType} />
181                                 </Grid>
182
183                                 <Grid item xs={6}>
184                                     <DetailsAttribute label="RAM" value={formatFileSize(nodeInfo.RAM)} />
185                                 </Grid>
186
187                                 <Grid item xs={6}>
188                                     <DetailsAttribute label="Price" value={"$" + nodeInfo.Price.toString()} />
189                                 </Grid>
190
191                                 <Grid item xs={6}>
192                                     <DetailsAttribute label="Included scratch disk" value={formatFileSize(nodeInfo.IncludedScratch)} />
193                                 </Grid>
194
195                                 <Grid item xs={6}>
196                                     <DetailsAttribute label="Preemptible" value={nodeInfo.Preemptible.toString()} />
197                                 </Grid>
198
199                                 <Grid item xs={6}>
200                                     <DetailsAttribute label="Added scratch disk" value={formatFileSize(nodeInfo.AddedScratch)} />
201                                 </Grid>
202
203                                 {nodeInfo.CUDA.DeviceCount > 0 &&
204                                     <>
205                                         <Grid item xs={6}>
206                                             <DetailsAttribute label="CUDA devices" value={formatFileSize(nodeInfo.CUDA.DeviceCount)} />
207                                         </Grid>
208
209                                         <Grid item xs={6}>
210                                         </Grid>
211
212                                         <Grid item xs={6}>
213                                             <DetailsAttribute label="CUDA driver version" value={formatFileSize(nodeInfo.CUDA.DriverVersion)} />
214                                         </Grid>
215
216                                         <Grid item xs={6}>
217                                         </Grid>
218
219                                         <Grid item xs={6}>
220                                             <DetailsAttribute label="CUDA hardware capability" value={formatFileSize(nodeInfo.CUDA.HardwareCapability)} />
221                                         </Grid>
222                                     </>
223                                 }
224                             </Grid>}
225                     </Grid>
226                 </Grid>
227             </CardContent>
228         </Card >;
229     }
230 ));