The Amarisoft gNodeB Agent is a RESTful API service designed to manage and control Amarisoft 5G gNodeB (Next Generation Node B) equipment. It serves as an intermediary between a central Resource Management System and the physical Amarisoft hardware, enabling remote configuration, monitoring, and User Equipment (UE) management.
The agent provides:
- Resource Inventory Management: Implements the TMF (TeleManagement Forum) Resource Inventory Management API (TMF639) specification v4.0.0
- Self-Registration: Automatic registration with a central management server
- Service Lifecycle Management: Start, stop, and restart of the LTE/5G service
- UE Database Management: Dynamic addition, modification, and removal of User Equipment entries via WebSocket
- Configuration Management: Runtime configuration updates for gNodeB parameters
It is implemented in Python 3 using the FastAPI web framework (version 0.65+), a modern, high-performance framework well-suited for building RESTful APIs with automatic OpenAPI documentation and data validation. The application runs on Uvicorn, a lightning-fast ASGI server, and leverages Pydantic for data validation and serialization. HTTP client operations are handled via the Requests library for outbound communication with the central management server, while real-time communication with the Amarisoft equipment is achieved through WebSocket using the websocket-client library. Configuration management is handled via PyYAML for parsing YAML-based profile and resource definitions. The application is designed to be containerized and deployable using Docker, with container orchestration supported through Docker Compose.
┌─────────────────────────────────────────────────────────────────┐
│ Resource Management Server │
└─────────────────────────────────────────────────────────────────┘
▲
│ HTTP REST (TMF639)
▼
┌─────────────────────────────────────────────────────────────────┐
│ gNodeB Agent (FastAPI) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ OpenAPI │ │ Agent │ │ Profile/Callbacks │ │
│ │ Endpoints │◄─┤ Core │◄─┤ (gNodeB_service) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ │
│ Shell Commands │ WebSocket
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ Amarisoft LTE │ │ Amarisoft MME/ │
│ Service (systemd) │ │ UE Database │
└─────────────────────┘ └─────────────────────┘
The API is based on the TMF639 Resource Inventory Management specification and exposes the following endpoint groups:
Base path: /resource
| Method | Endpoint | Description |
|---|---|---|
POST |
/resource |
Create a new Resource entity |
GET |
/resource |
List or find Resource objects |
GET |
/resource/{id} |
Retrieve a Resource by ID |
PATCH |
/resource/{id} |
Partially update a Resource |
DELETE |
/resource/{id} |
Delete a Resource entity |
fields: Comma-separated properties to include in responseoffset: Start index for paginationlimit: Number of resources to return
Base path: /physicalResource
| Method | Endpoint | Description |
|---|---|---|
POST |
/physicalResource |
Create a new PhysicalResource |
GET |
/physicalResource |
List or find PhysicalResource objects |
GET |
/physicalResource/{id} |
Retrieve a PhysicalResource by ID |
PATCH |
/physicalResource/{id} |
Partially update a PhysicalResource |
DELETE |
/physicalResource/{id} |
Delete a PhysicalResource entity |
Base path: /logicalResource
| Method | Endpoint | Description |
|---|---|---|
POST |
/logicalResource |
Create a new LogicalResource |
GET |
/logicalResource |
List or find LogicalResource objects |
GET |
/logicalResource/{id} |
Retrieve a LogicalResource by ID |
PATCH |
/logicalResource/{id} |
Partially update a LogicalResource |
PUT |
/logicalResource/{id} |
Fully update a LogicalResource |
DELETE |
/logicalResource/{id} |
Delete a LogicalResource entity |
Base path: /hub
| Method | Endpoint | Description |
|---|---|---|
POST |
/hub |
Register a listener for events |
DELETE |
/hub/{id} |
Unregister an event listener |
Base path: /listener
| Method | Endpoint | Description |
|---|---|---|
POST |
/listener/physicalResourceAttributeValueChangeEvent |
Listen for physical resource attribute changes |
POST |
/listener/physicalResourceCreateEvent |
Listen for physical resource creation |
POST |
/listener/physicalResourceDeleteEvent |
Listen for physical resource deletion |
POST |
/listener/physicalResourceStateChangeEvent |
Listen for physical resource state changes |
POST |
/listener/resourceAttributeValueChangeEvent |
Listen for resource attribute changes |
POST |
/listener/resourceCreateEvent |
Listen for resource creation |
POST |
/listener/resourceDeleteEvent |
Listen for resource deletion |
POST |
/listener/resourceStateChangeEvent |
Listen for resource state changes |
The agent implements a callback-based architecture that enables dynamic execution of commands on the gNodeB equipment. Callbacks are registered at startup based on the configured profile and are invoked when corresponding events are triggered.
def register_callback(event, callback):
"""Register a callback function for a specific event."""
if event not in callbacks:
callbacks[event] = callback
def process_event(event, debug_mode, params):
"""Process an event by invoking its registered callback."""
if event in callbacks:
callback = callbacks[event]
result = callback(debug_mode, params)
return result
return FalseThe gNodeB_service profile provides the following callbacks:
| Callback | Description | Parameters | Return Value |
|---|---|---|---|
start |
Start the LTE service | Optional configuration parameters | "Start Successful" or "Start Failed" |
stop |
Stop the LTE service | None | "Stop Successful" or "Stop Failed" |
restart |
Restart the LTE service | Optional configuration parameters | "Restart Successful" or "Restart Failed" |
Example - Start Service:
def start(debug_mode, params):
cmd2send = "systemctl start lte"
if params is not None:
write_conf_file(params) # Apply configuration before starting
return_code = exec_command(cmd2send)
return "Start Successful" if return_code == 0 else "Start Failed"| Callback | Description | Parameters | Return Value |
|---|---|---|---|
get_all_ues |
Retrieve all UEs from database | Optional filters (APN, NSSAI) | JSON with UE list |
get_ue_slices |
Get slice info for specific UE | {"imsi": "..."} |
UE slice configuration |
update_ues |
Add/modify/remove UEs | List of UE dictionaries | Operation status |
Example - Get All UEs with Filtering:
def get_all_ues(debug_mode, params):
"""
Supports filtering by:
- access_point_name: Filter by APN
- nssai: Filter by network slice (sst, sd)
Example params:
- [{"access_point_name": "internet"}]
- [{"nssai": {"sst": 1, "sd": 10}}]
"""
ues = read_users_db_file()
# Apply filters and return results
return {
"status": "success",
"count": len(filtered_ues),
"ues": filtered_ues
}Example - Update UEs:
def update_ues(debug_mode, params):
"""
Update UEs via WebSocket and local database file.
Params: List of UE dictionaries with fields:
- imsi: International Mobile Subscriber Identity
- pdn_list: List of PDN configurations
- Additional UE attributes
"""
response = update_ues_websocket_db(params)
return response| Callback | Description | Parameters |
|---|---|---|
touch |
Create a file | {"filename": "..."} |
echo |
Write message to file | {"filename": "...", "message": "..."} |
def exec_command(action_command, debug_mode=False):
"""
Execute a shell command with special handling for systemctl.
Features:
- Wraps systemctl commands with nsenter for host execution (containerized)
- Logs command output
- Returns process return code
"""The agent communicates with the Amarisoft MME via WebSocket for real-time UE database updates.
Configuration (Environment Variables):
| Variable | Default | Description |
|---|---|---|
WEBSOCKET_HOST |
172.16.100.207 |
WebSocket server IP |
WEBSOCKET_PORT |
9000 |
WebSocket server port |
Message Types:
| Message | Purpose | Payload |
|---|---|---|
ue_add |
Add new UE | {"message": "ue_add", "ue_db": [<ue_entry>]} |
ue_del |
Remove UE | {"message": "ue_del", "imsi": "<imsi>"} |
def send_ws_message(message, max_retries=3, timeout=5, retry_delay=0.5):
"""
Send message via WebSocket with retry logic.
Features:
- Automatic reconnection on failure
- Exponential backoff
- JSON serialization/deserialization
"""Files:
| File | Purpose | Format |
|---|---|---|
myconf.cfg |
gNodeB configuration | C-style defines |
users.db.cfg |
UE database | JSON-like format |
def write_conf_file(params):
"""
Write configuration parameters to myconf.cfg.
Generates C-style defines:
#define PRMT_AMF_ADDR "192.168.1.1"
#define PRMT_PLMN "00101"
"""{
"imsi": "001010000000001",
"amf": 36865,
"pdn_list": [
{
"access_point_name": "internet",
"nssai": [
{
"sst": 1,
"sd": 10
}
]
}
]
}The agent registers with the following characteristics:
| Characteristic | Type | Description |
|---|---|---|
IP |
string | Agent IP address and port |
location |
array | Geographic coordinates [lat, lon] |
profile |
string | Profile type (e.g.,gNodeB_service) |
supported_actions |
list | Available callback actions |
| State Type | Possible Values |
|---|---|
administrative_state |
unlocked, locked, shutdown |
operational_state |
enable, disable |
resource_status |
available, unavailable, reserved |
usage_state |
idle, active, busy |
| Variable | Default | Description |
|---|---|---|
MYCONF_FILE |
./shared/myconf.cfg |
Path to gNodeB config file |
USERS_DB_FILE |
./shared/users.db.cfg |
Path to UE database file |
WEBSOCKET_HOST |
172.16.100.207 |
Amarisoft WebSocket host |
WEBSOCKET_PORT |
9000 |
Amarisoft WebSocket port |
resource_data_RO.yml (Read-Only Resource Data):
resource_data:
category: gNB Controller
description: An agent that controls the lte service of an Amarisoft callbox
name: NAME_PLACEHOLDER
ip: IP_PLACEHOLDER:PORT_PLACEHOLDER
location: [123, 456]
profile_type: gNodeB_serviceconf_data_RW.yml (Runtime Configuration):
configuration:
server: http://<management-server-url>All endpoints return standard TMF error responses:
| Status Code | Description |
|---|---|
400 |
Bad Request - Invalid input |
401 |
Unauthorized - Authentication required |
403 |
Forbidden - Insufficient permissions |
404 |
Not Found - Resource doesn't exist |
405 |
Method Not Allowed |
409 |
Conflict - Resource already exists |
500 |
Internal Server Error |
The WebSocket communication includes:
- Retry Logic: Up to 3 attempts with exponential backoff
- Timeout Handling: 5-second timeout per operation
- Connection Recovery: Automatic reconnection attempts
The agent is designed to run in a Docker container with access to the host's systemd via nsenter.
Docker Compose Configuration:
services:
gnb-agent:
build: .
volumes:
- ./shared:/app/shared
environment:
- WEBSOCKET_HOST=172.16.100.207
- WEBSOCKET_PORT=9000
privileged: true # Required for nsenterSee requirements.txt for full dependency list. Key dependencies:
- FastAPI + Uvicorn (Web server)
- Pydantic (Data validation)
- websocket-client (WebSocket communication)
- PyYAML (Configuration parsing)
- Requests (HTTP client for registration)
┌─────────┐ ┌─────────────┐ ┌───────────────┐
│ Agent │ │ Management │ │ Amarisoft │
│ │ │ Server │ │ Equipment │
└────┬────┘ └──────┬──────┘ └───────┬───────┘
│ │ │
│ POST /resource │ │
│─────────────────────►│ │
│ │ │
│ 201 Created / 409 │ │
│◄─────────────────────│ │
│ │ │
│ PATCH /resource/{id} │ │
│─────────────────────►│ │
│ │ │
│ [Background Thread] │ │
│ Status polling loop │ │
│──────────────────────────────────────────────► │
│ │ │
┌─────────┐ ┌─────────────┐ ┌───────────────┐
│ Client │ │ Agent │ │ Amarisoft │
│ │ │ │ │ WebSocket │
└────┬────┘ └──────┬──────┘ └───────┬───────┘
│ │ │
│ update_ues callback │ │
│─────────────────────►│ │
│ │ │
│ │ WS: ue_del (if update) │
│ │────────────────────────►│
│ │ │
│ │ WS Response │
│ │◄────────────────────────│
│ │ │
│ │ WS: ue_add │
│ │────────────────────────►│
│ │ │
│ │ WS Response │
│ │◄────────────────────────│
│ │ │
│ Operation result │ │
│◄─────────────────────│ │
│ │ │
The agent uses YAML-based profile configuration:
supported_profiles:
gNodeB_service:
type: gNodeB_service
description: An agent that controls the lte service of an Amarisoft callbox
execution_mode: Shell commands
available_commands:
touch:
description: Create a file
command: touch name
echo:
description: Echo a message to a file
command: echo text >> file
stop:
description: Stop service
command: systemctl stop <service>
start:
description: Start service
command: systemctl start <service>
restart:
description: Restart service
command: systemctl restart <service>
get_ue_slices:
description: Get the slice(s) associated with a UE
update_ues:
description: Update UEs in users database file via websocket
get_all_ues:
description: Get all UEs from users database fileThe agent uses Python's standard logging module with the following format:
%(asctime)s - %(name)s - %(levelname)s - %(message)s
Log levels are set to INFO by default, with detailed logging for:
- WebSocket communications
- UE database operations
- Command execution
- Registration processes