A Python service that connects to LAVA CI server instances via websockets, monitors device health changes, and automatically creates/updates Jira Service Management tickets.
- Bad / Maintenance / Retired health → creates a Jira ticket
- Good health → adds a recovery comment to the existing ticket
- Connects to multiple LAVA servers concurrently
- Reconnects automatically with exponential backoff
- Optional BetterStack heartbeat monitoring and Sentry error tracking
- Image: Ubuntu 24.04 LTS
- Plan: $3.50/mo (512 MB RAM, 1 vCPU) is sufficient
- Enable the Static IP option so the address doesn't change on reboot
sudo apt update && sudo apt install -y python3 python3-venv gitThe 512 MB plan has no swap by default, and Ubuntu ships the fwupd
firmware-update daemon, which is useless on a VM but can balloon to
150+ MB of RAM. On a 512 MB box this repeatedly triggers the kernel
OOM killer, which can take networking down with it — surfacing as
StatusCheckFailed_Instance alarms even though the OS is still "up".
Disable fwupd (there is no physical firmware to update on a VM):
sudo systemctl stop fwupd
sudo systemctl mask fwupd fwupd-refresh.service fwupd-refresh.timerAdd 1 GB of swap so any future memory spike degrades gracefully instead of triggering a global OOM:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.confOptionally cap the journal so logs can't fill a small disk — edit
/etc/systemd/journald.conf, set SystemMaxUse=200M under [Journal],
then sudo systemctl restart systemd-journald.
Verify:
free -h # should show 1.0Gi of swap
systemctl is-active fwupd # should be inactive/unknownsudo mkdir -p /opt/lava-event-listener
sudo chown $USER:$USER /opt/lava-event-listener
git clone <YOUR_REPO_URL> /opt/lava-event-listenerOr copy the files manually with scp:
scp -r ./* user@<LIGHTSAIL_IP>:/opt/lava-event-listener/cd /opt/lava-event-listener
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtsudo mkdir -p /etc/lava-event-listener
sudo cp config.yaml.example /etc/lava-event-listener/config.yaml
sudo chmod 600 /etc/lava-event-listener/config.yaml
sudo nano /etc/lava-event-listener/config.yamlEdit the config with your actual values:
lava_servers— your LAVA server URLs (and optional credentials)jira.url— your Jira Cloud URL (e.g.https://yourorg.atlassian.net)jira.email— the email associated with the API tokenjira.api_token— generate one at https://id.atlassian.com/manage-profile/security/api-tokensjira.project_key— the Jira project key (e.g.LAVAOPS)jira.issue_type— the issue type to create (e.g.Service Request)sentry.dsn— (optional) your Sentry DSNbetterstack.heartbeat_url— (optional) your BetterStack heartbeat URL
sudo useradd --system --no-create-home --shell /usr/sbin/nologin lava-listenersudo mkdir -p /var/lib/lava-event-listener
sudo chown lava-listener:lava-listener /var/lib/lava-event-listenerMake sure the state_file in your config points here:
state_file: "/var/lib/lava-event-listener/state.json"sudo chown root:lava-listener /etc/lava-event-listener/config.yaml
sudo chmod 640 /etc/lava-event-listener/config.yamlsudo cp lava-event-listener.service /etc/systemd/system/
sudo systemctl daemon-reloadsudo systemctl enable lava-event-listener
sudo systemctl start lava-event-listenersudo systemctl status lava-event-listener
sudo journalctl -u lava-event-listener -fYou should see log output like:
INFO [__main__] Starting LAVA Event Listener with 1 server(s): linaro-production
INFO [lava_event_listener.listener] [linaro-production] Connecting to wss://validation.linaro.org/ws/
INFO [lava_event_listener.listener] [linaro-production] Connected.
# View live logs
sudo journalctl -u lava-event-listener -f
# Restart after config changes
sudo systemctl restart lava-event-listener
# Stop the service
sudo systemctl stop lava-event-listener
# Check the current state file
cat /var/lib/lava-event-listener/state.jsonOn a small instance this is almost always memory-related. The OS often keeps running (and logging locally) while networking is starved, so it looks "up" but fails its reachability check. If you reboot the instance to recover, remember the crash evidence is in the previous boot:
# Look at the PREVIOUS boot, not the current one
sudo journalctl -b -1 -k --no-pager | grep -i "killed process"Any Out of memory: Killed process ... (fwupd) lines mean you still
need Step 2a (disable fwupd + add swap). Check current memory headroom
and the biggest consumers with:
free -h
ps aux --sort=-%rss | headThe systemd unit also sets MemoryHigh/MemoryMax so that if the
listener itself ever runs away, systemd restarts just the service
rather than letting the whole box OOM.
cd /opt/lava-event-listener
source .venv/bin/activate
python -m lava_event_listener.main -c config.yaml