Skip to content

Commit

Permalink
Show gpu model in deployment detail page (#127)
Browse files Browse the repository at this point in the history
* Fix provider detail page (kube version)

* First iteration of endpoint

* Use akash node api instead of custom endpoint

* Improve typing

* Remove unnecessary check
  • Loading branch information
Redm4x authored Mar 14, 2024
1 parent a6cd78b commit 78b3f93
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 26 deletions.
7 changes: 6 additions & 1 deletion deploy-web/src/components/deploymentDetail/LeaseRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
useTheme
} from "@mui/material";
import { deploymentData } from "@src/utils/deploymentData";
import { sendManifestToProvider } from "@src/utils/deploymentUtils";
import { getGpusFromAttributes, sendManifestToProvider } from "@src/utils/deploymentUtils";
import { Snackbar } from "../shared/Snackbar";
import { ManifestErrorSnackbar } from "../shared/ManifestErrorSnackbar";
import { LabelValueOld } from "../shared/LabelValueOld";
Expand All @@ -47,6 +47,7 @@ import { getSplitText } from "@src/hooks/useShortText";
import { ApiProviderList } from "@src/types/provider";
import { LeaseDto } from "@src/types/deployment";
import { udenomToDenom } from "@src/utils/mathHelpers";
import { useBidInfo } from "@src/queries/useBidQuery";

const yaml = require("js-yaml");

