RIC-642 related changes: REST subscription, rnib enhancements, symptomdata, rest... 69/8569/7
authorehietala <erkki.hietala@nokia.com>
Wed, 15 Jun 2022 09:21:41 +0000 (12:21 +0300)
committerehietala <erkki.hietala@nokia.com>
Thu, 16 Jun 2022 11:19:12 +0000 (14:19 +0300)
Signed-off-by: Erkki Hietala <erkki.hietala@nokia.com>
Change-Id: Ibcbc85b57da571fb9c0eb3adff9ba950aec6c4c9

67 files changed:
.coveragerc
Dockerfile-Unit-Test
api/xapp_rest_api.yaml [new file with mode: 0644]
docs/conf.py
docs/developer-guide.rst
docs/release-notes.rst
docs/user-guide.rst
examples/Dockerfile-Xapp [new file with mode: 0644]
examples/Makefile [new file with mode: 0644]
examples/descriptor/config-file.json [new file with mode: 0644]
examples/descriptor/schema.json [new file with mode: 0644]
examples/descriptor/xapp-test.rt [new file with mode: 0644]
examples/restserversimu.py [new file with mode: 0644]
examples/start.sh [new file with mode: 0755]
examples/xapp_subscribe.py [new file with mode: 0644]
examples/xapp_symptomdata.py [new file with mode: 0644]
examples/xapp_test.py [new file with mode: 0644]
ricxappframe/entities/__init__.py [deleted file]
ricxappframe/entities/rnib/__init__.py [deleted file]
ricxappframe/entities/rnib/additional_cell_information_pb2.py
ricxappframe/entities/rnib/cell_pb2.py
ricxappframe/entities/rnib/cells_pb2.py
ricxappframe/entities/rnib/e2node_component_config_pb2.py [new file with mode: 0644]
ricxappframe/entities/rnib/enb_pb2.py
ricxappframe/entities/rnib/gnb_pb2.py
ricxappframe/entities/rnib/nb_identity_pb2.py
ricxappframe/entities/rnib/nb_types_pb2.py [new file with mode: 0644]
ricxappframe/entities/rnib/nodeb_info_pb2.py
ricxappframe/entities/rnib/ran_function_pb2.py
ricxappframe/entities/rnib/ran_load_information_pb2.py
ricxappframe/entities/rnib/x2_setup_failure_response_pb2.py
ricxappframe/subsclient/__init__.py [new file with mode: 0644]
ricxappframe/subsclient/api/__init__.py [new file with mode: 0644]
ricxappframe/subsclient/api/common_api.py [new file with mode: 0644]
ricxappframe/subsclient/api/xapp_api.py [new file with mode: 0644]
ricxappframe/subsclient/api_client.py [new file with mode: 0644]
ricxappframe/subsclient/configuration.py [new file with mode: 0644]
ricxappframe/subsclient/models/__init__.py [new file with mode: 0644]
ricxappframe/subsclient/models/action_definition.py [new file with mode: 0644]
ricxappframe/subsclient/models/action_to_be_setup.py [new file with mode: 0644]
ricxappframe/subsclient/models/actions_to_be_setup.py [new file with mode: 0644]
ricxappframe/subsclient/models/config_metadata.py [new file with mode: 0644]
ricxappframe/subsclient/models/event_trigger_definition.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_data.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_detail.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_details_list.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_instance.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_list.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_params.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_params_client_endpoint.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_params_e2_subscription_directives.py [new file with mode: 0644]
ricxappframe/subsclient/models/subscription_response.py [new file with mode: 0644]
ricxappframe/subsclient/models/subsequent_action.py [new file with mode: 0644]
ricxappframe/subsclient/models/x_app_config.py [new file with mode: 0644]
ricxappframe/subsclient/models/xapp_config_list.py [new file with mode: 0644]
ricxappframe/subsclient/rest.py [new file with mode: 0644]
ricxappframe/xapp_frame.py
ricxappframe/xapp_rest.py [new file with mode: 0644]
ricxappframe/xapp_subscribe.py [new file with mode: 0644]
ricxappframe/xapp_symptomdata.py [new file with mode: 0644]
setup.py
tests/conftest.py
tests/test_rest.py [new file with mode: 0644]
tests/test_subscribe.py [new file with mode: 0644]
tests/test_symptomdata.py [new file with mode: 0644]
tests/test_xapps.py
tox.ini

index 00d1de4..470b27b 100644 (file)
@@ -1,4 +1,4 @@
 [run]
 omit =
     # omit compiled protobuf files
-    ricxappframe/entities/*
+    ricxappframe/entities/*,ricxappframe/subsclient/*
index 1a95f51..c5f392a 100644 (file)
@@ -48,7 +48,7 @@ COPY --from=stretch /usr/local/lib/librmr_si.so.${rmr_version} /usr/local/lib/li
 COPY --from=stretch /usr/local/lib/libriclibe2ap.so.${e2ap_version} /usr/local/lib/libriclibe2ap.so
 
 # Upgrade pip, install tox
-RUN pip install --upgrade pip && pip install tox
+RUN pip install --upgrade pip && pip install tox && pip install certifi six python_dateutil setuptools urllib3 inotify_simple mdclogpy
 
 # copies
 COPY ricxappframe/ /tmp/ricxappframe
@@ -56,5 +56,12 @@ COPY tests/ /tmp/tests
 COPY setup.py tox.ini LICENSE.txt .coveragerc /tmp/
 WORKDIR /tmp
 
+# following is to get the docker instance and run tests from the bash shell, remove comment in the 
+# the next ENTRYPOINT line and comment out the last RUN line to get the runable docker instance.
+# Bbuild named image and run the instance - if you modify the files those are visible in container
+# docker build  -t xappframe:latest -f Dockerfile-Unit-Test .
+# docker run -ti --name xappframe --rm -v ${PWD}:/tmp -u $(id -u ${USER}):$(id -g ${USER}) --workdir /tmp xappframe:latest
+# then run : tox -e code,flake8,docs,docs-linkcheck
+#ENTRYPOINT ["/bin/bash"]
 # Run the unit tests
 RUN tox -e code,flake8
diff --git a/api/xapp_rest_api.yaml b/api/xapp_rest_api.yaml
new file mode 100644 (file)
index 0000000..c2e1be0
--- /dev/null
@@ -0,0 +1,325 @@
+swagger: '2.0'
+info:
+  description: This is the initial REST API for RIC subscription
+  version: 0.0.4
+  title: RIC subscription
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+host: hostname
+basePath: /ric/v1
+schemes:
+  - http
+paths:
+  /config:
+    get:
+      summary: Returns the configuration of all xapps
+      tags:
+        - xapp
+      operationId: getXappConfigList
+      produces:
+        - application/json
+        - application/xml
+      responses:
+        '200':
+          description: successful query of xApp config
+          schema:
+            $ref: '#/definitions/XappConfigList'
+        '500':
+          description: Internal error
+  /subscriptions:
+    get:
+      summary: Returns list of subscriptions
+      tags:
+        - common
+      operationId: getAllSubscriptions
+      produces:
+        - application/json
+      responses:
+        '200':
+          description: successful query of subscriptions
+          schema:
+            $ref: '#/definitions/SubscriptionList'
+        '500':
+          description: Internal error
+    post:
+      tags:
+        - common
+      operationId: Subscribe
+      summary: Subscribe a list of X2AP event triggers to receive messages sent by RAN
+      consumes:
+        - application/json
+      produces:
+        - application/json
+      parameters:
+        - name: SubscriptionParams
+          in: body
+          description: Subscription parameters
+          schema:
+            $ref: '#/definitions/SubscriptionParams'
+      responses:
+        '201':
+          description: Subscription successfully created
+          schema:
+            $ref: '#/definitions/SubscriptionResponse'
+        '400':
+          description: Not Found
+        '404':
+          description: Invalid input
+        '500':
+          description: Internal error
+        '503':
+          description: Service Unavailable
+  '/subscriptions/{subscriptionId}':
+    delete:
+      tags:
+        - common
+      summary: Unsubscribe X2AP events from Subscription Manager
+      operationId: Unsubscribe
+      consumes:
+        - application/json
+      produces:
+        - application/json
+      parameters:
+        - name: subscriptionId
+          in: path
+          description: The subscriptionId received in the Subscription Response
+          required: true
+          type: string
+      responses:
+        '204':
+          description: Operation done successfully
+        '400':
+          description: Invalid subscriptionId supplied
+        '500':
+          description: Internal error
+definitions:
+  ConfigMetadata:
+    type: object
+    required:
+      - xappName
+      - configType
+    properties:
+      xappName:
+        type: string
+        description: Name of the xApp
+      configType:
+        type: string
+        description: The type of the content
+        enum:
+          - json
+          - xml
+          - other
+  XAppConfig:
+    type: object
+    required:
+      - metadata
+      - config
+    properties:
+      metadata:
+        $ref: '#/definitions/ConfigMetadata'
+      config:
+        type: object
+        description: Configuration in JSON format
+  XappConfigList:
+    type: array
+    items:
+      $ref: '#/definitions/XAppConfig'
+  ActionDefinition:
+    type: array
+    description: E2SM byte array. ActionDefinition is an OPTIONAL IE
+    items:
+      type: integer
+  SubsequentAction:
+    description: SubsequentAction is an OPTIONAL IE
+    type: object
+    required:
+      - SubsequentActionType
+      - TimeToWait
+    properties:
+      SubsequentActionType:
+        type: string
+        enum:
+          - continue
+          - wait
+      TimeToWait:
+        type: string
+        enum:
+          - zero
+          - w1ms
+          - w2ms
+          - w5ms
+          - w10ms
+          - w20ms
+          - w30ms
+          - w40ms
+          - w50ms
+          - w100ms
+          - w200ms
+          - w500ms
+          - w1s
+          - w2s
+          - w5s
+          - w10s
+          - w20s
+          - w60s
+  ActionToBeSetup:
+    type: object
+    required:
+      - ActionID
+      - ActionType
+    properties:
+      ActionID:
+        type: integer
+        minimum: 0
+        maximum: 255
+      ActionType:
+        type: string
+        enum:
+          - insert
+          - policy
+          - report
+      ActionDefinition:
+        $ref: '#/definitions/ActionDefinition'
+      SubsequentAction:
+        $ref: '#/definitions/SubsequentAction'
+  ActionsToBeSetup:
+    type: array
+    items:
+      $ref: '#/definitions/ActionToBeSetup'
+  EventTriggerDefinition:
+    type: array
+    description: E2SM byte array
+    items:
+      type: integer
+  SubscriptionDetail:
+    type: object
+    required:
+      - XappEventInstanceId
+      - EventTriggers
+      - ActionToBeSetupList
+    properties:
+      XappEventInstanceId:
+        type: integer
+        minimum: 0
+        maximum: 65535
+      EventTriggers:
+        $ref: '#/definitions/EventTriggerDefinition'
+      ActionToBeSetupList:
+        $ref: '#/definitions/ActionsToBeSetup'
+  SubscriptionDetailsList:
+    type: array
+    items:
+      $ref: '#/definitions/SubscriptionDetail'
+  SubscriptionParams:
+    type: object
+    required:
+      - ClientEndpoint
+      - Meid
+      - RANFunctionID
+      - SubscriptionDetails
+    properties:
+      SubscriptionId:
+       type: string
+       description: Optional subscription ID (Submgr allocates if not given)
+      ClientEndpoint:
+        type: object
+        description: xApp service address and port
+        properties:
+          Host:
+            description: >-
+              xApp service address name like
+              'service-ricxapp-xappname-http.ricxapp'
+            type: string
+          HTTPPort:
+            description: xApp HTTP service address port
+            type: integer
+            minimum: 0
+            maximum: 65535
+          RMRPort:
+            description: xApp RMR service address port
+            type: integer
+            minimum: 0
+            maximum: 65535
+      Meid:
+        type: string
+      RANFunctionID:
+        type: integer
+        minimum: 0
+        maximum: 4095
+      E2SubscriptionDirectives:
+        description: Optional. If not set Submgr uses its default values
+        type: object
+        properties:
+          E2TimeoutTimerValue:
+            description: How long time response is waited from E2 node
+            type: integer
+            minimum: 1
+            maximum: 10
+          E2RetryCount:
+            description: How many times E2 subscription request is retried
+            type: integer
+            minimum: 0
+            maximum: 10
+          RMRRoutingNeeded:
+            description: Subscription needs RMR route from E2Term to xApp 
+            type: boolean
+      SubscriptionDetails:
+        $ref: '#/definitions/SubscriptionDetailsList'
+  SubscriptionResponse:
+    type: object
+    required:
+      - SubscriptionId
+      - SubscriptionInstances
+    properties:
+      SubscriptionId:
+        type: string
+      SubscriptionInstances:
+        type: array
+        items:
+          $ref: '#/definitions/SubscriptionInstance'
+  SubscriptionInstance:
+    type: object
+    required:
+      - XappEventInstanceId
+      - E2EventInstanceId
+    properties:
+      XappEventInstanceId:
+        type: integer
+        minimum: 0
+        maximum: 65535
+      E2EventInstanceId:
+        type: integer
+        minimum: 0
+        maximum: 65535
+      ErrorCause:
+        description: Descriptive error cause. Empty string when no error.
+        type: string
+      ErrorSource:
+        description: Source of error cause.
+        type: string
+        enum: [SUBMGR, RTMGR, DBAAS, ASN1, E2Node]
+      TimeoutType:
+        description: Type timeout. xApp should retry if timeout occurs.
+        type: string
+        enum: [E2-Timeout, RTMGR-Timeout, DBAAS-Timeout]
+  SubscriptionData:
+    type: object
+    properties:
+      SubscriptionId:
+        type: integer
+      Meid:
+        type: string
+      ClientEndpoint:
+        type: array
+        items:
+          type: string
+      SubscriptionInstances:
+        type: array
+        items:
+          $ref: '#/definitions/SubscriptionInstance'
+  SubscriptionList:
+    type: array
+    description: A list of subscriptions
+    items:
+      $ref: '#/definitions/SubscriptionData'
index ccad5c3..6a252b0 100755 (executable)
@@ -5,6 +5,8 @@ from docs_conf.conf import *
 # autodoc needs this to find the code
 sys.path.insert(0, os.path.abspath("../"))
 
+language = 'en'
+
 extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.viewcode", "numpydoc"]
 
 # don't alphabetically order
index 6892d15..036acfb 100644 (file)
@@ -11,7 +11,7 @@ Information for users of this framework (i.e., Xapp developers) is in the User G
 Tech Stack
 ----------
 
-The framework requires Python version 3.7 or later, and depends on
+The framework requires Python version 3.8 or later, and depends on
 these packages provided by the O-RAN-SC project and third parties:
 
 * msgpack
@@ -48,6 +48,73 @@ For registration and deregistration of Xapp following items need to be defined:
    Xapp as a docker container or in configmap in case of Xapp as a pod.
 #. Copy the xappConfig.json into the docker image in Dockerfile.
 
+Example Xapp
+------------
+
+Director examples has many examples for creating the xapp having features like:
+* REST subscription interface
+* symptomdata handler
+* rmr send/receive
+* REST healthy and ready response handler
+* REST config handler
+
+List of xapps:
+* ping_xapp.py and ping_xapp.py using RMR to send and receive
+* xapp_symptomdata.py for subscribing the symptomdata event
+* xapp_test.py for both symptomdata, RMR recveice, k8s healthy service and REST subscription
+
+xapp_test.py
+------------
+
+Test xapp can be run by creating the docker container or as standalone process. For testing restserversimu.py
+has been made to emulate the REST subscription request responses and responding the symptomdata dynamic registration
+reponse. When running the xapp_test you need to create the RMR static routing file so that the rmr initialization
+will return (otherwise it will wait for rtmgr connection).
+
+Test xapp has as well the config file in descriptor/config-file.json where your can adjust the local runtime
+environment for subscriptions and symptomdata lwsd service ip address.
+
+Subsciprion interface url has the submgr service endpoint : ``http://service-ricplt-submgr-http.ricplt:8088/``
+Symptomdata registration url set to lwsd service url : ``http://service-ricplt-lwsd-http.ricplt:8080/ric/v1/lwsd``
+
+In case of using restserversimu.py for testing configure your host ip address, for example 192.168.1.122 port 8090:
+
+Subsciprion interface url has the submgr service endpoint : ``http://192.168.1.122:9000/``
+Symptomdata registration url set to lwsd service url : ``http://192.168.1.122:9000/ric/v1/lwsd``
+
+Then start the restserversimu:
+
+export PYTHONPATH=./
+python3 examples/restserversimu.py -port 9000 -address 192.168.1.122
+
+and then the xapp_test:
+
+export PYTHONPATH=./
+export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
+export RMR_SEED_RT=examples/descriptor/xapp-test.rt
+export RMR_SRC_ID="192.168.1.122"
+python3 examples/xapp_test.py -config examples/descriptor/config-file.json -port 8888 -xapp xapp-test -service xapp-test
+
+If you like to implement the kubernetes healthy service responder, you can follow the example how to use the 
+xapp_rest.py defined rest hander. Basically you can initiate the REST service listener and add the handlers (examples in
+xapp_tets.py).
+
+Subscription REST interface
+---------------------------
+
+api/xapp_rest_api.yaml defines interface and it has been used to generate the swagger api calls.
+
+Generating the swagger client model:
+docker run --rm -v ${PWD}:/local -u $(id -u ${USER}):$(id -g ${USER}) swaggerapi/swagger-codegen-cli generate -i /local/api/xapp_rest_api.yaml -l python -o /local/out
+
+swagger-codegen-cli generated code result needs to be adjusted to have the ricxappframe prefix. 
+Replace the module name to have the ricxappframe prefix:
+
+find ./out/swagger_client -type f -exec sed -i -e 's/swagger_client/ricxappframe\.swagger_client/g' {} \;
+
+Then copy the generated ./out/swagger_client directory to ./ricxappframe/subsclient directory:
+
+cp -r ./out/swagger_client/* ./ricxappframe/subsclient
 
 Unit Testing
 ------------
index 939d2a4..f6f0f89 100644 (file)
@@ -10,6 +10,10 @@ 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/>`__.
 
+[3.1.0] - 2022-03-22
+--------------------
+* Added the symptomdata module
+
 [3.0.2] - 2021-12-17
 --------------------
 * Fix caching of error code data not happening (`RIC-862 <https://jira.o-ran-sc.org/browse/RIC-862>`_)
index 8189ab4..0f2bbdf 100644 (file)
@@ -49,3 +49,27 @@ Application writers may instantiate this class directly to communicate with the
 
 .. autoclass:: ricxappframe.xapp_sdl.SDLWrapper
     :members:
+
+Class Symptomdata
+-----------------
+
+Application writers may instantiate this class directly to communicate with the symptomdata service.
+
+.. autoclass:: ricxappframe.xapp_symptomdata.Symptomdata
+    :members:
+
+Class NewSubscriber
+-------------------
+
+Application writers may instantiate this class directly to communicate REST based subscriptions.
+
+.. autoclass:: ricxappframe.xapp_subscribe.NewSubscriber
+    :members:
+
+Class RestHandler
+-----------------
+
+Application writers may instantiate this class directly to have the xapp REST server service.
+
+.. autoclass:: ricxappframe.xapp_rest.RestHandler
+    :members:
diff --git a/examples/Dockerfile-Xapp b/examples/Dockerfile-Xapp
new file mode 100644 (file)
index 0000000..8d878a8
--- /dev/null
@@ -0,0 +1,56 @@
+FROM python:3.8-slim as stretch
+
+RUN apt-get clean -y && apt-get update -y && \
+    apt-get install -y wget curl less nano \
+    nmap mtr net-tools tcpdump apt-utils sudo jq tree iproute2 iputils-ping traceroute
+    
+ARG rmr_version=4.8.0
+ARG e2ap_version=1.1.0
+
+# download rmr and e2ap libraries from package cloud
+RUN wget -nv --content-disposition https://packagecloud.io/o-ran-sc/release/packages/debian/stretch/rmr_${rmr_version}_amd64.deb/download.deb
+RUN wget -nv --content-disposition https://packagecloud.io/o-ran-sc/release/packages/debian/stretch/rmr-dev_${rmr_version}_amd64.deb/download.deb
+
+RUN wget -nv --content-disposition https://packagecloud.io/o-ran-sc/release/packages/debian/stretch/riclibe2ap_${e2ap_version}_amd64.deb/download.deb
+RUN wget -nv --content-disposition https://packagecloud.io/o-ran-sc/release/packages/debian/stretch/riclibe2ap-dev_${e2ap_version}_amd64.deb/download.deb
+
+RUN dpkg -i rmr_${rmr_version}_amd64.deb
+RUN dpkg -i rmr-dev_${rmr_version}_amd64.deb
+
+RUN dpkg -i riclibe2ap_${e2ap_version}_amd64.deb
+RUN dpkg -i riclibe2ap-dev_${e2ap_version}_amd64.deb
+
+RUN ls /usr/local/lib/
+
+FROM python:3.8-slim
+
+ARG rmr_version=4.8.0
+ARG e2ap_version=1.1.0
+
+COPY --from=stretch /usr/local/lib/librmr_si.so.${rmr_version} /usr/local/lib/librmr_si.so
+COPY --from=stretch /usr/local/lib/libriclibe2ap.so.${e2ap_version} /usr/local/lib/libriclibe2ap.so
+RUN chmod -R 755 /usr/local/lib/librmr_si.so
+RUN chmod -R 755 /usr/local/lib/libriclibe2ap.so
+
+# Upgrade pip, install tox
+RUN pip install --upgrade pip && pip install certifi six python_dateutil setuptools urllib3 logger requests inotify_simple mdclogpy google-api-python-client msgpack ricsdl
+
+RUN mkdir -p /opt/nokia/ric/xapp-test && chmod -R 755 /opt/nokia/ric/xapp-test
+RUN mkdir -p /opt/nokia/ric/xapp-test/ricxappframe && chmod -R 755 /opt/nokia/ric/xapp-test/ricxappframe
+RUN mkdir -p /opt/ric/config && chmod -R 755 /opt/ric/config
+
+WORKDIR /opt/nokia/ric/xapp-test
+
+COPY ricxappframe /opt/nokia/ric/xapp-test/ricxappframe
+
+COPY examples/descriptor /opt/ric/config/.
+
+COPY examples/*.py /opt/nokia/ric/xapp-test/
+COPY examples/start.sh /opt/nokia/ric/xapp-test/.
+
+ENV CFG_FILE=/opt/ric/config/config-file.json
+
+ENV LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib
+
+#ENTRYPOINT ["/bin/bash"]
+ENTRYPOINT ["/opt/nokia/ric/xapp-test/start.sh"]
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644 (file)
index 0000000..44832dd
--- /dev/null
@@ -0,0 +1,22 @@
+VERSION ?= 0.1
+
+IMAGE_NAME ?= xapp-test
+CONTAINER_NAME ?= xapp-test
+REPOSITORY ?= edgeapps-docker-local.artifactory-blr1.int.net.nokia.com
+
+.PHONY: build push run rm release
+
+build: examples/Dockerfile-Xapp
+       docker build -t $(IMAGE_NAME):$(VERSION) -f examples/Dockerfile-Xapp .
+
+push:
+       docker tag $(IMAGE_NAME):$(VERSION) $(REPOSITORY)/$(IMAGE_NAME):$(VERSION)
+       docker push $(REPOSITORY)/$(IMAGE_NAME):$(VERSION)
+
+run:
+       docker run --rm --name $(CONTAINER_NAME) -ti $(ENV) $(IMAGE_NAME):$(VERSION)
+
+rm:
+       docker rm $(CONTAINER_NAME)
+
+default: build
diff --git a/examples/descriptor/config-file.json b/examples/descriptor/config-file.json
new file mode 100644 (file)
index 0000000..3c8d51c
--- /dev/null
@@ -0,0 +1,83 @@
+{
+  "name": "ts-kpi-storage",
+  "version": "0.7.0",
+  "vendor": "Nokia",
+  "moId": "SEP",
+  "containers": [
+    {
+      "name": "xapp-test",
+      "image": {
+        "registry": "edgeapps-docker-local.artifactory-blr1.int.net.nokia.com",
+        "name": "xapp-test",
+        "tag": "0.1"
+      },
+      "resources": {
+        "limits": {},
+        "requests": {}
+      }
+    }
+  ],
+  "livenessProbe": {
+    "httpGet": {
+      "path": "ric/v1/health/alive",
+      "port": 8080
+    },
+    "initialDelaySeconds": 5,
+    "periodSeconds": 15
+  },
+  "readinessProbe": {
+    "httpGet": {
+      "path": "ric/v1/health/ready",
+      "port": 8080
+    },
+    "initialDelaySeconds": 5,
+    "periodSeconds": 15
+  },
+  "messaging": {
+    "ports": [
+      {
+        "name": "http",
+        "container": "xapp-test",
+        "port": 8080,
+        "description": "http service"
+      },
+      {
+        "name": "rmrroute",
+        "container": "xapp-test",
+        "port": 4561,
+        "description": "rmr route port"
+      },
+      {
+        "name": "rmrdata",
+        "container": "xapp-test",
+        "port": 4560,
+        "maxSize": 2072,
+        "rxMessages": [],
+        "txMessages": [],
+        "policies": [],
+        "description": "rmr data port"
+      }
+    ]
+  },
+  "controls": {
+    "logger": {
+      "level": 3
+    },
+    "symptomdata": {
+        "lwsd": {
+            "url": "http://192.168.1.122:9000/ric/v1/lwsd",
+            "timeout": 10
+               }
+    },
+    "subscription": {
+      "url": "http://192.168.1.122:9000/",
+      "clientEndpoint": "192.168.1.122"
+    }
+  },
+  "metrics": {
+    "url": "/ric/v1/metrics",
+    "namespace": "ricxapp"
+  },
+  "faults": {},
+  "measurements": []
+}
diff --git a/examples/descriptor/schema.json b/examples/descriptor/schema.json
new file mode 100644 (file)
index 0000000..ce528f1
--- /dev/null
@@ -0,0 +1,49 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema",
+  "$id": "http://example.com/example.json",
+  "type": "object",
+  "title": "The root schema",
+  "description": "The root schema comprises the entire JSON document.",
+  "default": {},
+  "examples": [
+      {
+          "logger": {
+              "level": 3
+          },
+      }
+  ],
+  "required": [
+      "logger"
+  ],
+  "properties": {
+      "logger": {
+          "$id": "#/properties/logger",
+          "type": "object",
+          "title": "The logger schema",
+          "description": "An explanation about the purpose of this instance.",
+          "default": {},
+          "examples": [
+              {
+                  "level": 3
+              }
+          ],
+          "required": [
+              "level"
+          ],
+          "properties": {
+              "level": {
+                  "$id": "#/properties/logger/properties/level",
+                  "type": "integer",
+                  "title": "The level schema",
+                  "description": "An explanation about the purpose of this instance.",
+                  "default": 0,
+                  "examples": [
+                      3
+                  ]
+              }
+          },
+          "additionalProperties": true
+      }
+  },
+  "additionalProperties": true
+}
diff --git a/examples/descriptor/xapp-test.rt b/examples/descriptor/xapp-test.rt
new file mode 100644 (file)
index 0000000..fbc5017
--- /dev/null
@@ -0,0 +1,7 @@
+newrt|start
+rte|12011|service-ricxapp-xapp-test-rmr.ricxapp:4560
+rte|12012|service-ricxapp-xapp-test-rmr.ricxapp:4560
+rte|12021|service-ricxapp-xapp-test-rmr.ricxapp:4560
+rte|12022|service-ricxapp-xapp-test-rmr.ricxapp:4560
+rte|12050|service-ricxapp-xapp-test-rmr.ricxapp:4560
+newrt|end
diff --git a/examples/restserversimu.py b/examples/restserversimu.py
new file mode 100644 (file)
index 0000000..bf7e20e
--- /dev/null
@@ -0,0 +1,82 @@
+import sys
+import time
+import json
+import argparse
+
+sys.path.insert(0, './')
+
+import ricxappframe.xapp_rest as ricrest
+
+def respPostHandler(name, path, data, ctype):
+    print(name)
+    print(path)
+    print(data)
+    response = ricrest.initResponse()
+    response['payload'] = ('{ "SubscriptionResponse": {'
+        '"SubscriptionId": "testing",'
+        '"SubscriptionInstances": [{'
+            '"XappEventInstanceID": "16253",'
+            '"E2EventInstanceID": "1241"'
+            '}]'
+        '}'
+    '}')
+    return response
+
+
+def respSymptomGetHandler(name, path, data, ctype):
+    print(name)
+    print(path)
+    response = ricrest.initResponse()
+    response['payload'] = ('[{"service" : "xapp-test"}]')
+    print(json.loads(response['payload']))
+    return response
+
+def respGetHandler(name, path, data, ctype):
+    print(name)
+    print(path)
+    response = ricrest.initResponse()
+    response['payload'] = ('{ "SubscriptionList": [{'
+            '"SubscriptionId": "12345",'
+            '"Meid": "gnb123456",'
+                       '"ClientEndpoint": ["127.0.0.1:4056"],'
+            '"SubscriptionInstances": [{'
+                '"XappEventInstanceID": "16253",'
+                '"E2EventInstanceID": "1241"'
+                '}]'
+            '}]'
+        '}')
+    return response
+
+def respDeleteHandler(name, path, data, ctype):
+    print(name)
+    print(path)
+    response = ricrest.initResponse()
+    response['payload'] = ('{}')
+    return response
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-port', dest='port', help='HTTP rest server listen port', required=False, type=int)
+    parser.add_argument('-address', dest='address', help='HTTP rest IP listen address, default all interfaces', required=False, type=str)
+    
+    args = parser.parse_args()
+    
+    if args.port is None:
+        args.port = 8088 
+    if args.address is None:
+        args.address = "0.0.0.0"
+
+    # create the thread HTTP server
+    server = ricrest.ThreadedHTTPServer(args.address, args.port)
+    # trick to get the own handler with defined 
+    server.handler.add_handler(server.handler, "GET", "response", "/ric/v1/subscriptions", respGetHandler)
+    server.handler.add_handler(server.handler, "DELETE", "delete", "/ric/v1/subscriptions/", respDeleteHandler)
+    server.handler.add_handler(server.handler, "GET", "lwsdget", "/ric/v1/lwsd", respSymptomGetHandler)
+    server.handler.add_handler(server.handler, "POST", "lwsdpost", "/ric/v1/lwsd", respSymptomGetHandler)
+    server.handler.add_handler(server.handler, "POST", "responsepost", "/ric/v1", respPostHandler)
+    # for symptomdata subscription
+
+    server.start()
+    while True:
+        time.sleep(60)
+    server.stop()
diff --git a/examples/start.sh b/examples/start.sh
new file mode 100755 (executable)
index 0000000..be6b107
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+export RMR_SEED_RT=/opt/ric/config/xapp-test.rt
+python3 ./xapp_test.py -xapp xapp-test -config /opt/ric/config/config-file.json -service xapp-test &
+while [ 1 ]; do
+       # just dummy sleep command
+       sleep 60
+done
diff --git a/examples/xapp_subscribe.py b/examples/xapp_subscribe.py
new file mode 100644 (file)
index 0000000..ab5aaa6
--- /dev/null
@@ -0,0 +1,247 @@
+#!/usr/bin/env python3
+# ==================================================================================
+#       Copyright (c) 2022 Nokia
+#
+#   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 os
+import sys
+import time
+import json
+import logging
+import datetime
+import argparse
+import threading
+import http.server
+import signal
+import struct
+import socket
+import urllib.parse
+from io import open
+from time import gmtime, strftime
+
+#sys.path.insert(0, os.path.abspath("./"))
+#sys.path.insert(0, os.path.abspath("./ricxappframe"))
+sys.path.append(os.getcwd())
+from ricxappframe.xapp_frame import RMRXapp, rmr
+from ricxappframe.xapp_sdl import SDLWrapper
+from ricxappframe.xapp_symptomdata import Symptomdata
+import ricxappframe.xapp_subscribe as subscribe
+import ricxappframe.xapp_rest as ricrest
+
+# rmr init mode - when set to port 4561 then will wait for the rtmgr to connect
+# otherwise will connect to rtmgr like set below
+RMR_INIT_SVC = b"4560"
+MRC = None
+xapp = None
+
+def signal_handler(sig, frame):
+    global server
+    global MRC
+    
+    server.stop()
+    rmr.rmr_close(MRC)
+    sys.exit(0)
+
+def RMR_init_xapp(initbind):
+    global RMR_INIT_SVC
+    # Init rmr
+    MRC = mrc = rmr.rmr_init(initbind, rmr.RMR_MAX_RCV_BYTES, 0x00)
+    while rmr.rmr_ready(mrc) == 0:
+        time.sleep(1)
+        print('[%d]::RMR not yet ready')
+    rmr.rmr_set_stimeout(mrc, 1)
+    sbuf = rmr.rmr_alloc_msg(mrc, 500)
+    rmr.rmr_set_vlevel(5)
+    print('[%d]::RMR ready')
+    return mrc, sbuf
+
+def Subscribe(subscriber):
+    # setup the subscription data
+    subEndPoint = subscriber.SubscriptionParamsClientEndpoint("localhost", 8091, 4061)
+    subsDirective = subscriber.SubscriptionParamsE2SubscriptionDirectives(10, 2, False)
+    subsequentAction = subscriber.SubsequentAction("continue", "w10ms")
+    actionDefinitionList = subscriber.ActionToBeSetup(1, "policy", (11,12,13,14,15), subsequentAction)
+    subsDetail = subscriber.SubscriptionDetail(12110, (1,2,3,4,5), actionDefinitionList)
+    # subscription data ready, make the subscription
+    subObj = subscriber.SubscriptionParams("sub10", subEndPoint,"gnb123456",1231, subsDirective, subsDetail)
+    print(subObj.to_dict())
+    # subscribe
+    data, reason, status  = subscriber.Subscribe(subObj)
+    # returns the json data, make it dictionary
+    print(json.loads(data))
+
+    #data, st, hdrs   = api_instance.call_api(method="POST", resource_path="/ric/v1", body=subObj.to_dict())
+    #print(hdrs)
+    #print(data)
+
+    #response = api_instance.request(method="POST", url="http://127.0.0.1:8088/ric/v1", headers=None, body=subObj.to_dict())
+    #print(response.getheaders())
+    #print(respdict['SubscriptionResponse'])
+
+def Unsubscribe(subscriber):
+    reason, status  = subscriber.UnSubscribe("ygwefwebw")
+    print(data)
+    print(reason)
+    print(status)
+
+def QuerySubscribtions(subscriber):
+    data, reason, status  = subscriber.QuerySubscriptions()
+    print(data)
+    print(reason)
+    print(status)
+
+def read_file(filename):
+    try:
+        with open(filename, 'r') as f:
+            data = f.read()
+            if len(data) == 0:
+                return None
+            return data
+    except IOError as error:
+        return None
+
+def getSymptomData(symptomHndl, uriparams):
+    paramlist = urllib.parse.parse_qs(uriparams)
+    [x.upper() for x in paramlist]
+    fromtime = 0
+    totime = 0
+    print(paramlist)
+    if paramlist.get('fromTime'):
+        fromtime = getSeconds(paramlist.get('fromTime')[0])
+    if paramlist.get('toTime'):
+        totime = getSeconds(paramlist.get('toTime')[0])
+    zipfile = symptomHndl.collect("symptomdata"+'-%Y-%m-%d-%H-%M-%S.zip', ('examples/.*.py',), fromtime, totime)
+    if zipfile != None:
+        (zipfile, size, data) = symptomHndl.read()
+        return (zipfile, size, data)
+    return (None, 0, None)
+       
+def healthyGetReadyHandler(name, path, data, ctype):
+    print(name)
+    print(path)
+   
+    response = server.initResponse()
+    response['payload'] = ("{'status': 'ready'}")
+    return response
+
+def healthyGetAliveHandler(name, path, data, ctype):
+    print(name)
+    print(path)
+   
+    response = server.initResponse()
+    response['payload'] = ("{'status': 'alive'}")
+    return response
+        
+def subsResponseCB(name, path, data, ctype):
+    print(name)
+    print(path)
+   
+    response = server.initResponse()
+    response['payload'] = ("{}")
+    return response
+
+def symptomdataGetHandler(name, path, data, ctype):
+    reponse = ricrest.initResponse()
+    (zipfile, size, filedata) = getSymptomData(symptomHndl, self.path[20:])
+    if filedata != None:
+        reponse['payload'] = filedata
+        reponse['ctype'] = 'application/zip'
+        reponse['attachment'] = "symptomdata.zip"
+        reponse['mode'] = 'binary'
+        return reponse
+    logging.error("Symptom data does not exists")
+    reponse['response'] = 'System error - symptomdata does not exists'
+    reponse['status'] = 500
+    return reponse
+
+
+def main():
+    global server
+    global xapp
+    global symptomHndl
+    
+    # init the default values
+    ADDRESS = "0.0.0.0"     # bind to all interfaces
+    PORT = 8080             # web server listen port
+    
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-port', dest='port', help='HTTP server listen port, default 3000', required=False, type=int)
+    parser.add_argument('-address', dest='address', help='IP listen address, default all interfaces', required=False, type=str)
+    parser.add_argument('-xapp', dest='xapp', help='xapp name', required=True, type=str)
+    parser.add_argument('-service', dest='service', help='xapp service name (same as pod host name)', required=True, type=str)
+    args = parser.parse_args()
+    
+    if args.port is not None:
+        PORT = args.port
+    if args.address is not None:
+        ADDRESS = args.address
+
+    # handle the RMR_SEED_RT and RMR_RTG_SVC which is different in mcxapp
+    data = None
+    os.environ["RMR_SRC_ID"] = args.service
+    os.environ["RMR_LOG_VLEVEL"] = '4'
+    os.environ["RMR_RTG_SVC"] = "4561"
+    rmrseed = os.environ.get('RMR_SEED_RT')
+    if rmrseed is not None:
+        data = read_file(rmrseed)
+        if data is None:
+            print("RMR seed file %s does not exists or is empty" % (rmrseed))
+    else:
+        print("RMR_SEED_RT seed file not set in environment")
+        data = read_file('uta-rtg.rt')
+        if data is not None:
+            os.environ['RMR_SEED_RT'] = "./uta-rtg.rt"
+            print("Setting the default RMR_SEED_RT=uta-rtg.rt - content:")
+            print(data)
+        else:
+            print("Try to export the RMR_SEED_RT file if your RMR is not getting ready")
+
+    symptomHndl = Symptomdata(args.service, args.xapp, "/tmp/", "http://service-ricplt-lwsd-http:8080/ric/v1/lwsd", 10)
+    
+    # setup the subscription
+    subscriber = subscribe.NewSubscriber("http://127.0.0.1:8088/ric/v1")
+    
+    # create the thread HTTP server and set the uri handler callbacks
+    server = ricrest.ThreadedHTTPServer(ADDRESS, PORT)
+    # trick to get the own handler with defined 
+    server.handler.add_handler(server.handler, "GET", "healthAlive", "/ric/v1/health/alive", healthyGetAliveHandler)
+    server.handler.add_handler(server.handler, "GET", "healthReady", "/ric/v1/health/ready", healthyGetReadyHandler)
+    server.handler.add_handler(server.handler, "GET", "symptomdata", "/ric/v1/symptomdata", symptomdataGetHandler)
+    # add as well the own subscription response callback handler
+    if subscriber.ResponseHandler(subsResponseCB, server) is not True:
+        print("Error when trying to set the subscription reponse callback")
+    server.start()
+
+    mrc, sbuf = RMR_init_xapp(b"4560")
+
+    Subscribe(subscriber)
+
+    while True:
+        print("Waiting for a message, will timeout after 2000ms")
+        sbuf = rmr.rmr_torcv_msg(mrc, None, 2000)
+        summary = rmr.message_summary(sbuf)
+        if summary[rmr.RMR_MS_MSG_STATE] == 12:
+            print("Nothing received =(")
+        else:
+            print("Message received!: {}".format(summary))
+            data = rmr.get_payload(sbuf)
+        rmr.rmr_free_msg(sbuf)
+
+if __name__ == '__main__':
+    signal.signal(signal.SIGQUIT, signal_handler)
+    signal.signal(signal.SIGTERM, signal_handler)
+    signal.signal(signal.SIGINT, signal_handler)
+    main()
+
+
diff --git a/examples/xapp_symptomdata.py b/examples/xapp_symptomdata.py
new file mode 100644 (file)
index 0000000..cf8f7be
--- /dev/null
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+# ==================================================================================
+#       Copyright (c) 2022 Nokia
+#
+#   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 os
+import sys
+import time
+import json
+import logging
+import datetime
+import argparse
+import threading
+import http.server
+import signal
+import struct
+import socket
+import urllib.parse
+from io import open
+from time import gmtime, strftime
+
+#sys.path.insert(0, '../ricxappframe/xapp-frame-py')
+from ricxappframe.xapp_frame import RMRXapp, rmr
+from ricxappframe.xapp_sdl import SDLWrapper
+from ricxappframe.xapp_symptomdata import Symptomdata
+
+# rmr init mode - when set to port 4561 then will wait for the rtmgr to connect
+# otherwise will connect to rtmgr like set below
+RMR_INIT_SVC = b"4560"
+MRC = None
+xapp = None
+
+def signal_handler(sig, frame):
+    global server
+    global MRC
+    
+    server.stop()
+    rmr.rmr_close(MRC)
+    sys.exit(0)
+
+
+def RMR_init_xapp(initbind):
+    global RMR_INIT_SVC
+    # Init rmr
+    MRC = mrc = rmr.rmr_init(initbind, rmr.RMR_MAX_RCV_BYTES, 0x00)
+    while rmr.rmr_ready(mrc) == 0:
+        time.sleep(1)
+        print('[%d]::RMR not yet ready')
+    rmr.rmr_set_stimeout(mrc, 1)
+    sbuf = rmr.rmr_alloc_msg(mrc, 500)
+    rmr.rmr_set_vlevel(5)
+    print('[%d]::RMR ready')
+    return mrc, sbuf
+
+def read_file(filename):
+    try:
+        with open(filename, 'r') as f:
+            data = f.read()
+            if len(data) == 0:
+                return None
+            return data
+    except IOError as error:
+        return None
+
+def getSymptomData(symptomHndl, uriparams):
+    paramlist = urllib.parse.parse_qs(uriparams)
+    [x.upper() for x in paramlist]
+    fromtime = 0
+    totime = 0
+    print(paramlist)
+    if paramlist.get('fromTime'):
+        fromtime = getSeconds(paramlist.get('fromTime')[0])
+    if paramlist.get('toTime'):
+        totime = getSeconds(paramlist.get('toTime')[0])
+    zipfile = symptomHndl.collect("symptomdata"+'-%Y-%m-%d-%H-%M-%S.zip', ('examples/.*.py',), fromtime, totime)
+    if zipfile != None:
+        (zipfile, size, data) = symptomHndl.read()
+        return (zipfile, size, data)
+    return (None, 0, None)
+
+
+class RestHandler(http.server.BaseHTTPRequestHandler):
+    # responds to http request according to the process status
+    global symptomHndl
+    
+    def _set_headers(self, status, length=0, ctype = 'application/json', attachment = None):
+        self.send_response(status)
+        self.send_header("Server-name", "XAPP REST SERVER 1.0")
+        self.send_header('Content-type', ctype)
+        if length != 0:
+            self.send_header('Content-length', length)
+        if attachment != None:
+            self.send_header('Content-Disposition', "attachment; filename=" + attachment)
+        self.end_headers()
+        
+    def do_HEAD(self):
+        self._set_headers()
+        
+    def do_POST(self):
+        try:
+            logging.debug("POST %s" % (self.path))
+        except (socket.error, IOError):
+            pass
+
+    def do_DELETE(self):
+        try:
+            logging.debug("DELETE %s" % (self.path))
+        except (socket.error, IOError):
+            pass
+
+
+    def do_GET(self):
+        # default get handler
+        try:
+            data = None
+            mode = 'plain'
+            ctype = 'application/json'
+            attachment = None
+            if self.path == "/ric/v1/health/alive":
+                data = json.dumps({'status': 'alive'})
+            elif self.path == "/ric/v1/health/ready":
+                data = json.dumps({'status': 'ready'})
+            elif self.path.find("/ric/v1/symptomdata") >= 0:
+                (zipfile, size, data) = getSymptomData(symptomHndl, self.path[20:])
+                if data != None:
+                    mode = 'binary'
+                    ctype = 'application/zip'
+                    attachment = "symptomdata.zip"
+                else:
+                    logging.error("Symptom data does not exists")
+                    self._set_headers(404, 0)
+                
+            if data is not None:
+                length = len(data)
+                self._set_headers(200, length, ctype, attachment)
+                if mode == 'plain':
+                    # ascii mode
+                    self.wfile.write(data.encode('utf-8'))
+                else:
+                    # binary mode
+                    self.wfile.write(data)
+            else:
+                logging.error("Unknown uri %s" % (self.path))
+                self._set_headers(404, 0)
+        except (socket.error, IOError):
+            pass
+class ThreadedHTTPServer(object):
+    handler = RestHandler
+    server_class = http.server.HTTPServer
+    def __init__(self, host, port):
+        self.server = self.server_class((host, port), self.handler)
+        self.server_thread = threading.Thread(target=self.server.serve_forever)
+        self.server_thread.daemon = True
+
+    def start(self):
+        self.server_thread.start()
+
+    def stop(self):
+        self.server.socket.close()
+        self.server.server_close()
+        self.server.shutdown()
+
+def main():
+    global server
+    global xapp
+    global symptomHndl
+    
+    # init the default values
+    ADDRESS = "0.0.0.0"     # bind to all interfaces
+    PORT = 8080             # web server listen port
+    
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-port', dest='port', help='HTTP server listen port, default 3000', required=False, type=int)
+    parser.add_argument('-address', dest='address', help='IP listen address, default all interfaces', required=False, type=str)
+    parser.add_argument('-xapp', dest='xapp', help='xapp name', required=True, type=str)
+    parser.add_argument('-service', dest='service', help='xapp service name (same as pod host name)', required=True, type=str)
+    args = parser.parse_args()
+    
+    if args.port is not None:
+        PORT = args.port
+    if args.address is not None:
+        ADDRESS = args.address
+
+    # handle the RMR_SEED_RT and RMR_RTG_SVC which is different in mcxapp
+    data = None
+    os.environ["RMR_SRC_ID"] = args.service
+    os.environ["RMR_LOG_VLEVEL"] = '4'
+    os.environ["RMR_RTG_SVC"] = "4561"
+    rmrseed = os.environ.get('RMR_SEED_RT')
+    if rmrseed is not None:
+        data = read_file(rmrseed)
+        if data is None:
+            print("RMR seed file %s does not exists or is empty" % (rmrseed))
+    else:
+        print("RMR_SEED_RT seed file not set in environment")
+        data = read_file('uta-rtg.rt')
+        if data is not None:
+            os.environ['RMR_SEED_RT'] = "./uta-rtg.rt"
+            print("Setting the default RMR_SEED_RT=uta-rtg.rt - content:")
+            print(data)
+        else:
+            print("Try to export the RMR_SEED_RT file if your RMR is not getting ready")
+
+    symptomHndl = Symptomdata(args.service, args.xapp, "/tmp/", "http://service-ricplt-lwsd-http:8080/ric/v1/lwsd", 10)
+    
+    # Start the threaded server, bind to address
+    server = ThreadedHTTPServer(ADDRESS, PORT)
+    server.start()
+
+    mrc, sbuf = RMR_init_xapp(b"4560")
+
+    while True:
+        print("Waiting for a message, will timeout after 2000ms")
+        sbuf = rmr.rmr_torcv_msg(mrc, None, 2000)
+        summary = rmr.message_summary(sbuf)
+        if summary[rmr.RMR_MS_MSG_STATE] == 12:
+            print("Nothing received =(")
+        else:
+            print("Message received!: {}".format(summary))
+            data = rmr.get_payload(sbuf)
+        rmr.rmr_free_msg(sbuf)
+
+if __name__ == '__main__':
+    signal.signal(signal.SIGQUIT, signal_handler)
+    signal.signal(signal.SIGTERM, signal_handler)
+    signal.signal(signal.SIGINT, signal_handler)
+    main()
diff --git a/examples/xapp_test.py b/examples/xapp_test.py
new file mode 100644 (file)
index 0000000..b0be598
--- /dev/null
@@ -0,0 +1,317 @@
+#!/usr/bin/env python3
+# ==================================================================================
+#       Copyright (c) 2022 Nokia
+#
+#   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 os
+import sys
+import time
+import json
+import logging
+import datetime
+import argparse
+import threading
+import http.server
+import signal
+import struct
+import socket
+import urllib.parse
+from io import open
+from time import gmtime, strftime
+
+#sys.path.insert(0, os.path.abspath("./"))
+#sys.path.insert(0, os.path.abspath("./ricxappframe"))
+sys.path.append(os.getcwd())
+from ricxappframe.xapp_frame import RMRXapp, rmr
+from ricxappframe.xapp_sdl import SDLWrapper
+from ricxappframe.xapp_symptomdata import Symptomdata
+import ricxappframe.xapp_subscribe as subscribe
+import ricxappframe.xapp_rest as ricrest
+from mdclogpy import Logger, Level
+
+class Config(object):
+    def __init__(self, xapp_name, config_file):
+        self.config_file = config_file
+        self.xapp_name = xapp_name
+        self.cfg = None
+        self.keys = dict()
+        self.config()
+
+    def config(self):
+        with open(self.config_file, 'r') as file:
+            cfg = file.read()
+            if cfg != None:
+                self.cfg = json.loads(cfg)
+                if self.cfg is not None:
+                    self.controls = self.cfg['controls']
+
+    def get_key_item(self, key):
+        data = None
+        if self.keys.get(key) is not None:
+            data = self.keys[key]
+        return data
+
+    def get_config(self):
+        data = None
+        with open(self.config_file, 'r') as file:
+            cfg = file.read()
+            if cfg != None:
+                self.cfg = json.loads(cfg)
+                # following is required by the appmgr -  don't know why.
+                cfgescaped = cfg.replace('"', '\\"').replace('\n', '\\n')
+                data = '[{ "config": "' + cfgescaped + '", "metadata":{"configType":"json","xappName":"' + self.xapp_name + '"}}]'
+        if data == None:
+            logging.error("Config file %s empty or does not exists" % (self.config_file))
+        return data
+
+def read_file(filename):
+    try:
+        with open(filename, 'r') as f:
+            data = f.read()
+            if len(data) == 0:
+                return None
+            return data
+    except IOError as error:
+        return None
+
+
+class MyXapp(object):
+
+    def __init__(self, name, service, address, port, config, loglevel):
+        signal.signal(signal.SIGQUIT, self.signal_handler)
+        signal.signal(signal.SIGTERM, self.signal_handler)
+        signal.signal(signal.SIGINT, self.signal_handler)
+        self.running = False
+        
+        self.configData = Config(name, config)
+
+        if self.configData.controls.get('logger'):
+            level = self.configData.controls['logger'].get('level')
+
+        if port == None and self.configData.cfg['messaging'].get('ports'):
+            for item in self.configData.cfg['messaging'].get('ports'):
+                if item['name'] == http:
+                    port = int(item['port'])
+        if address == None and self.configData.cfg.get('name'):
+            address = self.configData.cfg.get('name')
+            
+        # save the listen address and port for later use
+        self.port = port
+        self.address = address
+        
+        self.logger = Logger(name, loglevel)
+        # setup the symptomdata
+        symptomCfg = self.GetSymptomConfig()
+        self.symptomHndl = Symptomdata(service, name, "/tmp/", symptomCfg['url'], symptomCfg['timeout'])
+
+        # create the thread HTTP server and set the uri handler callbacks
+        self.server = ricrest.ThreadedHTTPServer(address, port)
+        # trick to get the own handler with defined 
+        self.server.handler.add_handler(self.server.handler, "GET", "config", "/ric/v1/config", self.configGetHandler)
+        self.server.handler.add_handler(self.server.handler, "GET", "healthAlive", "/ric/v1/health/alive", self.healthyGetAliveHandler)
+        self.server.handler.add_handler(self.server.handler, "GET", "healthReady", "/ric/v1/health/ready", self.healthyGetReadyHandler)
+        self.server.handler.add_handler(self.server.handler, "GET", "symptomdata", "/ric/v1/symptomdata", self.symptomdataGetHandler)
+        # start rest server
+        self.server.start()
+        # start RMR
+        self.startRMR(service, 4)
+        self.running = True
+        # now we can subscribe
+        self.Subscribe()
+
+    def startRMR(self, service, level):
+        # handle the RMR_SEED_RT and RMR_RTG_SVC which is different in mcxapp
+        data = None
+        os.environ["RMR_SRC_ID"] = service
+        os.environ["RMR_LOG_VLEVEL"] = str(level)
+        os.environ["RMR_RTG_SVC"] = "4561"
+        rmrseed = os.environ.get('RMR_SEED_RT')
+        if rmrseed is not None:
+            data = read_file(rmrseed)
+            if data is None:
+                self.logger.warning("RMR seed file %s does not exists or is empty" % (rmrseed))
+        else:
+            self.logger.info("RMR_SEED_RT seed file not set in environment")
+            data = read_file('uta-rtg.rt')
+            if data is not None:
+                os.environ['RMR_SEED_RT'] = "./uta-rtg.rt"
+                self.logger.info("Setting the default RMR_SEED_RT=uta-rtg.rt - content:")
+            else:
+                self.logger.info("Try to export the RMR_SEED_RT file if your RMR is not getting ready")
+        self.rmrInit(b"4560")
+
+    def signal_handler(self, sig, frame):
+        if self.running is True:
+            self.server.stop()
+            rmr.rmr_close(self.rmr_mrc)
+        self.running = False
+        sys.exit(0)
+
+    def rmrInit(self, initbind):
+        # Init rmr
+        self.rmr_mrc = rmr.rmr_init(initbind, rmr.RMR_MAX_RCV_BYTES, 0x00)
+        while rmr.rmr_ready(self.rmr_mrc) == 0:
+            time.sleep(1)
+            self.logger.info('RMR not yet ready')
+        rmr.rmr_set_stimeout(self.rmr_mrc, 1)
+        rmr.rmr_set_vlevel(5)
+        self.logger.info('RMR ready')
+
+    def GetSymptomConfig(self):
+        if self.configData.cfg['controls'].get('symptomdata').get('lwsd'):
+            return self.configData.cfg['controls'].get('symptomdata').get('lwsd')
+
+    def GetSubsConfig(self):
+        if self.configData.cfg['controls'].get('subscription'):
+            return self.configData.cfg['controls'].get('subscription')
+
+    def Subscribe(self):
+        self.subsCfgDetail = self.GetSubsConfig()
+        if self.subsCfgDetail != None:
+            # this is example subscription, for your use case fill the attributes according to your needs
+            self.subscriber = subscribe.NewSubscriber(self.subsCfgDetail['url'] + 'ric/v1')
+            # add as well the own subscription response callback handler
+            if self.subscriber.ResponseHandler(self.subsResponseCB, self.server) is not True:
+                self.logger.error("Error when trying to set the subscription reponse callback")
+            # setup the subscription data
+            subEndPoint = self.subscriber.SubscriptionParamsClientEndpoint(self.subsCfgDetail['clientEndpoint'], self.port, 4061)
+            subsDirective = self.subscriber.SubscriptionParamsE2SubscriptionDirectives(10, 2, False)
+            subsequentAction = self.subscriber.SubsequentAction("continue", "w10ms")
+            actionDefinitionList = self.subscriber.ActionToBeSetup(1, "policy", (11,12,13,14,15), subsequentAction)
+            subsDetail = self.subscriber.SubscriptionDetail(12110, (1,2,3,4,5), actionDefinitionList)
+            # subscription data ready, make the subscription
+            subObj = self.subscriber.SubscriptionParams("sub10", subEndPoint,"gnb123456",1231, subsDirective, subsDetail)
+            self.logger.info("Sending the subscription to %s" %(self.subsCfgDetail['url'] + 'ric/v1'))
+            self.logger.info(subObj.to_dict())
+            # subscribe
+            data, reason, status  = self.subscriber.Subscribe(subObj)
+            # returns the json data, make it dictionary
+            self.logger.info("Getting the subscription reponse")
+            self.logger.info(json.loads(data))
+
+    def Unsubscribe(self):
+        reason, status  = self.subscriber.UnSubscribe("ygwefwebw")
+
+    def QuerySubscribtions(self):
+        data, reason, status  = self.subscriber.QuerySubscriptions()
+
+    def healthyGetReadyHandler(self, name, path, data, ctype):
+        response = server.initResponse()
+        response['payload'] = ("{'status': 'ready'}")
+        return response
+
+    def healthyGetAliveHandler(self, name, path, data, ctype):
+        response = server.initResponse()
+        response['payload'] = ("{'status': 'alive'}")
+        return response
+            
+    def subsResponseCB(self, name, path, data, ctype):
+        response = server.initResponse()
+        response['payload'] = ("{}")
+        return response
+
+    def getSymptomData(self, uriparams):
+        paramlist = urllib.parse.parse_qs(uriparams)
+        [x.upper() for x in paramlist]
+        fromtime = 0
+        totime = 0
+        print(paramlist)
+        if paramlist.get('fromTime'):
+            fromtime = getSeconds(paramlist.get('fromTime')[0])
+        if paramlist.get('toTime'):
+            totime = getSeconds(paramlist.get('toTime')[0])
+        zipfile = self.symptomHndl.collect("symptomdata"+'-%Y-%m-%d-%H-%M-%S.zip', ('examples/.*.py',), fromtime, totime)
+        if zipfile != None:
+            (zipfile, size, data) = self.symptomHndl.read()
+            return (zipfile, size, data)
+        return (None, 0, None)
+
+    def symptomdataGetHandler(self, name, path, data, ctype):
+        reponse = ricrest.initResponse()
+        (zipfile, size, filedata) = self.getSymptomData(self.path[20:])
+        if filedata != None:
+            reponse['payload'] = filedata
+            reponse['ctype'] = 'application/zip'
+            reponse['attachment'] = "symptomdata.zip"
+            reponse['mode'] = 'binary'
+            return reponse
+        logging.error("Symptom data does not exists")
+        reponse['response'] = 'System error - symptomdata does not exists'
+        reponse['status'] = 500
+        return reponse
+
+    def configGetHandler(self, name, path, data, ctype):
+        response = server.initResponse()
+        response['payload'] = (self.configData.get_config())
+        return response
+
+def removeEnvVar(evar):
+    if evar in os.environ:
+        del os.environ[evar]
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-port', dest='port', help='HTTP server listen port, default 8088', required=False, type=int)
+    parser.add_argument('-address', dest='address', help='IP listen address, default all interfaces', required=False, type=str)
+    parser.add_argument('-config', dest='config', help='config file path name, default /opt/ric/config/config.json', required=False, type=str)
+    parser.add_argument('-xapp', dest='xapp', help='xapp name', required=True, type=str)
+    parser.add_argument('-service', dest='service', help='xapp service name (same as pod host name)', required=True, type=str)
+    parser.add_argument('-verbose', dest='verbose', help='verbose logging level', required=False, type=int)
+    
+    args = parser.parse_args()
+    
+    if args.port is None:
+        args.port = 8088 
+    if args.address is None:
+        args.address = "0.0.0.0"
+    if args.config is None:
+        args.config = '/opt/ric/config/config.json'
+
+    # remove proxy so that it won't impact to rest calls
+    removeEnvVar('HTTPS_PROXY')
+    removeEnvVar('HTTP_PROXY')
+    removeEnvVar('https_proxy')
+    removeEnvVar('http_proxy')
+
+    # starting argument option will overwrite the config settings
+    if args.verbose is None:
+        args.verbose = 2
+
+    loglevel = Level.INFO
+    if args.verbose == 0:
+        loglevel = Level.ERROR
+    if args.verbose == 1:
+        loglevel = Level.WARNING
+    elif args.verbose == 2:
+        loglevel = Level.INFO
+    elif args.verbose >= 3:
+        loglevel = Level.DEBUG
+
+    myxapp = MyXapp(args.xapp, args.service, args.address, args.port, args.config, loglevel)
+
+    while True:
+        print("Waiting for a message, will timeout after 10s")
+        rmr_sbuf = rmr.rmr_torcv_msg(myxapp.rmr_mrc, None, 10000)
+        summary = rmr.message_summary(rmr_sbuf)
+        if summary[rmr.RMR_MS_MSG_STATE] == 12:
+            print("Nothing received")
+        else:
+            print("Message received!: {}".format(summary))
+            data = rmr.get_payload(rmr_sbuf)
+        rmr.rmr_free_msg(rmr_sbuf)
+
+if __name__ == '__main__':
+    main()
+
+
diff --git a/ricxappframe/entities/__init__.py b/ricxappframe/entities/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/ricxappframe/entities/rnib/__init__.py b/ricxappframe/entities/rnib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
index 64d575d..a5396b7 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: additional_cell_information.proto
 
@@ -107,11 +108,11 @@ _ADDITIONALCELLINFORMATION = _descriptor.Descriptor(
 DESCRIPTOR.message_types_by_name['AdditionalCellInformation'] = _ADDITIONALCELLINFORMATION
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-AdditionalCellInformation = _reflection.GeneratedProtocolMessageType('AdditionalCellInformation', (_message.Message,), dict(
-  DESCRIPTOR = _ADDITIONALCELLINFORMATION,
-  __module__ = 'additional_cell_information_pb2'
+AdditionalCellInformation = _reflection.GeneratedProtocolMessageType('AdditionalCellInformation', (_message.Message,), {
+  'DESCRIPTOR' : _ADDITIONALCELLINFORMATION,
+  '__module__' : 'additional_cell_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.AdditionalCellInformation)
-  ))
+  })
 _sym_db.RegisterMessage(AdditionalCellInformation)
 
 
index bd22582..22e07b8 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: cell.proto
 
@@ -115,11 +116,11 @@ _CELL.fields_by_name['served_nr_cell'].containing_oneof = _CELL.oneofs_by_name['
 DESCRIPTOR.message_types_by_name['Cell'] = _CELL
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-Cell = _reflection.GeneratedProtocolMessageType('Cell', (_message.Message,), dict(
-  DESCRIPTOR = _CELL,
-  __module__ = 'cell_pb2'
+Cell = _reflection.GeneratedProtocolMessageType('Cell', (_message.Message,), {
+  'DESCRIPTOR' : _CELL,
+  '__module__' : 'cell_pb2'
   # @@protoc_insertion_point(class_scope:entities.Cell)
-  ))
+  })
 _sym_db.RegisterMessage(Cell)
 
 
index 0d31c68..71419ca 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: cells.proto
 
@@ -154,25 +155,25 @@ DESCRIPTOR.message_types_by_name['ServedCellInfoList'] = _SERVEDCELLINFOLIST
 DESCRIPTOR.message_types_by_name['ServedNRCellList'] = _SERVEDNRCELLLIST
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-Cells = _reflection.GeneratedProtocolMessageType('Cells', (_message.Message,), dict(
-  DESCRIPTOR = _CELLS,
-  __module__ = 'cells_pb2'
+Cells = _reflection.GeneratedProtocolMessageType('Cells', (_message.Message,), {
+  'DESCRIPTOR' : _CELLS,
+  '__module__' : 'cells_pb2'
   # @@protoc_insertion_point(class_scope:entities.Cells)
-  ))
+  })
 _sym_db.RegisterMessage(Cells)
 
-ServedCellInfoList = _reflection.GeneratedProtocolMessageType('ServedCellInfoList', (_message.Message,), dict(
-  DESCRIPTOR = _SERVEDCELLINFOLIST,
-  __module__ = 'cells_pb2'
+ServedCellInfoList = _reflection.GeneratedProtocolMessageType('ServedCellInfoList', (_message.Message,), {
+  'DESCRIPTOR' : _SERVEDCELLINFOLIST,
+  '__module__' : 'cells_pb2'
   # @@protoc_insertion_point(class_scope:entities.ServedCellInfoList)
-  ))
+  })
 _sym_db.RegisterMessage(ServedCellInfoList)
 
-ServedNRCellList = _reflection.GeneratedProtocolMessageType('ServedNRCellList', (_message.Message,), dict(
-  DESCRIPTOR = _SERVEDNRCELLLIST,
-  __module__ = 'cells_pb2'
+ServedNRCellList = _reflection.GeneratedProtocolMessageType('ServedNRCellList', (_message.Message,), {
+  'DESCRIPTOR' : _SERVEDNRCELLLIST,
+  '__module__' : 'cells_pb2'
   # @@protoc_insertion_point(class_scope:entities.ServedNRCellList)
-  ))
+  })
 _sym_db.RegisterMessage(ServedNRCellList)
 
 
diff --git a/ricxappframe/entities/rnib/e2node_component_config_pb2.py b/ricxappframe/entities/rnib/e2node_component_config_pb2.py
new file mode 100644 (file)
index 0000000..90aa556
--- /dev/null
@@ -0,0 +1,735 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: e2node_component_config.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from . import nb_types_pb2 as nb__types__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='e2node_component_config.proto',
+  package='entities',
+  syntax='proto3',
+  serialized_options=None,
+  serialized_pb=_b('\n\x1d\x65\x32node_component_config.proto\x12\x08\x65ntities\x1a\x0enb_types.proto\"\xf3\x05\n\x15\x45\x32nodeComponentConfig\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeNG\x18\x01 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceNGH\x00\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeXn\x18\x02 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceXnH\x00\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeE1\x18\x03 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceE1H\x00\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeF1\x18\x04 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceF1H\x00\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeW1\x18\x05 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceW1H\x00\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeS1\x18\x06 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceS1H\x00\x12N\n\x1e\x65\x32nodeComponentInterfaceTypeX2\x18\x07 \x01(\x0b\x32$.entities.E2nodeComponentInterfaceX2H\x00\x12L\n\x1c\x65\x32nodeComponentInterfaceType\x18\x08 \x01(\x0e\x32&.entities.E2nodeComponentInterfaceType\x12\"\n\x1a\x65\x32nodeComponentRequestPart\x18\t \x01(\x0c\x12#\n\x1b\x65\x32nodeComponentResponsePart\x18\n \x01(\x0c\x42\x13\n\x11\x45\x32nodeComponentID\".\n\x1a\x45\x32nodeComponentInterfaceNG\x12\x10\n\x08\x61mf_name\x18\x0b \x01(\t\"\x99\x01\n\x1a\x45\x32nodeComponentInterfaceXn\x12\x32\n\x0fglobal_ngenb_id\x18\x0c \x01(\x0b\x32\x17.entities.GlobalNGENBIDH\x00\x12.\n\rglobal_gnb_id\x18\r \x01(\x0b\x32\x15.entities.GlobalGNBIDH\x00\x42\x17\n\x15global_ng_ran_node_id\"2\n\x1a\x45\x32nodeComponentInterfaceE1\x12\x14\n\x0cgNB_cu_cp_id\x18\x0e \x01(\x03\"/\n\x1a\x45\x32nodeComponentInterfaceF1\x12\x11\n\tgNB_du_id\x18\x0f \x01(\x03\"1\n\x1a\x45\x32nodeComponentInterfaceW1\x12\x13\n\x0bngenb_du_id\x18\x10 \x01(\x03\".\n\x1a\x45\x32nodeComponentInterfaceS1\x12\x10\n\x08mme_name\x18\x11 \x01(\t\"|\n\x1a\x45\x32nodeComponentInterfaceX2\x12,\n\rglobal_enb_id\x18\x12 \x01(\x0b\x32\x15.entities.GlobalENBID\x12\x30\n\x0fglobal_engnb_id\x18\x13 \x01(\x0b\x32\x17.entities.GlobalENGNBID\"Y\n\x0bGlobalENBID\x12\x15\n\rplmn_identity\x18\x14 \x01(\t\x12\x0e\n\x06\x65nb_id\x18\x15 \x01(\t\x12#\n\x08\x65nb_type\x18\x16 \x01(\x0e\x32\x11.entities.EnbType\"[\n\rGlobalENGNBID\x12\x15\n\rplmn_identity\x18\x17 \x01(\t\x12\x0e\n\x06gnb_id\x18\x18 \x01(\t\x12#\n\x08gnb_type\x18\x19 \x01(\x0e\x32\x11.entities.GnbType\"Y\n\x0bGlobalGNBID\x12\x15\n\rplmn_identity\x18\x1a \x01(\t\x12\x0e\n\x06gnb_id\x18\x1b \x01(\t\x12#\n\x08gnb_type\x18\x1c \x01(\x0e\x32\x11.entities.GnbType\"[\n\rGlobalNGENBID\x12\x15\n\rplmn_identity\x18\x1d \x01(\t\x12\x0e\n\x06\x65nb_id\x18\x1e \x01(\t\x12#\n\x08\x65nb_type\x18\x1f \x01(\x0e\x32\x11.entities.EnbType*V\n\x1c\x45\x32nodeComponentInterfaceType\x12\x06\n\x02ng\x10\x00\x12\x06\n\x02xn\x10\x01\x12\x06\n\x02\x65\x31\x10\x02\x12\x06\n\x02\x66\x31\x10\x03\x12\x06\n\x02w1\x10\x05\x12\x06\n\x02s1\x10\x06\x12\x06\n\x02x2\x10\x07\x62\x06proto3')
+  ,
+  dependencies=[nb__types__pb2.DESCRIPTOR,])
+
+_E2NODECOMPONENTINTERFACETYPE = _descriptor.EnumDescriptor(
+  name='E2nodeComponentInterfaceType',
+  full_name='entities.E2nodeComponentInterfaceType',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='ng', index=0, number=0,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='xn', index=1, number=1,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='e1', index=2, number=2,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='f1', index=3, number=3,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='w1', index=4, number=5,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='s1', index=5, number=6,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='x2', index=6, number=7,
+      serialized_options=None,
+      type=None),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=1715,
+  serialized_end=1801,
+)
+_sym_db.RegisterEnumDescriptor(_E2NODECOMPONENTINTERFACETYPE)
+
+E2nodeComponentInterfaceType = enum_type_wrapper.EnumTypeWrapper(_E2NODECOMPONENTINTERFACETYPE)
+ng = 0
+xn = 1
+e1 = 2
+f1 = 3
+w1 = 5
+s1 = 6
+x2 = 7
+
+
+
+_E2NODECOMPONENTCONFIG = _descriptor.Descriptor(
+  name='E2nodeComponentConfig',
+  full_name='entities.E2nodeComponentConfig',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeNG', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeNG', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeXn', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeXn', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeE1', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeE1', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeF1', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeF1', index=3,
+      number=4, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeW1', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeW1', index=4,
+      number=5, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeS1', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeS1', index=5,
+      number=6, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceTypeX2', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceTypeX2', index=6,
+      number=7, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentInterfaceType', full_name='entities.E2nodeComponentConfig.e2nodeComponentInterfaceType', index=7,
+      number=8, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentRequestPart', full_name='entities.E2nodeComponentConfig.e2nodeComponentRequestPart', index=8,
+      number=9, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b(""),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e2nodeComponentResponsePart', full_name='entities.E2nodeComponentConfig.e2nodeComponentResponsePart', index=9,
+      number=10, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b(""),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+    _descriptor.OneofDescriptor(
+      name='E2nodeComponentID', full_name='entities.E2nodeComponentConfig.E2nodeComponentID',
+      index=0, containing_type=None, fields=[]),
+  ],
+  serialized_start=60,
+  serialized_end=815,
+)
+
+
+_E2NODECOMPONENTINTERFACENG = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceNG',
+  full_name='entities.E2nodeComponentInterfaceNG',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='amf_name', full_name='entities.E2nodeComponentInterfaceNG.amf_name', index=0,
+      number=11, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=817,
+  serialized_end=863,
+)
+
+
+_E2NODECOMPONENTINTERFACEXN = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceXn',
+  full_name='entities.E2nodeComponentInterfaceXn',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='global_ngenb_id', full_name='entities.E2nodeComponentInterfaceXn.global_ngenb_id', index=0,
+      number=12, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='global_gnb_id', full_name='entities.E2nodeComponentInterfaceXn.global_gnb_id', index=1,
+      number=13, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+    _descriptor.OneofDescriptor(
+      name='global_ng_ran_node_id', full_name='entities.E2nodeComponentInterfaceXn.global_ng_ran_node_id',
+      index=0, containing_type=None, fields=[]),
+  ],
+  serialized_start=866,
+  serialized_end=1019,
+)
+
+
+_E2NODECOMPONENTINTERFACEE1 = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceE1',
+  full_name='entities.E2nodeComponentInterfaceE1',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='gNB_cu_cp_id', full_name='entities.E2nodeComponentInterfaceE1.gNB_cu_cp_id', index=0,
+      number=14, type=3, cpp_type=2, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1021,
+  serialized_end=1071,
+)
+
+
+_E2NODECOMPONENTINTERFACEF1 = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceF1',
+  full_name='entities.E2nodeComponentInterfaceF1',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='gNB_du_id', full_name='entities.E2nodeComponentInterfaceF1.gNB_du_id', index=0,
+      number=15, type=3, cpp_type=2, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1073,
+  serialized_end=1120,
+)
+
+
+_E2NODECOMPONENTINTERFACEW1 = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceW1',
+  full_name='entities.E2nodeComponentInterfaceW1',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='ngenb_du_id', full_name='entities.E2nodeComponentInterfaceW1.ngenb_du_id', index=0,
+      number=16, type=3, cpp_type=2, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1122,
+  serialized_end=1171,
+)
+
+
+_E2NODECOMPONENTINTERFACES1 = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceS1',
+  full_name='entities.E2nodeComponentInterfaceS1',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='mme_name', full_name='entities.E2nodeComponentInterfaceS1.mme_name', index=0,
+      number=17, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1173,
+  serialized_end=1219,
+)
+
+
+_E2NODECOMPONENTINTERFACEX2 = _descriptor.Descriptor(
+  name='E2nodeComponentInterfaceX2',
+  full_name='entities.E2nodeComponentInterfaceX2',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='global_enb_id', full_name='entities.E2nodeComponentInterfaceX2.global_enb_id', index=0,
+      number=18, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='global_engnb_id', full_name='entities.E2nodeComponentInterfaceX2.global_engnb_id', index=1,
+      number=19, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1221,
+  serialized_end=1345,
+)
+
+
+_GLOBALENBID = _descriptor.Descriptor(
+  name='GlobalENBID',
+  full_name='entities.GlobalENBID',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='plmn_identity', full_name='entities.GlobalENBID.plmn_identity', index=0,
+      number=20, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='enb_id', full_name='entities.GlobalENBID.enb_id', index=1,
+      number=21, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='enb_type', full_name='entities.GlobalENBID.enb_type', index=2,
+      number=22, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1347,
+  serialized_end=1436,
+)
+
+
+_GLOBALENGNBID = _descriptor.Descriptor(
+  name='GlobalENGNBID',
+  full_name='entities.GlobalENGNBID',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='plmn_identity', full_name='entities.GlobalENGNBID.plmn_identity', index=0,
+      number=23, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='gnb_id', full_name='entities.GlobalENGNBID.gnb_id', index=1,
+      number=24, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='gnb_type', full_name='entities.GlobalENGNBID.gnb_type', index=2,
+      number=25, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1438,
+  serialized_end=1529,
+)
+
+
+_GLOBALGNBID = _descriptor.Descriptor(
+  name='GlobalGNBID',
+  full_name='entities.GlobalGNBID',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='plmn_identity', full_name='entities.GlobalGNBID.plmn_identity', index=0,
+      number=26, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='gnb_id', full_name='entities.GlobalGNBID.gnb_id', index=1,
+      number=27, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='gnb_type', full_name='entities.GlobalGNBID.gnb_type', index=2,
+      number=28, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1531,
+  serialized_end=1620,
+)
+
+
+_GLOBALNGENBID = _descriptor.Descriptor(
+  name='GlobalNGENBID',
+  full_name='entities.GlobalNGENBID',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='plmn_identity', full_name='entities.GlobalNGENBID.plmn_identity', index=0,
+      number=29, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='enb_id', full_name='entities.GlobalNGENBID.enb_id', index=1,
+      number=30, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='enb_type', full_name='entities.GlobalNGENBID.enb_type', index=2,
+      number=31, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1622,
+  serialized_end=1713,
+)
+
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeNG'].message_type = _E2NODECOMPONENTINTERFACENG
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeXn'].message_type = _E2NODECOMPONENTINTERFACEXN
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeE1'].message_type = _E2NODECOMPONENTINTERFACEE1
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeF1'].message_type = _E2NODECOMPONENTINTERFACEF1
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeW1'].message_type = _E2NODECOMPONENTINTERFACEW1
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeS1'].message_type = _E2NODECOMPONENTINTERFACES1
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeX2'].message_type = _E2NODECOMPONENTINTERFACEX2
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceType'].enum_type = _E2NODECOMPONENTINTERFACETYPE
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeNG'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeNG'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeXn'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeXn'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeE1'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeE1'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeF1'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeF1'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeW1'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeW1'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeS1'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeS1'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID'].fields.append(
+  _E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeX2'])
+_E2NODECOMPONENTCONFIG.fields_by_name['e2nodeComponentInterfaceTypeX2'].containing_oneof = _E2NODECOMPONENTCONFIG.oneofs_by_name['E2nodeComponentID']
+_E2NODECOMPONENTINTERFACEXN.fields_by_name['global_ngenb_id'].message_type = _GLOBALNGENBID
+_E2NODECOMPONENTINTERFACEXN.fields_by_name['global_gnb_id'].message_type = _GLOBALGNBID
+_E2NODECOMPONENTINTERFACEXN.oneofs_by_name['global_ng_ran_node_id'].fields.append(
+  _E2NODECOMPONENTINTERFACEXN.fields_by_name['global_ngenb_id'])
+_E2NODECOMPONENTINTERFACEXN.fields_by_name['global_ngenb_id'].containing_oneof = _E2NODECOMPONENTINTERFACEXN.oneofs_by_name['global_ng_ran_node_id']
+_E2NODECOMPONENTINTERFACEXN.oneofs_by_name['global_ng_ran_node_id'].fields.append(
+  _E2NODECOMPONENTINTERFACEXN.fields_by_name['global_gnb_id'])
+_E2NODECOMPONENTINTERFACEXN.fields_by_name['global_gnb_id'].containing_oneof = _E2NODECOMPONENTINTERFACEXN.oneofs_by_name['global_ng_ran_node_id']
+_E2NODECOMPONENTINTERFACEX2.fields_by_name['global_enb_id'].message_type = _GLOBALENBID
+_E2NODECOMPONENTINTERFACEX2.fields_by_name['global_engnb_id'].message_type = _GLOBALENGNBID
+_GLOBALENBID.fields_by_name['enb_type'].enum_type = nb__types__pb2._ENBTYPE
+_GLOBALENGNBID.fields_by_name['gnb_type'].enum_type = nb__types__pb2._GNBTYPE
+_GLOBALGNBID.fields_by_name['gnb_type'].enum_type = nb__types__pb2._GNBTYPE
+_GLOBALNGENBID.fields_by_name['enb_type'].enum_type = nb__types__pb2._ENBTYPE
+DESCRIPTOR.message_types_by_name['E2nodeComponentConfig'] = _E2NODECOMPONENTCONFIG
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceNG'] = _E2NODECOMPONENTINTERFACENG
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceXn'] = _E2NODECOMPONENTINTERFACEXN
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceE1'] = _E2NODECOMPONENTINTERFACEE1
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceF1'] = _E2NODECOMPONENTINTERFACEF1
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceW1'] = _E2NODECOMPONENTINTERFACEW1
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceS1'] = _E2NODECOMPONENTINTERFACES1
+DESCRIPTOR.message_types_by_name['E2nodeComponentInterfaceX2'] = _E2NODECOMPONENTINTERFACEX2
+DESCRIPTOR.message_types_by_name['GlobalENBID'] = _GLOBALENBID
+DESCRIPTOR.message_types_by_name['GlobalENGNBID'] = _GLOBALENGNBID
+DESCRIPTOR.message_types_by_name['GlobalGNBID'] = _GLOBALGNBID
+DESCRIPTOR.message_types_by_name['GlobalNGENBID'] = _GLOBALNGENBID
+DESCRIPTOR.enum_types_by_name['E2nodeComponentInterfaceType'] = _E2NODECOMPONENTINTERFACETYPE
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+E2nodeComponentConfig = _reflection.GeneratedProtocolMessageType('E2nodeComponentConfig', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTCONFIG,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentConfig)
+  })
+_sym_db.RegisterMessage(E2nodeComponentConfig)
+
+E2nodeComponentInterfaceNG = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceNG', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACENG,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceNG)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceNG)
+
+E2nodeComponentInterfaceXn = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceXn', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACEXN,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceXn)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceXn)
+
+E2nodeComponentInterfaceE1 = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceE1', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACEE1,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceE1)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceE1)
+
+E2nodeComponentInterfaceF1 = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceF1', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACEF1,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceF1)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceF1)
+
+E2nodeComponentInterfaceW1 = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceW1', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACEW1,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceW1)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceW1)
+
+E2nodeComponentInterfaceS1 = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceS1', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACES1,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceS1)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceS1)
+
+E2nodeComponentInterfaceX2 = _reflection.GeneratedProtocolMessageType('E2nodeComponentInterfaceX2', (_message.Message,), {
+  'DESCRIPTOR' : _E2NODECOMPONENTINTERFACEX2,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.E2nodeComponentInterfaceX2)
+  })
+_sym_db.RegisterMessage(E2nodeComponentInterfaceX2)
+
+GlobalENBID = _reflection.GeneratedProtocolMessageType('GlobalENBID', (_message.Message,), {
+  'DESCRIPTOR' : _GLOBALENBID,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.GlobalENBID)
+  })
+_sym_db.RegisterMessage(GlobalENBID)
+
+GlobalENGNBID = _reflection.GeneratedProtocolMessageType('GlobalENGNBID', (_message.Message,), {
+  'DESCRIPTOR' : _GLOBALENGNBID,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.GlobalENGNBID)
+  })
+_sym_db.RegisterMessage(GlobalENGNBID)
+
+GlobalGNBID = _reflection.GeneratedProtocolMessageType('GlobalGNBID', (_message.Message,), {
+  'DESCRIPTOR' : _GLOBALGNBID,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.GlobalGNBID)
+  })
+_sym_db.RegisterMessage(GlobalGNBID)
+
+GlobalNGENBID = _reflection.GeneratedProtocolMessageType('GlobalNGENBID', (_message.Message,), {
+  'DESCRIPTOR' : _GLOBALNGENBID,
+  '__module__' : 'e2node_component_config_pb2'
+  # @@protoc_insertion_point(class_scope:entities.GlobalNGENBID)
+  })
+_sym_db.RegisterMessage(GlobalNGENBID)
+
+
+# @@protoc_insertion_point(module_scope)
index 7df3324..1fb4b4e 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: enb.proto
 
@@ -14,6 +15,8 @@ _sym_db = _symbol_database.Default()
 
 
 from . import additional_cell_information_pb2 as additional__cell__information__pb2
+from . import e2node_component_config_pb2 as e2node__component__config__pb2
+from . import nb_types_pb2 as nb__types__pb2
 
 
 DESCRIPTOR = _descriptor.FileDescriptor(
@@ -21,9 +24,9 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   package='entities',
   syntax='proto3',
   serialized_options=None,
-  serialized_pb=_b('\n\tenb.proto\x12\x08\x65ntities\x1a!additional_cell_information.proto\"p\n\x03\x45nb\x12#\n\x08\x65nb_type\x18\x01 \x01(\x0e\x32\x11.entities.EnbType\x12.\n\x0cserved_cells\x18\x02 \x03(\x0b\x32\x18.entities.ServedCellInfo\x12\x14\n\x0cgu_group_ids\x18\x03 \x03(\t\"\xc0\x05\n\x0eServedCellInfo\x12\x0b\n\x03pci\x18\x01 \x01(\r\x12\x0f\n\x07\x63\x65ll_id\x18\x02 \x01(\t\x12\x0b\n\x03tac\x18\x03 \x01(\t\x12\x17\n\x0f\x62roadcast_plmns\x18\x04 \x03(\t\x12\x34\n\x11\x63hoice_eutra_mode\x18\x05 \x01(\x0b\x32\x19.entities.ChoiceEUTRAMode\x12(\n\neutra_mode\x18\x06 \x01(\x0e\x32\x14.entities.Eutra.Mode\x12?\n\x17number_of_antenna_ports\x18\x07 \x01(\x0e\x32\x1e.entities.NumberOfAntennaPorts\x12\x39\n\x13prach_configuration\x18\x08 \x01(\x0b\x32\x1c.entities.PrachConfiguration\x12\x35\n\x14mbsfn_subframe_infos\x18\t \x03(\x0b\x32\x17.entities.MbsfnSubframe\x12\x0e\n\x06\x63sg_id\x18\n \x01(\t\x12$\n\x1cmbms_service_area_identities\x18\x0b \x03(\t\x12\x17\n\x0fmultiband_infos\x18\x0c \x03(\r\x12I\n\x1c\x66req_band_indicator_priority\x18\r \x01(\x0e\x32#.entities.FreqBandIndicatorPriority\x12:\n\x14\x62\x61ndwidth_reduced_si\x18\x0e \x01(\x0e\x32\x1c.entities.BandwidthReducedSI\x12\x37\n\x0fneighbour_infos\x18\x0f \x03(\x0b\x32\x1e.entities.NeighbourInformation\x12H\n\x1b\x61\x64\x64itional_cell_information\x18\x10 \x01(\x0b\x32#.entities.AdditionalCellInformation\"Q\n\x0f\x43hoiceEUTRAMode\x12\x1e\n\x03\x66\x64\x64\x18\x01 \x01(\x0b\x32\x11.entities.FddInfo\x12\x1e\n\x03tdd\x18\x02 \x01(\x0b\x32\x11.entities.TddInfo\".\n\x05\x45utra\"%\n\x04Mode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x46\x44\x44\x10\x01\x12\x07\n\x03TDD\x10\x02\"O\n\x14NeighbourInformation\x12\x0c\n\x04\x65\x63gi\x18\x01 \x01(\t\x12\x0b\n\x03pci\x18\x02 \x01(\r\x12\x0f\n\x07\x65\x61r_fcn\x18\x03 \x01(\r\x12\x0b\n\x03tac\x18\x04 \x01(\t\"\xe2\x01\n\rMbsfnSubframe\x12J\n\x1cradioframe_allocation_period\x18\x01 \x01(\x0e\x32$.entities.RadioframeAllocationPeriod\x12$\n\x1cradioframe_allocation_offset\x18\x02 \x01(\r\x12\x1b\n\x13subframe_allocation\x18\x03 \x01(\t\x12\x42\n\x18subframe_allocation_type\x18\x04 \x01(\x0e\x32 .entities.SubframeAllocationType\"\xba\x01\n\x12PrachConfiguration\x12\x1b\n\x13root_sequence_index\x18\x01 \x01(\r\x12+\n#zero_correlation_zone_configuration\x18\x02 \x01(\r\x12\x17\n\x0fhigh_speed_flag\x18\x03 \x01(\x08\x12\x1e\n\x16prach_frequency_offset\x18\x04 \x01(\r\x12!\n\x19prach_configuration_index\x18\x05 \x01(\r\"\x8d\x03\n\x07TddInfo\x12\x0f\n\x07\x65\x61r_fcn\x18\x01 \x01(\r\x12?\n\x16transmission_bandwidth\x18\x02 \x01(\x0e\x32\x1f.entities.TransmissionBandwidth\x12\x39\n\x13subframe_assignment\x18\x03 \x01(\x0e\x32\x1c.entities.SubframeAssignment\x12<\n\x15special_subframe_info\x18\x04 \x01(\x0b\x32\x1d.entities.SpecialSubframeInfo\x12Q\n additional_special_subframe_info\x18\x05 \x01(\x0b\x32\'.entities.AdditionalSpecialSubframeInfo\x12\x64\n*additional_special_subframe_extension_info\x18\x06 \x01(\x0b\x32\x30.entities.AdditionalSpecialSubframeExtensionInfo\"\xfb\x01\n&AdditionalSpecialSubframeExtensionInfo\x12m\n.additional_special_subframe_patterns_extension\x18\x01 \x01(\x0e\x32\x35.entities.AdditionalSpecialSubframePatterns.Extension\x12\x30\n\x10\x63yclic_prefix_dl\x18\x02 \x01(\x0e\x32\x16.entities.CyclicPrefix\x12\x30\n\x10\x63yclic_prefix_ul\x18\x03 \x01(\x0e\x32\x16.entities.CyclicPrefix\"\xdf\x01\n\x1d\x41\x64\x64itionalSpecialSubframeInfo\x12Z\n$additional_special_subframe_patterns\x18\x01 \x01(\x0e\x32,.entities.AdditionalSpecialSubframe.Patterns\x12\x30\n\x10\x63yclic_prefix_dl\x18\x02 \x01(\x0e\x32\x16.entities.CyclicPrefix\x12\x30\n\x10\x63yclic_prefix_ul\x18\x03 \x01(\x0e\x32\x16.entities.CyclicPrefix\"\xb7\x01\n\x07\x46\x64\x64Info\x12\x11\n\tulear_fcn\x18\x01 \x01(\r\x12\x11\n\tdlear_fcn\x18\x02 \x01(\r\x12\x42\n\x19ul_transmission_bandwidth\x18\x03 \x01(\x0e\x32\x1f.entities.TransmissionBandwidth\x12\x42\n\x19\x64l_transmission_bandwidth\x18\x04 \x01(\x0e\x32\x1f.entities.TransmissionBandwidth\"\xc0\x01\n\x13SpecialSubframeInfo\x12\x45\n\x19special_subframe_patterns\x18\x01 \x01(\x0e\x32\".entities.SpecialSubframe.Patterns\x12\x30\n\x10\x63yclic_prefix_dl\x18\x02 \x01(\x0e\x32\x16.entities.CyclicPrefix\x12\x30\n\x10\x63yclic_prefix_ul\x18\x03 \x01(\x0e\x32\x16.entities.CyclicPrefix\"\x84\x01\n\x0fSpecialSubframe\"q\n\x08Patterns\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04SSP0\x10\x01\x12\x08\n\x04SSP1\x10\x02\x12\x08\n\x04SSP2\x10\x03\x12\x08\n\x04SSP3\x10\x04\x12\x08\n\x04SSP4\x10\x05\x12\x08\n\x04SSP5\x10\x06\x12\x08\n\x04SSP6\x10\x07\x12\x08\n\x04SSP7\x10\x08\x12\x08\n\x04SSP8\x10\t\"\x98\x01\n\x19\x41\x64\x64itionalSpecialSubframe\"{\n\x08Patterns\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04SSP0\x10\x01\x12\x08\n\x04SSP1\x10\x02\x12\x08\n\x04SSP2\x10\x03\x12\x08\n\x04SSP3\x10\x04\x12\x08\n\x04SSP4\x10\x05\x12\x08\n\x04SSP5\x10\x06\x12\x08\n\x04SSP6\x10\x07\x12\x08\n\x04SSP7\x10\x08\x12\x08\n\x04SSP8\x10\t\x12\x08\n\x04SSP9\x10\n\"H\n!AdditionalSpecialSubframePatterns\"#\n\tExtension\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05SSP10\x10\x01*k\n\x19\x46reqBandIndicatorPriority\x12(\n$UNKNOWN_FREQ_BAND_INDICATOR_PRIORITY\x10\x00\x12\x13\n\x0fNOT_BROADCASTED\x10\x01\x12\x0f\n\x0b\x42ROADCASTED\x10\x02*E\n\x12\x42\x61ndwidthReducedSI\x12 \n\x1cUNKNOWN_BANDWIDTH_REDUCED_SI\x10\x00\x12\r\n\tSCHEDULED\x10\x01*]\n\x16SubframeAllocationType\x12$\n UNKNOWN_SUBFRAME_ALLOCATION_TYPE\x10\x00\x12\r\n\tONE_FRAME\x10\x01\x12\x0e\n\nFOUR_FRAME\x10\x02*x\n\x1aRadioframeAllocationPeriod\x12(\n$UNKNOWN_RADIOFRAME_ALLOCATION_PERIOD\x10\x00\x12\x06\n\x02N1\x10\x01\x12\x06\n\x02N2\x10\x02\x12\x06\n\x02N4\x10\x03\x12\x06\n\x02N8\x10\x04\x12\x07\n\x03N16\x10\x05\x12\x07\n\x03N32\x10\x06*V\n\x14NumberOfAntennaPorts\x12#\n\x1fUNKNOWN_NUMBER_OF_ANTENNA_PORTS\x10\x00\x12\x07\n\x03\x41N1\x10\x01\x12\x07\n\x03\x41N2\x10\x02\x12\x07\n\x03\x41N4\x10\x03*\xa6\x01\n\x07\x45nbType\x12\x14\n\x10UNKNOWN_ENB_TYPE\x10\x00\x12\r\n\tMACRO_ENB\x10\x01\x12\x0c\n\x08HOME_ENB\x10\x02\x12\x13\n\x0fSHORT_MACRO_ENB\x10\x03\x12\x12\n\x0eLONG_MACRO_ENB\x10\x04\x12\x10\n\x0cMACRO_NG_ENB\x10\x05\x12\x16\n\x12SHORT_MACRO_NG_ENB\x10\x06\x12\x15\n\x11LONG_MACRO_NG_ENB\x10\x07*t\n\x12SubframeAssignment\x12\x1f\n\x1bUNKNOWN_SUBFRAME_ASSIGNMENT\x10\x00\x12\x07\n\x03SA0\x10\x01\x12\x07\n\x03SA1\x10\x02\x12\x07\n\x03SA2\x10\x03\x12\x07\n\x03SA3\x10\x04\x12\x07\n\x03SA4\x10\x05\x12\x07\n\x03SA5\x10\x06\x12\x07\n\x03SA6\x10\x07*C\n\x0c\x43yclicPrefix\x12\x19\n\x15UNKNOWN_CYCLIC_PREFIX\x10\x00\x12\n\n\x06NORMAL\x10\x01\x12\x0c\n\x08\x45XTENDED\x10\x02*\x80\x01\n\x15TransmissionBandwidth\x12\"\n\x1eUNKNOWN_TRANSMISSION_BANDWIDTH\x10\x00\x12\x07\n\x03\x42W6\x10\x01\x12\x08\n\x04\x42W15\x10\x02\x12\x08\n\x04\x42W25\x10\x03\x12\x08\n\x04\x42W50\x10\x04\x12\x08\n\x04\x42W75\x10\x05\x12\t\n\x05\x42W100\x10\x06\x12\x07\n\x03\x42W1\x10\x07\x62\x06proto3')
+  serialized_pb=_b('\n\tenb.proto\x12\x08\x65ntities\x1a!additional_cell_information.proto\x1a\x1d\x65\x32node_component_config.proto\x1a\x0enb_types.proto\"\xa7\x01\n\x03\x45nb\x12#\n\x08\x65nb_type\x18\x01 \x01(\x0e\x32\x11.entities.EnbType\x12.\n\x0cserved_cells\x18\x02 \x03(\x0b\x32\x18.entities.ServedCellInfo\x12\x14\n\x0cgu_group_ids\x18\x03 \x03(\t\x12\x35\n\x0cnode_configs\x18\x04 \x03(\x0b\x32\x1f.entities.E2nodeComponentConfig\"\xc0\x05\n\x0eServedCellInfo\x12\x0b\n\x03pci\x18\x01 \x01(\r\x12\x0f\n\x07\x63\x65ll_id\x18\x02 \x01(\t\x12\x0b\n\x03tac\x18\x03 \x01(\t\x12\x17\n\x0f\x62roadcast_plmns\x18\x04 \x03(\t\x12\x34\n\x11\x63hoice_eutra_mode\x18\x05 \x01(\x0b\x32\x19.entities.ChoiceEUTRAMode\x12(\n\neutra_mode\x18\x06 \x01(\x0e\x32\x14.entities.Eutra.Mode\x12?\n\x17number_of_antenna_ports\x18\x07 \x01(\x0e\x32\x1e.entities.NumberOfAntennaPorts\x12\x39\n\x13prach_configuration\x18\x08 \x01(\x0b\x32\x1c.entities.PrachConfiguration\x12\x35\n\x14mbsfn_subframe_infos\x18\t \x03(\x0b\x32\x17.entities.MbsfnSubframe\x12\x0e\n\x06\x63sg_id\x18\n \x01(\t\x12$\n\x1cmbms_service_area_identities\x18\x0b \x03(\t\x12\x17\n\x0fmultiband_infos\x18\x0c \x03(\r\x12I\n\x1c\x66req_band_indicator_priority\x18\r \x01(\x0e\x32#.entities.FreqBandIndicatorPriority\x12:\n\x14\x62\x61ndwidth_reduced_si\x18\x0e \x01(\x0e\x32\x1c.entities.BandwidthReducedSI\x12\x37\n\x0fneighbour_infos\x18\x0f \x03(\x0b\x32\x1e.entities.NeighbourInformation\x12H\n\x1b\x61\x64\x64itional_cell_information\x18\x10 \x01(\x0b\x32#.entities.AdditionalCellInformation\"Q\n\x0f\x43hoiceEUTRAMode\x12\x1e\n\x03\x66\x64\x64\x18\x01 \x01(\x0b\x32\x11.entities.FddInfo\x12\x1e\n\x03tdd\x18\x02 \x01(\x0b\x32\x11.entities.TddInfo\".\n\x05\x45utra\"%\n\x04Mode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x46\x44\x44\x10\x01\x12\x07\n\x03TDD\x10\x02\"O\n\x14NeighbourInformation\x12\x0c\n\x04\x65\x63gi\x18\x01 \x01(\t\x12\x0b\n\x03pci\x18\x02 \x01(\r\x12\x0f\n\x07\x65\x61r_fcn\x18\x03 \x01(\r\x12\x0b\n\x03tac\x18\x04 \x01(\t\"\xe2\x01\n\rMbsfnSubframe\x12J\n\x1cradioframe_allocation_period\x18\x01 \x01(\x0e\x32$.entities.RadioframeAllocationPeriod\x12$\n\x1cradioframe_allocation_offset\x18\x02 \x01(\r\x12\x1b\n\x13subframe_allocation\x18\x03 \x01(\t\x12\x42\n\x18subframe_allocation_type\x18\x04 \x01(\x0e\x32 .entities.SubframeAllocationType\"\xba\x01\n\x12PrachConfiguration\x12\x1b\n\x13root_sequence_index\x18\x01 \x01(\r\x12+\n#zero_correlation_zone_configuration\x18\x02 \x01(\r\x12\x17\n\x0fhigh_speed_flag\x18\x03 \x01(\x08\x12\x1e\n\x16prach_frequency_offset\x18\x04 \x01(\r\x12!\n\x19prach_configuration_index\x18\x05 \x01(\r\"\x8d\x03\n\x07TddInfo\x12\x0f\n\x07\x65\x61r_fcn\x18\x01 \x01(\r\x12?\n\x16transmission_bandwidth\x18\x02 \x01(\x0e\x32\x1f.entities.TransmissionBandwidth\x12\x39\n\x13subframe_assignment\x18\x03 \x01(\x0e\x32\x1c.entities.SubframeAssignment\x12<\n\x15special_subframe_info\x18\x04 \x01(\x0b\x32\x1d.entities.SpecialSubframeInfo\x12Q\n additional_special_subframe_info\x18\x05 \x01(\x0b\x32\'.entities.AdditionalSpecialSubframeInfo\x12\x64\n*additional_special_subframe_extension_info\x18\x06 \x01(\x0b\x32\x30.entities.AdditionalSpecialSubframeExtensionInfo\"\xfb\x01\n&AdditionalSpecialSubframeExtensionInfo\x12m\n.additional_special_subframe_patterns_extension\x18\x01 \x01(\x0e\x32\x35.entities.AdditionalSpecialSubframePatterns.Extension\x12\x30\n\x10\x63yclic_prefix_dl\x18\x02 \x01(\x0e\x32\x16.entities.CyclicPrefix\x12\x30\n\x10\x63yclic_prefix_ul\x18\x03 \x01(\x0e\x32\x16.entities.CyclicPrefix\"\xdf\x01\n\x1d\x41\x64\x64itionalSpecialSubframeInfo\x12Z\n$additional_special_subframe_patterns\x18\x01 \x01(\x0e\x32,.entities.AdditionalSpecialSubframe.Patterns\x12\x30\n\x10\x63yclic_prefix_dl\x18\x02 \x01(\x0e\x32\x16.entities.CyclicPrefix\x12\x30\n\x10\x63yclic_prefix_ul\x18\x03 \x01(\x0e\x32\x16.entities.CyclicPrefix\"\xb7\x01\n\x07\x46\x64\x64Info\x12\x11\n\tulear_fcn\x18\x01 \x01(\r\x12\x11\n\tdlear_fcn\x18\x02 \x01(\r\x12\x42\n\x19ul_transmission_bandwidth\x18\x03 \x01(\x0e\x32\x1f.entities.TransmissionBandwidth\x12\x42\n\x19\x64l_transmission_bandwidth\x18\x04 \x01(\x0e\x32\x1f.entities.TransmissionBandwidth\"\xc0\x01\n\x13SpecialSubframeInfo\x12\x45\n\x19special_subframe_patterns\x18\x01 \x01(\x0e\x32\".entities.SpecialSubframe.Patterns\x12\x30\n\x10\x63yclic_prefix_dl\x18\x02 \x01(\x0e\x32\x16.entities.CyclicPrefix\x12\x30\n\x10\x63yclic_prefix_ul\x18\x03 \x01(\x0e\x32\x16.entities.CyclicPrefix\"\x84\x01\n\x0fSpecialSubframe\"q\n\x08Patterns\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04SSP0\x10\x01\x12\x08\n\x04SSP1\x10\x02\x12\x08\n\x04SSP2\x10\x03\x12\x08\n\x04SSP3\x10\x04\x12\x08\n\x04SSP4\x10\x05\x12\x08\n\x04SSP5\x10\x06\x12\x08\n\x04SSP6\x10\x07\x12\x08\n\x04SSP7\x10\x08\x12\x08\n\x04SSP8\x10\t\"\x98\x01\n\x19\x41\x64\x64itionalSpecialSubframe\"{\n\x08Patterns\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04SSP0\x10\x01\x12\x08\n\x04SSP1\x10\x02\x12\x08\n\x04SSP2\x10\x03\x12\x08\n\x04SSP3\x10\x04\x12\x08\n\x04SSP4\x10\x05\x12\x08\n\x04SSP5\x10\x06\x12\x08\n\x04SSP6\x10\x07\x12\x08\n\x04SSP7\x10\x08\x12\x08\n\x04SSP8\x10\t\x12\x08\n\x04SSP9\x10\n\"H\n!AdditionalSpecialSubframePatterns\"#\n\tExtension\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05SSP10\x10\x01*k\n\x19\x46reqBandIndicatorPriority\x12(\n$UNKNOWN_FREQ_BAND_INDICATOR_PRIORITY\x10\x00\x12\x13\n\x0fNOT_BROADCASTED\x10\x01\x12\x0f\n\x0b\x42ROADCASTED\x10\x02*E\n\x12\x42\x61ndwidthReducedSI\x12 \n\x1cUNKNOWN_BANDWIDTH_REDUCED_SI\x10\x00\x12\r\n\tSCHEDULED\x10\x01*]\n\x16SubframeAllocationType\x12$\n UNKNOWN_SUBFRAME_ALLOCATION_TYPE\x10\x00\x12\r\n\tONE_FRAME\x10\x01\x12\x0e\n\nFOUR_FRAME\x10\x02*x\n\x1aRadioframeAllocationPeriod\x12(\n$UNKNOWN_RADIOFRAME_ALLOCATION_PERIOD\x10\x00\x12\x06\n\x02N1\x10\x01\x12\x06\n\x02N2\x10\x02\x12\x06\n\x02N4\x10\x03\x12\x06\n\x02N8\x10\x04\x12\x07\n\x03N16\x10\x05\x12\x07\n\x03N32\x10\x06*V\n\x14NumberOfAntennaPorts\x12#\n\x1fUNKNOWN_NUMBER_OF_ANTENNA_PORTS\x10\x00\x12\x07\n\x03\x41N1\x10\x01\x12\x07\n\x03\x41N2\x10\x02\x12\x07\n\x03\x41N4\x10\x03*t\n\x12SubframeAssignment\x12\x1f\n\x1bUNKNOWN_SUBFRAME_ASSIGNMENT\x10\x00\x12\x07\n\x03SA0\x10\x01\x12\x07\n\x03SA1\x10\x02\x12\x07\n\x03SA2\x10\x03\x12\x07\n\x03SA3\x10\x04\x12\x07\n\x03SA4\x10\x05\x12\x07\n\x03SA5\x10\x06\x12\x07\n\x03SA6\x10\x07*C\n\x0c\x43yclicPrefix\x12\x19\n\x15UNKNOWN_CYCLIC_PREFIX\x10\x00\x12\n\n\x06NORMAL\x10\x01\x12\x0c\n\x08\x45XTENDED\x10\x02*\x80\x01\n\x15TransmissionBandwidth\x12\"\n\x1eUNKNOWN_TRANSMISSION_BANDWIDTH\x10\x00\x12\x07\n\x03\x42W6\x10\x01\x12\x08\n\x04\x42W15\x10\x02\x12\x08\n\x04\x42W25\x10\x03\x12\x08\n\x04\x42W50\x10\x04\x12\x08\n\x04\x42W75\x10\x05\x12\t\n\x05\x42W100\x10\x06\x12\x07\n\x03\x42W1\x10\x07\x62\x06proto3')
   ,
-  dependencies=[additional__cell__information__pb2.DESCRIPTOR,])
+  dependencies=[additional__cell__information__pb2.DESCRIPTOR,e2node__component__config__pb2.DESCRIPTOR,nb__types__pb2.DESCRIPTOR,])
 
 _FREQBANDINDICATORPRIORITY = _descriptor.EnumDescriptor(
   name='FreqBandIndicatorPriority',
@@ -46,8 +49,8 @@ _FREQBANDINDICATORPRIORITY = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3134,
-  serialized_end=3241,
+  serialized_start=3237,
+  serialized_end=3344,
 )
 _sym_db.RegisterEnumDescriptor(_FREQBANDINDICATORPRIORITY)
 
@@ -69,8 +72,8 @@ _BANDWIDTHREDUCEDSI = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3243,
-  serialized_end=3312,
+  serialized_start=3346,
+  serialized_end=3415,
 )
 _sym_db.RegisterEnumDescriptor(_BANDWIDTHREDUCEDSI)
 
@@ -96,8 +99,8 @@ _SUBFRAMEALLOCATIONTYPE = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3314,
-  serialized_end=3407,
+  serialized_start=3417,
+  serialized_end=3510,
 )
 _sym_db.RegisterEnumDescriptor(_SUBFRAMEALLOCATIONTYPE)
 
@@ -139,8 +142,8 @@ _RADIOFRAMEALLOCATIONPERIOD = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3409,
-  serialized_end=3529,
+  serialized_start=3512,
+  serialized_end=3632,
 )
 _sym_db.RegisterEnumDescriptor(_RADIOFRAMEALLOCATIONPERIOD)
 
@@ -170,59 +173,12 @@ _NUMBEROFANTENNAPORTS = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3531,
-  serialized_end=3617,
+  serialized_start=3634,
+  serialized_end=3720,
 )
 _sym_db.RegisterEnumDescriptor(_NUMBEROFANTENNAPORTS)
 
 NumberOfAntennaPorts = enum_type_wrapper.EnumTypeWrapper(_NUMBEROFANTENNAPORTS)
-_ENBTYPE = _descriptor.EnumDescriptor(
-  name='EnbType',
-  full_name='entities.EnbType',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNKNOWN_ENB_TYPE', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MACRO_ENB', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='HOME_ENB', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='SHORT_MACRO_ENB', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LONG_MACRO_ENB', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MACRO_NG_ENB', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='SHORT_MACRO_NG_ENB', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LONG_MACRO_NG_ENB', index=7, number=7,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3620,
-  serialized_end=3786,
-)
-_sym_db.RegisterEnumDescriptor(_ENBTYPE)
-
-EnbType = enum_type_wrapper.EnumTypeWrapper(_ENBTYPE)
 _SUBFRAMEASSIGNMENT = _descriptor.EnumDescriptor(
   name='SubframeAssignment',
   full_name='entities.SubframeAssignment',
@@ -264,8 +220,8 @@ _SUBFRAMEASSIGNMENT = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3788,
-  serialized_end=3904,
+  serialized_start=3722,
+  serialized_end=3838,
 )
 _sym_db.RegisterEnumDescriptor(_SUBFRAMEASSIGNMENT)
 
@@ -291,8 +247,8 @@ _CYCLICPREFIX = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3906,
-  serialized_end=3973,
+  serialized_start=3840,
+  serialized_end=3907,
 )
 _sym_db.RegisterEnumDescriptor(_CYCLICPREFIX)
 
@@ -338,8 +294,8 @@ _TRANSMISSIONBANDWIDTH = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3976,
-  serialized_end=4104,
+  serialized_start=3910,
+  serialized_end=4038,
 )
 _sym_db.RegisterEnumDescriptor(_TRANSMISSIONBANDWIDTH)
 
@@ -363,14 +319,6 @@ UNKNOWN_NUMBER_OF_ANTENNA_PORTS = 0
 AN1 = 1
 AN2 = 2
 AN4 = 3
-UNKNOWN_ENB_TYPE = 0
-MACRO_ENB = 1
-HOME_ENB = 2
-SHORT_MACRO_ENB = 3
-LONG_MACRO_ENB = 4
-MACRO_NG_ENB = 5
-SHORT_MACRO_NG_ENB = 6
-LONG_MACRO_NG_ENB = 7
 UNKNOWN_SUBFRAME_ASSIGNMENT = 0
 SA0 = 1
 SA1 = 2
@@ -413,8 +361,8 @@ _EUTRA_MODE = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=971,
-  serialized_end=1008,
+  serialized_start=1074,
+  serialized_end=1111,
 )
 _sym_db.RegisterEnumDescriptor(_EUTRA_MODE)
 
@@ -467,8 +415,8 @@ _SPECIALSUBFRAME_PATTERNS = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=2790,
-  serialized_end=2903,
+  serialized_start=2893,
+  serialized_end=3006,
 )
 _sym_db.RegisterEnumDescriptor(_SPECIALSUBFRAME_PATTERNS)
 
@@ -525,8 +473,8 @@ _ADDITIONALSPECIALSUBFRAME_PATTERNS = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=2935,
-  serialized_end=3058,
+  serialized_start=3038,
+  serialized_end=3161,
 )
 _sym_db.RegisterEnumDescriptor(_ADDITIONALSPECIALSUBFRAME_PATTERNS)
 
@@ -547,8 +495,8 @@ _ADDITIONALSPECIALSUBFRAMEPATTERNS_EXTENSION = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=3097,
-  serialized_end=3132,
+  serialized_start=3200,
+  serialized_end=3235,
 )
 _sym_db.RegisterEnumDescriptor(_ADDITIONALSPECIALSUBFRAMEPATTERNS_EXTENSION)
 
@@ -581,6 +529,13 @@ _ENB = _descriptor.Descriptor(
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='node_configs', full_name='entities.Enb.node_configs', index=3,
+      number=4, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
   ],
   extensions=[
   ],
@@ -593,8 +548,8 @@ _ENB = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=58,
-  serialized_end=170,
+  serialized_start=106,
+  serialized_end=273,
 )
 
 
@@ -729,8 +684,8 @@ _SERVEDCELLINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=173,
-  serialized_end=877,
+  serialized_start=276,
+  serialized_end=980,
 )
 
 
@@ -767,8 +722,8 @@ _CHOICEEUTRAMODE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=879,
-  serialized_end=960,
+  serialized_start=982,
+  serialized_end=1063,
 )
 
 
@@ -792,8 +747,8 @@ _EUTRA = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=962,
-  serialized_end=1008,
+  serialized_start=1065,
+  serialized_end=1111,
 )
 
 
@@ -844,8 +799,8 @@ _NEIGHBOURINFORMATION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1010,
-  serialized_end=1089,
+  serialized_start=1113,
+  serialized_end=1192,
 )
 
 
@@ -896,8 +851,8 @@ _MBSFNSUBFRAME = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1092,
-  serialized_end=1318,
+  serialized_start=1195,
+  serialized_end=1421,
 )
 
 
@@ -955,8 +910,8 @@ _PRACHCONFIGURATION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1321,
-  serialized_end=1507,
+  serialized_start=1424,
+  serialized_end=1610,
 )
 
 
@@ -1021,8 +976,8 @@ _TDDINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1510,
-  serialized_end=1907,
+  serialized_start=1613,
+  serialized_end=2010,
 )
 
 
@@ -1066,8 +1021,8 @@ _ADDITIONALSPECIALSUBFRAMEEXTENSIONINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1910,
-  serialized_end=2161,
+  serialized_start=2013,
+  serialized_end=2264,
 )
 
 
@@ -1111,8 +1066,8 @@ _ADDITIONALSPECIALSUBFRAMEINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2164,
-  serialized_end=2387,
+  serialized_start=2267,
+  serialized_end=2490,
 )
 
 
@@ -1163,8 +1118,8 @@ _FDDINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2390,
-  serialized_end=2573,
+  serialized_start=2493,
+  serialized_end=2676,
 )
 
 
@@ -1208,8 +1163,8 @@ _SPECIALSUBFRAMEINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2576,
-  serialized_end=2768,
+  serialized_start=2679,
+  serialized_end=2871,
 )
 
 
@@ -1233,8 +1188,8 @@ _SPECIALSUBFRAME = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2771,
-  serialized_end=2903,
+  serialized_start=2874,
+  serialized_end=3006,
 )
 
 
@@ -1258,8 +1213,8 @@ _ADDITIONALSPECIALSUBFRAME = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2906,
-  serialized_end=3058,
+  serialized_start=3009,
+  serialized_end=3161,
 )
 
 
@@ -1283,12 +1238,13 @@ _ADDITIONALSPECIALSUBFRAMEPATTERNS = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=3060,
-  serialized_end=3132,
+  serialized_start=3163,
+  serialized_end=3235,
 )
 
-_ENB.fields_by_name['enb_type'].enum_type = _ENBTYPE
+_ENB.fields_by_name['enb_type'].enum_type = nb__types__pb2._ENBTYPE
 _ENB.fields_by_name['served_cells'].message_type = _SERVEDCELLINFO
+_ENB.fields_by_name['node_configs'].message_type = e2node__component__config__pb2._E2NODECOMPONENTCONFIG
 _SERVEDCELLINFO.fields_by_name['choice_eutra_mode'].message_type = _CHOICEEUTRAMODE
 _SERVEDCELLINFO.fields_by_name['eutra_mode'].enum_type = _EUTRA_MODE
 _SERVEDCELLINFO.fields_by_name['number_of_antenna_ports'].enum_type = _NUMBEROFANTENNAPORTS
@@ -1342,115 +1298,114 @@ DESCRIPTOR.enum_types_by_name['BandwidthReducedSI'] = _BANDWIDTHREDUCEDSI
 DESCRIPTOR.enum_types_by_name['SubframeAllocationType'] = _SUBFRAMEALLOCATIONTYPE
 DESCRIPTOR.enum_types_by_name['RadioframeAllocationPeriod'] = _RADIOFRAMEALLOCATIONPERIOD
 DESCRIPTOR.enum_types_by_name['NumberOfAntennaPorts'] = _NUMBEROFANTENNAPORTS
-DESCRIPTOR.enum_types_by_name['EnbType'] = _ENBTYPE
 DESCRIPTOR.enum_types_by_name['SubframeAssignment'] = _SUBFRAMEASSIGNMENT
 DESCRIPTOR.enum_types_by_name['CyclicPrefix'] = _CYCLICPREFIX
 DESCRIPTOR.enum_types_by_name['TransmissionBandwidth'] = _TRANSMISSIONBANDWIDTH
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-Enb = _reflection.GeneratedProtocolMessageType('Enb', (_message.Message,), dict(
-  DESCRIPTOR = _ENB,
-  __module__ = 'enb_pb2'
+Enb = _reflection.GeneratedProtocolMessageType('Enb', (_message.Message,), {
+  'DESCRIPTOR' : _ENB,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.Enb)
-  ))
+  })
 _sym_db.RegisterMessage(Enb)
 
-ServedCellInfo = _reflection.GeneratedProtocolMessageType('ServedCellInfo', (_message.Message,), dict(
-  DESCRIPTOR = _SERVEDCELLINFO,
-  __module__ = 'enb_pb2'
+ServedCellInfo = _reflection.GeneratedProtocolMessageType('ServedCellInfo', (_message.Message,), {
+  'DESCRIPTOR' : _SERVEDCELLINFO,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.ServedCellInfo)
-  ))
+  })
 _sym_db.RegisterMessage(ServedCellInfo)
 
-ChoiceEUTRAMode = _reflection.GeneratedProtocolMessageType('ChoiceEUTRAMode', (_message.Message,), dict(
-  DESCRIPTOR = _CHOICEEUTRAMODE,
-  __module__ = 'enb_pb2'
+ChoiceEUTRAMode = _reflection.GeneratedProtocolMessageType('ChoiceEUTRAMode', (_message.Message,), {
+  'DESCRIPTOR' : _CHOICEEUTRAMODE,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.ChoiceEUTRAMode)
-  ))
+  })
 _sym_db.RegisterMessage(ChoiceEUTRAMode)
 
-Eutra = _reflection.GeneratedProtocolMessageType('Eutra', (_message.Message,), dict(
-  DESCRIPTOR = _EUTRA,
-  __module__ = 'enb_pb2'
+Eutra = _reflection.GeneratedProtocolMessageType('Eutra', (_message.Message,), {
+  'DESCRIPTOR' : _EUTRA,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.Eutra)
-  ))
+  })
 _sym_db.RegisterMessage(Eutra)
 
-NeighbourInformation = _reflection.GeneratedProtocolMessageType('NeighbourInformation', (_message.Message,), dict(
-  DESCRIPTOR = _NEIGHBOURINFORMATION,
-  __module__ = 'enb_pb2'
+NeighbourInformation = _reflection.GeneratedProtocolMessageType('NeighbourInformation', (_message.Message,), {
+  'DESCRIPTOR' : _NEIGHBOURINFORMATION,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.NeighbourInformation)
-  ))
+  })
 _sym_db.RegisterMessage(NeighbourInformation)
 
-MbsfnSubframe = _reflection.GeneratedProtocolMessageType('MbsfnSubframe', (_message.Message,), dict(
-  DESCRIPTOR = _MBSFNSUBFRAME,
-  __module__ = 'enb_pb2'
+MbsfnSubframe = _reflection.GeneratedProtocolMessageType('MbsfnSubframe', (_message.Message,), {
+  'DESCRIPTOR' : _MBSFNSUBFRAME,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.MbsfnSubframe)
-  ))
+  })
 _sym_db.RegisterMessage(MbsfnSubframe)
 
-PrachConfiguration = _reflection.GeneratedProtocolMessageType('PrachConfiguration', (_message.Message,), dict(
-  DESCRIPTOR = _PRACHCONFIGURATION,
-  __module__ = 'enb_pb2'
+PrachConfiguration = _reflection.GeneratedProtocolMessageType('PrachConfiguration', (_message.Message,), {
+  'DESCRIPTOR' : _PRACHCONFIGURATION,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.PrachConfiguration)
-  ))
+  })
 _sym_db.RegisterMessage(PrachConfiguration)
 
-TddInfo = _reflection.GeneratedProtocolMessageType('TddInfo', (_message.Message,), dict(
-  DESCRIPTOR = _TDDINFO,
-  __module__ = 'enb_pb2'
+TddInfo = _reflection.GeneratedProtocolMessageType('TddInfo', (_message.Message,), {
+  'DESCRIPTOR' : _TDDINFO,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.TddInfo)
-  ))
+  })
 _sym_db.RegisterMessage(TddInfo)
 
-AdditionalSpecialSubframeExtensionInfo = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframeExtensionInfo', (_message.Message,), dict(
-  DESCRIPTOR = _ADDITIONALSPECIALSUBFRAMEEXTENSIONINFO,
-  __module__ = 'enb_pb2'
+AdditionalSpecialSubframeExtensionInfo = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframeExtensionInfo', (_message.Message,), {
+  'DESCRIPTOR' : _ADDITIONALSPECIALSUBFRAMEEXTENSIONINFO,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.AdditionalSpecialSubframeExtensionInfo)
-  ))
+  })
 _sym_db.RegisterMessage(AdditionalSpecialSubframeExtensionInfo)
 
-AdditionalSpecialSubframeInfo = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframeInfo', (_message.Message,), dict(
-  DESCRIPTOR = _ADDITIONALSPECIALSUBFRAMEINFO,
-  __module__ = 'enb_pb2'
+AdditionalSpecialSubframeInfo = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframeInfo', (_message.Message,), {
+  'DESCRIPTOR' : _ADDITIONALSPECIALSUBFRAMEINFO,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.AdditionalSpecialSubframeInfo)
-  ))
+  })
 _sym_db.RegisterMessage(AdditionalSpecialSubframeInfo)
 
-FddInfo = _reflection.GeneratedProtocolMessageType('FddInfo', (_message.Message,), dict(
-  DESCRIPTOR = _FDDINFO,
-  __module__ = 'enb_pb2'
+FddInfo = _reflection.GeneratedProtocolMessageType('FddInfo', (_message.Message,), {
+  'DESCRIPTOR' : _FDDINFO,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.FddInfo)
-  ))
+  })
 _sym_db.RegisterMessage(FddInfo)
 
-SpecialSubframeInfo = _reflection.GeneratedProtocolMessageType('SpecialSubframeInfo', (_message.Message,), dict(
-  DESCRIPTOR = _SPECIALSUBFRAMEINFO,
-  __module__ = 'enb_pb2'
+SpecialSubframeInfo = _reflection.GeneratedProtocolMessageType('SpecialSubframeInfo', (_message.Message,), {
+  'DESCRIPTOR' : _SPECIALSUBFRAMEINFO,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.SpecialSubframeInfo)
-  ))
+  })
 _sym_db.RegisterMessage(SpecialSubframeInfo)
 
-SpecialSubframe = _reflection.GeneratedProtocolMessageType('SpecialSubframe', (_message.Message,), dict(
-  DESCRIPTOR = _SPECIALSUBFRAME,
-  __module__ = 'enb_pb2'
+SpecialSubframe = _reflection.GeneratedProtocolMessageType('SpecialSubframe', (_message.Message,), {
+  'DESCRIPTOR' : _SPECIALSUBFRAME,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.SpecialSubframe)
-  ))
+  })
 _sym_db.RegisterMessage(SpecialSubframe)
 
-AdditionalSpecialSubframe = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframe', (_message.Message,), dict(
-  DESCRIPTOR = _ADDITIONALSPECIALSUBFRAME,
-  __module__ = 'enb_pb2'
+AdditionalSpecialSubframe = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframe', (_message.Message,), {
+  'DESCRIPTOR' : _ADDITIONALSPECIALSUBFRAME,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.AdditionalSpecialSubframe)
-  ))
+  })
 _sym_db.RegisterMessage(AdditionalSpecialSubframe)
 
-AdditionalSpecialSubframePatterns = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframePatterns', (_message.Message,), dict(
-  DESCRIPTOR = _ADDITIONALSPECIALSUBFRAMEPATTERNS,
-  __module__ = 'enb_pb2'
+AdditionalSpecialSubframePatterns = _reflection.GeneratedProtocolMessageType('AdditionalSpecialSubframePatterns', (_message.Message,), {
+  'DESCRIPTOR' : _ADDITIONALSPECIALSUBFRAMEPATTERNS,
+  '__module__' : 'enb_pb2'
   # @@protoc_insertion_point(class_scope:entities.AdditionalSpecialSubframePatterns)
-  ))
+  })
 _sym_db.RegisterMessage(AdditionalSpecialSubframePatterns)
 
 
index 8e0bce4..7dbcdf7 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: gnb.proto
 
@@ -14,7 +15,9 @@ _sym_db = _symbol_database.Default()
 
 
 from . import ran_function_pb2 as ran__function__pb2
+from . import e2node_component_config_pb2 as e2node__component__config__pb2
 from . import additional_cell_information_pb2 as additional__cell__information__pb2
+from . import nb_types_pb2 as nb__types__pb2
 
 
 DESCRIPTOR = _descriptor.FileDescriptor(
@@ -22,9 +25,9 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   package='entities',
   syntax='proto3',
   serialized_options=None,
-  serialized_pb=_b('\n\tgnb.proto\x12\x08\x65ntities\x1a\x12ran_function.proto\x1a!additional_cell_information.proto\"\x89\x01\n\x03Gnb\x12/\n\x0fserved_nr_cells\x18\x01 \x03(\x0b\x32\x16.entities.ServedNRCell\x12,\n\rran_functions\x18\x02 \x03(\x0b\x32\x15.entities.RanFunction\x12#\n\x08gnb_type\x18\x03 \x01(\x0e\x32\x11.entities.GnbType\"\x93\x01\n\x0cServedNRCell\x12\x45\n\x1aserved_nr_cell_information\x18\x01 \x01(\x0b\x32!.entities.ServedNRCellInformation\x12<\n\x12nr_neighbour_infos\x18\x02 \x03(\x0b\x32 .entities.NrNeighbourInformation\"\xc3\x06\n\x17ServedNRCellInformation\x12\x0e\n\x06nr_pci\x18\x01 \x01(\r\x12\x0f\n\x07\x63\x65ll_id\x18\x02 \x01(\t\x12\x0e\n\x06stac5g\x18\x03 \x01(\t\x12\x17\n\x0f\x63onfigured_stac\x18\x04 \x01(\t\x12\x14\n\x0cserved_plmns\x18\x05 \x03(\t\x12\"\n\x07nr_mode\x18\x06 \x01(\x0e\x32\x11.entities.Nr.Mode\x12\x46\n\x0e\x63hoice_nr_mode\x18\x07 \x01(\x0b\x32..entities.ServedNRCellInformation.ChoiceNRMode\x12H\n\x1b\x61\x64\x64itional_cell_information\x18\x08 \x01(\x0b\x32#.entities.AdditionalCellInformation\x1a\x91\x04\n\x0c\x43hoiceNRMode\x12\x43\n\x03\x66\x64\x64\x18\x01 \x01(\x0b\x32\x36.entities.ServedNRCellInformation.ChoiceNRMode.FddInfo\x12\x43\n\x03tdd\x18\x02 \x01(\x0b\x32\x36.entities.ServedNRCellInformation.ChoiceNRMode.TddInfo\x1a\xf7\x01\n\x07\x46\x64\x64Info\x12/\n\x0cul_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12/\n\x0c\x64l_freq_info\x18\x02 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12\x44\n\x19ul_transmission_bandwidth\x18\x03 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\x12\x44\n\x19\x64l_transmission_bandwidth\x18\x04 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\x1a}\n\x07TddInfo\x12/\n\x0cnr_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12\x41\n\x16transmission_bandwidth\x18\x02 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\"+\n\x02Nr\"%\n\x04Mode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x46\x44\x44\x10\x01\x12\x07\n\x03TDD\x10\x02\"\x89\x02\n\x0fNrFrequencyInfo\x12\x11\n\tnr_ar_fcn\x18\x01 \x01(\x04\x12@\n\x0esulInformation\x18\x03 \x01(\x0b\x32(.entities.NrFrequencyInfo.SulInformation\x12\x34\n\x0f\x66requency_bands\x18\x04 \x03(\x0b\x32\x1b.entities.FrequencyBandItem\x1ak\n\x0eSulInformation\x12\x12\n\nsul_ar_fcn\x18\x01 \x01(\x04\x12\x45\n\x1asul_transmission_bandwidth\x18\x02 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\"K\n\x11\x46requencyBandItem\x12\x19\n\x11nr_frequency_band\x18\x01 \x01(\r\x12\x1b\n\x13supported_sul_bands\x18\x02 \x03(\r\"Y\n\x17NrTransmissionBandwidth\x12\x1e\n\x05nrscs\x18\x01 \x01(\x0e\x32\x0f.entities.Nrscs\x12\x1e\n\x05ncnrb\x18\x02 \x01(\x0e\x32\x0f.entities.Ncnrb\"\xa1\x04\n\x16NrNeighbourInformation\x12\x0e\n\x06nr_pci\x18\x01 \x01(\r\x12\x0e\n\x06nr_cgi\x18\x02 \x01(\t\x12\"\n\x07nr_mode\x18\x03 \x01(\x0e\x32\x11.entities.Nr.Mode\x12\x45\n\x0e\x63hoice_nr_mode\x18\x04 \x01(\x0b\x32-.entities.NrNeighbourInformation.ChoiceNRMode\x12\x0e\n\x06stac5g\x18\x05 \x01(\t\x12\x17\n\x0f\x63onfigured_stac\x18\x06 \x01(\t\x1a\xd2\x02\n\x0c\x43hoiceNRMode\x12\x42\n\x03\x66\x64\x64\x18\x01 \x01(\x0b\x32\x35.entities.NrNeighbourInformation.ChoiceNRMode.FddInfo\x12\x42\n\x03tdd\x18\x02 \x01(\x0b\x32\x35.entities.NrNeighbourInformation.ChoiceNRMode.TddInfo\x1aw\n\x07\x46\x64\x64Info\x12\x35\n\x12ular_fcn_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12\x35\n\x12\x64lar_fcn_freq_info\x18\x02 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x1a\x41\n\x07TddInfo\x12\x36\n\x13\x61r_fcn_nr_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo*G\n\x05Nrscs\x12\x11\n\rUNKNOWN_NRSCS\x10\x00\x12\t\n\x05SCS15\x10\x01\x12\t\n\x05SCS30\x10\x02\x12\t\n\x05SCS60\x10\x03\x12\n\n\x06SCS120\x10\x04*\xe8\x02\n\x05Ncnrb\x12\x11\n\rUNKNOWN_NCNRB\x10\x00\x12\t\n\x05NRB11\x10\x01\x12\t\n\x05NRB18\x10\x02\x12\t\n\x05NRB24\x10\x03\x12\t\n\x05NRB25\x10\x04\x12\t\n\x05NRB31\x10\x05\x12\t\n\x05NRB32\x10\x06\x12\t\n\x05NRB38\x10\x07\x12\t\n\x05NRB51\x10\x08\x12\t\n\x05NRB52\x10\t\x12\t\n\x05NRB65\x10\n\x12\t\n\x05NRB66\x10\x0b\x12\t\n\x05NRB78\x10\x0c\x12\t\n\x05NRB79\x10\r\x12\t\n\x05NRB93\x10\x0e\x12\n\n\x06NRB106\x10\x0f\x12\n\n\x06NRB107\x10\x10\x12\n\n\x06NRB121\x10\x11\x12\n\n\x06NRB132\x10\x12\x12\n\n\x06NRB133\x10\x13\x12\n\n\x06NRB135\x10\x14\x12\n\n\x06NRB160\x10\x15\x12\n\n\x06NRB162\x10\x16\x12\n\n\x06NRB189\x10\x17\x12\n\n\x06NRB216\x10\x18\x12\n\n\x06NRB217\x10\x19\x12\n\n\x06NRB245\x10\x1a\x12\n\n\x06NRB264\x10\x1b\x12\n\n\x06NRB270\x10\x1c\x12\n\n\x06NRB273\x10\x1d*4\n\x07GnbType\x12\x14\n\x10UNKNOWN_GNB_TYPE\x10\x00\x12\x07\n\x03GNB\x10\x01\x12\n\n\x06\x45N_GNB\x10\x02\x62\x06proto3')
+  serialized_pb=_b('\n\tgnb.proto\x12\x08\x65ntities\x1a\x12ran_function.proto\x1a\x1d\x65\x32node_component_config.proto\x1a!additional_cell_information.proto\x1a\x0enb_types.proto\"\xc0\x01\n\x03Gnb\x12/\n\x0fserved_nr_cells\x18\x01 \x03(\x0b\x32\x16.entities.ServedNRCell\x12,\n\rran_functions\x18\x02 \x03(\x0b\x32\x15.entities.RanFunction\x12#\n\x08gnb_type\x18\x03 \x01(\x0e\x32\x11.entities.GnbType\x12\x35\n\x0cnode_configs\x18\x04 \x03(\x0b\x32\x1f.entities.E2nodeComponentConfig\"\x93\x01\n\x0cServedNRCell\x12\x45\n\x1aserved_nr_cell_information\x18\x01 \x01(\x0b\x32!.entities.ServedNRCellInformation\x12<\n\x12nr_neighbour_infos\x18\x02 \x03(\x0b\x32 .entities.NrNeighbourInformation\"\xc3\x06\n\x17ServedNRCellInformation\x12\x0e\n\x06nr_pci\x18\x01 \x01(\r\x12\x0f\n\x07\x63\x65ll_id\x18\x02 \x01(\t\x12\x0e\n\x06stac5g\x18\x03 \x01(\t\x12\x17\n\x0f\x63onfigured_stac\x18\x04 \x01(\t\x12\x14\n\x0cserved_plmns\x18\x05 \x03(\t\x12\"\n\x07nr_mode\x18\x06 \x01(\x0e\x32\x11.entities.Nr.Mode\x12\x46\n\x0e\x63hoice_nr_mode\x18\x07 \x01(\x0b\x32..entities.ServedNRCellInformation.ChoiceNRMode\x12H\n\x1b\x61\x64\x64itional_cell_information\x18\x08 \x01(\x0b\x32#.entities.AdditionalCellInformation\x1a\x91\x04\n\x0c\x43hoiceNRMode\x12\x43\n\x03\x66\x64\x64\x18\x01 \x01(\x0b\x32\x36.entities.ServedNRCellInformation.ChoiceNRMode.FddInfo\x12\x43\n\x03tdd\x18\x02 \x01(\x0b\x32\x36.entities.ServedNRCellInformation.ChoiceNRMode.TddInfo\x1a\xf7\x01\n\x07\x46\x64\x64Info\x12/\n\x0cul_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12/\n\x0c\x64l_freq_info\x18\x02 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12\x44\n\x19ul_transmission_bandwidth\x18\x03 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\x12\x44\n\x19\x64l_transmission_bandwidth\x18\x04 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\x1a}\n\x07TddInfo\x12/\n\x0cnr_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12\x41\n\x16transmission_bandwidth\x18\x02 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\"+\n\x02Nr\"%\n\x04Mode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x46\x44\x44\x10\x01\x12\x07\n\x03TDD\x10\x02\"\x89\x02\n\x0fNrFrequencyInfo\x12\x11\n\tnr_ar_fcn\x18\x01 \x01(\x04\x12@\n\x0esulInformation\x18\x03 \x01(\x0b\x32(.entities.NrFrequencyInfo.SulInformation\x12\x34\n\x0f\x66requency_bands\x18\x04 \x03(\x0b\x32\x1b.entities.FrequencyBandItem\x1ak\n\x0eSulInformation\x12\x12\n\nsul_ar_fcn\x18\x01 \x01(\x04\x12\x45\n\x1asul_transmission_bandwidth\x18\x02 \x01(\x0b\x32!.entities.NrTransmissionBandwidth\"K\n\x11\x46requencyBandItem\x12\x19\n\x11nr_frequency_band\x18\x01 \x01(\r\x12\x1b\n\x13supported_sul_bands\x18\x02 \x03(\r\"Y\n\x17NrTransmissionBandwidth\x12\x1e\n\x05nrscs\x18\x01 \x01(\x0e\x32\x0f.entities.Nrscs\x12\x1e\n\x05ncnrb\x18\x02 \x01(\x0e\x32\x0f.entities.Ncnrb\"\xa1\x04\n\x16NrNeighbourInformation\x12\x0e\n\x06nr_pci\x18\x01 \x01(\r\x12\x0e\n\x06nr_cgi\x18\x02 \x01(\t\x12\"\n\x07nr_mode\x18\x03 \x01(\x0e\x32\x11.entities.Nr.Mode\x12\x45\n\x0e\x63hoice_nr_mode\x18\x04 \x01(\x0b\x32-.entities.NrNeighbourInformation.ChoiceNRMode\x12\x0e\n\x06stac5g\x18\x05 \x01(\t\x12\x17\n\x0f\x63onfigured_stac\x18\x06 \x01(\t\x1a\xd2\x02\n\x0c\x43hoiceNRMode\x12\x42\n\x03\x66\x64\x64\x18\x01 \x01(\x0b\x32\x35.entities.NrNeighbourInformation.ChoiceNRMode.FddInfo\x12\x42\n\x03tdd\x18\x02 \x01(\x0b\x32\x35.entities.NrNeighbourInformation.ChoiceNRMode.TddInfo\x1aw\n\x07\x46\x64\x64Info\x12\x35\n\x12ular_fcn_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x12\x35\n\x12\x64lar_fcn_freq_info\x18\x02 \x01(\x0b\x32\x19.entities.NrFrequencyInfo\x1a\x41\n\x07TddInfo\x12\x36\n\x13\x61r_fcn_nr_freq_info\x18\x01 \x01(\x0b\x32\x19.entities.NrFrequencyInfo*G\n\x05Nrscs\x12\x11\n\rUNKNOWN_NRSCS\x10\x00\x12\t\n\x05SCS15\x10\x01\x12\t\n\x05SCS30\x10\x02\x12\t\n\x05SCS60\x10\x03\x12\n\n\x06SCS120\x10\x04*\xe8\x02\n\x05Ncnrb\x12\x11\n\rUNKNOWN_NCNRB\x10\x00\x12\t\n\x05NRB11\x10\x01\x12\t\n\x05NRB18\x10\x02\x12\t\n\x05NRB24\x10\x03\x12\t\n\x05NRB25\x10\x04\x12\t\n\x05NRB31\x10\x05\x12\t\n\x05NRB32\x10\x06\x12\t\n\x05NRB38\x10\x07\x12\t\n\x05NRB51\x10\x08\x12\t\n\x05NRB52\x10\t\x12\t\n\x05NRB65\x10\n\x12\t\n\x05NRB66\x10\x0b\x12\t\n\x05NRB78\x10\x0c\x12\t\n\x05NRB79\x10\r\x12\t\n\x05NRB93\x10\x0e\x12\n\n\x06NRB106\x10\x0f\x12\n\n\x06NRB107\x10\x10\x12\n\n\x06NRB121\x10\x11\x12\n\n\x06NRB132\x10\x12\x12\n\n\x06NRB133\x10\x13\x12\n\n\x06NRB135\x10\x14\x12\n\n\x06NRB160\x10\x15\x12\n\n\x06NRB162\x10\x16\x12\n\n\x06NRB189\x10\x17\x12\n\n\x06NRB216\x10\x18\x12\n\n\x06NRB217\x10\x19\x12\n\n\x06NRB245\x10\x1a\x12\n\n\x06NRB264\x10\x1b\x12\n\n\x06NRB270\x10\x1c\x12\n\n\x06NRB273\x10\x1d\x62\x06proto3')
   ,
-  dependencies=[ran__function__pb2.DESCRIPTOR,additional__cell__information__pb2.DESCRIPTOR,])
+  dependencies=[ran__function__pb2.DESCRIPTOR,e2node__component__config__pb2.DESCRIPTOR,additional__cell__information__pb2.DESCRIPTOR,nb__types__pb2.DESCRIPTOR,])
 
 _NRSCS = _descriptor.EnumDescriptor(
   name='Nrscs',
@@ -55,8 +58,8 @@ _NRSCS = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=2235,
-  serialized_end=2306,
+  serialized_start=2337,
+  serialized_end=2408,
 )
 _sym_db.RegisterEnumDescriptor(_NRSCS)
 
@@ -190,39 +193,12 @@ _NCNRB = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=2309,
-  serialized_end=2669,
+  serialized_start=2411,
+  serialized_end=2771,
 )
 _sym_db.RegisterEnumDescriptor(_NCNRB)
 
 Ncnrb = enum_type_wrapper.EnumTypeWrapper(_NCNRB)
-_GNBTYPE = _descriptor.EnumDescriptor(
-  name='GnbType',
-  full_name='entities.GnbType',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNKNOWN_GNB_TYPE', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GNB', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='EN_GNB', index=2, number=2,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2671,
-  serialized_end=2723,
-)
-_sym_db.RegisterEnumDescriptor(_GNBTYPE)
-
-GnbType = enum_type_wrapper.EnumTypeWrapper(_GNBTYPE)
 UNKNOWN_NRSCS = 0
 SCS15 = 1
 SCS30 = 2
@@ -258,9 +234,6 @@ NRB245 = 26
 NRB264 = 27
 NRB270 = 28
 NRB273 = 29
-UNKNOWN_GNB_TYPE = 0
-GNB = 1
-EN_GNB = 2
 
 
 _NR_MODE = _descriptor.EnumDescriptor(
@@ -284,8 +257,8 @@ _NR_MODE = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=1212,
-  serialized_end=1249,
+  serialized_start=1314,
+  serialized_end=1351,
 )
 _sym_db.RegisterEnumDescriptor(_NR_MODE)
 
@@ -318,6 +291,13 @@ _GNB = _descriptor.Descriptor(
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='node_configs', full_name='entities.Gnb.node_configs', index=3,
+      number=4, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
   ],
   extensions=[
   ],
@@ -330,8 +310,8 @@ _GNB = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=79,
-  serialized_end=216,
+  serialized_start=126,
+  serialized_end=318,
 )
 
 
@@ -368,8 +348,8 @@ _SERVEDNRCELL = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=219,
-  serialized_end=366,
+  serialized_start=321,
+  serialized_end=468,
 )
 
 
@@ -420,8 +400,8 @@ _SERVEDNRCELLINFORMATION_CHOICENRMODE_FDDINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=830,
-  serialized_end=1077,
+  serialized_start=932,
+  serialized_end=1179,
 )
 
 _SERVEDNRCELLINFORMATION_CHOICENRMODE_TDDINFO = _descriptor.Descriptor(
@@ -457,8 +437,8 @@ _SERVEDNRCELLINFORMATION_CHOICENRMODE_TDDINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1079,
-  serialized_end=1204,
+  serialized_start=1181,
+  serialized_end=1306,
 )
 
 _SERVEDNRCELLINFORMATION_CHOICENRMODE = _descriptor.Descriptor(
@@ -494,8 +474,8 @@ _SERVEDNRCELLINFORMATION_CHOICENRMODE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=675,
-  serialized_end=1204,
+  serialized_start=777,
+  serialized_end=1306,
 )
 
 _SERVEDNRCELLINFORMATION = _descriptor.Descriptor(
@@ -573,8 +553,8 @@ _SERVEDNRCELLINFORMATION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=369,
-  serialized_end=1204,
+  serialized_start=471,
+  serialized_end=1306,
 )
 
 
@@ -598,8 +578,8 @@ _NR = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1206,
-  serialized_end=1249,
+  serialized_start=1308,
+  serialized_end=1351,
 )
 
 
@@ -636,8 +616,8 @@ _NRFREQUENCYINFO_SULINFORMATION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1410,
-  serialized_end=1517,
+  serialized_start=1512,
+  serialized_end=1619,
 )
 
 _NRFREQUENCYINFO = _descriptor.Descriptor(
@@ -680,8 +660,8 @@ _NRFREQUENCYINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1252,
-  serialized_end=1517,
+  serialized_start=1354,
+  serialized_end=1619,
 )
 
 
@@ -718,8 +698,8 @@ _FREQUENCYBANDITEM = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1519,
-  serialized_end=1594,
+  serialized_start=1621,
+  serialized_end=1696,
 )
 
 
@@ -756,8 +736,8 @@ _NRTRANSMISSIONBANDWIDTH = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1596,
-  serialized_end=1685,
+  serialized_start=1698,
+  serialized_end=1787,
 )
 
 
@@ -794,8 +774,8 @@ _NRNEIGHBOURINFORMATION_CHOICENRMODE_FDDINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2047,
-  serialized_end=2166,
+  serialized_start=2149,
+  serialized_end=2268,
 )
 
 _NRNEIGHBOURINFORMATION_CHOICENRMODE_TDDINFO = _descriptor.Descriptor(
@@ -824,8 +804,8 @@ _NRNEIGHBOURINFORMATION_CHOICENRMODE_TDDINFO = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=2168,
-  serialized_end=2233,
+  serialized_start=2270,
+  serialized_end=2335,
 )
 
 _NRNEIGHBOURINFORMATION_CHOICENRMODE = _descriptor.Descriptor(
@@ -861,8 +841,8 @@ _NRNEIGHBOURINFORMATION_CHOICENRMODE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1895,
-  serialized_end=2233,
+  serialized_start=1997,
+  serialized_end=2335,
 )
 
 _NRNEIGHBOURINFORMATION = _descriptor.Descriptor(
@@ -926,13 +906,14 @@ _NRNEIGHBOURINFORMATION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1688,
-  serialized_end=2233,
+  serialized_start=1790,
+  serialized_end=2335,
 )
 
 _GNB.fields_by_name['served_nr_cells'].message_type = _SERVEDNRCELL
 _GNB.fields_by_name['ran_functions'].message_type = ran__function__pb2._RANFUNCTION
-_GNB.fields_by_name['gnb_type'].enum_type = _GNBTYPE
+_GNB.fields_by_name['gnb_type'].enum_type = nb__types__pb2._GNBTYPE
+_GNB.fields_by_name['node_configs'].message_type = e2node__component__config__pb2._E2NODECOMPONENTCONFIG
 _SERVEDNRCELL.fields_by_name['served_nr_cell_information'].message_type = _SERVEDNRCELLINFORMATION
 _SERVEDNRCELL.fields_by_name['nr_neighbour_infos'].message_type = _NRNEIGHBOURINFORMATION
 _SERVEDNRCELLINFORMATION_CHOICENRMODE_FDDINFO.fields_by_name['ul_freq_info'].message_type = _NRFREQUENCYINFO
@@ -976,116 +957,115 @@ DESCRIPTOR.message_types_by_name['NrTransmissionBandwidth'] = _NRTRANSMISSIONBAN
 DESCRIPTOR.message_types_by_name['NrNeighbourInformation'] = _NRNEIGHBOURINFORMATION
 DESCRIPTOR.enum_types_by_name['Nrscs'] = _NRSCS
 DESCRIPTOR.enum_types_by_name['Ncnrb'] = _NCNRB
-DESCRIPTOR.enum_types_by_name['GnbType'] = _GNBTYPE
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-Gnb = _reflection.GeneratedProtocolMessageType('Gnb', (_message.Message,), dict(
-  DESCRIPTOR = _GNB,
-  __module__ = 'gnb_pb2'
+Gnb = _reflection.GeneratedProtocolMessageType('Gnb', (_message.Message,), {
+  'DESCRIPTOR' : _GNB,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.Gnb)
-  ))
+  })
 _sym_db.RegisterMessage(Gnb)
 
-ServedNRCell = _reflection.GeneratedProtocolMessageType('ServedNRCell', (_message.Message,), dict(
-  DESCRIPTOR = _SERVEDNRCELL,
-  __module__ = 'gnb_pb2'
+ServedNRCell = _reflection.GeneratedProtocolMessageType('ServedNRCell', (_message.Message,), {
+  'DESCRIPTOR' : _SERVEDNRCELL,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.ServedNRCell)
-  ))
+  })
 _sym_db.RegisterMessage(ServedNRCell)
 
-ServedNRCellInformation = _reflection.GeneratedProtocolMessageType('ServedNRCellInformation', (_message.Message,), dict(
+ServedNRCellInformation = _reflection.GeneratedProtocolMessageType('ServedNRCellInformation', (_message.Message,), {
 
-  ChoiceNRMode = _reflection.GeneratedProtocolMessageType('ChoiceNRMode', (_message.Message,), dict(
+  'ChoiceNRMode' : _reflection.GeneratedProtocolMessageType('ChoiceNRMode', (_message.Message,), {
 
-    FddInfo = _reflection.GeneratedProtocolMessageType('FddInfo', (_message.Message,), dict(
-      DESCRIPTOR = _SERVEDNRCELLINFORMATION_CHOICENRMODE_FDDINFO,
-      __module__ = 'gnb_pb2'
+    'FddInfo' : _reflection.GeneratedProtocolMessageType('FddInfo', (_message.Message,), {
+      'DESCRIPTOR' : _SERVEDNRCELLINFORMATION_CHOICENRMODE_FDDINFO,
+      '__module__' : 'gnb_pb2'
       # @@protoc_insertion_point(class_scope:entities.ServedNRCellInformation.ChoiceNRMode.FddInfo)
-      ))
+      })
     ,
 
-    TddInfo = _reflection.GeneratedProtocolMessageType('TddInfo', (_message.Message,), dict(
-      DESCRIPTOR = _SERVEDNRCELLINFORMATION_CHOICENRMODE_TDDINFO,
-      __module__ = 'gnb_pb2'
+    'TddInfo' : _reflection.GeneratedProtocolMessageType('TddInfo', (_message.Message,), {
+      'DESCRIPTOR' : _SERVEDNRCELLINFORMATION_CHOICENRMODE_TDDINFO,
+      '__module__' : 'gnb_pb2'
       # @@protoc_insertion_point(class_scope:entities.ServedNRCellInformation.ChoiceNRMode.TddInfo)
-      ))
+      })
     ,
-    DESCRIPTOR = _SERVEDNRCELLINFORMATION_CHOICENRMODE,
-    __module__ = 'gnb_pb2'
+    'DESCRIPTOR' : _SERVEDNRCELLINFORMATION_CHOICENRMODE,
+    '__module__' : 'gnb_pb2'
     # @@protoc_insertion_point(class_scope:entities.ServedNRCellInformation.ChoiceNRMode)
-    ))
+    })
   ,
-  DESCRIPTOR = _SERVEDNRCELLINFORMATION,
-  __module__ = 'gnb_pb2'
+  'DESCRIPTOR' : _SERVEDNRCELLINFORMATION,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.ServedNRCellInformation)
-  ))
+  })
 _sym_db.RegisterMessage(ServedNRCellInformation)
 _sym_db.RegisterMessage(ServedNRCellInformation.ChoiceNRMode)
 _sym_db.RegisterMessage(ServedNRCellInformation.ChoiceNRMode.FddInfo)
 _sym_db.RegisterMessage(ServedNRCellInformation.ChoiceNRMode.TddInfo)
 
-Nr = _reflection.GeneratedProtocolMessageType('Nr', (_message.Message,), dict(
-  DESCRIPTOR = _NR,
-  __module__ = 'gnb_pb2'
+Nr = _reflection.GeneratedProtocolMessageType('Nr', (_message.Message,), {
+  'DESCRIPTOR' : _NR,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.Nr)
-  ))
+  })
 _sym_db.RegisterMessage(Nr)
 
-NrFrequencyInfo = _reflection.GeneratedProtocolMessageType('NrFrequencyInfo', (_message.Message,), dict(
+NrFrequencyInfo = _reflection.GeneratedProtocolMessageType('NrFrequencyInfo', (_message.Message,), {
 
-  SulInformation = _reflection.GeneratedProtocolMessageType('SulInformation', (_message.Message,), dict(
-    DESCRIPTOR = _NRFREQUENCYINFO_SULINFORMATION,
-    __module__ = 'gnb_pb2'
+  'SulInformation' : _reflection.GeneratedProtocolMessageType('SulInformation', (_message.Message,), {
+    'DESCRIPTOR' : _NRFREQUENCYINFO_SULINFORMATION,
+    '__module__' : 'gnb_pb2'
     # @@protoc_insertion_point(class_scope:entities.NrFrequencyInfo.SulInformation)
-    ))
+    })
   ,
-  DESCRIPTOR = _NRFREQUENCYINFO,
-  __module__ = 'gnb_pb2'
+  'DESCRIPTOR' : _NRFREQUENCYINFO,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.NrFrequencyInfo)
-  ))
+  })
 _sym_db.RegisterMessage(NrFrequencyInfo)
 _sym_db.RegisterMessage(NrFrequencyInfo.SulInformation)
 
-FrequencyBandItem = _reflection.GeneratedProtocolMessageType('FrequencyBandItem', (_message.Message,), dict(
-  DESCRIPTOR = _FREQUENCYBANDITEM,
-  __module__ = 'gnb_pb2'
+FrequencyBandItem = _reflection.GeneratedProtocolMessageType('FrequencyBandItem', (_message.Message,), {
+  'DESCRIPTOR' : _FREQUENCYBANDITEM,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.FrequencyBandItem)
-  ))
+  })
 _sym_db.RegisterMessage(FrequencyBandItem)
 
-NrTransmissionBandwidth = _reflection.GeneratedProtocolMessageType('NrTransmissionBandwidth', (_message.Message,), dict(
-  DESCRIPTOR = _NRTRANSMISSIONBANDWIDTH,
-  __module__ = 'gnb_pb2'
+NrTransmissionBandwidth = _reflection.GeneratedProtocolMessageType('NrTransmissionBandwidth', (_message.Message,), {
+  'DESCRIPTOR' : _NRTRANSMISSIONBANDWIDTH,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.NrTransmissionBandwidth)
-  ))
+  })
 _sym_db.RegisterMessage(NrTransmissionBandwidth)
 
-NrNeighbourInformation = _reflection.GeneratedProtocolMessageType('NrNeighbourInformation', (_message.Message,), dict(
+NrNeighbourInformation = _reflection.GeneratedProtocolMessageType('NrNeighbourInformation', (_message.Message,), {
 
-  ChoiceNRMode = _reflection.GeneratedProtocolMessageType('ChoiceNRMode', (_message.Message,), dict(
+  'ChoiceNRMode' : _reflection.GeneratedProtocolMessageType('ChoiceNRMode', (_message.Message,), {
 
-    FddInfo = _reflection.GeneratedProtocolMessageType('FddInfo', (_message.Message,), dict(
-      DESCRIPTOR = _NRNEIGHBOURINFORMATION_CHOICENRMODE_FDDINFO,
-      __module__ = 'gnb_pb2'
+    'FddInfo' : _reflection.GeneratedProtocolMessageType('FddInfo', (_message.Message,), {
+      'DESCRIPTOR' : _NRNEIGHBOURINFORMATION_CHOICENRMODE_FDDINFO,
+      '__module__' : 'gnb_pb2'
       # @@protoc_insertion_point(class_scope:entities.NrNeighbourInformation.ChoiceNRMode.FddInfo)
-      ))
+      })
     ,
 
-    TddInfo = _reflection.GeneratedProtocolMessageType('TddInfo', (_message.Message,), dict(
-      DESCRIPTOR = _NRNEIGHBOURINFORMATION_CHOICENRMODE_TDDINFO,
-      __module__ = 'gnb_pb2'
+    'TddInfo' : _reflection.GeneratedProtocolMessageType('TddInfo', (_message.Message,), {
+      'DESCRIPTOR' : _NRNEIGHBOURINFORMATION_CHOICENRMODE_TDDINFO,
+      '__module__' : 'gnb_pb2'
       # @@protoc_insertion_point(class_scope:entities.NrNeighbourInformation.ChoiceNRMode.TddInfo)
-      ))
+      })
     ,
-    DESCRIPTOR = _NRNEIGHBOURINFORMATION_CHOICENRMODE,
-    __module__ = 'gnb_pb2'
+    'DESCRIPTOR' : _NRNEIGHBOURINFORMATION_CHOICENRMODE,
+    '__module__' : 'gnb_pb2'
     # @@protoc_insertion_point(class_scope:entities.NrNeighbourInformation.ChoiceNRMode)
-    ))
+    })
   ,
-  DESCRIPTOR = _NRNEIGHBOURINFORMATION,
-  __module__ = 'gnb_pb2'
+  'DESCRIPTOR' : _NRNEIGHBOURINFORMATION,
+  '__module__' : 'gnb_pb2'
   # @@protoc_insertion_point(class_scope:entities.NrNeighbourInformation)
-  ))
+  })
 _sym_db.RegisterMessage(NrNeighbourInformation)
 _sym_db.RegisterMessage(NrNeighbourInformation.ChoiceNRMode)
 _sym_db.RegisterMessage(NrNeighbourInformation.ChoiceNRMode.FddInfo)
index 42c2227..d768082 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: nb_identity.proto
 
@@ -179,18 +180,18 @@ DESCRIPTOR.message_types_by_name['NbIdentity'] = _NBIDENTITY
 DESCRIPTOR.enum_types_by_name['ConnectionStatus'] = _CONNECTIONSTATUS
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-GlobalNbId = _reflection.GeneratedProtocolMessageType('GlobalNbId', (_message.Message,), dict(
-  DESCRIPTOR = _GLOBALNBID,
-  __module__ = 'nb_identity_pb2'
+GlobalNbId = _reflection.GeneratedProtocolMessageType('GlobalNbId', (_message.Message,), {
+  'DESCRIPTOR' : _GLOBALNBID,
+  '__module__' : 'nb_identity_pb2'
   # @@protoc_insertion_point(class_scope:entities.GlobalNbId)
-  ))
+  })
 _sym_db.RegisterMessage(GlobalNbId)
 
-NbIdentity = _reflection.GeneratedProtocolMessageType('NbIdentity', (_message.Message,), dict(
-  DESCRIPTOR = _NBIDENTITY,
-  __module__ = 'nb_identity_pb2'
+NbIdentity = _reflection.GeneratedProtocolMessageType('NbIdentity', (_message.Message,), {
+  'DESCRIPTOR' : _NBIDENTITY,
+  '__module__' : 'nb_identity_pb2'
   # @@protoc_insertion_point(class_scope:entities.NbIdentity)
-  ))
+  })
 _sym_db.RegisterMessage(NbIdentity)
 
 
diff --git a/ricxappframe/entities/rnib/nb_types_pb2.py b/ricxappframe/entities/rnib/nb_types_pb2.py
new file mode 100644 (file)
index 0000000..034d006
--- /dev/null
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: nb_types.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='nb_types.proto',
+  package='entities',
+  syntax='proto3',
+  serialized_options=None,
+  serialized_pb=_b('\n\x0enb_types.proto\x12\x08\x65ntities*\xa6\x01\n\x07\x45nbType\x12\x14\n\x10UNKNOWN_ENB_TYPE\x10\x00\x12\r\n\tMACRO_ENB\x10\x01\x12\x0c\n\x08HOME_ENB\x10\x02\x12\x13\n\x0fSHORT_MACRO_ENB\x10\x03\x12\x12\n\x0eLONG_MACRO_ENB\x10\x04\x12\x10\n\x0cMACRO_NG_ENB\x10\x05\x12\x16\n\x12SHORT_MACRO_NG_ENB\x10\x06\x12\x15\n\x11LONG_MACRO_NG_ENB\x10\x07*4\n\x07GnbType\x12\x14\n\x10UNKNOWN_GNB_TYPE\x10\x00\x12\x07\n\x03GNB\x10\x01\x12\n\n\x06\x45N_GNB\x10\x02\x62\x06proto3')
+)
+
+_ENBTYPE = _descriptor.EnumDescriptor(
+  name='EnbType',
+  full_name='entities.EnbType',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='UNKNOWN_ENB_TYPE', index=0, number=0,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='MACRO_ENB', index=1, number=1,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='HOME_ENB', index=2, number=2,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='SHORT_MACRO_ENB', index=3, number=3,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='LONG_MACRO_ENB', index=4, number=4,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='MACRO_NG_ENB', index=5, number=5,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='SHORT_MACRO_NG_ENB', index=6, number=6,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='LONG_MACRO_NG_ENB', index=7, number=7,
+      serialized_options=None,
+      type=None),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=29,
+  serialized_end=195,
+)
+_sym_db.RegisterEnumDescriptor(_ENBTYPE)
+
+EnbType = enum_type_wrapper.EnumTypeWrapper(_ENBTYPE)
+_GNBTYPE = _descriptor.EnumDescriptor(
+  name='GnbType',
+  full_name='entities.GnbType',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='UNKNOWN_GNB_TYPE', index=0, number=0,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='GNB', index=1, number=1,
+      serialized_options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='EN_GNB', index=2, number=2,
+      serialized_options=None,
+      type=None),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=197,
+  serialized_end=249,
+)
+_sym_db.RegisterEnumDescriptor(_GNBTYPE)
+
+GnbType = enum_type_wrapper.EnumTypeWrapper(_GNBTYPE)
+UNKNOWN_ENB_TYPE = 0
+MACRO_ENB = 1
+HOME_ENB = 2
+SHORT_MACRO_ENB = 3
+LONG_MACRO_ENB = 4
+MACRO_NG_ENB = 5
+SHORT_MACRO_NG_ENB = 6
+LONG_MACRO_NG_ENB = 7
+UNKNOWN_GNB_TYPE = 0
+GNB = 1
+EN_GNB = 2
+
+
+DESCRIPTOR.enum_types_by_name['EnbType'] = _ENBTYPE
+DESCRIPTOR.enum_types_by_name['GnbType'] = _GNBTYPE
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+
+# @@protoc_insertion_point(module_scope)
index 24865e4..89216d9 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: nodeb_info.proto
 
@@ -302,25 +303,25 @@ DESCRIPTOR.message_types_by_name['Failure'] = _FAILURE
 DESCRIPTOR.enum_types_by_name['E2ApplicationProtocol'] = _E2APPLICATIONPROTOCOL
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-NodebInfo = _reflection.GeneratedProtocolMessageType('NodebInfo', (_message.Message,), dict(
-  DESCRIPTOR = _NODEBINFO,
-  __module__ = 'nodeb_info_pb2'
+NodebInfo = _reflection.GeneratedProtocolMessageType('NodebInfo', (_message.Message,), {
+  'DESCRIPTOR' : _NODEBINFO,
+  '__module__' : 'nodeb_info_pb2'
   # @@protoc_insertion_point(class_scope:entities.NodebInfo)
-  ))
+  })
 _sym_db.RegisterMessage(NodebInfo)
 
-Node = _reflection.GeneratedProtocolMessageType('Node', (_message.Message,), dict(
-  DESCRIPTOR = _NODE,
-  __module__ = 'nodeb_info_pb2'
+Node = _reflection.GeneratedProtocolMessageType('Node', (_message.Message,), {
+  'DESCRIPTOR' : _NODE,
+  '__module__' : 'nodeb_info_pb2'
   # @@protoc_insertion_point(class_scope:entities.Node)
-  ))
+  })
 _sym_db.RegisterMessage(Node)
 
-Failure = _reflection.GeneratedProtocolMessageType('Failure', (_message.Message,), dict(
-  DESCRIPTOR = _FAILURE,
-  __module__ = 'nodeb_info_pb2'
+Failure = _reflection.GeneratedProtocolMessageType('Failure', (_message.Message,), {
+  'DESCRIPTOR' : _FAILURE,
+  '__module__' : 'nodeb_info_pb2'
   # @@protoc_insertion_point(class_scope:entities.Failure)
-  ))
+  })
 _sym_db.RegisterMessage(Failure)
 
 
index fd48767..6f31065 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: ran_function.proto
 
@@ -19,7 +20,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   package='entities',
   syntax='proto3',
   serialized_options=None,
-  serialized_pb=_b('\n\x12ran_function.proto\x12\x08\x65ntities\"f\n\x0bRanFunction\x12\x17\n\x0fran_function_id\x18\x01 \x01(\r\x12\x1f\n\x17ran_function_definition\x18\x02 \x01(\t\x12\x1d\n\x15ran_function_revision\x18\x03 \x01(\rb\x06proto3')
+  serialized_pb=_b('\n\x12ran_function.proto\x12\x08\x65ntities\"\x80\x01\n\x0bRanFunction\x12\x17\n\x0fran_function_id\x18\x01 \x01(\r\x12\x1f\n\x17ran_function_definition\x18\x02 \x01(\t\x12\x1d\n\x15ran_function_revision\x18\x03 \x01(\r\x12\x18\n\x10ran_function_oid\x18\x04 \x01(\tb\x06proto3')
 )
 
 
@@ -53,6 +54,13 @@ _RANFUNCTION = _descriptor.Descriptor(
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='ran_function_oid', full_name='entities.RanFunction.ran_function_oid', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
   ],
   extensions=[
   ],
@@ -65,18 +73,18 @@ _RANFUNCTION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=32,
-  serialized_end=134,
+  serialized_start=33,
+  serialized_end=161,
 )
 
 DESCRIPTOR.message_types_by_name['RanFunction'] = _RANFUNCTION
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-RanFunction = _reflection.GeneratedProtocolMessageType('RanFunction', (_message.Message,), dict(
-  DESCRIPTOR = _RANFUNCTION,
-  __module__ = 'ran_function_pb2'
+RanFunction = _reflection.GeneratedProtocolMessageType('RanFunction', (_message.Message,), {
+  'DESCRIPTOR' : _RANFUNCTION,
+  '__module__' : 'ran_function_pb2'
   # @@protoc_insertion_point(class_scope:entities.RanFunction)
-  ))
+  })
 _sym_db.RegisterMessage(RanFunction)
 
 
index 1238cea..74b92e6 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: ran_load_information.proto
 
@@ -976,88 +977,88 @@ DESCRIPTOR.enum_types_by_name['NaicsState'] = _NAICSSTATE
 DESCRIPTOR.enum_types_by_name['PA'] = _PA
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-RanLoadInformation = _reflection.GeneratedProtocolMessageType('RanLoadInformation', (_message.Message,), dict(
-  DESCRIPTOR = _RANLOADINFORMATION,
-  __module__ = 'ran_load_information_pb2'
+RanLoadInformation = _reflection.GeneratedProtocolMessageType('RanLoadInformation', (_message.Message,), {
+  'DESCRIPTOR' : _RANLOADINFORMATION,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.RanLoadInformation)
-  ))
+  })
 _sym_db.RegisterMessage(RanLoadInformation)
 
-CellLoadInformation = _reflection.GeneratedProtocolMessageType('CellLoadInformation', (_message.Message,), dict(
-  DESCRIPTOR = _CELLLOADINFORMATION,
-  __module__ = 'ran_load_information_pb2'
+CellLoadInformation = _reflection.GeneratedProtocolMessageType('CellLoadInformation', (_message.Message,), {
+  'DESCRIPTOR' : _CELLLOADINFORMATION,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.CellLoadInformation)
-  ))
+  })
 _sym_db.RegisterMessage(CellLoadInformation)
 
-UlHighInterferenceInformation = _reflection.GeneratedProtocolMessageType('UlHighInterferenceInformation', (_message.Message,), dict(
-  DESCRIPTOR = _ULHIGHINTERFERENCEINFORMATION,
-  __module__ = 'ran_load_information_pb2'
+UlHighInterferenceInformation = _reflection.GeneratedProtocolMessageType('UlHighInterferenceInformation', (_message.Message,), {
+  'DESCRIPTOR' : _ULHIGHINTERFERENCEINFORMATION,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.UlHighInterferenceInformation)
-  ))
+  })
 _sym_db.RegisterMessage(UlHighInterferenceInformation)
 
-RelativeNarrowbandTxPower = _reflection.GeneratedProtocolMessageType('RelativeNarrowbandTxPower', (_message.Message,), dict(
-  DESCRIPTOR = _RELATIVENARROWBANDTXPOWER,
-  __module__ = 'ran_load_information_pb2'
+RelativeNarrowbandTxPower = _reflection.GeneratedProtocolMessageType('RelativeNarrowbandTxPower', (_message.Message,), {
+  'DESCRIPTOR' : _RELATIVENARROWBANDTXPOWER,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.RelativeNarrowbandTxPower)
-  ))
+  })
 _sym_db.RegisterMessage(RelativeNarrowbandTxPower)
 
-EnhancedRntp = _reflection.GeneratedProtocolMessageType('EnhancedRntp', (_message.Message,), dict(
-  DESCRIPTOR = _ENHANCEDRNTP,
-  __module__ = 'ran_load_information_pb2'
+EnhancedRntp = _reflection.GeneratedProtocolMessageType('EnhancedRntp', (_message.Message,), {
+  'DESCRIPTOR' : _ENHANCEDRNTP,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.EnhancedRntp)
-  ))
+  })
 _sym_db.RegisterMessage(EnhancedRntp)
 
-StartTime = _reflection.GeneratedProtocolMessageType('StartTime', (_message.Message,), dict(
-  DESCRIPTOR = _STARTTIME,
-  __module__ = 'ran_load_information_pb2'
+StartTime = _reflection.GeneratedProtocolMessageType('StartTime', (_message.Message,), {
+  'DESCRIPTOR' : _STARTTIME,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.StartTime)
-  ))
+  })
 _sym_db.RegisterMessage(StartTime)
 
-AbsInformation = _reflection.GeneratedProtocolMessageType('AbsInformation', (_message.Message,), dict(
-  DESCRIPTOR = _ABSINFORMATION,
-  __module__ = 'ran_load_information_pb2'
+AbsInformation = _reflection.GeneratedProtocolMessageType('AbsInformation', (_message.Message,), {
+  'DESCRIPTOR' : _ABSINFORMATION,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.AbsInformation)
-  ))
+  })
 _sym_db.RegisterMessage(AbsInformation)
 
-ExtendedUlInterferenceOverloadInfo = _reflection.GeneratedProtocolMessageType('ExtendedUlInterferenceOverloadInfo', (_message.Message,), dict(
-  DESCRIPTOR = _EXTENDEDULINTERFERENCEOVERLOADINFO,
-  __module__ = 'ran_load_information_pb2'
+ExtendedUlInterferenceOverloadInfo = _reflection.GeneratedProtocolMessageType('ExtendedUlInterferenceOverloadInfo', (_message.Message,), {
+  'DESCRIPTOR' : _EXTENDEDULINTERFERENCEOVERLOADINFO,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.ExtendedUlInterferenceOverloadInfo)
-  ))
+  })
 _sym_db.RegisterMessage(ExtendedUlInterferenceOverloadInfo)
 
-CompInformation = _reflection.GeneratedProtocolMessageType('CompInformation', (_message.Message,), dict(
-  DESCRIPTOR = _COMPINFORMATION,
-  __module__ = 'ran_load_information_pb2'
+CompInformation = _reflection.GeneratedProtocolMessageType('CompInformation', (_message.Message,), {
+  'DESCRIPTOR' : _COMPINFORMATION,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.CompInformation)
-  ))
+  })
 _sym_db.RegisterMessage(CompInformation)
 
-CompInformationItem = _reflection.GeneratedProtocolMessageType('CompInformationItem', (_message.Message,), dict(
-  DESCRIPTOR = _COMPINFORMATIONITEM,
-  __module__ = 'ran_load_information_pb2'
+CompInformationItem = _reflection.GeneratedProtocolMessageType('CompInformationItem', (_message.Message,), {
+  'DESCRIPTOR' : _COMPINFORMATIONITEM,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.CompInformationItem)
-  ))
+  })
 _sym_db.RegisterMessage(CompInformationItem)
 
-CompHypothesisSet = _reflection.GeneratedProtocolMessageType('CompHypothesisSet', (_message.Message,), dict(
-  DESCRIPTOR = _COMPHYPOTHESISSET,
-  __module__ = 'ran_load_information_pb2'
+CompHypothesisSet = _reflection.GeneratedProtocolMessageType('CompHypothesisSet', (_message.Message,), {
+  'DESCRIPTOR' : _COMPHYPOTHESISSET,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.CompHypothesisSet)
-  ))
+  })
 _sym_db.RegisterMessage(CompHypothesisSet)
 
-DynamicDlTransmissionInformation = _reflection.GeneratedProtocolMessageType('DynamicDlTransmissionInformation', (_message.Message,), dict(
-  DESCRIPTOR = _DYNAMICDLTRANSMISSIONINFORMATION,
-  __module__ = 'ran_load_information_pb2'
+DynamicDlTransmissionInformation = _reflection.GeneratedProtocolMessageType('DynamicDlTransmissionInformation', (_message.Message,), {
+  'DESCRIPTOR' : _DYNAMICDLTRANSMISSIONINFORMATION,
+  '__module__' : 'ran_load_information_pb2'
   # @@protoc_insertion_point(class_scope:entities.DynamicDlTransmissionInformation)
-  ))
+  })
 _sym_db.RegisterMessage(DynamicDlTransmissionInformation)
 
 
index d234394..12e706a 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: x2_setup_failure_response.proto
 
@@ -813,53 +814,53 @@ DESCRIPTOR.enum_types_by_name['TriggeringMessage'] = _TRIGGERINGMESSAGE
 DESCRIPTOR.enum_types_by_name['Criticality'] = _CRITICALITY
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-SetupFailure = _reflection.GeneratedProtocolMessageType('SetupFailure', (_message.Message,), dict(
-  DESCRIPTOR = _SETUPFAILURE,
-  __module__ = 'x2_setup_failure_response_pb2'
+SetupFailure = _reflection.GeneratedProtocolMessageType('SetupFailure', (_message.Message,), {
+  'DESCRIPTOR' : _SETUPFAILURE,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.SetupFailure)
-  ))
+  })
 _sym_db.RegisterMessage(SetupFailure)
 
-RadioNetworkLayer = _reflection.GeneratedProtocolMessageType('RadioNetworkLayer', (_message.Message,), dict(
-  DESCRIPTOR = _RADIONETWORKLAYER,
-  __module__ = 'x2_setup_failure_response_pb2'
+RadioNetworkLayer = _reflection.GeneratedProtocolMessageType('RadioNetworkLayer', (_message.Message,), {
+  'DESCRIPTOR' : _RADIONETWORKLAYER,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.RadioNetworkLayer)
-  ))
+  })
 _sym_db.RegisterMessage(RadioNetworkLayer)
 
-TransportLayer = _reflection.GeneratedProtocolMessageType('TransportLayer', (_message.Message,), dict(
-  DESCRIPTOR = _TRANSPORTLAYER,
-  __module__ = 'x2_setup_failure_response_pb2'
+TransportLayer = _reflection.GeneratedProtocolMessageType('TransportLayer', (_message.Message,), {
+  'DESCRIPTOR' : _TRANSPORTLAYER,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.TransportLayer)
-  ))
+  })
 _sym_db.RegisterMessage(TransportLayer)
 
-Protocol = _reflection.GeneratedProtocolMessageType('Protocol', (_message.Message,), dict(
-  DESCRIPTOR = _PROTOCOL,
-  __module__ = 'x2_setup_failure_response_pb2'
+Protocol = _reflection.GeneratedProtocolMessageType('Protocol', (_message.Message,), {
+  'DESCRIPTOR' : _PROTOCOL,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.Protocol)
-  ))
+  })
 _sym_db.RegisterMessage(Protocol)
 
-Miscellaneous = _reflection.GeneratedProtocolMessageType('Miscellaneous', (_message.Message,), dict(
-  DESCRIPTOR = _MISCELLANEOUS,
-  __module__ = 'x2_setup_failure_response_pb2'
+Miscellaneous = _reflection.GeneratedProtocolMessageType('Miscellaneous', (_message.Message,), {
+  'DESCRIPTOR' : _MISCELLANEOUS,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.Miscellaneous)
-  ))
+  })
 _sym_db.RegisterMessage(Miscellaneous)
 
-CriticalityDiagnostics = _reflection.GeneratedProtocolMessageType('CriticalityDiagnostics', (_message.Message,), dict(
-  DESCRIPTOR = _CRITICALITYDIAGNOSTICS,
-  __module__ = 'x2_setup_failure_response_pb2'
+CriticalityDiagnostics = _reflection.GeneratedProtocolMessageType('CriticalityDiagnostics', (_message.Message,), {
+  'DESCRIPTOR' : _CRITICALITYDIAGNOSTICS,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.CriticalityDiagnostics)
-  ))
+  })
 _sym_db.RegisterMessage(CriticalityDiagnostics)
 
-InformationElementCriticalityDiagnostic = _reflection.GeneratedProtocolMessageType('InformationElementCriticalityDiagnostic', (_message.Message,), dict(
-  DESCRIPTOR = _INFORMATIONELEMENTCRITICALITYDIAGNOSTIC,
-  __module__ = 'x2_setup_failure_response_pb2'
+InformationElementCriticalityDiagnostic = _reflection.GeneratedProtocolMessageType('InformationElementCriticalityDiagnostic', (_message.Message,), {
+  'DESCRIPTOR' : _INFORMATIONELEMENTCRITICALITYDIAGNOSTIC,
+  '__module__' : 'x2_setup_failure_response_pb2'
   # @@protoc_insertion_point(class_scope:entities.InformationElementCriticalityDiagnostic)
-  ))
+  })
 _sym_db.RegisterMessage(InformationElementCriticalityDiagnostic)
 
 
diff --git a/ricxappframe/subsclient/__init__.py b/ricxappframe/subsclient/__init__.py
new file mode 100644 (file)
index 0000000..3e852a6
--- /dev/null
@@ -0,0 +1,42 @@
+# coding: utf-8
+
+# flake8: noqa
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+from __future__ import absolute_import
+
+# import apis into sdk package
+from ricxappframe.subsclient.api.common_api import CommonApi
+from ricxappframe.subsclient.api.xapp_api import XappApi
+
+# import ApiClient
+from ricxappframe.subsclient.api_client import ApiClient
+from ricxappframe.subsclient.configuration import Configuration
+# import models into sdk package
+from ricxappframe.subsclient.models.action_definition import ActionDefinition
+from ricxappframe.subsclient.models.action_to_be_setup import ActionToBeSetup
+from ricxappframe.subsclient.models.actions_to_be_setup import ActionsToBeSetup
+from ricxappframe.subsclient.models.config_metadata import ConfigMetadata
+from ricxappframe.subsclient.models.event_trigger_definition import EventTriggerDefinition
+from ricxappframe.subsclient.models.subscription_data import SubscriptionData
+from ricxappframe.subsclient.models.subscription_detail import SubscriptionDetail
+from ricxappframe.subsclient.models.subscription_details_list import SubscriptionDetailsList
+from ricxappframe.subsclient.models.subscription_instance import SubscriptionInstance
+from ricxappframe.subsclient.models.subscription_list import SubscriptionList
+from ricxappframe.subsclient.models.subscription_params import SubscriptionParams
+from ricxappframe.subsclient.models.subscription_params_client_endpoint import SubscriptionParamsClientEndpoint
+from ricxappframe.subsclient.models.subscription_params_e2_subscription_directives import SubscriptionParamsE2SubscriptionDirectives
+from ricxappframe.subsclient.models.subscription_response import SubscriptionResponse
+from ricxappframe.subsclient.models.subsequent_action import SubsequentAction
+from ricxappframe.subsclient.models.x_app_config import XAppConfig
+from ricxappframe.subsclient.models.xapp_config_list import XappConfigList
diff --git a/ricxappframe/subsclient/api/__init__.py b/ricxappframe/subsclient/api/__init__.py
new file mode 100644 (file)
index 0000000..b05b68f
--- /dev/null
@@ -0,0 +1,7 @@
+from __future__ import absolute_import
+
+# flake8: noqa
+
+# import apis into api package
+from ricxappframe.subsclient.api.common_api import CommonApi
+from ricxappframe.subsclient.api.xapp_api import XappApi
diff --git a/ricxappframe/subsclient/api/common_api.py b/ricxappframe/subsclient/api/common_api.py
new file mode 100644 (file)
index 0000000..8890463
--- /dev/null
@@ -0,0 +1,309 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+from __future__ import absolute_import
+
+import re  # noqa: F401
+
+# python 2 and python 3 compatibility library
+import six
+
+from ricxappframe.subsclient.api_client import ApiClient
+
+
+class CommonApi(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    Ref: https://github.com/swagger-api/swagger-codegen
+    """
+
+    def __init__(self, api_client=None):
+        if api_client is None:
+            api_client = ApiClient()
+        self.api_client = api_client
+
+    def get_all_subscriptions(self, **kwargs):  # noqa: E501
+        """Returns list of subscriptions  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.get_all_subscriptions(async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :return: SubscriptionList
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.get_all_subscriptions_with_http_info(**kwargs)  # noqa: E501
+        else:
+            (data) = self.get_all_subscriptions_with_http_info(**kwargs)  # noqa: E501
+            return data
+
+    def get_all_subscriptions_with_http_info(self, **kwargs):  # noqa: E501
+        """Returns list of subscriptions  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.get_all_subscriptions_with_http_info(async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :return: SubscriptionList
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = []  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method get_all_subscriptions" % key
+                )
+            params[key] = val
+        del params['kwargs']
+
+        collection_formats = {}
+
+        path_params = {}
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        # HTTP header `Accept`
+        header_params['Accept'] = self.api_client.select_header_accept(
+            ['application/json'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/subscriptions', 'GET',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type='SubscriptionList',  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
+
+    def subscribe(self, **kwargs):  # noqa: E501
+        """Subscribe a list of X2AP event triggers to receive messages sent by RAN  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.subscribe(async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param SubscriptionParams subscription_params: Subscription parameters
+        :return: SubscriptionResponse
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.subscribe_with_http_info(**kwargs)  # noqa: E501
+        else:
+            (data) = self.subscribe_with_http_info(**kwargs)  # noqa: E501
+            return data
+
+    def subscribe_with_http_info(self, **kwargs):  # noqa: E501
+        """Subscribe a list of X2AP event triggers to receive messages sent by RAN  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.subscribe_with_http_info(async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param SubscriptionParams subscription_params: Subscription parameters
+        :return: SubscriptionResponse
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['subscription_params']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method subscribe" % key
+                )
+            params[key] = val
+        del params['kwargs']
+
+        collection_formats = {}
+
+        path_params = {}
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        if 'subscription_params' in params:
+            body_params = params['subscription_params']
+        # HTTP header `Accept`
+        header_params['Accept'] = self.api_client.select_header_accept(
+            ['application/json'])  # noqa: E501
+
+        # HTTP header `Content-Type`
+        header_params['Content-Type'] = self.api_client.select_header_content_type(  # noqa: E501
+            ['application/json'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/subscriptions', 'POST',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type='SubscriptionResponse',  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
+
+    def unsubscribe(self, subscription_id, **kwargs):  # noqa: E501
+        """Unsubscribe X2AP events from Subscription Manager  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.unsubscribe(subscription_id, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param str subscription_id: The subscriptionId received in the Subscription Response (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.unsubscribe_with_http_info(subscription_id, **kwargs)  # noqa: E501
+        else:
+            (data) = self.unsubscribe_with_http_info(subscription_id, **kwargs)  # noqa: E501
+            return data
+
+    def unsubscribe_with_http_info(self, subscription_id, **kwargs):  # noqa: E501
+        """Unsubscribe X2AP events from Subscription Manager  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.unsubscribe_with_http_info(subscription_id, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param str subscription_id: The subscriptionId received in the Subscription Response (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['subscription_id']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method unsubscribe" % key
+                )
+            params[key] = val
+        del params['kwargs']
+        # verify the required parameter 'subscription_id' is set
+        if self.api_client.client_side_validation and ('subscription_id' not in params or
+                                                       params['subscription_id'] is None):  # noqa: E501
+            raise ValueError("Missing the required parameter `subscription_id` when calling `unsubscribe`")  # noqa: E501
+
+        collection_formats = {}
+
+        path_params = {}
+        if 'subscription_id' in params:
+            path_params['subscriptionId'] = params['subscription_id']  # noqa: E501
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        # HTTP header `Accept`
+        header_params['Accept'] = self.api_client.select_header_accept(
+            ['application/json'])  # noqa: E501
+
+        # HTTP header `Content-Type`
+        header_params['Content-Type'] = self.api_client.select_header_content_type(  # noqa: E501
+            ['application/json'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/subscriptions/{subscriptionId}', 'DELETE',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type=None,  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
diff --git a/ricxappframe/subsclient/api/xapp_api.py b/ricxappframe/subsclient/api/xapp_api.py
new file mode 100644 (file)
index 0000000..cdef33f
--- /dev/null
@@ -0,0 +1,119 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+from __future__ import absolute_import
+
+import re  # noqa: F401
+
+# python 2 and python 3 compatibility library
+import six
+
+from ricxappframe.subsclient.api_client import ApiClient
+
+
+class XappApi(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    Ref: https://github.com/swagger-api/swagger-codegen
+    """
+
+    def __init__(self, api_client=None):
+        if api_client is None:
+            api_client = ApiClient()
+        self.api_client = api_client
+
+    def get_xapp_config_list(self, **kwargs):  # noqa: E501
+        """Returns the configuration of all xapps  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.get_xapp_config_list(async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :return: XappConfigList
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.get_xapp_config_list_with_http_info(**kwargs)  # noqa: E501
+        else:
+            (data) = self.get_xapp_config_list_with_http_info(**kwargs)  # noqa: E501
+            return data
+
+    def get_xapp_config_list_with_http_info(self, **kwargs):  # noqa: E501
+        """Returns the configuration of all xapps  # noqa: E501
+
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.get_xapp_config_list_with_http_info(async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :return: XappConfigList
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = []  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method get_xapp_config_list" % key
+                )
+            params[key] = val
+        del params['kwargs']
+
+        collection_formats = {}
+
+        path_params = {}
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        # HTTP header `Accept`
+        header_params['Accept'] = self.api_client.select_header_accept(
+            ['application/json', 'application/xml'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/config', 'GET',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type='XappConfigList',  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
diff --git a/ricxappframe/subsclient/api_client.py b/ricxappframe/subsclient/api_client.py
new file mode 100644 (file)
index 0000000..49172d5
--- /dev/null
@@ -0,0 +1,639 @@
+# coding: utf-8
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+from __future__ import absolute_import
+
+import datetime
+import json
+import mimetypes
+from multiprocessing.pool import ThreadPool
+import os
+import re
+import tempfile
+
+# python 2 and python 3 compatibility library
+import six
+from six.moves.urllib.parse import quote
+
+from ricxappframe.subsclient.configuration import Configuration
+import ricxappframe.subsclient.models
+from ricxappframe.subsclient import rest
+
+
+class ApiClient(object):
+    """Generic API client for Swagger client library builds.
+
+    Swagger generic API client. This client handles the client-
+    server communication, and is invariant across implementations. Specifics of
+    the methods and models for each application are generated from the Swagger
+    templates.
+
+    NOTE: This class is auto generated by the swagger code generator program.
+    Ref: https://github.com/swagger-api/swagger-codegen
+    Do not edit the class manually.
+
+    :param configuration: .Configuration object for this client
+    :param header_name: a header to pass when making calls to the API.
+    :param header_value: a header value to pass when making calls to
+        the API.
+    :param cookie: a cookie to include in the header when making calls
+        to the API
+    """
+
+    PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types
+    NATIVE_TYPES_MAPPING = {
+        'int': int,
+        'long': int if six.PY3 else long,  # noqa: F821
+        'float': float,
+        'str': str,
+        'bool': bool,
+        'date': datetime.date,
+        'datetime': datetime.datetime,
+        'object': object,
+    }
+
+    def __init__(self, configuration=None, header_name=None, header_value=None,
+                 cookie=None):
+        if configuration is None:
+            configuration = Configuration()
+        self.configuration = configuration
+
+        # Use the pool property to lazily initialize the ThreadPool.
+        self._pool = None
+        self.rest_client = rest.RESTClientObject(configuration)
+        self.default_headers = {}
+        if header_name is not None:
+            self.default_headers[header_name] = header_value
+        self.cookie = cookie
+        # Set default User-Agent.
+        self.user_agent = 'Swagger-Codegen/1.0.0/python'
+        self.client_side_validation = configuration.client_side_validation
+
+    def __del__(self):
+        if self._pool is not None:
+            self._pool.close()
+            self._pool.join()
+
+    @property
+    def pool(self):
+        if self._pool is None:
+            self._pool = ThreadPool()
+        return self._pool
+
+    @property
+    def user_agent(self):
+        """User agent for this API client"""
+        return self.default_headers['User-Agent']
+
+    @user_agent.setter
+    def user_agent(self, value):
+        self.default_headers['User-Agent'] = value
+
+    def set_default_header(self, header_name, header_value):
+        self.default_headers[header_name] = header_value
+
+    def __call_api(
+            self, resource_path, method, path_params=None,
+            query_params=None, header_params=None, body=None, post_params=None,
+            files=None, response_type=None, auth_settings=None,
+            _return_http_data_only=None, collection_formats=None,
+            _preload_content=True, _request_timeout=None):
+
+        config = self.configuration
+
+        # header parameters
+        header_params = header_params or {}
+        header_params.update(self.default_headers)
+        if self.cookie:
+            header_params['Cookie'] = self.cookie
+        if header_params:
+            header_params = self.sanitize_for_serialization(header_params)
+            header_params = dict(self.parameters_to_tuples(header_params,
+                                                           collection_formats))
+
+        # path parameters
+        if path_params:
+            path_params = self.sanitize_for_serialization(path_params)
+            path_params = self.parameters_to_tuples(path_params,
+                                                    collection_formats)
+            for k, v in path_params:
+                # specified safe chars, encode everything
+                resource_path = resource_path.replace(
+                    '{%s}' % k,
+                    quote(str(v), safe=config.safe_chars_for_path_param)
+                )
+
+        # query parameters
+        if query_params:
+            query_params = self.sanitize_for_serialization(query_params)
+            query_params = self.parameters_to_tuples(query_params,
+                                                     collection_formats)
+
+        # post parameters
+        if post_params or files:
+            post_params = self.prepare_post_parameters(post_params, files)
+            post_params = self.sanitize_for_serialization(post_params)
+            post_params = self.parameters_to_tuples(post_params,
+                                                    collection_formats)
+
+        # auth setting
+        self.update_params_for_auth(header_params, query_params, auth_settings)
+
+        # body
+        if body:
+            body = self.sanitize_for_serialization(body)
+
+        # request url
+        url = self.configuration.host + resource_path
+
+        # perform request and return response
+        response_data = self.request(
+            method, url, query_params=query_params, headers=header_params,
+            post_params=post_params, body=body,
+            _preload_content=_preload_content,
+            _request_timeout=_request_timeout)
+
+        self.last_response = response_data
+
+        return_data = response_data
+        if _preload_content:
+            # deserialize response data
+            if response_type:
+                return_data = self.deserialize(response_data, response_type)
+            else:
+                return_data = None
+
+        if _return_http_data_only:
+            return (return_data)
+        else:
+            return (return_data, response_data.status,
+                    response_data.getheaders())
+
+    def sanitize_for_serialization(self, obj):
+        """Builds a JSON POST object.
+
+        If obj is None, return None.
+        If obj is str, int, long, float, bool, return directly.
+        If obj is datetime.datetime, datetime.date
+            convert to string in iso8601 format.
+        If obj is list, sanitize each element in the list.
+        If obj is dict, return the dict.
+        If obj is swagger model, return the properties dict.
+
+        :param obj: The data to serialize.
+        :return: The serialized form of data.
+        """
+        if obj is None:
+            return None
+        elif isinstance(obj, self.PRIMITIVE_TYPES):
+            return obj
+        elif isinstance(obj, list):
+            return [self.sanitize_for_serialization(sub_obj)
+                    for sub_obj in obj]
+        elif isinstance(obj, tuple):
+            return tuple(self.sanitize_for_serialization(sub_obj)
+                         for sub_obj in obj)
+        elif isinstance(obj, (datetime.datetime, datetime.date)):
+            return obj.isoformat()
+
+        if isinstance(obj, dict):
+            obj_dict = obj
+        else:
+            # Convert model obj to dict except
+            # attributes `swagger_types`, `attribute_map`
+            # and attributes which value is not None.
+            # Convert attribute name to json key in
+            # model definition for request.
+            obj_dict = {obj.attribute_map[attr]: getattr(obj, attr)
+                        for attr, _ in six.iteritems(obj.swagger_types)
+                        if getattr(obj, attr) is not None}
+
+        return {key: self.sanitize_for_serialization(val)
+                for key, val in six.iteritems(obj_dict)}
+
+    def deserialize(self, response, response_type):
+        """Deserializes response into an object.
+
+        :param response: RESTResponse object to be deserialized.
+        :param response_type: class literal for
+            deserialized object, or string of class name.
+
+        :return: deserialized object.
+        """
+        # handle file downloading
+        # save response body into a tmp file and return the instance
+        if response_type == "file":
+            return self.__deserialize_file(response)
+
+        # fetch data from response object
+        try:
+            data = json.loads(response.data)
+        except ValueError:
+            data = response.data
+
+        return self.__deserialize(data, response_type)
+
+    def __deserialize(self, data, klass):
+        """Deserializes dict, list, str into an object.
+
+        :param data: dict, list or str.
+        :param klass: class literal, or string of class name.
+
+        :return: object.
+        """
+        if data is None:
+            return None
+
+        if type(klass) == str:
+            if klass.startswith('list['):
+                sub_kls = re.match(r'list\[(.*)\]', klass).group(1)
+                return [self.__deserialize(sub_data, sub_kls)
+                        for sub_data in data]
+
+            if klass.startswith('dict('):
+                sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2)
+                return {k: self.__deserialize(v, sub_kls)
+                        for k, v in six.iteritems(data)}
+
+            # convert str to class
+            if klass in self.NATIVE_TYPES_MAPPING:
+                klass = self.NATIVE_TYPES_MAPPING[klass]
+            else:
+                klass = getattr(ricxappframe.subsclient.models, klass)
+
+        if klass in self.PRIMITIVE_TYPES:
+            return self.__deserialize_primitive(data, klass)
+        elif klass == object:
+            return self.__deserialize_object(data)
+        elif klass == datetime.date:
+            return self.__deserialize_date(data)
+        elif klass == datetime.datetime:
+            return self.__deserialize_datatime(data)
+        else:
+            return self.__deserialize_model(data, klass)
+
+    def call_api(self, resource_path, method,
+                 path_params=None, query_params=None, header_params=None,
+                 body=None, post_params=None, files=None,
+                 response_type=None, auth_settings=None, async_req=None,
+                 _return_http_data_only=None, collection_formats=None,
+                 _preload_content=True, _request_timeout=None):
+        """Makes the HTTP request (synchronous) and returns deserialized data.
+
+        To make an async request, set the async_req parameter.
+
+        :param resource_path: Path to method endpoint.
+        :param method: Method to call.
+        :param path_params: Path parameters in the url.
+        :param query_params: Query parameters in the url.
+        :param header_params: Header parameters to be
+            placed in the request header.
+        :param body: Request body.
+        :param post_params dict: Request post form parameters,
+            for `application/x-www-form-urlencoded`, `multipart/form-data`.
+        :param auth_settings list: Auth Settings names for the request.
+        :param response: Response data type.
+        :param files dict: key -> filename, value -> filepath,
+            for `multipart/form-data`.
+        :param async_req bool: execute request asynchronously
+        :param _return_http_data_only: response data without head status code
+                                       and headers
+        :param collection_formats: dict of collection formats for path, query,
+            header, and post parameters.
+        :param _preload_content: if False, the urllib3.HTTPResponse object will
+                                 be returned without reading/decoding response
+                                 data. Default is True.
+        :param _request_timeout: timeout setting for this request. If one
+                                 number provided, it will be total request
+                                 timeout. It can also be a pair (tuple) of
+                                 (connection, read) timeouts.
+        :return:
+            If async_req parameter is True,
+            the request will be called asynchronously.
+            The method will return the request thread.
+            If parameter async_req is False or missing,
+            then the method will return the response directly.
+        """
+        if not async_req:
+            return self.__call_api(resource_path, method,
+                                   path_params, query_params, header_params,
+                                   body, post_params, files,
+                                   response_type, auth_settings,
+                                   _return_http_data_only, collection_formats,
+                                   _preload_content, _request_timeout)
+        else:
+            thread = self.pool.apply_async(self.__call_api, (resource_path,
+                                           method, path_params, query_params,
+                                           header_params, body,
+                                           post_params, files,
+                                           response_type, auth_settings,
+                                           _return_http_data_only,
+                                           collection_formats,
+                                           _preload_content, _request_timeout))
+        return thread
+
+    def request(self, method, url, query_params=None, headers=None,
+                post_params=None, body=None, _preload_content=True,
+                _request_timeout=None):
+        """Makes the HTTP request using RESTClient."""
+        if method == "GET":
+            return self.rest_client.GET(url,
+                                        query_params=query_params,
+                                        _preload_content=_preload_content,
+                                        _request_timeout=_request_timeout,
+                                        headers=headers)
+        elif method == "HEAD":
+            return self.rest_client.HEAD(url,
+                                         query_params=query_params,
+                                         _preload_content=_preload_content,
+                                         _request_timeout=_request_timeout,
+                                         headers=headers)
+        elif method == "OPTIONS":
+            return self.rest_client.OPTIONS(url,
+                                            query_params=query_params,
+                                            headers=headers,
+                                            post_params=post_params,
+                                            _preload_content=_preload_content,
+                                            _request_timeout=_request_timeout,
+                                            body=body)
+        elif method == "POST":
+            return self.rest_client.POST(url,
+                                         query_params=query_params,
+                                         headers=headers,
+                                         post_params=post_params,
+                                         _preload_content=_preload_content,
+                                         _request_timeout=_request_timeout,
+                                         body=body)
+        elif method == "PUT":
+            return self.rest_client.PUT(url,
+                                        query_params=query_params,
+                                        headers=headers,
+                                        post_params=post_params,
+                                        _preload_content=_preload_content,
+                                        _request_timeout=_request_timeout,
+                                        body=body)
+        elif method == "PATCH":
+            return self.rest_client.PATCH(url,
+                                          query_params=query_params,
+                                          headers=headers,
+                                          post_params=post_params,
+                                          _preload_content=_preload_content,
+                                          _request_timeout=_request_timeout,
+                                          body=body)
+        elif method == "DELETE":
+            return self.rest_client.DELETE(url,
+                                           query_params=query_params,
+                                           headers=headers,
+                                           _preload_content=_preload_content,
+                                           _request_timeout=_request_timeout,
+                                           body=body)
+        else:
+            raise ValueError(
+                "http method must be `GET`, `HEAD`, `OPTIONS`,"
+                " `POST`, `PATCH`, `PUT` or `DELETE`."
+            )
+
+    def parameters_to_tuples(self, params, collection_formats):
+        """Get parameters as list of tuples, formatting collections.
+
+        :param params: Parameters as dict or list of two-tuples
+        :param dict collection_formats: Parameter collection formats
+        :return: Parameters as list of tuples, collections formatted
+        """
+        new_params = []
+        if collection_formats is None:
+            collection_formats = {}
+        for k, v in six.iteritems(params) if isinstance(params, dict) else params:  # noqa: E501
+            if k in collection_formats:
+                collection_format = collection_formats[k]
+                if collection_format == 'multi':
+                    new_params.extend((k, value) for value in v)
+                else:
+                    if collection_format == 'ssv':
+                        delimiter = ' '
+                    elif collection_format == 'tsv':
+                        delimiter = '\t'
+                    elif collection_format == 'pipes':
+                        delimiter = '|'
+                    else:  # csv is the default
+                        delimiter = ','
+                    new_params.append(
+                        (k, delimiter.join(str(value) for value in v)))
+            else:
+                new_params.append((k, v))
+        return new_params
+
+    def prepare_post_parameters(self, post_params=None, files=None):
+        """Builds form parameters.
+
+        :param post_params: Normal form parameters.
+        :param files: File parameters.
+        :return: Form parameters with files.
+        """
+        params = []
+
+        if post_params:
+            params = post_params
+
+        if files:
+            for k, v in six.iteritems(files):
+                if not v:
+                    continue
+                file_names = v if type(v) is list else [v]
+                for n in file_names:
+                    with open(n, 'rb') as f:
+                        filename = os.path.basename(f.name)
+                        filedata = f.read()
+                        mimetype = (mimetypes.guess_type(filename)[0] or
+                                    'application/octet-stream')
+                        params.append(
+                            tuple([k, tuple([filename, filedata, mimetype])]))
+
+        return params
+
+    def select_header_accept(self, accepts):
+        """Returns `Accept` based on an array of accepts provided.
+
+        :param accepts: List of headers.
+        :return: Accept (e.g. application/json).
+        """
+        if not accepts:
+            return
+
+        accepts = [x.lower() for x in accepts]
+
+        if 'application/json' in accepts:
+            return 'application/json'
+        else:
+            return ', '.join(accepts)
+
+    def select_header_content_type(self, content_types):
+        """Returns `Content-Type` based on an array of content_types provided.
+
+        :param content_types: List of content-types.
+        :return: Content-Type (e.g. application/json).
+        """
+        if not content_types:
+            return 'application/json'
+
+        content_types = [x.lower() for x in content_types]
+
+        if 'application/json' in content_types or '*/*' in content_types:
+            return 'application/json'
+        else:
+            return content_types[0]
+
+    def update_params_for_auth(self, headers, querys, auth_settings):
+        """Updates header and query params based on authentication setting.
+
+        :param headers: Header parameters dict to be updated.
+        :param querys: Query parameters tuple list to be updated.
+        :param auth_settings: Authentication setting identifiers list.
+        """
+        if not auth_settings:
+            return
+
+        for auth in auth_settings:
+            auth_setting = self.configuration.auth_settings().get(auth)
+            if auth_setting:
+                if not auth_setting['value']:
+                    continue
+                elif auth_setting['in'] == 'header':
+                    headers[auth_setting['key']] = auth_setting['value']
+                elif auth_setting['in'] == 'query':
+                    querys.append((auth_setting['key'], auth_setting['value']))
+                else:
+                    raise ValueError(
+                        'Authentication token must be in `query` or `header`'
+                    )
+
+    def __deserialize_file(self, response):
+        """Deserializes body to file
+
+        Saves response body into a file in a temporary folder,
+        using the filename from the `Content-Disposition` header if provided.
+
+        :param response:  RESTResponse.
+        :return: file path.
+        """
+        fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
+        os.close(fd)
+        os.remove(path)
+
+        content_disposition = response.getheader("Content-Disposition")
+        if content_disposition:
+            filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
+                                 content_disposition).group(1)
+            path = os.path.join(os.path.dirname(path), filename)
+
+        with open(path, "w") as f:
+            f.write(response.data)
+
+        return path
+
+    def __deserialize_primitive(self, data, klass):
+        """Deserializes string to primitive type.
+
+        :param data: str.
+        :param klass: class literal.
+
+        :return: int, long, float, str, bool.
+        """
+        try:
+            return klass(data)
+        except UnicodeEncodeError:
+            return six.text_type(data)
+        except TypeError:
+            return data
+
+    def __deserialize_object(self, value):
+        """Return a original value.
+
+        :return: object.
+        """
+        return value
+
+    def __deserialize_date(self, string):
+        """Deserializes string to date.
+
+        :param string: str.
+        :return: date.
+        """
+        try:
+            from dateutil.parser import parse
+            return parse(string).date()
+        except ImportError:
+            return string
+        except ValueError:
+            raise rest.ApiException(
+                status=0,
+                reason="Failed to parse `{0}` as date object".format(string)
+            )
+
+    def __deserialize_datatime(self, string):
+        """Deserializes string to datetime.
+
+        The string should be in iso8601 datetime format.
+
+        :param string: str.
+        :return: datetime.
+        """
+        try:
+            from dateutil.parser import parse
+            return parse(string)
+        except ImportError:
+            return string
+        except ValueError:
+            raise rest.ApiException(
+                status=0,
+                reason=(
+                    "Failed to parse `{0}` as datetime object"
+                    .format(string)
+                )
+            )
+
+    def __hasattr(self, object, name):
+        return name in object.__class__.__dict__
+
+    def __deserialize_model(self, data, klass):
+        """Deserializes list or dict to model.
+
+        :param data: dict, list.
+        :param klass: class literal.
+        :return: model object.
+        """
+
+        if (not klass.swagger_types and
+                not self.__hasattr(klass, 'get_real_child_model')):
+            return data
+
+        kwargs = {}
+        if klass.swagger_types is not None:
+            for attr, attr_type in six.iteritems(klass.swagger_types):
+                if (data is not None and
+                        klass.attribute_map[attr] in data and
+                        isinstance(data, (list, dict))):
+                    value = data[klass.attribute_map[attr]]
+                    kwargs[attr] = self.__deserialize(value, attr_type)
+
+        instance = klass(**kwargs)
+
+        if (isinstance(instance, dict) and
+                klass.swagger_types is not None and
+                isinstance(data, dict)):
+            for key, value in data.items():
+                if key not in klass.swagger_types:
+                    instance[key] = value
+        if self.__hasattr(instance, 'get_real_child_model'):
+            klass_name = instance.get_real_child_model(data)
+            if klass_name:
+                instance = self.__deserialize(data, klass_name)
+        return instance
diff --git a/ricxappframe/subsclient/configuration.py b/ricxappframe/subsclient/configuration.py
new file mode 100644 (file)
index 0000000..1c4f6bf
--- /dev/null
@@ -0,0 +1,248 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+from __future__ import absolute_import
+
+import copy
+import logging
+import multiprocessing
+import sys
+import urllib3
+
+import six
+from six.moves import http_client as httplib
+
+
+class Configuration(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Ref: https://github.com/swagger-api/swagger-codegen
+    Do not edit the class manually.
+    """
+
+    _default = None
+
+    def __init__(self):
+        """Constructor"""
+        if self._default:
+            for key in self._default.__dict__.keys():
+                self.__dict__[key] = copy.copy(self._default.__dict__[key])
+            return
+
+        # Default Base url
+        self.host = "http://hostname/ric/v1"
+        # Temp file folder for downloading files
+        self.temp_folder_path = None
+
+        # Authentication Settings
+        # dict to store API key(s)
+        self.api_key = {}
+        # dict to store API prefix (e.g. Bearer)
+        self.api_key_prefix = {}
+        # function to refresh API key if expired
+        self.refresh_api_key_hook = None
+        # Username for HTTP basic authentication
+        self.username = ""
+        # Password for HTTP basic authentication
+        self.password = ""
+
+        # Logging Settings
+        self.logger = {}
+        self.logger["package_logger"] = logging.getLogger("ricxappframe.subsclient")
+        self.logger["urllib3_logger"] = logging.getLogger("urllib3")
+        # Log format
+        self.logger_format = '%(asctime)s %(levelname)s %(message)s'
+        # Log stream handler
+        self.logger_stream_handler = None
+        # Log file handler
+        self.logger_file_handler = None
+        # Debug file location
+        self.logger_file = None
+        # Debug switch
+        self.debug = False
+
+        # SSL/TLS verification
+        # Set this to false to skip verifying SSL certificate when calling API
+        # from https server.
+        self.verify_ssl = True
+        # Set this to customize the certificate file to verify the peer.
+        self.ssl_ca_cert = None
+        # client certificate file
+        self.cert_file = None
+        # client key file
+        self.key_file = None
+        # Set this to True/False to enable/disable SSL hostname verification.
+        self.assert_hostname = None
+
+        # urllib3 connection pool's maximum number of connections saved
+        # per pool. urllib3 uses 1 connection as default value, but this is
+        # not the best value when you are making a lot of possibly parallel
+        # requests to the same host, which is often the case here.
+        # cpu_count * 5 is used as default value to increase performance.
+        self.connection_pool_maxsize = multiprocessing.cpu_count() * 5
+
+        # Proxy URL
+        self.proxy = None
+        # Safe chars for path_param
+        self.safe_chars_for_path_param = ''
+
+        # Disable client side validation
+        self.client_side_validation = True
+
+    @classmethod
+    def set_default(cls, default):
+        cls._default = default
+
+    @property
+    def logger_file(self):
+        """The logger file.
+
+        If the logger_file is None, then add stream handler and remove file
+        handler. Otherwise, add file handler and remove stream handler.
+
+        :param value: The logger_file path.
+        :type: str
+        """
+        return self.__logger_file
+
+    @logger_file.setter
+    def logger_file(self, value):
+        """The logger file.
+
+        If the logger_file is None, then add stream handler and remove file
+        handler. Otherwise, add file handler and remove stream handler.
+
+        :param value: The logger_file path.
+        :type: str
+        """
+        self.__logger_file = value
+        if self.__logger_file:
+            # If set logging file,
+            # then add file handler and remove stream handler.
+            self.logger_file_handler = logging.FileHandler(self.__logger_file)
+            self.logger_file_handler.setFormatter(self.logger_formatter)
+            for _, logger in six.iteritems(self.logger):
+                logger.addHandler(self.logger_file_handler)
+                if self.logger_stream_handler:
+                    logger.removeHandler(self.logger_stream_handler)
+        else:
+            # If not set logging file,
+            # then add stream handler and remove file handler.
+            self.logger_stream_handler = logging.StreamHandler()
+            self.logger_stream_handler.setFormatter(self.logger_formatter)
+            for _, logger in six.iteritems(self.logger):
+                logger.addHandler(self.logger_stream_handler)
+                if self.logger_file_handler:
+                    logger.removeHandler(self.logger_file_handler)
+
+    @property
+    def debug(self):
+        """Debug status
+
+        :param value: The debug status, True or False.
+        :type: bool
+        """
+        return self.__debug
+
+    @debug.setter
+    def debug(self, value):
+        """Debug status
+
+        :param value: The debug status, True or False.
+        :type: bool
+        """
+        self.__debug = value
+        if self.__debug:
+            # if debug status is True, turn on debug logging
+            for _, logger in six.iteritems(self.logger):
+                logger.setLevel(logging.DEBUG)
+            # turn on httplib debug
+            httplib.HTTPConnection.debuglevel = 1
+        else:
+            # if debug status is False, turn off debug logging,
+            # setting log level to default `logging.WARNING`
+            for _, logger in six.iteritems(self.logger):
+                logger.setLevel(logging.WARNING)
+            # turn off httplib debug
+            httplib.HTTPConnection.debuglevel = 0
+
+    @property
+    def logger_format(self):
+        """The logger format.
+
+        The logger_formatter will be updated when sets logger_format.
+
+        :param value: The format string.
+        :type: str
+        """
+        return self.__logger_format
+
+    @logger_format.setter
+    def logger_format(self, value):
+        """The logger format.
+
+        The logger_formatter will be updated when sets logger_format.
+
+        :param value: The format string.
+        :type: str
+        """
+        self.__logger_format = value
+        self.logger_formatter = logging.Formatter(self.__logger_format)
+
+    def get_api_key_with_prefix(self, identifier):
+        """Gets API key (with prefix if set).
+
+        :param identifier: The identifier of apiKey.
+        :return: The token for api key authentication.
+        """
+
+        if self.refresh_api_key_hook:
+            self.refresh_api_key_hook(self)
+
+        key = self.api_key.get(identifier)
+        if key:
+            prefix = self.api_key_prefix.get(identifier)
+            if prefix:
+                return "%s %s" % (prefix, key)
+            else:
+                return key
+
+    def get_basic_auth_token(self):
+        """Gets HTTP basic authentication header (string).
+
+        :return: The token for basic HTTP authentication.
+        """
+        return urllib3.util.make_headers(
+            basic_auth=self.username + ':' + self.password
+        ).get('authorization')
+
+    def auth_settings(self):
+        """Gets Auth Settings dict for api client.
+
+        :return: The Auth Settings information dict.
+        """
+        return {
+
+        }
+
+    def to_debug_report(self):
+        """Gets the essential information for debugging.
+
+        :return: The report for debugging.
+        """
+        return "Python SDK Debug Report:\n"\
+               "OS: {env}\n"\
+               "Python Version: {pyversion}\n"\
+               "Version of the API: 0.0.4\n"\
+               "SDK Package Version: 1.0.0".\
+               format(env=sys.platform, pyversion=sys.version)
diff --git a/ricxappframe/subsclient/models/__init__.py b/ricxappframe/subsclient/models/__init__.py
new file mode 100644 (file)
index 0000000..82505c6
--- /dev/null
@@ -0,0 +1,34 @@
+# coding: utf-8
+
+# flake8: noqa
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+from __future__ import absolute_import
+
+# import models into model package
+from ricxappframe.subsclient.models.action_definition import ActionDefinition
+from ricxappframe.subsclient.models.action_to_be_setup import ActionToBeSetup
+from ricxappframe.subsclient.models.actions_to_be_setup import ActionsToBeSetup
+from ricxappframe.subsclient.models.config_metadata import ConfigMetadata
+from ricxappframe.subsclient.models.event_trigger_definition import EventTriggerDefinition
+from ricxappframe.subsclient.models.subscription_data import SubscriptionData
+from ricxappframe.subsclient.models.subscription_detail import SubscriptionDetail
+from ricxappframe.subsclient.models.subscription_details_list import SubscriptionDetailsList
+from ricxappframe.subsclient.models.subscription_instance import SubscriptionInstance
+from ricxappframe.subsclient.models.subscription_list import SubscriptionList
+from ricxappframe.subsclient.models.subscription_params import SubscriptionParams
+from ricxappframe.subsclient.models.subscription_params_client_endpoint import SubscriptionParamsClientEndpoint
+from ricxappframe.subsclient.models.subscription_params_e2_subscription_directives import SubscriptionParamsE2SubscriptionDirectives
+from ricxappframe.subsclient.models.subscription_response import SubscriptionResponse
+from ricxappframe.subsclient.models.subsequent_action import SubsequentAction
+from ricxappframe.subsclient.models.x_app_config import XAppConfig
+from ricxappframe.subsclient.models.xapp_config_list import XappConfigList
diff --git a/ricxappframe/subsclient/models/action_definition.py b/ricxappframe/subsclient/models/action_definition.py
new file mode 100644 (file)
index 0000000..b13f316
--- /dev/null
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class ActionDefinition(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+    }
+
+    attribute_map = {
+    }
+
+    def __init__(self, _configuration=None):  # noqa: E501
+        """ActionDefinition - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+        self.discriminator = None
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(ActionDefinition, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, ActionDefinition):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, ActionDefinition):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/action_to_be_setup.py b/ricxappframe/subsclient/models/action_to_be_setup.py
new file mode 100644 (file)
index 0000000..ba96c49
--- /dev/null
@@ -0,0 +1,216 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class ActionToBeSetup(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'action_id': 'int',
+        'action_type': 'str',
+        'action_definition': 'ActionDefinition',
+        'subsequent_action': 'SubsequentAction'
+    }
+
+    attribute_map = {
+        'action_id': 'ActionID',
+        'action_type': 'ActionType',
+        'action_definition': 'ActionDefinition',
+        'subsequent_action': 'SubsequentAction'
+    }
+
+    def __init__(self, action_id=None, action_type=None, action_definition=None, subsequent_action=None, _configuration=None):  # noqa: E501
+        """ActionToBeSetup - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._action_id = None
+        self._action_type = None
+        self._action_definition = None
+        self._subsequent_action = None
+        self.discriminator = None
+
+        self.action_id = action_id
+        self.action_type = action_type
+        if action_definition is not None:
+            self.action_definition = action_definition
+        if subsequent_action is not None:
+            self.subsequent_action = subsequent_action
+
+    @property
+    def action_id(self):
+        """Gets the action_id of this ActionToBeSetup.  # noqa: E501
+
+
+        :return: The action_id of this ActionToBeSetup.  # noqa: E501
+        :rtype: int
+        """
+        return self._action_id
+
+    @action_id.setter
+    def action_id(self, action_id):
+        """Sets the action_id of this ActionToBeSetup.
+
+
+        :param action_id: The action_id of this ActionToBeSetup.  # noqa: E501
+        :type: int
+        """
+        if self._configuration.client_side_validation and action_id is None:
+            raise ValueError("Invalid value for `action_id`, must not be `None`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                action_id is not None and action_id > 255):  # noqa: E501
+            raise ValueError("Invalid value for `action_id`, must be a value less than or equal to `255`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                action_id is not None and action_id < 0):  # noqa: E501
+            raise ValueError("Invalid value for `action_id`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._action_id = action_id
+
+    @property
+    def action_type(self):
+        """Gets the action_type of this ActionToBeSetup.  # noqa: E501
+
+
+        :return: The action_type of this ActionToBeSetup.  # noqa: E501
+        :rtype: str
+        """
+        return self._action_type
+
+    @action_type.setter
+    def action_type(self, action_type):
+        """Sets the action_type of this ActionToBeSetup.
+
+
+        :param action_type: The action_type of this ActionToBeSetup.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and action_type is None:
+            raise ValueError("Invalid value for `action_type`, must not be `None`")  # noqa: E501
+        allowed_values = ["insert", "policy", "report"]  # noqa: E501
+        if (self._configuration.client_side_validation and
+                action_type not in allowed_values):
+            raise ValueError(
+                "Invalid value for `action_type` ({0}), must be one of {1}"  # noqa: E501
+                .format(action_type, allowed_values)
+            )
+
+        self._action_type = action_type
+
+    @property
+    def action_definition(self):
+        """Gets the action_definition of this ActionToBeSetup.  # noqa: E501
+
+
+        :return: The action_definition of this ActionToBeSetup.  # noqa: E501
+        :rtype: ActionDefinition
+        """
+        return self._action_definition
+
+    @action_definition.setter
+    def action_definition(self, action_definition):
+        """Sets the action_definition of this ActionToBeSetup.
+
+
+        :param action_definition: The action_definition of this ActionToBeSetup.  # noqa: E501
+        :type: ActionDefinition
+        """
+
+        self._action_definition = action_definition
+
+    @property
+    def subsequent_action(self):
+        """Gets the subsequent_action of this ActionToBeSetup.  # noqa: E501
+
+
+        :return: The subsequent_action of this ActionToBeSetup.  # noqa: E501
+        :rtype: SubsequentAction
+        """
+        return self._subsequent_action
+
+    @subsequent_action.setter
+    def subsequent_action(self, subsequent_action):
+        """Sets the subsequent_action of this ActionToBeSetup.
+
+
+        :param subsequent_action: The subsequent_action of this ActionToBeSetup.  # noqa: E501
+        :type: SubsequentAction
+        """
+
+        self._subsequent_action = subsequent_action
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(ActionToBeSetup, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, ActionToBeSetup):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, ActionToBeSetup):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/actions_to_be_setup.py b/ricxappframe/subsclient/models/actions_to_be_setup.py
new file mode 100644 (file)
index 0000000..8116915
--- /dev/null
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class ActionsToBeSetup(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+    }
+
+    attribute_map = {
+    }
+
+    def __init__(self, _configuration=None):  # noqa: E501
+        """ActionsToBeSetup - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+        self.discriminator = None
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(ActionsToBeSetup, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, ActionsToBeSetup):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, ActionsToBeSetup):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/config_metadata.py b/ricxappframe/subsclient/models/config_metadata.py
new file mode 100644 (file)
index 0000000..df0925f
--- /dev/null
@@ -0,0 +1,162 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class ConfigMetadata(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'xapp_name': 'str',
+        'config_type': 'str'
+    }
+
+    attribute_map = {
+        'xapp_name': 'xappName',
+        'config_type': 'configType'
+    }
+
+    def __init__(self, xapp_name=None, config_type=None, _configuration=None):  # noqa: E501
+        """ConfigMetadata - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._xapp_name = None
+        self._config_type = None
+        self.discriminator = None
+
+        self.xapp_name = xapp_name
+        self.config_type = config_type
+
+    @property
+    def xapp_name(self):
+        """Gets the xapp_name of this ConfigMetadata.  # noqa: E501
+
+        Name of the xApp  # noqa: E501
+
+        :return: The xapp_name of this ConfigMetadata.  # noqa: E501
+        :rtype: str
+        """
+        return self._xapp_name
+
+    @xapp_name.setter
+    def xapp_name(self, xapp_name):
+        """Sets the xapp_name of this ConfigMetadata.
+
+        Name of the xApp  # noqa: E501
+
+        :param xapp_name: The xapp_name of this ConfigMetadata.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and xapp_name is None:
+            raise ValueError("Invalid value for `xapp_name`, must not be `None`")  # noqa: E501
+
+        self._xapp_name = xapp_name
+
+    @property
+    def config_type(self):
+        """Gets the config_type of this ConfigMetadata.  # noqa: E501
+
+        The type of the content  # noqa: E501
+
+        :return: The config_type of this ConfigMetadata.  # noqa: E501
+        :rtype: str
+        """
+        return self._config_type
+
+    @config_type.setter
+    def config_type(self, config_type):
+        """Sets the config_type of this ConfigMetadata.
+
+        The type of the content  # noqa: E501
+
+        :param config_type: The config_type of this ConfigMetadata.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and config_type is None:
+            raise ValueError("Invalid value for `config_type`, must not be `None`")  # noqa: E501
+        allowed_values = ["json", "xml", "other"]  # noqa: E501
+        if (self._configuration.client_side_validation and
+                config_type not in allowed_values):
+            raise ValueError(
+                "Invalid value for `config_type` ({0}), must be one of {1}"  # noqa: E501
+                .format(config_type, allowed_values)
+            )
+
+        self._config_type = config_type
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(ConfigMetadata, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, ConfigMetadata):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, ConfigMetadata):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/event_trigger_definition.py b/ricxappframe/subsclient/models/event_trigger_definition.py
new file mode 100644 (file)
index 0000000..5f71a65
--- /dev/null
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class EventTriggerDefinition(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+    }
+
+    attribute_map = {
+    }
+
+    def __init__(self, _configuration=None):  # noqa: E501
+        """EventTriggerDefinition - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+        self.discriminator = None
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(EventTriggerDefinition, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, EventTriggerDefinition):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, EventTriggerDefinition):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_data.py b/ricxappframe/subsclient/models/subscription_data.py
new file mode 100644 (file)
index 0000000..3fdb085
--- /dev/null
@@ -0,0 +1,201 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionData(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'subscription_id': 'int',
+        'meid': 'str',
+        'client_endpoint': 'list[str]',
+        'subscription_instances': 'list[SubscriptionInstance]'
+    }
+
+    attribute_map = {
+        'subscription_id': 'SubscriptionId',
+        'meid': 'Meid',
+        'client_endpoint': 'ClientEndpoint',
+        'subscription_instances': 'SubscriptionInstances'
+    }
+
+    def __init__(self, subscription_id=None, meid=None, client_endpoint=None, subscription_instances=None, _configuration=None):  # noqa: E501
+        """SubscriptionData - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._subscription_id = None
+        self._meid = None
+        self._client_endpoint = None
+        self._subscription_instances = None
+        self.discriminator = None
+
+        if subscription_id is not None:
+            self.subscription_id = subscription_id
+        if meid is not None:
+            self.meid = meid
+        if client_endpoint is not None:
+            self.client_endpoint = client_endpoint
+        if subscription_instances is not None:
+            self.subscription_instances = subscription_instances
+
+    @property
+    def subscription_id(self):
+        """Gets the subscription_id of this SubscriptionData.  # noqa: E501
+
+
+        :return: The subscription_id of this SubscriptionData.  # noqa: E501
+        :rtype: int
+        """
+        return self._subscription_id
+
+    @subscription_id.setter
+    def subscription_id(self, subscription_id):
+        """Sets the subscription_id of this SubscriptionData.
+
+
+        :param subscription_id: The subscription_id of this SubscriptionData.  # noqa: E501
+        :type: int
+        """
+
+        self._subscription_id = subscription_id
+
+    @property
+    def meid(self):
+        """Gets the meid of this SubscriptionData.  # noqa: E501
+
+
+        :return: The meid of this SubscriptionData.  # noqa: E501
+        :rtype: str
+        """
+        return self._meid
+
+    @meid.setter
+    def meid(self, meid):
+        """Sets the meid of this SubscriptionData.
+
+
+        :param meid: The meid of this SubscriptionData.  # noqa: E501
+        :type: str
+        """
+
+        self._meid = meid
+
+    @property
+    def client_endpoint(self):
+        """Gets the client_endpoint of this SubscriptionData.  # noqa: E501
+
+
+        :return: The client_endpoint of this SubscriptionData.  # noqa: E501
+        :rtype: list[str]
+        """
+        return self._client_endpoint
+
+    @client_endpoint.setter
+    def client_endpoint(self, client_endpoint):
+        """Sets the client_endpoint of this SubscriptionData.
+
+
+        :param client_endpoint: The client_endpoint of this SubscriptionData.  # noqa: E501
+        :type: list[str]
+        """
+
+        self._client_endpoint = client_endpoint
+
+    @property
+    def subscription_instances(self):
+        """Gets the subscription_instances of this SubscriptionData.  # noqa: E501
+
+
+        :return: The subscription_instances of this SubscriptionData.  # noqa: E501
+        :rtype: list[SubscriptionInstance]
+        """
+        return self._subscription_instances
+
+    @subscription_instances.setter
+    def subscription_instances(self, subscription_instances):
+        """Sets the subscription_instances of this SubscriptionData.
+
+
+        :param subscription_instances: The subscription_instances of this SubscriptionData.  # noqa: E501
+        :type: list[SubscriptionInstance]
+        """
+
+        self._subscription_instances = subscription_instances
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionData, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionData):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionData):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_detail.py b/ricxappframe/subsclient/models/subscription_detail.py
new file mode 100644 (file)
index 0000000..2657cdb
--- /dev/null
@@ -0,0 +1,184 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionDetail(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'xapp_event_instance_id': 'int',
+        'event_triggers': 'EventTriggerDefinition',
+        'action_to_be_setup_list': 'ActionsToBeSetup'
+    }
+
+    attribute_map = {
+        'xapp_event_instance_id': 'XappEventInstanceId',
+        'event_triggers': 'EventTriggers',
+        'action_to_be_setup_list': 'ActionToBeSetupList'
+    }
+
+    def __init__(self, xapp_event_instance_id=None, event_triggers=None, action_to_be_setup_list=None, _configuration=None):  # noqa: E501
+        """SubscriptionDetail - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._xapp_event_instance_id = None
+        self._event_triggers = None
+        self._action_to_be_setup_list = None
+        self.discriminator = None
+
+        self.xapp_event_instance_id = xapp_event_instance_id
+        self.event_triggers = event_triggers
+        self.action_to_be_setup_list = action_to_be_setup_list
+
+    @property
+    def xapp_event_instance_id(self):
+        """Gets the xapp_event_instance_id of this SubscriptionDetail.  # noqa: E501
+
+
+        :return: The xapp_event_instance_id of this SubscriptionDetail.  # noqa: E501
+        :rtype: int
+        """
+        return self._xapp_event_instance_id
+
+    @xapp_event_instance_id.setter
+    def xapp_event_instance_id(self, xapp_event_instance_id):
+        """Sets the xapp_event_instance_id of this SubscriptionDetail.
+
+
+        :param xapp_event_instance_id: The xapp_event_instance_id of this SubscriptionDetail.  # noqa: E501
+        :type: int
+        """
+        if self._configuration.client_side_validation and xapp_event_instance_id is None:
+            raise ValueError("Invalid value for `xapp_event_instance_id`, must not be `None`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                xapp_event_instance_id is not None and xapp_event_instance_id > 65535):  # noqa: E501
+            raise ValueError("Invalid value for `xapp_event_instance_id`, must be a value less than or equal to `65535`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                xapp_event_instance_id is not None and xapp_event_instance_id < 0):  # noqa: E501
+            raise ValueError("Invalid value for `xapp_event_instance_id`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._xapp_event_instance_id = xapp_event_instance_id
+
+    @property
+    def event_triggers(self):
+        """Gets the event_triggers of this SubscriptionDetail.  # noqa: E501
+
+
+        :return: The event_triggers of this SubscriptionDetail.  # noqa: E501
+        :rtype: EventTriggerDefinition
+        """
+        return self._event_triggers
+
+    @event_triggers.setter
+    def event_triggers(self, event_triggers):
+        """Sets the event_triggers of this SubscriptionDetail.
+
+
+        :param event_triggers: The event_triggers of this SubscriptionDetail.  # noqa: E501
+        :type: EventTriggerDefinition
+        """
+        if self._configuration.client_side_validation and event_triggers is None:
+            raise ValueError("Invalid value for `event_triggers`, must not be `None`")  # noqa: E501
+
+        self._event_triggers = event_triggers
+
+    @property
+    def action_to_be_setup_list(self):
+        """Gets the action_to_be_setup_list of this SubscriptionDetail.  # noqa: E501
+
+
+        :return: The action_to_be_setup_list of this SubscriptionDetail.  # noqa: E501
+        :rtype: ActionsToBeSetup
+        """
+        return self._action_to_be_setup_list
+
+    @action_to_be_setup_list.setter
+    def action_to_be_setup_list(self, action_to_be_setup_list):
+        """Sets the action_to_be_setup_list of this SubscriptionDetail.
+
+
+        :param action_to_be_setup_list: The action_to_be_setup_list of this SubscriptionDetail.  # noqa: E501
+        :type: ActionsToBeSetup
+        """
+        if self._configuration.client_side_validation and action_to_be_setup_list is None:
+            raise ValueError("Invalid value for `action_to_be_setup_list`, must not be `None`")  # noqa: E501
+
+        self._action_to_be_setup_list = action_to_be_setup_list
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionDetail, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionDetail):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionDetail):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_details_list.py b/ricxappframe/subsclient/models/subscription_details_list.py
new file mode 100644 (file)
index 0000000..eb0c237
--- /dev/null
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionDetailsList(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+    }
+
+    attribute_map = {
+    }
+
+    def __init__(self, _configuration=None):  # noqa: E501
+        """SubscriptionDetailsList - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+        self.discriminator = None
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionDetailsList, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionDetailsList):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionDetailsList):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_instance.py b/ricxappframe/subsclient/models/subscription_instance.py
new file mode 100644 (file)
index 0000000..df8d00f
--- /dev/null
@@ -0,0 +1,261 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionInstance(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'xapp_event_instance_id': 'int',
+        'e2_event_instance_id': 'int',
+        'error_cause': 'str',
+        'error_source': 'str',
+        'timeout_type': 'str'
+    }
+
+    attribute_map = {
+        'xapp_event_instance_id': 'XappEventInstanceId',
+        'e2_event_instance_id': 'E2EventInstanceId',
+        'error_cause': 'ErrorCause',
+        'error_source': 'ErrorSource',
+        'timeout_type': 'TimeoutType'
+    }
+
+    def __init__(self, xapp_event_instance_id=None, e2_event_instance_id=None, error_cause=None, error_source=None, timeout_type=None, _configuration=None):  # noqa: E501
+        """SubscriptionInstance - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._xapp_event_instance_id = None
+        self._e2_event_instance_id = None
+        self._error_cause = None
+        self._error_source = None
+        self._timeout_type = None
+        self.discriminator = None
+
+        self.xapp_event_instance_id = xapp_event_instance_id
+        self.e2_event_instance_id = e2_event_instance_id
+        if error_cause is not None:
+            self.error_cause = error_cause
+        if error_source is not None:
+            self.error_source = error_source
+        if timeout_type is not None:
+            self.timeout_type = timeout_type
+
+    @property
+    def xapp_event_instance_id(self):
+        """Gets the xapp_event_instance_id of this SubscriptionInstance.  # noqa: E501
+
+
+        :return: The xapp_event_instance_id of this SubscriptionInstance.  # noqa: E501
+        :rtype: int
+        """
+        return self._xapp_event_instance_id
+
+    @xapp_event_instance_id.setter
+    def xapp_event_instance_id(self, xapp_event_instance_id):
+        """Sets the xapp_event_instance_id of this SubscriptionInstance.
+
+
+        :param xapp_event_instance_id: The xapp_event_instance_id of this SubscriptionInstance.  # noqa: E501
+        :type: int
+        """
+        if self._configuration.client_side_validation and xapp_event_instance_id is None:
+            raise ValueError("Invalid value for `xapp_event_instance_id`, must not be `None`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                xapp_event_instance_id is not None and xapp_event_instance_id > 65535):  # noqa: E501
+            raise ValueError("Invalid value for `xapp_event_instance_id`, must be a value less than or equal to `65535`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                xapp_event_instance_id is not None and xapp_event_instance_id < 0):  # noqa: E501
+            raise ValueError("Invalid value for `xapp_event_instance_id`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._xapp_event_instance_id = xapp_event_instance_id
+
+    @property
+    def e2_event_instance_id(self):
+        """Gets the e2_event_instance_id of this SubscriptionInstance.  # noqa: E501
+
+
+        :return: The e2_event_instance_id of this SubscriptionInstance.  # noqa: E501
+        :rtype: int
+        """
+        return self._e2_event_instance_id
+
+    @e2_event_instance_id.setter
+    def e2_event_instance_id(self, e2_event_instance_id):
+        """Sets the e2_event_instance_id of this SubscriptionInstance.
+
+
+        :param e2_event_instance_id: The e2_event_instance_id of this SubscriptionInstance.  # noqa: E501
+        :type: int
+        """
+        if self._configuration.client_side_validation and e2_event_instance_id is None:
+            raise ValueError("Invalid value for `e2_event_instance_id`, must not be `None`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                e2_event_instance_id is not None and e2_event_instance_id > 65535):  # noqa: E501
+            raise ValueError("Invalid value for `e2_event_instance_id`, must be a value less than or equal to `65535`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                e2_event_instance_id is not None and e2_event_instance_id < 0):  # noqa: E501
+            raise ValueError("Invalid value for `e2_event_instance_id`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._e2_event_instance_id = e2_event_instance_id
+
+    @property
+    def error_cause(self):
+        """Gets the error_cause of this SubscriptionInstance.  # noqa: E501
+
+        Descriptive error cause. Empty string when no error.  # noqa: E501
+
+        :return: The error_cause of this SubscriptionInstance.  # noqa: E501
+        :rtype: str
+        """
+        return self._error_cause
+
+    @error_cause.setter
+    def error_cause(self, error_cause):
+        """Sets the error_cause of this SubscriptionInstance.
+
+        Descriptive error cause. Empty string when no error.  # noqa: E501
+
+        :param error_cause: The error_cause of this SubscriptionInstance.  # noqa: E501
+        :type: str
+        """
+
+        self._error_cause = error_cause
+
+    @property
+    def error_source(self):
+        """Gets the error_source of this SubscriptionInstance.  # noqa: E501
+
+        Source of error cause.  # noqa: E501
+
+        :return: The error_source of this SubscriptionInstance.  # noqa: E501
+        :rtype: str
+        """
+        return self._error_source
+
+    @error_source.setter
+    def error_source(self, error_source):
+        """Sets the error_source of this SubscriptionInstance.
+
+        Source of error cause.  # noqa: E501
+
+        :param error_source: The error_source of this SubscriptionInstance.  # noqa: E501
+        :type: str
+        """
+        allowed_values = ["SUBMGR", "RTMGR", "DBAAS", "ASN1", "E2Node"]  # noqa: E501
+        if (self._configuration.client_side_validation and
+                error_source not in allowed_values):
+            raise ValueError(
+                "Invalid value for `error_source` ({0}), must be one of {1}"  # noqa: E501
+                .format(error_source, allowed_values)
+            )
+
+        self._error_source = error_source
+
+    @property
+    def timeout_type(self):
+        """Gets the timeout_type of this SubscriptionInstance.  # noqa: E501
+
+        Type timeout. xApp should retry if timeout occurs.  # noqa: E501
+
+        :return: The timeout_type of this SubscriptionInstance.  # noqa: E501
+        :rtype: str
+        """
+        return self._timeout_type
+
+    @timeout_type.setter
+    def timeout_type(self, timeout_type):
+        """Sets the timeout_type of this SubscriptionInstance.
+
+        Type timeout. xApp should retry if timeout occurs.  # noqa: E501
+
+        :param timeout_type: The timeout_type of this SubscriptionInstance.  # noqa: E501
+        :type: str
+        """
+        allowed_values = ["E2-Timeout", "RTMGR-Timeout", "DBAAS-Timeout"]  # noqa: E501
+        if (self._configuration.client_side_validation and
+                timeout_type not in allowed_values):
+            raise ValueError(
+                "Invalid value for `timeout_type` ({0}), must be one of {1}"  # noqa: E501
+                .format(timeout_type, allowed_values)
+            )
+
+        self._timeout_type = timeout_type
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionInstance, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionInstance):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionInstance):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_list.py b/ricxappframe/subsclient/models/subscription_list.py
new file mode 100644 (file)
index 0000000..f4fba1b
--- /dev/null
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionList(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+    }
+
+    attribute_map = {
+    }
+
+    def __init__(self, _configuration=None):  # noqa: E501
+        """SubscriptionList - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+        self.discriminator = None
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionList, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionList):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionList):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_params.py b/ricxappframe/subsclient/models/subscription_params.py
new file mode 100644 (file)
index 0000000..18b89ca
--- /dev/null
@@ -0,0 +1,265 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionParams(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'subscription_id': 'str',
+        'client_endpoint': 'SubscriptionParamsClientEndpoint',
+        'meid': 'str',
+        'ran_function_id': 'int',
+        'e2_subscription_directives': 'SubscriptionParamsE2SubscriptionDirectives',
+        'subscription_details': 'SubscriptionDetailsList'
+    }
+
+    attribute_map = {
+        'subscription_id': 'SubscriptionId',
+        'client_endpoint': 'ClientEndpoint',
+        'meid': 'Meid',
+        'ran_function_id': 'RANFunctionID',
+        'e2_subscription_directives': 'E2SubscriptionDirectives',
+        'subscription_details': 'SubscriptionDetails'
+    }
+
+    def __init__(self, subscription_id=None, client_endpoint=None, meid=None, ran_function_id=None, e2_subscription_directives=None, subscription_details=None, _configuration=None):  # noqa: E501
+        """SubscriptionParams - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._subscription_id = None
+        self._client_endpoint = None
+        self._meid = None
+        self._ran_function_id = None
+        self._e2_subscription_directives = None
+        self._subscription_details = None
+        self.discriminator = None
+
+        if subscription_id is not None:
+            self.subscription_id = subscription_id
+        self.client_endpoint = client_endpoint
+        self.meid = meid
+        self.ran_function_id = ran_function_id
+        if e2_subscription_directives is not None:
+            self.e2_subscription_directives = e2_subscription_directives
+        self.subscription_details = subscription_details
+
+    @property
+    def subscription_id(self):
+        """Gets the subscription_id of this SubscriptionParams.  # noqa: E501
+
+        Optional subscription ID (Submgr allocates if not given)  # noqa: E501
+
+        :return: The subscription_id of this SubscriptionParams.  # noqa: E501
+        :rtype: str
+        """
+        return self._subscription_id
+
+    @subscription_id.setter
+    def subscription_id(self, subscription_id):
+        """Sets the subscription_id of this SubscriptionParams.
+
+        Optional subscription ID (Submgr allocates if not given)  # noqa: E501
+
+        :param subscription_id: The subscription_id of this SubscriptionParams.  # noqa: E501
+        :type: str
+        """
+
+        self._subscription_id = subscription_id
+
+    @property
+    def client_endpoint(self):
+        """Gets the client_endpoint of this SubscriptionParams.  # noqa: E501
+
+
+        :return: The client_endpoint of this SubscriptionParams.  # noqa: E501
+        :rtype: SubscriptionParamsClientEndpoint
+        """
+        return self._client_endpoint
+
+    @client_endpoint.setter
+    def client_endpoint(self, client_endpoint):
+        """Sets the client_endpoint of this SubscriptionParams.
+
+
+        :param client_endpoint: The client_endpoint of this SubscriptionParams.  # noqa: E501
+        :type: SubscriptionParamsClientEndpoint
+        """
+        if self._configuration.client_side_validation and client_endpoint is None:
+            raise ValueError("Invalid value for `client_endpoint`, must not be `None`")  # noqa: E501
+
+        self._client_endpoint = client_endpoint
+
+    @property
+    def meid(self):
+        """Gets the meid of this SubscriptionParams.  # noqa: E501
+
+
+        :return: The meid of this SubscriptionParams.  # noqa: E501
+        :rtype: str
+        """
+        return self._meid
+
+    @meid.setter
+    def meid(self, meid):
+        """Sets the meid of this SubscriptionParams.
+
+
+        :param meid: The meid of this SubscriptionParams.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and meid is None:
+            raise ValueError("Invalid value for `meid`, must not be `None`")  # noqa: E501
+
+        self._meid = meid
+
+    @property
+    def ran_function_id(self):
+        """Gets the ran_function_id of this SubscriptionParams.  # noqa: E501
+
+
+        :return: The ran_function_id of this SubscriptionParams.  # noqa: E501
+        :rtype: int
+        """
+        return self._ran_function_id
+
+    @ran_function_id.setter
+    def ran_function_id(self, ran_function_id):
+        """Sets the ran_function_id of this SubscriptionParams.
+
+
+        :param ran_function_id: The ran_function_id of this SubscriptionParams.  # noqa: E501
+        :type: int
+        """
+        if self._configuration.client_side_validation and ran_function_id is None:
+            raise ValueError("Invalid value for `ran_function_id`, must not be `None`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                ran_function_id is not None and ran_function_id > 4095):  # noqa: E501
+            raise ValueError("Invalid value for `ran_function_id`, must be a value less than or equal to `4095`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                ran_function_id is not None and ran_function_id < 0):  # noqa: E501
+            raise ValueError("Invalid value for `ran_function_id`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._ran_function_id = ran_function_id
+
+    @property
+    def e2_subscription_directives(self):
+        """Gets the e2_subscription_directives of this SubscriptionParams.  # noqa: E501
+
+
+        :return: The e2_subscription_directives of this SubscriptionParams.  # noqa: E501
+        :rtype: SubscriptionParamsE2SubscriptionDirectives
+        """
+        return self._e2_subscription_directives
+
+    @e2_subscription_directives.setter
+    def e2_subscription_directives(self, e2_subscription_directives):
+        """Sets the e2_subscription_directives of this SubscriptionParams.
+
+
+        :param e2_subscription_directives: The e2_subscription_directives of this SubscriptionParams.  # noqa: E501
+        :type: SubscriptionParamsE2SubscriptionDirectives
+        """
+
+        self._e2_subscription_directives = e2_subscription_directives
+
+    @property
+    def subscription_details(self):
+        """Gets the subscription_details of this SubscriptionParams.  # noqa: E501
+
+
+        :return: The subscription_details of this SubscriptionParams.  # noqa: E501
+        :rtype: SubscriptionDetailsList
+        """
+        return self._subscription_details
+
+    @subscription_details.setter
+    def subscription_details(self, subscription_details):
+        """Sets the subscription_details of this SubscriptionParams.
+
+
+        :param subscription_details: The subscription_details of this SubscriptionParams.  # noqa: E501
+        :type: SubscriptionDetailsList
+        """
+        if self._configuration.client_side_validation and subscription_details is None:
+            raise ValueError("Invalid value for `subscription_details`, must not be `None`")  # noqa: E501
+
+        self._subscription_details = subscription_details
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionParams, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionParams):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionParams):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_params_client_endpoint.py b/ricxappframe/subsclient/models/subscription_params_client_endpoint.py
new file mode 100644 (file)
index 0000000..4521653
--- /dev/null
@@ -0,0 +1,193 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionParamsClientEndpoint(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'host': 'str',
+        'http_port': 'int',
+        'rmr_port': 'int'
+    }
+
+    attribute_map = {
+        'host': 'Host',
+        'http_port': 'HTTPPort',
+        'rmr_port': 'RMRPort'
+    }
+
+    def __init__(self, host=None, http_port=None, rmr_port=None, _configuration=None):  # noqa: E501
+        """SubscriptionParamsClientEndpoint - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._host = None
+        self._http_port = None
+        self._rmr_port = None
+        self.discriminator = None
+
+        if host is not None:
+            self.host = host
+        if http_port is not None:
+            self.http_port = http_port
+        if rmr_port is not None:
+            self.rmr_port = rmr_port
+
+    @property
+    def host(self):
+        """Gets the host of this SubscriptionParamsClientEndpoint.  # noqa: E501
+
+        xApp service address name like 'service-ricxapp-xappname-http.ricxapp'  # noqa: E501
+
+        :return: The host of this SubscriptionParamsClientEndpoint.  # noqa: E501
+        :rtype: str
+        """
+        return self._host
+
+    @host.setter
+    def host(self, host):
+        """Sets the host of this SubscriptionParamsClientEndpoint.
+
+        xApp service address name like 'service-ricxapp-xappname-http.ricxapp'  # noqa: E501
+
+        :param host: The host of this SubscriptionParamsClientEndpoint.  # noqa: E501
+        :type: str
+        """
+
+        self._host = host
+
+    @property
+    def http_port(self):
+        """Gets the http_port of this SubscriptionParamsClientEndpoint.  # noqa: E501
+
+        xApp HTTP service address port  # noqa: E501
+
+        :return: The http_port of this SubscriptionParamsClientEndpoint.  # noqa: E501
+        :rtype: int
+        """
+        return self._http_port
+
+    @http_port.setter
+    def http_port(self, http_port):
+        """Sets the http_port of this SubscriptionParamsClientEndpoint.
+
+        xApp HTTP service address port  # noqa: E501
+
+        :param http_port: The http_port of this SubscriptionParamsClientEndpoint.  # noqa: E501
+        :type: int
+        """
+        if (self._configuration.client_side_validation and
+                http_port is not None and http_port > 65535):  # noqa: E501
+            raise ValueError("Invalid value for `http_port`, must be a value less than or equal to `65535`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                http_port is not None and http_port < 0):  # noqa: E501
+            raise ValueError("Invalid value for `http_port`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._http_port = http_port
+
+    @property
+    def rmr_port(self):
+        """Gets the rmr_port of this SubscriptionParamsClientEndpoint.  # noqa: E501
+
+        xApp RMR service address port  # noqa: E501
+
+        :return: The rmr_port of this SubscriptionParamsClientEndpoint.  # noqa: E501
+        :rtype: int
+        """
+        return self._rmr_port
+
+    @rmr_port.setter
+    def rmr_port(self, rmr_port):
+        """Sets the rmr_port of this SubscriptionParamsClientEndpoint.
+
+        xApp RMR service address port  # noqa: E501
+
+        :param rmr_port: The rmr_port of this SubscriptionParamsClientEndpoint.  # noqa: E501
+        :type: int
+        """
+        if (self._configuration.client_side_validation and
+                rmr_port is not None and rmr_port > 65535):  # noqa: E501
+            raise ValueError("Invalid value for `rmr_port`, must be a value less than or equal to `65535`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                rmr_port is not None and rmr_port < 0):  # noqa: E501
+            raise ValueError("Invalid value for `rmr_port`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._rmr_port = rmr_port
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionParamsClientEndpoint, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionParamsClientEndpoint):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionParamsClientEndpoint):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_params_e2_subscription_directives.py b/ricxappframe/subsclient/models/subscription_params_e2_subscription_directives.py
new file mode 100644 (file)
index 0000000..74cf43c
--- /dev/null
@@ -0,0 +1,193 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionParamsE2SubscriptionDirectives(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'e2_timeout_timer_value': 'int',
+        'e2_retry_count': 'int',
+        'rmr_routing_needed': 'bool'
+    }
+
+    attribute_map = {
+        'e2_timeout_timer_value': 'E2TimeoutTimerValue',
+        'e2_retry_count': 'E2RetryCount',
+        'rmr_routing_needed': 'RMRRoutingNeeded'
+    }
+
+    def __init__(self, e2_timeout_timer_value=None, e2_retry_count=None, rmr_routing_needed=None, _configuration=None):  # noqa: E501
+        """SubscriptionParamsE2SubscriptionDirectives - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._e2_timeout_timer_value = None
+        self._e2_retry_count = None
+        self._rmr_routing_needed = None
+        self.discriminator = None
+
+        if e2_timeout_timer_value is not None:
+            self.e2_timeout_timer_value = e2_timeout_timer_value
+        if e2_retry_count is not None:
+            self.e2_retry_count = e2_retry_count
+        if rmr_routing_needed is not None:
+            self.rmr_routing_needed = rmr_routing_needed
+
+    @property
+    def e2_timeout_timer_value(self):
+        """Gets the e2_timeout_timer_value of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+
+        How long time response is waited from E2 node  # noqa: E501
+
+        :return: The e2_timeout_timer_value of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+        :rtype: int
+        """
+        return self._e2_timeout_timer_value
+
+    @e2_timeout_timer_value.setter
+    def e2_timeout_timer_value(self, e2_timeout_timer_value):
+        """Sets the e2_timeout_timer_value of this SubscriptionParamsE2SubscriptionDirectives.
+
+        How long time response is waited from E2 node  # noqa: E501
+
+        :param e2_timeout_timer_value: The e2_timeout_timer_value of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+        :type: int
+        """
+        if (self._configuration.client_side_validation and
+                e2_timeout_timer_value is not None and e2_timeout_timer_value > 10):  # noqa: E501
+            raise ValueError("Invalid value for `e2_timeout_timer_value`, must be a value less than or equal to `10`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                e2_timeout_timer_value is not None and e2_timeout_timer_value < 1):  # noqa: E501
+            raise ValueError("Invalid value for `e2_timeout_timer_value`, must be a value greater than or equal to `1`")  # noqa: E501
+
+        self._e2_timeout_timer_value = e2_timeout_timer_value
+
+    @property
+    def e2_retry_count(self):
+        """Gets the e2_retry_count of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+
+        How many times E2 subscription request is retried  # noqa: E501
+
+        :return: The e2_retry_count of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+        :rtype: int
+        """
+        return self._e2_retry_count
+
+    @e2_retry_count.setter
+    def e2_retry_count(self, e2_retry_count):
+        """Sets the e2_retry_count of this SubscriptionParamsE2SubscriptionDirectives.
+
+        How many times E2 subscription request is retried  # noqa: E501
+
+        :param e2_retry_count: The e2_retry_count of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+        :type: int
+        """
+        if (self._configuration.client_side_validation and
+                e2_retry_count is not None and e2_retry_count > 10):  # noqa: E501
+            raise ValueError("Invalid value for `e2_retry_count`, must be a value less than or equal to `10`")  # noqa: E501
+        if (self._configuration.client_side_validation and
+                e2_retry_count is not None and e2_retry_count < 0):  # noqa: E501
+            raise ValueError("Invalid value for `e2_retry_count`, must be a value greater than or equal to `0`")  # noqa: E501
+
+        self._e2_retry_count = e2_retry_count
+
+    @property
+    def rmr_routing_needed(self):
+        """Gets the rmr_routing_needed of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+
+        Subscription needs RMR route from E2Term to xApp  # noqa: E501
+
+        :return: The rmr_routing_needed of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+        :rtype: bool
+        """
+        return self._rmr_routing_needed
+
+    @rmr_routing_needed.setter
+    def rmr_routing_needed(self, rmr_routing_needed):
+        """Sets the rmr_routing_needed of this SubscriptionParamsE2SubscriptionDirectives.
+
+        Subscription needs RMR route from E2Term to xApp  # noqa: E501
+
+        :param rmr_routing_needed: The rmr_routing_needed of this SubscriptionParamsE2SubscriptionDirectives.  # noqa: E501
+        :type: bool
+        """
+
+        self._rmr_routing_needed = rmr_routing_needed
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionParamsE2SubscriptionDirectives, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionParamsE2SubscriptionDirectives):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionParamsE2SubscriptionDirectives):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subscription_response.py b/ricxappframe/subsclient/models/subscription_response.py
new file mode 100644 (file)
index 0000000..df08c08
--- /dev/null
@@ -0,0 +1,151 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubscriptionResponse(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'subscription_id': 'str',
+        'subscription_instances': 'list[SubscriptionInstance]'
+    }
+
+    attribute_map = {
+        'subscription_id': 'SubscriptionId',
+        'subscription_instances': 'SubscriptionInstances'
+    }
+
+    def __init__(self, subscription_id=None, subscription_instances=None, _configuration=None):  # noqa: E501
+        """SubscriptionResponse - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._subscription_id = None
+        self._subscription_instances = None
+        self.discriminator = None
+
+        self.subscription_id = subscription_id
+        self.subscription_instances = subscription_instances
+
+    @property
+    def subscription_id(self):
+        """Gets the subscription_id of this SubscriptionResponse.  # noqa: E501
+
+
+        :return: The subscription_id of this SubscriptionResponse.  # noqa: E501
+        :rtype: str
+        """
+        return self._subscription_id
+
+    @subscription_id.setter
+    def subscription_id(self, subscription_id):
+        """Sets the subscription_id of this SubscriptionResponse.
+
+
+        :param subscription_id: The subscription_id of this SubscriptionResponse.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and subscription_id is None:
+            raise ValueError("Invalid value for `subscription_id`, must not be `None`")  # noqa: E501
+
+        self._subscription_id = subscription_id
+
+    @property
+    def subscription_instances(self):
+        """Gets the subscription_instances of this SubscriptionResponse.  # noqa: E501
+
+
+        :return: The subscription_instances of this SubscriptionResponse.  # noqa: E501
+        :rtype: list[SubscriptionInstance]
+        """
+        return self._subscription_instances
+
+    @subscription_instances.setter
+    def subscription_instances(self, subscription_instances):
+        """Sets the subscription_instances of this SubscriptionResponse.
+
+
+        :param subscription_instances: The subscription_instances of this SubscriptionResponse.  # noqa: E501
+        :type: list[SubscriptionInstance]
+        """
+        if self._configuration.client_side_validation and subscription_instances is None:
+            raise ValueError("Invalid value for `subscription_instances`, must not be `None`")  # noqa: E501
+
+        self._subscription_instances = subscription_instances
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubscriptionResponse, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubscriptionResponse):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubscriptionResponse):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/subsequent_action.py b/ricxappframe/subsclient/models/subsequent_action.py
new file mode 100644 (file)
index 0000000..9f701f9
--- /dev/null
@@ -0,0 +1,165 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class SubsequentAction(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'subsequent_action_type': 'str',
+        'time_to_wait': 'str'
+    }
+
+    attribute_map = {
+        'subsequent_action_type': 'SubsequentActionType',
+        'time_to_wait': 'TimeToWait'
+    }
+
+    def __init__(self, subsequent_action_type=None, time_to_wait=None, _configuration=None):  # noqa: E501
+        """SubsequentAction - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._subsequent_action_type = None
+        self._time_to_wait = None
+        self.discriminator = None
+
+        self.subsequent_action_type = subsequent_action_type
+        self.time_to_wait = time_to_wait
+
+    @property
+    def subsequent_action_type(self):
+        """Gets the subsequent_action_type of this SubsequentAction.  # noqa: E501
+
+
+        :return: The subsequent_action_type of this SubsequentAction.  # noqa: E501
+        :rtype: str
+        """
+        return self._subsequent_action_type
+
+    @subsequent_action_type.setter
+    def subsequent_action_type(self, subsequent_action_type):
+        """Sets the subsequent_action_type of this SubsequentAction.
+
+
+        :param subsequent_action_type: The subsequent_action_type of this SubsequentAction.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and subsequent_action_type is None:
+            raise ValueError("Invalid value for `subsequent_action_type`, must not be `None`")  # noqa: E501
+        allowed_values = ["continue", "wait"]  # noqa: E501
+        if (self._configuration.client_side_validation and
+                subsequent_action_type not in allowed_values):
+            raise ValueError(
+                "Invalid value for `subsequent_action_type` ({0}), must be one of {1}"  # noqa: E501
+                .format(subsequent_action_type, allowed_values)
+            )
+
+        self._subsequent_action_type = subsequent_action_type
+
+    @property
+    def time_to_wait(self):
+        """Gets the time_to_wait of this SubsequentAction.  # noqa: E501
+
+
+        :return: The time_to_wait of this SubsequentAction.  # noqa: E501
+        :rtype: str
+        """
+        return self._time_to_wait
+
+    @time_to_wait.setter
+    def time_to_wait(self, time_to_wait):
+        """Sets the time_to_wait of this SubsequentAction.
+
+
+        :param time_to_wait: The time_to_wait of this SubsequentAction.  # noqa: E501
+        :type: str
+        """
+        if self._configuration.client_side_validation and time_to_wait is None:
+            raise ValueError("Invalid value for `time_to_wait`, must not be `None`")  # noqa: E501
+        allowed_values = ["zero", "w1ms", "w2ms", "w5ms", "w10ms", "w20ms", "w30ms", "w40ms", "w50ms", "w100ms", "w200ms", "w500ms", "w1s", "w2s", "w5s", "w10s", "w20s", "w60s"]  # noqa: E501
+        if (self._configuration.client_side_validation and
+                time_to_wait not in allowed_values):
+            raise ValueError(
+                "Invalid value for `time_to_wait` ({0}), must be one of {1}"  # noqa: E501
+                .format(time_to_wait, allowed_values)
+            )
+
+        self._time_to_wait = time_to_wait
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(SubsequentAction, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, SubsequentAction):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, SubsequentAction):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/x_app_config.py b/ricxappframe/subsclient/models/x_app_config.py
new file mode 100644 (file)
index 0000000..77a1b94
--- /dev/null
@@ -0,0 +1,153 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class XAppConfig(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'metadata': 'ConfigMetadata',
+        'config': 'object'
+    }
+
+    attribute_map = {
+        'metadata': 'metadata',
+        'config': 'config'
+    }
+
+    def __init__(self, metadata=None, config=None, _configuration=None):  # noqa: E501
+        """XAppConfig - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+
+        self._metadata = None
+        self._config = None
+        self.discriminator = None
+
+        self.metadata = metadata
+        self.config = config
+
+    @property
+    def metadata(self):
+        """Gets the metadata of this XAppConfig.  # noqa: E501
+
+
+        :return: The metadata of this XAppConfig.  # noqa: E501
+        :rtype: ConfigMetadata
+        """
+        return self._metadata
+
+    @metadata.setter
+    def metadata(self, metadata):
+        """Sets the metadata of this XAppConfig.
+
+
+        :param metadata: The metadata of this XAppConfig.  # noqa: E501
+        :type: ConfigMetadata
+        """
+        if self._configuration.client_side_validation and metadata is None:
+            raise ValueError("Invalid value for `metadata`, must not be `None`")  # noqa: E501
+
+        self._metadata = metadata
+
+    @property
+    def config(self):
+        """Gets the config of this XAppConfig.  # noqa: E501
+
+        Configuration in JSON format  # noqa: E501
+
+        :return: The config of this XAppConfig.  # noqa: E501
+        :rtype: object
+        """
+        return self._config
+
+    @config.setter
+    def config(self, config):
+        """Sets the config of this XAppConfig.
+
+        Configuration in JSON format  # noqa: E501
+
+        :param config: The config of this XAppConfig.  # noqa: E501
+        :type: object
+        """
+        if self._configuration.client_side_validation and config is None:
+            raise ValueError("Invalid value for `config`, must not be `None`")  # noqa: E501
+
+        self._config = config
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(XAppConfig, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, XAppConfig):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, XAppConfig):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/models/xapp_config_list.py b/ricxappframe/subsclient/models/xapp_config_list.py
new file mode 100644 (file)
index 0000000..853a11a
--- /dev/null
@@ -0,0 +1,95 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+from ricxappframe.subsclient.configuration import Configuration
+
+
+class XappConfigList(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+    }
+
+    attribute_map = {
+    }
+
+    def __init__(self, _configuration=None):  # noqa: E501
+        """XappConfigList - a model defined in Swagger"""  # noqa: E501
+        if _configuration is None:
+            _configuration = Configuration()
+        self._configuration = _configuration
+        self.discriminator = None
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(XappConfigList, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, XappConfigList):
+            return False
+
+        return self.to_dict() == other.to_dict()
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        if not isinstance(other, XappConfigList):
+            return True
+
+        return self.to_dict() != other.to_dict()
diff --git a/ricxappframe/subsclient/rest.py b/ricxappframe/subsclient/rest.py
new file mode 100644 (file)
index 0000000..12ef032
--- /dev/null
@@ -0,0 +1,323 @@
+# coding: utf-8
+
+"""
+    RIC subscription
+
+    This is the initial REST API for RIC subscription  # noqa: E501
+
+    OpenAPI spec version: 0.0.4
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+
+from __future__ import absolute_import
+
+import io
+import json
+import logging
+import re
+import ssl
+
+import certifi
+# python 2 and python 3 compatibility library
+import six
+from six.moves.urllib.parse import urlencode
+
+try:
+    import urllib3
+except ImportError:
+    raise ImportError('Swagger python client requires urllib3.')
+
+
+logger = logging.getLogger(__name__)
+
+
+class RESTResponse(io.IOBase):
+
+    def __init__(self, resp):
+        self.urllib3_response = resp
+        self.status = resp.status
+        self.reason = resp.reason
+        self.data = resp.data
+
+    def getheaders(self):
+        """Returns a dictionary of the response headers."""
+        return self.urllib3_response.getheaders()
+
+    def getheader(self, name, default=None):
+        """Returns a given response header."""
+        return self.urllib3_response.getheader(name, default)
+
+
+class RESTClientObject(object):
+
+    def __init__(self, configuration, pools_size=4, maxsize=None):
+        # urllib3.PoolManager will pass all kw parameters to connectionpool
+        # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75  # noqa: E501
+        # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680  # noqa: E501
+        # maxsize is the number of requests to host that are allowed in parallel  # noqa: E501
+        # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html  # noqa: E501
+
+        # cert_reqs
+        if configuration.verify_ssl:
+            cert_reqs = ssl.CERT_REQUIRED
+        else:
+            cert_reqs = ssl.CERT_NONE
+
+        # ca_certs
+        if configuration.ssl_ca_cert:
+            ca_certs = configuration.ssl_ca_cert
+        else:
+            # if not set certificate file, use Mozilla's root certificates.
+            ca_certs = certifi.where()
+
+        addition_pool_args = {}
+        if configuration.assert_hostname is not None:
+            addition_pool_args['assert_hostname'] = configuration.assert_hostname  # noqa: E501
+
+        if maxsize is None:
+            if configuration.connection_pool_maxsize is not None:
+                maxsize = configuration.connection_pool_maxsize
+            else:
+                maxsize = 4
+
+        # https pool manager
+        if configuration.proxy:
+            self.pool_manager = urllib3.ProxyManager(
+                num_pools=pools_size,
+                maxsize=maxsize,
+                cert_reqs=cert_reqs,
+                ca_certs=ca_certs,
+                cert_file=configuration.cert_file,
+                key_file=configuration.key_file,
+                proxy_url=configuration.proxy,
+                **addition_pool_args
+            )
+        else:
+            self.pool_manager = urllib3.PoolManager(
+                num_pools=pools_size,
+                maxsize=maxsize,
+                cert_reqs=cert_reqs,
+                ca_certs=ca_certs,
+                cert_file=configuration.cert_file,
+                key_file=configuration.key_file,
+                **addition_pool_args
+            )
+
+    def request(self, method, url, query_params=None, headers=None,
+                body=None, post_params=None, _preload_content=True,
+                _request_timeout=None):
+        """Perform requests.
+
+        :param method: http request method
+        :param url: http request url
+        :param query_params: query parameters in the url
+        :param headers: http request headers
+        :param body: request json body, for `application/json`
+        :param post_params: request post parameters,
+                            `application/x-www-form-urlencoded`
+                            and `multipart/form-data`
+        :param _preload_content: if False, the urllib3.HTTPResponse object will
+                                 be returned without reading/decoding response
+                                 data. Default is True.
+        :param _request_timeout: timeout setting for this request. If one
+                                 number provided, it will be total request
+                                 timeout. It can also be a pair (tuple) of
+                                 (connection, read) timeouts.
+        """
+        method = method.upper()
+        assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
+                          'PATCH', 'OPTIONS']
+
+        if post_params and body:
+            raise ValueError(
+                "body parameter cannot be used with post_params parameter."
+            )
+
+        post_params = post_params or {}
+        headers = headers or {}
+
+        timeout = None
+        if _request_timeout:
+            if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
+                timeout = urllib3.Timeout(total=_request_timeout)
+            elif (isinstance(_request_timeout, tuple) and
+                  len(_request_timeout) == 2):
+                timeout = urllib3.Timeout(
+                    connect=_request_timeout[0], read=_request_timeout[1])
+
+        if 'Content-Type' not in headers:
+            headers['Content-Type'] = 'application/json'
+
+        try:
+            # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
+            if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
+                if query_params:
+                    url += '?' + urlencode(query_params)
+                if re.search('json', headers['Content-Type'], re.IGNORECASE):
+                    request_body = '{}'
+                    if body is not None:
+                        request_body = json.dumps(body)
+                    r = self.pool_manager.request(
+                        method, url,
+                        body=request_body,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                elif headers['Content-Type'] == 'application/x-www-form-urlencoded':  # noqa: E501
+                    r = self.pool_manager.request(
+                        method, url,
+                        fields=post_params,
+                        encode_multipart=False,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                elif headers['Content-Type'] == 'multipart/form-data':
+                    # must del headers['Content-Type'], or the correct
+                    # Content-Type which generated by urllib3 will be
+                    # overwritten.
+                    del headers['Content-Type']
+                    r = self.pool_manager.request(
+                        method, url,
+                        fields=post_params,
+                        encode_multipart=True,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                # Pass a `string` parameter directly in the body to support
+                # other content types than Json when `body` argument is
+                # provided in serialized form
+                elif isinstance(body, str):
+                    request_body = body
+                    r = self.pool_manager.request(
+                        method, url,
+                        body=request_body,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                else:
+                    # Cannot generate the request from given parameters
+                    msg = """Cannot prepare a request message for provided
+                             arguments. Please check that your arguments match
+                             declared content type."""
+                    raise ApiException(status=0, reason=msg)
+            # For `GET`, `HEAD`
+            else:
+                r = self.pool_manager.request(method, url,
+                                              fields=query_params,
+                                              preload_content=_preload_content,
+                                              timeout=timeout,
+                                              headers=headers)
+        except urllib3.exceptions.SSLError as e:
+            msg = "{0}\n{1}".format(type(e).__name__, str(e))
+            raise ApiException(status=0, reason=msg)
+
+        if _preload_content:
+            r = RESTResponse(r)
+
+            # In the python 3, the response.data is bytes.
+            # we need to decode it to string.
+            if six.PY3:
+                r.data = r.data.decode('utf8')
+
+            # log response body
+            logger.debug("response body: %s", r.data)
+
+        if not 200 <= r.status <= 299:
+            raise ApiException(http_resp=r)
+
+        return r
+
+    def GET(self, url, headers=None, query_params=None, _preload_content=True,
+            _request_timeout=None):
+        return self.request("GET", url,
+                            headers=headers,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            query_params=query_params)
+
+    def HEAD(self, url, headers=None, query_params=None, _preload_content=True,
+             _request_timeout=None):
+        return self.request("HEAD", url,
+                            headers=headers,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            query_params=query_params)
+
+    def OPTIONS(self, url, headers=None, query_params=None, post_params=None,
+                body=None, _preload_content=True, _request_timeout=None):
+        return self.request("OPTIONS", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def DELETE(self, url, headers=None, query_params=None, body=None,
+               _preload_content=True, _request_timeout=None):
+        return self.request("DELETE", url,
+                            headers=headers,
+                            query_params=query_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def POST(self, url, headers=None, query_params=None, post_params=None,
+             body=None, _preload_content=True, _request_timeout=None):
+        return self.request("POST", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def PUT(self, url, headers=None, query_params=None, post_params=None,
+            body=None, _preload_content=True, _request_timeout=None):
+        return self.request("PUT", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def PATCH(self, url, headers=None, query_params=None, post_params=None,
+              body=None, _preload_content=True, _request_timeout=None):
+        return self.request("PATCH", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+
+class ApiException(Exception):
+
+    def __init__(self, status=None, reason=None, http_resp=None):
+        if http_resp:
+            self.status = http_resp.status
+            self.reason = http_resp.reason
+            self.body = http_resp.data
+            self.headers = http_resp.getheaders()
+        else:
+            self.status = status
+            self.reason = reason
+            self.body = None
+            self.headers = None
+
+    def __str__(self):
+        """Custom error messages for exception"""
+        error_message = "({0})\n"\
+                        "Reason: {1}\n".format(self.status, self.reason)
+        if self.headers:
+            error_message += "HTTP response headers: {0}\n".format(
+                self.headers)
+
+        if self.body:
+            error_message += "HTTP response body: {0}\n".format(self.body)
+
+        return error_message
index feb5d66..e939b0e 100644 (file)
@@ -31,8 +31,12 @@ from mdclogpy import Logger
 
 from ricxappframe import xapp_rmr
 from ricxappframe.constants import sdl_namespaces
+
+import ricxappframe.entities.rnib.nodeb_info_pb2 as pb_nbi
+import ricxappframe.entities.rnib.cell_pb2 as pb_cell
 from ricxappframe.entities.rnib.nb_identity_pb2 import NbIdentity
 from ricxappframe.entities.rnib.nodeb_info_pb2 import Node
+
 from ricxappframe.rmr import rmr
 from ricxappframe.util.constants import Constants
 from ricxappframe.xapp_sdl import SDLWrapper
@@ -79,6 +83,7 @@ class _BaseXapp:
         """
         # PUBLIC, can be used by xapps using self.(name):
         self.logger = Logger(name=__name__)
+        self._appthread = None
 
         # Start rmr rcv thread
         self._rmr_loop = xapp_rmr.RmrLoop(port=rmr_port, wait_for_ready=rmr_wait_for_ready)
@@ -111,7 +116,7 @@ class _BaseXapp:
             self.logger.error("__init__: Cannot Read config file for xapp Registration")
             self._config_data = {}
 
-        Thread(target=self.registerXapp).start()
+        self._appthread = Thread(target=self.registerXapp).start()
 
         # run the optionally provided user post init
         if post_init:
@@ -481,7 +486,7 @@ class _BaseXapp:
 
     def _get_rnib_info(self, node_type):
         """
-        Since the difference between get_list_gnb_ids and get_list_enb_ids is only note-type,
+        Since the difference between get_list_gnb_ids and get_list_enb_ids is only node-type,
         this function extracted from the duplicated logic.
 
         Parameters
@@ -490,7 +495,7 @@ class _BaseXapp:
            Type of node. This is EnumDescriptor.
            Available node types
            - UNKNOWN
-           - ENG
+           - ENB
            - GNB
 
         Returns
@@ -498,7 +503,7 @@ class _BaseXapp:
             List: (NbIdentity)
 
         Raises
-        -------
+        ------
             SdlTypeError: If function's argument is of an inappropriate type.
             NotConnected: If SDL is not connected to the backend data storage.
             RejectedByBackend: If backend data storage rejects the request.
@@ -524,13 +529,13 @@ class _BaseXapp:
             List: (NbIdentity)
 
         Raises
-        -------
+        ------
             SdlTypeError: If function's argument is of an inappropriate type.
             NotConnected: If SDL is not connected to the backend data storage.
             RejectedByBackend: If backend data storage rejects the request.
             BackendError: If the backend data storage fails to process the request.
         """
-        return self._get_rnib_info(Node.Type.Name(Node.Type.GNB))
+        return self._get_rnib_info(Node.Type.Name(Node.GNB))
 
     def get_list_enb_ids(self):
         """
@@ -550,9 +555,218 @@ class _BaseXapp:
             RejectedByBackend: If backend data storage rejects the request.
             BackendError: If the backend data storage fails to process the request.
         """
-        return self._get_rnib_info(Node.Type.Name(Node.Type.ENB))
+        return self._get_rnib_info(Node.Type.Name(Node.ENB))
+
+    """
+        Following RNIB methods are made to be inline of the go-lang based RNIB methods.
+        Method names are same as in repository:
+        gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/rnib
+    """
+    def GetNodeb(self, inventoryName):
+        """
+        Returns nodeb info
+        In RNIB SDL key is defined following way: RAN:<inventoryName>
+
+        Parameters
+        ----------
+        inventoryName: string
+
+        Returns
+        -------
+            NodebInfo()
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        nbid_string: Set[bytes] = self.sdl_get(sdl_namespaces.E2_MANAGER, 'RAN:' + inventoryName, usemsgpack=False)
+        if nbid_string is not None:
+            nbinfo = pb_nbi.NodebInfo()
+            nbinfo.ParseFromString(nbid_string)
+            return nbinfo
+        return None
+
+    def GetNodebByGlobalNbId(self, nodeType, plmnId, nbId):
+        """
+        Returns nodeb identity based on type, plmn id and node id
+        In RNIB SDL key is defined following way: <nodeType>:<plmnId>:<nbId>
 
-    # Health
+        Parameters
+        ----------
+            nodeType: string
+            plmnId: string
+            nbId: string
+
+        Returns
+        -------
+            NbIdentity()
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        nbid_string: Set[bytes] = self.sdl_get(sdl_namespaces.E2_MANAGER, nodeType + ':' + plmnId + ':' + nbId, usemsgpack=False)
+        if nbid_string is not None:
+            nbid = NbIdentity()
+            nbid.ParseFromString(nbid_string)
+            return nbid
+        return None
+
+    def GetCellList(self, inventoryName):
+        """
+        Returns nodeb served cell list from the saved node data
+        In RNIB SDL key is defined following way: RAN:<inventoryName>
+
+        Parameters
+        ----------
+            nodeType: string
+            plmnId: string
+            nbId: string
+
+        Returns
+        -------
+            ServedCellInfo() in case of ENB
+            ServedNRCell() in case of GNB
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        nodeb = self.GetNodeb(inventoryName)
+        if nodeb is not None:
+            if nodeb.HasField('enb'):
+                return nodeb.enb.served_cells
+            elif nodeb.HasField('gnb'):
+                return nodeb.gnb.served_nr_cells
+        return None
+
+    def GetCellById(self, cell_type, cell_id):
+        """
+        Returns cell info by cell type and id.
+        In RNIB SDL keys are defined based on the cell type:
+        ENB type CELL:<cell_id>
+        GNB type NRCELL:<cell_id>
+
+        Parameters
+        ----------
+        cell_type: string
+           Available cell types
+           - ENB
+           - GNB
+
+        Returns
+        -------
+            Cell()
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        cellstr = None
+        if cell_type == pb_cell.Cell.Type.Name(pb_cell.Cell.LTE_CELL):
+            cellstr = 'CELL'
+        elif cell_type == pb_cell.Cell.Type.Name(pb_cell.Cell.NR_CELL):
+            cellstr = 'NRCELL'
+        if cellstr is not None:
+            cell_string: Set[bytes] = self.sdl_get(sdl_namespaces.E2_MANAGER, cellstr + ':' + cell_id, usemsgpack=False)
+            if cell_string is not None:
+                cell = pb_cell.Cell()
+                cell.ParseFromString(cell_string)
+                return cell
+        return None
+
+    def GetListNodebIds(self):
+        """
+        Returns both enb and gnb NbIdentity list
+
+        Returns
+        -------
+            List: (NbIdentity)
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        nlist1 = self._get_rnib_info(Node.Type.Name(Node.ENB))
+        nlist2 = self._get_rnib_info(Node.Type.Name(Node.GNB))
+
+        for n in nlist2:
+            nlist1.append(n)
+        return nlist1
+
+    def GetCell(self, inventoryName, pci):
+        """
+        Returns cell info using pci
+        In RNIB SDL key is defined following way: PCI:<inventoryName>:<pci hex val>
+
+        Parameters
+        ----------
+        inventoryName: string
+        pci: int
+
+        Returns
+        -------
+            Cell()
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        cell_string: Set[bytes] = self.sdl_get(sdl_namespaces.E2_MANAGER, 'PCI:{0:s}:{1:02x}'.format(inventoryName, pci), usemsgpack=False)
+        if cell_string is not None:
+            cell = pb_cell.Cell()
+            cell.ParseFromString(cell_string)
+            return cell
+        return None
+
+    def GetRanFunctionDefinition(self, inventoryName, ran_function_oid):
+        """
+        Returns GNB ran function definition list based on the ran_function_oid
+        In RNIB SDL key is defined following way: RAN:<inventoryName>
+
+        Parameters
+        ----------
+            inventoryName: string
+            ran_function_oid: int
+
+        Returns
+        -------
+            array of ran_function_definition matching to ran_function_oid
+
+        Raises
+        ------
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If SDL is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        nodeb = self.GetNodeb(inventoryName)
+        if nodeb is not None:
+            if nodeb.HasField('gnb') and nodeb.gnb.ran_functions is not None:
+                ranFDList = []
+                for rf in nodeb.gnb.ran_functions:
+                    if rf.ran_function_oid == ran_function_oid:
+                        ranFDList.append(rf.ran_function_definition)
+                return ranFDList
+        return None
 
     def healthcheck(self):
         """
@@ -595,6 +809,8 @@ class _BaseXapp:
         TODO: can we register a ctrl-c handler so this gets called on
         ctrl-c? Because currently two ctrl-c are needed to stop.
         """
+        if self._appthread is not None:
+            self._appthread.join()
 
         self.xapp_shutdown()
 
diff --git a/ricxappframe/xapp_rest.py b/ricxappframe/xapp_rest.py
new file mode 100644 (file)
index 0000000..1f4a4e8
--- /dev/null
@@ -0,0 +1,193 @@
+#!/usr/bin/env python3
+# ==================================================================================
+#       Copyright (c) 2022 Nokia
+#
+#   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 socket
+import http.server
+import threading
+
+
+def initResponse(status=200, response="OK"):
+
+    """
+    initResponse
+        init the reponse data for handler to get all details defined
+
+    Parameters
+    ----------
+    status: int
+        http status code
+    response: string
+        http response text
+    Returns
+    -------
+    response - http response text
+    status - http status code
+    payload - payload data for the client (response data text or attachment file data)
+    attachment - file name of the attached payload data
+    mode text (utf-8) or binary data
+    """
+    return {'response': response, 'status': status, 'payload': None, 'ctype': 'application/json', 'attachment': None, 'mode': 'plain'}
+
+
+class RestHandler(http.server.BaseHTTPRequestHandler):
+
+    def _findUrihandler(self, uri, keys):
+        for key in keys:
+            value = keys[key]
+            if uri.find(value['uri']) >= 0:
+                return key, value
+        return None, None
+
+    def _sendResponse(self, response):
+        # sends the reponse according to the initResponse() response data
+        self.send_response(response['status'])
+        self.send_header("Server-name", "XAPP REST SERVER 0.9")
+        self.send_header('Content-type', response['ctype'])
+
+        if response['payload'] is not None:
+            # payload has been set
+            length = len(response['payload'])
+            if length != 0:
+                self.send_header('Content-length', length)
+            if response['attachment'] is not None:
+                self.send_header('Content-Disposition', "attachment; filename=" + response['attachment'])
+        self.end_headers()
+        if response['payload'] is not None:
+            if response['mode'] == 'plain':
+                # ascii mode
+                self.wfile.write(response['payload'].encode('utf-8'))
+            elif response['mode'] == 'binary':
+                # binary mode
+                self.wfile.write(response['payload'])
+
+    def add_handler(self, method=None, name=None, uri=None, callback=None):
+        """
+        Adds the function handler for given uri. The function callback is matched in first matching
+        uri. So prepare your handlers setup in such a way that those won't override each other. For example you can setup
+        usual xapp handler in this list:
+
+            server = ricrest.ThreadedHTTPServer(address, port)
+            server.handler.add_handler(self.server.handler, "GET", "config", "/ric/v1/config", self.configGetHandler)
+            server.handler.add_handler(self.server.handler, "GET", "healthAlive", "/ric/v1/health/alive", self.healthyGetAliveHandler)
+            server.handler.add_handler(self.server.handler, "GET", "healthReady", "/ric/v1/health/ready", self.healthyGetReadyHandler)
+            server.handler.add_handler(self.server.handler, "GET", "symptomdata", "/ric/v1/symptomdata", self.symptomdataGetHandler)
+
+        Parameters
+        ----------
+        method string
+            http method GET, POST, DELETE
+        name string
+            unique name - used for map name
+        uri string
+            http uri part which triggers the callback function
+        cb  function
+            function to be used for http method processing
+        """
+        if not hasattr(self, 'handlers'):
+            # init method can't be used becuase it has been inherited from base object
+            # so check the handlers existence and create if not defined
+            self.lock = threading.Lock()
+            self.handlers = dict()
+            self.handlers["get"] = dict()
+            self.handlers["post"] = dict()
+            self.handlers["delete"] = dict()
+        self.lock.acquire()
+        if method == "GET":
+            self.handlers["get"][name] = dict()
+            self.handlers["get"][name]['uri'] = uri
+            self.handlers["get"][name]['cb'] = callback
+        elif method == "POST":
+            self.handlers["post"][name] = dict()
+            self.handlers["post"][name]['uri'] = uri
+            self.handlers["post"][name]['cb'] = callback
+        elif method == "DELETE":
+            self.handlers["delete"][name] = dict()
+            self.handlers["delete"][name]['uri'] = uri
+            self.handlers["delete"][name]['cb'] = callback
+        self.lock.release()
+
+    def do_GET(self):
+        try:
+            response = initResponse(status=404, response='Not Found')
+            cbname, hndl = self._findUrihandler(self.path, self.handlers['get'])
+            if hndl is not None:
+                # call the defined callback handler
+                response = hndl['cb'](cbname, self.path, None, self.headers['Content-Type'])
+            self._sendResponse(response)
+
+        except (socket.error, IOError):
+            pass
+
+    def do_DELETE(self):
+        try:
+            response = initResponse(status=404, response='Not Found')
+            cbname, hndl = self._findUrihandler(self.path, self.handlers['delete'])
+            if hndl is not None:
+                # call the defined callback handler
+                response = hndl['cb'](cbname, self.path, None, self.headers['Content-Type'])
+            self._sendResponse(response)
+        except (socket.error, IOError):
+            pass
+
+    def do_POST(self):
+        try:
+            response = initResponse(status=404, response='Not Found')
+            cbname, hndl = self._findUrihandler(self.path, self.handlers['post'])
+            if hndl is not None:
+                data = self.rfile.read(int(self.headers['Content-Length']))
+                # call the defined callback handler
+                response = hndl['cb'](cbname, self.path, data, self.headers['Content-Type'])
+                print(response)
+            self._sendResponse(response)
+        except (socket.error, IOError):
+            pass
+
+
+class ThreadedHTTPServer(object):
+
+    handler = RestHandler
+    server_class = http.server.HTTPServer
+
+    def __init__(self, host, port):
+        """
+        init
+
+        Parameters
+        ----------
+        host string
+            http listen interface ip ("0.0.0.0" binds all interfaces)
+        port int
+            listen service port
+        """
+        self.server = self.server_class((host, port), self.handler)
+        self.server_thread = threading.Thread(target=self.server.serve_forever)
+        self.server_thread.daemon = True
+
+    def start(self):
+        """
+        start
+            starts the thread serving http requests
+        """
+        self.server_thread.start()
+
+    def stop(self):
+        """
+        stop
+            stops thread serving http requests
+        """
+        self.server.socket.close()
+        self.server.server_close()
+        self.server.shutdown()
diff --git a/ricxappframe/xapp_subscribe.py b/ricxappframe/xapp_subscribe.py
new file mode 100644 (file)
index 0000000..0bd5b24
--- /dev/null
@@ -0,0 +1,171 @@
+#       Copyright (c) 2022 Nokia
+#
+#   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.
+#
+# Subscription interface implements the subscription manager REST based interface defined in
+# https://docs.o-ran-sc.org/projects/o-ran-sc-ric-plt-submgr/en/latest/user-guide.html
+#
+
+import ricxappframe.subsclient as subsclient
+import ricxappframe.xapp_rest as ricrest
+from mdclogpy import Logger
+
+logging = Logger(name=__name__)
+
+
+class NewSubscriber():
+
+    def __init__(self, uri, timeout=None, local_address="0.0.0.0", local_port=8088, rmr_port=4061):
+        """
+        init
+
+        Parameters
+        ----------
+        uri: string
+            xapp submgr service uri
+        timeout: int
+            rest method timeout
+        local_address: string
+            local interface IP address for rest service binding (for response handler)
+        local_port: int
+            local service port nunber for rest service binding (for response handler)
+        rmr_port: int
+            rmr port number
+        """
+        self.uri = uri
+        self.timeout = timeout
+        self.local_address = local_address
+        self.local_port = local_port
+        self.rmr_port = rmr_port
+        self.url = "/ric/v1/subscriptions/response"
+        self.serverHandler = None
+        self.responseCB = None
+        # Configure API
+        configuration = subsclient.Configuration()
+        configuration.verify_ssl = False
+        configuration.host = "http://127.0.0.1:8088/"
+        self.api = subsclient.ApiClient(configuration)
+
+    def _responsePostHandler(self, name, path, data, ctype):
+        """
+        _resppnsePostHandler
+            internally used subscription reponse handler it the callback function is not set
+        """
+        return "{}", 'application/json', "OK", 200
+
+    # following methods are wrappers to hide the swagger client
+    def SubscriptionParamsClientEndpoint(self, host=None, http_port=None, rmr_port=None):
+        return subsclient.SubscriptionParamsClientEndpoint(host, http_port, rmr_port)
+
+    def SubscriptionParamsE2SubscriptionDirectives(self, e2_timeout_timer_value=None, e2_retry_count=None, rmr_routing_needed=None):
+        return subsclient.SubscriptionParamsE2SubscriptionDirectives(e2_timeout_timer_value, e2_retry_count, rmr_routing_needed)
+
+    def SubsequentAction(self, subsequent_action_type=None, time_to_wait=None):
+        return subsclient.SubsequentAction(subsequent_action_type, time_to_wait)
+
+    def ActionToBeSetup(self, action_id=None, action_type=None, action_definition=None, subsequent_action=None):
+        return subsclient.ActionToBeSetup(action_id, action_type, action_definition, subsequent_action)
+
+    def SubscriptionDetail(self, xapp_event_instance_id=None, event_triggers=None, action_to_be_setup_list=None):
+        return subsclient.SubscriptionDetail(xapp_event_instance_id, event_triggers, action_to_be_setup_list)
+
+    def SubscriptionParams(self, subscription_id=None, client_endpoint=None, meid=None, ran_function_id=None, e2_subscription_directives=None, subscription_details=None):
+        return subsclient.SubscriptionParams(subscription_id, client_endpoint, meid, ran_function_id, e2_subscription_directives, subscription_details)
+
+    def Subscribe(self, subs_params=None):
+        """
+        Subscribe
+            subscription request
+
+        Parameters
+        ----------
+        subs_params: SubscriptionParams
+            structured subscription data definition defined in subsclient
+        Returns
+        -------
+        SubscriptionResponse
+             json string of SubscriptionResponse object
+        """
+#        if subs_params is not None and type(subs_params) is subsclient.models.subscription_params.SubscriptionParams:
+        if subs_params is not None:
+            response = self.api.request(method="POST", url=self.uri, headers=None, body=subs_params.to_dict())
+            return response.data, response.reason, response.status
+        return None, "Input parameter is not SubscriptionParams{}", 500
+
+    def UnSubscribe(self, subs_id=None):
+        """
+        UnSubscribe
+            subscription remove
+
+        Parameters
+        ----------
+        subs_id: int
+            subscription id returned in SubscriptionResponse
+        Returns
+        -------
+        response.reason: string
+            http reason
+        response.status: int
+            http status code
+        """
+        response = self.api.request(method="DELETE", url=self.uri + "/subscriptions/" + subs_id, headers=None)
+        return response.data, response.reason, response.status
+
+    def QuerySubscriptions(self):
+        """
+        QuerySubscriptions
+            Query all subscriptions
+
+        Returns
+        -------
+        response.data: json string
+            SubscriptionList
+        response.reason: string
+            http reason
+        response.status: int
+            http status code
+        """
+        response = self.api.request(method="GET", url=self.uri + "/subscriptions", headers=None)
+        return response.data, response.reason, response.status
+
+    def ResponseHandler(self, responseCB=None, server=None):
+        """
+        ResponseHandler
+            Starts the response handler and set the callback
+
+        Parameters
+        ----------
+        responseCB
+            Set the callback handler, if not set the the default self._responsePostHandler is used
+        server: xapp_rest.ThreadedHTTPServer
+            if set then the existing xapp_rest.ThreadedHTTPServer handler is used, otherwise a new will be created
+
+        Returns
+        -------
+        status: boolean
+            True = success, False = failed
+        """
+        # create the thread HTTP server
+        self.serverHandler = server
+        if self.serverHandler is None:
+            # make the serverhandler
+            self.serverHandler = ricrest.ThreadedHTTPServer(self.local_address, self.local_port)
+            self.serverHandler.start()
+        if self.serverHandler is not None:
+            if responseCB is not None:
+                self.responseCB = responseCB
+            # get http handler with object reference
+            self.serverHandler.handler.add_handler(self.serverHandler.handler, "POST", "response", self.url, responseCB)
+            return True
+        else:
+            return False
diff --git a/ricxappframe/xapp_symptomdata.py b/ricxappframe/xapp_symptomdata.py
new file mode 100644 (file)
index 0000000..8d979bc
--- /dev/null
@@ -0,0 +1,228 @@
+#       Copyright (c) 2022 Nokia
+#
+#   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.
+#
+# Symptomdata collection is triggered from the trblmgr ricplt pod. This subsystem provides for xapp interface to subscribe the
+# symptomdata collection via lwsd pod. When the symptomdata collection is triggered then the xapp gets the callback to collect
+# the symptomdata.
+#
+# If the dynamic registration is needed, then the xapp needs to use the Symptomdata.subscribe(...) method to indicate symptomdata
+# collection. In case the xapp is set to trblmgr config file then the registration is not needed.
+#
+# If the xapp has the internal data for symptomdata collection REST call response, it can use the helper methods getFileList and collect
+# to get the needed files or readymade zipped package for reponse.
+#
+import os
+import re
+import time
+import requests
+import json
+from requests.exceptions import HTTPError
+from zipfile import ZipFile
+from threading import Timer
+from datetime import datetime
+from mdclogpy import Logger
+
+logging = Logger(name=__name__)
+
+
+class RepeatTimer(Timer):
+    # timer class for housekeeping and file rotating
+    def run(self):
+        while not self.finished.wait(self.interval):
+            self.function(*self.args, **self.kwargs)
+
+
+class Symptomdata(object):
+    # service is the local POD service id, path the temporal storage, host should be the trblmgr service name
+    def __init__(self, service="", servicehost="", path="/tmp/", lwsduri=None, timeout=30):
+        """
+        init
+
+        Parameters
+        ----------
+        service: string
+            xapp service name
+        servicehost: string
+            xapp service host name
+        path:
+            temporal path where the symptomdata collection is stored
+        lwsduri:
+            lwsd uri for symptomdata dynamic registration
+        timeout:
+            timeout for subscription status polling
+        """
+        if not os.path.exists(path):
+            os.mkdir(path)
+        self.service = service
+        self.servicehost = servicehost
+        self.path = path
+        self.lwsduri = lwsduri
+        self.timeout = timeout
+        # runtime attrs
+        self.zipfilename = None
+        logging.info("Symptomdata init service:%s path:%s lwsduri:%s timeout:%d" % (self.service, self.path, self.lwsduri, self.timeout))
+        if self.lwsduri is not None:
+            # do the subscription, set to True so that first the query is triggered
+            self.lwsdok = True
+            self.subscribe(args=("",))
+            self.subscribetimer = RepeatTimer(self.timeout, self.subscribe, args=("",))
+            self.subscribetimer.start()
+
+    # make the symptomdata subscription query to lwsd - dynamic registration (needed if the static config in trblmgr does not have xapp service data)
+    def subscribe(self, args):
+        """
+        subscribe
+            internally used subscription function if the dynamic registration has been set
+        """
+        if self.lwsduri is not None:
+            try:
+                proxies = {"http": "", "https": ""}    # disable proxy usage
+                headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
+                if self.lwsdok is False:
+                    jsondata = json.dumps({'url': 'http://' + self.servicehost +
+                                           ':8080/ric/v1/symptomdata', 'service': self.service, 'instance': '1'})
+                    response = requests.post(self.lwsduri,
+                                             data=jsondata,
+                                             headers=headers,
+                                             proxies=proxies)
+                    logging.info("Symptomdata subscription success")
+                    self.lwsdok = True
+                elif self.lwsdok is True:
+                    self.lwsdok = False
+                    response = requests.get(self.lwsduri, headers=headers, proxies=proxies)
+                    for item in response.json():
+                        if item.get('service') == self.service:
+                            logging.info("Symptomdata subscription request success")
+                            self.lwsdok = True
+                    if self.lwsdok is False:
+                        logging.error("Symptomdata subscription missing")
+                response.raise_for_status()
+            except HTTPError as http_err:
+                logging.error("Symptomdata subscription failed - http error : %s" % (http_err))
+                self.lwsdok = False
+            except Exception as err:
+                logging.error("Symptomdata subscription failed - error : %s" % (err))
+                self.lwsdok = False
+
+    def stop(self):
+        """
+        stop
+            stops the dynamic service registration/polling
+        """
+        if self.subscribetimer is not None:
+            self.subscribetimer.cancel()
+
+    def __del__(self):
+        if self.subscribetimer is not None:
+            self.subscribetimer.cancel()
+
+    def getFileList(self, regex, fromtime, totime):
+        """
+        getFileList
+            internal use only, get the matching files for collect method
+        """
+        fileList = []
+        path, wc = regex.rsplit('/', 1)
+        logging.info("Filtering path: %s using wildcard %s fromtime %d totime %d" % (path + '/', wc, fromtime, totime))
+        try:
+            for root, dirs, files in os.walk((path + '/')):
+                for filename in files:
+                    if re.match(wc, filename):
+                        file_path = os.path.join(root, filename)
+                        filest = os.stat(file_path)
+                        if fromtime > 0:
+                            logging.info("Filtering file time %d fromtime %d totime %d" % (filest.st_ctime, fromtime, totime))
+                            if fromtime <= filest.st_ctime:
+                                logging.info("Adding file time %d fromtime %d" % (filest.st_ctime, fromtime))
+                                if totime > 0:
+                                    if totime >= filest.st_ctime:
+                                        fileList.append(file_path)
+                                else:
+                                    fileList.append(file_path)
+                        elif totime > 0:
+                            if totime >= filest.st_ctime:
+                                logging.info("Filtering file time %d fromtime %d totime %d" % (filest.st_ctime, fromtime, totime))
+                                fileList.append(file_path)
+                        else:
+                            fileList.append(file_path)
+
+        except OSError as e:
+            logging.error("System error %d" % (e.errno))
+        return fileList
+
+    def collect(self, zipfiletmpl, fileregexlist, fromtime, totime):
+        """
+        collect
+            collects the symptomdata based on the file regular expression match and stored the symptomdata. Optionaly
+            caller can use fromtime and totime to choose only files matching the access time
+
+        Parameters
+        ----------
+        zipfiletmpl: string
+            template for zip file name using the strftime format - ex: ``"symptomdata"+'-%Y-%m-%d-%H-%M-%S.zip'``
+        fileregexlist: string array
+            array for file matching - ex: ``('examples/*.csv',)``
+        fromtime: integer
+            time value seconds
+        totime: integer
+            time value seconds
+        Returns
+        -------
+        string
+            zipfile name
+        """
+        zipfilename = self.path + datetime.fromtimestamp(int(time.time())).strftime(zipfiletmpl)
+        logging.info("Compressing files to symptomdata archive: %s" % (zipfilename))
+        zipdata = ZipFile(zipfilename, "w")
+        self.remove()
+        self.zipfilename = None
+        fileCnt = 0
+        for fileregex in fileregexlist:
+            logging.info("Compressing files using %s" % (fileregex))
+            fileList = self.getFileList(fileregex, fromtime, totime)
+            try:
+                if len(fileList) > 0:
+                    for file_path in fileList:
+                        logging.info("Adding file %s to archive" % (file_path))
+                        zipdata.write(file_path, file_path)
+                        fileCnt += 1
+            except OSError as e:
+                logging.error("System error %d" % (e.errno))
+        zipdata.close()
+        if fileCnt > 0:
+            self.zipfilename = zipfilename
+        return self.zipfilename
+
+    def read(self):
+        """
+        read
+            reads the stored symptomdata file content
+
+        Returns
+        -------
+        string
+            zipfile name
+        integer
+            data lenght
+        bytes
+            bytes of the file data
+        """
+        data = None
+        with open(self.zipfilename, 'rb') as file:
+            data = file.read()
+        return (self.zipfilename, len(data), data)
+
+    def remove(self):
+        if self.zipfilename is not None:
+            os.remove(self.zipfilename)
index a77b7e9..04797f5 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -32,12 +32,12 @@ def _long_descr():
 
 setup(
     name="ricxappframe",
-    version="3.0.2",
+    version="3.1.0",
     packages=find_packages(exclude=["tests.*", "tests"]),
     author="O-RAN Software Community",
     description="Xapp and RMR framework for Python",
     url="https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/xapp-frame-py",
-    install_requires=["inotify_simple", "msgpack", "mdclogpy", "ricsdl>=3.0.0,<4.0.0", "requests", "protobuf", "inotify"],
+    install_requires=["inotify_simple", "msgpack", "mdclogpy", "ricsdl>=3.0.0,<4.0.0", "requests", "protobuf<3.21.0", "inotify"],
     classifiers=[
         "Development Status :: 4 - Beta",
         "Intended Audience :: Telecommunications Industry",
index dbff888..8ad34e6 100644 (file)
 import pytest
 
 from ricxappframe.entities.rnib.nb_identity_pb2 import NbIdentity
+from ricxappframe.entities.rnib.cell_pb2 import Cell
+import ricxappframe.entities.rnib.nb_identity_pb2 as pb_nb
+import ricxappframe.entities.rnib.nodeb_info_pb2 as pb_nbi
+import ricxappframe.entities.rnib.enb_pb2 as pb_enb
+import ricxappframe.entities.rnib.gnb_pb2 as pb_gnb
+import ricxappframe.entities.rnib.cell_pb2 as pb_cell
+import ricxappframe.entities.rnib.ran_function_pb2 as pb_rf
 
 
 # These are here just to reduce the size of the code in test_rmr so those (important) tests are more readable; in theory these dicts could be large
@@ -94,3 +101,94 @@ def rnib_information():
     rnib1.connection_status = 6
 
     return [rnib1.SerializeToString(), rnib2.SerializeToString()]
+
+
+@pytest.fixture
+def rnib_cellinformation():
+    rnib_cell1 = Cell()
+    print(rnib_cell1)
+    rnib_cell1.type = Cell.LTE_CELL
+
+    rnib_cell2 = Cell()
+    rnib_cell2.type = Cell.LTE_CELL
+
+    return [rnib_cell2.SerializeToString(), rnib_cell2.SerializeToString()]
+
+
+def createRanFunction(ran_function_id, definition, revision, oid):
+    r = pb_rf.RanFunction()
+    r.ran_function_id = ran_function_id
+    r.ran_function_definition = definition
+    r.ran_function_revision = revision
+    r.ran_function_oid = oid
+    return r
+
+
+def createServedCellInfo(pci, cell_id, tac):
+    s = pb_enb.ServedCellInfo()
+    s.pci = pci
+    s.cell_id = cell_id
+    s.tac = tac
+    return s
+
+
+def createServedNRCellInfo(pci, cell_id, tac):
+    s = pb_gnb.ServedNRCell()
+#    s = pb_gnb.ServedNRCellInformation()
+    s.served_nr_cell_information.nr_pci = pci
+    s.served_nr_cell_information.cell_id = cell_id
+    s.served_nr_cell_information.stac5g = tac
+    s.served_nr_cell_information.nr_mode = 2
+    return s
+
+
+class rnibHelpers:
+    @staticmethod
+    def createNodeb(name, plmn, nbid):
+        nb = pb_nb.NbIdentity()
+        nb.inventory_name = name
+        nb.global_nb_id.plmn_id = plmn
+        nb.global_nb_id.nb_id = nbid
+        nb.connection_status = 1
+        return nb
+
+    @staticmethod
+    def createNodebInfo(name, nbtype, ip, port):
+        nbi = pb_nbi.NodebInfo()
+        nbi.ip = ip
+        nbi.port = port
+        nbi.e2_application_protocol = 1
+        nbi.connection_status = 1
+        if nbtype == 'GNB':
+            nbi.node_type = 2
+            rf1 = createRanFunction(1, b'te524367153', 1, "1.3.6.1.4.1.1.2.2.1")
+            rf2 = createRanFunction(1, b'te524367153', 1, "1.3.6.1.4.1.1.2.2.2")
+            rf3 = createRanFunction(1, b'te524367153', 1, "1.3.6.1.4.1.1.2.2.3")
+            nbi.gnb.ran_functions.extend([rf1, rf2, rf3])
+            s1 = createServedNRCellInfo(1, b'822', b'1452')
+            s2 = createServedNRCellInfo(2, b'823', b'1453')
+            s3 = createServedNRCellInfo(3, b'824', b'1454')
+            nbi.gnb.served_nr_cells.extend([s1, s2, s3])
+        else:
+            nbi.node_type = 1
+            nbi.enb.enb_type = 1
+            s1 = createServedCellInfo(1, b'822', b'1452')
+            s2 = createServedCellInfo(2, b'823', b'1453')
+            s3 = createServedCellInfo(3, b'824', b'1454')
+            nbi.enb.served_cells.extend([s1, s2, s3])
+        return nbi
+
+    @staticmethod
+    def createCell(name, pci):
+        c = pb_cell.Cell()
+        c.type = pb_cell.Cell.Type.Value('LTE_CELL')
+#        print(pb_cell.Cell.Type.Name(pb_cell.Cell.LTE_CELL))
+        c.served_cell_info.pci = pci
+        c.served_cell_info.cell_id = b'822'
+        c.served_cell_info.tac = b'1452'
+        return c
+
+
+@pytest.fixture
+def rnib_helpers():
+    return rnibHelpers
diff --git a/tests/test_rest.py b/tests/test_rest.py
new file mode 100644 (file)
index 0000000..d03e594
--- /dev/null
@@ -0,0 +1,74 @@
+import requests
+import ricxappframe.xapp_rest
+
+
+def doGetRequest(url):
+    proxies = {"http": "", "https": ""}    # disable proxy usage
+    return requests.get(url, proxies=proxies)
+
+
+def doDeleteRequest(url):
+    proxies = {"http": "", "https": ""}    # disable proxy usage
+    return requests.delete(url, proxies=proxies)
+
+
+def doPostRequest(url, data):
+    proxies = {"http": "", "https": ""}    # disable proxy usage
+    return requests.post(url, data, proxies=proxies)
+
+
+def respPostHandler(name, path, data, ctype):
+    response = ricxappframe.xapp_rest.initResponse()
+    response['payload'] = data.decode("utf-8")
+    return response
+
+
+def respGetHandler(name, path, data, ctype):
+    response = ricxappframe.xapp_rest.initResponse()
+    response['payload'] = ('{ "Testitem": "Testdata"}')
+    return response
+
+
+def respDeleteHandler(name, path, data, ctype):
+    response = ricxappframe.xapp_rest.initResponse()
+    response['payload'] = None
+    response['status'] = 204
+    return response
+
+
+def respGetEmptyHandler(name, path, data, ctype):
+    response = ricxappframe.xapp_rest.initResponse()
+    response['payload'] = None
+    response['status'] = 204
+    return response
+
+
+def test_subscribe(monkeypatch):
+
+    server = ricxappframe.xapp_rest.ThreadedHTTPServer("127.0.0.1", 18088)
+    # trick to get the own handler with defined
+    server.handler.add_handler(server.handler, "GET", "get", "/ric/v1/subscriptions", respGetHandler)
+    server.handler.add_handler(server.handler, "GET", "getempty", "/ric/v1/empty", respGetEmptyHandler)
+    server.handler.add_handler(server.handler, "POST", "post", "/ric/v1", respPostHandler)
+    server.handler.add_handler(server.handler, "DELETE", "delete", "/ric/v1/delete", respDeleteHandler)
+    server.start()
+
+    resp = doGetRequest('http://127.0.0.1:18088/ric/v1/subscriptions')
+    assert resp.text == '{ "Testitem": "Testdata"}'
+    assert resp.status_code == 200
+
+    resp = doGetRequest('http://127.0.0.1:18088/ric/v1/empty')
+    assert resp.text == ""
+    assert resp.status_code == 204
+
+    resp = doPostRequest('http://127.0.0.1:18088/ric/v1', '{"Testdataitem": "foobar"}')
+    assert resp.text == '{"Testdataitem": "foobar"}'
+    assert resp.status_code == 200
+
+    resp = doDeleteRequest('http://127.0.0.1:18088/ric/v1/delete')
+    assert resp.text == ""
+    assert resp.status_code == 204
+    # not found case
+    resp = doGetRequest('http://127.0.0.1:18088/ricci/v1/subscriptions')
+    assert resp.text == ""
+    assert resp.status_code == 404
diff --git a/tests/test_subscribe.py b/tests/test_subscribe.py
new file mode 100644 (file)
index 0000000..71dc8ca
--- /dev/null
@@ -0,0 +1,157 @@
+import json
+import ricxappframe.xapp_subscribe
+import ricxappframe.subsclient
+import ricxappframe.xapp_rest
+
+
+class MockApiClientResponse:
+    def __init__(self, data, reason, status):
+        self.data = data
+        self.status = status
+        self.reason = reason
+
+
+class MockApiClientLoader(ricxappframe.subsclient.ApiClient):
+    def __init__(self, config):
+        return
+
+    def __del__(self):
+        return
+
+    def request(self, method, url, headers, body=None):
+        if method == 'POST':
+            data = (
+                '{ "SubscriptionResponse": {'
+                '"SubscriptionId": "testing",'
+                '"SubscriptionInstances": [{'
+                '"XappEventInstanceID": "16253",'
+                '"E2EventInstanceID": "1241"'
+                '}]'
+                '}}'
+            )
+            return MockApiClientResponse(data, 'OK', 200)
+        elif method == 'DELETE':
+            return MockApiClientResponse(None, 'OK', 204)
+        elif method == 'GET':
+            data = (
+                '{ "SubscriptionList": [{'
+                '"SubscriptionId": "12345",'
+                '"Meid": "gnb123456",'
+                '"ClientEndpoint": ["127.0.0.1:4056"],'
+                '"SubscriptionInstances": [{'
+                '"XappEventInstanceID": "16253",'
+                '"E2EventInstanceID": "1241"'
+                '}]'
+                '}]'
+                '}'
+            )
+            return MockApiClientResponse(data, 'OK', 200)
+
+
+def test_subscribe(monkeypatch):
+
+    monkeypatch.setattr("ricxappframe.subsclient.ApiClient", MockApiClientLoader)
+
+    subscriber = ricxappframe.xapp_subscribe.NewSubscriber("http://127.0.0.1:8088/ric/v1", local_port=9099)
+    # setup the subscription
+    subEndPoint = subscriber.SubscriptionParamsClientEndpoint("localhost", 8091, 4061)
+    assert subEndPoint.to_dict() == {'host': 'localhost', 'http_port': 8091, 'rmr_port': 4061}
+
+    subsDirective = subscriber.SubscriptionParamsE2SubscriptionDirectives(10, 2, False)
+    assert subsDirective.to_dict() == {'e2_retry_count': 2, 'e2_timeout_timer_value': 10, 'rmr_routing_needed': False}
+
+    subsequentAction = subscriber.SubsequentAction("continue", "w10ms")
+    assert subsequentAction.to_dict() == {'subsequent_action_type': 'continue', 'time_to_wait': 'w10ms'}
+
+    actionDefinitionList = subscriber.ActionToBeSetup(1, "policy", (11, 12, 13, 14, 15), subsequentAction)
+    assert actionDefinitionList.to_dict() == {
+                                                'action_definition': (11, 12, 13, 14, 15),
+                                                'action_id': 1, 'action_type': 'policy',
+                                                'subsequent_action': {
+                                                    'subsequent_action_type': 'continue',
+                                                    'time_to_wait': 'w10ms'
+                                                }
+                                             }
+
+    subsDetail = subscriber.SubscriptionDetail(12110, (1, 2, 3, 4, 5), actionDefinitionList)
+    assert subsDetail.to_dict() == {
+                                        'action_to_be_setup_list': {
+                                            'action_definition': (11, 12, 13, 14, 15),
+                                            'action_id': 1, 'action_type': 'policy',
+                                            'subsequent_action': {
+                                                'subsequent_action_type': 'continue',
+                                                'time_to_wait': 'w10ms'
+                                            }
+                                        },
+                                        'event_triggers': (1, 2, 3, 4, 5),
+                                        'xapp_event_instance_id': 12110
+                                    }
+
+    # subscription data ready, make the subscription
+    subObj = subscriber.SubscriptionParams("sub10", subEndPoint, "gnb123456", 1231, subsDirective, subsDetail)
+    assert subObj.to_dict() == {
+                                    'client_endpoint': {
+                                        'host': 'localhost', 'http_port': 8091, 'rmr_port': 4061
+                                    },
+                                    'e2_subscription_directives': {
+                                        'e2_retry_count': 2, 'e2_timeout_timer_value': 10,
+                                        'rmr_routing_needed': False
+                                    },
+                                    'meid': 'gnb123456', 'ran_function_id': 1231, 'subscription_details': {
+                                        'action_to_be_setup_list': {
+                                            'action_definition': (11, 12, 13, 14, 15),
+                                            'action_id': 1, 'action_type': 'policy', 'subsequent_action': {
+                                                'subsequent_action_type': 'continue', 'time_to_wait': 'w10ms'
+                                            }
+                                        },
+                                        'event_triggers': (1, 2, 3, 4, 5), 'xapp_event_instance_id': 12110
+                                    },
+                                    'subscription_id': 'sub10'
+                                }
+
+    data, resp, status = subscriber.Subscribe(subObj)
+    assert json.loads(data) == {"SubscriptionResponse": {
+                                    "SubscriptionId": "testing", "SubscriptionInstances": [{
+                                        "XappEventInstanceID": "16253", "E2EventInstanceID": "1241"
+                                    }]
+                                }}
+    assert resp == 'OK'
+    assert status == 200
+
+
+def test_unsubscribe(monkeypatch):
+
+    monkeypatch.setattr("ricxappframe.subsclient.ApiClient", MockApiClientLoader)
+
+    subscriber = ricxappframe.xapp_subscribe.NewSubscriber("http://127.0.0.1:8088/ric/v1", local_port=9099)
+    data, resp, status = subscriber.UnSubscribe('1654236')
+    assert resp == 'OK'
+    assert status == 204
+
+
+def test_QuerySubscriptions(monkeypatch):
+
+    monkeypatch.setattr("ricxappframe.subsclient.ApiClient", MockApiClientLoader)
+
+    subscriber = ricxappframe.xapp_subscribe.NewSubscriber("http://127.0.0.1:8088/ric/v1", local_port=9099)
+    data, resp, status = subscriber.QuerySubscriptions()
+    assert json.loads(data) == {'SubscriptionList': [{'SubscriptionId': '12345', 'Meid': 'gnb123456',
+                                'ClientEndpoint': ['127.0.0.1:4056'], 'SubscriptionInstances':
+                                [{'XappEventInstanceID': '16253', 'E2EventInstanceID': '1241'}]}]}
+    assert resp == 'OK'
+    assert status == 200
+
+
+def test_ResponseHandler(monkeypatch):
+
+    def subsResponseCB(name, path, data, ctype):
+        response = ricxappframe.xapp_rest.initResponse()
+        response['payload'] = ("{}")
+        return response
+
+    monkeypatch.setattr("ricxappframe.subsclient.ApiClient", MockApiClientLoader)
+
+    subscriber = ricxappframe.xapp_subscribe.NewSubscriber("http://127.0.0.1:8088/ric/v1", local_port=9099)
+    ret = subscriber.ResponseHandler(subsResponseCB)
+
+    assert ret is True
diff --git a/tests/test_symptomdata.py b/tests/test_symptomdata.py
new file mode 100644 (file)
index 0000000..93a8fdb
--- /dev/null
@@ -0,0 +1,149 @@
+import os
+import requests
+from zipfile import ZipFile
+from requests import Response as response
+from ricxappframe.xapp_symptomdata import Symptomdata
+
+
+def new_loaddata(*args, **kwargs):
+    # Your custom testing override
+    return ""
+
+
+class MockResponse(object):
+    def __init__(self, reponse, jsonout):
+        self.status_code = response
+        self.url = 'http://lwsd.ricplt:8089/ric/v1/lwsd'
+        self.headers = {'Content-type': 'application/json'}
+        self.jsonout = jsonout
+
+    def json(self):
+        return self.jsonout
+
+    def raise_for_status(self):
+        return self.status_code
+
+
+class MockStat(object):
+    def __init__(self, st_ctime=None):
+        self.st_ctime = st_ctime
+
+
+class MockOs(object):
+    def __init__(self, walk=None, st_ctime=None):
+        self.walkresp = walk
+        self.st_ctime = st_ctime
+
+    def walk(self, path):
+        return self.walkresp
+
+    def stat(self, filename):
+        st = MockStat(self.st_ctime)
+        return st
+
+
+def test_symptomdata_subscribe(monkeypatch):
+    def mock_requests_post(uri, data, headers, proxies):
+        print("%s %s" % (uri, data))
+        return MockResponse(200, [{'service': 'xapp.service'}])
+
+    def mock_requests_get(uri, headers, proxies):
+        print("%s" % (uri))
+        return MockResponse(200, [])
+
+    # mock the http get and post
+    monkeypatch.setattr(requests, 'post', mock_requests_post)
+    monkeypatch.setattr(requests, 'get', mock_requests_get)
+
+    # this will return not found
+    s = Symptomdata("xapp", "xapp.ricxapp.service", "tmp", "http://lwsd.ricplt:8089/ric/v1/lwsd")
+    # stop timer loop
+    s.stop()
+    # make subscription
+    s.subscribe(None)
+    assert s.lwsdok is True
+
+
+def test_symptomdata_subscribe_exists(monkeypatch):
+    def mock_requests_get(uri, headers, proxies):
+        print("%s" % (uri))
+        return MockResponse(200, [{'service': 'xapp_other'}, {'service': 'xapp'}])
+
+    # mock the http get
+    monkeypatch.setattr(requests, 'get', mock_requests_get)
+
+    # this will return not found
+    s = Symptomdata("xapp", "xapp.ricxapp.service", "tmp", "http://lwsd.ricplt:8089/ric/v1/lwsd")
+    # stop timer loop
+    s.stop()
+    assert s.lwsdok is True
+
+
+def test_symptomdata_collect_time(monkeypatch):
+    myos = MockOs(walk=[('mydir', (), ('file1.csv', 'file2.csv', 'file3.txt', 'file.json'))], st_ctime=1647502471)
+
+    def mock_requests_get(uri, headers, proxies):
+        return MockResponse(200, [{'service': 'xapp_other'}, {'service': 'xapp'}])
+
+    def mock_os_walk(path):
+        return myos.walk(path)
+
+    def mock_os_stat(filename):
+        return myos.stat(filename)
+
+    def mock_zipfile_write(me, fromfile, tofile):
+        return
+
+    # mock the http get
+    monkeypatch.setattr(requests, 'get', mock_requests_get)
+    # mock the os walk
+    monkeypatch.setattr(os, 'walk', mock_os_walk)
+    # mock the os stat
+    monkeypatch.setattr(os, 'stat', mock_os_stat)
+
+    # mock the zipfile stat
+    monkeypatch.setattr(ZipFile, 'write', mock_zipfile_write)
+
+    # this will return not found
+    s = Symptomdata("xapp", "xapp.ricxapp.service", "tmp", "http://lwsd.ricplt:8089/ric/v1/lwsd")
+    # stop timer loop
+    s.stop()
+    assert s.lwsdok is True
+
+    zipfile = s.collect("zipfile.zip", (r'/tmp/csv/.*\.csv', r'/tmp/json/.*\.json'), 1647502470, 1647502570)
+    assert zipfile is not None
+
+
+def test_symptomdata_collect(monkeypatch):
+    myos = MockOs(walk=[('mydir', (), ('file1.csv', 'file2.csv', 'file3.txt', 'file.json'))], st_ctime=1647502471)
+
+    def mock_requests_get(uri, headers, proxies):
+        return MockResponse(200, [{'service': 'xapp_other'}, {'service': 'xapp'}])
+
+    def mock_os_walk(path):
+        return myos.walk(path)
+
+    def mock_os_stat(filename):
+        return myos.stat(filename)
+
+    def mock_zipfile_write(me, fromfile, tofile):
+        return
+
+    # mock the http get
+    monkeypatch.setattr(requests, 'get', mock_requests_get)
+    # mock the os walk
+    monkeypatch.setattr(os, 'walk', mock_os_walk)
+    # mock the os stat
+    monkeypatch.setattr(os, 'stat', mock_os_stat)
+
+    # mock the zipfile stat
+    monkeypatch.setattr(ZipFile, 'write', mock_zipfile_write)
+
+    # this will return not found
+    s = Symptomdata("xapp", "xapp.ricxapp.service", "tmp", "http://lwsd.ricplt:8089/ric/v1/lwsd")
+    # stop timer loop
+    s.stop()
+    assert s.lwsdok is True
+
+    zipfile = s.collect("zipfile.zip", ('/tmp/csv/.*.csv', '/tmp/json/.*.json'), 0, 0)
+    assert zipfile is not None
index 3706f30..20ebe86 100644 (file)
@@ -22,6 +22,8 @@ from ricxappframe.util.constants import Constants
 from ricxappframe.xapp_frame import _BaseXapp, Xapp, RMRXapp
 from ricxappframe.constants import sdl_namespaces
 
+import ricxappframe.entities.rnib.nb_identity_pb2 as pb_nb
+
 rmr_xapp = None
 rmr_xapp_health = None
 gen_xapp = None
@@ -110,7 +112,7 @@ def test_rmr_healthcheck():
     assert health_pay == b"OK\n"
 
 
-def test_get_list_nodeb(rnib_information):
+def test_rnib_get_list_nodeb(rnib_information):
     global rnib_xapp
     rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
 
@@ -135,6 +137,151 @@ def test_get_list_nodeb(rnib_information):
     for enb in enb_list:
         assert enb.SerializeToString() in rnib_information
 
+    rnib_xapp.stop()
+
+
+def test_rnib_get_list_all_nodeb(rnib_information):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+
+    # Add rnib information directly.
+    for rnib in rnib_information:
+        rnib_xapp.sdl.add_member(sdl_namespaces.E2_MANAGER, "GNB", rnib, usemsgpack=False)
+
+    nb_list = rnib_xapp.GetListNodebIds()
+    assert len(nb_list) == 2
+
+    for rnib in rnib_information:
+        rnib_xapp.sdl.add_member(sdl_namespaces.E2_MANAGER, "ENB", rnib, usemsgpack=False)
+
+    nb_list = rnib_xapp.GetListNodebIds()
+    assert len(nb_list) == 4
+
+    rnib_xapp.stop()
+
+
+def test_rnib_get_list_cells(rnib_cellinformation):
+    global rnib_xapp
+
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+
+    mynb = pb_nb.NbIdentity()
+    mynb.inventory_name = "nodeb_1234"
+    mynb.global_nb_id.plmn_id = "plmn_1234"
+    mynb.global_nb_id.nb_id = "nb_1234"
+    mynb.connection_status = 1
+    rnib_xapp.sdl.add_member(sdl_namespaces.E2_MANAGER, "ENB", mynb.SerializeToString(), usemsgpack=False)
+
+    # Add rnib information directly.
+    for rnib in rnib_cellinformation:
+        rnib_xapp.sdl.add_member(sdl_namespaces.E2_MANAGER, "ENBCELL1", rnib, usemsgpack=False)
+        rnib_xapp.sdl.add_member(sdl_namespaces.E2_MANAGER, "ENBCELL2", rnib, usemsgpack=False)
+    rnib_xapp.stop()
+
+
+def test_rnib_get_nodeb(rnib_helpers):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+    nb1 = rnib_helpers.createNodebInfo('nodeb_1234', 'GNB', '192.168.1.1', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1234', nb1.SerializeToString(), usemsgpack=False)
+    nb2 = rnib_helpers.createNodebInfo('nodeb_1234', 'ENB', '192.168.1.2', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1235', nb2.SerializeToString(), usemsgpack=False)
+
+    gnb = rnib_xapp.GetNodeb('nodeb_1235')
+    assert gnb == nb2
+    gnb = rnib_xapp.GetNodeb('nodeb_1234')
+    assert gnb == nb1
+    gnb = rnib_xapp.GetNodeb('nodeb_1230')
+    assert gnb is None
+    rnib_xapp.stop()
+
+
+def test_rnib_get_cell(rnib_helpers):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+    c1 = rnib_helpers.createCell('c1234', 8)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "PCI:c1234:08", c1.SerializeToString(), usemsgpack=False)
+    c2 = rnib_helpers.createCell('c1235', 11)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "PCI:c1235:0b", c2.SerializeToString(), usemsgpack=False)
+
+    cell = rnib_xapp.GetCell('c1235', 11)
+    assert cell == c2
+    cell = rnib_xapp.GetCell('c1234', 8)
+    assert cell == c1
+    cell = rnib_xapp.GetCell('c1236', 11)
+    assert cell is None
+    rnib_xapp.stop()
+
+
+def test_rnib_get_cell_by_id(rnib_helpers):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+    c1 = rnib_helpers.createCell('c1234', 8)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "CELL:c1234", c1.SerializeToString(), usemsgpack=False)
+    c2 = rnib_helpers.createCell('c1235', 11)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "CELL:c1235", c2.SerializeToString(), usemsgpack=False)
+
+    cell = rnib_xapp.GetCellById('LTE_CELL', 'c1235')
+    assert cell == c2
+    cell = rnib_xapp.GetCellById('LTE_CELL', 'c1234')
+    assert cell == c1
+    cell = rnib_xapp.GetCellById('LTE_CELL', 'c1236')
+    assert cell is None
+    rnib_xapp.stop()
+
+
+def test_rnib_get_cells(rnib_helpers):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+    nb1 = rnib_helpers.createNodebInfo('nodeb_1234', 'GNB', '192.168.1.1', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1234', nb1.SerializeToString(), usemsgpack=False)
+    nb2 = rnib_helpers.createNodebInfo('nodeb_1234', 'ENB', '192.168.1.2', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1235', nb2.SerializeToString(), usemsgpack=False)
+
+    sc = rnib_xapp.GetCellList('nodeb_1235')
+    assert sc == nb2.enb.served_cells
+    sc = rnib_xapp.GetCellList('nodeb_1234')
+    assert sc == nb1.gnb.served_nr_cells
+    sc = rnib_xapp.GetCellList('nodeb_1230')
+    assert sc is None
+    rnib_xapp.stop()
+
+
+def test_rnib_get_global_nodeb(rnib_helpers):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+    nb1 = rnib_helpers.createNodeb('nodeb_1234', '358', 'nb_1234')
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "GNB:" + '358:' + 'nodeb_1234', nb1.SerializeToString(), usemsgpack=False)
+    nb2 = rnib_helpers.createNodeb('nodeb_1235', '356', 'nb_1235')
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "GNB:" + '356:' + 'nodeb_1235', nb2.SerializeToString(), usemsgpack=False)
+
+    gnb = rnib_xapp.GetNodebByGlobalNbId('GNB', '356', 'nodeb_1235')
+    assert gnb == nb2
+    gnb = rnib_xapp.GetNodebByGlobalNbId('GNB', '358', 'nodeb_1234')
+    assert gnb == nb1
+    gnb = rnib_xapp.GetNodebByGlobalNbId('GNB', '356', 'nodeb_1230')
+    assert gnb is None
+    rnib_xapp.stop()
+
+
+def test_rnib_get_ranfunction(rnib_helpers):
+    global rnib_xapp
+    rnib_xapp = _BaseXapp(rmr_port=4777, rmr_wait_for_ready=False, use_fake_sdl=True)
+    nb1 = rnib_helpers.createNodebInfo('nodeb_1234', 'GNB', '192.168.1.1', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1234', nb1.SerializeToString(), usemsgpack=False)
+    nb2 = rnib_helpers.createNodebInfo('nodeb_1235', 'GNB', '192.168.1.2', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1235', nb2.SerializeToString(), usemsgpack=False)
+    nb3 = rnib_helpers.createNodebInfo('nodeb_1236', 'GNB', '192.168.1.2', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1236', nb3.SerializeToString(), usemsgpack=False)
+    nb4 = rnib_helpers.createNodebInfo('nodeb_1237', 'GNB', '192.168.1.2', 8088)
+    rnib_xapp.sdl.set(sdl_namespaces.E2_MANAGER, "RAN:" + 'nodeb_1237', nb4.SerializeToString(), usemsgpack=False)
+
+    sc = rnib_xapp.GetRanFunctionDefinition('nodeb_1235', "1.3.6.1.4.1.1.2.2.2")
+    assert sc == ['te524367153']
+    sc = rnib_xapp.GetRanFunctionDefinition('nodeb_1235', "1.3.6.1.4.1.1.2.2.5")
+    assert sc == []
+    rnib_xapp.stop()
+
 
 def teardown_module():
     """
@@ -148,5 +295,3 @@ def teardown_module():
         rmr_xapp.stop()
     with suppress(Exception):
         rmr_xapp_health.stop()
-    with suppress(Exception):
-        rnib_xapp.stop()
diff --git a/tox.ini b/tox.ini
index 0180e50..2497e9c 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -24,11 +24,11 @@ deps=
     pytest
     coverage
     pytest-cov
+    six
 setenv =
     LD_LIBRARY_PATH = /usr/local/lib/:/usr/local/lib64
     RMR_SEED_RT = tests/fixtures/test_local.rt
     RMR_ASYNC_CONN = 0
-
 commands =
     # add -s flag after pytest to show logs immediately instead of delaying
     pytest --cov ricxappframe --cov-report xml --cov-report term-missing --cov-report html --cov-fail-under=70 --junitxml=/tmp/tests.xml
@@ -42,7 +42,7 @@ commands = flake8 setup.py ricxappframe tests
 
 [flake8]
 extend-ignore = E501,E741,E731
-exclude = ricxappframe/entities
+exclude = ricxappframe/entities,ricxappframe/subsclient
 
 [testenv:clm]
 # use pip to gather dependencies with versions for CLM analysis