mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-29 01:58:54 +00:00
174 lines
3.7 KiB
TypeScript
174 lines
3.7 KiB
TypeScript
|
import * as DBus from 'dbus';
|
||
|
import { createSystemInterface } from './utils';
|
||
|
|
||
|
const systemdService = DBus.registerService(
|
||
|
'system',
|
||
|
'org.freedesktop.systemd1',
|
||
|
);
|
||
|
|
||
|
// Create the systemd
|
||
|
const systemd = createSystemInterface(
|
||
|
systemdService,
|
||
|
'/org/freedesktop/systemd1',
|
||
|
'org.freedesktop.systemd1.Manager',
|
||
|
);
|
||
|
|
||
|
type Unit = {
|
||
|
running: boolean;
|
||
|
path: string;
|
||
|
partOf?: string;
|
||
|
};
|
||
|
|
||
|
// Maintain the state of created units in memory
|
||
|
const units: { [key: string]: Unit } = {};
|
||
|
function createUnit(name: string, path: string, partOf?: string) {
|
||
|
// Each unit needs an object and a properties interface
|
||
|
const obj = systemdService.createObject(path);
|
||
|
const iface = obj.createInterface('org.freedesktop.DBus.Properties');
|
||
|
|
||
|
units[name] = { running: false, path, partOf };
|
||
|
|
||
|
// org.freedesktop.DBus.Properties needs a Get method to get the
|
||
|
// unit properties
|
||
|
iface.addMethod(
|
||
|
'Get',
|
||
|
{
|
||
|
in: [
|
||
|
{ type: 's', name: 'interface_name' },
|
||
|
{ type: 's', name: 'property_name' },
|
||
|
],
|
||
|
out: { type: 'v' },
|
||
|
} as any,
|
||
|
function (interfaceName, propertyName, callback: any) {
|
||
|
if (interfaceName !== 'org.freedesktop.systemd1.Unit') {
|
||
|
callback(`Unkown interface: ${interfaceName}`);
|
||
|
}
|
||
|
|
||
|
switch (propertyName) {
|
||
|
case 'ActiveState':
|
||
|
callback(null, units[name].running ? 'active' : 'inactive');
|
||
|
break;
|
||
|
case 'PartOf':
|
||
|
callback(partOf ?? 'none');
|
||
|
break;
|
||
|
default:
|
||
|
callback(`Unknown property: ${propertyName}`);
|
||
|
}
|
||
|
},
|
||
|
);
|
||
|
|
||
|
iface.update();
|
||
|
}
|
||
|
|
||
|
systemd.addMethod(
|
||
|
'StopUnit',
|
||
|
{
|
||
|
in: [
|
||
|
{ type: 's', name: 'unit_name' },
|
||
|
{ type: 's', name: 'mode' },
|
||
|
],
|
||
|
out: { type: 'o' },
|
||
|
} as any,
|
||
|
function (unitName, _mode, callback: any) {
|
||
|
if (!units[unitName]) {
|
||
|
callback(`Unit not found: ${unitName}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Wait a bit before changing the runtime state
|
||
|
setTimeout(() => {
|
||
|
units[unitName] = { ...units[unitName], running: false };
|
||
|
}, 500);
|
||
|
|
||
|
callback(
|
||
|
null,
|
||
|
`/org/freedesktop/systemd1/job/${String(
|
||
|
Math.floor(Math.random() * 10000),
|
||
|
)}`,
|
||
|
);
|
||
|
},
|
||
|
);
|
||
|
|
||
|
systemd.addMethod(
|
||
|
'StartUnit',
|
||
|
{
|
||
|
in: [
|
||
|
{ type: 's', name: 'unit_name' },
|
||
|
{ type: 's', name: 'mode' },
|
||
|
],
|
||
|
out: { type: 'o' },
|
||
|
} as any,
|
||
|
function (unitName, _mode, callback: any) {
|
||
|
if (!units[unitName]) {
|
||
|
callback(`Unit not found: ${unitName}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Wait a bit before changing the runtime state
|
||
|
setTimeout(() => {
|
||
|
units[unitName] = { ...units[unitName], running: true };
|
||
|
}, 500);
|
||
|
|
||
|
callback(
|
||
|
null,
|
||
|
// Make up a job number
|
||
|
`/org/freedesktop/systemd1/job/${String(
|
||
|
Math.floor(Math.random() * 10000),
|
||
|
)}`,
|
||
|
);
|
||
|
},
|
||
|
);
|
||
|
|
||
|
systemd.addMethod(
|
||
|
'RestartUnit',
|
||
|
{
|
||
|
in: [
|
||
|
{ type: 's', name: 'unit_name' },
|
||
|
{ type: 's', name: 'mode' },
|
||
|
],
|
||
|
out: { type: 'o' },
|
||
|
} as any,
|
||
|
function (unitName, _mode, callback: any) {
|
||
|
if (!units[unitName]) {
|
||
|
callback(`Unit not found: ${unitName}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Wait a bit before changing the runtime state
|
||
|
setTimeout(() => {
|
||
|
units[unitName] = { ...units[unitName], running: false };
|
||
|
}, 500);
|
||
|
|
||
|
setTimeout(() => {
|
||
|
units[unitName] = { ...units[unitName], running: true };
|
||
|
}, 1000);
|
||
|
|
||
|
callback(
|
||
|
null,
|
||
|
`/org/freedesktop/systemd1/job/${String(
|
||
|
Math.floor(Math.random() * 10000),
|
||
|
)}`,
|
||
|
);
|
||
|
},
|
||
|
);
|
||
|
|
||
|
systemd.addMethod(
|
||
|
'GetUnit',
|
||
|
{ in: [{ type: 's', name: 'unit_name' }], out: { type: 'o' } } as any,
|
||
|
function (unitName, callback) {
|
||
|
if (!units[unitName]) {
|
||
|
callback(`Unit not found: ${unitName}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const { path } = units[unitName];
|
||
|
callback(null, path);
|
||
|
},
|
||
|
);
|
||
|
|
||
|
// Simulate OS units
|
||
|
createUnit('openvpn.service', '/org/freedesktop/systemd1/unit/openvpn');
|
||
|
createUnit('avahi.socket', '/org/freedesktop/systemd1/unit/avahi');
|
||
|
|
||
|
systemd.update();
|