示例#1
0
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 test_config_no_env(monkeypatch):
    init_config_file()
    monkeypatch.delenv(Constants.CONFIG_FILE_ENV, raising=False)

    def default_rmr_handler(self, summary, sbuf):
        pass

    config_event_seen = False

    def config_handler(self, json):
        nonlocal config_event_seen
        config_event_seen = True

    global rmr_xapp_noconfig
    rmr_xapp_noconfig = RMRXapp(default_rmr_handler,
                                config_handler=config_handler,
                                rmr_port=4652,
                                use_fake_sdl=True)
    # in unit tests we need to thread here or else execution is not returned!
    rmr_xapp_noconfig.run(thread=True, rmr_timeout=1)

    write_config_file()
    # give the work loop a chance to timeout on RMR and process the config event
    time.sleep(3)
    assert not config_event_seen
    rmr_xapp_noconfig.stop()
    rmr_xapp_noconfig = None
示例#3
0
def test_rmr_healthcheck():
    # thanos uses the rmr xapp to healthcheck the rmr xapp

    # test variables
    health_pay = None

    def post_init(self):
        self.rmr_send(b"", RIC_HEALTH_CHECK_REQ)

    def default_handler(self, summary, sbuf):
        pass

    global rmr_xapp_health
    rmr_xapp_health = RMRXapp(default_handler,
                              post_init=post_init,
                              rmr_port=4666,
                              use_fake_sdl=True)

    def health_handler(self, summary, sbuf):
        nonlocal health_pay
        health_pay = summary["payload"]
        self.rmr_free(sbuf)

    rmr_xapp_health.register_callback(health_handler, RIC_HEALTH_CHECK_RESP)
    rmr_xapp_health.run(
        thread=True
    )  # in unit tests we need to thread here or else execution is not returned!

    time.sleep(1)

    assert health_pay == b"OK\n"
示例#4
0
def test_custom_config_handler(monkeypatch):
    # point watcher at the file
    init_config_file()
    monkeypatch.setenv(CONFIG_FILE_ENV, config_file_path)

    def default_handler(self, summary, sbuf):
        pass

    startup_config_event = False
    change_config_event = False

    def config_handler(self, json):
        mdc_logger.info("config_handler: json {}".format(json))
        nonlocal startup_config_event
        nonlocal change_config_event
        if "start" in json:
            startup_config_event = True
        if "change" in json:
            change_config_event = True

    # listen port is irrelevant, no messages arrive
    global rmr_xapp_config
    rmr_xapp_config = RMRXapp(default_handler,
                              config_handler=config_handler,
                              rmr_port=4567,
                              use_fake_sdl=True)
    assert startup_config_event
    rmr_xapp_config.run(
        thread=True, rmr_timeout=1
    )  # in unit tests we need to thread here or else execution is not returned!
    write_config_file()
    # give the work loop a chance to timeout on RMR and process the config event
    time.sleep(3)
    assert change_config_event
    rmr_xapp_config.stop()
def test_bad_init():
    """test that an xapp whose rmr fails to init blows up"""
    def entry(self):
        pass

    with pytest.raises(InitFailed):
        bad_xapp = Xapp(entrypoint=entry, rmr_port=-1)
        bad_xapp.run()  # we wont get here

    def defh(self):
        pass

    with pytest.raises(InitFailed):
        bad_xapp = RMRXapp(default_handler=defh, rmr_port=-1)
        bad_xapp.run()  # we wont get here
