fix: update add worker command

This commit is contained in:
jialin
2025-12-10 15:50:53 +08:00
parent d8452e98f5
commit 7fdabd90a5
15 changed files with 56 additions and 48 deletions
+1 -2
View File
@@ -45,8 +45,7 @@ const NO_CONTAINER_PAGES = [
'image', 'image',
'text2images', 'text2images',
'clusterDetail', 'clusterDetail',
'clusterCreate', 'clusterCreate'
'workers'
]; ];
const loginPath = DEFAULT_ENTER_PAGE.login; const loginPath = DEFAULT_ENTER_PAGE.login;
+1 -1
View File
@@ -75,7 +75,7 @@ Same applies to the <span class="bold-text">/opt/dtk</span> directory.`,
'clusters.addworker.extraVolume': 'Additional Volume Mount', 'clusters.addworker.extraVolume': 'Additional Volume Mount',
'clusters.addworker.cacheVolume': 'Model Cache Volume Mount', 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount',
'clusters.addworker.cacheVolume.tips': 'clusters.addworker.cacheVolume.tips':
'If you want to custom the model cache directory, you can specify the path to mount it.', 'If you want to customize the model cache directory, you can specify the path to mount it.',
'clusters.addworker.configSummary': 'Configuration Summary', 'clusters.addworker.configSummary': 'Configuration Summary',
'clusters.addworker.gpuVendor': 'GPU Vendor', 'clusters.addworker.gpuVendor': 'GPU Vendor',
'clusters.addworker.workerIP': 'Worker IP', 'clusters.addworker.workerIP': 'Worker IP',
+2 -2
View File
@@ -75,7 +75,7 @@ Same applies to the <span class="bold-text">/opt/dtk</span> directory.`,
'clusters.addworker.extraVolume': 'Additional Volume Mount', 'clusters.addworker.extraVolume': 'Additional Volume Mount',
'clusters.addworker.cacheVolume': 'Model Cache Volume Mount', 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount',
'clusters.addworker.cacheVolume.tips': 'clusters.addworker.cacheVolume.tips':
'If you want to custom the model cache directory, you can specify the path to mount it.', 'If you want to customize the model cache directory, you can specify the path to mount it.',
'clusters.addworker.configSummary': 'Configuration Summary', 'clusters.addworker.configSummary': 'Configuration Summary',
'clusters.addworker.gpuVendor': 'GPU Vendor', 'clusters.addworker.gpuVendor': 'GPU Vendor',
'clusters.addworker.workerIP': 'Worker IP', 'clusters.addworker.workerIP': 'Worker IP',
@@ -163,6 +163,6 @@ Same applies to the <span class="bold-text">/opt/dtk</span> directory.`,
// 69. 'clusters.button.genToken': 'Need to create a new token? Click <a href="{link}" target="_blank">here</a>.', // 69. 'clusters.button.genToken': 'Need to create a new token? Click <a href="{link}" target="_blank">here</a>.',
// 70. 'clusters.addworker.amdNotes-01': `If the <span class="bold-text">/opt/rocm</span> directory does not exist, please create a symbolic link pointing to the ROCm installed path: <span class="bold-text">ln -s /path/to/rocm /opt/rocm</span>.`, // 70. 'clusters.addworker.amdNotes-01': `If the <span class="bold-text">/opt/rocm</span> directory does not exist, please create a symbolic link pointing to the ROCm installed path: <span class="bold-text">ln -s /path/to/rocm /opt/rocm</span>.`,
// 71. 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount', // 71. 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount',
// 72. 'clusters.addworker.cacheVolume.tips': 'If you want to custom the model cache directory, you can specify the path to mount it.', // 72. 'clusters.addworker.cacheVolume.tips': 'If you want to customize the model cache directory, you can specify the path to mount it.',
// 73. 'clusters.addworker.cacheVolume.holder': 'e.g. /data/cache (path must start with /)', // 73. 'clusters.addworker.cacheVolume.holder': 'e.g. /data/cache (path must start with /)',
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+2 -2
View File
@@ -75,7 +75,7 @@ export default {
'clusters.addworker.extraVolume': 'Дополнительное монтирование тома', 'clusters.addworker.extraVolume': 'Дополнительное монтирование тома',
'clusters.addworker.cacheVolume': 'Model Cache Volume Mount', 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount',
'clusters.addworker.cacheVolume.tips': 'clusters.addworker.cacheVolume.tips':
'If you want to custom the model cache directory, you can specify the path to mount it.', 'If you want to customize the model cache directory, you can specify the path to mount it.',
'clusters.addworker.configSummary': 'Сводка конфигурации', 'clusters.addworker.configSummary': 'Сводка конфигурации',
'clusters.addworker.gpuVendor': 'Производитель GPU', 'clusters.addworker.gpuVendor': 'Производитель GPU',
'clusters.addworker.workerIP': 'IP воркера', 'clusters.addworker.workerIP': 'IP воркера',
@@ -95,5 +95,5 @@ export default {
// 1. 'clusters.addworker.amdNotes-01': `If the <span class="bold-text">/opt/rocm</span> directory does not exist, please create a symbolic link pointing to the ROCm installed path: <span class="bold-text">ln -s /path/to/rocm /opt/rocm</span>.`, // 1. 'clusters.addworker.amdNotes-01': `If the <span class="bold-text">/opt/rocm</span> directory does not exist, please create a symbolic link pointing to the ROCm installed path: <span class="bold-text">ln -s /path/to/rocm /opt/rocm</span>.`,
// 2. 'clusters.button.genToken': 'Need to create a new token? Click <a href="{link}" target="_blank">here</a>.', // 2. 'clusters.button.genToken': 'Need to create a new token? Click <a href="{link}" target="_blank">here</a>.',
// 3. 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount', // 3. 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount',
// 4. 'clusters.addworker.cacheVolume.tips': 'If you want to custom the model cache directory, you can specify the path to mount it.', // 4. 'clusters.addworker.cacheVolume.tips': 'If you want to customize the model cache directory, you can specify the path to mount it.',
// ================================================================ // ================================================================
@@ -5,6 +5,7 @@ import { SummaryDataKey } from './config';
interface AddWorkerContextProps { interface AddWorkerContextProps {
clusterList?: Global.BaseOption<number, ClusterListItem>[]; clusterList?: Global.BaseOption<number, ClusterListItem>[];
clusterLoading?: boolean;
provider: ProviderType; provider: ProviderType;
stepList: string[]; stepList: string[];
onClusterChange?: (value: number, row?: any) => void; onClusterChange?: (value: number, row?: any) => void;
@@ -30,6 +30,7 @@ const Container = styled.div`
type AddWorkerProps = { type AddWorkerProps = {
provider: ProviderType; provider: ProviderType;
clusterList?: Global.BaseOption<number, ClusterListItem>[]; clusterList?: Global.BaseOption<number, ClusterListItem>[];
clusterLoading?: boolean;
stepList: StepName[]; stepList: StepName[];
onClusterChange?: (value: number, row?: any) => void; onClusterChange?: (value: number, row?: any) => void;
registrationInfo: { registrationInfo: {
@@ -50,6 +51,7 @@ const AddWorkerSteps: React.FC<AddWorkerProps> = (props) => {
registrationInfo, registrationInfo,
provider, provider,
clusterList, clusterList,
clusterLoading,
stepList = [], stepList = [],
onClusterChange onClusterChange
} = props || {}; } = props || {};
@@ -77,6 +79,7 @@ const AddWorkerSteps: React.FC<AddWorkerProps> = (props) => {
<AddWorkerContext.Provider <AddWorkerContext.Provider
value={{ value={{
clusterList, clusterList,
clusterLoading,
provider, provider,
stepList: stepList, stepList: stepList,
collapseKey, collapseKey,
@@ -1,27 +1,17 @@
import ScrollerModal from '@/components/scroller-modal'; import ScrollerModal from '@/components/scroller-modal';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import styled from 'styled-components';
import { queryClusterToken } from '../../apis'; import { queryClusterToken } from '../../apis';
import { ProviderType } from '../../config'; import { ProviderType } from '../../config';
import { ClusterListItem } from '../../config/types'; import { ClusterListItem } from '../../config/types';
import AddWorkerStep from './add-worker-step'; import AddWorkerStep from './add-worker-step';
import { StepName } from './config'; import { StepName } from './config';
const Container = styled.div`
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 16px;
.command-info {
margin-bottom: 8px;
}
`;
type AddWorkerProps = { type AddWorkerProps = {
open: boolean; open: boolean;
provider: ProviderType; provider: ProviderType;
title: string; title: string;
clusterList?: Global.BaseOption<number, ClusterListItem>[]; clusterList?: Global.BaseOption<number, ClusterListItem>[];
clusterLoading?: boolean;
stepList: StepName[]; stepList: StepName[];
onClusterChange?: (value: number, row?: any) => void; onClusterChange?: (value: number, row?: any) => void;
onCancel: () => void; onCancel: () => void;
@@ -47,6 +37,7 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
cluster_id, cluster_id,
title, title,
clusterList, clusterList,
clusterLoading,
stepList = [] stepList = []
} = props || {}; } = props || {};
const firstLoad = React.useRef(true); const firstLoad = React.useRef(true);
@@ -103,6 +94,7 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
stepList={stepList} stepList={stepList}
provider={provider} provider={provider}
clusterList={clusterList} clusterList={clusterList}
clusterLoading={clusterLoading}
onClusterChange={handleOnClusterChange} onClusterChange={handleOnClusterChange}
registrationInfo={registrationInfo} registrationInfo={registrationInfo}
></AddWorkerStep> ></AddWorkerStep>
@@ -1,5 +1,6 @@
import BaseSelect from '@/components/seal-form/base/select'; import BaseSelect from '@/components/seal-form/base/select';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Spin } from 'antd';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useAddWorkerContext } from './add-worker-context'; import { useAddWorkerContext } from './add-worker-context';
import { StepNamesMap } from './config'; import { StepNamesMap } from './config';
@@ -9,6 +10,7 @@ import StepCollapse from './step-collapse';
const SelectCluster = () => { const SelectCluster = () => {
const { const {
clusterList, clusterList,
clusterLoading,
registrationInfo, registrationInfo,
stepList, stepList,
summary, summary,
@@ -55,13 +57,15 @@ const SelectCluster = () => {
</div> </div>
} }
> >
<BaseSelect <Spin spinning={clusterLoading}>
defaultValue={registrationInfo.cluster_id} <BaseSelect
options={clusterList} defaultValue={registrationInfo.cluster_id}
value={clusterId} options={clusterList}
onChange={onClusterChange} value={clusterId}
style={{ width: '100%' }} onChange={onClusterChange}
/> style={{ width: '100%' }}
/>
</Spin>
</StepCollapse> </StepCollapse>
); );
}; };
@@ -43,7 +43,7 @@ const FooterButtons: React.FC<FooterButtonsProps> = (props) => {
)} )}
{showButtons.skip && ( {showButtons.skip && (
<Button type="primary" onClick={handleCancel}> <Button type="primary" onClick={handleCancel}>
{intl.formatMessage({ id: 'clusters.create.skipfornow' })} {intl.formatMessage({ id: 'common.button.done' })}
</Button> </Button>
)} )}
{showButtons.save && ( {showButtons.save && (
@@ -11,10 +11,11 @@ import {
import { ClusterListItem } from '../config/types'; import { ClusterListItem } from '../config/types';
const useAddWorker = (props: { const useAddWorker = (props: {
clusterLoading?: boolean;
clusterList?: Global.BaseOption<number, ClusterListItem>[]; clusterList?: Global.BaseOption<number, ClusterListItem>[];
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const { clusterList } = props || {}; const { clusterList, clusterLoading } = props || {};
const [stepList, setStepList] = useState<StepName[]>([]); const [stepList, setStepList] = useState<StepName[]>([]);
const [openAddWorker, setOpenAddWorker] = useState<{ const [openAddWorker, setOpenAddWorker] = useState<{
open: boolean; open: boolean;
@@ -73,6 +74,7 @@ const useAddWorker = (props: {
open={openAddWorker.open} open={openAddWorker.open}
provider={openAddWorker.provider} provider={openAddWorker.provider}
clusterList={clusterDataList} clusterList={clusterDataList}
clusterLoading={clusterLoading}
cluster_id={openAddWorker.cluster_id} cluster_id={openAddWorker.cluster_id}
onClusterChange={handleClusterChange} onClusterChange={handleClusterChange}
onCancel={() => onCancel={() =>
+2 -2
View File
@@ -56,7 +56,7 @@ export async function queryModelsList(
return request<Global.PageResponse<ListItem>>( return request<Global.PageResponse<ListItem>>(
`${MODELS_API}?${qs.stringify(params)}`, `${MODELS_API}?${qs.stringify(params)}`,
{ {
methos: 'GET', method: 'GET',
...options ...options
} }
); );
@@ -360,7 +360,7 @@ export async function queryCatalogList(
return request<Global.PageResponse<CatalogItem>>( return request<Global.PageResponse<CatalogItem>>(
`/model-sets?${qs.stringify(params)}`, `/model-sets?${qs.stringify(params)}`,
{ {
methos: 'GET', method: 'GET',
...options ...options
} }
); );
+2 -2
View File
@@ -52,14 +52,14 @@ export async function queryWorkersList<T extends Record<string, any>>(
export async function queryGpuDevicesList(params: Global.SearchParams) { export async function queryGpuDevicesList(params: Global.SearchParams) {
return request<Global.PageResponse<GPUDeviceItem>>(`${GPU_DEVICES_API}`, { return request<Global.PageResponse<GPUDeviceItem>>(`${GPU_DEVICES_API}`, {
methos: 'GET', method: 'GET',
params params
}); });
} }
export async function queryGPUDeviceItem(id: string) { export async function queryGPUDeviceItem(id: string) {
return request<GPUDeviceItem>(`${GPU_DEVICES_API}/${id}`, { return request<GPUDeviceItem>(`${GPU_DEVICES_API}/${id}`, {
methos: 'GET' method: 'GET'
}); });
} }
+9 -6
View File
@@ -1,7 +1,7 @@
import DeleteModal from '@/components/delete-modal'; import DeleteModal from '@/components/delete-modal';
import { FilterBar } from '@/components/page-tools'; import { FilterBar } from '@/components/page-tools';
import useTableFetch from '@/hooks/use-table-fetch'; import useTableFetch from '@/hooks/use-table-fetch';
import { PageContainerInner } from '@/pages/_components/page-box'; import PageBox from '@/pages/_components/page-box';
import { queryClusterList } from '@/pages/cluster-management/apis'; import { queryClusterList } from '@/pages/cluster-management/apis';
import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add-worker/config'; import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add-worker/config';
import { import {
@@ -65,9 +65,11 @@ const Workers: React.FC = () => {
}); });
const [clusterData, setClusterData] = useState<{ const [clusterData, setClusterData] = useState<{
list: Global.BaseOption<number, ClusterListItem>[]; list: Global.BaseOption<number, ClusterListItem>[];
loading: boolean;
data: Record<number, string>; data: Record<number, string>;
}>({ }>({
list: [], list: [],
loading: false,
data: {} data: {}
}); });
const [workerDetailStatus, setWorkerDetailStatus] = useState<{ const [workerDetailStatus, setWorkerDetailStatus] = useState<{
@@ -78,7 +80,8 @@ const Workers: React.FC = () => {
currentData: null currentData: null
}); });
const { handleAddWorker, AddWorkerModal, setStepList } = useAddWorker({ const { handleAddWorker, AddWorkerModal, setStepList } = useAddWorker({
clusterList: clusterData.list clusterList: clusterData.list,
clusterLoading: clusterData.loading
}); });
const getClusterList = async () => { const getClusterList = async () => {
@@ -103,11 +106,13 @@ const Workers: React.FC = () => {
})); }));
setClusterData({ setClusterData({
list, list,
loading: false,
data: clusterMap data: clusterMap
}); });
} catch (error) { } catch (error) {
setClusterData({ setClusterData({
list: [], list: [],
loading: false,
data: {} data: {}
}); });
} }
@@ -243,9 +248,7 @@ const Workers: React.FC = () => {
return ( return (
<> <>
<PageContainerInner <PageBox>
footer={terminals.length ? [TerminalPanel] : undefined}
>
<FilterBar <FilterBar
showSelect={true} showSelect={true}
selectHolder={intl.formatMessage({ id: 'clusters.filterBy.cluster' })} selectHolder={intl.formatMessage({ id: 'clusters.filterBy.cluster' })}
@@ -300,7 +303,7 @@ const Workers: React.FC = () => {
/> />
{MaintenanceModal} {MaintenanceModal}
{AddWorkerModal} {AddWorkerModal}
</PageContainerInner> </PageBox>
</> </>
); );
}; };
+14 -10
View File
@@ -81,7 +81,10 @@ const generateNvidiaDockerEnvCommand = (config: {
runtime: string; runtime: string;
driver: string; driver: string;
}) => { }) => {
return `${config.driver} >/dev/null 2>&1 && echo "${config.label} driver OK" || (echo "${config.label} driver issue"; exit 1) && sudo docker info 2>/dev/null | grep -q "${config.runtime}" && echo "${config.label} Container Toolkit OK" || (echo "${config.label} Container Toolkit not configured"; exit 1)`; const runtimeCheck =
config.runtime === 'nvidia' ? 'Runtime.*nvidia' : config.runtime;
return `${config.driver} >/dev/null 2>&1 && echo "${config.label} driver OK" || (echo "${config.label} driver issue"; exit 1) && sudo docker info 2>/dev/null | grep -q "${runtimeCheck}" && echo "${config.label} Container Toolkit OK" || (echo "${config.label} Container Toolkit not configured"; exit 1)`;
}; };
// avaliable for Hygon、Iluvatar、MetaX 、Cambricon // avaliable for Hygon、Iluvatar、MetaX 、Cambricon
@@ -127,15 +130,16 @@ export const dockerEnvCommandMap = {
) )
}; };
const setNormalArgs = (params: any) => { const setNormalArgs = (params: any) => {
console.log('params++++++++++++++', params); return `CONTAINER_NAME="gpustack-worker" \\
return `sudo docker run -d --name gpustack-worker \\ sudo docker run -d --name \${CONTAINER_NAME} \\
--restart=unless-stopped \\ -e GPUSTACK_RUNTIME_DEPLOY_MIRRORED_NAME=\${CONTAINER_NAME} \\
--privileged \\ --restart=unless-stopped \\
--network=host \\ --privileged \\
--volume /var/run/docker.sock:/var/run/docker.sock \\ --network=host \\
--volume gpustack-data:/var/lib/gpustack \\ --volume /var/run/docker.sock:/var/run/docker.sock \\
${params.modelDir ? `--volume ${params.modelDir}:${params.modelDir} \\` : ''} --volume gpustack-data:/var/lib/gpustack \\
${params.cacheDir ? `--volume ${params.cacheDir}:/var/lib/gpustack/cache \\` : ''}`; ${params.modelDir ? `--volume ${params.modelDir}:${params.modelDir} \\` : ''}
${params.cacheDir ? `--volume ${params.cacheDir}:/var/lib/gpustack/cache \\` : ''}`;
}; };
const setImageArgs = (params: any) => { const setImageArgs = (params: any) => {
+1 -1
View File
@@ -5,7 +5,7 @@ export const USERS_API = '/users';
export async function queryUsersList(params: Global.SearchParams) { export async function queryUsersList(params: Global.SearchParams) {
return request<Global.PageResponse<ListItem>>(`${USERS_API}`, { return request<Global.PageResponse<ListItem>>(`${USERS_API}`, {
methos: 'GET', method: 'GET',
params params
}); });
} }