diff --git a/src/assets/logo/thead.png b/src/assets/logo/thead.png new file mode 100644 index 00000000..300b5734 Binary files /dev/null and b/src/assets/logo/thead.png differ diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx index 987b95d8..1b3f42f8 100644 --- a/src/components/icon-font/index.tsx +++ b/src/components/icon-font/index.tsx @@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons'; // import './iconfont/iconfont.js'; const IconFont = createFromIconfontCN({ - scriptUrl: '//at.alicdn.com/t/c/font_4613488_xson4g41d39.js' + scriptUrl: '//at.alicdn.com/t/c/font_4613488_7f4klfqdzm.js' }); export default IconFont; diff --git a/src/locales/en-US/clusters.ts b/src/locales/en-US/clusters.ts index 717ff1b0..f82ceff8 100644 --- a/src/locales/en-US/clusters.ts +++ b/src/locales/en-US/clusters.ts @@ -125,5 +125,9 @@ export default { 'You can also skip this step and add them later from the cluster list.', 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', 'clusters.create.k8sTips2': - 'You can also skip this step and register it later from the cluster list.' + 'You can also skip this step and register it later from the cluster list.', + 'clusters.addworker.theadNotes': + 'If the /usr/local/PPU_SDK directory does not exist, please create a symbolic link pointing to the T-Head installed path: ln -s /path/to/PPU_SDK /usr/local/PPU_SDK.', + 'clusters.addworker.theadNotes-02': + 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the /var/run/cdi directory to be available for CDI generation.' }; diff --git a/src/locales/en-US/vendor.ts b/src/locales/en-US/vendor.ts index a1eede4c..f63a4e21 100644 --- a/src/locales/en-US/vendor.ts +++ b/src/locales/en-US/vendor.ts @@ -5,5 +5,6 @@ export default { 'vendor.moorthreads': 'Moore Threads', 'vendor.iluvatar': 'Iluvatar', 'vendor.metax': 'Metax', - 'vendor.cambricon': 'Cambricon' + 'vendor.cambricon': 'Cambricon', + 'vendor.thead': 'T-Head' }; diff --git a/src/locales/ja-JP/clusters.ts b/src/locales/ja-JP/clusters.ts index 755f3a1c..cdc74550 100644 --- a/src/locales/ja-JP/clusters.ts +++ b/src/locales/ja-JP/clusters.ts @@ -125,7 +125,11 @@ export default { 'You can also skip this step and add them later from the cluster list.', 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', 'clusters.create.k8sTips2': - 'You can also skip this step and register it later from the cluster list.' + 'You can also skip this step and register it later from the cluster list.', + 'clusters.addworker.theadNotes': + 'If the ln -s /path/to/PPU_SDK /usr/local/PPU_SDK', + 'clusters.addworker.theadNotes-02': + 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the /var/run/cdi directory to be available for CDI generation.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -227,4 +231,6 @@ export default { // 92. 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', // 93. 'clusters.create.k8sTips2': 'You can also skip this step and register it later from the cluster list.', // 94. 'clusters.create.steps.configure': 'Configure', +// 99. 'clusters.addworker.theadNotes': 'If the ln -s /path/to/PPU_SDK /usr/local/PPU_SDK', +// 100. 'clusters.addworker.theadNotes-02': 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the /var/run/cdi directory to be available for CDI generation.' // ========== End of To-Do List ========== diff --git a/src/locales/ja-JP/vendor.ts b/src/locales/ja-JP/vendor.ts index a1eede4c..f63a4e21 100644 --- a/src/locales/ja-JP/vendor.ts +++ b/src/locales/ja-JP/vendor.ts @@ -5,5 +5,6 @@ export default { 'vendor.moorthreads': 'Moore Threads', 'vendor.iluvatar': 'Iluvatar', 'vendor.metax': 'Metax', - 'vendor.cambricon': 'Cambricon' + 'vendor.cambricon': 'Cambricon', + 'vendor.thead': 'T-Head' }; diff --git a/src/locales/ru-RU/clusters.ts b/src/locales/ru-RU/clusters.ts index a15c1306..2e72642b 100644 --- a/src/locales/ru-RU/clusters.ts +++ b/src/locales/ru-RU/clusters.ts @@ -126,7 +126,11 @@ export default { 'You can also skip this step and add them later from the cluster list.', 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', 'clusters.create.k8sTips2': - 'You can also skip this step and register it later from the cluster list.' + 'You can also skip this step and register it later from the cluster list.', + 'clusters.addworker.theadNotes': + 'If the ln -s /path/to/PPU_SDK /usr/local/PPU_SDK', + 'clusters.addworker.theadNotes-02': + 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the /var/run/cdi directory to be available for CDI generation.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -139,4 +143,6 @@ export default { // 7. 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', // 8. 'clusters.create.k8sTips2': 'You can also skip this step and register it later from the cluster list.', // 9. 'clusters.create.steps.configure': 'Configure', +// 10. 'clusters.addworker.theadNotes': 'If the ln -s /path/to/PPU_SDK /usr/local/PPU_SDK', +// 11. 'clusters.addworker.theadNotes-02': 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the /var/run/cdi directory to be available for CDI generation.' // ================================================================ diff --git a/src/locales/ru-RU/vendor.ts b/src/locales/ru-RU/vendor.ts index a1eede4c..f63a4e21 100644 --- a/src/locales/ru-RU/vendor.ts +++ b/src/locales/ru-RU/vendor.ts @@ -5,5 +5,6 @@ export default { 'vendor.moorthreads': 'Moore Threads', 'vendor.iluvatar': 'Iluvatar', 'vendor.metax': 'Metax', - 'vendor.cambricon': 'Cambricon' + 'vendor.cambricon': 'Cambricon', + 'vendor.thead': 'T-Head' }; diff --git a/src/locales/zh-CN/clusters.ts b/src/locales/zh-CN/clusters.ts index 946b9a73..1498f568 100644 --- a/src/locales/zh-CN/clusters.ts +++ b/src/locales/zh-CN/clusters.ts @@ -121,5 +121,9 @@ export default { 'clusters.create.dockerTips1': '接下来,为该集群添加节点。', 'clusters.create.dockerTips2': '你也可以跳过此步骤,稍后在集群列表中添加。', 'clusters.create.k8sTips1': '接下来,注册已有的 Kubernetes 集群。', - 'clusters.create.k8sTips2': '你也可以跳过此步骤,稍后在集群列表中进行注册。' + 'clusters.create.k8sTips2': '你也可以跳过此步骤,稍后在集群列表中进行注册。', + 'clusters.addworker.theadNotes': + '如果 /usr/local/PPU_SDK 目录不存在,请创建一个指向已安装平头哥(T-Head)路径的符号链接:ln -s /path/to/PPU_SDK /usr/local/PPU_SDK。', + 'clusters.addworker.theadNotes-02': + '平头哥(T-Head)PPU 使用容器设备接口(CDI)进行设备注入,因此需要确保 /var/run/cdi 目录可用以生成 CDI。' }; diff --git a/src/locales/zh-CN/vendor.ts b/src/locales/zh-CN/vendor.ts index 57760bd9..afc48c70 100644 --- a/src/locales/zh-CN/vendor.ts +++ b/src/locales/zh-CN/vendor.ts @@ -5,5 +5,6 @@ export default { 'vendor.moorthreads': '摩尔线程', 'vendor.iluvatar': '天数智芯', 'vendor.metax': '沐曦', - 'vendor.cambricon': '寒武纪' + 'vendor.cambricon': '寒武纪', + 'vendor.thead': '平头哥' }; diff --git a/src/pages/cluster-management/components/check-env-command.tsx b/src/pages/cluster-management/components/check-env-command.tsx index d1d491c9..14d348b0 100644 --- a/src/pages/cluster-management/components/check-env-command.tsx +++ b/src/pages/cluster-management/components/check-env-command.tsx @@ -12,6 +12,7 @@ const AddWorkerCommand: React.FC = ({ provider = '', currentGPU }) => { + console.log('check env command provider:', currentGPU); const code = React.useMemo(() => { const configs = addWorkerGuide['all']; const command = configs.checkEnvCommand(currentGPU); diff --git a/src/pages/cluster-management/components/support-gpus.tsx b/src/pages/cluster-management/components/support-gpus.tsx index a01568a2..43098962 100644 --- a/src/pages/cluster-management/components/support-gpus.tsx +++ b/src/pages/cluster-management/components/support-gpus.tsx @@ -96,7 +96,7 @@ const SupportedHardware: React.FC = ({ locale: false, notes: AddWorkerDockerNotes[GPUDriverMap.NVIDIA], link: 'https://docs.gpustack.ai/latest/installation/requirements/#nvidia-gpu', - icon: + icon: }, { label: 'AMD', @@ -139,7 +139,6 @@ const SupportedHardware: React.FC = ({ { label: intl.formatMessage({ id: 'vendor.moorthreads' }), hiddenTitle: true, - // description: 'common.tag.experimental', extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.MOORE_THREADS, key: GPUDriverMap.MOORE_THREADS, @@ -151,7 +150,6 @@ const SupportedHardware: React.FC = ({ { label: intl.formatMessage({ id: 'vendor.iluvatar' }), hiddenTitle: true, - // description: 'common.tag.experimental', extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.ILUVATAR, key: GPUDriverMap.ILUVATAR, @@ -163,7 +161,6 @@ const SupportedHardware: React.FC = ({ { label: intl.formatMessage({ id: 'vendor.cambricon' }), hiddenTitle: true, - // description: 'common.tag.experimental', extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.CAMBRICON, key: GPUDriverMap.CAMBRICON, @@ -175,7 +172,6 @@ const SupportedHardware: React.FC = ({ { label: intl.formatMessage({ id: 'vendor.metax' }), hiddenTitle: true, - // description: 'common.tag.experimental', extra: intl.formatMessage({ id: 'common.tag.experimental' }), value: GPUDriverMap.METAX, key: GPUDriverMap.METAX, @@ -183,6 +179,22 @@ const SupportedHardware: React.FC = ({ link: 'https://docs.gpustack.ai/latest/installation/requirements/#metax-gpu', notes: AddWorkerDockerNotes[GPUDriverMap.METAX], icon: + }, + { + label: intl.formatMessage({ id: 'vendor.thead' }), + hiddenTitle: true, + extra: intl.formatMessage({ id: 'common.tag.experimental' }), + value: GPUDriverMap.THEAD, + key: GPUDriverMap.THEAD, + locale: false, + link: 'https://docs.gpustack.ai/latest/installation/requirements/#thead-gpu', + notes: AddWorkerDockerNotes[GPUDriverMap.THEAD], + icon: ( + + ) } ]; @@ -194,7 +206,7 @@ const SupportedHardware: React.FC = ({ current={current} dataList={supportedHardPlatforms} clickable={clickable} - cols={4} + cols={5} /> ); diff --git a/src/pages/resources/config/gpu-driver.ts b/src/pages/resources/config/gpu-driver.ts index d202a8b7..e4ab3118 100644 --- a/src/pages/resources/config/gpu-driver.ts +++ b/src/pages/resources/config/gpu-driver.ts @@ -6,7 +6,8 @@ export const GPUDriverMap = { MOORE_THREADS: 'musa', ILUVATAR: 'corex', CAMBRICON: 'neuware', - METAX: 'maca' + METAX: 'maca', + THEAD: 'ppu' }; export const ManufacturerMap = { @@ -17,7 +18,8 @@ export const ManufacturerMap = { [GPUDriverMap.MOORE_THREADS]: 'vendor.moorthreads', [GPUDriverMap.ILUVATAR]: 'vendor.iluvatar', [GPUDriverMap.CAMBRICON]: 'vendor.cambricon', - [GPUDriverMap.METAX]: 'vendor.metax' + [GPUDriverMap.METAX]: 'vendor.metax', + [GPUDriverMap.THEAD]: 'vendor.thead' }; export const GPUsConfigs: Record< @@ -25,52 +27,58 @@ export const GPUsConfigs: Record< { label: string; value: string; runtime: string; driver: string } > = { [GPUDriverMap.NVIDIA]: { - label: ManufacturerMap[GPUDriverMap.NVIDIA], + label: 'Nvidia', // this label is used in echo command, do not translate value: GPUDriverMap.NVIDIA, runtime: 'nvidia', driver: 'nvidia-smi' }, [GPUDriverMap.AMD]: { - label: ManufacturerMap[GPUDriverMap.AMD], + label: 'AMD', value: GPUDriverMap.AMD, runtime: 'amd', driver: 'amd-smi static' }, [GPUDriverMap.ASCEND]: { - label: ManufacturerMap[GPUDriverMap.ASCEND], + label: 'Ascend', value: GPUDriverMap.ASCEND, runtime: 'ascend', driver: 'npu-smi info' }, [GPUDriverMap.HYGON]: { - label: ManufacturerMap[GPUDriverMap.HYGON], + label: 'Hygon', value: GPUDriverMap.HYGON, runtime: '', // TODO: confirm runtime name driver: 'hy-smi' }, [GPUDriverMap.MOORE_THREADS]: { - label: ManufacturerMap[GPUDriverMap.MOORE_THREADS], + label: 'Moore Threads', value: GPUDriverMap.MOORE_THREADS, runtime: 'mthreads', driver: 'mthreads-gmi' }, [GPUDriverMap.ILUVATAR]: { - label: ManufacturerMap[GPUDriverMap.ILUVATAR], + label: 'Iluvatar', value: GPUDriverMap.ILUVATAR, runtime: 'iluvatar', driver: 'ixsmi' }, [GPUDriverMap.CAMBRICON]: { - label: ManufacturerMap[GPUDriverMap.CAMBRICON], + label: 'Cambricon', value: GPUDriverMap.CAMBRICON, runtime: 'cambricon', driver: 'cnmon info' }, [GPUDriverMap.METAX]: { - label: ManufacturerMap[GPUDriverMap.METAX], + label: 'Metax', value: GPUDriverMap.METAX, runtime: 'metax', driver: 'mx-smi' + }, + [GPUDriverMap.THEAD]: { + label: 'T-Head', + value: GPUDriverMap.THEAD, + runtime: 'thead', // TODO: confirm runtime name + driver: 'ppu-smi' } }; @@ -87,7 +95,7 @@ const generateNvidiaDockerEnvCommand = (config: { 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、T-Head const generateHygonDockerEnvCommand = (config: { label: string; value: string; @@ -127,6 +135,9 @@ export const dockerEnvCommandMap = { ), [GPUDriverMap.METAX]: generateHygonDockerEnvCommand( GPUsConfigs[GPUDriverMap.METAX] + ), + [GPUDriverMap.THEAD]: generateHygonDockerEnvCommand( + GPUsConfigs[GPUDriverMap.THEAD] ) }; @@ -145,9 +156,17 @@ interface AddWorkerCommandParams { const generateEnvArgs = (params: any) => { const registrationInfo = params.registrationInfo || {}; + registrationInfo.env = { + ...registrationInfo.env, + ...params.extraEnv + }; // generate environment variables args from registrationInfo.env let envArgs = ''; - if (registrationInfo.env && typeof registrationInfo.env === 'object') { + if ( + registrationInfo.env && + typeof registrationInfo.env === 'object' && + Object.keys(registrationInfo.env).length > 0 + ) { Object.keys(registrationInfo.env).forEach((key) => { const value = registrationInfo.env[key]; envArgs += `-e "${key}=${value}" \\\n `; @@ -217,6 +236,25 @@ const registerAscendWorker = (params: AddWorkerCommandParams) => { ${setWorkerIPArg(params)}`; }; +// avaliable for t-head + +const registerTHeadWorker = (params: AddWorkerCommandParams) => { + const config = GPUsConfigs[params.gpu]; + const commonArgs = setNormalArgs({ + ...params, + extraEnv: { + GPUSTACK_RUNTIME_DOCKER_RESOURCE_INJECTION_POLICY: 'CDI' + } + }); + const imageArgs = setImageArgs(params); + return `${commonArgs} + --volume /usr/local/PPU_SDK:/usr/local/PPU_SDK:ro \\ + --volume /var/run/cdi:/var/run/cdi \\ + --runtime ${config.runtime} \\ + ${imageArgs} + ${setWorkerIPArg(params)}`; +}; + const registerHygonWorker = (params: AddWorkerCommandParams) => { const config = GPUsConfigs[params.gpu]; const commonArgs = setNormalArgs(params); @@ -273,7 +311,8 @@ export const registerAddWokerCommandMap = { [GPUDriverMap.ILUVATAR]: registerIluvatarWorker, [GPUDriverMap.CAMBRICON]: registerCambriconWorker, [GPUDriverMap.METAX]: registerMetaXWorker, - [GPUDriverMap.MOORE_THREADS]: registerWorker + [GPUDriverMap.MOORE_THREADS]: registerWorker, + [GPUDriverMap.THEAD]: registerTHeadWorker }; export const AddWorkerDockerNotes: Record = { @@ -287,5 +326,9 @@ export const AddWorkerDockerNotes: Record = { ], [GPUDriverMap.ILUVATAR]: ['clusters.addworker.corexNotes'], [GPUDriverMap.CAMBRICON]: ['clusters.addworker.cambriconNotes'], - [GPUDriverMap.METAX]: ['clusters.addworker.metaxNotes'] + [GPUDriverMap.METAX]: ['clusters.addworker.metaxNotes'], + [GPUDriverMap.THEAD]: [ + 'clusters.addworker.theadNotes', + 'clusters.addworker.theadNotes-02' + ] };