示例#6
0
def test_rmr_init():

    # test variables
    def_pay = None
    sixty_pay = None

    # create rmr app

    def default_handler(self, summary, sbuf):
        nonlocal def_pay
        def_pay = json.loads(summary["payload"])
        self.rmr_free(sbuf)

    def sixtythou_handler(self, summary, sbuf):
        nonlocal sixty_pay
        sixty_pay = json.loads(summary["payload"])
        self.rmr_free(sbuf)

    global rmr_xapp
    rmr_xapp = RMRXapp(default_handler, rmr_port=4564, use_fake_sdl=True)
    rmr_xapp.register_callback(sixtythou_handler, 60000)
    rmr_xapp.run(
        thread=True
    )  # in unit tests we need to thread here or else execution is not returned!

    time.sleep(1)

    # create a general xapp that will demonstrate some SDL functionality and launch some requests against the rmr xapp

    def entry(self):

        time.sleep(1)

        self.sdl_set("testns", "mykey", 6)
        assert self.sdl_get("testns", "mykey") == 6
        assert self.sdl_find_and_get("testns", "myk") == {"mykey": 6}
        assert self.healthcheck()

        val = json.dumps({"test send 60000": 1}).encode()
        self.rmr_send(val, 60000)

        val = json.dumps({"test send 60001": 2}).encode()
        self.rmr_send(val, 60001)

        self.sdl_delete("testns", "bogus")

    global gen_xapp
    gen_xapp = Xapp(entrypoint=entry, use_fake_sdl=True)
    gen_xapp.run()

    time.sleep(1)

    assert def_pay == {"test send 60001": 2}
    assert sixty_pay == {"test send 60000": 1}
