mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Multiple updates
- Support to notify about external uci changes - Call uci_to_dmmap sync function on uci changes notification - Documentation update
This commit is contained in:
parent
2cd0a1ef6b
commit
786863cf0e
7 changed files with 415 additions and 230 deletions
|
|
@ -890,6 +890,15 @@ static void perform_uci_sync_op(struct uloop_timeout *timeout)
|
||||||
dynamic_obj[i].uci_sync_handler();
|
dynamic_obj[i].uci_sync_handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct bbfdm_context *bbfdm_ctx = container_of(timeout, struct bbfdm_context, sync_timer);
|
||||||
|
if (bbfdm_ctx == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bbfdm_refresh_references(BBFDM_BOTH, bbfdm_ctx->config.out_name)) {
|
||||||
|
BBF_ERR("Failed to refresh instance data base");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bbfdm_apply_event_cb(struct ubus_context *ctx __attribute__((unused)),
|
static void bbfdm_apply_event_cb(struct ubus_context *ctx __attribute__((unused)),
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ List of utilities:
|
||||||
|
|
||||||
1. bbf.diag
|
1. bbf.diag
|
||||||
2. bbf.secure
|
2. bbf.secure
|
||||||
3. bbf.config
|
3. bbf_configd
|
||||||
|
|
||||||
## bbf.diag utility
|
## bbf.diag utility
|
||||||
|
|
||||||
|
|
@ -67,82 +67,349 @@ But storing Secured parameters in plain text in uci/filesystem is bit of a secur
|
||||||
|
|
||||||
A how to use guide for bbf.secure available [here](https://dev.iopsys.eu/feed/iopsys/-/tree/devel/bbfdm?ref_type=heads#bbf_obfuscation_key)
|
A how to use guide for bbf.secure available [here](https://dev.iopsys.eu/feed/iopsys/-/tree/devel/bbfdm?ref_type=heads#bbf_obfuscation_key)
|
||||||
|
|
||||||
## bbf.config utility
|
## bbf_configd
|
||||||
|
|
||||||
|
The BBF Config daemon (`bbf_configd`) is a configuration management system designed for device management. It provides UBUS-based configuration commit and revert operations with service monitoring and reload capabilities.
|
||||||
|
|
||||||
OpenWRT way of reloading services with `ubus call uci commit '{"name":"<uci_name>"}` does not perfectly fits with datamodel requirements. It send a trigger via rpcd to procd by using this ubus call which returns instantly, internally procd reloads for all the services which has a reload dependency configured on that specific uci.
|
OpenWRT way of reloading services with `ubus call uci commit '{"name":"<uci_name>"}` does not perfectly fits with datamodel requirements. It send a trigger via rpcd to procd by using this ubus call which returns instantly, internally procd reloads for all the services which has a reload dependency configured on that specific uci.
|
||||||
Sometimes, there is a good amount of delay in trigger and actual service reload.
|
Sometimes, there is a good amount of delay in trigger and actual service reload.
|
||||||
|
bbf_configd solves that by adding an in-build reload monitoring functionality which get the list of impacted services and then monitor for PID change for the services with a timeout of 10 sec, with this we make sure Higher layer application(icwmp/obsupa) waits for the application before processing more command.
|
||||||
|
|
||||||
Bbf.config solves that by adding an in-build reload monitoring functionality which get the list of impacted services and then monitor for PID change for the services with a timeout of 10 sec, with this we make sure Higher layer application(icwmp/obsupa) waits for the application before processing more command.
|
### Architecture
|
||||||
|
|
||||||
Currently have two variants of bbf.config, which can be enabled with below compile time configs
|
- **Purpose**: Daemon implementing UBUS interface for configuration management
|
||||||
|
- **Key Features**:
|
||||||
|
- Configuration commit/revert operations
|
||||||
|
- Service monitoring and validation
|
||||||
|
- Event handling for configuration changes
|
||||||
|
- Critical service detection and monitoring
|
||||||
|
|
||||||
1. CONFIG_BBF_CONFIGMNGR_SCRIPT_BACKEND => Simple rpcd script based backend
|
### UBUS Interface
|
||||||
2. CONFIG_BBF_CONFIGMNGR_C_BACKEND => C based application backend with PID monitoring (default)
|
|
||||||
|
|
||||||
### bbf.config Supported methods
|
#### Methods
|
||||||
|
|
||||||
`bbf.config` provides several methods for managing and monitoring configuration changes in services. These methods can be accessed using the ubus command.
|
##### `commit`
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ubus -v list bbf.config
|
|
||||||
'bbf.config' @da2cc0d9
|
|
||||||
"commit":{"services":"Array","proto":"String","reload":"Boolean"}
|
"commit":{"services":"Array","proto":"String","reload":"Boolean"}
|
||||||
|
- **Description**: Commits configuration changes and reloads affected services
|
||||||
|
- **Parameters**:
|
||||||
|
- `services` (array): List of specific services to commit
|
||||||
|
- `proto` (string): Protocol type ("both", "cwmp", "usp")
|
||||||
|
- `reload` (bool): Whether to reload services after commit
|
||||||
|
- **Response**: Status message indicating success or failure
|
||||||
|
|
||||||
|
##### `revert`
|
||||||
|
|
||||||
"revert":{"services":"Array","proto":"String","reload":"Boolean"}
|
"revert":{"services":"Array","proto":"String","reload":"Boolean"}
|
||||||
"changes":{"services":"Array","proto":"String","reload":"Boolean"}
|
- **Description**: Reverts uncommitted configuration changes
|
||||||
|
- **Parameters**:
|
||||||
|
- `services` (array): List of specific services to revert
|
||||||
|
- `proto` (string): Protocol type
|
||||||
|
- **Response**: Status message indicating success or failure
|
||||||
|
|
||||||
|
#### Events
|
||||||
|
|
||||||
|
##### `bbfdm.apply`
|
||||||
|
- **Trigger**: Sent after configuration commits
|
||||||
|
- **Payload**: Protocol information and list of changed UCI files
|
||||||
|
- **Purpose**: Notifies components about applied configuration changes to perform synchronization if required
|
||||||
|
|
||||||
|
### Configuration Management
|
||||||
|
|
||||||
|
#### Protocol Support
|
||||||
|
The daemon supports multiple protocols with dedicated configuration directories:
|
||||||
|
|
||||||
|
| Protocol | Config Directory | DMMAP Directory | Index |
|
||||||
|
|----------|------------------|-----------------|-------|
|
||||||
|
| both | `/tmp/bbfdm/.bbfdm/config/` | `/tmp/bbfdm/.bbfdm/dmmap/` | 0 |
|
||||||
|
| cwmp | `/tmp/bbfdm/.cwmp/config/` | `/tmp/bbfdm/.cwmp/dmmap/` | 1 |
|
||||||
|
| usp | `/tmp/bbfdm/.usp/config/` | `/tmp/bbfdm/.usp/dmmap/` | 2 |
|
||||||
|
|
||||||
|
#### UCI Integration
|
||||||
|
- **Standard UCI Path**: `/etc/config/`
|
||||||
|
- **DMMAP UCI Path**: `/etc/bbfdm/dmmap/`
|
||||||
|
- **Operations**: Commit, revert, and list configurations
|
||||||
|
- **Persistence**: Changes saved to protocol-specific directories
|
||||||
|
|
||||||
|
### Service Management
|
||||||
|
|
||||||
|
#### Service Monitoring
|
||||||
|
- **Validation**: Checks if services are properly reloaded after configuration changes
|
||||||
|
- **Criteria**:
|
||||||
|
- Instance status changes (running/stopped)
|
||||||
|
- Process ID (PID) changes
|
||||||
|
- Instance count changes
|
||||||
|
- **Timeout**: Configurable wait time for service reload validation
|
||||||
|
|
||||||
|
#### Critical Services
|
||||||
|
- **Definition File**: `/etc/bbfdm/critical_services.json`
|
||||||
|
- **Purpose**: Identifies services that require monitoring during configuration changes
|
||||||
|
- **Effect**: Enables asynchronous request handling with validation
|
||||||
|
|
||||||
|
#### External Handlers
|
||||||
|
- **Configuration Path**: `/etc/bbfdm/services/`
|
||||||
|
- **Types**: DMMAP and UCI handlers
|
||||||
|
- **Default Handler**: `/etc/bbfdm/bbf_default_reload.sh`
|
||||||
|
- **Purpose**: Custom scripts for service-specific configuration handling
|
||||||
|
|
||||||
|
##### Example and Explanation
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"daemon": {
|
||||||
|
"enable": "1",
|
||||||
|
"service_name": "xxxx",
|
||||||
|
"unified_daemon": true,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"parent_dm": "Device.",
|
||||||
|
"object": "XXXX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"config": {
|
||||||
|
"loglevel": "3"
|
||||||
|
},
|
||||||
|
"apply_handler": {
|
||||||
|
"uci": [
|
||||||
|
{
|
||||||
|
"file": [
|
||||||
|
"xxxx",
|
||||||
|
"yyyy"
|
||||||
|
],
|
||||||
|
"external_handler": "/etc/xxxx/bbf_config_reload.sh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dmmap": [
|
||||||
|
{
|
||||||
|
"file": [
|
||||||
|
"zzzz"
|
||||||
|
],
|
||||||
|
"external_handler": "/etc/xxxx/bbf_dmmap_handler.sh"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
#### bbf.config commit method:
|
|
||||||
|
|
||||||
This method commits configuration changes to the specified services based on the given `proto` option (protocol). It reloads services according to `reload` option but handles critical services differently.
|
- If external component asks to commit UCI file 'xxxx' or 'yyyy' or both then this module will commit the changes from protocol based UCI save directory to the standard UCI and will execute the script provided in the `external_handler` field. If no external handler is provided then it will execute default reload handler script `/etc/bbfdm/bbf_default_reload.sh`.
|
||||||
|
- If there is any change in the dmmap file `zzzz` and a commit request has been received then this module will commit the changes in standard dmmap file from the protocol based dmmap directory and if any external handler is given like in above example then it will execute that script. Services may use this handler script to perform any desired tasks on changes in the dmmap file.
|
||||||
|
|
||||||
The Critical services are defined in `/etc/bbfdm/critical_services.json` file.
|
### Operational Flow
|
||||||
- If a service is critical, the process waits until the service's timeout expires or the service's PID changes and then it does reload the service.
|
|
||||||
- Non-critical services are reloaded immediately.
|
|
||||||
|
|
||||||
Critical Services File
|
#### Commit Operation
|
||||||
|
1. Parse incoming UBUS request parameters
|
||||||
|
2. Load critical services configuration
|
||||||
|
3. If monitoring required, capture current service states
|
||||||
|
4. Process configuration changes:
|
||||||
|
- Specific services: Process only requested services
|
||||||
|
- All services: Process all modified configurations
|
||||||
|
5. Execute external handlers for affected services if any otherwise default handler
|
||||||
|
6. If monitoring enabled:
|
||||||
|
- Defer response and validate service reloads
|
||||||
|
- Send response after validation or timeout
|
||||||
|
7. Send bbfdm.apply event with list of all modified UCI names
|
||||||
|
8. Clean up allocated resources
|
||||||
|
|
||||||
The following file defines critical services for each protocol:
|
#### Revert Operation
|
||||||
|
1. Parse incoming UBUS request parameters
|
||||||
|
2. Revert UCI changes for specified or all services
|
||||||
|
4. Return immediate success response
|
||||||
|
|
||||||
|
#### Flow Diagram
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A[Start bbf_configd] --> B[Parse command line args]
|
||||||
|
B --> C[Initialize ulog & uloop]
|
||||||
|
C --> D[Connect to UBUS]
|
||||||
|
D --> E[Load critical services JSON]
|
||||||
|
E --> F[Load apply handlers from /etc/bbfdm/services]
|
||||||
|
F --> G[Register UBUS object 'bbf.config']
|
||||||
|
G --> H[Register event handler 'bbf.config.notify']
|
||||||
|
H --> I[Enter uloop_run - Wait for requests]
|
||||||
|
|
||||||
|
I --> J{Incoming Request}
|
||||||
|
|
||||||
|
J -->|commit| K[bbf_config_commit_handler]
|
||||||
|
J -->|revert| L[bbf_config_revert_handler]
|
||||||
|
J -->|notify event| M[receive_notify_event]
|
||||||
|
|
||||||
|
%% Commit Handler Flow
|
||||||
|
K --> K1[Parse blob message]
|
||||||
|
K1 --> K2[Allocate async request structure]
|
||||||
|
K2 --> K3[Determine protocol index from 'proto']
|
||||||
|
K3 --> K4[Get monitor status for critical services]
|
||||||
|
K4 --> K5{Monitor required?}
|
||||||
|
|
||||||
|
K5 -->|Yes| K6[Get current service info via UBUS]
|
||||||
|
K5 -->|No| K7[Process services]
|
||||||
|
|
||||||
|
K6 --> K7
|
||||||
|
K7 --> K8{Services specified?}
|
||||||
|
|
||||||
|
K8 -->|Yes| K9[commit specified configs]
|
||||||
|
K8 -->|No| K10[commit all config changes]
|
||||||
|
|
||||||
|
K9 --> K11[Execute action scripts]
|
||||||
|
K10 --> K11
|
||||||
|
K11 --> K12{Monitor enabled?}
|
||||||
|
|
||||||
|
K12 -->|Yes| K13[Defer request & set timeout]
|
||||||
|
K12 -->|No| K14[Send immediate reply]
|
||||||
|
|
||||||
|
K13 --> K15[validate_required_services]
|
||||||
|
K15 --> K16{Services reloaded?}
|
||||||
|
K16 -->|Yes| K17[Complete request, send reply]
|
||||||
|
K16 -->|No| K18[Wait & retry]
|
||||||
|
K18 --> K17
|
||||||
|
|
||||||
|
K14 --> K20[Send bbfdm.apply event]
|
||||||
|
K17 --> K19[Sync with externally changed uci list]
|
||||||
|
K19 --> K20
|
||||||
|
K20 --> I
|
||||||
|
|
||||||
|
%% Revert Handler Flow
|
||||||
|
L --> L1[Parse blob message]
|
||||||
|
L1 --> L2[Determine protocol index]
|
||||||
|
L2 --> L3{Services specified?}
|
||||||
|
L3 -->|Yes| L4[revert specified_services]
|
||||||
|
L3 -->|No| L5[revert all services]
|
||||||
|
L4 --> L6[Send reply]
|
||||||
|
L5 --> L6
|
||||||
|
L6 --> I
|
||||||
|
|
||||||
|
%% Notify Event Flow
|
||||||
|
M --> M1[Parse config name from event]
|
||||||
|
M1 --> M2{Internal commit in progress?}
|
||||||
|
M2 -->|Yes| M3[Add to global external changed list]
|
||||||
|
M2 -->|No| M4[Send immediate bbfdm.apply event]
|
||||||
|
M3 --> I
|
||||||
|
M4 --> I
|
||||||
|
|
||||||
|
%% Service Processing Detail
|
||||||
|
subgraph SP[Service Processing Details]
|
||||||
|
SP1[commit services] --> SP2[For each service]
|
||||||
|
SP2 --> SP3[Determine UCI path & save directory]
|
||||||
|
SP3 --> SP4[Set UCI context directories]
|
||||||
|
SP4 --> SP5[Lookup UCI pointer]
|
||||||
|
SP5 -->|Commit| SP6[uci_commit]
|
||||||
|
SP6 --> SP7[Add specific action to action list]
|
||||||
|
SP7 --> SP8[Add to changed UCI list if not DMMAP]
|
||||||
|
end
|
||||||
|
|
||||||
|
%% UBUS Service Info Gathering
|
||||||
|
subgraph SG[Service Info Gathering]
|
||||||
|
SG1[fill_service_info] --> SG2[Call service.list via UBUS]
|
||||||
|
SG2 --> SG3[_get_service_list_cb or _get_specific_service_cb]
|
||||||
|
SG3 --> SG4[Parse service instances & triggers]
|
||||||
|
SG4 --> SG5[Build config package structure]
|
||||||
|
end
|
||||||
|
|
||||||
|
K6 -.-> SG1
|
||||||
|
K15 -.-> SG1
|
||||||
|
K9 -.-> SP1
|
||||||
|
K10 -.-> SP1
|
||||||
|
|
||||||
|
style K fill:#e1f5fe
|
||||||
|
style L fill:#f3e5f5
|
||||||
|
style M fill:#e8f5e8
|
||||||
|
style K13 fill:#fff3e0
|
||||||
|
style K20 fill:#fce4ec
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
#### Common Error Scenarios
|
||||||
|
- **Memory Allocation Failures**: Proper cleanup and error responses
|
||||||
|
- **UCI Operation Failures**: Logging and graceful continuation
|
||||||
|
- **UBUS Communication Errors**: Timeout handling and retries
|
||||||
|
- **Service Validation Timeouts**: Fallback completion after maximum wait time
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
|
||||||
|
#### Critical Services Definition (`critical_services.json`)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cwmp": ["cwmp_service"],
|
||||||
|
"usp": ["usp_service"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Example
|
||||||
```bash
|
```bash
|
||||||
cat /etc/bbfdm/critical_services.json
|
cat /etc/bbfdm/critical_services.json
|
||||||
{
|
{
|
||||||
"usp": [
|
"usp": [
|
||||||
"firewall",
|
"/etc/config/mapcontroller",
|
||||||
"network",
|
"/etc/config/wireless",
|
||||||
"dhcp",
|
"/etc/bbfdm/dmmap/WiFi",
|
||||||
"wireless",
|
...
|
||||||
"time"
|
...
|
||||||
],
|
],
|
||||||
"cwmp": [
|
"cwmp": [
|
||||||
"firewall",
|
"/etc/config/mapcontroller",
|
||||||
"network",
|
"/etc/config/wireless",
|
||||||
"dhcp",
|
"/etc/bbfdm/dmmap/WiFi",
|
||||||
"stunc",
|
...
|
||||||
"xmpp",
|
...
|
||||||
"wireless",
|
|
||||||
"time"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### bbf.config revert method:
|
#### Service Configuration for apply handler (`services/*.json`)
|
||||||
this method commits the changes in the required services based on proto option.
|
```json
|
||||||
|
|
||||||
#### bbf.config changes method:
|
|
||||||
|
|
||||||
this method provides the list of certical services based on protocol (proto option) and provide the available config changes based on protocol.
|
|
||||||
```bash
|
|
||||||
ubus call bbf.config changes '{"proto":"usp"}'
|
|
||||||
{
|
{
|
||||||
"configs": [
|
"daemon": {
|
||||||
"users",
|
"enable": "0 or 1",
|
||||||
"wireless"
|
"service_name": "name_of_the_service",
|
||||||
|
...
|
||||||
|
...
|
||||||
|
"apply_handler": {
|
||||||
|
"uci": [
|
||||||
|
{
|
||||||
|
"file": ["config_name"],
|
||||||
|
"external_handler": "/path/to/handler.sh"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"critical_services": [
|
"dmmap": [
|
||||||
"firewall",
|
{
|
||||||
"network",
|
"file": ["dmmap_file"],
|
||||||
"dhcp",
|
"external_handler": "/path/to/dmmap_handler.sh"
|
||||||
"wireless",
|
}
|
||||||
"time"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
#### UBUS Commands
|
||||||
|
```bash
|
||||||
|
# Commit all changes
|
||||||
|
ubus call bbf.config commit '{"proto":"both", "reload":true}'
|
||||||
|
|
||||||
|
# Commit specific services
|
||||||
|
ubus call bbf.config commit '{"services":["network","wireless"], "proto":"both"}'
|
||||||
|
|
||||||
|
# Revert all changes
|
||||||
|
ubus call bbf.config revert '{"proto":"both"}'
|
||||||
|
|
||||||
|
# Revert specific services
|
||||||
|
ubus call bbf.config revert '{"services":["network"], "proto":"both"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
#### Libraries
|
||||||
|
- `libubox`: UBUS and event loop functionality
|
||||||
|
- `libuci`: UCI configuration management
|
||||||
|
- `json-c`: JSON parsing for configuration files
|
||||||
|
- `libc`: Standard C library functions
|
||||||
|
|
||||||
|
#### System Requirements
|
||||||
|
- OpenWrt-based system
|
||||||
|
- UBUS daemon running
|
||||||
|
- UCI system configured
|
||||||
|
- Proper directory structure for configuration files
|
||||||
|
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
. /usr/share/libubox/jshn.sh
|
|
||||||
|
|
||||||
BBFDM_CONFIG_CONFDIR="/etc/config"
|
|
||||||
BBFDM_DMMAP_CONFDIR="/etc/bbfdm/dmmap"
|
|
||||||
BBFDM_CONFIG_SAVEDIR="/tmp/bbfdm/.bbfdm/config"
|
|
||||||
BBFDM_DMMAP_SAVEDIR="/tmp/bbfdm/.bbfdm/dmmap"
|
|
||||||
|
|
||||||
LOGLEVEL="$(uci -q get bbfdm.bbfdmd.loglevel)"
|
|
||||||
|
|
||||||
log() {
|
|
||||||
local level
|
|
||||||
|
|
||||||
level="${LOGLEVEL:-0}"
|
|
||||||
if [ "${level}" -gt 2 ]; then
|
|
||||||
echo "$@" | logger -t bbf.config -p info
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_result() {
|
|
||||||
local res="$1"
|
|
||||||
local service="$2"
|
|
||||||
local action="$3"
|
|
||||||
|
|
||||||
if [ "${res}" -ne 0 ]; then
|
|
||||||
echo "{ \"error\": \"Failed to ${action} ${service} service\" }"
|
|
||||||
exit "${res}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_config_changes() {
|
|
||||||
local service="$1"
|
|
||||||
local action="$3"
|
|
||||||
local reload="$4"
|
|
||||||
|
|
||||||
# Check if either service or action is empty
|
|
||||||
if [ -z "$service" ] || [ -z "$action" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Applying $action configuration for service: $service"
|
|
||||||
|
|
||||||
# Commit/Revert config changes
|
|
||||||
log "Applying ${action} configuration for file: ${service}"
|
|
||||||
uci -q -c "${BBFDM_CONFIG_CONFDIR}" -t "${BBFDM_CONFIG_SAVEDIR}" "${action}" "${service}"
|
|
||||||
check_result "$?" "${service}" "${action}"
|
|
||||||
|
|
||||||
if [ "${reload}" == "1" ]; then
|
|
||||||
# Reload service
|
|
||||||
ubus -t 1 call uci "${action}" "{'config': '${service}'}"
|
|
||||||
check_result "$?" "${service}" "${action}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
list)
|
|
||||||
echo '{ "commit": { "services": [], "proto": "str", "monitor": true, "reload": true }, "revert": { "services": [], "proto": "str", "monitor": true, "reload": true }, "changes": { "proto": "str" } }'
|
|
||||||
;;
|
|
||||||
call)
|
|
||||||
# Read input JSON from standard input
|
|
||||||
read -r input
|
|
||||||
|
|
||||||
# Parse input JSON
|
|
||||||
json_load "${input}"
|
|
||||||
|
|
||||||
# Get the 'proto' value from the input JSON
|
|
||||||
json_get_var proto proto
|
|
||||||
|
|
||||||
if [ "${proto}" == "cwmp" ]; then
|
|
||||||
BBFDM_CONFIG_SAVEDIR="/tmp/bbfdm/.cwmp/config"
|
|
||||||
BBFDM_DMMAP_SAVEDIR="/tmp/bbfdm/.cwmp/dmmap"
|
|
||||||
elif [ "${proto}" == "usp" ]; then
|
|
||||||
BBFDM_CONFIG_SAVEDIR="/tmp/bbfdm/.usp/config"
|
|
||||||
BBFDM_DMMAP_SAVEDIR="/tmp/bbfdm/.usp/dmmap"
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$2" in
|
|
||||||
commit|revert)
|
|
||||||
|
|
||||||
# Get the 'reload' value from the input JSON
|
|
||||||
json_get_var reload reload
|
|
||||||
json_get_var monitor monitor
|
|
||||||
|
|
||||||
if [ -z "${reload}" ]; then
|
|
||||||
reload=1
|
|
||||||
else
|
|
||||||
if [ "${reload}" != "0" ] && [ "${reload}" != "1" ]; then
|
|
||||||
echo '{ "error": "Reload should be boolean type !!!" }'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if 'services' array is provided
|
|
||||||
json_get_type type "services"
|
|
||||||
if [ -z "${type}" ]; then
|
|
||||||
# Iterate over all services and apply config changes
|
|
||||||
for config in $(uci -q -c "${BBFDM_CONFIG_CONFDIR}" -t "${BBFDM_CONFIG_SAVEDIR}" changes | awk -F'.' '{print $1}' | sort | uniq); do
|
|
||||||
apply_config_changes "${config}" "" "$2" "$reload"
|
|
||||||
done
|
|
||||||
else
|
|
||||||
# Check if 'services' is array
|
|
||||||
if [ "${type}" != "array" ]; then
|
|
||||||
echo '{ "error": "Services argument should be array of strings !!!" }'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Iterate over each service and apply config changes
|
|
||||||
json_for_each_item "apply_config_changes" "services" "$2" "$reload"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${reload}" == "1" ]; then
|
|
||||||
# Commit/Revert bbfdm dmmap config changes
|
|
||||||
if [ -d "${BBFDM_DMMAP_SAVEDIR}" ] && [ "$(ls -A "${BBFDM_DMMAP_SAVEDIR}" 2>/dev/null)" ]; then
|
|
||||||
for file in "${BBFDM_DMMAP_SAVEDIR}"/*; do
|
|
||||||
file_name=$(basename "${file}")
|
|
||||||
log "Applying $2 configuration for file: $file_name"
|
|
||||||
uci -q -c "${BBFDM_DMMAP_CONFDIR}" -t "${BBFDM_DMMAP_SAVEDIR}" "$2" "${file_name}"
|
|
||||||
check_result "$?" "${file_name}" "$2"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${monitor}" -eq "1" ]; then
|
|
||||||
sleep 3
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Send 'bbf.config.change' event to run refresh instances
|
|
||||||
ubus send bbf.config.change
|
|
||||||
|
|
||||||
echo '{ "status": "ok" }'
|
|
||||||
;;
|
|
||||||
changes)
|
|
||||||
json_init
|
|
||||||
json_add_array "configs"
|
|
||||||
for config in $(uci -q -c "${BBFDM_CONFIG_CONFDIR}" -t "${BBFDM_CONFIG_SAVEDIR}" changes | awk -F'.' '{print $1}' | sort | uniq); do
|
|
||||||
json_add_string "" "${config}"
|
|
||||||
done
|
|
||||||
json_close_array
|
|
||||||
json_dump
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
@ -7,6 +7,22 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# Send 'bbf.config.notify' event to notify about the 'config.change' from external configs
|
# Send 'bbf.config.notify' event to notify about the 'config.change' from external configs
|
||||||
ubus send bbf.config.notify
|
. /usr/share/libubox/jshn.sh
|
||||||
|
|
||||||
|
config="${1}"
|
||||||
|
|
||||||
|
if [ -z "${config}" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
json_init
|
||||||
|
json_add_string "config" "${config}"
|
||||||
|
json_compact
|
||||||
|
|
||||||
|
json_data=$(json_dump)
|
||||||
|
|
||||||
|
ubus send bbf.config.notify "${json_data}"
|
||||||
|
|
||||||
|
json_cleanup
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
#define CRITICAL_DEF_JSON "/etc/bbfdm/critical_services.json"
|
#define CRITICAL_DEF_JSON "/etc/bbfdm/critical_services.json"
|
||||||
#define BBFDM_MICROSERVICE_INPUT_PATH "/etc/bbfdm/services"
|
#define BBFDM_MICROSERVICE_INPUT_PATH "/etc/bbfdm/services"
|
||||||
|
|
||||||
|
static struct list_head g_external_changed_uci;
|
||||||
|
|
||||||
// Structure to represent an instance of a service
|
// Structure to represent an instance of a service
|
||||||
struct instance {
|
struct instance {
|
||||||
char name[NAME_LENGTH];
|
char name[NAME_LENGTH];
|
||||||
|
|
@ -461,28 +463,10 @@ wait:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_bbf_config_change_event()
|
|
||||||
{
|
|
||||||
struct ubus_context *ctx;
|
|
||||||
struct blob_buf bb = {0};
|
|
||||||
|
|
||||||
ctx = ubus_connect(NULL);
|
|
||||||
if (ctx == NULL) {
|
|
||||||
ULOG_ERR("Can't create UBUS context for 'bbf.config.change' event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULOG_INFO("Sending bbf.config.change event");
|
|
||||||
|
|
||||||
memset(&bb, 0, sizeof(struct blob_buf));
|
|
||||||
blob_buf_init(&bb, 0);
|
|
||||||
ubus_send_event(ctx, "bbf.config.change", bb.head);
|
|
||||||
blob_buf_free(&bb);
|
|
||||||
ubus_free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
|
static void send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
|
||||||
{
|
{
|
||||||
|
char protocol[16] = {0};
|
||||||
|
|
||||||
if (changed_uci_list == NULL || list_empty(changed_uci_list))
|
if (changed_uci_list == NULL || list_empty(changed_uci_list))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -493,7 +477,9 @@ static void send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
|
||||||
memset(&bb, 0, sizeof(struct blob_buf));
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
blob_buf_init(&bb, 0);
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
blobmsg_add_string(&bb, "proto", get_proto_name_by_idx(idx));
|
snprintf(protocol, sizeof(protocol), "%s", (idx == -1) ? "external" : get_proto_name_by_idx(idx));
|
||||||
|
|
||||||
|
blobmsg_add_string(&bb, "proto", protocol);
|
||||||
void *array = blobmsg_open_array(&bb, "uci_changed");
|
void *array = blobmsg_open_array(&bb, "uci_changed");
|
||||||
list_for_each_entry_safe(node, tmp, changed_uci_list, list) {
|
list_for_each_entry_safe(node, tmp, changed_uci_list, list) {
|
||||||
if (node->uci == NULL) {
|
if (node->uci == NULL) {
|
||||||
|
|
@ -546,8 +532,22 @@ static void complete_deferred_request(struct bbf_config_async_req *async_req)
|
||||||
// Complete the deferred request and send the response
|
// Complete the deferred request and send the response
|
||||||
ubus_complete_deferred_request(async_req->ctx, &async_req->req, 0);
|
ubus_complete_deferred_request(async_req->ctx, &async_req->req, 0);
|
||||||
|
|
||||||
// Send 'bbf.config.change' event to run refresh instances
|
// If any uci is changed externally then add it in bbf.apply event
|
||||||
send_bbf_config_change_event();
|
struct modi_uci_node *node = NULL, *tmp = NULL;
|
||||||
|
list_for_each_entry_safe(node, tmp, &g_external_changed_uci, list) {
|
||||||
|
if (node->uci == NULL) {
|
||||||
|
list_del(&node->list);
|
||||||
|
FREE(node);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_changed_uci_list(&async_req->changed_uci_list, node->uci);
|
||||||
|
list_del(&node->list);
|
||||||
|
FREE(node->uci);
|
||||||
|
FREE(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send 'bbf.apply' event
|
||||||
send_bbf_apply_event(async_req->idx, &async_req->changed_uci_list);
|
send_bbf_apply_event(async_req->idx, &async_req->changed_uci_list);
|
||||||
|
|
||||||
// Free the allocated memory
|
// Free the allocated memory
|
||||||
|
|
@ -766,8 +766,7 @@ static int bbf_config_commit_handler(struct ubus_context *ctx, struct ubus_objec
|
||||||
ULOG_INFO("Sending immediate success response");
|
ULOG_INFO("Sending immediate success response");
|
||||||
send_reply(ctx, req, "status", "ok");
|
send_reply(ctx, req, "status", "ok");
|
||||||
|
|
||||||
// Send 'bbf.config.change' event to run refresh instances
|
// Send 'bbf.apply' event
|
||||||
send_bbf_config_change_event();
|
|
||||||
send_bbf_apply_event(idx, changed_uci);
|
send_bbf_apply_event(idx, changed_uci);
|
||||||
|
|
||||||
// Free the allocated memory
|
// Free the allocated memory
|
||||||
|
|
@ -820,25 +819,59 @@ static int bbf_config_revert_handler(struct ubus_context *ctx, struct ubus_objec
|
||||||
ULOG_INFO("Sending success response");
|
ULOG_INFO("Sending success response");
|
||||||
send_reply(ctx, req, "status", "ok");
|
send_reply(ctx, req, "status", "ok");
|
||||||
|
|
||||||
// Send 'bbf.config.change' event to run refresh instances
|
|
||||||
send_bbf_config_change_event();
|
|
||||||
|
|
||||||
ULOG_INFO("revert handler exit");
|
ULOG_INFO("revert handler exit");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_changed_uci_list(struct list_head *uci_list)
|
||||||
|
{
|
||||||
|
struct modi_uci_node *node = NULL, *tmp = NULL;
|
||||||
|
|
||||||
|
if (uci_list == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(node, tmp, uci_list, list) {
|
||||||
|
list_del(&node->list);
|
||||||
|
FREE(node->uci);
|
||||||
|
FREE(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void receive_notify_event(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
static void receive_notify_event(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
||||||
const char *type, struct blob_attr *msg)
|
const char *type, struct blob_attr *msg)
|
||||||
{
|
{
|
||||||
// Skip sending 'bbf.config.change' event if triggered by an internal commit
|
char file_path[1024] = {0};
|
||||||
|
|
||||||
|
struct blob_attr *tb[1] = {0};
|
||||||
|
const struct blobmsg_policy p[1] = {
|
||||||
|
{ "config", BLOBMSG_TYPE_STRING }
|
||||||
|
};
|
||||||
|
|
||||||
|
blobmsg_parse(p, 1, tb, blob_data(msg), blob_len(msg));
|
||||||
|
|
||||||
|
if (!tb[0])
|
||||||
|
return;
|
||||||
|
|
||||||
|
char *config = blobmsg_get_string(tb[0]);
|
||||||
|
snprintf(file_path, sizeof(file_path), "/etc/config/%s", config);
|
||||||
|
|
||||||
if (g_internal_commit) {
|
if (g_internal_commit) {
|
||||||
ULOG_DEBUG("Event triggered by internal commit; skipping 'bbf.config.change' event transmission");
|
ULOG_DEBUG("internal commit in progress, add uci in global list");
|
||||||
|
add_changed_uci_list(&g_external_changed_uci, file_path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger 'bbf.config.change' event to refresh instances as required
|
// Trigger 'bbfdm.apply' event
|
||||||
send_bbf_config_change_event();
|
struct list_head uci_list;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&uci_list);
|
||||||
|
add_changed_uci_list(&uci_list, file_path);
|
||||||
|
|
||||||
|
send_bbf_apply_event(-1, &uci_list);
|
||||||
|
free_changed_uci_list(&uci_list);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ubus_method bbf_config_methods[] = {
|
static const struct ubus_method bbf_config_methods[] = {
|
||||||
|
|
@ -1071,6 +1104,8 @@ int main(int argc, char **argv)
|
||||||
load_critical_services();
|
load_critical_services();
|
||||||
load_apply_handlers();
|
load_apply_handlers();
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&g_external_changed_uci);
|
||||||
|
|
||||||
if (ubus_add_object(uctx, &bbf_config_object)) {
|
if (ubus_add_object(uctx, &bbf_config_object)) {
|
||||||
ULOG_ERR("Failed to add 'bbf.config' ubus object");
|
ULOG_ERR("Failed to add 'bbf.config' ubus object");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
@ -1085,6 +1120,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
free_apply_handlers();
|
free_apply_handlers();
|
||||||
|
free_changed_uci_list(&g_external_changed_uci);
|
||||||
blob_buf_free(&g_critical_bb);
|
blob_buf_free(&g_critical_bb);
|
||||||
uloop_done();
|
uloop_done();
|
||||||
ubus_free(uctx);
|
ubus_free(uctx);
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ static void add_external_action_list(struct list_head *action_list, struct list_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_changed_uci_list(struct list_head *changed_uci, const char *file_path)
|
void add_changed_uci_list(struct list_head *changed_uci, const char *file_path)
|
||||||
{
|
{
|
||||||
if (changed_uci == NULL || file_path == NULL || strlen(file_path) == 0)
|
if (changed_uci == NULL || file_path == NULL || strlen(file_path) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -78,5 +78,6 @@ const char *get_proto_dmmap_savedir_by_idx(int idx);
|
||||||
const char *get_proto_name_by_idx(int idx);
|
const char *get_proto_name_by_idx(int idx);
|
||||||
bool file_exists(const char *path);
|
bool file_exists(const char *path);
|
||||||
bool regular_file(const char *path);
|
bool regular_file(const char *path);
|
||||||
|
void add_changed_uci_list(struct list_head *changed_uci, const char *file_path);
|
||||||
|
|
||||||
#endif //__UTILS_H__
|
#endif //__UTILS_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue