diff --git a/src/lib/systemd.coffee b/src/lib/systemd.coffee deleted file mode 100644 index ca455c3e..00000000 --- a/src/lib/systemd.coffee +++ /dev/null @@ -1,55 +0,0 @@ -dbus = require 'dbus-native' -Promise = require 'bluebird' - -bus = Promise.promisifyAll(dbus.systemBus()) - -systemdManagerMethodCall = (method, signature = '', body = []) -> - bus.invokeAsync({ - path: '/org/freedesktop/systemd1' - destination: 'org.freedesktop.systemd1' - interface: 'org.freedesktop.systemd1.Manager' - member: method - signature - body - }) - -exports.restartService = (serviceName) -> - systemdManagerMethodCall('RestartUnit', 'ss', [ "#{serviceName}.service", 'fail' ]) - -exports.startService = (serviceName) -> - systemdManagerMethodCall('StartUnit', 'ss', [ "#{serviceName}.service", 'fail' ]) - -exports.stopService = (serviceName) -> - systemdManagerMethodCall('StopUnit', 'ss', [ "#{serviceName}.service", 'fail' ]) - -exports.enableService = (serviceName) -> - systemdManagerMethodCall('EnableUnitFiles', 'asbb', [ [ "#{serviceName}.service" ], false, false ]) - -exports.disableService = (serviceName) -> - systemdManagerMethodCall('DisableUnitFiles', 'asb', [ [ "#{serviceName}.service" ], false ]) - -exports.reboot = Promise.method -> - setTimeout( -> - systemdManagerMethodCall('Reboot') - , 1000) - -exports.shutdown = Promise.method -> - setTimeout( -> - systemdManagerMethodCall('PowerOff') - , 1000) - -getUnitProperty = (unitName, property) -> - systemdManagerMethodCall('GetUnit', 's', [ unitName ]) - .then (unitPath) -> - bus.invokeAsync({ - path: unitPath - destination: 'org.freedesktop.systemd1' - interface: 'org.freedesktop.DBus.Properties' - member: 'Get' - signature: 'ss' - body: [ 'org.freedesktop.systemd1.Unit', property ] - }) - .get(1).get(0) - -exports.serviceActiveState = (serviceName) -> - getUnitProperty("#{serviceName}.service", 'ActiveState') diff --git a/src/lib/systemd.ts b/src/lib/systemd.ts new file mode 100644 index 00000000..cfe9601f --- /dev/null +++ b/src/lib/systemd.ts @@ -0,0 +1,90 @@ +import * as Bluebird from 'bluebird'; +import * as dbus from 'dbus-native'; + +const bus = dbus.systemBus(); +const invokeAsync = Bluebird.promisify(bus.invoke).bind(bus); + +const systemdManagerMethodCall = ( + method: string, + signature?: string, + body?: any[], +) => { + if (signature == null) { + signature = ''; + } + if (body == null) { + body = []; + } + return invokeAsync({ + path: '/org/freedesktop/systemd1', + destination: 'org.freedesktop.systemd1', + interface: 'org.freedesktop.systemd1.Manager', + member: method, + signature, + body, + }); +}; + +export function restartService(serviceName: string) { + return systemdManagerMethodCall('RestartUnit', 'ss', [ + `${serviceName}.service`, + 'fail', + ]); +} + +export function startService(serviceName: string) { + return systemdManagerMethodCall('StartUnit', 'ss', [ + `${serviceName}.service`, + 'fail', + ]); +} + +export function stopService(serviceName: string) { + return systemdManagerMethodCall('StopUnit', 'ss', [ + `${serviceName}.service`, + 'fail', + ]); +} + +export function enableService(serviceName: string) { + return systemdManagerMethodCall('EnableUnitFiles', 'asbb', [ + [`${serviceName}.service`], + false, + false, + ]); +} + +export function disableService(serviceName: string) { + return systemdManagerMethodCall('DisableUnitFiles', 'asb', [ + [`${serviceName}.service`], + false, + ]); +} + +export const reboot = Bluebird.method(() => + setTimeout(() => systemdManagerMethodCall('Reboot'), 1000), +); + +export const shutdown = Bluebird.method(() => + setTimeout(() => systemdManagerMethodCall('PowerOff'), 1000), +); + +function getUnitProperty(unitName: string, property: string) { + return systemdManagerMethodCall('GetUnit', 's', [unitName]) + .then((unitPath: string) => + invokeAsync({ + path: unitPath, + destination: 'org.freedesktop.systemd1', + interface: 'org.freedesktop.DBus.Properties', + member: 'Get', + signature: 'ss', + body: ['org.freedesktop.systemd1.Unit', property], + }), + ) + .get(1) + .get(0); +} + +export function serviceActiveState(serviceName: string) { + return getUnitProperty(`${serviceName}.service`, 'ActiveState'); +} diff --git a/typings/dbus-native.d.ts b/typings/dbus-native.d.ts new file mode 100644 index 00000000..100847fc --- /dev/null +++ b/typings/dbus-native.d.ts @@ -0,0 +1,134 @@ +// Adapted from: https://gist.github.com/TianyiLi/a231afa2f804d8fa0805baa4830f9242 +declare module 'dbus-native' { + import * as net from 'net'; + import * as events from 'events'; + + interface msg { + destination?: string; + path?: string; + interface?: any; + member: string; + signature?: any; + body?: Array; + } + + interface MessageBus { + connection: any; + serial: number; + cookies: Object; + methodCallHandlers: Object; + signals: events.EventEmitter; + exportedObjects: Object; + + invoke(msg: msg, callback?: Callback): void; + invokeDbus(msg: msg, callback?: Callback): void; + mangle(path: any, iface: any, member: any): string; + mangle(obj: { path: any; iface: any; member: any }): string; + sendSignal( + path: any, + iface: any, + name: any, + signature: any, + args: any, + ): void; + sendError(msg: any, signature: any, body: any): void; + setMethodCallHandler( + objectPath: any, + iface: any, + member: any, + handler: any, + ): void; + exportInterface( + obj: Object, + path: string, + ifaceDesc: { + name: string; + signals: Object; + method: Object; + properties: Object; + }, + ): void; + getService(serviceName: string): DBusService; + getObject(path: string, name: string, callback: Callback): DBusService; + getInterface( + path: string, + objname: string, + name: string, + callback: Callback, + ): DBusService; + + addMatch(match: string, callback?: Callback): void; + removeMatch(match: string, callback?: Callback): void; + getId(callback?: Callback): void; + requestName(name: string, flags: any, callback?: Callback): void; + releaseName(name: string, callback?: Callback): void; + listNames(callback?: Callback): void; + listActivatableNames(callback?: Callback): void; + updateActivationEnvironment(env: any, callback?: Callback): void; + startServiceByName(name: any, flags: any, callback?: Callback): void; + getConnectionUnixUser(name: any, callback?: Callback): void; + getConnectionUnixProcessId(name: any, callback?: Callback): void; + getNameOwner(name: any, callback?: Callback): void; + nameHasOwner(name: any, callback?: Callback): void; + } + + /** + * This Should Not Used + * + * TODO: Fix this + * + * @interface DBusService + */ + interface DBusService { + name: string; + bus: MessageBus; + getObject(name: any, callback: Callback): void; + getInterface( + objName: string, + ifaceName: string, + callback: Callback, + ): void; + } + + interface Server { + server: net.Server; + listen: void; + } + + const messageType: { + error: number; + invalid: number; + methodCall: number; + methodReturn: number; + signal: number; + }; + + enum flags { + noReplyExpected = 1, + noAutoStart, + } + + interface StreamOptions { + socket: string; + host: any; + port: any; + busAddress: string; + } + + class CreateConnection extends events.EventEmitter { + message(msg: { path: string }): void; + end(): void; + } + + function createClient(options?: StreamOptions): MessageBus; + function createConnection(opts?: StreamOptions): CreateConnection; + /** + * Default is /var/run/dbus/system_bus_socket + * + * @export + * @returns {MessageBus} + */ + function systemBus(): MessageBus; + function sessionBus(options?: StreamOptions): MessageBus; + function createServer(): Server; +} diff --git a/typings/global.d.ts b/typings/global.d.ts index 64dbc25f..c35e9a4d 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -1,3 +1,7 @@ interface Dictionary { [key: string]: T; } + +interface Callback { + (err?: Error, res?: T): void; +}