Expand Down Expand Up @@ -144,6 +145,7 @@ export const LeaseRow = React.forwardRef<AcceptRefType, Props>(({ lease, setActi
const { classes } = useStyles();
const theme = useTheme();
const [isSendingManifest, setIsSendingManifest] = useState(false);
const { data: bid } = useBidInfo(lease.owner, lease.dseq, lease.gseq, lease.oseq, lease.provider);

React.useImperativeHandle(ref, () => ({
getLeaseStatus: loadLeaseStatus
Expand Down Expand Up @@ -210,6 +212,8 @@ export const LeaseRow = React.forwardRef<AcceptRefType, Props>(({ lease, setActi
updateFavoriteProviders(newFavorites);
};

const gpuModels = bid && bid.bid.resources_offer.flatMap(x => getGpusFromAttributes(x.resources.gpu.attributes));

return (
<Card className={classes.root} elevation={4}>
<CardHeader
Expand Down Expand Up @@ -256,6 +260,7 @@ export const LeaseRow = React.forwardRef<AcceptRefType, Props>(({ lease, setActi
<SpecDetail
cpuAmount={lease.cpuAmount}
gpuAmount={lease.gpuAmount}
gpuModels={gpuModels}
memoryAmount={lease.memoryAmount}
storageAmount={lease.storageAmount}
color={isLeaseActive ? "primary" : "default"}
Expand Down
13 changes: 2 additions & 11 deletions deploy-web/src/components/newDeploymentWizard/BidRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Uptime } from "../providers/Uptime";
import { udenomToDenom } from "@src/utils/mathHelpers";
import { hasSomeParentTheClass } from "@src/utils/domUtils";
import WarningIcon from "@mui/icons-material/Warning";
import { getGpusFromAttributes } from "@src/utils/deploymentUtils";

const useStyles = makeStyles()(theme => ({
root: {
Expand Down Expand Up @@ -101,17 +102,7 @@ export const BidRow: React.FunctionComponent<Props> = ({ bid, selectedBid, handl
enabled: false,
retry: false
});
const gpuModels = bid.resourcesOffer
.map(x =>
x.resources.gpu.attributes
.filter(y => y.key.startsWith("vendor/"))
.map(y => {
const modelKey = y.key.split("/");
// vendor/nvidia/model/h100 -> nvidia,h100
return { vendor: modelKey[1], model: modelKey[modelKey.length - 1] };
})
)
.flat();
const gpuModels = bid.resourcesOffer.flatMap(x => getGpusFromAttributes(x.resources.gpu.attributes));

useEffect(() => {
if (provider) {
Expand Down
38 changes: 35 additions & 3 deletions deploy-web/src/components/shared/SpecDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,25 @@ const useStyles = makeStyles()(theme => ({
}
}));

export function SpecDetail({ cpuAmount, memoryAmount, storageAmount, gpuAmount = 0, color = "default", size = "large", gutterSize = "large" }) {
export function SpecDetail({
cpuAmount,
memoryAmount,
storageAmount,
gpuAmount = 0,
gpuModels,
color = "default",
size = "large",
gutterSize = "large"
}: {
cpuAmount: number;
memoryAmount: number;
storageAmount: number;
gpuAmount?: number;
gpuModels?: { vendor: string; model: string }[];
color?: React.ComponentProps<typeof Chip>["color"];
size?: "small" | "medium" | "large";
gutterSize?: "small" | "medium" | "large";
}) {
const { classes } = useStyles();
const memory = bytesToShrink(memoryAmount);
const storage = bytesToShrink(storageAmount);
Expand All @@ -75,8 +93,7 @@ export function SpecDetail({ cpuAmount, memoryAmount, storageAmount, gpuAmount =
>
<Chip
variant="outlined"
// TODO Type
color={color as any}
color={color}
classes={{ root: classes.chipRoot }}
className={cx({ [classes.defaultColor]: color === "default" })}
label={
Expand Down Expand Up @@ -123,13 +140,28 @@ export function SpecDetail({ cpuAmount, memoryAmount, storageAmount, gpuAmount =
})}
/>
<Box
style={{ display: "flex", alignItems: "center" }}
className={cx(classes.specDetail, {
[classes.specDetailSmall]: size === "small",
[classes.specDetailMedium]: size === "medium",
[classes.specDetailLarge]: size === "large"
})}
>
{gpuAmount + " GPU"}

{gpuModels?.length > 0 && (
<div style={{ display: "inline", marginLeft: "5px" }}>
{gpuModels.map((gpu, i) => (
<Chip
key={`${gpu.vendor}-${gpu.model}`}
label={`${gpu.vendor}-${gpu.model}`}
sx={{ marginRight: i < gpuModels.length ? ".2rem" : 0 }}
color="default"
size="small"
/>
))}
</div>
)}
</Box>
</div>
}
Expand Down
1 change: 0 additions & 1 deletion deploy-web/src/pages/deployments/[dseq].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,3 @@ export async function getServerSideProps({ params }) {
}
};
}

11 changes: 1 addition & 10 deletions deploy-web/src/pages/providers/[owner]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useState, useEffect } from "react";
import { Typography, Box, Paper, useTheme, CircularProgress, Alert } from "@mui/material";
import { useRouter } from "next/router";
import { useAllLeases } from "@src/queries/useLeaseQuery";
import Layout from "@src/components/layout/Layout";
import { useWallet } from "@src/context/WalletProvider";
Expand Down Expand Up @@ -43,7 +42,6 @@ const useStyles = makeStyles()(theme => ({
const ProviderDetailPage: React.FunctionComponent<Props> = ({ owner, _provider }) => {
const [provider, setProvider] = useState<Partial<ClientProviderDetailWithStatus>>(_provider);
const { classes } = useStyles();
const router = useRouter();
const theme = useTheme();
const { address } = useWallet();
const { isLoading: isLoadingProvider, refetch: getProviderDetail } = useProviderDetail(owner, {
Expand All @@ -60,7 +58,7 @@ const ProviderDetailPage: React.FunctionComponent<Props> = ({ owner, _provider }
isLoading: isLoadingStatus,
refetch: getProviderStatus
} = useProviderStatus(provider?.hostUri, {
enabled: false,
enabled: true,
retry: false,
onSuccess: _providerStatus => {
setProvider(provider => (provider ? { ...provider, ..._providerStatus } : _providerStatus));
Expand All @@ -74,12 +72,6 @@ const ProviderDetailPage: React.FunctionComponent<Props> = ({ owner, _provider }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (provider && !providerStatus) {
getProviderStatus();
}
}, [provider, providerStatus]);

useEffect(() => {
if (leases) {
const numberOfDeployments = leases?.filter(d => d.provider === owner).length || 0;
Expand Down Expand Up @@ -251,4 +243,3 @@ export async function getServerSideProps({ params, query }) {
}
};
}

1 change: 1 addition & 0 deletions deploy-web/src/queries/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class QueryKeys {
static getLeasesKey = (address: string, dseq: string) => ["LEASE_LIST", address, dseq];
static getLeaseStatusKey = (dseq: string, gseq: number, oseq: number) => ["LEASE_STATUS", dseq, gseq, oseq];
static getBidListKey = (address: string, dseq: string) => ["BID_LIST", address, dseq];
static getBidInfoKey = (address: string, dseq: string, gseq: number, oseq: number, provider: string) => ["BID_INFO", address, dseq, gseq, oseq, provider];
static getProvidersKey = () => ["PROVIDERS"];
static getProviderListKey = () => ["PROVIDER_LIST"];
static getProviderRegionsKey = () => ["PROVIDER_REGIONS"];
Expand Down
17 changes: 17 additions & 0 deletions deploy-web/src/queries/useBidQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,20 @@ export function useBidList(address: string, dseq: string, options) {
const { settings } = useSettings();
return useQuery(QueryKeys.getBidListKey(address, dseq), () => getBidList(settings.apiEndpoint, address, dseq), options);
}

async function getBidInfo(apiEndpoint: string, address: string, dseq: string, gseq: number, oseq: number, provider: string): Promise<RpcBid> {
if (!address || !dseq || !gseq || !oseq || !provider) return null;

const response = await axios.get(ApiUrlService.bidInfo(apiEndpoint, address, dseq, gseq, oseq, provider));

return response.data;
}

export function useBidInfo(address: string, dseq: string, gseq: number, oseq: number, provider: string, options = {}) {
const { settings } = useSettings();
return useQuery(
QueryKeys.getBidInfoKey(address, dseq, gseq, oseq, provider),
() => getBidInfo(settings.apiEndpoint, address, dseq, gseq, oseq, provider),
options
);
}
3 changes: 3 additions & 0 deletions deploy-web/src/utils/apiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export class ApiUrlService {
static bidList(apiEndpoint: string, address: string, dseq: string) {
return `${apiEndpoint}/akash/market/${networkVersionMarket}/bids/list?filters.owner=${address}&filters.dseq=${dseq}`;
}
static bidInfo(apiEndpoint: string, address: string, dseq: string, gseq: number, oseq: number, provider: string) {
return `${apiEndpoint}/akash/market/${networkVersionMarket}/bids/info?id.owner=${address}&id.dseq=${dseq}&id.gseq=${gseq}&id.oseq=${oseq}&id.provider=${provider}`;
}
static leaseList(apiEndpoint: string, address: string, dseq: string) {
return `${apiEndpoint}/akash/market/${networkVersionMarket}/leases/list?filters.owner=${address}${dseq ? "&filters.dseq=" + dseq : ""}`;
}
Expand Down
11 changes: 11 additions & 0 deletions deploy-web/src/utils/deploymentUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,14 @@ export function validateDeploymentData(deploymentData, selectedTemplate?) {
}
}
}

export function getGpusFromAttributes(attributes: { key: string; value: string }[]) {
return attributes
.filter(attr => attr.key.startsWith("vendor/") && attr.value === "true")
.map(attr => {
const modelKey = attr.key.split("/");

// vendor/nvidia/model/h100 -> nvidia,h100
return { vendor: modelKey[1], model: modelKey[3] };
});
}

0 comments on commit 78b3f93

Please sign in to comment.