Skip to content

Commit

Permalink
feat: add banner for promoting GPU enabled machine (#1717)
Browse files Browse the repository at this point in the history
* feat: add banner for promoting GPU enabled machine

Fixes #1582

Signed-off-by: Jeff MAURY <[email protected]>
  • Loading branch information
jeffmaury committed Sep 16, 2024
1 parent 2b7d7e3 commit c1f0add
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ import { VMType } from '@shared/src/models/IPodman';
vi.mock('../../utils/client', async () => ({
studioClient: {
checkContainerConnectionStatusAndResources: vi.fn(),
getExtensionConfiguration: vi.fn(),
},
rpcBrowser: {
subscribe: (): unknown => {
return {
unsubscribe: (): void => {},
};
},
},
}));

Expand All @@ -55,6 +63,13 @@ beforeEach(() => {
canRedirect: false,
status: 'running',
});
vi.mocked(studioClient.getExtensionConfiguration).mockResolvedValue({
experimentalGPU: false,
apiPort: 0,
experimentalTuning: false,
modelsPath: '',
modelUploadDisabled: false,
});
});

test('model without memory should not check for status', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ import type {
import type { ModelCheckerContext, ModelInfo } from '@shared/src/models/IModelInfo';
import ContainerConnectionStatusInfo from './ContainerConnectionStatusInfo.svelte';
import { studioClient } from '/@/utils/client';
import { configuration } from '/@/stores/extensionConfiguration';
import { fromStore } from 'svelte/store';
import GPUEnabledMachine from '/@/lib/notification/GPUEnabledMachine.svelte';
import { VMType } from '@shared/src/models/IPodman';
export let containerProviderConnection: ContainerProviderConnectionInfo | undefined = undefined;
export let model: ModelInfo | undefined = undefined;
export let checkContext: ModelCheckerContext = 'inference';
let connectionInfo: ContainerConnectionInfo | undefined;
let gpuWarningRequired = false;
function shouldRecommendGPU(connection: ContainerProviderConnectionInfo): boolean {
return connection.vmType === VMType.APPLEHV || connection.vmType === VMType.APPLEHV_LABEL;
}
$: if (typeof model?.memory === 'number' && containerProviderConnection) {
studioClient
.checkContainerConnectionStatusAndResources({
Expand All @@ -26,11 +35,17 @@ $: if (typeof model?.memory === 'number' && containerProviderConnection) {
connectionInfo = undefined;
console.error(err);
});
if (fromStore(configuration)?.current?.experimentalGPU && shouldRecommendGPU(containerProviderConnection)) {
gpuWarningRequired = true;
}
} else {
connectionInfo = undefined;
}
</script>

{#if gpuWarningRequired}
<GPUEnabledMachine />
{/if}
{#if connectionInfo}
<ContainerConnectionStatusInfo connectionInfo={connectionInfo} />
{/if}
54 changes: 54 additions & 0 deletions packages/frontend/src/lib/notification/GPUEnabledMachine.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**********************************************************************
* Copyright (C) 2024 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/

import '@testing-library/jest-dom/vitest';
import { beforeEach, expect, test, vi } from 'vitest';
import { render, screen } from '@testing-library/svelte';
import { studioClient } from '/@/utils/client';
import GPUEnabledMachine from '/@/lib/notification/GPUEnabledMachine.svelte';

vi.mock('/@/utils/client', async () => {
return {
studioClient: {
navigateToResources: vi.fn(),
},
};
});

beforeEach(() => {
vi.resetAllMocks();
vi.mocked(studioClient.navigateToResources).mockResolvedValue(undefined);
});

test('should show navigation to resources', async () => {
render(GPUEnabledMachine);

const banner = screen.getByLabelText('GPU machine banner');
expect(banner).toBeInTheDocument();
const titleDiv = screen.getByLabelText('title');
expect(titleDiv).toBeInTheDocument();
expect(titleDiv.textContent).equals('Non GPU enabled machine');
const descriptionDiv = screen.getByLabelText('description');
expect(descriptionDiv).toBeInTheDocument();
expect(descriptionDiv.textContent).equals(
`The selected Podman machine is not GPU enabled. On MacOS, you can run GPU workloads using the krunkit\n environment. Do you want to create a GPU enabled machine ?`,
);

const btnUpdate = screen.queryByRole('button', { name: 'Create GPU enabled machine' });
expect(btnUpdate).toBeInTheDocument();
});
31 changes: 31 additions & 0 deletions packages/frontend/src/lib/notification/GPUEnabledMachine.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import Fa from 'svelte-fa';
import { faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
import { Button } from '@podman-desktop/ui-svelte';
import { studioClient } from '/@/utils/client';
const actionName = 'Create GPU enabled machine';
function executeCommand(): void {
studioClient.navigateToResources().catch(err => console.error('Error navigating to resources', err));
}
</script>

<div
class="w-full bg-[var(--pd-content-card-bg)] text-[var(--pd-content-card-text)] border-t-[3px] border-amber-500 p-4 mt-5 shadow-inner"
aria-label="GPU machine banner">
<div class="flex flex-row space-x-3">
<div class="flex">
<Fa icon={faTriangleExclamation} class="text-amber-400" />
</div>
<div class="flex flex-col grow">
<span class="font-medium" aria-label="title">Non GPU enabled machine</span>
<span aria-label="description"
>The selected Podman machine is not GPU enabled. On MacOS, you can run GPU workloads using the krunkit
environment. Do you want to create a GPU enabled machine ?</span>
</div>
<div class="flex items-center">
<Button class="grow text-gray-500" on:click={executeCommand} aria-label={actionName}>{actionName}</Button>
</div>
</div>
</div>
15 changes: 15 additions & 0 deletions packages/frontend/src/pages/CreateService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ vi.mock('../utils/client', async () => ({
requestCreateInferenceServer: vi.fn(),
getHostFreePort: vi.fn(),
checkContainerConnectionStatusAndResources: vi.fn(),
getExtensionConfiguration: vi.fn(),
},
rpcBrowser: {
subscribe: (): unknown => {
return {
unsubscribe: (): void => {},
};
},
},
}));

Expand Down Expand Up @@ -140,6 +148,13 @@ beforeEach(() => {
mocks.getInferenceServersMock.mockReturnValue([
{ container: { containerId: 'dummyContainerId' } } as InferenceServer,
]);
vi.mocked(studioClient.getExtensionConfiguration).mockResolvedValue({
experimentalGPU: false,
apiPort: 0,
experimentalTuning: false,
modelsPath: '',
modelUploadDisabled: false,
});

window.HTMLElement.prototype.scrollIntoView = vi.fn();
});
Expand Down

0 comments on commit c1f0add

Please sign in to comment.