Skip to content

Commit

Permalink
refactor(web-ui): move starting/stopping of the required hotspot syst…
Browse files Browse the repository at this point in the history
…em services to the `ubo-hotspot` service (the more general version of the `ubo-redirect-server` service which runs the redirect server as its main process.)
  • Loading branch information
sassanh committed Jan 31, 2025
1 parent aa4ecf0 commit a563c3e
Show file tree
Hide file tree
Showing 25 changed files with 117 additions and 108 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- refactor(ci): use new github runner arm images for building images
- feat(web-ui): add `ubo-redirect-server` service
- refactor(web-ui): add notifications for when starting/stopping the hotspot fails in the system manager
- refactor(web-ui): move starting/stopping of the required hotspot system services to the `ubo-hotspot` service (the more general version of the `ubo-redirect-server` service which runs the redirect server as its main process.)

## Version 1.1.0

Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ pyfakefs = { git = "https://github.com/pytest-dev/pyfakefs.git" }

[project.scripts]
ubo = "ubo_app.main:main"
bootstrap = "ubo_app.bootstrap:main"
ubo-bootstrap = "ubo_app.system.bootstrap:main"
ubo-system = "ubo_app.system.system_manager.main:main"
ubo-hotspot-config = "ubo_app.system.hotspot_config:main"
ubo-redirect-server = "ubo_app.system.redirect_server:main"


Expand Down
3 changes: 1 addition & 2 deletions scripts/consume.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
set -o errexit
set -o pipefail
set -o nounset

FILE=$1
CHUNK_SIZE=$((1024*1024*1024))
SIZE=$(wc -c $FILE | awk '{print $1}')
SIZE=$(stat -c "%s" "$FILE")
CHUNKS=$((($SIZE + $CHUNK_SIZE - 1) / $CHUNK_SIZE))
BLOCK_BASED_SIZE=$(($CHUNKS*$CHUNK_SIZE))

