1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { StyleRulesCallback, WithStyles, withStyles, Card, CardContent, Typography, Grid } from '@material-ui/core';
7 import { ArvadosTheme } from 'common/custom-theme';
8 import { ResourceIcon } from 'components/icon/icon';
9 import { RootState } from 'store/store';
10 import { connect } from 'react-redux';
11 import { ClusterConfigJSON } from 'common/config';
12 import { NotFoundView } from 'views/not-found-panel/not-found-panel';
13 import { formatCWLResourceSize, formatCost, formatFileSize } from 'common/formatters';
14 import { DetailsAttribute } from 'components/details-attribute/details-attribute';
15 import { DefaultCodeSnippet } from 'components/default-code-snippet/default-code-snippet';
17 type CssRules = 'root' | 'infoBox' | 'instanceType';
19 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
21 width: "calc(100% + 20px)",
26 padding: "0 10px 10px",
33 type InstanceTypesPanelConnectedProps = {config: ClusterConfigJSON};
35 type InstanceTypesPanelRootProps = InstanceTypesPanelConnectedProps & WithStyles<CssRules>;
37 const mapStateToProps = ({auth}: RootState): InstanceTypesPanelConnectedProps => ({
38 config: auth.config.clusterConfig,
41 export const InstanceTypesPanel = withStyles(styles)(connect(mapStateToProps)(
42 ({ config, classes }: InstanceTypesPanelRootProps) => {
44 const instances = config.InstanceTypes || {};
46 return <Grid className={classes.root} container direction="row">
47 <Grid className={classes.infoBox} item xs={12}>
50 <Typography variant="body2">
51 These are the cloud compute instance types
52 configured for this cluster. The core count and
53 maximum RAM request correspond to the greatest
54 values you can put in the CWL Workflow
61 <DefaultCodeSnippet inline lines={["minRAM"]} />{" "}
62 and still be scheduled on that instance type.
67 {Object.keys(instances).length > 0 ?
68 Object.keys(instances)
70 const typeA = instances[a];
71 const typeB = instances[b];
73 if (typeA.Price !== typeB.Price) {
74 return typeA.Price - typeB.Price;
76 return typeA.ProviderType.localeCompare(typeB.ProviderType);
78 }).map((instanceKey) => {
79 const instanceType = instances[instanceKey];
80 const maxDiskRequest = instanceType.IncludedScratch;
81 const keepBufferOverhead = calculateKeepBufferOverhead(instanceType.VCPUs);
82 const maxRamRequest = discountRamByPercent(instanceType.RAM - config.Containers.ReserveExtraRAM - keepBufferOverhead);
84 return <Grid data-cy={instanceKey} className={classes.instanceType} item sm={6} xs={12} key={instanceKey}>
87 <Typography variant="h6">
91 <DetailsAttribute label="Provider type" value={instanceType.ProviderType} />
94 <DetailsAttribute label="Price" value={formatCost(instanceType.Price)} />
97 <DetailsAttribute label="Cores" value={instanceType.VCPUs} />
100 <DetailsAttribute label="Max RAM request" value={`${formatCWLResourceSize(maxRamRequest)} (${formatFileSize(maxRamRequest)})`} />
103 <DetailsAttribute label="Max disk request" value={`${formatCWLResourceSize(maxDiskRequest)} (${formatFileSize(maxDiskRequest)})`} />
106 <DetailsAttribute label="Preemptible" value={instanceType.Preemptible.toString()} />
108 {instanceType.CUDA && instanceType.CUDA.DeviceCount > 0 ?
111 <DetailsAttribute label="CUDA GPUs" value={instanceType.CUDA.DeviceCount} />
114 <DetailsAttribute label="Hardware capability" value={instanceType.CUDA.HardwareCapability} />
117 <DetailsAttribute label="Driver version" value={instanceType.CUDA.DriverVersion} />
127 messages={["No instances found"]}
134 export const calculateKeepBufferOverhead = (coreCount: number): number => {
135 // TODO replace with exported server config
136 const buffersPerVCPU = 1;
138 // Returns 220 MiB + 64MiB+10% per buffer
139 return (220 << 20) + (buffersPerVCPU * coreCount * (1 << 26) * (11/10))
142 export const discountRamByPercent = (requestedRamBytes: number): number => {
143 // TODO replace this with exported server config or remove when no longer
144 // used by server in ram calculation
145 const discountPercent = 5;
147 return requestedRamBytes * 100 / (100-discountPercent);