Write your first xApp in Python
hello-xapp that subscribes to E2 indications from a simulated E2 Node, package it into a container, and onboard it via dms_cli to the Near-RT RIC you stood up in Lab 01.0Prerequisites
- Lab 01 complete — Near-RT RIC running on
kind python3≥ 3.9 withpipdocker(to build the xApp image)
1Clone the xApp framework
git clone "https://gerrit.o-ran-sc.org/r/ric-plt/xapp-frame-py" xapp-frame-py cd xapp-frame-py git checkout bronze pip install -e .
2Write hello-xapp.py
Create a new directory and write the xApp:
mkdir hello-xapp && cd hello-xapp
cat > hello_xapp.py <<'EOF'
from ricxappframe.xapp_frame import Xapp, RMRXapp, rmr
class HelloXapp(Xapp):
def __init__(self):
super().__init__(entrypoint=self.entry, rmr_port=4560, use_fake_sdl=False)
self.logger.info("hello-xapp instantiated")
def entry(self, sdl):
self.logger.info("xApp main loop started")
while True:
for msg in self.rmr_get_messages():
self.logger.info(f"got message: mtype={msg.mtype} len={len(msg.payload)}")
msg.payload = b"ACK from hello-xapp"
self.rmr_send(msg)
sleep(1)
if __name__ == "__main__":
HelloXapp().run()
EOF
3Add the xApp descriptor
Every xApp needs a JSON descriptor that tells the RIC platform what RMR messages it handles and what config it needs. Create config-file.json:
cat > config-file.json <<'EOF'
{
"xapp_name": "hello-xapp",
"version": "1.0.0",
"containers": [{
"name": "hello-xapp",
"image": {"registry":"docker.io","name":"hello-xapp","tag":"1.0.0"}
}],
"messaging": {
"ports": [{
"name": "rmr-data",
"container": "hello-xapp",
"port": 4560,
"rxMessages": ["RIC_SUB_RESP","RIC_INDICATION"],
"txMessages": ["RIC_SUB_REQ","RIC_CONTROL_REQ"],
"policies": [],
"description": "RMR data port for xApp"
}]
},
"metrics": [],
"rmr": {"protPort":"tcp:4560","maxSize":2072,"numWorkers":1,"txMessages":["RIC_SUB_REQ"],"rxMessages":["RIC_INDICATION"]}
}
EOF
4Containerize
cat > Dockerfile <<'EOF' FROM python:3.10-slim WORKDIR /app RUN pip install ricxappframe COPY hello_xapp.py config-file.json /app/ ENV CONFIG_FILE=/app/config-file.json CMD ["python3","-u","hello_xapp.py"] EOF docker build -t hello-xapp:1.0.0 . kind load docker-image hello-xapp:1.0.0 --name oran-ric
The kind load step makes the image available inside the kind cluster.
5Onboard via dms_cli
The xApp Onboarder service (in the RIC) accepts xApp packages via its REST API. Use dms_cli:
pip install xapp-dms-cli kubectl -n ricplt port-forward svc/service-ricplt-xapp-onboarder-http 8888:8888 & dms_cli onboard --config_file_path=./config-file.json --shcema_file_path=./schema.json
If onboarding succeeds, the xApp appears in the catalog:
dms_cli get_charts_list
6Deploy
dms_cli install --xapp_chart_name=hello-xapp --version=1.0.0 --namespace=ricxapp
Then verify it's running:
kubectl -n ricxapp get pods
Expected: deployment-ricxapp-hello-xapp-... 1/1 Running
7Watch the xApp logs
kubectl -n ricxapp logs -f deployment/deployment-ricxapp-hello-xapp
You'll see hello-xapp instantiated and xApp main loop started. Since there's no E2 Node attached yet, no messages flow. We'll attach one in Lab 03.
Checkpoint
hello-xapppod STATUS =Runninginricxappnamespace- Logs show
main loop started - RMR port 4560 is exposed inside the cluster
- Onboarder catalog shows
hello-xappversion1.0.0