Skip to content

Commit

Permalink
Network settings implementation for Ubuntu and Ubuntu Core - closes #…
Browse files Browse the repository at this point in the history
  • Loading branch information
benfrancis committed Nov 13, 2024
1 parent 4cba700 commit 6e68b40
Show file tree
Hide file tree
Showing 15 changed files with 1,209 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Install system dependencies
run: |
sudo apt -qq update
sudo apt install -y google-chrome-stable
sudo apt install -y google-chrome-stable libdbus-1-dev
- name: Install node dependencies
run: |
npm ci
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ npm-debug.log

# Test artifacts
/coverage/

# Built packages
*.snap
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

[![Build Status](https://github.com/WebThingsIO/gateway/workflows/Build/badge.svg)](https://github.com/WebThingsIO/gateway/actions?query=workflow%3ABuild)
[![codecov](https://codecov.io/gh/WebThingsIO/gateway/branch/master/graph/badge.svg)](https://codecov.io/gh/WebThingsIO/gateway)
[![dependencies](https://david-dm.org/WebThingsIO/gateway.svg)](https://david-dm.org/WebThingsIO/gateway)
[![devDependencies](https://david-dm.org/WebThingsIO/gateway/dev-status.svg)](https://david-dm.org/WebThingsIO/gateway?type=dev)
[![license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)

Web of Things gateway.
Expand All @@ -12,9 +10,8 @@ Web of Things gateway.

- If you have a Rasberry Pi, the easiest way to use the gateway is to [download and flash](http://webthings.io/gateway/) a pre-built software image to an SD card.
- If you prefer to use Docker, we have a prebuilt Docker image available [here](https://hub.docker.com/r/webthingsio/gateway), for both ARM and amd64. You can also build your own image from this repository.
- On Fedora, Debian, Raspberry Pi OS, or Ubuntu, you can install the relevant .rpm or .deb package from the [releases page](https://github.com/WebThingsIO/gateway/releases).
- On Arch Linux, you can install the [webthings-gateway AUR package](https://aur.archlinux.org/packages/webthings-gateway/). The PKGBUILD for this package can also be seen [here](https://github.com/WebThingsIO/gateway-aur).
- Otherwise, you can build it from source yourself (see below).
- On Ubuntu or Ubuntu Core you can install the experimental [snap package](https://snapcraft.io/webthings-gateway) with `$ snap install webthings-gateway --edge`. (Requires the `system-observe` and `network-manager` interfaces to be connected in order to configure network settings).
- Otherwise, you can build WebThings Gateway from source yourself (see below).

## Documentation

Expand Down Expand Up @@ -50,6 +47,7 @@ $ sudo apt install \
libbluetooth-dev \
libboost-python-dev \
libboost-thread-dev \
libdbus-1-dev \
libffi-dev \
libglib2.0-dev \
libpng-dev \
Expand Down Expand Up @@ -93,11 +91,19 @@ $ brew update
$ brew install \
autoconf \
libffi \
pkg-config
$ sudo -H python2 -m pip install six
pkg-config \
[email protected] \
dbus
$ sudo -H python3 -m pip install git+https://github.com/WebThingsIO/gateway-addon-python#egg=gateway_addon
```

To get DBus to build properly, you currently need to symlink `python` to `python3` if a python binary is not already available. E.g.

```
$ echo 'export PATH=/opt/homebrew/opt/[email protected]/libexec/bin:$PATH' >> ~/.zprofile
$ source ~/.zprofile
```

### Install Node.js

#### nvm (Recommended)
Expand Down
41 changes: 37 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"config": "^3.3.4",
"country-list": "^2.2.0",
"csv-parse": "^4.15.3",
"dbus": "^1.0.7",
"express": "^4.17.1",
"express-fileupload": "^1.2.1",
"express-handlebars": "^5.3.5",
Expand All @@ -52,11 +53,13 @@
"gateway-addon": "^1.2.0-alpha.1",
"glob-to-regexp": "^0.4.1",
"http-proxy": "^1.18.1",
"ip": "^2.0.1",
"ip-regex": "^4.3.0",
"jsonwebtoken": "^8.5.1",
"minipass": "^3.3.5",
"mkdirp": "^1.0.4",
"ncp": "^2.0.0",
"netmask": "^2.0.2",
"nocache": "^2.1.0",
"node-fetch": "^2.6.7",
"node-getopt": "^0.3.2",
Expand Down Expand Up @@ -87,6 +90,7 @@
"@types/compression": "^1.7.0",
"@types/config": "0.0.38",
"@types/country-list": "^2.1.0",
"@types/dbus": "^1.0.9",
"@types/event-to-promise": "^0.7.1",
"@types/eventsource": "^1.1.6",
"@types/express": "^4.17.11",
Expand All @@ -97,12 +101,14 @@
"@types/find": "^0.2.1",
"@types/glob-to-regexp": "^0.4.0",
"@types/http-proxy": "^1.17.5",
"@types/ip": "^1.1.3",
"@types/jest": "^27.0.1",
"@types/jsdom": "^16.2.6",
"@types/jsonfile": "^6.0.0",
"@types/jsonwebtoken": "^8.5.0",
"@types/mkdirp": "^1.0.1",
"@types/ncp": "^2.0.4",
"@types/netmask": "^2.0.5",
"@types/node": "^14.14.31",
"@types/node-fetch": "^2.5.8",
"@types/node-getopt": "^0.2.31",
Expand Down
2 changes: 2 additions & 0 deletions snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ apps:
- network
- network-bind
- system-observe
- network-manager

parts:
python-deps:
Expand Down Expand Up @@ -45,6 +46,7 @@ parts:
- libpng-dev
- libudev-dev
- libusb-1.0-0-dev
- libdbus-1-dev
override-build: |
craftctl default
npm install --only-dev
Expand Down
3 changes: 3 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ function startGateway(): void {
}

function gracefulExit(): void {
if (Platform.implemented('stop')) {
Platform.stop();
}
AddonManager.unloadAddons();
TunnelService.stop();
}
Expand Down
43 changes: 38 additions & 5 deletions src/controllers/settings_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import TunnelService from '../tunnel-service';
import * as CertificateManager from '../certificate-manager';
import pkg from '../package.json';
import { HttpErrorWithCode } from '../errors';
import { LanMode, NetworkAddresses } from '../platforms/types';

function build(): express.Router {
const auth = jwtMiddleware.middleware();
Expand Down Expand Up @@ -397,7 +398,11 @@ function build(): express.Router {
});

controller.get('/network/lan', auth, (_request, response) => {
if (Platform.implemented('getLanMode')) {
if (Platform.implemented('getLanModeAsync')) {
Platform.getLanModeAsync().then((mode: LanMode) => {
response.json(mode);
});
} else if (Platform.implemented('getLanMode')) {
response.json(Platform.getLanMode());
} else {
response.status(500).send('LAN mode not implemented');
Expand All @@ -413,7 +418,15 @@ function build(): express.Router {
const mode = request.body.mode;
const options = request.body.options;

if (Platform.implemented('setLanMode')) {
if (Platform.implemented('setLanModeAsync')) {
Platform.setLanModeAsync(mode, options).then((result: boolean) => {
if (result == true) {
response.status(200).json({});
} else {
response.status(500).send('Failed to update LAN configuration');
}
});
} else if (Platform.implemented('setLanMode')) {
if (Platform.setLanMode(mode, options)) {
response.status(200).json({});
} else {
Expand All @@ -433,7 +446,11 @@ function build(): express.Router {
});

controller.get('/network/wireless/networks', auth, (_request, response) => {
if (Platform.implemented('scanWirelessNetworks')) {
if (Platform.implemented('scanWirelessNetworksAsync')) {
Platform.scanWirelessNetworksAsync().then((networks) => {
response.json(networks);
});
} else if (Platform.implemented('scanWirelessNetworks')) {
response.json(Platform.scanWirelessNetworks());
} else {
response.status(500).send('Wireless scanning not implemented');
Expand All @@ -450,7 +467,19 @@ function build(): express.Router {
const mode = request.body.mode;
const options = request.body.options;

if (Platform.implemented('setWirelessMode')) {
if (Platform.implemented('setWirelessModeAsync')) {
Platform.setWirelessModeAsync(enabled, mode, options)
.then((result) => {
if (result === true) {
response.status(200).json({});
} else {
response.status(500).send('Failed to update wireless configuration');
}
})
.catch(() => {
response.status(500).send('Failed to update wireless configuration');
});
} else if (Platform.implemented('setWirelessMode')) {
if (Platform.setWirelessMode(enabled, mode, options)) {
response.status(200).json({});
} else {
Expand All @@ -462,7 +491,11 @@ function build(): express.Router {
});

controller.get('/network/addresses', auth, (_request, response) => {
if (Platform.implemented('getNetworkAddresses')) {
if (Platform.implemented('getNetworkAddressesAsync')) {
Platform.getNetworkAddressesAsync().then((networkAddresses: NetworkAddresses) => {
response.json(networkAddresses);
});
} else if (Platform.implemented('getNetworkAddresses')) {
response.json(Platform.getNetworkAddresses());
} else {
response.status(500).send('Network addresses not implemented');
Expand Down
33 changes: 28 additions & 5 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import LinuxArchPlatform from './platforms/linux-arch';
import LinuxDebianPlatform from './platforms/linux-debian';
import LinuxRaspbianPlatform from './platforms/linux-raspbian';
import LinuxUbuntuPlatform from './platforms/linux-ubuntu';
import LinuxUbuntuCorePlatform from './platforms/linux-ubuntu-core';
import {
LanMode,
NetworkAddresses,
Expand Down Expand Up @@ -68,7 +69,7 @@ export function getOS(): string {
return 'linux-unknown';
}

// Otherwise try to detect if running on Ubuntu Core.
// Otherwise try to detect Ubuntu or Ubuntu Core from inside a snap
try {
const osReleaseLines = fs
.readFileSync('/var/lib/snapd/hostfs/etc/os-release', {
Expand All @@ -85,10 +86,14 @@ export function getOS(): string {
let id = line.substring(3, line.length);
// Remove any quotation marks
id = id.replace(/"/g, '');
if (id == 'ubuntu-core') {
return 'linux-ubuntu-core';
} else {
console.log('Unknown host Linux distribution');
switch (id) {
case 'ubuntu':
return 'linux-ubuntu';
case 'ubuntu-core':
return 'linux-ubuntu-core';
default:
console.log('Unknown host Linux distribution');
break;
}
}
}
Expand Down Expand Up @@ -195,6 +200,9 @@ switch (getOS()) {
case 'linux-ubuntu':
platform = LinuxUbuntuPlatform;
break;
case 'linux-ubuntu-core':
platform = LinuxUbuntuCorePlatform;
break;
default:
platform = null;
break;
Expand All @@ -205,21 +213,35 @@ export const setDhcpServerStatus = wrapPlatform<boolean>(platform, 'setDhcpServe
export const getHostname = wrapPlatform<string>(platform, 'getHostname');
export const setHostname = wrapPlatform<boolean>(platform, 'setHostname');
export const getLanMode = wrapPlatform<LanMode>(platform, 'getLanMode');
export const getLanModeAsync = wrapPlatform<Promise<LanMode>>(platform, 'getLanModeAsync');
export const setLanMode = wrapPlatform<boolean>(platform, 'setLanMode');
export const setLanModeAsync = wrapPlatform<Promise<boolean>>(platform, 'setLanModeAsync');
export const getMacAddress = wrapPlatform<string | null>(platform, 'getMacAddress');
export const getMdnsServerStatus = wrapPlatform<boolean>(platform, 'getMdnsServerStatus');
export const setMdnsServerStatus = wrapPlatform<boolean>(platform, 'setMdnsServerStatus');
export const getNetworkAddresses = wrapPlatform<NetworkAddresses>(platform, 'getNetworkAddresses');
export const getNetworkAddressesAsync = wrapPlatform<Promise<NetworkAddresses>>(
platform,
'getNetworkAddressesAsync'
);
export const getSshServerStatus = wrapPlatform<boolean>(platform, 'getSshServerStatus');
export const setSshServerStatus = wrapPlatform<boolean>(platform, 'setSshServerStatus');
export const getWirelessMode = wrapPlatform<WirelessMode>(platform, 'getWirelessMode');
export const setWirelessMode = wrapPlatform<boolean>(platform, 'setWirelessMode');
export const setWirelessModeAsync = wrapPlatform<Promise<boolean>>(
platform,
'setWirelessModeAsync'
);
export const restartGateway = wrapPlatform<boolean>(platform, 'restartGateway');
export const restartSystem = wrapPlatform<boolean>(platform, 'restartSystem');
export const scanWirelessNetworks = wrapPlatform<WirelessNetwork[]>(
platform,
'scanWirelessNetworks'
);
export const scanWirelessNetworksAsync = wrapPlatform<Promise<WirelessNetwork[]>>(
platform,
'scanWirelessNetworksAsync'
);
export const getSelfUpdateStatus = wrapPlatform<SelfUpdateStatus>(platform, 'getSelfUpdateStatus');
export const setSelfUpdateStatus = wrapPlatform<boolean>(platform, 'setSelfUpdateStatus');
export const getValidTimezones = wrapPlatform<string[]>(platform, 'getValidTimezones');
Expand All @@ -239,6 +261,7 @@ export const getNtpStatus = (): boolean => {

return wrapPlatform<boolean>(platform, 'getNtpStatus')();
};
export const stop = wrapPlatform<string>(platform, 'stop');

export const implemented = (fn: string): boolean => {
if (platform === null) {
Expand Down
Loading

0 comments on commit 6e68b40

Please sign in to comment.