Skip to content

Commit

Permalink
feat: add gpu support (#147)
Browse files Browse the repository at this point in the history
* fix: typo lease details (oseq -> dseq)

* fix: exception when manifest request fails

* feat: gpu support

* feat: add gpu support in sdl editor

* chore: update akashjs version
  • Loading branch information
jtary authored Jul 27, 2023
1 parent 436f943 commit f68eb95
Show file tree
Hide file tree
Showing 19 changed files with 4,557 additions and 4,515 deletions.
2 changes: 2 additions & 0 deletions web/.eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ env:
extends:
- eslint:recommended
- plugin:@typescript-eslint/recommended
- plugin:react/recommended
overrides: []
parser: '@typescript-eslint/parser'
parserOptions:
ecmaVersion: latest
sourceType: module
plugins:
- '@typescript-eslint'
- react
settings:
react:
version: detect
Expand Down
8 changes: 1 addition & 7 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"css": "npx tailwindcss -i ./src/style/app.scss -o ./src/style/app.css --watch"
},
"dependencies": {
"@akashnetwork/akashjs": "^0.4.5",
"@akashnetwork/akashjs": "^0.4.7",
"@cosmjs/launchpad": "^0.27.1",
"@cosmjs/proto-signing": "0.25.4",
"@craco/craco": "^6.4.4",
Expand Down Expand Up @@ -79,12 +79,6 @@
"tailwindcss": "^3.0.24",
"typescript": "^4.7.3"
},
"eslintConfig": {
"rules": {
"react-hooks/exhaustive-deps": "off",
"react/jsx-no-target-blank": 0
}
},
"browserslist": {
"production": [
">0.2%",
Expand Down
8 changes: 3 additions & 5 deletions web/src/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,18 @@ export const queryProviders = createQueryFunction(() => {

export const queryProviderInfo = createQueryFunction((owner: string | undefined) => {
const { networkType, rpcNode } = getRpcNode();
let ret = null;

const fetchMethod =
networkType === 'testnet'
? beta3.providers.fetchProviderInfo
: beta2.providers.fetchProviderInfo;

if (owner === undefined) {
ret = Promise.resolve(undefined);
} else {
ret = fetchMethod({ owner }, rpcNode);
return Promise.reject(new Error('No owner provided'));
}

return Promise.any([ret]);
return fetchMethod({ owner }, rpcNode)
.then(result => result);
});

export const queryProviderAttributes = createQueryFunction((owner: string) => {
Expand Down
3 changes: 3 additions & 0 deletions web/src/api/rpc/beta2/deployments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ export async function sendManifest(address: string, lease: Lease, sdl: any) {
// logging.warn('Sending manifest failed.');
result.text().then(reject);
}
}, (error) => {
logging.error('Error sending manifest to provider. This is likey an issue with the provider.');
console.error(error);
});
};

Expand Down
49 changes: 49 additions & 0 deletions web/src/components/Deployment/DeploymentActionButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import { Button, Stack, Link, Tooltip, ButtonProps } from '@mui/material';

type DeploymentActionButtonProps = {
tooltipTitle: string;
tooltip: React.ReactNode;
linkTo: string;
children: React.ReactNode;
} & ButtonProps;

const ConditionalTooltip = ({ children, condition, ...rest}: any) => {
return condition
? <Link {...rest}>{children}</Link>
: <Tooltip {...rest} placement="top">{children}</Tooltip>;
};


const DeploymentActionButton: React.FC<DeploymentActionButtonProps> = (props) => {
const {
tooltipTitle,
tooltip,
linkTo,
children,
...rest
} = props;

return <Stack direction="row" spacing={1} marginBottom="0.75rem" alignItems="center">
<ConditionalTooltip
title={tooltipTitle}
to={linkTo}
className="grow"
>
<Button
fullWidth
variant="outlined"
color="secondary"
sx={{
justifyContent: 'left'
}}
{...rest}
>
{children}
</Button>
</ConditionalTooltip>
{tooltip}
</Stack>;
};

export default DeploymentActionButton;
4 changes: 3 additions & 1 deletion web/src/components/Leases/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export const Leases: React.FC<LeaseProps> = ({ dseq, lease, status: leaseStatus
}
}

console.table(application);

setProviderDetails([
{ label: 'Name', value: _attributes?.organization },
{ label: 'Region', value: _attributes?.region },
Expand All @@ -86,7 +88,7 @@ export const Leases: React.FC<LeaseProps> = ({ dseq, lease, status: leaseStatus
setDetails([
{ label: 'GSEQ', value: lease?.lease?.leaseId?.gseq },
{ label: 'OSEQ', value: lease?.lease?.leaseId?.oseq },
{ label: 'OSEQ', value: dseq },
{ label: 'DSEQ', value: dseq },
]);
setCapacity([
{ label: 'Virtual CPUs', value: application?.cpu },
Expand Down
3 changes: 3 additions & 0 deletions web/src/components/MeasurementControl/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface MeasurementControlProps {
subTitle?: string;
setFieldValue: (name: string, value: string | number) => void;
disabled: boolean;
children: Array<React.ReactNode>;

[key: string]: any;
}
Expand All @@ -16,6 +17,7 @@ export const MeasurementControl: React.FC<MeasurementControlProps> = ({
subTitle,
setFieldValue,
disabled,
children,
...field
}) => {
return (
Expand All @@ -25,6 +27,7 @@ export const MeasurementControl: React.FC<MeasurementControlProps> = ({
<MeasurementSubTitle>{subTitle}</MeasurementSubTitle>
</div>
<InputNumber setFieldValue={setFieldValue} disabled={disabled} {...field} />
{children}
</MeasurementWrapper>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const EnvironmentVariable: React.FC<EnvironmentVariableProps> = ({
return (
<FieldArray
name={`sdl.services.${serviceName}.env`}
render={(arrayHelpers) => (
render={(arrayHelpers: any) => (
<SdlSectionWrapper>
{services[serviceName]?.env?.map((env, index) => (
<VariableWrapper key={index}>
Expand Down
156 changes: 156 additions & 0 deletions web/src/components/SdlConfiguration/Gpu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import React, { useCallback, useState } from 'react';
import { Field, useFormikContext } from 'formik';
import { MeasurementControl } from '../MeasurementControl';
import { AddNewButton, AddNewButtonWrapper, FieldWrapper, PlusSign, SdlSectionWrapper } from './styling';
import { Button, Box, Stack, Typography, List, ListItem, OutlinedInput } from '@mui/material';
import { IconTrash } from '../Icons';

type GpuUnitProps = {
currentProfile: string;
disabled: boolean;
};

type GpuProps = {
currentProfile: string;
disabled: boolean;
};

const GpuUnits: React.FC<GpuUnitProps> = ({ currentProfile, disabled }) => {
const { setFieldValue, values } = useFormikContext<any>();

const handleSetUnits = useCallback((name: string, units: string) => {
const unitsAsInt = parseInt(units);
setFieldValue(`sdl.profiles.compute.${currentProfile}.resources.gpu.units`, unitsAsInt);
}, [currentProfile, setFieldValue]);

return (
<FieldWrapper>
<Field
name={`sdl.profiles.compute.${currentProfile}.resources.gpu.units`}
defaultValue={formValues.sdl.profiles.compute[currentProfile].resources.gpu.units || 0}
id="gpu"
>
{({ field, form, meta }: any) => (
<React.Fragment>
<MeasurementControl
error={meta?.error}
title="GPU"
subTitle="GPUs Required"
setFieldValue={handleSetUnits}
type="number"
withOutSuffix
disabled={disabled}
{...field}
>
</MeasurementControl>
</React.Fragment>
)}
</Field>
</FieldWrapper>
);
};

// tag based component for selecting which gpus to allow.
const GpuAttributes: React.FC<GpuUnitProps> = ({ currentProfile, disabled }) => {
const { setFieldValue, values } = useFormikContext();
const formValues = (values as any);

const [attributes, setAttributes] = useState<string[]>(() => {
const attributes = formValues.sdl.profiles.compute[currentProfile].resources.gpu.attributes;
if (attributes) {
return attributes.map((attr: any) => attr.key);
}
return [];
});

const handleSetAttributes = useCallback((attributes: string[]) => {
const attrObjs = attributes
.filter((attr) => attr !== '')
.map((key) => ({ key, value: true }));

setFieldValue(`sdl.profiles.compute.${currentProfile}.resources.gpu.attributes`, attrObjs);
}, [currentProfile, setFieldValue]);

const addAttribute = useCallback(() => {
setAttributes((attributes) => [...attributes, '']);
}, []);

const removeAttribute = useCallback((index: number) => {
setAttributes((attributes) => attributes.filter((_, i) => i !== index));
}, []);

return (
<FieldWrapper>
<Typography variant="body2" color="text.secondary" marginTop={2}>
Example filters:
<List>
<ListItem>/vendor/nvidia/model/a6000 (nVidia A6000 only)</ListItem>
<ListItem>/vendor/amd/model/* (any AMD GPU)</ListItem>
</List>
</Typography>
<Stack gap={1}>
{attributes.map((attribute, index) => (
<Stack direction="row" key={index} gap={1}>
<Box
flexGrow={1}
>
<OutlinedInput
type="text"
placeholder="Enter GPU Filter"
value={attribute}
fullWidth={true}
inputProps={{
style: {
padding: '10px 16px',
}
}}
onChange={(e) => {
const newAttributes = [...attributes];
newAttributes[index] = e.target.value;
setAttributes(newAttributes);
handleSetAttributes(newAttributes);
}}
/>
</Box>
<Button onClick={() => removeAttribute(index)}
aria-label='delete'
variant="outlined">
<IconTrash />
</Button>
</Stack>
))}

{!disabled && (
<AddNewButtonWrapper>
<AddNewButton
startIcon={<PlusSign />}
variant="outlined"
size="small"
onClick={addAttribute}
>
Add New GPU Filter
</AddNewButton>
</AddNewButtonWrapper>
)}
</Stack>
</FieldWrapper >
);
};

export const Gpu: React.FC<GpuProps> = ({ currentProfile, disabled }) => {
const { values } = useFormikContext<any>();

return (
<SdlSectionWrapper>
<Typography variant="h4">
GPUs
</Typography>
<Stack>
<GpuUnits currentProfile={currentProfile} disabled={disabled} />
{values.sdl.profiles.compute[currentProfile].resources.gpu.units > 0 && (
<GpuAttributes currentProfile={currentProfile} disabled={disabled} />
)}
</Stack>
</SdlSectionWrapper>
);
};
Loading

0 comments on commit f68eb95

Please sign in to comment.