diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md index 4ad086d..2ca6b75 100644 --- a/IMPLEMENTATION.md +++ b/IMPLEMENTATION.md @@ -1,19 +1,31 @@ # Implementation -This document provides high-level implementation details of the RRM service. +This document provides high-level implementation details for the RRM service. + +## Overview + +

+ +

## Framework -`Launcher` is the main class, which creates *clients* and then passes them to -the `RRM` class to run all *modules* (details below). Many of these will run in -their own threads and implement the standard `Runnable` interface. -The service configuration model is specified in the `RRMConfig` class, which can -be provided either via environment variables or as a JSON-serialized file. When -using the static file option, any new/missing fields are appended automatically. -All fields are documented in Javadoc. +### Initialization +`Launcher` is the main class, exposing a command-line interface implemented +using [picocli]. The launcher creates *clients* and then passes them to the +`RRM` class to start all *modules* (details below). Typically, each module is an +event loop which runs in its own thread, implementing the Java `Runnable` +interface. +The service configuration is defined in the `RRMConfig` class, and can be +provided either via environment variables or as a JSON-serialized file. Default +values are used for any omitted fields. When using the static file option, any +new/missing fields are appended automatically. All fields are documented in +Javadoc. + +### Data Structures The device topology, `DeviceTopology`, is specified as groupings of APs into disjoint "RF zones" (default `topology.json`). For example: -```JSON +```json { "": ["", ""], "building-A": ["aaaaaaaaaa01", "aaaaaaaaaa02"] @@ -28,24 +40,49 @@ following layers from least to greatest precedence: * Per-zone config (`zoneConfig`) * Per-AP config (`apConfig`) +`DeviceDataManager` wraps all operations for the device topology and device +configuration, and enables safe concurrent access. + +### Logging Logging is handled using [SLF4J]/[Log4j] and configured in -`src/main/resources/log4j.properties`. +`src/main/resources/log4j.properties`. Output is written to console as well as +rotated log files. + +### Versioning +The artifact version is defined in `pom.xml` and should match the OpenAPI +document version (see `ApiServer` annotations). During Maven builds, the version +string is written to `src/main/resources-filtered/version.txt`, and additional +metadata can also be appended via the property `appendVersionString`. During +runtime, version information can be accessed via `VersionProvider`. ## Clients The *clients* implement connections to external services. -### uCentral Client -`UCentralClient` implements OpenAPI HTTP client calls to the [uCentralGw] and -[uCentralSec] services using [Unirest]. Where possible, request/response models -are defined in the package `com.facebook.openwifirrm.ucentral.gw.models` and -serialized/deserialized using [Gson]. +### uCentral OpenAPI +`UCentralClient` implements OpenAPI HTTP client calls to other uCentral services +(ex. [uCentralGw], [uCentralSec], [owprov]) using [Unirest]. Most request and +response schemas are defined in a corresponding "models" subpackage and are +serialized/deserialized as JSON using [Gson]. -### uCentral Kafka Consumer -`UCentralKafkaConsumer` implements the [Apache Kafka] consumer for uCentral -topics, and passes data to other modules via listener interfaces. This is -wrapped by `KafkaConsumerRunner` to handle graceful shutdown. +The client supports two modes: +* **Private endpoints:** When deployed in a cluster with other OpenWiFi + services, private service URLs are learned from Kafka and requests are sent + with API keys (i.e. `X-API-KEY` header). +* **Public endpoints:** Mainly for development purposes, public service URLs are + learned from [uCentralSec] and requests are sent with a Bearer token (i.e. + `Authorization` header) obtained via login using configured credentials. -### Database Client +### uCentral Kafka +`KafkaRunner` wraps the following [Apache Kafka] clients, handling the run loop +and graceful shutdown: +* `UCentralKafkaConsumer` implements the Kafka consumer for OpenWiFi topics, and + passes data (ex. device state, wifi scan results, system endpoints) to other + modules via listener interfaces. +* `UCentralKafkaProducer` implements the Kafka producer, which is responsible + for periodically pushing system events required for discoverability by other + OpenWiFi services. + +### RRM Database `DatabaseManager` handles JDBC connection details for the RRM database and exposes methods for specific database operations. It uses the [MySQL Connector/J] driver and [HikariCP] for connection pooling. @@ -58,15 +95,30 @@ The *modules* implement the service's application logic. * Issues WiFi scan commands periodically and handles responses * Registers Kafka listeners to write records into the RRM database * Registers config listeners to configure the stats interval in OpenWiFi devices +* Periodically queries capabilities for OpenWiFi devices ### Config Manager -`ConfigManager` periodically sends config changes to OpenWiFi devices. Any +`ConfigManager` sends config changes to OpenWiFi devices (via [uCentralGw]). Any desired config changes are applied via listener interfaces, including the output -of RRM algorithms. +of RRM algorithms. Device config updates are either applied periodically (when +needed) or only triggered upon events (ex. RRM algorithm execution, API calls), +depending on RRM service configuration. To minimize polling frequency since +device config updates are rare, this thread has a long default sleep time and is +interrupted by other threads when a config update is needed. + +`UCentralApConfiguration` wraps the raw device configuration JSON and provides +various access methods. ### Modeler -`Modeler` subscribes to uCentral device state and wifi scan data, then prepares -it for use by an optimizer. +`Modeler` subscribes to raw uCentral data, then prepares it for use by an +optimizer. The "model" is defined in `DataModel` and includes the following +information for each device: +* Recent wifi scan results +* Statistics (or "state") +* Configuration (or "status") +* Capabilities + +Additional data processing utilities are contained in `ModelerUtils`. ### API Server `ApiServer` is an OpenAPI HTTP server written using [Spark], exposing the @@ -77,23 +129,42 @@ following endpoints: [Swagger Core] * `/api/v1/` - RRM API methods -### owprov Monitor -`ProvMonitor` handles sync with the owprov service when it is desirable to use -their topology ("venues") and certain device configuration fields. +The OpenWiFi SDK dictates several API endpoints which must be implemented by +every service, as well as endpoints specific to RRM providers. They are both +marked here under the "SDK" tag. -### Scheduler +Depending on RRM service configuration, the API server may also enable CORS +selectively or globally, HTTP basic auth, and/or OpenWiFi auth (via Bearer +tokens or internal API keys). + +### Provisioning Monitor +`ProvMonitor` syncs device topology ("venues") and configuration with the +OpenWiFi Provisioning service (when enabled). + +### RRM Scheduler `RRMScheduler` uses the [Quartz Job Scheduler] to schedule RRM algorithms to run -per zone with different intervals and parameters. +per zone with different intervals and parameters. The schedules are specified in +the device configuration as `RRMSchedule` and are applied only at the zone and +network layers. ## Optimizers -The *optimizers* implement the RRM algorithms, which are described in +The *optimizers* implement the RRM algorithms, and are described in detail in [ALGORITHMS.md](ALGORITHMS.md). +The `RRMAlgorithm` class provides a common entry point for all algorithm +invocations. The general logic is as follows: +* Identify the algorithm type (`AlgorithmType`), implementation class ("mode"), + and any algorithm arguments +* Take the current data model snapshot from `Modeler` as input +* Compute the new device configs, then save and push them via `ConfigManager` + +[picocli]: https://picocli.info/ [SLF4J]: http://www.slf4j.org/ [Log4j]: https://logging.apache.org/log4j/ [uCentralGw]: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw [uCentralSec]: https://github.com/Telecominfraproject/wlan-cloud-ucentralsec +[owprov]: https://github.com/Telecominfraproject/wlan-cloud-owprov [Unirest]: https://github.com/kong/unirest-java [Gson]: https://github.com/google/gson [Apache Kafka]: https://kafka.apache.org/ diff --git a/README.md b/README.md index d05f832..34ccacf 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ Unit tests are written using [JUnit 5]. ``` $ java -jar openwifi-rrm.jar [-h] ``` -The command-line interface is implemented using [picocli]. To start the service, use the `run` command while providing configuration via either environment variables (`--config-env`) or a static JSON file @@ -55,4 +54,3 @@ See [LICENSE](LICENSE). [Apache Maven]: https://maven.apache.org/ [JUnit 5]: https://junit.org/junit5/ -[picocli]: https://picocli.info/ diff --git a/diagram.svg b/diagram.svg new file mode 100644 index 0000000..14e6601 --- /dev/null +++ b/diagram.svg @@ -0,0 +1,4 @@ + + + +
OpenWiFi Cloud
OpenWiFi Cloud
Microservices
Microservices
Datastores
Datastores
OpenWiFi APs
OpenWiFi APs
Gateway
Gateway
Kafka
Kafka
Security
Security
Provisioning
Provisioning
MySQL
MySQL
RRM
RRM
RRM
RRM
Data Collector
Data Collector
API Server
API Server
Config Manager
Config Manager
RRM Scheduler
RRM Scheduler
Provisioning Monitor
Provisioning Monitor
Modeler
Modeler
Optimizers
Optimizers
Text is not SVG - cannot display
\ No newline at end of file