示例#7
0
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.
    """
    logger.debug("QP xApp starting")
    global qp_xapp
    fake_sdl = os.environ.get("USE_FAKE_SDL", None)
    qp_xapp = RMRXapp(qp_default_handler,
                      rmr_port=4560,
                      post_init=post_init,
                      use_fake_sdl=bool(fake_sdl))
    qp_xapp.register_callback(qp_predict_handler, 30001)
    qp_xapp.run(thread)
def test_init_rmr_xapp():
    def post_init(self):
        print("hey")

    def foo(self, _summary, _sbuf):
        pass

    rmr_xapp = RMRXapp(foo,
                       post_init=post_init,
                       rmr_wait_for_ready=False,
                       use_fake_sdl=True)
    # pytest will never return without thread and stop
    rmr_xapp.run(thread=True)
    time.sleep(1)
    rmr_xapp.stop()
示例#9
0
def test_rmr_flow(monkeypatch, qpd_to_qp, qp_prediction):
    """
    this flow mocks out the xapps on both sides of QP.
    It first stands up a mock ts, then it starts up a mock qp-driver
    which will immediately send requests to the running qp.
    """

    expected_result = {}

    # define a mock traffic steering xapp that listens on 4563
    def mock_ts_default_handler(self, summary, sbuf):
        pass

    def mock_ts_prediction_handler(self, summary, sbuf):
        nonlocal expected_result  # closures ftw
        pay = json.loads(summary["payload"])
        expected_result = pay

    global mock_ts_xapp
    mock_ts_xapp = RMRXapp(mock_ts_default_handler,
                           rmr_port=4563,
                           use_fake_sdl=True)
    mock_ts_xapp.register_callback(mock_ts_prediction_handler, 30002)
    mock_ts_xapp.run(thread=True)

    time.sleep(1)

    # define a mock qp driver xapp that sends a message to QP under test
    def mock_qpd_entry(self):

        # good traffic steering request
        val = json.dumps(qpd_to_qp).encode()
        self.rmr_send(val, 30001)

        # should trigger the default handler and do nothing
        val = json.dumps({"test send 60001": 2}).encode()
        self.rmr_send(val, 60001)

    global mock_qpd_xapp
    mock_qpd_xapp = Xapp(entrypoint=mock_qpd_entry,
                         rmr_port=4666,
                         use_fake_sdl=True)
    mock_qpd_xapp.run()  # this will return since entry isn't a loop

    time.sleep(1)

    assert main.get_stats() == {"PredictRequests": 1}
    assert expected_result == qp_prediction
示例#10
0
def test_default_config_handler(monkeypatch):
    """Just for coverage"""
    init_config_file()
    monkeypatch.setenv(CONFIG_FILE_ENV, config_file_path)

    def default_rmr_handler(self, summary, sbuf):
        pass

    # listen port is irrelevant, no messages arrive
    global rmr_xapp_defconfig
    rmr_xapp_defconfig = RMRXapp(default_rmr_handler,
                                 rmr_port=4567,
                                 use_fake_sdl=True)
    # in unit tests we need to thread here or else execution is not returned!
    rmr_xapp_defconfig.run(thread=True, rmr_timeout=1)
    write_config_file()
    # give the work loop a chance to timeout on RMR and process the config event
    time.sleep(3)
    rmr_xapp_defconfig.stop()
示例#11
0
def post_init(_self):
    """post init"""
    print("pong xapp could do some useful stuff here!")


def sixtyh(self, summary, sbuf):
    """callback for 60000"""
    self.logger.info("pong registered 60000 handler called!")
    # see comment in ping about this; bytes does not work with the ric mdc logger currently
    print("pong 60000 handler received: {0}".format(summary))
    jpay = json.loads(summary['payload'])
    self.rmr_rts(sbuf,
                 new_payload=json.dumps({
                     "ACK": jpay["test_send"]
                 }).encode(),
                 new_mtype=60001,
                 retries=100)
    self.rmr_free(sbuf)


def defh(self, summary, sbuf):
    """default callback"""
    self.logger.info("pong default handler called!")
    print("pong default handler received: {0}".format(summary))
    self.rmr_free(sbuf)


xapp = RMRXapp(default_handler=defh, post_init=post_init, use_fake_sdl=True)
xapp.register_callback(sixtyh, 60000)
xapp.run()  # will not thread by default
示例#12
0
def test_rmr_flow(monkeypatch, qpd_to_qp, qpd_to_qp_bad_cell):
    """
    this flow mocks out the xapps on both sides of QP driver.
    It first stands up a mock qp, then it starts up a mock ts
    which will immediately send requests to the running qp driver.
    """

    expected_result = {}

    # define a mock qp predictor
    def mock_qp_default_handler(self, summary, sbuf):
        pass

    def mock_qp_predict_handler(self, summary, sbuf):
        nonlocal expected_result  # closures ftw
        pay = json.loads(summary["payload"])
        expected_result[pay["PredictionUE"]] = pay

    global mock_qp_xapp
    mock_qp_xapp = RMRXapp(mock_qp_default_handler,
                           rmr_port=4666,
                           use_fake_sdl=True)
    mock_qp_xapp.register_callback(mock_qp_predict_handler, 30001)
    mock_qp_xapp.run(thread=True)

    time.sleep(1)

    # define a mock traffic steering xapp
    def mock_ts_entry(self):

        # make sure a bad steering request doesn't blow up in qpd
        val = "notevenjson".encode()
        self.rmr_send(val, 30000)
        val = json.dumps({
            "bad": "tothebone"
        }).encode()  # json but missing UEPredictionSet
        self.rmr_send(val, 30000)

        # valid request body but missing cell id
        val = json.dumps({"UEPredictionSet": ["VOIDOFLIGHT"]}).encode()
        self.rmr_send(val, 30000)

        # good traffic steering request
        val = json.dumps({"UEPredictionSet": ["12345", "8675309"]}).encode()
        self.rmr_send(val, 30000)

        # should trigger the default handler and do nothing
        val = json.dumps({"test send 60001": 2}).encode()
        self.rmr_send(val, 60001)

    global mock_ts_xapp
    mock_ts_xapp = Xapp(entrypoint=mock_ts_entry,
                        rmr_port=4564,
                        use_fake_sdl=True)
    mock_ts_xapp.run()  # this will return since entry isn't a loop

    time.sleep(1)

    assert expected_result == {
        "12345": qpd_to_qp,
        "8675309": qpd_to_qp_bad_cell
    }
    assert main.get_stats() == {"DefCalled": 1, "SteeringRequests": 4}

    # break SDL and send traffic again
    def sdl_healthcheck_fails(self):
        return False

    monkeypatch.setattr("ricxappframe.xapp_sdl.SDLWrapper.healthcheck",
                        sdl_healthcheck_fails)
    mock_ts_xapp.run()

    # restore SDL and send traffic once more
    def sdl_healthcheck_passes(self):
        return True

    monkeypatch.setattr("ricxappframe.xapp_sdl.SDLWrapper.healthcheck",
                        sdl_healthcheck_passes)
    mock_ts_xapp.run()