Skip to content

Scale setup script to bootstrap N simulated Edge instances#65

Open
amalbet wants to merge 7 commits intofeature/rrd4j-fixfrom
feature/multi-edge
Open

Scale setup script to bootstrap N simulated Edge instances#65
amalbet wants to merge 7 commits intofeature/rrd4j-fixfrom
feature/multi-edge

Conversation

@amalbet
Copy link

@amalbet amalbet commented Mar 10, 2026

Summary

  • Add --edges N flag to setup.sh (default: 1, max: 9) to bootstrap N independent Edge instances
  • Generate per-edge config directories from the template with unique UUIDs, service.pid values, and apikeys
  • Generate docker-compose.override.yml with N edge services on unique ports (edge i → 8{i}80/8{i}85)
  • Register each edge in Odoo DB with unique apikey written to both config file and database
  • Fix existing bug: template had apikey="DEMO_API_KEY" but setup.sh hardcoded a different value
  • Extend verification to check all N edges for Scheduler + RRD4j connectivity

Closes #64

Changes

  • setup.sh: New helper functions (generate_apikey, generate_edge_config, generate_compose_override, generate_uuid, sedi), argument parsing for --edges N, loops for DB registration/verification/restart
  • .gitignore: Ignore generated config-edge*/ dirs and docker-compose.override.yml

Bug fixes included (discovered during integration testing)

Critical: Backend Odoo UID was wrong (odooUid=1odooUid=2)

The backend's Metadata/Odoo.config had odooUid=I"1" — the Odoo __system user, which cannot make XML-RPC calls. This caused Access Denied errors on every edge metadata sync, making edges connected but invisible in the OpenEMS UI. Fixed to odooUid=I"2" (the admin user). This affects all deployments, not just multi-edge.

Edge device INSERT missing active=true

Odoo's ORM has an implicit active=True filter — records without it are treated as "archived" and hidden from all queries. The raw SQL INSERT for edge registration didn't set this field, so edge1/edge2 were invisible despite being fully connected at the backend level. Also added name_number for proper display ordering.

Port 8075 not exposed

The B2B REST API port (used by the billing engine for meter discovery) was missing from the docker-compose backend port mappings.

Setup script hardening

  • SIGPIPE in generate_apikey: tr </dev/urandom | head -c 20 exits 141 with pipefail; fixed with subshell set +o pipefail
  • Odoo password race condition: Replaced sleep 5 with a 12-attempt retry loop — Odoo takes 15-30s to accept XML-RPC on first boot
  • psql default database: Added -d postgres for pg_database catalog query (no odoo database exists by default)
  • Admin user-role assignment: Insert into openems_device_user_role so edges appear in the UI

Port scheme

Edge Felix Console Websocket
edge0 localhost:8080 localhost:8085
edge1 localhost:8180 localhost:8185
edge2 localhost:8280 localhost:8285
... 8{i}80 8{i}85

Test plan

  • ./setup.sh (no flag) — bootstraps 1 edge, identical behavior to before
  • ./setup.sh --edges 3 — generates 3 config dirs, 3 services in override, 3 DB entries
  • Verify all edges visible in OpenEMS UI (not just edge0)
  • Verify each edge connects to backend (check logs for Edge.Websocket)
  • Verify no Access Denied errors in backend logs
  • Verify config filenames match service.pid in all generated configs
  • Verify --edges 0, --edges 10, --edges abc are rejected with clear errors
  • Verify template dir openems-edge/config.d/ is not modified

Merge order

PRs must merge bottom-up: #59#60#63#65

Dependencies

🤖 Generated with Claude Code

amalbet and others added 7 commits March 9, 2026 12:27
- Add InfluxDB 1.8 container with healthcheck and named volume
- Replace Dummy timedata with InfluxDB provider (timedata0.config)
- Remove embedded InfluxDB from backend Dockerfile (now separate container)
- Volume-mount edge config.d to persist Felix configs across restarts
- Fix Metadata/Odoo.config to use Docker service names (db, odoo16)
- Fix edge backend controller apikey to match Odoo device registration
- Include Felix runtime config updates (Core, Ess, Evcs, DynamicBindings)

Closes #56, closes #57

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add --edges N flag (default: 1) to setup.sh that generates per-edge
config directories, unique API keys, and a docker-compose.override.yml
with N edge services.

Key changes:
- Parse --edges N flag with validation (1-9 range, port scheme limit)
- generate_edge_config: copies template, regenerates UUIDs for factory
  configs, updates service.pid and LDAP target filters, writes apikey
- generate_compose_override: creates override.yml disabling the default
  edge service and adding N uniquely-ported edge services
- DB registration loops over N edges with generated apikeys
- Verification and summary output extended for N edges
- Portable sedi() helper for macOS/GNU sed compatibility
- Fixes existing apikey mismatch bug (DEMO_API_KEY vs hardcoded key)

Closes #64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rden Odoo init

- Expose port 8075 (B2B REST API) for meter discovery from billing engine
- Assign admin user role to each edge in openems_device_user_role so all
  edges appear in the OpenEMS UI (not just edge0 from demo data)
- Fix generate_apikey SIGPIPE: disable pipefail in subshell for tr|head pipe
- Fix psql default database: use -d postgres for pg_database catalog query
- Replace sleep 5 with retry loop for Odoo XML-RPC password change

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Odoo __system user (uid 1) cannot make XML-RPC calls, causing
"Access Denied" errors when the backend tries to update edge metadata.
The admin user (uid 2) has proper permissions for the openems.device model.

This was the root cause of edges being connected but not visible in the
OpenEMS UI — the backend couldn't sync connection state to Odoo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Odoo's ORM filters out records where active is NULL (treats as archived).
Raw SQL inserts were missing this field, making edge1/edge2 invisible to
the OpenEMS UI even though they were connected at the backend level.

Also set name_number (used by Odoo for display ordering).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant