diff --git a/src/config/schema-type.ts b/src/config/schema-type.ts index 9c8f3a9a..985c0950 100644 --- a/src/config/schema-type.ts +++ b/src/config/schema-type.ts @@ -170,6 +170,10 @@ export const schemaTypes = { type: t.string, default: NullOrUndefined, }, + hostDiscoverability: { + type: PermissiveBoolean, + default: true, + }, // Function schema types // The type should be the value that the promise resolves diff --git a/src/config/schema.ts b/src/config/schema.ts index 6e134c2e..b219be30 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -190,6 +190,11 @@ export const schema = { mutable: true, removeIfNull: false, }, + hostDiscoverability: { + source: 'db', + mutable: true, + removeIfNull: false, + }, }; export type Schema = typeof schema; diff --git a/src/device-config.ts b/src/device-config.ts index 026a1c71..cdeed2aa 100644 --- a/src/device-config.ts +++ b/src/device-config.ts @@ -127,6 +127,11 @@ export class DeviceConfig { varType: 'string', defaultValue: 'off', }, + hostDiscoverability: { + envVarName: 'HOST_DISCOVERABILITY', + varType: 'bool', + defaultValue: 'true', + }, }; public static validKeys = [ diff --git a/src/lib/avahi.ts b/src/lib/avahi.ts new file mode 100644 index 00000000..7daa5df6 --- /dev/null +++ b/src/lib/avahi.ts @@ -0,0 +1,32 @@ +import * as config from '../config'; +import * as dbus from './dbus'; + +import log from './supervisor-console'; + +export const initialized = (async () => { + await config.initialized; + + config.on('change', (conf) => { + if (conf.hostDiscoverability != null) { + switchDiscoverability(conf.hostDiscoverability); + } + }); + + await switchDiscoverability(await config.get('hostDiscoverability')); +})(); + +async function switchDiscoverability(discoverable: boolean) { + try { + if (discoverable) { + log.info('Setting host to discoverable'); + await dbus.startService('avahi-daemon'); + await dbus.startSocket('avahi-daemon'); + } else { + log.info('Setting host to undiscoverable'); + await dbus.stopService('avahi-daemon'); + await dbus.stopSocket('avahi-daemon'); + } + } catch (e) { + log.error('There was an error switching host discoverability:', e); + } +} diff --git a/src/lib/dbus.ts b/src/lib/dbus.ts index 434c3526..3db412a3 100644 --- a/src/lib/dbus.ts +++ b/src/lib/dbus.ts @@ -35,6 +35,15 @@ export async function getLoginManagerInterface() { } } +async function startUnit(unitName: string) { + const systemd = await getSystemdInterface(); + try { + systemd.StartUnit(unitName, 'fail'); + } catch (e) { + throw new DbusError(e); + } +} + export async function restartService(serviceName: string) { const systemd = await getSystemdInterface(); try { @@ -45,21 +54,28 @@ export async function restartService(serviceName: string) { } export async function startService(serviceName: string) { + return startUnit(`${serviceName}.service`); +} + +export async function startSocket(socketName: string) { + return startUnit(`${socketName}.socket`); +} + +async function stopUnit(unitName: string) { const systemd = await getSystemdInterface(); try { - systemd.StartUnit(`${serviceName}.service`, 'fail'); + systemd.StopUnit(unitName, 'fail'); } catch (e) { throw new DbusError(e); } } export async function stopService(serviceName: string) { - const systemd = await getSystemdInterface(); - try { - systemd.StopUnit(`${serviceName}.service`, 'fail'); - } catch (e) { - throw new DbusError(e); - } + return stopUnit(`${serviceName}.service`); +} + +export async function stopSocket(socketName: string) { + return stopUnit(`${socketName}.socket`); } export async function enableService(serviceName: string) { diff --git a/src/supervisor.ts b/src/supervisor.ts index a4d4c6eb..c9eb91a4 100644 --- a/src/supervisor.ts +++ b/src/supervisor.ts @@ -12,6 +12,7 @@ import SupervisorAPI from './supervisor-api'; import log from './lib/supervisor-console'; import version = require('./lib/supervisor-version'); +import * as avahi from './lib/avahi'; import * as firewall from './lib/firewall'; const startupConfigFields: config.ConfigKey[] = [ @@ -61,6 +62,7 @@ export class Supervisor { await db.initialized; await config.initialized; await eventTracker.initialized; + await avahi.initialized; log.debug('Starting logging infrastructure'); await logger.initialized; diff --git a/test/05-device-state.spec.ts b/test/05-device-state.spec.ts index 4658910d..0f970db1 100644 --- a/test/05-device-state.spec.ts +++ b/test/05-device-state.spec.ts @@ -42,6 +42,7 @@ const testTarget1 = { config: { HOST_CONFIG_gpu_mem: '256', HOST_FIREWALL_MODE: 'off', + HOST_DISCOVERABILITY: 'true', SUPERVISOR_CONNECTIVITY_CHECK: 'true', SUPERVISOR_DELTA: 'false', SUPERVISOR_DELTA_APPLY_TIMEOUT: '0', @@ -129,6 +130,7 @@ const testTargetWithDefaults2 = { config: { HOST_CONFIG_gpu_mem: '512', HOST_FIREWALL_MODE: 'off', + HOST_DISCOVERABILITY: 'true', SUPERVISOR_CONNECTIVITY_CHECK: 'true', SUPERVISOR_DELTA: 'false', SUPERVISOR_DELTA_APPLY_TIMEOUT: '0', diff --git a/test/13-device-config.spec.ts b/test/13-device-config.spec.ts index bb4940bc..d7716b9b 100644 --- a/test/13-device-config.spec.ts +++ b/test/13-device-config.spec.ts @@ -192,6 +192,7 @@ describe('Device Backend Config', () => { const conf = deviceConfig.getDefaults(); return expect(conf).to.deep.equal({ HOST_FIREWALL_MODE: 'off', + HOST_DISCOVERABILITY: 'true', SUPERVISOR_VPN_CONTROL: 'true', SUPERVISOR_POLL_INTERVAL: '60000', SUPERVISOR_LOCAL_MODE: 'false',