fix: container name in add worker

This commit is contained in:
jialin
2025-12-17 14:59:07 +08:00
parent 6968f9fa6b
commit bd46fcdc75
22 changed files with 332 additions and 207 deletions
@@ -7,6 +7,8 @@ type ViewModalProps = {
workerIP?: string;
modelDir?: string;
cacheDir?: string;
containerName?: string;
gpustackDataVolume?: string;
registrationInfo: {
token: string;
image: string;
@@ -19,7 +21,9 @@ const AddWorkerCommand: React.FC<ViewModalProps> = ({
workerIP,
modelDir,
cacheDir,
currentGPU
currentGPU,
containerName,
gpustackDataVolume
}) => {
const code = React.useMemo(() => {
const commandCode = addWorkerGuide['all'];
@@ -31,13 +35,23 @@ const AddWorkerCommand: React.FC<ViewModalProps> = ({
workerIP: workerIP,
modelDir: modelDir,
cacheDir: cacheDir,
containerName: containerName,
gpustackDataVolume: gpustackDataVolume,
image: registrationInfo.image,
token: registrationInfo.token || '${token}'
})
?.trim()
.replace(/\s+$/gm, '')
.replace(/\\+$/, '');
}, [registrationInfo, currentGPU, workerIP, modelDir, cacheDir]);
}, [
registrationInfo,
currentGPU,
workerIP,
modelDir,
cacheDir,
containerName,
gpustackDataVolume
]);
return (
<HighlightCode
@@ -51,6 +51,14 @@ export interface SummaryDataKeys {
ip: string;
required: boolean;
};
containerNameConfig: {
enabled: boolean;
name: string;
};
gpustackDataVolumeConfig: {
enabled: boolean;
path: string;
};
}
export type SummaryDataMap = {
@@ -25,6 +25,15 @@ const DockerRunCommand = () => {
enable: false,
path: ''
};
const containerNameConfig = summary.get('containerNameConfig') || {
enable: false,
name: ''
};
const gpustackDataVolumeConfig = summary.get('gpustackDataVolumeConfig') || {
enable: false,
path: ''
};
const currentGPU = summary.get('currentGPU') || '';
const stepIndex = stepList.indexOf(StepNamesMap.RunCommand) + 1;
@@ -56,6 +65,12 @@ const DockerRunCommand = () => {
workerIP={workerIPConfig.enable ? workerIPConfig.ip : ''}
modelDir={modelDirConfig.enable ? modelDirConfig.path : ''}
cacheDir={cacheDirConfig.enable ? cacheDirConfig.path : ''}
containerName={
containerNameConfig.enable ? containerNameConfig.name : ''
}
gpustackDataVolume={
gpustackDataVolumeConfig.enable ? gpustackDataVolumeConfig.path : ''
}
currentGPU={currentGPU}
/>
</StepCollapse>
@@ -96,6 +96,16 @@ const SpecifyArguments = () => {
path: ''
};
const containerNameConfig = summary.get('containerNameConfig') || {
enable: false,
name: ''
};
const gpustackDataVolumeConfig = summary.get('gpustackDataVolumeConfig') || {
enable: false,
path: ''
};
const setWorkerIPConfig = (config: {
enable: boolean;
ip?: string;
@@ -138,10 +148,16 @@ const SpecifyArguments = () => {
const unregisterWorkerIP = registerField('workerIPConfig');
const unregisterModelDir = registerField('modelDirConfig');
const unregisterCacheDir = registerField('cacheDirConfig');
const unregisterContainerName = registerField('containerNameConfig');
const unregisterGpustackDataVolume = registerField(
'gpustackDataVolumeConfig'
);
return () => {
unregisterWorkerIP();
unregisterModelDir();
unregisterCacheDir();
unregisterContainerName();
unregisterGpustackDataVolume();
};
}, []);
@@ -161,6 +177,16 @@ const SpecifyArguments = () => {
enable: false,
path: ''
});
updateField('containerNameConfig', {
enable: false,
name: ''
});
updateField('gpustackDataVolumeConfig', {
enable: false,
path: ''
});
}, []);
return (
@@ -246,6 +272,60 @@ const SpecifyArguments = () => {
)
}
></SwitchSetting>
{/* container name config */}
<SwitchSetting
label={intl.formatMessage({ id: 'clusters.addworker.containerName' })}
tips={intl.formatMessage({
id: 'clusters.addworker.containerName.tips'
})}
placeholder={intl.formatMessage(
{
id: 'common.help.default'
},
{ content: 'gpustack-worker' }
)}
checked={containerNameConfig.enable}
value={containerNameConfig.name}
onChange={(checked) =>
updateField('containerNameConfig', {
...containerNameConfig,
enable: checked
})
}
onInputChange={(value) =>
updateField('containerNameConfig', {
...containerNameConfig,
name: value
})
}
></SwitchSetting>
{/* gpustack data volume config */}
<SwitchSetting
label={intl.formatMessage({ id: 'clusters.addworker.dataVolume' })}
tips={intl.formatMessage({
id: 'clusters.addworker.dataVolume.tips'
})}
placeholder={intl.formatMessage(
{
id: 'common.help.default'
},
{ content: 'gpustack-data' }
)}
checked={gpustackDataVolumeConfig.enable}
value={gpustackDataVolumeConfig.path}
onChange={(checked) =>
updateField('gpustackDataVolumeConfig', {
...gpustackDataVolumeConfig,
enable: checked
})
}
onInputChange={(value) =>
updateField('gpustackDataVolumeConfig', {
...gpustackDataVolumeConfig,
path: value
})
}
></SwitchSetting>
{/* model directory config */}
<SwitchSetting
label={intl.formatMessage({ id: 'clusters.addworker.extraVolume' })}
@@ -5,10 +5,77 @@ import {
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import React from 'react';
import styled from 'styled-components';
import { useAddWorkerContext } from './add-worker-context';
import { StepNamesMap } from './config';
import { ConfigWrapper, Title } from './constainers';
interface DataItemProps {
enable: boolean;
value: string;
required?: boolean;
label: string;
tips?: string;
}
const DataItemWrapper = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
.label {
color: var(--ant-color-text);
}
.value {
display: flex;
align-items: center;
}
`;
const DataItem: React.FC<DataItemProps> = ({
enable,
value,
required,
label,
tips
}) => {
return (
<DataItemWrapper>
<span className="label">{label}:</span>
<span className="value">
<span>{enable && value ? value : ''}</span>
{tips}
{(!value || !enable) && !required && (
<StopOutlined
style={{
color: 'var(--ant-color-text-tertiary)'
}}
/>
)}
{((enable && value) || (required && !enable)) && (
<CheckCircleOutlined
style={{
color: 'var(--ant-color-success)',
marginLeft: 4
}}
/>
)}
{enable && !value && required && (
<>
<WarningOutlined
style={{
color: 'var(--ant-color-warning)',
marginLeft: 4
}}
/>
</>
)}
</span>
</DataItemWrapper>
);
};
const SummaryData: React.FC = () => {
const intl = useIntl();
const { summary, stepList } = useAddWorkerContext();
@@ -32,6 +99,16 @@ const SummaryData: React.FC = () => {
path: ''
};
const containerNameConfig = summary.get('containerNameConfig') || {
enable: false,
name: ''
};
const gpustackDataVolumeConfig = summary.get('gpustackDataVolumeConfig') || {
enable: false,
path: ''
};
return (
<ConfigWrapper>
<Title>
@@ -39,127 +116,56 @@ const SummaryData: React.FC = () => {
</Title>
<div className="config-content">
{stepList.includes(StepNamesMap.SelectCluster) && (
<div className="item">
<span className="label">
{intl.formatMessage({ id: 'clusters.title' })}:
</span>
<span className="value">
{clusterName}
{clusterName ? (
<CheckCircleOutlined
style={{
color: 'var(--ant-color-success)',
marginLeft: 4
}}
/>
) : (
<WarningOutlined
style={{
color: 'var(--ant-color-warning)',
marginLeft: 4
}}
/>
)}
</span>
</div>
<DataItem
value={clusterName}
enable={true}
label={intl.formatMessage({ id: 'clusters.title' })}
></DataItem>
)}
<div className="item">
<span className="label">
{intl.formatMessage({ id: 'clusters.addworker.gpuVendor' })}:
</span>
<span className="value">
{/* for checked style */}
{workerCommand.label}
<CheckCircleOutlined
style={{
color: 'var(--ant-color-success)',
marginLeft: 4
}}
/>
</span>
</div>
<div className="item">
<span className="label">
{intl.formatMessage({ id: 'clusters.addworker.workerIP' })}:
</span>
<span className="value">
{/* for invalidate style */}
{workerIPConfig.enable
<DataItem
label={intl.formatMessage({ id: 'clusters.addworker.gpuVendor' })}
enable={true}
value={workerCommand.label}
></DataItem>
<DataItem
label={intl.formatMessage({ id: 'clusters.addworker.workerIP' })}
tips={
workerIPConfig.enable
? workerIPConfig.ip
? workerIPConfig.ip
: intl.formatMessage({ id: 'clusters.addworker.notSpecified' })
: intl.formatMessage({ id: 'clusters.addworker.autoDetect' })}
: intl.formatMessage({ id: 'clusters.addworker.autoDetect' })
}
enable={workerIPConfig.enable}
value={workerIPConfig.ip}
required={true}
></DataItem>
{workerIPConfig.enable && !workerIPConfig.ip && (
<WarningOutlined
style={{
color: 'var(--ant-color-warning)',
marginLeft: 4
}}
/>
)}
{(!workerIPConfig.enable || workerIPConfig.ip) && (
<CheckCircleOutlined
style={{
color: 'var(--ant-color-success)',
marginLeft: 4
}}
/>
)}
</span>
</div>
<div className="item">
<span className="label">
{intl.formatMessage({ id: 'clusters.addworker.extraVolume' })}:
</span>
<span className="value">
{modelDirConfig.enable && modelDirConfig.path
? modelDirConfig.path
: ''}
{(!modelDirConfig.path || !modelDirConfig.enable) && (
<StopOutlined
style={{
color: 'var(--ant-color-text-tertiary)'
}}
/>
)}
<DataItem
label={intl.formatMessage({ id: 'clusters.addworker.containerName' })}
enable={containerNameConfig.enable}
value={containerNameConfig.name}
></DataItem>
{modelDirConfig.enable && modelDirConfig.path && (
<CheckCircleOutlined
style={{
color: 'var(--ant-color-success)',
marginLeft: 4
}}
/>
)}
</span>
</div>
<div className="item">
<span className="label">
{intl.formatMessage({ id: 'clusters.addworker.cacheVolume' })}:
</span>
<span className="value">
{cacheDirConfig.enable && cacheDirConfig.path
? cacheDirConfig.path
: ''}
{(!cacheDirConfig.path || !cacheDirConfig.enable) && (
<StopOutlined
style={{
color: 'var(--ant-color-text-tertiary)'
}}
/>
)}
<DataItem
label={intl.formatMessage({ id: 'clusters.addworker.dataVolume' })}
enable={gpustackDataVolumeConfig.enable}
value={gpustackDataVolumeConfig.path}
></DataItem>
{cacheDirConfig.enable && cacheDirConfig.path && (
<CheckCircleOutlined
style={{
color: 'var(--ant-color-success)',
marginLeft: 4
}}
/>
)}
</span>
</div>
<DataItem
label={intl.formatMessage({ id: 'clusters.addworker.extraVolume' })}
enable={modelDirConfig.enable}
value={modelDirConfig.path}
></DataItem>
<DataItem
label={intl.formatMessage({ id: 'clusters.addworker.cacheVolume' })}
enable={cacheDirConfig.enable}
value={cacheDirConfig.path}
></DataItem>
</div>
</ConfigWrapper>
);
+1
View File
@@ -184,6 +184,7 @@ export interface CatalogItem {
name: string;
id: number;
description: string;
deployment_notes?: string;
home: string;
icon: string;
categories: string[];
+10 -5
View File
@@ -271,15 +271,20 @@ export const useCheckCompatibility = () => {
// current cluster is not available, but other clusters are available
const othersAvailable = !hasClaim && resourceClaimMap.size > 0;
let compatibilityMessage = compatibility_messages.join(' ');
compatibilityMessage = compatibilityMessage.startsWith(
'The model file path you specified does not exist on the GPUStack server'
)
? intl.formatMessage({ id: 'models.form.modelfile.notfound' })
: compatibilityMessage;
let msgData = {
title:
scheduling_messages?.length > 0
? compatibility_messages?.join(' ')
: '',
title: scheduling_messages?.length > 0 ? compatibilityMessage : '',
message:
scheduling_messages?.length > 0
? scheduling_messages
: compatibility_messages?.join(' ')
: compatibilityMessage
};
if (hasClaim) {
+1
View File
@@ -29,6 +29,7 @@ export const logout = async (userInfo?: any) => {
});
clearStorageUserSettings();
clearAtomStorage(userAtom);
if (res?.logout_url) {
window.location.href = res.logout_url;
}
+25 -67
View File
@@ -129,15 +129,28 @@ export const dockerEnvCommandMap = {
GPUsConfigs[GPUDriverMap.METAX]
)
};
interface AddWorkerCommandParams {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
containerName?: string;
gpustackDataVolume?: string;
cacheDir?: string;
}
const setNormalArgs = (params: any) => {
return `CONTAINER_NAME="gpustack-worker"
sudo docker run -d --name "\${CONTAINER_NAME}" \\
-e "GPUSTACK_RUNTIME_DEPLOY_MIRRORED_NAME=\${CONTAINER_NAME}" \\
return `sudo docker run -d --name ${params.containerName || 'gpustack-worker'} \\
-e "GPUSTACK_RUNTIME_DEPLOY_MIRRORED_NAME=${params.containerName || 'gpustack-worker'}" \\
--restart=unless-stopped \\
--privileged \\
--network=host \\
--volume /var/run/docker.sock:/var/run/docker.sock \\
--volume gpustack-data:/var/lib/gpustack \\
--volume ${params.gpustackDataVolume || 'gpustack-data'}:/var/lib/gpustack \\
${params.modelDir ? `--volume ${params.modelDir}:${params.modelDir} \\` : ''}
${params.cacheDir ? `--volume ${params.cacheDir}:/var/lib/gpustack/cache \\` : ''}`;
};
@@ -149,18 +162,11 @@ const setImageArgs = (params: any) => {
};
// avaliable for NVIDIA、MThreads
const registerWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);
// remove empty enter lines and trailing backslash
return `${commonArgs}
--runtime ${config.runtime} \\
@@ -169,15 +175,7 @@ const registerWorker = (params: {
};
// avaliable for AMD
const registerAMDWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerAMDWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);
@@ -190,15 +188,7 @@ const registerAMDWorker = (params: {
};
// avaliable for Ascend
const registerAscendWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerAscendWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);
@@ -209,15 +199,7 @@ const registerAscendWorker = (params: {
${params.workerIP ? `--advertise-address ${params.workerIP} \\` : ''}`;
};
const registerHygonWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerHygonWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);
@@ -230,15 +212,7 @@ const registerHygonWorker = (params: {
${params.workerIP ? `--advertise-address ${params.workerIP} \\` : ''}`;
};
const registerIluvatarWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerIluvatarWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);
@@ -251,15 +225,7 @@ const registerIluvatarWorker = (params: {
${params.workerIP ? `--advertise-address ${params.workerIP} \\` : ''}`;
};
const registerMetaXWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerMetaXWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);
@@ -270,15 +236,7 @@ const registerMetaXWorker = (params: {
${params.workerIP ? `--advertise-address ${params.workerIP} \\` : ''}`;
};
const registerCambriconWorker = (params: {
server: string;
tag: string;
token: string;
image: string;
gpu: string;
workerIP?: string;
modelDir?: string;
}) => {
const registerCambriconWorker = (params: AddWorkerCommandParams) => {
const config = GPUsConfigs[params.gpu];
const commonArgs = setNormalArgs(params);
const imageArgs = setImageArgs(params);