feat: node-agent detects NVIDIA GPUs and Blackmagic DeckLink cards, reports in heartbeat
This commit is contained in:
parent
86d2960b60
commit
a941f609f0
1 changed files with 45 additions and 5 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
const MAM_API_URL = (process.env.MAM_API_URL || 'http://localhost:3000').replace(/\/$/, '');
|
const MAM_API_URL = (process.env.MAM_API_URL || 'http://localhost:3000').replace(/\/$/, '');
|
||||||
const NODE_TOKEN = process.env.NODE_TOKEN || '';
|
const NODE_TOKEN = process.env.NODE_TOKEN || '';
|
||||||
|
|
@ -49,12 +50,48 @@ function getIp() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Hardware detection ────────────────────────────────────────────────────
|
||||||
|
// GPU_COUNT env var overrides filesystem detection (useful when /dev not mapped into container)
|
||||||
|
// BMD_COUNT env var similarly overrides Blackmagic DeckLink detection
|
||||||
|
function detectHardware() {
|
||||||
|
const capabilities = { gpus: [], blackmagic: [] };
|
||||||
|
|
||||||
|
const gpuOverride = parseInt(process.env.GPU_COUNT || '-1', 10);
|
||||||
|
if (gpuOverride >= 0) {
|
||||||
|
for (let i = 0; i < gpuOverride; i++) {
|
||||||
|
capabilities.gpus.push({ device: `/dev/nvidia${i}`, type: 'nvidia', index: i });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
try {
|
||||||
|
fs.accessSync(`/dev/nvidia${i}`, fs.constants.F_OK);
|
||||||
|
capabilities.gpus.push({ device: `/dev/nvidia${i}`, type: 'nvidia', index: i });
|
||||||
|
} catch (_) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bmdOverride = parseInt(process.env.BMD_COUNT || '-1', 10);
|
||||||
|
if (bmdOverride >= 0) {
|
||||||
|
for (let i = 0; i < bmdOverride; i++) {
|
||||||
|
capabilities.blackmagic.push({ device: `/dev/blackmagic/dv${i}`, index: i });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const bmdEntries = fs.readdirSync('/dev/blackmagic');
|
||||||
|
capabilities.blackmagic = bmdEntries.map(d => ({ device: `/dev/blackmagic/${d}` }));
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Heartbeat ─────────────────────────────────────────────────────────────
|
// ── Heartbeat ─────────────────────────────────────────────────────────────
|
||||||
async function heartbeat() {
|
async function heartbeat() {
|
||||||
const cpu_usage = await sampleCpu();
|
const cpu_usage = await sampleCpu();
|
||||||
const totalMem = os.totalmem();
|
const totalMem = os.totalmem();
|
||||||
const freeMem = os.freemem();
|
const freeMem = os.freemem();
|
||||||
const ip_address = getIp();
|
const ip_address = getIp();
|
||||||
|
const capabilities = detectHardware();
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
hostname: os.hostname(),
|
hostname: os.hostname(),
|
||||||
|
|
@ -65,6 +102,7 @@ async function heartbeat() {
|
||||||
cpu_usage,
|
cpu_usage,
|
||||||
mem_used_mb: Math.round((totalMem - freeMem) / 1048576),
|
mem_used_mb: Math.round((totalMem - freeMem) / 1048576),
|
||||||
mem_total_mb: Math.round(totalMem / 1048576),
|
mem_total_mb: Math.round(totalMem / 1048576),
|
||||||
|
capabilities,
|
||||||
};
|
};
|
||||||
|
|
||||||
const headers = { 'Content-Type': 'application/json' };
|
const headers = { 'Content-Type': 'application/json' };
|
||||||
|
|
@ -78,9 +116,11 @@ async function heartbeat() {
|
||||||
signal: AbortSignal.timeout(8000),
|
signal: AbortSignal.timeout(8000),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
const gpuStr = capabilities.gpus.length ? ` gpu=${capabilities.gpus.length}` : '';
|
||||||
|
const bmdStr = capabilities.blackmagic.length ? ` bmd=${capabilities.blackmagic.length}` : '';
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`[hb] ${payload.hostname} cpu=${cpu_usage}% ` +
|
`[hb] ${payload.hostname} cpu=${cpu_usage}% ` +
|
||||||
`mem=${payload.mem_used_mb}/${payload.mem_total_mb}MB\n`
|
`mem=${payload.mem_used_mb}/${payload.mem_total_mb}MB${gpuStr}${bmdStr}\n`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const txt = await res.text().catch(() => '');
|
const txt = await res.text().catch(() => '');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue