From a2a8765042697b6839818a39559cf911c7011ad7 Mon Sep 17 00:00:00 2001 From: RahulBanerji Date: Mon, 7 Dec 2020 13:42:19 +0530 Subject: [PATCH] Added A1 policy handler, healthcheck handler, sdl handler and alarm Issue-Id: [ RICAPP-157 | RICAPP-158 | RICAPP-159 | RICAPP-160 ] Change-Id: Icd0363fa6b6cc2d96252fb971d02db73e2c6b612 Signed-off-by: Rahul Banerji --- Dockerfile | 13 +++- README.md | 2 +- init/config-file.json | 48 +++++++++++++++ init/init_script.py | 125 ++++++++++++++++++++++++++++++++++++++ init/test_route.rt | 5 ++ resources/pod.yaml | 18 ++++++ resources/test_route.rt | 3 - setup.py | 13 +++- src/__init__.py | 1 + src/handler/A1PolicyHandler.py | 60 ++++++++++++++++++ src/handler/HealthCheckHandler.py | 38 ++++++++++++ src/handler/_BaseHandler.py | 41 +++++++++++++ src/handler/__init__.py | 20 ++++++ src/hwxapp.py | 84 +++++++++++++++++++++++++ src/main.py | 58 ++---------------- src/manager/A1PolicyManager.py | 34 +++++++++++ src/manager/SdlAlarmManager.py | 48 +++++++++++++++ src/manager/SdlManager.py | 41 +++++++++++++ src/manager/_BaseManager.py | 33 ++++++++++ src/manager/__init__.py | 21 +++++++ src/utils/__init__.py | 17 ++++++ src/utils/constants.py | 26 ++++++++ 22 files changed, 690 insertions(+), 59 deletions(-) create mode 100644 init/config-file.json create mode 100644 init/init_script.py create mode 100644 init/test_route.rt delete mode 100644 resources/test_route.rt create mode 100644 src/handler/A1PolicyHandler.py create mode 100644 src/handler/HealthCheckHandler.py create mode 100644 src/handler/_BaseHandler.py create mode 100644 src/handler/__init__.py create mode 100644 src/hwxapp.py create mode 100644 src/manager/A1PolicyManager.py create mode 100644 src/manager/SdlAlarmManager.py create mode 100644 src/manager/SdlManager.py create mode 100644 src/manager/_BaseManager.py create mode 100644 src/manager/__init__.py create mode 100644 src/utils/__init__.py create mode 100644 src/utils/constants.py diff --git a/Dockerfile b/Dockerfile index 34578ff..5f7a66e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ FROM python:3.8-alpine COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ # RMR setup RUN mkdir -p /opt/route/ -COPY resources/test_route.rt /opt/route/test_route.rt +COPY init/test_route.rt /opt/route/test_route.rt ENV LD_LIBRARY_PATH /usr/local/lib/:/usr/local/lib64 ENV RMR_SEED_RT /opt/route/test_route.rt @@ -28,10 +28,19 @@ RUN apk update && apk add gcc musl-dev bash # Install COPY setup.py /tmp +COPY README.md /tmp COPY LICENSE.txt /tmp/ COPY src/ /tmp/src +COPY init/ /tmp/init RUN pip install /tmp -# Run +# Env - TODO- Configmap ENV PYTHONUNBUFFERED 1 +ENV CONFIG_FILE=/tmp/init/config-file.json + +# For Default DB connection, modify for resp kubernetes env +ENV DBAAS_SERVICE_PORT=6379 +ENV DBAAS_SERVICE_HOST=service-ricplt-dbaas-tcp.ricplt.svc.cluster.local + +#Run CMD run-hw-python.py diff --git a/README.md b/README.md index e38d2af..eb323ec 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ This covers all three methods. 3. Kubernetes - +: Software Installation and Deployment ------------------------------------ The build process assumes a Linux environment with python >= 3.8 and has been tested on Ubuntu. For building docker images, diff --git a/init/config-file.json b/init/config-file.json new file mode 100644 index 0000000..5478079 --- /dev/null +++ b/init/config-file.json @@ -0,0 +1,48 @@ + { + "xapp_name": "hwxapp", + "version": "1.0.0", + "containers": [ + { + "name": "hwxapp", + "image": { + "registry": "nexus3.o-ran-sc.org:10002", + "name": "o-ran-sc/ric-app-hw", + "tag": "1.0.6" + } + } + ], + "messaging": { + "ports": [ + { + "name": "rmr-data", + "container": "hwxapp", + "port": 4560, + "rxMessages": [ + "A1_POLICY_REQ", "RIC_HEALTH_CHECK_REQ" + ], + "txMessages": [ "A1_POLICY_RESP", "A1_POLICY_QUERY", "RIC_HEALTH_CHECK_RESP" ], + "policies": [1], + "description": "rmr receive data port for HWxapp" + }, + { + "name": "rmr-route", + "container": "hwxapp", + "port": 4561, + "description": "rmr route port for hwxapp" + } + ] + }, + "rmr": { + "protPort": "tcp:4560", + "maxSize": 2072, + "numWorkers": 1, + "txMessages": [ + "RIC_SUB_REQ", "A1_POLICY_RESP", "A1_POLICY_QUERY", "RIC_HEALTH_CHECK_RESP" + ], + "rxMessages": [ + "RIC_SUB_RESP", + "A1_POLICY_REQ", "RIC_HEALTH_CHECK_REQ" + ], + "policies": [1] + } + } diff --git a/init/init_script.py b/init/init_script.py new file mode 100644 index 0000000..f8c9167 --- /dev/null +++ b/init/init_script.py @@ -0,0 +1,125 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + + +# This initialization script reads in a json from the specified config map path +# to set up the initializations (route config map, variables etc) for the main +# xapp process + +import json +import sys +import os +import signal +import time + +default_routing_file = "/opt/route/test_route.rt" +lport = 0 + + +def signal_handler(signum, frame): + print("Received signal {0}\n".format(signum)) + if xapp_subprocess is None or xapp_pid is None: + print("No xapp running. Quiting without sending signal to xapp\n", flush=True) + else: + print("Sending signal {0} to xapp ...".format(signum), flush=True) + xapp_subprocess.send_signal(signum) + + +def parseConfigJson(config): + for k1 in config.keys(): + if k1 in ParseSection: + result = ParseSection[k1](config) + if not result: + return False + + +def getMessagingInfo(config): + global lport + if 'messaging' in config.keys() and 'ports' in config['messaging'].keys(): + port_list = config['messaging']['ports'] + for portdesc in port_list: + if 'port' in portdesc.keys() and 'name' in portdesc.keys() and portdesc['name'] == 'rmr-data': + lport = portdesc['port'] + # Set the environment variable + os.environ["HW_PORT"] = str(lport) + return True + if lport == 0: + print("Error! No valid listening port", flush=True) + return False + + +def getXappName(config): + myKey = "xapp_name" + if myKey not in config.keys(): + print(("Error ! No information found for {0} in config\n".format(myKey)), flush=True) + return False + + xapp_name = config[myKey] + print("Xapp Name is: " + xapp_name) + os.environ["XAPP_NAME"] = xapp_name + + +ParseSection = dict() +ParseSection["xapp_name"] = getXappName +ParseSection["messaging"] = getMessagingInfo + +# ================================================================ +if __name__ == "__main__": + + import subprocess + + cmd = ["/usr/local/bin/run-hw-python.py"] + config_file = os.getenv("CONFIG_FILE", None) + + if config_file is None: + print("Error! No configuration file specified\n", flush=True) + sys.exit(1) + + with open(config_file, 'r') as f: + try: + config = json.load(f) + except Exception as e: + print(("Error loading json file from {0}. Reason = {1}\n".format(config_file, e)), flush=True) + sys.exit(1) + + result = parseConfigJson(config) + if not result: + print("Error parsing config json. Not executing xAPP", flush=True) + sys.exit(1) + + else: + + print("Config read successfully", flush=True) + + # Register signal handlers + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Start the xAPP + print("Executing xAPP ....", flush=True) + xapp_subprocess = subprocess.Popen(cmd, shell=False, stdin=None, stdout=None, stderr=None) + xapp_pid = xapp_subprocess.pid + + # Periodically poll the process every 5 seconds to check if still alive + while 1: + xapp_status = xapp_subprocess.poll() + if xapp_status is None: + time.sleep(5) + else: + print("XaPP terminated via signal {0}\n".format(-1 * xapp_status), flush=True) + break diff --git a/init/test_route.rt b/init/test_route.rt new file mode 100644 index 0000000..8e82103 --- /dev/null +++ b/init/test_route.rt @@ -0,0 +1,5 @@ +newrt|start +rte|13111|127.0.0.1:4560 +rte|20011|service-ricplt-a1mediator-rmr.ricplt:4562 +rte|20012|service-ricplt-a1mediator-rmr.ricplt:4562 +newrt|end diff --git a/resources/pod.yaml b/resources/pod.yaml index 30f55b9..5e6cd44 100644 --- a/resources/pod.yaml +++ b/resources/pod.yaml @@ -1,3 +1,21 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + apiVersion: v1 kind: Pod metadata: diff --git a/resources/test_route.rt b/resources/test_route.rt deleted file mode 100644 index 7f69614..0000000 --- a/resources/test_route.rt +++ /dev/null @@ -1,3 +0,0 @@ -newrt|start -rte|13111|127.0.0.1:4560 -newrt|end diff --git a/setup.py b/setup.py index 0da755d..e832e67 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,12 @@ # ================================================================================== from setuptools import setup, find_packages +import os + + +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + setup( name='hw_python', @@ -23,8 +29,13 @@ setup( packages=find_packages(), url='https://gerrit.o-ran-sc.org/r/admin/repos/ric-app/hw-python', license='Apache 2.0', + description="Hello World Python XAPP for O-RAN RIC Platform", + long_description=read('README.md'), + author='Rahul Banerji', + author_email='r.banerji@samsung.com', + python_requires='>=3.8', install_requires=["ricxappframe>=1.1.1,<2.0.0"], - entry_points={"console_scripts": ["run-hw-python.py=src.main:start"]}, # adds a magical entrypoint for Docker + entry_points={"console_scripts": ["run-hw-python.py=src.main:launchXapp"]}, # adds a magical entrypoint for Docker data_files=[("", ["LICENSE.txt"])], ) diff --git a/src/__init__.py b/src/__init__.py index 4f7e5d5..f035acd 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -13,4 +13,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# # ================================================================================== diff --git a/src/handler/A1PolicyHandler.py b/src/handler/A1PolicyHandler.py new file mode 100644 index 0000000..b21a0ac --- /dev/null +++ b/src/handler/A1PolicyHandler.py @@ -0,0 +1,60 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +import json +from ricxappframe.xapp_frame import RMRXapp, rmr +from ..utils.constants import Constants +from ._BaseHandler import _BaseHandler + + +class A1PolicyHandler(_BaseHandler): + + def __init__(self, rmr_xapp: RMRXapp, msgtype): + super().__init__(rmr_xapp, msgtype) + + def request_handler(self, rmr_xapp, summary, sbuf): + self._rmr_xapp.rmr_free(sbuf) + try: + req = json.loads(summary[rmr.RMR_MS_PAYLOAD]) # input should be a json encoded as bytes + self.logger.debug("A1PolicyHandler.resp_handler:: Handler processing request") + except (json.decoder.JSONDecodeError, KeyError): + self.logger.error("A1PolicyManager.resp_handler:: Handler failed to parse request") + return + + if self.verifyPolicy(req): + self.logger.info("A1PolicyHandler.resp_handler:: Handler processed request: {}".format(req)) + else: + self.logger.error("A1PolicyHandler.resp_handler:: Request verification failed: {}".format(req)) + return + self.logger.debug("A1PolicyHandler.resp_handler:: Request verification success: {}".format(req)) + + resp = self.buildPolicyResp(req) + self._rmr_xapp.rmr_send(json.dumps(resp).encode(), Constants.A1_POLICY_RESP) + self.logger.info("A1PolicyHandler.resp_handler:: Response sent: {}".format(resp)) + + def verifyPolicy(self, req: dict): + for i in ["policy_type_id", "operation", "policy_instance_id"]: + if i not in req: + return False + return True + + def buildPolicyResp(self, req: dict): + req["handler_id"] = self._rmr_xapp.config["xapp_name"] + del req["operation"] + req["status"] = "OK" + return req diff --git a/src/handler/HealthCheckHandler.py b/src/handler/HealthCheckHandler.py new file mode 100644 index 0000000..25f7dc9 --- /dev/null +++ b/src/handler/HealthCheckHandler.py @@ -0,0 +1,38 @@ +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +import json +from ricxappframe.xapp_frame import RMRXapp +from ..utils.constants import Constants +from ._BaseHandler import _BaseHandler +# from ..manager import SdlAlarmManager + + +class HealthCheckHandler(_BaseHandler): + + def __init__(self, rmr_xapp: RMRXapp, msgtype): + super().__init__(rmr_xapp, msgtype) + # self.sdl_alarm_mgr = SdlAlarmManager() + + def request_handler(self, rmr_xapp, summary, sbuf): + ok = self._rmr_xapp.healthcheck() + # self.sdl_alarm_mgr.checkSdl() + if ok: + payload = b"OK\n" + else: + payload = b"ERROR [RMR or SDL is unhealthy]\n" + self._rmr_xapp.rmr_rts(sbuf, new_payload=payload, new_mtype=Constants.RIC_HEALTH_CHECK_RESP) + self._rmr_xapp.rmr_free(sbuf) diff --git a/src/handler/_BaseHandler.py b/src/handler/_BaseHandler.py new file mode 100644 index 0000000..b99ed81 --- /dev/null +++ b/src/handler/_BaseHandler.py @@ -0,0 +1,41 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from ricxappframe.xapp_frame import RMRXapp +from abc import ABC, abstractmethod + + +class _BaseHandler(ABC): + """ + Represents base Abstract Handler class + Here initialize variables which will be common to all xapp + + Parameters: + rmr_xapp: Reference to original RMRxappframe object + msgtype: Integer specifying messagetype + """ + + def __init__(self, rmr_xapp: RMRXapp, msgtype): + self._rmr_xapp = rmr_xapp + self.logger = self._rmr_xapp.logger + self.msgtype = msgtype + self._rmr_xapp.register_callback(self.request_handler, msgtype) + + @abstractmethod + def request_handler(self, rmr_xapp, summary, sbuf): + pass diff --git a/src/handler/__init__.py b/src/handler/__init__.py new file mode 100644 index 0000000..5c7b391 --- /dev/null +++ b/src/handler/__init__.py @@ -0,0 +1,20 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from .A1PolicyHandler import A1PolicyHandler +from .HealthCheckHandler import HealthCheckHandler diff --git a/src/hwxapp.py b/src/hwxapp.py new file mode 100644 index 0000000..7d66d0c --- /dev/null +++ b/src/hwxapp.py @@ -0,0 +1,84 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from os import getenv +from ricxappframe.xapp_frame import RMRXapp, rmr +from .utils.constants import Constants +from .manager import * +from .handler import * +from mdclogpy import Logger + + +class HWXapp: + + def __init__(self): + fake_sdl = getenv("USE_FAKE_SDL", False) + self._rmr_xapp = RMRXapp(self._default_handler, + config_handler=self._handle_config_change, + rmr_port=4560, + post_init=self._post_init, + use_fake_sdl=bool(fake_sdl)) + + def _post_init(self, rmr_xapp): + """ + Function that runs when xapp initialization is complete + """ + rmr_xapp.logger.info("HWXapp.post_init :: post_init called") + # self.sdl_alarm_mgr = SdlAlarmManager() + sdl_mgr = SdlManager(rmr_xapp) + sdl_mgr.sdlGetGnbList() + a1_mgr = A1PolicyManager(rmr_xapp) + a1_mgr.startup() + + def _handle_config_change(self, rmr_xapp, config): + """ + Function that runs at start and on every configuration file change. + """ + rmr_xapp.logger.info("HWXapp.handle_config_change:: config: {}".format(config)) + rmr_xapp.config = config # No mutex required due to GIL + + def _default_handler(self, rmr_xapp, summary, sbuf): + """ + Function that processes messages for which no handler is defined + """ + rmr_xapp.logger.info("HWXapp.default_handler called for msg type = " + + str(summary[rmr.RMR_MS_MSG_TYPE])) + rmr_xapp.rmr_free(sbuf) + + def createHandlers(self): + """ + Function that creates all the handlers for RMR Messages + """ + HealthCheckHandler(self._rmr_xapp, Constants.RIC_HEALTH_CHECK_REQ) + A1PolicyHandler(self._rmr_xapp, Constants.A1_POLICY_REQ) + + def start(self, thread=False): + """ + This is a convenience function that allows this xapp to run in Docker + for "real" (no thread, real SDL), but also easily modified for unit testing + (e.g., use_fake_sdl). The defaults for this function are for the Dockerized xapp. + """ + self.createHandlers() + self._rmr_xapp.run(thread) + + def stop(self): + """ + can only be called if thread=True when started + TODO: could we register a signal handler for Docker SIGTERM that calls this? + """ + self._rmr_xapp.stop() diff --git a/src/main.py b/src/main.py index 10ad0f8..34875b3 100644 --- a/src/main.py +++ b/src/main.py @@ -13,62 +13,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# # ================================================================================== -import json -from os import getenv -from ricxappframe.xapp_frame import RMRXapp, rmr -from ricxappframe.alarm import alarm - - -# pylint: disable=invalid-name -rmr_xapp = None - - -def post_init(self): - """ - Function that runs when xapp initialization is complete - """ - self.logger.info("post_init called") - -def handle_config_change(self, config): - """ - Function that runs at start and on every configuration file change. - """ - self.logger.info("handle_config_change: config: {}".format(config)) - - -def default_handler(self, summary, sbuf): - """ - Function that processes messages for which no handler is defined - """ - self.logger.info("default_handler called") - self.rmr_free(sbuf) - +from .hwxapp import HWXapp -def start(thread=False): - """ - This is a convenience function that allows this xapp to run in Docker - for "real" (no thread, real SDL), but also easily modified for unit testing - (e.g., use_fake_sdl). The defaults for this function are for the Dockerized xapp. - """ - global rmr_xapp - fake_sdl = getenv("USE_FAKE_SDL", True) - config_file = getenv("CONFIG_FILE", None) - rmr_xapp = RMRXapp(default_handler, - config_handler=handle_config_change, - rmr_port=4560, - post_init=post_init, - use_fake_sdl=bool(fake_sdl)) - rmr_xapp.run(thread) +def launchXapp(): + hwxapp = HWXapp() + hwxapp.start() -def stop(): - """ - can only be called if thread=True when started - TODO: could we register a signal handler for Docker SIGTERM that calls this? - """ - rmr_xapp.stop() if __name__ == "__main__": - start() + launchXapp() diff --git a/src/manager/A1PolicyManager.py b/src/manager/A1PolicyManager.py new file mode 100644 index 0000000..57c6760 --- /dev/null +++ b/src/manager/A1PolicyManager.py @@ -0,0 +1,34 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +import json +from ricxappframe.xapp_frame import RMRXapp, rmr +from ..utils.constants import Constants +from ._BaseManager import _BaseManager + + +class A1PolicyManager(_BaseManager): + + def __init__(self, rmr_xapp: RMRXapp): + super().__init__(rmr_xapp) + + def startup(self): + policy_query = '{"policy_type_id":"' + str(Constants.HELLOWORLD_POLICY_ID) + '"}' + self._rmr_xapp.rmr_send(policy_query.encode(), Constants.A1_POLICY_QUERY) + self.logger.info("A1PolicyManager.startup:: Sent A1 policy query = " + policy_query) + diff --git a/src/manager/SdlAlarmManager.py b/src/manager/SdlAlarmManager.py new file mode 100644 index 0000000..dc5bd7b --- /dev/null +++ b/src/manager/SdlAlarmManager.py @@ -0,0 +1,48 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from ricxappframe.xapp_frame import RMRXapp +from ricxappframe.alarm import alarm +from ._BaseManager import _BaseManager + + +# noinspection PyProtectedMember,PyProtectedMember +class SdlAlarmManager(_BaseManager): + + def __init__(self, rmr_xapp: RMRXapp): + super().__init__(rmr_xapp) + self.alarm_mgr = alarm.AlarmManager(self._rmr_xapp._mrc, "ric-xapp", "hw-python") + self.alarm_sdl = None + + def checkSdl(self): + if self._rmr_xapp._sdl.healthcheck(): + # healthy, so clear the alarm if it was raised + if self.alarm_sdl: + self.logger.info("SdlAlarmManager:: clearing alarm") + self.alarm_mgr.clear_alarm(self.alarm_sdl) + self.alarm_sdl = None + else: + # not healthy, so (re-)raise the alarm + self.logger.info("SdlAlarmManager:: connection to SDL is not healthy, raising alarm") + if self.alarm_sdl: + self.alarm_mgr.reraise_alarm(self.alarm_sdl) + else: + self.alarm_sdl = self.alarm_mgr.create_alarm(1, alarm.AlarmSeverity.CRITICAL, + "SdlAlarmManager:: SDL failure") + self.alarm_mgr.raise_alarm(self.alarm_sdl) + self.logger.warning("SdlAlarmManager:: dropping request!") diff --git a/src/manager/SdlManager.py b/src/manager/SdlManager.py new file mode 100644 index 0000000..827e8f4 --- /dev/null +++ b/src/manager/SdlManager.py @@ -0,0 +1,41 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from ricxappframe.xapp_frame import RMRXapp +import json +from ._BaseManager import _BaseManager + + +class SdlManager(_BaseManager): + + __namespace = "e2Manager" + + def __init__(self, rmr_xapp: RMRXapp): + super().__init__(rmr_xapp) + + def sdlGetGnbList(self): + gnblist = self._rmr_xapp.sdl_find_and_get(self.__namespace, "GNB") + self.logger.info("SdlManager.sdlGetGnbList:: Processed request: {}".format(json.dumps(gnblist))) + + def sdlGetEnbList(self): + enblist = self._rmr_xapp.sdl_find_and_get(self.__namespace, "ENB") + self.logger.info("SdlManager.sdlGetGnbList:: Handler processed request: {}".format(json.dumps(enblist))) + + + + diff --git a/src/manager/_BaseManager.py b/src/manager/_BaseManager.py new file mode 100644 index 0000000..be8df7c --- /dev/null +++ b/src/manager/_BaseManager.py @@ -0,0 +1,33 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from ricxappframe.xapp_frame import RMRXapp +from abc import ABC + + +class _BaseManager(ABC): + """ + Represents base Manager Abstract class + Here initialize variables which will be common to all xapp + + Parameters: + rmr_xapp: Reference to original RMRxappframe object + """ + def __init__(self, rmr_xapp: RMRXapp): + self._rmr_xapp = rmr_xapp + self.logger = self._rmr_xapp.logger diff --git a/src/manager/__init__.py b/src/manager/__init__.py new file mode 100644 index 0000000..54b63c3 --- /dev/null +++ b/src/manager/__init__.py @@ -0,0 +1,21 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +from .A1PolicyManager import A1PolicyManager +from .SdlAlarmManager import SdlAlarmManager +from .SdlManager import SdlManager diff --git a/src/utils/__init__.py b/src/utils/__init__.py new file mode 100644 index 0000000..f035acd --- /dev/null +++ b/src/utils/__init__.py @@ -0,0 +1,17 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== diff --git a/src/utils/constants.py b/src/utils/constants.py new file mode 100644 index 0000000..55c12e2 --- /dev/null +++ b/src/utils/constants.py @@ -0,0 +1,26 @@ +# ================================================================================== +# +# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ================================================================================== + +class Constants: + A1_POLICY_QUERY = 20012 + HELLOWORLD_POLICY_ID = 2 + RIC_HEALTH_CHECK_REQ = 100 + RIC_HEALTH_CHECK_RESP = 101 + A1_POLICY_REQ = 20010 + A1_POLICY_RESP = 20011 + RIC_ALARM_UPDATE = 110 -- 2.16.6