Extend user guide with southbound API details 72/3872/2
authorLott, Christopher (cl778h) <cl778h@att.com>
Wed, 27 May 2020 13:45:49 +0000 (09:45 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Wed, 27 May 2020 14:18:30 +0000 (10:18 -0400)
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
Change-Id: I66b9603eb70ad41841a06e43e4d48a70dcb9768f

docs/api-spec.rst [deleted file]
docs/conf.yaml
docs/developer-guide.rst
docs/index.rst
docs/installation-guide.rst
docs/overview.rst
docs/release-notes.rst
docs/user-guide-api.rst [new file with mode: 0644]

diff --git a/docs/api-spec.rst b/docs/api-spec.rst
deleted file mode 100644 (file)
index 2191c4d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-.. This work is licensed under a Creative Commons Attribution 4.0 International License.
-.. SPDX-License-Identifier: CC-BY-4.0
-
-A1 Mediator API
-===============
-
-This page shows the Open API specification for the A1 Mediator.
-Alternately, if you have checked out the code and are running the server,
-you can see a formatted version at this URL: ``http://localhost:10000/ui/``.
-
-OpenAPI Specification
----------------------
-
-.. literalinclude:: ../a1/openapi.yaml
-   :language: yaml
-   :linenos:
index 8f8b08a..721e54b 100644 (file)
@@ -1,3 +1,3 @@
 ---
 project_cfg: oran
-project: a1
+project: A1 Mediator
index 97c18a2..2f2447c 100644 (file)
@@ -1,8 +1,8 @@
 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
 .. http://creativecommons.org/licenses/by/4.0
 
-A1 Developer Guide
-==================
+Developer Guide
+===============
 
 .. contents::
    :depth: 3
@@ -11,8 +11,8 @@ A1 Developer Guide
 Tech Stack
 ----------
 
-The A1 Mediator is implemented in Python, currently 3.8, and depends on these third-party packages
-and technologies:
+The A1 Mediator is implemented in Python, currently version 3.8, and
+depends on these third-party packages and technologies:
 
 - OpenAPI3
 - Connexion
@@ -22,7 +22,8 @@ and technologies:
 Version bumping A1
 ------------------
 
-This project follows semver. When the version string changes, these files must be updated:
+This project follows semver. When the version string changes, these
+files must be updated:
 
 #. ``setup.py``
 #. ``container-tag.yaml``
@@ -31,8 +32,9 @@ This project follows semver. When the version string changes, these files must b
 #. ``a1/openapi.yaml`` But note this is an API version, not a software version; there's no need to bump on non-API changes.
 #.  And over in the ric-plt/ric-dep repo that contains the A1 Mediator helm chart, files ``values.yaml`` and ``Chart.yaml``.
 
-It's convenient to use the Python utility `bumpversion` to maintain the first three items.
-After setup (``pip install bumpversion``) you can change the patch version like this::
+It's convenient to use the Python utility `bumpversion` to maintain
+the first three items.  After setup (``pip install bumpversion``) you
+can change the patch version like this::
 
     bumpversion --verbose patch
 
@@ -40,26 +42,30 @@ Or change the minor version like this::
 
     bumpversion --verbose minor
 
-After the `bumpversion` utility has modified the files, update the release notes then commit.
+After the `bumpversion` utility has modified the files, update the
+release notes then commit.
 
 
 Version bumping RMR
 -------------------
 
-A1 (Dockerfile), Dockerfile-Unit-Test, and all three integration test receivers use an Alpine
-base image and install RMR from a base builder image.  Must update and rebuild all 5 containers
-in the A1 repo (or just A1 itself for production usage).
+A1 (Dockerfile), Dockerfile-Unit-Test, and all three integration test
+receivers use an Alpine base image and install RMR from a base builder
+image.  Must update and rebuild all 5 containers in the A1 repo (or
+just A1 itself for production usage).
 
 In addition these items in this repo must be kept in sync:
 
-#. ``rmr-version.yaml`` controls what rmr gets installed for unit testing in Jenkins
-#. ``integration_tests/install_rmr.sh`` is a useful script for a variety of local testing.
+#. ``rmr-version.yaml`` controls what rmr gets installed for unit
+   testing in Jenkins
+#. ``integration_tests/install_rmr.sh`` is a useful script for a
+   variety of local testing.
 
 Version bumping Python
 ----------------------
 
-If you want to update the version of python; for example this was recently done to move
-from 3.7 to 3.8, update these files:
+If you want to update the version of python; for example this was
+recently done to move from 3.7 to 3.8, update these files:
 
 #. ``Dockerfile``
 #. ``Dockerfile-Unit-Test``
@@ -70,9 +76,9 @@ Unit Testing
 
 Running the unit tests requires the python packages ``tox`` and ``pytest``.
 
-The RMR library is also required during unit tests. If running directly from tox
-(outside a Docker container), install RMR using the script in the integration_tests
-directory: ``install_rmr.sh``.
+The RMR library is also required during unit tests. If running
+directly from tox (outside a Docker container), install RMR using the
+script in the integration_tests directory: ``install_rmr.sh``.
 
 Upon completion, view the test coverage like this:
 
index 40e4463..d679286 100644 (file)
@@ -1,8 +1,8 @@
 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
 .. SPDX-License-Identifier: CC-BY-4.0
 
-RIC Platform A1 Mediator
-========================
+A1 Mediator
+===========
 
 .. toctree::
    :maxdepth: 2
@@ -10,7 +10,7 @@ RIC Platform A1 Mediator
 
    overview.rst
    installation-guide.rst
-   api-spec.rst
+   user-guide-api.rst
    developer-guide.rst
    release-notes.rst
 
index 111058d..0b1de6a 100644 (file)
@@ -2,8 +2,8 @@
 .. http://creativecommons.org/licenses/by/4.0
 .. Copyright (C) 2019 AT&T Intellectual Property
 
-A1 Installation Guide
-=====================
+Installation Guide
+==================
 
 .. contents::
    :depth: 3
index ac751e7..46ea3ff 100644 (file)
@@ -1,12 +1,13 @@
 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
 .. SPDX-License-Identifier: CC-BY-4.0
 
-A1 Overview
-===========
+Overview
+========
 
-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 xApps via RMR messages (the "southbound" interface).
+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
+xApps via RMR messages (the "southbound" interface).
 
 Code
 ----
@@ -18,85 +19,111 @@ https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/a1
 
 Policy Overview
 ----------------
-There are two "object types" associated with policy: policy types and policy instances.
 
-Policy types define the name, description, and most importantly the schema of all instances of that type. Think of policy types as defining a JSON schema for the messages sent from A1 to xapps.
+There are two "object types" associated with policy: policy types and
+policy instances.
 
-Xapps do not receive policy types from A1; types are used only by A1 to validate instance creation requests. However, xapps must register to receive instances of type ids in their xapp descriptor.
+Policy Types
+~~~~~~~~~~~~
 
-Xapp developers can also create new policy types, though the exact process of where these are stored is still TBD. For practical purposes, when the RIC is running, A1s API needs to be invoked to load the policy types before instances can be created.
+Policy types define the name, description, and most importantly the
+schema of all instances of that type.  Think of policy types as
+defining a JSON schema for the messages sent from A1 to xapps.  Xapps
+do not receive policy types from A1; types are used only by A1 to
+validate instance creation requests.  However, xapps must register to
+receive instances of type ids in their xapp descriptor.  Xapp
+developers can also create new policy types, though the exact process
+of where these are stored is still TBD.  For practical purposes, when
+the RIC is running, A1s API needs to be invoked to load the policy
+types before instances can be created.  Xapps can "sign up" for
+multiple policy types using their xapp descriptor.
 
-Policy instances are concrete instantiations of a policy type. They give concrete values of a policy. There may be many instances of a single type. Whenever a policy instance is created in A1, messages are sent over RMR to all xapps registered for that policy type; see below.
+Policy Instances
+~~~~~~~~~~~~~~~~
 
-Xapps can "sign up" for multiple policy types using their xapp descriptor.
-
-Xapps are expected to handle multiple simultaneous instances of each type that they are registered for.
-
-Xapps supporting A1
-
-
-Integrating Xapps with A1
--------------------------
-
-A1 to Xapps
-~~~~~~~~~~~
-When A1 sends a message to xapps, the schema for messages from A1 to the xapp is defined by ``downstream_message_schema`` in ``docs/a1_xapp_contract_openapi.yaml``
-
-All policy instance requests get sent from A1 using message type 20010
-
-Xapps to A1
-~~~~~~~~~~~
-There are three scenarios in which Xapps are to send a message to A1:
-
-1. When an xapp receives a CREATE message for a policy instance. Xapps must respond to these requests by sending a message of type 20011 to A1.
-   The schema for that message is defined by ``downstream_notification_schema`` in ``docs/a1_xapp_contract_openapi.yaml``.
-   Note, if the Xapp uses RTS for this, do not forget to change the message type before replying!
-2. Since policy instances can "deprecate" other instances, there are times when xapps need to asyncronously tell A1 that a policy is no longer active. Same message type and schema.
-3. Xapps can request A1 to re-send all instances of a type T using a query, message 20012.
-   The schema for that message is defined by ``policy_query_schema`` in ``docs/a1_xapp_contract_openapi.yaml`` (just a body with ``{policy_type_id}: ...}```.
-   When A1 receives this, A1 will send the xapp a CREATE message N times, where N is the number of policy instances for type T. The xapp should reply normally to each of those as per bullet 1.
-   That is, after the Xapp performs the query, the N CREATE messages sent and the N replies are "as normal".
-   The query just kicks off this process rather than an external caller to A1.
+Policy instances are concrete instantiations of a policy type. They
+give concrete values of a policy.  There may be many instances of a
+single type. Whenever a policy instance is created in A1, messages are
+sent over RMR to all xapps registered for that policy type; see below.
+Xapps are expected to handle multiple simultaneous instances of each
+type that they are registered for.
 
 
 Known differences from A1 1.0.0 spec
 ------------------------------------
-This is a list of some of the known differences between the API here and the a1 spec dated 2019.09.30.
-In some cases, the spec is deficient and we are "ahead", in other cases this does not yet conform to recent spec changes.
-
-1. [RIC is ahead] There is no notion of policy types in the spec, however this aspect is quite critical for the intended use of the RIC, where many Xapps may implement the same policy, and new Xapps may be created often that define new types. Moreover, policy types define the schema for policy instances, and without types, A1 cannot validate whether instances are valid, which the RIC A1m does. The RIC A1m view of things is that, there are a set of schemas, called policy types, and one or more instances of each schema can be created. Instances are validated against types. The spec currently provides no mechanism for the implementation of A1 to know whether policy [instances] are correct since there is no schema for them. This difference has the rather large consequence that none of the RIC A1m URLs match the spec.
-
-2. [RIC is ahead] There is a rich status URL in the RIC A1m for policy instances, but this is not in the spec.
 
-3. [RIC is ahead] There is a state machine for when instances are actually deleted from the RIC (at which point all URLs referencing it are a 404); this is a configurable option when deploying the RIC A1m.
-
-4. [CR coming to spec] The spec contains a PATCH for partially updating a policy instance, and creating/deleting multiple instances, however the team agreed to remove this from a later version of the Spec. The RIC A1m does not have this operation.
-
-5. [Spec is ahead] The RIC A1 PUT bodies for policy instances do not exactly conform to the "scope" and "statements" block that the spec defines. They are very close otherwise, however.
-   (I would argue some of the spec is redundant; for example "policy [instance] id" is a key inside the PUT body to create an instance, but it is already in the URL.)
-
-6. [Spec is ahead] The RIC A1m does not yet notify external clients when instance statuses change.
-
-7. [Spec is ahead] The spec defines that a query of all policy instances should return the full bodies, however right now the RIC A1m returns a list of IDs (assuming subsequent queries can fetch the bodies).
-
-8. [?] The spec document details some very specific "types", but the RIC A1m allows these to be loaded in (see #1). For example, spec section 4.2.6.2. We believe this should be removed from the spec and rather defined as a type. Xapps can be created that define new types, so the spec will quickly become "stale" if "types" are defined in the spec.
+This is a list of some of the known differences between the API here
+and the a1 spec dated 2019.09.30.  In some cases, the spec is
+deficient and RIC is "ahead", in other cases this does not yet conform
+to recent spec changes.
+
+#. [RIC is ahead] There is no notion of policy types in the spec,
+   however this aspect is quite critical for the intended use of the
+   RIC, where many Xapps may implement the same policy, and new Xapps
+   may be created often that define new types. Moreover, policy types
+   define the schema for policy instances, and without types, A1
+   cannot validate whether instances are valid, which the RIC A1m
+   does. The RIC A1 Mediator view of things is that, there are a set
+   of schemas, called policy types, and one or more instances of each
+   schema can be created. Instances are validated against types. The
+   spec currently provides no mechanism for the implementation of A1
+   to know whether policy [instances] are correct since there is no
+   schema for them. This difference has the rather large consequence
+   that none of the RIC A1m URLs match the spec.
+#. [RIC is ahead] There is a rich status URL in the RIC A1m for policy
+   instances, but this is not in the spec.
+#. [RIC is ahead] There is a state machine for when instances are
+   actually deleted from the RIC (at which point all URLs referencing
+   it are a 404); this is a configurable option when deploying the RIC
+   A1m.
+#. [CR coming to spec] The spec contains a PATCH for partially
+   updating a policy instance, and creating/deleting multiple
+   instances, however the team agreed to remove this from a later
+   version of the Spec. The RIC A1m does not have this operation.
+#. [Spec is ahead] The RIC A1 PUT bodies for policy instances do not
+   exactly conform to the "scope" and "statements" block that the spec
+   defines. They are very close otherwise, however.   (I would argue
+   some of the spec is redundant; for example "policy [instance] id"
+   is a key inside the PUT body to create an instance, but it is
+   already in the URL.)
+#. [Spec is ahead] The RIC A1m does not yet notify external clients
+   when instance statuses change.
+#. [Spec is ahead] The spec defines that a query of all policy
+   instances should return the full bodies, however right now the RIC
+   A1m returns a list of IDs (assuming subsequent queries can fetch
+   the bodies).
+#. [?] The spec document details some very specific "types", but the
+   RIC A1m allows these to be loaded in (see #1). For example, spec
+   section 4.2.6.2. We believe this should be removed from the spec
+   and rather defined as a type. Xapps can be created that define new
+   types, so the spec will quickly become "stale" if "types" are
+   defined in the spec.
 
 
 Resiliency
 ----------
 
-A1 is resilient to the majority of failures, but not all currently (though a solution is known).
-
-A1 uses the RIC SDL library to persist all policy state information: this includes the policy types, policy instances, and policy statuses.
-If state is built up in A1, and A1 fails (where Kubernetes will then restart it), none of this state is lost.
-
-The tiny bit of state that *is currently* in A1 (volatile) is it's "next second" job queue.
-Specifically, when policy instances are created or deleted, A1 creates jobs in a job queue (in memory).
-An rmr thread polls that thread every second, dequeues the jobs, and performs them.
-
-If A1 were killed at *exactly* the right time, you could have jobs lost, meaning the PUT or DELETE of an instance wouldn't actually take.
-This isn't drastic, as the operations are idempotent and could always be re-performed.
-
-In order for A1 to be considered completely resilient, this job queue would need to be moved to SDL.
-SDL uses Redis as a backend, and Redis natively supports queues via LIST, LPUSH, RPOP.
-I've asked the SDL team to consider an extension to SDL to support these Redis operations.
+A1 is resilient to the majority of failures, but not all currently
+(though a solution is known).
+
+A1 uses the RIC SDL library to persist all policy state information:
+this includes the policy types, policy instances, and policy statuses.
+If state is built up in A1, and A1 fails (where Kubernetes will then
+restart it), none of this state is lost.
+
+The tiny bit of state that *is currently* in A1 (volatile) is its
+"next second" job queue.  Specifically, when policy instances are
+created or deleted, A1 creates jobs in a job queue (in memory).  An
+rmr thread polls that thread every second, dequeues the jobs, and
+performs them.
+
+If A1 were killed at *exactly* the right time, you could have jobs
+lost, meaning the PUT or DELETE of an instance wouldn't actually take.
+This isn't drastic, as the operations are idempotent and could always
+be re-performed.
+
+In order for A1 to be considered completely resilient, this job queue
+would need to be moved to SDL.  SDL uses Redis as a backend, and Redis
+natively supports queues via LIST, LPUSH, RPOP.  I've asked the SDL
+team to consider an extension to SDL to support these Redis
+operations.
index ba65417..babfbef 100644 (file)
@@ -10,10 +10,6 @@ All notable changes to this project will be documented in this file.
 The format is based on `Keep a Changelog <http://keepachangelog.com/>`__
 and this project adheres to `Semantic Versioning <http://semver.org/>`__.
 
-.. contents::
-   :depth: 3
-   :local:
-
 
 [2.1.9] - 2020-05-26
 --------------------
@@ -24,6 +20,7 @@ and this project adheres to `Semantic Versioning <http://semver.org/>`__.
 * Use constants from ricxappframe.rmr instead of hardcoded strings
 * Upgrade RMR to version 4.0.5
 * Upgrade tavern to version 1.2.2
+* Extend user guide with southbound API schemas
 
 
 [2.1.8] - 2020-04-30
@@ -126,8 +123,8 @@ and this project adheres to `Semantic Versioning <http://semver.org/>`__.
 * Implements a POLICY QUERY feature where A1 listens for queries for a policy type. A1 then responds via multiple RTS messages every policy instance of that policy type (and expects an ACK back from xapps as usual). This feature can be used for xapp recovery etc.
 
 
-[1.0.4]
--------
+[1.0.4] - 10/24/2019
+--------------------
 
 * Only external change here is to healthcheck the rmr thread as part of a1s healthcheck. k8s will now respin a1 if that is failing.
 * Refactors (simplifies) how we wait for rmr initialization; it is now called as part of __init__
diff --git a/docs/user-guide-api.rst b/docs/user-guide-api.rst
new file mode 100644 (file)
index 0000000..2dcd31e
--- /dev/null
@@ -0,0 +1,100 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+
+User Guide and APIs
+===================
+
+This document explains how to communicate with the A1 Mediator.
+Information for maintainers of this platform component is in the Developer Guide.
+
+Example Messages
+----------------
+
+Send the following JSON to create policy type 20008, which supports instances with
+a single integer value:
+
+.. code-block:: yaml
+
+    {
+      "name": "tsapolicy",
+      "description": "tsa parameters",
+      "policy_type_id": 20008,
+      "create_schema": {
+        "$schema": "http://json-schema.org/draft-07/schema#",
+        "type": "object",
+        "properties": {
+          "threshold": {
+            "type": "integer",
+            "default": 0
+          }
+        },
+        "additionalProperties": false
+      }
+    }
+
+
+Send the following JSON to create an instance of policy type 20008:
+
+.. code-block:: yaml
+
+    {
+      "threshold" : 5
+    }
+
+
+Integrating Xapps with A1
+-------------------------
+
+The schema for messages sent by A1 to Xapps is labeled ``downstream_message_schema``
+in the Southbound API Specification section below. A1 sends policy instance requests
+using message type 20010.
+
+The schemas for messages sent by Xapps to A1 appear in the Southbound API
+Specification section below. Xapps must use a message type and content appropriate
+for the scenario:
+
+#. When an Xapp receives a CREATE message for a policy instance, the Xapp
+   must respond by sending a message of type 20011 to A1. The content is
+   defined by schema ``downstream_notification_schema``.  The most convenient
+   way is to use RMR's return-to-sender (RTS) feature after setting the
+   message type appropriately.
+#. Since policy instances can "deprecate" other instances, there are
+   times when Xapps need to asynchronously tell A1 that a policy is no
+   longer active. Use the same message type and schema as above.
+#. Xapps can request A1 to re-send all instances of policy type T using a
+   query, message type 20012.  The schema for that message is defined by
+   ``policy_query_schema`` (just a body with ``{policy_type_id: ... }``).
+   When A1 receives this, A1 will send the Xapp a CREATE message N times,
+   where N is the number of policy instances for type T. The Xapp should reply
+   normally to each of those as the first item above. That is, after the Xapp
+   performs the query, the N CREATE messages sent and the N replies
+   are "as normal".  The query just kicks off this process rather than
+   an external caller to A1.
+
+
+Northbound API Specification
+----------------------------
+
+This section shows the Open API specification for the A1 Mediator's
+northbound interface, which accepts policy type and policy instance requests.
+Alternately, if you have checked out the code and are running the server,
+you can see a formatted version at this URL: ``http://localhost:10000/ui/``.
+
+
+.. literalinclude:: ../a1/openapi.yaml
+   :language: yaml
+   :linenos:
+
+
+Southbound API Specification
+----------------------------
+
+This section shows Open API schemas for the A1 Mediator's southbound interface,
+which communicates with Xapps via RMR. A1 sends policy instance requests using
+message type 20010. Xapps may send requests to A1 using message types 20011 and
+20012.
+
+
+.. literalinclude:: a1_xapp_contract_openapi.yaml
+   :language: yaml
+   :linenos: