KASM-1190 Remove legacy GPU seeding in favour of 1.19.0 agent management

In 1.19.0, the provision agent dynamically assigns GPUs to containers
using capability probing (EGL, DRI3, VAAPI, NVENC, VULKAN) and
load-balancing across devices. Pre-seeding GPU run_config/exec_config
into workspace images at install time conflicts with this system and
uses removed env var names (HW3D/DRINODE replaced by
KVNC_DESKTOP_GPU_HW3D/KVNC_DESKTOP_GPU_DRINODE).

Remove setGpu(), the gpuinfo.sh detection block, the GPU yaml-merge
call in install(), and the "Use GPU on all images" install UI option.
Replace the UI option with a notice directing admins to configure GPU
acceleration in the admin panel post-install.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Richard Koliser 2026-06-17 14:16:12 -04:00
parent 64f3768748
commit 0774b59deb
No known key found for this signature in database
2 changed files with 3 additions and 82 deletions

View file

@ -19,12 +19,11 @@ const docker = new Docker({socketPath: '/var/run/docker.sock'});
const arch = os.arch().replace('x64', 'amd64');
const baseUrl = process.env.SUBFOLDER || '/';
const port = process.env.KASM_PORT || '443';
const { spawn } = require('node:child_process');
let EULA;
let images;
let currentVersion;
let sourceLocal = false;
let gpuInfo;
let gpuInfo = {};
let installSettings = {};
let upgradeSettings = {};
@ -145,72 +144,9 @@ async function installerBlobs() {
currentVersion = '1.19.0';
}
images = await fetchWorkspaceList(currentVersion, arch);
gpuInfo = {};
await new Promise((resolve) => {
let gpuData = [];
let gpuCmd = spawn('/gpuinfo.sh');
gpuCmd.stdout.on('data', function(data) {
gpuData.push(data);
});
gpuCmd.on('close', function(code) {
try {
if (code == 0) {
gpuInfo = JSON.parse(gpuData.join(''));
} else {
gpuInfo = {};
}
} catch (err) {
// Manually backfill GPU info if available
gpuInfo = {};
for (let i = 0; i < 10; i++) {
let num = i.toString();
if (fs.existsSync('/dev/dri/card' + num)) {
gpuInfo['/dev/dri/card' + num] = "Unknown GPU";
}
}
}
resolve();
});
});
}
installerBlobs();
// GPU image yaml merging
async function setGpu(imagesI) {
if (upgradeSettings['forceGpu'] !== undefined) {
installSettings = upgradeSettings;
}
const forceGpu = installSettings.forceGpu;
if (!forceGpu || forceGpu === 'disabled' || !forceGpu.includes('|')) {
console.error('setGpu: invalid or missing forceGpu value:', forceGpu);
return imagesI;
}
const [gpu, gpuName] = forceGpu.split('|');
if (!gpu || !gpuName) {
console.error('setGpu: could not parse GPU path or name from forceGpu:', forceGpu);
return imagesI;
}
const card = gpu.slice(-1);
const render = (Number(card) + 128).toString();
// Handle NVIDIA Gpus
let baseRun;
if (gpuName.includes('NVIDIA')) {
baseRun = JSON.parse('{"runtime":"nvidia","environment":{"NVIDIA_DRIVER_CAPABILITIES":"all","KASM_EGL_CARD":"/dev/dri/card' + card + '","KASM_RENDERD":"/dev/dri/renderD' + render + '"},"device_requests":[{"driver": "","count": -1,"device_ids": null,"capabilities":[["gpu"]],"options":{}}]}');
} else {
baseRun = JSON.parse('{"environment":{"DRINODE":"/dev/dri/renderD' + render + '", "HW3D": true},"devices":["/dev/dri/card' + card + ':/dev/dri/card' + card + ':rwm","/dev/dri/renderD' + render + ':/dev/dri/renderD' + render + ':rwm"]}');
}
let baseExec = JSON.parse('{"first_launch":{"user":"root","cmd": "bash -c \'chown -R kasm-user:kasm-user /dev/dri/*\'"}}');
for (let i=0; i<imagesI.images.length; i++) {
console.log(imagesI.images[i]['run_config']);
let finalRun = _.merge(imagesI.images[i]['run_config'], baseRun)
let finalExec = _.merge(imagesI.images[i]['exec_config'], baseExec)
imagesI.images[i]['run_config'] = finalRun;
imagesI.images[i]['exec_config'] = finalExec;
}
return imagesI;
}
//// Http server ////
baserouter.use('/public', express.static(__dirname + '/public'));
baserouter.get("/", function (req, res) {
@ -235,11 +171,6 @@ io.on('connection', async function (socket) {
installFlags.push('-b');
}
// GPU yaml merge
if (installSettings.forceGpu !== 'disabled' && imagesI && imagesI.images) {
imagesI = await setGpu(imagesI);
}
// Write finalized image data
let yamlStr = yaml.dump(imagesI);
if (yamlStr.startsWith("false")) {

View file

@ -1,7 +1,6 @@
// Variables
let EULA;
let images;
let gpus;
let term;
let installImages = [];
const installSettings = {};
@ -93,7 +92,6 @@ function renderInstall(data) {
titleChange('EULA');
EULA = data[0];
images = data[1];
gpus = data[2] || {};
versionChange(data[3], data[4]);
let EULADiv = $('<div>', {id: 'EULA'}).text(EULA);
$('#container').append(EULADiv);
@ -230,14 +228,7 @@ async function pickSettings() {
$('<label>', {for: 'userPass'}).text('user@kasm.local Password: '),
$('<input>', {name: 'userPass', id: 'userPass', type: 'password', required: true, placeholder: 'required'})
]);
let gpuOptions = [$('<option>', {value: 'disabled'}).text('Disabled')];
for (let card of Object.keys(gpus || {})) {
gpuOptions.push($('<option>', {value: card + '|' + gpus[card]}).text(card + ' - ' + gpus[card]));
}
let forceGpu = $('<div>', {class: 'form-group'}).append([
$('<label>', {for: 'forceGpu'}).text('Use GPU on all images: '),
$('<select>', {name: 'forceGpu', id: 'forceGpu',}).append(gpuOptions)
]);
let gpuNotice = $('<p>').text('GPU acceleration is automatically managed by Kasm Workspaces 1.19.0. Configure GPU settings after installation in the admin panel under Infrastructure > Agents.');
let submit = $('<div>', {class: 'form-group'}).append([
$('<input>', {name: 'submit', type: 'submit', value: 'Next', class: 'btn btn-default btn-ghost'})
]);
@ -249,7 +240,7 @@ async function pickSettings() {
passHint,
adminPass,
userPass,
forceGpu,
gpuNotice,
submit
]);
form.append(fieldset);
@ -267,7 +258,6 @@ async function pickSettings() {
$('#pass-hint').css('color', 'inherit');
installSettings.adminPass = adminPassVal;
installSettings.userPass = userPassVal;
installSettings.forceGpu = $('#forceGpu').val();
pickImages(false);
});
}