| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import {
- DocumentTitle,
- K8sResourceCommon,
- k8sPatch,
- useK8sModel,
- useK8sWatchResource,
- } from '@openshift-console/dynamic-plugin-sdk';
- import {
- Alert,
- Card,
- CardBody,
- CardTitle,
- PageSection,
- Spinner,
- Switch,
- Title,
- } from '@patternfly/react-core';
- import type { FC } from 'react';
- import { useState } from 'react';
- const TUNED_NAMESPACE = 'openshift-cluster-node-tuning-operator';
- const TUNED_NAME = 'custom-tuned-profile';
- const POWERSAVE_PROFILE = 'homelab-powersave';
- const PERFORMANCE_PROFILE = 'homelab-performance';
- const TunedGVK = {
- group: 'tuned.openshift.io',
- version: 'v1',
- kind: 'Tuned',
- };
- interface TunedResource extends K8sResourceCommon {
- spec?: {
- recommend?: Array<{
- profile?: string;
- [key: string]: unknown;
- }>;
- };
- }
- const DashboardPage: FC = () => {
- const [patching, setPatching] = useState(false);
- const [patchError, setPatchError] = useState<string>();
- const [tunedModel, modelLoading] = useK8sModel(TunedGVK);
- const [tuned, loaded, loadError] =
- useK8sWatchResource<TunedResource>({
- groupVersionKind: TunedGVK,
- name: TUNED_NAME,
- namespace: TUNED_NAMESPACE,
- });
- const recommendations = tuned?.spec?.recommend ?? [];
- const profileIndex = recommendations.findIndex(
- (recommendation) =>
- recommendation.profile === POWERSAVE_PROFILE ||
- recommendation.profile === PERFORMANCE_PROFILE,
- );
- const currentProfile =
- profileIndex >= 0
- ? recommendations[profileIndex]?.profile
- : undefined;
- const performanceEnabled =
- currentProfile === PERFORMANCE_PROFILE;
- const profileKnown =
- currentProfile === POWERSAVE_PROFILE ||
- currentProfile === PERFORMANCE_PROFILE;
- const changePerformanceMode = async (enabled: boolean) => {
- if (!tunedModel || !tuned || profileIndex < 0) {
- return;
- }
- setPatching(true);
- setPatchError(undefined);
- try {
- await k8sPatch({
- model: tunedModel,
- resource: tuned,
- data: [
- {
- op: 'replace',
- path: `/spec/recommend/${profileIndex}/profile`,
- value: enabled
- ? PERFORMANCE_PROFILE
- : POWERSAVE_PROFILE,
- },
- ],
- });
- } catch (error) {
- setPatchError(
- error instanceof Error
- ? error.message
- : String(error),
- );
- } finally {
- setPatching(false);
- }
- };
- return (
- <>
- <DocumentTitle>Dashboard</DocumentTitle>
- <PageSection>
- <Title headingLevel="h1" size="2xl">
- Homelab Dashboard
- </Title>
- </PageSection>
- <PageSection>
- <Card>
- <CardTitle>Cluster performance</CardTitle>
- <CardBody>
- {!loaded || modelLoading ? (
- <Spinner />
- ) : loadError ? (
- <Alert
- isInline
- variant="danger"
- title="Unable to read TuneD configuration"
- >
- {String(loadError)}
- </Alert>
- ) : (
- <>
- <Switch
- id="cluster-performance-mode"
- label="Performance mode"
- isChecked={performanceEnabled}
- isDisabled={patching || !profileKnown}
- onChange={(_, checked) =>
- void changePerformanceMode(checked)
- }
- /><br />
- <p>
- Current profile:{' '}
- <strong>
- {currentProfile ?? 'Unknown'}
- </strong>
- </p>
- {patching && <Spinner size="md" />}
- {!profileKnown && (
- <Alert
- isInline
- variant="warning"
- title="Unknown TuneD profile"
- >
- Expected {POWERSAVE_PROFILE} or{' '}
- {PERFORMANCE_PROFILE}.
- </Alert>
- )}
- {patchError && (
- <Alert
- isInline
- variant="danger"
- title="Unable to change performance mode"
- >
- {patchError}
- </Alert>
- )}
- </>
- )}
- </CardBody>
- </Card>
- </PageSection>
- </>
- );
- };
- export default DashboardPage;
|