feat: update and download ovms to 2025.3 official release from offici… (#10603)

* feat: update and download ovms to 2025.3 official release from official site.

Signed-off-by: Kejiang Ma <kj.ma@intel.com>

* fix UI text

Signed-off-by: Kejiang Ma <kj.ma@intel.com>

---------

Signed-off-by: Kejiang Ma <kj.ma@intel.com>
This commit is contained in:
Kejiang Ma 2025-10-17 13:40:53 +08:00 committed by GitHub
parent 1f7d2fa93f
commit 2243bb2862
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 179 additions and 85 deletions

View File

@ -5,105 +5,171 @@ const { execSync } = require('child_process')
const { downloadWithPowerShell } = require('./download')
// Base URL for downloading OVMS binaries
const OVMS_PKG_NAME = 'ovms250911.zip'
const OVMS_RELEASE_BASE_URL = [`https://gitcode.com/gcw_ggDjjkY3/kjfile/releases/download/download/${OVMS_PKG_NAME}`]
const OVMS_RELEASE_BASE_URL =
'https://storage.openvinotoolkit.org/repositories/openvino_model_server/packages/2025.3.0/ovms_windows_python_on.zip'
const OVMS_EX_URL = 'https://gitcode.com/gcw_ggDjjkY3/kjfile/releases/download/download/ovms_25.3_ex.zip'
/**
* Downloads and extracts the OVMS binary for the specified platform
* error code:
* 101: Unsupported CPU (not Intel Ultra)
* 102: Unsupported platform (not Windows)
* 103: Download failed
* 104: Installation failed
* 105: Failed to create ovdnd.exe
* 106: Failed to create run.bat
* 110: Cleanup of old installation failed
*/
async function downloadOvmsBinary() {
// Create output directory structure - OVMS goes into its own subdirectory
/**
* Clean old OVMS installation if it exists
*/
function cleanOldOvmsInstallation() {
console.log('Cleaning the existing OVMS installation...')
const csDir = path.join(os.homedir(), '.cherrystudio')
// Ensure directories exist
fs.mkdirSync(csDir, { recursive: true })
const csOvmsDir = path.join(csDir, 'ovms')
// Delete existing OVMS directory if it exists
if (fs.existsSync(csOvmsDir)) {
fs.rmSync(csOvmsDir, { recursive: true })
}
const tempdir = os.tmpdir()
const tempFilename = path.join(tempdir, 'ovms.zip')
// Try each URL until one succeeds
let downloadSuccess = false
let lastError = null
for (let i = 0; i < OVMS_RELEASE_BASE_URL.length; i++) {
const downloadUrl = OVMS_RELEASE_BASE_URL[i]
console.log(`Attempting download from URL ${i + 1}/${OVMS_RELEASE_BASE_URL.length}: ${downloadUrl}`)
try {
console.log(`Downloading OVMS from ${downloadUrl} to ${tempFilename}...`)
// Try PowerShell download first, fallback to Node.js download if it fails
await downloadWithPowerShell(downloadUrl, tempFilename)
// If we get here, download was successful
downloadSuccess = true
console.log(`Successfully downloaded from: ${downloadUrl}`)
break
fs.rmSync(csOvmsDir, { recursive: true })
} catch (error) {
console.warn(`Download failed from ${downloadUrl}: ${error.message}`)
lastError = error
// Clean up failed download file if it exists
if (fs.existsSync(tempFilename)) {
try {
fs.unlinkSync(tempFilename)
} catch (cleanupError) {
console.warn(`Failed to clean up temporary file: ${cleanupError.message}`)
}
}
// Continue to next URL if this one failed
if (i < OVMS_RELEASE_BASE_URL.length - 1) {
console.log(`Trying next URL...`)
}
console.warn(`Failed to clean up old OVMS installation: ${error.message}`)
return 110
}
}
// Check if any download succeeded
if (!downloadSuccess) {
console.error(`All download URLs failed. Last error: ${lastError?.message || 'Unknown error'}`)
return 0
}
/**
* Install OVMS Base package
*/
async function installOvmsBase() {
// Download the base package
const tempdir = os.tmpdir()
const tempFilename = path.join(tempdir, 'ovms.zip')
try {
console.log(`Downloading OVMS Base Package from ${OVMS_RELEASE_BASE_URL} to ${tempFilename}...`)
// Try PowerShell download first, fallback to Node.js download if it fails
await downloadWithPowerShell(OVMS_RELEASE_BASE_URL, tempFilename)
console.log(`Successfully downloaded from: ${OVMS_RELEASE_BASE_URL}`)
} catch (error) {
console.error(`Download OVMS Base failed: ${error.message}`)
fs.unlinkSync(tempFilename)
return 103
}
try {
console.log(`Extracting to ${csDir}...`)
// unzip the base package to the target directory
const csDir = path.join(os.homedir(), '.cherrystudio')
const csOvmsDir = path.join(csDir, 'ovms')
fs.mkdirSync(csOvmsDir, { recursive: true })
try {
// Use tar.exe to extract the ZIP file
console.log(`Extracting OVMS to ${csDir}...`)
execSync(`tar -xf ${tempFilename} -C ${csDir}`, { stdio: 'inherit' })
console.log(`OVMS extracted to ${csDir}`)
console.log(`Extracting OVMS Base to ${csOvmsDir}...`)
execSync(`tar -xf ${tempFilename} -C ${csOvmsDir}`, { stdio: 'inherit' })
console.log(`OVMS extracted to ${csOvmsDir}`)
// Clean up temporary file
fs.unlinkSync(tempFilename)
console.log(`Installation directory: ${csDir}`)
} catch (error) {
console.error(`Error installing OVMS: ${error.message}`)
if (fs.existsSync(tempFilename)) {
fs.unlinkSync(tempFilename)
}
// Check if ovmsDir is empty and remove it if so
try {
const ovmsDir = path.join(csDir, 'ovms')
const files = fs.readdirSync(ovmsDir)
if (files.length === 0) {
fs.rmSync(ovmsDir, { recursive: true })
console.log(`Removed empty directory: ${ovmsDir}`)
}
} catch (cleanupError) {
console.warn(`Warning: Failed to clean up directory: ${cleanupError.message}`)
return 105
}
fs.unlinkSync(tempFilename)
return 104
}
const csOvmsBinDir = path.join(csOvmsDir, 'ovms')
// copy ovms.exe to ovdnd.exe
try {
fs.copyFileSync(path.join(csOvmsBinDir, 'ovms.exe'), path.join(csOvmsBinDir, 'ovdnd.exe'))
console.log('Copied ovms.exe to ovdnd.exe')
} catch (error) {
console.error(`Error copying ovms.exe to ovdnd.exe: ${error.message}`)
return 105
}
// copy {csOvmsBinDir}/setupvars.bat to {csOvmsBinDir}/run.bat, and append the following lines to run.bat:
// del %USERPROFILE%\.cherrystudio\ovms_log.log
// ovms.exe --config_path models/config.json --rest_port 8000 --log_level DEBUG --log_path %USERPROFILE%\.cherrystudio\ovms_log.log
const runBatPath = path.join(csOvmsBinDir, 'run.bat')
try {
fs.copyFileSync(path.join(csOvmsBinDir, 'setupvars.bat'), runBatPath)
fs.appendFileSync(runBatPath, '\r\n')
fs.appendFileSync(runBatPath, 'del %USERPROFILE%\\.cherrystudio\\ovms_log.log\r\n')
fs.appendFileSync(
runBatPath,
'ovms.exe --config_path models/config.json --rest_port 8000 --log_level DEBUG --log_path %USERPROFILE%\\.cherrystudio\\ovms_log.log\r\n'
)
console.log(`Created run.bat at: ${runBatPath}`)
} catch (error) {
console.error(`Error creating run.bat: ${error.message}`)
return 106
}
// create {csOvmsBinDir}/models/config.json with content '{"model_config_list": []}'
const configJsonPath = path.join(csOvmsBinDir, 'models', 'config.json')
fs.mkdirSync(path.dirname(configJsonPath), { recursive: true })
fs.writeFileSync(configJsonPath, '{"mediapipe_config_list":[],"model_config_list":[]}')
console.log(`Created config file: ${configJsonPath}`)
return 0
}
/**
* Install OVMS Extra package
*/
async function installOvmsExtra() {
// Download the extra package
const tempdir = os.tmpdir()
const tempFilename = path.join(tempdir, 'ovms_ex.zip')
try {
console.log(`Downloading OVMS Extra Package from ${OVMS_EX_URL} to ${tempFilename}...`)
// Try PowerShell download first, fallback to Node.js download if it fails
await downloadWithPowerShell(OVMS_EX_URL, tempFilename)
console.log(`Successfully downloaded from: ${OVMS_EX_URL}`)
} catch (error) {
console.error(`Download OVMS Extra failed: ${error.message}`)
fs.unlinkSync(tempFilename)
return 103
}
// unzip the extra package to the target directory
const csDir = path.join(os.homedir(), '.cherrystudio')
const csOvmsDir = path.join(csDir, 'ovms')
try {
// Use tar.exe to extract the ZIP file
console.log(`Extracting OVMS Extra to ${csOvmsDir}...`)
execSync(`tar -xf ${tempFilename} -C ${csOvmsDir}`, { stdio: 'inherit' })
console.log(`OVMS extracted to ${csOvmsDir}`)
// Clean up temporary file
fs.unlinkSync(tempFilename)
console.log(`Installation directory: ${csDir}`)
} catch (error) {
console.error(`Error installing OVMS Extra: ${error.message}`)
fs.unlinkSync(tempFilename)
return 104
}
// apply ovms patch, copy all files in {csOvmsDir}/patch/ovms to {csOvmsDir}/ovms with overwrite mode
const patchDir = path.join(csOvmsDir, 'patch', 'ovms')
const csOvmsBinDir = path.join(csOvmsDir, 'ovms')
try {
const files = fs.readdirSync(patchDir)
files.forEach((file) => {
const srcPath = path.join(patchDir, file)
const destPath = path.join(csOvmsBinDir, file)
fs.copyFileSync(srcPath, destPath)
console.log(`Applied patch file: ${file}`)
})
} catch (error) {
console.error(`Error applying OVMS patch: ${error.message}`)
}
return 0
}
@ -158,7 +224,27 @@ async function installOvms() {
return 102
}
return await downloadOvmsBinary()
// Clean old installation if it exists
const cleanupCode = cleanOldOvmsInstallation()
if (cleanupCode !== 0) {
console.error(`OVMS cleanup failed with code: ${cleanupCode}`)
return cleanupCode
}
const installBaseCode = await installOvmsBase()
if (installBaseCode !== 0) {
console.error(`OVMS Base installation failed with code: ${installBaseCode}`)
cleanOldOvmsInstallation()
return installBaseCode
}
const installExtraCode = await installOvmsExtra()
if (installExtraCode !== 0) {
console.error(`OVMS Extra installation failed with code: ${installExtraCode}`)
return installExtraCode
}
return 0
}
// Run the installation

View File

@ -2110,8 +2110,10 @@
"install_code_101": "Only supports Intel(R) Core(TM) Ultra CPU",
"install_code_102": "Only supports Windows",
"install_code_103": "Download OVMS runtime failed",
"install_code_104": "Uncompress OVMS runtime failed",
"install_code_105": "Clean OVMS runtime failed",
"install_code_104": "Failed to install OVMS runtime",
"install_code_105": "Failed to create ovdnd.exe",
"install_code_106": "Failed to create run.bat",
"install_code_110": "Failed to clean old OVMS runtime",
"run": "Run OVMS failed:",
"stop": "Stop OVMS failed:"
},

View File

@ -2085,7 +2085,7 @@
"description": "<div><p>1. 下载 OV 模型.</p><p>2. 在 'Manager' 中添加模型.</p><p>仅支持 Windows!</p><p>OVMS 安装路径: '%USERPROFILE%\\.cherrystudio\\ovms' .</p><p>请参考 <a href=https://github.com/openvinotoolkit/model_server/blob/c55551763d02825829337b62c2dcef9339706f79/docs/deploying_server_baremetal.md>Intel OVMS 指南</a></p></dev>",
"download": {
"button": "下载",
"error": "选择失败",
"error": "下载失败",
"model_id": {
"label": "模型 ID",
"model_id_pattern": "模型 ID 必须以 OpenVINO/ 开头",
@ -2110,8 +2110,10 @@
"install_code_101": "仅支持 Intel(R) Core(TM) Ultra CPU",
"install_code_102": "仅支持 Windows",
"install_code_103": "下载 OVMS runtime 失败",
"install_code_104": "解压 OVMS runtime 失败",
"install_code_105": "清理 OVMS runtime 失败",
"install_code_104": "安装 OVMS runtime 失败",
"install_code_105": "创建 ovdnd.exe 失败",
"install_code_106": "创建 run.bat 失败",
"install_code_110": "清理旧 OVMS runtime 失败",
"run": "运行 OVMS 失败:",
"stop": "停止 OVMS 失败:"
},

View File

@ -2085,7 +2085,7 @@
"description": "<div><p>1. 下載 OV 模型。</p><p>2. 在 'Manager' 中新增模型。</p><p>僅支援 Windows</p><p>OVMS 安裝路徑: '%USERPROFILE%\\.cherrystudio\\ovms' 。</p><p>請參考 <a href=https://github.com/openvinotoolkit/model_server/blob/c55551763d02825829337b62c2dcef9339706f79/docs/deploying_server_baremetal.md>Intel OVMS 指南</a></p></dev>",
"download": {
"button": "下載",
"error": "選擇失敗",
"error": "下載失敗",
"model_id": {
"label": "模型 ID",
"model_id_pattern": "模型 ID 必須以 OpenVINO/ 開頭",
@ -2110,8 +2110,10 @@
"install_code_101": "僅支援 Intel(R) Core(TM) Ultra CPU",
"install_code_102": "僅支援 Windows",
"install_code_103": "下載 OVMS runtime 失敗",
"install_code_104": "解壓 OVMS runtime 失敗",
"install_code_105": "清理 OVMS runtime 失敗",
"install_code_104": "安裝 OVMS runtime 失敗",
"install_code_105": "創建 ovdnd.exe 失敗",
"install_code_106": "創建 run.bat 失敗",
"install_code_110": "清理舊 OVMS runtime 失敗",
"run": "執行 OVMS 失敗:",
"stop": "停止 OVMS 失敗:"
},

View File

@ -36,7 +36,9 @@ const OVMSSettings: FC = () => {
'102': t('ovms.failed.install_code_102'),
'103': t('ovms.failed.install_code_103'),
'104': t('ovms.failed.install_code_104'),
'105': t('ovms.failed.install_code_105')
'105': t('ovms.failed.install_code_105'),
'106': t('ovms.failed.install_code_106'),
'110': t('ovms.failed.install_code_110')
}
const match = error.message.match(/code (\d+)/)
const code = match ? match[1] : 'unknown'
@ -135,7 +137,7 @@ const OVMSSettings: FC = () => {
type="primary"
onClick={runOvms}
loading={isRunningOvms}
disabled={isRunningOvms}
disabled={isRunningOvms || isInstallingOvms}
size="small">
{isRunningOvms ? t('ovms.action.starting') : t('ovms.action.run')}
</Button>