From: Tommy Carpenter Date: Fri, 27 Mar 2020 12:31:01 +0000 (-0400) Subject: Implement SDL calls and testing X-Git-Tag: 1.0.1~3 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F32%2F3032%2F2;p=ric-app%2Fqp-driver.git Implement SDL calls and testing Issue-ID: RICAPP-92 Change-Id: I15e86369b72ab19df5548d09c56c95b603495356 Signed-off-by: Tommy Carpenter --- diff --git a/container-tag.yaml b/container-tag.yaml index 61e4b76..a6eeb69 100644 --- a/container-tag.yaml +++ b/container-tag.yaml @@ -1,4 +1,4 @@ # The Jenkins job uses this string for the tag in the image name # for example nexus3.o-ran-sc.org:10004/my-image-name:my-tag --- -tag: 0.1.0 +tag: 0.2.0 diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 4aeb5b0..5d4c3c3 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -14,6 +14,14 @@ and this project adheres to `Semantic Versioning `__. :depth: 3 :local: +[0.2.0] - 3/27/2020 +------------------- +:: + + * Implement SDL calls and testing + * Small cleanups + + [0.1.0] - 3/26/2020 ------------------- :: diff --git a/qpdriver/data.py b/qpdriver/data.py index 0e18dd5..e08a0ac 100644 --- a/qpdriver/data.py +++ b/qpdriver/data.py @@ -17,6 +17,10 @@ qpdriver module responsible for SDL queries and data merging # limitations under the License. # ================================================================================== +# namespaces +UE_NS = "TS-UE-metrics" +CELL_NS = "TS-cell-metrics" + # list of keys in ue metrics that we want to carry over to qp pred UE_KEY_LIST = set( [ @@ -48,17 +52,7 @@ CELL_KEY_LIST = set( ) -def _fetch_ue_metrics(ueid): - """fetch ue metrics for ueid""" - return {} - - -def _fetch_cell_metrics(cellid): - """fetch cell metrics for a cellid""" - return {} - - -def form_qp_pred_req(ueid): +def form_qp_pred_req(xapp_ref, ueid): """ this function takes in a single ueid and: - fetches the current ue data @@ -67,7 +61,7 @@ def form_qp_pred_req(ueid): Note that a single request to qp driver may have many UEs in a list, however since a new message needs to be sent for each one, the calling function iterates over that list, rather than doing it here. """ - ue_data = _fetch_ue_metrics(ueid) + ue_data = xapp_ref.sdl_get(UE_NS, str(ueid), usemsgpack=False) serving_cid = ue_data["ServingCellID"] @@ -88,7 +82,7 @@ def form_qp_pred_req(ueid): # form the CellMeasurements for cid in cell_ids: - cellm = _fetch_cell_metrics(cid) + cellm = xapp_ref.sdl_get(CELL_NS, cid, usemsgpack=False) # if we were really under performance strain here we could delete from the orig instead of copying but this code is far simpler cell_data = {k: cellm[k] for k in CELL_KEY_LIST} diff --git a/qpdriver/main.py b/qpdriver/main.py index decf7aa..f58f460 100644 --- a/qpdriver/main.py +++ b/qpdriver/main.py @@ -18,12 +18,6 @@ qpdriver entrypoint module # ================================================================================== from ricxappframe.xapp_frame import RMRXapp - -""" -This is only a stencil for now, will be filled in! -What is currently here was only for initial skeleton and test creation. -""" - """ RMR Messages #define TS_UE_LIST 30000 @@ -32,6 +26,9 @@ RMR Messages """ +rmr_xapp = None + + def post_init(self): self.def_hand_called = 0 self.traffic_steering_requests = 0 @@ -39,7 +36,7 @@ def post_init(self): def default_handler(self, summary, sbuf): self.def_hand_called += 1 - print(summary) + self.logger.info("QP Driver received an unexpected message of type: {}, dropping.".format(summary["message type"])) self.rmr_free(sbuf) @@ -57,17 +54,23 @@ def steering_req_handler(self, summary, sbuf): self.rmr_free(sbuf) -# obv some of these flags have to change -rmr_xapp = RMRXapp(default_handler, post_init=post_init, rmr_port=4562, use_fake_sdl=True) -rmr_xapp.register_callback(steering_req_handler, 30000) - - -def start(thread=False): +def start(thread=False, use_fake_sdl=False): + """ + this is a convienence 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 + rmr_xapp = RMRXapp(default_handler, post_init=post_init, rmr_port=4562, use_fake_sdl=use_fake_sdl) + rmr_xapp.register_callback(steering_req_handler, 30000) rmr_xapp.run(thread) def stop(): - """can only be called if thread=True when started""" + """ + 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() diff --git a/setup.py b/setup.py index 7d22ec7..f8c5b1a 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ from setuptools import setup, find_packages setup( name="qpdriver", - version="0.1.0", + version="0.2.0", packages=find_packages(exclude=["tests.*", "tests"]), author="Tommy Carpenter", description="QP Driver Xapp for traffic steering", diff --git a/tests/test_data.py b/tests/test_data.py deleted file mode 100644 index 4a207f8..0000000 --- a/tests/test_data.py +++ /dev/null @@ -1,37 +0,0 @@ -# ================================================================================== -# Copyright (c) 2020 AT&T Intellectual Property. -# -# 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 qpdriver import data - - -def test_merge(monkeypatch, ue_metrics, cell_metrics_1, cell_metrics_2, cell_metrics_3, qpd_to_qp): - - # monkeypatch - def fake_ue(ueid): - if ueid == 12345: - return ue_metrics - - def fake_cell(cellid): - if cellid == "310-680-200-555001": - return cell_metrics_1 - if cellid == "310-680-200-555002": - return cell_metrics_2 - if cellid == "310-680-200-555003": - return cell_metrics_3 - - monkeypatch.setattr("qpdriver.data._fetch_ue_metrics", fake_ue) - monkeypatch.setattr("qpdriver.data._fetch_cell_metrics", fake_cell) - - assert data.form_qp_pred_req(12345) == qpd_to_qp diff --git a/tests/test_qpd.py b/tests/test_qpd.py index 96d4dd1..62bd67f 100644 --- a/tests/test_qpd.py +++ b/tests/test_qpd.py @@ -16,19 +16,47 @@ import json import time from contextlib import suppress -from qpdriver import main +from qpdriver import main, data from ricxappframe.xapp_frame import Xapp test_sender = None +""" + these tests are not currently parallelizable (do not use this tox flag) + I would use setup_module, however that can't take monkeypatch fixtures + Currently looking for the best way to make this better: https://stackoverflow.com/questions/60886013/python-monkeypatch-in-pytest-setup-module +""" -def test_flow(): + +def test_init_xapp(monkeypatch, ue_metrics, cell_metrics_1, cell_metrics_2, cell_metrics_3, qpd_to_qp): + # monkeypatch post_init to set the data we want in SDL + def fake_post_init(self): + self.def_hand_called = 0 + self.traffic_steering_requests = 0 + self.sdl_set(data.UE_NS, "12345", ue_metrics, usemsgpack=False) + self.sdl_set(data.CELL_NS, "310-680-200-555001", cell_metrics_1, usemsgpack=False) + self.sdl_set(data.CELL_NS, "310-680-200-555002", cell_metrics_2, usemsgpack=False) + self.sdl_set(data.CELL_NS, "310-680-200-555003", cell_metrics_3, usemsgpack=False) + + # patch + monkeypatch.setattr("qpdriver.main.post_init", fake_post_init) + + # start qpd + main.start(thread=True, use_fake_sdl=True) + + +def test_data_merge(qpd_to_qp): """ - just a skeleton for now.. this will evolve when qpd evolves + test the merge (basically tests all of the code in data.py in this one line) + TODO: this will go away when the full E2E flow is implemented as we can just look at the final result """ + assert data.form_qp_pred_req(main.rmr_xapp, 12345) == qpd_to_qp - # start qpd - main.start(thread=True) + +def test_rmr_flow(monkeypatch, ue_metrics, cell_metrics_1, cell_metrics_2, cell_metrics_3, qpd_to_qp): + """ + just a skeleton for now.. this will evolve when qpd evolves + """ # define a test sender def entry(self):