The UBS Engine Go API is a UBS Engine management interface developed based on the Go language. It is used to schedule and manage resources and perform key service operations.
This document aims to help developers quickly master the core functions, application scenarios, and development skills of the UBS Engine Go API, provide sample code that can be directly executed, and avoid common issues.
1. Prerequisites
To use the UBS Engine Go API for development, prepare the UBS Engine development environment and install the development package by following the steps below.
1.1 Environment Requirements
- OS: Linux
- Go version: Go 1.21 or later
- GCC compiler: supports CGO compilation.
1.2 Development Package Installation
# Install the development package (for integrated development).
sudo dnf install -y ubs-engine-client-libs ubs-engine-client-devel
1.3 Installation Result
| File/Directory | Other Information |
|---|---|
/usr/include/ubse |
Permission on the header file (*.h) in the directory: 644 |
/usr/lib64/libubse-client.so |
Soft link, pointing to /usr/lib64/libubse-client.so.1 |
/usr/lib64/libubse-client.so.1 |
Soft link, pointing to libubse-client.so.xx.xx.xx |
/usr/lib64/libubse-client.so.xx.xx.xx |
Binary dynamic library |
/usr/lib64/libubse-client.a |
Binary static library |
1.4 Go Module Dependencies
In a Go project, you need to import the following modules:
import (
"atomgit.com/openeuler/ubs-engine.git/src/sdk/go/engine"
"atomgit.com/openeuler/ubs-engine.git/src/sdk/go/log"
"atomgit.com/openeuler/ubs-engine.git/src/sdk/go/mem"
"atomgit.com/openeuler/ubs-engine.git/src/sdk/go/topo"
)
2. Using the UBS Engine Go API: Topology Query as an Example
Topology query is a common scenario of the UBS Engine service. Cluster resources can be scheduled and managed by querying node and connection information.
2.1 Implementation Logic Overview
The implementation of topology query can be divided into the following four main steps:
-
Initialize the client: Use
engine.UbsEngineClientInitializeto initialize the client connection. -
Register log callback: Use
log.UbsEngineLogCallbackRegisterto register the log callback function for debugging and monitoring. -
Query topology information: Use
topo.UbsTopoNodeListto query information about all nodes,topo.UbsTopoNodeLocalGetto query information about the local node, andtopo.UbsTopoLinkListto query information about all connections. -
Clear resources: Use
engine.UbsEngineClientFinalizeto clear client resources after fter the operation is complete.
2.2 Implementation Code
The example.go file provides the implementation code for topology query. You can refer to this code to implement the topology query process.
2.3 Expected Output
Initialize result: 0
====== Start to query all node information. ======
[log_example][INFO][ubse_uds_client.cpp:Connect:90] Connection successful
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:98] Sending request, module_code=3, op_code=1
[log_example][INFO][ubse_uds_client.cpp:Send:178] Starting Send operation with timeout: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Send:212] Waiting for response...
[log_example][INFO][ubse_uds_client.cpp:Receive:271] Starting Receive operation with remaining time: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Receive:321] Receive operation completed successfully
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:105] Sending request successfully, module_code=3, op_code=1
Information about two nodes is obtained.
=== Node information [0] ===
Slot ID (SlotId): 2
Host name (HostName): node01
Socket ID: Socket[0]=36 Socket[1]=236
NUMA IDs:
Socket[0]: NUMA[0]=0 NUMA[1]=4294967295 NUMA[2]=4294967295 NUMA[3]=4294967295
Socket[1]: NUMA[0]=1 NUMA[1]=4294967295 NUMA[2]=4294967295 NUMA[3]=4294967295
IP address list (three IP addresses):
IP[0]: 192.168.122.1
IP[1]: 192.168.1.11
IP[2]: 192.168.100.101
=== Node information [1] ===
Slot ID (SlotId): 1
Host name (HostName): controller
Socket ID: Socket[0]=236 Socket[1]=36
NUMA IDs:
Socket[0]: NUMA[0]=1 NUMA[1]=4294967295 NUMA[2]=4294967295 NUMA[3]=4294967295
Socket[1]: NUMA[0]=0 NUMA[1]=4294967295 NUMA[2]=4294967295 NUMA[3]=4294967295
IP address list (three IP addresses):
IP[0]: 192.168.122.1
IP[1]: 192.168.1.10
IP[2]: 192.168.100.100
====== Full node information query is complete. ======
====== Start to query local node information. ======
[log_example][INFO][ubse_uds_client.cpp:Connect:90] Connection successful
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:98] Sending request, module_code=3, op_code=4
[log_example][INFO][ubse_uds_client.cpp:Send:178] Starting Send operation with timeout: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Send:212] Waiting for response...
[log_example][INFO][ubse_uds_client.cpp:Receive:271] Starting Receive operation with remaining time: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Receive:321] Receive operation completed successfully
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:105] Sending request successfully, module_code=3, op_code=4
Information about the local node is obtained.
=== Node information [0] ===
Slot ID (SlotId): 1
Host name (HostName): controller
Socket ID: Socket[0]=236 Socket[1]=36
NUMA IDs:
Socket[0]: NUMA[0]=1 NUMA[1]=4294967295 NUMA[2]=4294967295 NUMA[3]=4294967295
Socket[1]: NUMA[0]=0 NUMA[1]=4294967295 NUMA[2]=4294967295 NUMA[3]=4294967295
IP address list (three IP addresses):
IP[0]: 192.168.122.1
IP[1]: 192.168.1.10
IP[2]: 192.168.100.100
====== Local node information query is complete. ======
====== Start to query all connection information. ======
[log_example][INFO][ubse_uds_client.cpp:Connect:90] Connection successful
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:98] Sending request, module_code=3, op_code=2
[log_example][INFO][ubse_uds_client.cpp:Send:178] Starting Send operation with timeout: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Send:212] Waiting for response...
[log_example][INFO][ubse_uds_client.cpp:Receive:271] Starting Receive operation with remaining time: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Receive:321] Receive operation completed successfully
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:105] Sending request successfully, module_code=3, op_code=2
Link: 0
SlotId=1, SocketId=36, PortId=1
PeerSlotId=2, PeerSocketId=36, PeerPortId=1
Link: 1
SlotId=1, SocketId=236, PortId=1
PeerSlotId=2, PeerSocketId=236, PeerPortId=1
====== Full connection information query is complete. ======
3. Using the UBS Engine Go API: NUMA Memory Query as an Example
NUMA memory query is another common scenario of the UBS Engine service. Memory resources can be managed by querying the remote memory information in NUMA topology.
3.1 Implementation Logic Overview
The implementation of NUMA memory query can be divided into the following four main steps:
-
Initialize the client: Use
engine.UbsEngineClientInitializeto initialize the client connection. -
Query NUMA memory: Use
mem.UbsMemNumaListto query all remote NUMA memory on the local node. -
Process the query result: Parse the returned memory description, including the borrow identifier, NUMA ID, borrow size, and lending/borrowing node information.
-
Clear resources: Use
engine.UbsEngineClientFinalizeto clear client resources after fter the operation is complete.
3.2 Implementation Code
The example.go file provides the implementation code for NUMA memory query. You can refer to this code to implement the memory query process.
3.3 Expected Output
# Example of the expected output
====== Start to query all NUMA memory information.======
[log_example][INFO][ubse_uds_client.cpp:Connect:90] Connection successful
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:98] Sending request, module_code=1, op_code=20
[log_example][INFO][ubse_uds_client.cpp:Send:178] Starting Send operation with timeout: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Send:212] Waiting for response...
[log_example][INFO][ubse_uds_client.cpp:Receive:271] Starting Receive operation with remaining time: 1800000ms
[log_example][INFO][ubse_uds_client.cpp:Receive:321] Receive operation completed successfully
[log_example][INFO][ubse_ipc_client.cpp:ubse_invoke_call:105] Sending request successfully, module_code=1, op_code=20
No NUMA memory description is obtained.
====== Full NUMA memory information query is complete. ======
Client finalized successfully
4. Running Example
4.1 Preparing the Service Environment
Environment requirements
- OS: openEuler 24.03 LTS or later
- CPU architecture: AArch64
- Memory: ≥ 64 GB
- Disk: SSD, throughput 500 MB/s (IOPS)
- Chip interconnection: UB
- NIC: optional dependency (TCP can be used to assist UB in link establishment. By default, UB bootstrap is used for link establishment.)
- User permission: The
rootpermission is required for installation and management.
For more requirements, see Deployment Description.
Install the RPM package. (The ubs-engine main package must be installed on all cluster nodes.)
# Install the main program package.
sudo dnf install -y ubs-engine
# Install the client runtime library (mandatory for third-party integration).
sudo dnf install -y ubs-engine-client-libs
Start the UBS Engine service on each node.
By default, secure communication is enabled for UBS Engine. Ensure that the certificate is successfully imported. Otherwise, the cluster status may be abnormal. For details about how to import the certificate, see ubsectl_cert. Alternatively, you can modify the /etc/ubse/ubse.conf configuration file and set cert.use to false to disable secure communication.
sudo systemctl start ubse
# Check the service process status.
$ ps -ef | grep ubse
--------------------------------------------------------------------------
ubse 64120 1 99 15:14 ? 00:18:18 /usr/bin/ubse
root 2182344 2181443 0 15:52 pts/3 00:00:00 grep --color=auto ubse
Wait for about 1 minute and check whether the nodes are started and active and standby clusters are successfully selected.
sudo ubsectl display cluster
# Expected output example (two-node environment)
-------------------------------------------------------------------------------------------------------------
node role bonding-eid guid
-------------------------------------------------------------------------------------------------------------
controller(1) master 4245:4944:0000:0000:0000:0000:0100:0000 CC08-A000-0-0-000000-0000000800010000
node01(2) standby 4245:4944:0000:0000:0000:0000:0200:0000 CC08-A000-0-0-000000-0000000801000000
-------------------------------------------------------------------------------------------------------------
4.2 Building a Sample Program
Ensure that your Go version is 1.21 or later and CGO is enabled.
Build the sample program in the example/go directory.
cd example/go
go mod tidy
go build -o example example.go
After the compilation is complete, the executable file example is generated in the current directory. You need to manually transfer the executable file to the service runtime environment and modify the file permission based on service requirements.
4.3 Running the Sample Program
4.3.1 Configuring the Client Program
For details about the UBSE authentication mechanism, see UBSE Role-based Access Control Design. The user who delivers the configuration must have the root permission. Assume that the user who uses the UBSE API is test_user.
-
Add test_user to the UBSE user group.
sudo usermod -aG ubse test_user -
Create a custom permission configuration file for the client.
sudo touch /etc/ubse/auth_test_api.conf -
Edit the custom permission configuration file for the client.
sudo vi /etc/ubse/auth_test_api.confPress the i key to enter insert mode and copy the following content into the file:
# Authentication configuration file # Defines base user-role and role-permission mappings with priority flags. [auth.user] # Section for user-to-role mappings. test_user=test [auth.role] # Section for role-to-permission mappings. test=mem.numa,mem.shm,topoPress Esc to exit insert mode, type :wq, and press Enter to save and exit the editor.
-
Restart the UBSE service for the configuration to take effect.
sudo systemctl restart ubse
4.3.2 Running the Client Program
# Run the sample program.
./example
4.4 Precautions
-
Required permissions
- User permissions: The
ubsectlcommand can be used only by the root user and the UBSE user automatically created during installation. The API can be used only by the root user, the UBSE user automatically created during installation, and custom users added to the UBSE group. If the API is used by a custom user added to the UBSE group, a custom permission configuration file for the client needs to be configured.
- User permissions: The
-
Startup exception analysis
-
Node query error: If the error message is
ERROR: Failed to obtain cluster information, the current node has not been started or the startup is abnormal. You can query the service process status. If the process exists, the node is still being started. Try again later. -
Incomplete active/standby node information: If the queried node is the active node and the standby node status is empty, the current node has not been added to the cluster. You are advised to check whether the communication between nodes is normal.
-
-
CGO dependencies
- The UBS Engine Go API uses CGO to call the C library. Ensure that the GCC compiler and related C development libraries have been installed in the system.
-
Resource management
- You must call
engine.UbsEngineClientFinalize()to clean up resources before the program exits. You are advised to use thedeferstatement to ensure that resources are released.
- You must call