Expand Down
2 changes: 1 addition & 1 deletion scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mv /tmp/models /opt/ubo/env/lib/python3.*/site-packages/ubo_app/services/*-voice
true"

if [ "$bootstrap" == "True" ] || [ "$env" == "True" ] || [ "$restart" == "True" ]; then
run_on_pod_as_root "$(if [ "$bootstrap" == "True" ]; then echo "/opt/ubo/env/bin/bootstrap && systemctl daemon-reload && systemctl restart ubo-system.service &&"; fi)
run_on_pod_as_root "$(if [ "$bootstrap" == "True" ]; then echo "/opt/ubo/env/bin/ubo-bootstrap && systemctl daemon-reload && systemctl restart ubo-system.service &&"; fi)
$(if [ "$env" == "True" ]; then echo "cat <<'EOF' > /tmp/.dev.env
$(cat ubo_app/.dev.env)
EOF &&
Expand Down
16 changes: 0 additions & 16 deletions ubo_app/bootstrap.py

This file was deleted.

5 changes: 5 additions & 0 deletions ubo_app/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@
GRPC_ENVOY_LISTEN_ADDRESS = os.environ.get('UBO_GRPC_ENVOY_LISTEN_ADDRESS', '127.0.0.1')
GRPC_ENVOY_LISTEN_PORT = int(os.environ.get('UBO_GRPC_ENVOY_LISTEN_PORT', '50052'))

# Most of these should be changed in ubo-app and ubo-system-manager simultaneously to
# avoid breaking the system.
# TODO(sassanh): Make above comment visible to the end user when a change # noqa: FIX002
# is detected in of these values.
WEB_UI_LISTEN_ADDRESS = os.environ.get('UBO_WEB_UI_LISTEN_ADDRESS', '0.0.0.0') # noqa: S104
WEB_UI_LISTEN_PORT = int(os.environ.get('UBO_WEB_UI_LISTEN_PORT', '4321'))
WEB_UI_DEBUG_MODE = str_to_bool(os.environ.get('UBO_WEB_UI_DEBUG_MODE', 'False')) == 1
WEB_UI_HOTSPOT_PASSWORD = os.environ.get('UBO_WEB_UI_HOTSPOT_PASSWORD', 'ubopod-setup')

UPDATE_ASSETS_PATH = Path(f'{INSTALLATION_PATH}/_update/')
UPDATE_LOCK_PATH = UPDATE_ASSETS_PATH / 'update_is_ready.lock'
Expand Down
4 changes: 3 additions & 1 deletion ubo_app/services/000-audio/audio_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from __future__ import annotations

import asyncio
import math
import wave

Expand Down Expand Up @@ -40,7 +41,7 @@ def __init__(self: AudioManager) -> None:
self.cardindex = None

async def initialize_audio() -> None:
while True:
for _ in range(20):
try:
cards = alsaaudio.cards()
self.cardindex = cards.index(
Expand All @@ -50,6 +51,7 @@ async def initialize_audio() -> None:
logger.exception('No audio card found')
else:
break
await asyncio.sleep(1)

create_task(initialize_audio())

Expand Down
5 changes: 3 additions & 2 deletions ubo_app/services/090-web-ui/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from ubo_app.constants import (
WEB_UI_DEBUG_MODE,
WEB_UI_HOTSPOT_PASSWORD,
WEB_UI_LISTEN_ADDRESS,
WEB_UI_LISTEN_PORT,
)
Expand Down Expand Up @@ -82,8 +83,8 @@ async def initialize(event: WebUIInitializeEvent) -> None:
'in your browser.'
if is_connected
else f'Please connect to the "{get_pod_id()}" WiFi network '
f'and open http://{hostname}.local:{WEB_UI_LISTEN_PORT} in '
'your browser.'
f'with password "{WEB_UI_HOTSPOT_PASSWORD}" and open '
f'http://{hostname}.local:{WEB_UI_LISTEN_PORT} in your browser.'
),
),
expiration_timestamp=datetime.datetime.now(tz=datetime.UTC),
Expand Down
2 changes: 1 addition & 1 deletion ubo_app/side_effects.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ async def replay_recorded_sequence() -> None:

async def check_wifi() -> None:
"""Dispatch the Wi-Fi input action if needed."""
await asyncio.sleep(5)
await asyncio.sleep(10)
logger.info(
'Checking Wi-Fi',
extra={
Expand Down
40 changes: 23 additions & 17 deletions ubo_app/system/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os
import pwd
import subprocess
import sys
import time
import warnings
from pathlib import Path
Expand All @@ -23,25 +24,14 @@ class Service(TypedDict):

name: str
scope: Literal['system', 'user']
enabled: bool


SERVICES: list[Service] = [
{
'name': 'ubo-system',
'scope': 'system',
},
{
'name': 'ubo-update',
'scope': 'system',
},
{
'name': 'ubo-redirect-server',
'scope': 'system',
},
{
'name': 'ubo-app',
'scope': 'user',
},
Service(name='ubo-system', scope='system', enabled=True),
Service(name='ubo-update', scope='system', enabled=True),
Service(name='ubo-hotspot', scope='system', enabled=False),
Service(name='ubo-app', scope='user', enabled=True),
]

uid = pwd.getpwnam(USERNAME).pw_uid
Expand Down Expand Up @@ -151,7 +141,12 @@ def enable_services() -> None:
)
elif service['scope'] == 'system':
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'enable', service['name']],
[
'/usr/bin/env',
'systemctl',
'enable' if service['enabled'] else 'disable',
service['name'],
],
check=True,
)

Expand Down Expand Up @@ -275,3 +270,14 @@ def bootstrap(*, with_docker: bool = False, in_packer: bool = False) -> None:
stdout.flush()

install_audio_driver(in_packer=in_packer)


def main() -> None:
"""Run the bootstrap script."""
bootstrap(
with_docker='--with-docker' in sys.argv,
in_packer='--in-packer' in sys.argv,
)
sys.stdout.write('Bootstrap completed.\n')
sys.stdout.flush()
sys.exit(0)
26 changes: 26 additions & 0 deletions ubo_app/system/hotspot_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Set up the hotspot configuration files."""

import pathlib
import sys

from ubo_app.constants import WEB_UI_HOTSPOT_PASSWORD
from ubo_app.utils.pod_id import get_pod_id
from ubo_app.utils.template_files import copy_templates, restore_backups


def main() -> None:
"""Set up the hotspot configuration files."""
templates_path = pathlib.Path(__file__).parent / 'hotspot_templates'
if sys.argv[1] == 'configure':
copy_templates(
templates_path,
variables={
'SSID': get_pod_id(with_default=True),
'PASSWORD': WEB_UI_HOTSPOT_PASSWORD,
},
)
elif sys.argv[1] == 'restore':
restore_backups(templates_path)
else:
msg = 'Invalid argument'
raise ValueError(msg)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ieee80211n=1
ieee80211ac=1
wpa=2
auth_algs=1
wpa_passphrase=ubo-pod-setup
wpa_passphrase={{PASSWORD}}
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=CCMP
2 changes: 1 addition & 1 deletion ubo_app/system/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ chown -R $USERNAME:$USERNAME "$INSTALLATION_PATH"
chmod -R 700 "$INSTALLATION_PATH"

# Bootstrap the application
UBO_LOG_LEVEL=INFO "$INSTALLATION_PATH/env/bin/bootstrap"${WITH_DOCKER:+ --with-docker}${IN_PACKER:+ --in-packer}
UBO_LOG_LEVEL=INFO "$INSTALLATION_PATH/env/bin/ubo-bootstrap"${WITH_DOCKER:+ --with-docker}${IN_PACKER:+ --in-packer}
echo "Bootstrapping completed"

if [ "$UPDATE" = true ]; then
Expand Down
2 changes: 1 addition & 1 deletion ubo_app/system/install_wm8960.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function install_module {
fi

if [[ -e /usr/src/$mod-$ver || -e /var/lib/dkms/$mod/$ver ]]; then
dkms remove --force -m $mod -v $ver --all
dkms remove --force -m $mod -v $ver --all || true
rm -rf /usr/src/$mod-$ver
fi
mkdir -p /usr/src/$mod-$ver
Expand Down
2 changes: 0 additions & 2 deletions ubo_app/system/services/ubo-app.service.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ Type=simple
Environment="UBO_SERVICES_PATH=/home/{{USERNAME}}/ubo_services/"
ExecStart={{INSTALLATION_PATH}}/env/bin/ubo
WorkingDirectory={{INSTALLATION_PATH}}
StandardOutput=inherit
StandardError=inherit
Restart=always
RestartPreventExitStatus=255
TimeoutStopSec=60s
Expand Down
39 changes: 39 additions & 0 deletions ubo_app/system/services/ubo-hotspot.service.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[Unit]
Description=Ubo Hotspot Service

[Service]
Type=simple
User=root
ExecStartPre=/bin/sh -c 'echo "Disabling power save mode on wlan0"'
ExecStartPre=/usr/bin/env iw wlan0 set power_save off
ExecStartPre=/bin/sh -c 'echo "Unblocking wifi"'
ExecStartPre=/usr/bin/env rfkill unblock wifi
ExecStartPre=/bin/sh -c 'echo "Writing configuration files"'
ExecStartPre=/opt/ubo/env/bin/ubo-hotspot-config configure
ExecStartPre=/bin/sh -c 'echo "Restarting dhcpcd service"'
ExecStartPre=/bin/systemctl restart dhcpcd.service
ExecStartPre=/bin/sh -c 'echo "Restarting dnsmasq service"'
ExecStartPre=/bin/systemctl restart dnsmasq.service
ExecStartPre=/bin/sh -c 'echo "Unmasking hostapd service"'
ExecStartPre=/bin/systemctl unmask hostapd.service
ExecStartPre=/bin/sh -c 'echo "Enabling hostapd service"'
ExecStartPre=/bin/systemctl enable hostapd.service
ExecStartPre=/bin/sh -c 'echo "Starting Ubo Hotspot Service"'
ExecStartPre=/bin/systemctl start hostapd.service
ExecStartPre=/bin/sh -c 'echo "Starting Redirect Server"'
ExecStart=/opt/ubo/env/bin/ubo-redirect-server
ExecStopPost={{INSTALLATION_PATH}}/env/bin/ubo-hotspot-config restore
ExecStopPost=/bin/sh -c 'echo "# Default dhcpcd configuration\n# Leave this blank for automatic configuration" > /etc/dhcpcd.conf'
ExecStartPre=/bin/sh -c 'echo "Stopping Ubo Hotspot Service"'
ExecStopPost=/bin/systemctl stop hostapd.service
ExecStartPre=/bin/sh -c 'echo "Disabling hostapd service"'
ExecStopPost=/bin/systemctl disable hostapd.service
ExecStartPre=/bin/sh -c 'echo "Masking hostapd service"'
ExecStopPost=/bin/systemctl mask hostapd.service
ExecStartPre=/bin/sh -c 'echo "Stopping dnsmasq service"'
ExecStopPost=/bin/systemctl stop dnsmasq.service
ExecStartPre=/bin/sh -c 'echo "Restarting dhcpcd service"'
ExecStopPost=/bin/systemctl restart dhcpcd.service
WorkingDirectory=/opt/ubo
KillMode=control-group
Restart=always
12 changes: 0 additions & 12 deletions ubo_app/system/services/ubo-redirect-server.service.tmpl

This file was deleted.

2 changes: 0 additions & 2 deletions ubo_app/system/services/ubo-system.service.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ Environment=INSTALLATION_PATH={{INSTALLATION_PATH}}
Environment=USERNAME={{USERNAME}}
ExecStart={{INSTALLATION_PATH}}/env/bin/ubo-system
WorkingDirectory={{INSTALLATION_PATH}}
StandardOutput=inherit
StandardError=inherit
KillMode=control-group
Restart=always
RestartPreventExitStatus=255
Expand Down
1 change: 0 additions & 1 deletion ubo_app/system/services/ubo-update.service.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ ExecStartPre=/bin/bash -c '[[ -e /opt/ubo/_update/update_is_ready.lock ]]'
ExecStartPre=rm -f {{INSTALLATION_PATH}}/app_ready
ExecStart={{INSTALLATION_PATH}}/_update/install.sh --update --wait-for-app
RemainAfterExit=no
Restart=yes
RestartSec=5
44 changes: 2 additions & 42 deletions ubo_app/system/system_manager/hotspot.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,17 @@
"""Set up a hotspot on the UBO."""

import pathlib
import subprocess

from ubo_app.logger import get_logger
from ubo_app.utils.pod_id import get_pod_id
from ubo_app.utils.template_files import copy_templates, restore_backups

logger = get_logger('system-manager')


def _start() -> str:
logger.info('Starting the hotspot')
templates_path = pathlib.Path(__file__).parent / 'hotspot_templates'
copy_templates(
templates_path,
variables={'SSID': get_pod_id(with_default=True)},
)
try:
subprocess.run( # noqa: S603
['/usr/bin/env', 'iw', 'wlan0', 'set', 'power_save', 'off'],
check=True,
)
subprocess.run(['/usr/bin/env', 'rfkill', 'unblock', 'wifi'], check=True) # noqa: S603
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'restart', 'dhcpcd'],
check=True,
)
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'restart', 'dnsmasq'],
check=True,
)
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'unmask', 'hostapd'],
check=True,
)
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'enable', 'hostapd'],
check=True,
)
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'start', 'hostapd'],
check=True,
)
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'start', 'ubo-redirect-server'],
['/usr/bin/env', 'systemctl', 'start', 'ubo-hotspot'],
check=True,
)
except subprocess.CalledProcessError:
Expand All @@ -58,18 +25,11 @@ def _start() -> str:

def _stop() -> str:
logger.info('Stopping the hotspot')
templates_path = pathlib.Path(__file__).parent / 'hotspot_templates'
restore_backups(templates_path)
try:
subprocess.run( # noqa: S603
['/usr/bin/env', 'systemctl', 'stop', 'ubo-redirect-server'],
['/usr/bin/env', 'systemctl', 'stop', 'ubo-hotspot'],
check=False,
)
subprocess.run(['/usr/bin/env', 'systemctl', 'stop', 'hostapd'], check=False) # noqa: S603
subprocess.run(['/usr/bin/env', 'systemctl', 'disable', 'hostapd'], check=False) # noqa: S603
subprocess.run(['/usr/bin/env', 'systemctl', 'mask', 'hostapd'], check=False) # noqa: S603
subprocess.run(['/usr/bin/env', 'systemctl', 'stop', 'dnsmasq'], check=False) # noqa: S603
subprocess.run(['/usr/bin/env', 'systemctl', 'restart', 'dhcpcd'], check=False) # noqa: S603
except subprocess.CalledProcessError:
logger.exception('Failed to stop the hotspot properly')
return 'failed'
Expand Down
Loading

0 comments on commit a563c3e

Please sign in to comment.