[bumpversion]
-current_version = 2.1.9
+current_version = 2.2.0
commit = False
tag = False
ENV USE_FAKE_SDL False
ENV PYTHONUNBUFFERED 1
# pip installs console script to ~/.local/bin so PATH is critical
-ENV PATH=/home/a1user/.local/bin:$PATH
+ENV PATH /home/a1user/.local/bin:$PATH
+# prometheus client gathers data here
+ENV prometheus_multiproc_dir /tmp
# Run!
CMD run-a1
contains the app; broken out here for ease of unit testing
"""
import connexion
+from prometheus_client import CollectorRegistry, generate_latest, multiprocess
app = connexion.App(__name__, specification_dir=".")
app.add_api("openapi.yaml", arguments={"title": "My Title"})
+
+
+# python decorators feel like black magic to me
+@app.app.route('/a1-p/metrics', methods=['GET'])
+def metrics(): # pylint: disable=unused-variable
+ # /metrics API shouldn't be visible in the API documentation,
+ # hence it's added here in the create_app step
+ # requires environment variable prometheus_multiproc_dir
+ registry = CollectorRegistry()
+ multiprocess.MultiProcessCollector(registry)
+ return generate_latest(registry)
from jsonschema import validate
from jsonschema.exceptions import ValidationError
import connexion
+from prometheus_client import Counter
from mdclogpy import Logger
from ricsdl.exceptions import RejectedByBackend, NotConnected, BackendError
from a1 import a1rmr, exceptions, data
mdc_logger = Logger(name=__name__)
+request_counter = Counter('policy_requests', 'Policy type and instance requests', ['action', 'target'])
def _log_build_http_resp(exception, http_resp_code):
"""
Handles PUT /a1-p/policytypes/policy_type_id
"""
+ request_counter.labels(action='create', target='policy_type').inc()
def put_type_handler():
data.store_policy_type(policy_type_id, body)
"""
Handles DELETE /a1-p/policytypes/policy_type_id
"""
+ request_counter.labels(action='delete', target='policy_type').inc()
def delete_policy_type_handler():
data.delete_policy_type(policy_type_id)
"""
Handles PUT /a1-p/policytypes/polidyid/policies/policy_instance_id
"""
+ request_counter.labels(action='create', target='policy_inst').inc()
instance = connexion.request.json
def put_instance_handler():
"""
Handles DELETE /a1-p/policytypes/polidyid/policies/policy_instance_id
"""
+ request_counter.labels(action='delete', target='policy_inst').inc()
def delete_instance_handler():
data.delete_policy_instance(policy_type_id, policy_instance_id)
# 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: 2.1.9
+tag: 2.2.0
- Connexion
- Flask with Gevent serving
- Swagger
+- Prometheus
+
Version bumping A1
------------------
#. ``integration_tests/install_rmr.sh`` is a useful script for a
variety of local testing.
+
Version bumping Python
----------------------
#. ``Dockerfile-Unit-Test``
#. ``tox.ini``
+
+Running A1 Standalone
+---------------------
+
+The A1 container can be run standalone, which means using an in-memory mock
+version of SDL and a static route table. The host machine must have the RMR
+library and the environment must define the variable `prometheus_multiproc_dir`
+with a value like /tmp. Alternately, use the following command to run A1 as
+a Docker container, using a route table mounted as a file from this git
+repository and exposing the server's HTTP port on the Docker host::
+
+ docker run -e USE_FAKE_SDL=True -p 10000:10000 -v `pwd`:/opt/route [DOCKER_IMAGE_ID_HERE]
+
+Then test the server with an invocation such as this::
+
+ curl localhost:10000/a1-p/healthcheck
+
+
Unit Testing
------------
docker build --no-cache -f Dockerfile-Unit-Test .
+
Integration testing
-------------------
:depth: 3
:local:
-Optional ENV Variables
-----------------------
+Environment Variables
+---------------------
You can set the following environment variables when launching a container to change the A1 behavior:
4. ``USE_FAKE_SDL``: This allows testing of the A1 feature without a DBaaS SDL container. The default is False.
-K8S
----
-The "real" helm chart for A1 is in the LF it/dep repo. That repo holds all of the helm charts for the RIC platform. There is a helm chart in `integration_tests` here for running the integration tests as discussed above.
+5. ``prometheus_multiproc_dir``: The directory where Prometheus gathers metrics. The default is /tmp.
-Local Docker
--------------
+
+Kubernetes Deployment
+---------------------
+The official Helm chart for the A1 Mediator is in a deployment repository, which holds all of the Helm charts
+for the RIC platform. There is a helm chart in `integration_tests` here for running the integration tests as
+discussed above.
+
+Local Deployment
+----------------
+
+Build and run the A1 mediator locally using the docker CLI as follows.
Build the image
~~~~~~~~~~~~~~~
Overview
========
+.. contents::
+ :depth: 3
+ :local:
+
The RAN Intelligent Controller (RIC) Platform's A1 Mediator component
listens for policy type and policy instance requests sent via HTTP
(the "northbound" interface), and publishes those requests to running
and this project adheres to `Semantic Versioning <http://semver.org/>`__.
+[2.2.0] - 2020-05-28
+--------------------
+
+* Add counters of create/update/delete actions on policy types and instances
+* Add Prometheus /metrics endpoint to report counter data
+
+
[2.1.9] - 2020-05-26
--------------------
User Guide and APIs
===================
+.. contents::
+ :depth: 3
+ :local:
+
This document explains how to communicate with the A1 Mediator.
Information for maintainers of this platform component is in the Developer Guide.
}
+For example, if you put the JSON above into a file called "create.json" you can use
+the curl command-line tool to send the request::
+
+ curl -X PUT --header "Content-Type: application/json" --data-raw @create.json http://localhost/a1-p/policytypes/20008
+
+
Send the following JSON to create an instance of policy type 20008:
.. code-block:: yaml
}
+For example, you can use the curl command-line tool to send this request::
+
+ curl -X PUT --header "Content-Type: application/json" --data '{"threshold" : 5}' http://localhost/a1-p/policytypes/20008/policies/tsapolicy145
+
+
Integrating Xapps with A1
-------------------------
apiVersion: v1
description: A1 Helm chart for Kubernetes
name: a1mediator
-version: 2.1.9
+version: 2.2.0
setup(
name="a1",
- version="2.1.9",
+ version="2.2.0",
packages=find_packages(exclude=["tests.*", "tests"]),
author="Tommy Carpenter",
description="RIC A1 Mediator for policy/intent changes",
url="https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/a1",
entry_points={"console_scripts": ["run-a1=a1.run:main"]},
# we require jsonschema, should be in that list, but connexion already requires a specific version of it
- install_requires=["requests", "Flask", "connexion[swagger-ui]", "gevent", "mdclogpy", "ricxappframe>=1.0.0,<2.0.0"],
+ install_requires=["requests", "Flask", "connexion[swagger-ui]", "gevent", "prometheus-client", "mdclogpy", "ricxappframe>=1.0.0,<2.0.0"],
package_data={"a1": ["openapi.yaml"]},
)
assert res.status_code == 200
+def test_metrics(client):
+ """
+ test Prometheus metrics
+ """
+ res = client.get("/a1-p/metrics")
+ assert res.status_code == 200
+
+
def teardown_module():
"""module teardown"""
a1rmr.stop_rmr_thread()
A1_RMR_RETRY_TIMES = 2
INSTANCE_DELETE_NO_RESP_TTL = 3
INSTANCE_DELETE_RESP_TTL = 3
+ prometheus_multiproc_dir = /tmp
# Note, before this will work, for the first time on that machine, run ./install_deps.sh
commands =