RIC-769: Committing individual files rather than tar archive 16/5816/1
authorwahidw <abdulwahid.w@nokia.com>
Mon, 29 Mar 2021 04:22:36 +0000 (04:22 +0000)
committerwahidw <abdulwahid.w@nokia.com>
Mon, 29 Mar 2021 04:24:28 +0000 (04:24 +0000)
Signed-off-by: wahidw <abdulwahid.w@nokia.com>
Change-Id: Id8c3838d37b5f82a47d90228d0e6619dc823d935

86 files changed:
xapp_orchestrater/dev/INFO.yaml [new file with mode: 0644]
xapp_orchestrater/dev/LICENSES.txt [new file with mode: 0644]
xapp_orchestrater/dev/README.md [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/README.md [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-go/Dockerfile [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-go/container-tag.yaml [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-mdclog/Dockerfile [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-mdclog/container-tag.yaml [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-rmr/Dockerfile [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-rmr/container-tag.yaml [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3/Dockerfile [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-alpine3/container-tag.yaml [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-ubuntu18-c-go/Dockerfile [new file with mode: 0644]
xapp_orchestrater/dev/bldr-imgs/bldr-ubuntu18-c-go/container-tag.yaml [new file with mode: 0644]
xapp_orchestrater/dev/ci/xapp_onboarder/Dockerfile [new file with mode: 0644]
xapp_orchestrater/dev/ci/xapp_onboarder/container-tag.yaml [new file with mode: 0644]
xapp_orchestrater/dev/docs/_static/css/s4defs-roles.css [new file with mode: 0644]
xapp_orchestrater/dev/docs/_static/logo.png [new file with mode: 0644]
xapp_orchestrater/dev/docs/conf.py [new file with mode: 0644]
xapp_orchestrater/dev/docs/conf.yaml [new file with mode: 0644]
xapp_orchestrater/dev/docs/favicon.ico [new file with mode: 0644]
xapp_orchestrater/dev/docs/index.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/release-notes.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/requirements-docs.txt [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/guide/config-file.json [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/guide/descriptor.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/guide/embedded-schema.json [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/guide/example.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/guide/schema.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/guide_index.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/images/onboard.png [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/images/xapp-flow.png [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/index.rst [new file with mode: 0644]
xapp_orchestrater/dev/docs/xapp_onboarder/overview.rst [new file with mode: 0644]
xapp_orchestrater/dev/releases/alpine3-mdclog-container.yaml [new file with mode: 0644]
xapp_orchestrater/dev/releases/alpine3-rmr-container.yaml [new file with mode: 0644]
xapp_orchestrater/dev/releases/container-release-ric-plt-xapponboarder.yaml [new file with mode: 0644]
xapp_orchestrater/dev/tox.ini [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/MANIFEST.in [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/README.md [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/charts/index-cache.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/requirements.txt [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/setup.cfg [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/setup.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/conftest.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/constants.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/mock_helm_repo/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/mock_helm_repo/mock_helm_repo.py [new file with mode: 0755]
xapp_orchestrater/dev/xapp_onboarder/tests/test_api.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/test_helm_controller.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tests/test_trim_thread.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/tox.ini [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/api_reference.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/charts.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/charts_ep.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/health_check_ep.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/onboard_ep.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/request_models.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/response_models.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/onboard.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/artifacts_manager.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/xApp_builder.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/xapp_schema.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/logging.conf [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/repo_manager/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/repo_manager/repo_manager.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/Chart.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/_helpers.tpl [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/appconfig.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/appenv.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/deployment.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/service-http.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/service-rmr.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/values.yaml [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/__init__.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/cli.py [new file with mode: 0755]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/server.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/settings.py [new file with mode: 0644]
xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/xapp-onboarder-api.yaml [new file with mode: 0644]
xapp_orchestrater/xapp_orchestrater.tgz [deleted file]

diff --git a/xapp_orchestrater/dev/INFO.yaml b/xapp_orchestrater/dev/INFO.yaml
new file mode 100644 (file)
index 0000000..7f57254
--- /dev/null
@@ -0,0 +1,54 @@
+---
+project: 'Integration and Testing'
+project_creation_date: '2019-05-21'
+project_category: ''
+lifecycle_state: 'Incubation'
+project_lead: &it-dev_ptl
+    name: 'Lusheng Ji'
+    email: 'lji@research.att.com'
+    id: 'wrider'
+    company: 'AT&T Labs-Research'
+    timezone: 'America/New_York'
+primary_contact: *it-dev_ptl
+issue_tracking:
+    type: 'jira'
+    url: 'https://jira.o-ran-sc.org/projects/INT'
+    key: 'INT'
+mailing_list:
+    type: 'groups.io'
+    url: 'https://lists.o-ran-sc.org/g/main'
+    tag: '<[it/dev]>'
+realtime_discussion:
+    type: 'irc'
+    server: 'freenode.net'
+    channel: '#o-ran-sc'
+meetings:
+    - type: 'zoom'
+      agenda: ''
+      url: ''
+      server: 'n/a'
+      channel: 'n/a'
+      repeats: 'weekly'
+      time: ''
+repositories:
+    - 'it/dev'
+committers:
+    - <<: *it-dev_ptl
+    - name: 'Zhe Huang'
+      email: 'zhehuang@research.att.com'
+      company: 'AT&T Labs-Research'
+      id: 'eefelixwong'
+      timezone: 'America/New_York'
+    - name: 'Dave Korman'
+      email: 'davek@research.att.com'
+      company: 'AT&T Labs-Research'
+      id: 'multics'
+      timezone: 'America/New_York'
+    - name: 'Chris Lott'
+      email: 'clott@research.att.com'
+      company: 'AT&T Labs-Research'
+      id: 'cl778h'
+      timezone: 'America/New_York'
+tsc:
+    # yamllint disable rule:line-length
+    approval: 'https://wiki.o-ran-sc.org/display/TOC#O-RANSCTechnicalOversightCommittee(TOC)-20190821'
diff --git a/xapp_orchestrater/dev/LICENSES.txt b/xapp_orchestrater/dev/LICENSES.txt
new file mode 100644 (file)
index 0000000..a9db3d0
--- /dev/null
@@ -0,0 +1,31 @@
+LICENSES.txt
+
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the "Software License");
+you may not use this software except in compliance with the Software
+License. You may obtain a copy of the Software License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the Software License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the Software License for the specific language governing permissions
+and limitations under the Software License.
+
+
+
+Unless otherwise specified, all documentation contained herein is licensed
+under the Creative Commons License, Attribution 4.0 Intl. (the
+"Documentation License"); you may not use this documentation except in
+compliance with the Documentation License. You may obtain a copy of the
+Documentation License at
+
+https://creativecommons.org/licenses/by/4.0/
+
+Unless required by applicable law or agreed to in writing, documentation
+distributed under the Documentation License is distributed on an "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied. See the Documentation License for the specific language governing
+permissions and limitations under the Documentation License.
diff --git a/xapp_orchestrater/dev/README.md b/xapp_orchestrater/dev/README.md
new file mode 100644 (file)
index 0000000..dcc8ab0
--- /dev/null
@@ -0,0 +1 @@
+This repo holds various integration and testing development codes.
diff --git a/xapp_orchestrater/dev/bldr-imgs/README.md b/xapp_orchestrater/dev/bldr-imgs/README.md
new file mode 100644 (file)
index 0000000..0d37ad4
--- /dev/null
@@ -0,0 +1,8 @@
+# Base builder images for O-RAN-SC
+
+This area contains Dockerfiles for images suitable for use as the
+first stage in a multi-stage Docker build.  These images have large
+build and compile tools like C, C++, Golang, cmake, ninja, etc.  Using
+these base images reduces the time needed to build Docker images with
+project features. The images are published to the O-RAN-SC staging
+registry at the Linux Foundation: nexus3.o-ran-sc.org:10004
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-go/Dockerfile b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-go/Dockerfile
new file mode 100644 (file)
index 0000000..80db68f
--- /dev/null
@@ -0,0 +1,32 @@
+# ==================================================================================
+#       Copyright (c) 2020 Nokia
+#       Copyright (c) 2020 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#          http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+# ==================================================================================
+
+# Has:
+# golang 1.13.8
+# alpine 3.11
+# rmr 3.x
+
+# install a well known working rmr
+FROM golang:1.13.8-alpine3.11
+RUN apk update && apk add autoconf automake build-base cmake libtool ninja pkgconfig git sudo
+RUN git clone --branch 3.7.1 https://gerrit.oran-osc.org/r/ric-plt/lib/rmr \
+    && cd rmr \
+    && mkdir .build; cd .build \
+    && echo "<<<installing rmr devel headers>>>" \
+    && cmake .. -DDEV_PKG=1; make install \
+    && echo "<<< installing rmr .so>>>" \
+    && cmake .. -DDEV_PKG=0; make install
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-go/container-tag.yaml b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-go/container-tag.yaml
new file mode 100644 (file)
index 0000000..7fa1a65
--- /dev/null
@@ -0,0 +1,2 @@
+---
+tag: 6-a3.11-rmr3
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-mdclog/Dockerfile b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-mdclog/Dockerfile
new file mode 100644 (file)
index 0000000..f56882f
--- /dev/null
@@ -0,0 +1,56 @@
+# O-RAN-SC
+#
+# Copyright (C) 2019-2020 AT&T Intellectual Property and 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.
+
+# Provides MDCLOG for Alpine including header files and shared-object libraries,
+# basically a workaround for missing APK support at PackageCloud.io.
+# Unlike other bldr- images, this only has library files, no build tools.
+# See list of available files below.  Use the following command to copy a file
+# in a Docker build, after replacing "TAG" with the desired version string:
+#
+# COPY --from=nexus3.o-ran-sc.org:10002/bldr-alpine3-mdclog:TAG /usr/local/lib/libmdclog.so /usr/local/lib/libmdclog.so
+#
+# /usr/local/include/mdclog:
+#     mdclog.h
+#
+# /usr/local/lib:
+#     libmdclog.a
+#     libmdclog.la
+#     libmdclog.so
+#     libmdclog.so.0         (subject to version change)
+#     libmdclog.so.0.0.4     (ditto)
+
+FROM alpine:3.11 as bldr
+RUN apk update && apk add autoconf automake build-base cmake libtool pkgconfig git sudo
+
+# the autoconf-archive in alpine's edge repos is too new
+# for our purposes, so we'll use one from the source.
+RUN cd /tmp \
+    && git clone --branch v2015.09.25 git://git.sv.gnu.org/autoconf-archive.git \
+    && cp /tmp/autoconf-archive/m4/* /usr/share/aclocal \
+    && rm -rf /tmp/autoconf-archive
+
+# MCDLOG, version is pinned
+RUN cd /tmp \
+   && git clone --branch v0.0.4 https://gerrit.o-ran-sc.org/r/com/log \
+   && cd log \
+   && ./autogen.sh \
+   && ./configure \
+   && make \
+   && make install
+
+FROM scratch
+COPY --from=bldr /usr/local/include/mdclog /usr/local/include/mdclog
+COPY --from=bldr /usr/local/lib/libmdclog.* /usr/local/lib/
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-mdclog/container-tag.yaml b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-mdclog/container-tag.yaml
new file mode 100644 (file)
index 0000000..6f59723
--- /dev/null
@@ -0,0 +1,3 @@
+# Version of the com/log aka MDCLog library
+---
+tag: 0.0.4
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-rmr/Dockerfile b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-rmr/Dockerfile
new file mode 100644 (file)
index 0000000..5c65815
--- /dev/null
@@ -0,0 +1,54 @@
+# ==================================================================================
+#       Copyright (c) 2020 Nokia
+#       Copyright (c) 2020 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#          http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+# ==================================================================================
+
+# Provides RMR for Alpine including header files and shared-object libraries,
+# basically a workaround for missing APK support at PackageCloud.io.
+# Unlike other bldr- images, this only has library files, no build tools.
+# See list of available files below.  Use the following command to copy a file
+# in a Docker build, after replacing "TAG" with the desired version string:
+#
+# COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:TAG /usr/local/lib64/librmr* /usr/local/lib64/
+#
+# /usr/local/bin:
+#     rmr_probe
+#
+# /usr/local/include/rmr:
+#     RIC_message_types.h
+#     rmr.h
+#     rmr_logging.h
+#     rmr_symtab.h
+#
+# /usr/local/lib64:
+#     librmr_si.a
+#     librmr_si.so
+#     librmr_si.so.4         (subject to version change)
+#     librmr_si.so.4.0.2     (subject to version change)
+
+FROM alpine:3.11 as bldr
+RUN apk update && apk add autoconf automake build-base cmake libtool pkgconfig git sudo
+RUN git clone --branch 4.1.2 https://gerrit.oran-osc.org/r/ric-plt/lib/rmr \
+    && cd rmr \
+    && mkdir .build; cd .build \
+    && echo "<<<installing rmr devel headers>>>" \
+    && cmake .. -DDEV_PKG=1; make install \
+    && echo "<<< installing rmr .so>>>" \
+    && cmake .. -DDEV_PKG=0; make install
+
+FROM scratch
+COPY --from=bldr /usr/local/bin/rmr* /usr/local/bin/
+COPY --from=bldr /usr/local/include/rmr /usr/local/include/rmr
+COPY --from=bldr /usr/local/lib64/librmr* /usr/local/lib64/
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-rmr/container-tag.yaml b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3-rmr/container-tag.yaml
new file mode 100644 (file)
index 0000000..fe126a9
--- /dev/null
@@ -0,0 +1,2 @@
+---
+tag: 4.1.2
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3/Dockerfile b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3/Dockerfile
new file mode 100644 (file)
index 0000000..8c2ad17
--- /dev/null
@@ -0,0 +1,42 @@
+# O-RAN-SC
+#
+# Copyright (C) 2019-2020 AT&T Intellectual Property and 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.
+
+# This is an all-things-to-all-ORAN-people Alpine 3.11 build image with:
+# gcc/g++ v 8
+# golang v 1.13.x
+# python 3.7
+# ORAN libraries are not provided here to reduce version churn
+
+FROM python:3.7-alpine
+RUN apk update && apk add \
+  autoconf \
+  automake \
+  build-base \
+  cmake \
+  libtool \
+  ninja \
+  pkgconfig \
+  python-dev \
+  sudo \
+  git \
+  go
+
+# the autoconf-archive in alpine's edge repos is too new
+# for our purposes, so we'll use one from the source.
+RUN cd /tmp \
+    && git clone --branch v2015.09.25 git://git.sv.gnu.org/autoconf-archive.git \
+    && cp /tmp/autoconf-archive/m4/* /usr/share/aclocal \
+    && rm -rf /tmp/autoconf-archive
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3/container-tag.yaml b/xapp_orchestrater/dev/bldr-imgs/bldr-alpine3/container-tag.yaml
new file mode 100644 (file)
index 0000000..a8e11aa
--- /dev/null
@@ -0,0 +1,3 @@
+# Not feasible to show all the software versions
+---
+tag: 12-a3.11
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-ubuntu18-c-go/Dockerfile b/xapp_orchestrater/dev/bldr-imgs/bldr-ubuntu18-c-go/Dockerfile
new file mode 100644 (file)
index 0000000..c7be3e4
--- /dev/null
@@ -0,0 +1,110 @@
+# O-RAN-SC
+#
+# Copyright (C) 2019-2020 AT&T Intellectual Property and 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.
+
+# Builder image with superset of CI tools for RIC components
+
+FROM nexus3.o-ran-sc.org:10001/ubuntu:18.04
+
+RUN apt-get update && apt-get install -y \
+    alien \
+    autoconf \
+    autoconf-archive \
+    automake \
+    autotools-dev \
+    build-essential \
+    cmake \
+    g++  \
+    gcc \
+    git \
+    ksh \
+    libbz2-dev \
+    libicu-dev \
+    libsctp-dev \
+    libtool \
+    lksctp-tools \
+    make \
+    python-dev \
+    pkg-config \
+    software-properties-common \
+    sudo \
+    wget \
+    zlib1g \
+    zlib1g-dev \
+    zlibc \
+    zip
+
+WORKDIR /tmp
+
+# Install go versions in /opt
+RUN mkdir -p /opt/go
+
+ARG g12="1.12.17"
+RUN wget -nv https://dl.google.com/go/go${g12}.linux-amd64.tar.gz \
+    && tar -xf go${g12}.linux-amd64.tar.gz \
+    && mv go /opt/go/1.12 \
+    && rm -f go*.gz
+
+ARG g13="1.13.12"
+RUN wget -nv https://dl.google.com/go/go${g13}.linux-amd64.tar.gz \
+    && tar -xf go${g13}.linux-amd64.tar.gz \
+    && mv go /opt/go/1.13 \
+    && rm -f go*.gz
+
+ARG g14="1.14.4"
+RUN wget -nv https://dl.google.com/go/go${g14}.linux-amd64.tar.gz \
+    && tar -xf go${g14}.linux-amd64.tar.gz \
+    && mv go /opt/go/1.14 \
+    && rm -f go*.gz
+
+ENV GOPATH=/root/go
+# Default path has go version 1.12.x
+# Use /opt/go/1.13/bin for version 1.13.x
+# Use /opt/go/1.14/bin for version 1.14.x
+ENV PATH=$PATH:/opt/go/1.12/bin:$GOPATH/bin
+
+# This installs go-acc to GOPATH
+RUN go version \
+    && go get -v github.com/ory/go-acc \
+    && go-acc --help
+
+# install a recent version of cmake, ubuntu repo version is old
+ARG cv="3.14.5"
+RUN wget -nv https://github.com/Kitware/CMake/releases/download/v${cv}/cmake-${cv}-Linux-x86_64.sh \
+    && chmod +x cmake-${cv}-Linux-x86_64.sh \
+    && ./cmake-${cv}-Linux-x86_64.sh --prefix=/usr/local --skip-license \
+    && rm -f cmake*.sh
+
+# sonar-scanner is not available in ubuntu repo
+ARG sv="4.2.0.1873"
+RUN wget -nv https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${sv}-linux.zip \
+    && unzip sonar-scanner-cli-${sv}-linux.zip \
+    && mv sonar-scanner-${sv}-linux /usr/local/sonar-scanner \
+    && rm -f sonar*.zip
+
+# golangci-lint is not available in ubuntu repo
+RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $GOPATH/bin v1.23.6 \
+    && rm -f install.sh
+
+# install a recent version of boost, ubuntu repo version is old
+ARG bv="1_69_0"
+RUN wget -nv https://dl.bintray.com/boostorg/release/1.69.0/source/boost_${bv}.zip \
+    && unzip -q boost_${bv}.zip \
+    && cd boost_${bv} \
+    && ./bootstrap.sh --prefix=/usr/ \
+    && ./b2 \
+    && ./b2 install \
+    && cd ../ \
+    && rm -rf boost*.zip boost_${bv}
diff --git a/xapp_orchestrater/dev/bldr-imgs/bldr-ubuntu18-c-go/container-tag.yaml b/xapp_orchestrater/dev/bldr-imgs/bldr-ubuntu18-c-go/container-tag.yaml
new file mode 100644 (file)
index 0000000..54cbd00
--- /dev/null
@@ -0,0 +1,4 @@
+# Not feasible to show all the software versions
+# here so just use a counter plus the base image
+---
+tag: 9-u18.04
diff --git a/xapp_orchestrater/dev/ci/xapp_onboarder/Dockerfile b/xapp_orchestrater/dev/ci/xapp_onboarder/Dockerfile
new file mode 100644 (file)
index 0000000..28a72b1
--- /dev/null
@@ -0,0 +1,27 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+FROM python:3.7-alpine
+
+ADD ./xapp_onboarder /opt/xapp_onboarder
+
+RUN cd /opt/xapp_onboarder && pip3 install . && rm -r /opt/xapp_onboarder
+
+ARG HELM_VERSION="2.12.3"
+
+RUN wget https://storage.googleapis.com/kubernetes-helm/helm-v${HELM_VERSION}-linux-amd64.tar.gz && tar -xvf helm-v${HELM_VERSION}-linux-amd64.tar.gz && mv linux-amd64/helm /usr/local/bin/helm && rm -r linux-amd64 && rm helm-v${HELM_VERSION}-linux-amd64.tar.gz
+
+ENTRYPOINT ["xapp_onboarder"]
diff --git a/xapp_orchestrater/dev/ci/xapp_onboarder/container-tag.yaml b/xapp_orchestrater/dev/ci/xapp_onboarder/container-tag.yaml
new file mode 100644 (file)
index 0000000..ab18407
--- /dev/null
@@ -0,0 +1 @@
+tag: 1.0.8
diff --git a/xapp_orchestrater/dev/docs/_static/css/s4defs-roles.css b/xapp_orchestrater/dev/docs/_static/css/s4defs-roles.css
new file mode 100644 (file)
index 0000000..f47492d
--- /dev/null
@@ -0,0 +1,316 @@
+.black {
+    color: black;
+}
+
+.gray {
+    color: gray;
+}
+
+.grey {
+    color: gray;
+}
+
+.silver {
+    color: silver;
+}
+
+.white {
+    color: white;
+}
+
+.maroon {
+    color: maroon;
+}
+
+.red {
+    color: red;
+}
+
+.magenta {
+    color: magenta;
+}
+
+.fuchsia {
+    color: fuchsia;
+}
+
+.pink {
+    color: pink;
+}
+
+.orange {
+    color: orange;
+}
+
+.yellow {
+    color: yellow;
+}
+
+.lime {
+    color: lime;
+}
+
+.green {
+    color: green;
+}
+
+.olive {
+    color: olive;
+}
+
+.teal {
+    color: teal;
+}
+
+.cyan {
+    color: cyan;
+}
+
+.aqua {
+    color: aqua;
+}
+
+.blue {
+    color: blue;
+}
+
+.navy {
+    color: navy;
+}
+
+.purple {
+    color: purple;
+}
+
+.under {
+    text-decoration: underline;
+}
+
+.over {
+    text-decoration: overline;
+}
+
+.blink {
+    text-decoration: blink;
+}
+
+.line {
+    text-decoration: line-through;
+}
+
+.strike {
+    text-decoration: line-through;
+}
+
+.it {
+    font-style: italic;
+}
+
+.ob {
+    font-style: oblique;
+}
+
+.small {
+    font-size: small;
+}
+
+.large {
+    font-size: large;
+}
+
+.smallpar {
+    font-size: small;
+}
+
+
+/* Style pour les badges en bas de la page. */
+
+div.supportBadges {
+    margin: 1em;
+    text-align: right;
+}
+
+div.supportBadges ul {
+    padding: 0;
+    display: inline;
+}
+
+div.supportBadges li {
+    display: inline;
+}
+
+div.supportBadges a {
+    margin-right: 1px;
+    opacity: 0.6;
+}
+
+div.supportBadges a:hover {
+    opacity: 1;
+}
+
+
+/* Details elements in the sidebar */
+
+a.reference {
+    border-bottom: none;
+    text-decoration: none;
+}
+
+ul.details {
+    font-size: 80%;
+}
+
+ul.details li p {
+    font-size: 85%;
+}
+
+ul.externallinks {
+    font-size: 85%;
+}
+
+
+/* Pour le drapeau de langue */
+
+img.languageswitch {
+    width: 50px;
+    height: 32px;
+    margin-left: 5px;
+    vertical-align: bottom;
+}
+
+div.sphinxsidebar {
+    overflow: hidden !important;
+    font-size: 120%;
+    word-wrap: break-word;
+    width: 300px;
+    max-width: 300px;
+}
+
+div.sphinxsidebar h3 {
+    font-size: 125%;
+}
+
+div.sphinxsidebar h4 {
+    font-size: 110%;
+}
+
+div.sphinxsidebar a {
+    font-size: 85%;
+}
+
+
+/* Image style for scrollUp jQuery plugin */
+
+#scrollUpLeft {
+    bottom: 50px;
+    left: 260px;
+    height: 38px;
+    width: 38px;
+    background: url('//perso.crans.org/besson/_images/.top.svg');
+    background: url('../_images/.top.svg');
+}
+
+@media screen and (max-width: 875px) {
+    #scrollUpLeft {
+        right: 50px;
+        left: auto;
+    }
+}
+
+
+/* responsive for font-size. */
+
+@media (max-width: 875px) {
+    body {
+        font-size: 105%;
+        /* Increase font size for responsive theme */
+    }
+}
+
+@media (max-width: 1480px) and (min-width: 876px) {
+    body {
+        font-size: 110%;
+        /* Increase font size for not-so-big screens */
+    }
+}
+
+@media (min-width: 1481px) {
+    body {
+        font-size: 115%;
+        /* Increase even more font size for big screens */
+    }
+}
+
+
+/* Social Icons in the sidebar (available: twitter, facebook, linkedin, google+, bitbucket, github) */
+
+.social-icons {
+    display: inline-block;
+    margin: 0;
+    text-align: center;
+}
+
+.social-icons a {
+    background: none no-repeat scroll center top #444444;
+    border: 1px solid #F6F6F6;
+    border-radius: 50% 50% 50% 50%;
+    display: inline-block;
+    height: 35px;
+    width: 35px;
+    margin: 0;
+    text-indent: -9000px;
+    transition: all 0.2s ease 0s;
+    text-align: center;
+    border-bottom: none;
+}
+
+.social-icons li {
+    display: inline-block;
+    list-style-type: none;
+    border-bottom: none;
+}
+.social-icons li a {
+    border-bottom: none;
+}
+
+.social-icons a:hover {
+    background-color: #666666;
+    transition: all 0.2s ease 0s;
+    text-decoration: none;
+}
+
+.social-icons a.facebook {
+    background-image: url('../_images/.facebook.png');
+    background-image: url('//perso.crans.org/besson/_images/.facebook.png');
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    background-size: 35px 35px;
+}
+
+.social-icons a.bitbucket {
+    background-image: url('../_images/.bitbucket.png');
+    background-image: url('//perso.crans.org/besson/_images/.bitbucket.png');
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    background-size: 35px 35px;
+}
+
+.social-icons li a.github {
+    background-image: url('../_images/.github.png');
+    background-image: url('//perso.crans.org/besson/_images/.github.png');
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    background-size: 35px 35px;
+}
+
+.social-icons li a.wikipedia {
+    background-image: url('../_images/.wikipedia.png');
+    background-image: url('//perso.crans.org/besson/_images/.wikipedia.png');
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    background-size: 35px 35px;
+}
diff --git a/xapp_orchestrater/dev/docs/_static/logo.png b/xapp_orchestrater/dev/docs/_static/logo.png
new file mode 100644 (file)
index 0000000..c3b6ce5
Binary files /dev/null and b/xapp_orchestrater/dev/docs/_static/logo.png differ
diff --git a/xapp_orchestrater/dev/docs/conf.py b/xapp_orchestrater/dev/docs/conf.py
new file mode 100644 (file)
index 0000000..443da2a
--- /dev/null
@@ -0,0 +1,32 @@
+# ==================================================================================
+#       Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#          http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+# ==================================================================================
+
+from docs_conf.conf import *
+linkcheck_ignore = [
+    'http://localhost.*',
+    'http://127.0.0.1.*',
+    'https://gerrit.o-ran-sc.org.*'
+]
+
+rst_prolog = """
+.. include:: <s5defs.txt>
+.. default-role::
+
+"""
+
+html_css_files = ['css/s4defs-roles.css']
+
+extensions = ['sphinxcontrib.contentui']
diff --git a/xapp_orchestrater/dev/docs/conf.yaml b/xapp_orchestrater/dev/docs/conf.yaml
new file mode 100644 (file)
index 0000000..2f2ff27
--- /dev/null
@@ -0,0 +1,20 @@
+---
+# ==================================================================================
+#       Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#          http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+# ==================================================================================
+project_cfg: oran
+project: it/dev
+
+
diff --git a/xapp_orchestrater/dev/docs/favicon.ico b/xapp_orchestrater/dev/docs/favicon.ico
new file mode 100644 (file)
index 0000000..00b0fd0
Binary files /dev/null and b/xapp_orchestrater/dev/docs/favicon.ico differ
diff --git a/xapp_orchestrater/dev/docs/index.rst b/xapp_orchestrater/dev/docs/index.rst
new file mode 100644 (file)
index 0000000..d7e3537
--- /dev/null
@@ -0,0 +1,25 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+
+Welcome to O-RAN SC Integratoin for xApp Development Documentation
+==================================================================
+
+The it/dev repo is used by the O-RAN SC Integration and Testing project for hosting miscellaneous development codes.
+This repo contains integration artifacts for developing Near Realtime RAN Intelligent Controller applications (xApps).
+
+Because the life cycles of Near Realtime RIC xApps are managed by Near Realtime RIC
+Platform, the xApps are expect to conform with certain behavioral patterns and provide
+well-described interfaces.  The artifacts here help the xApp developers to generate (Near Realtime) RIC Platform deployment ready Helm charts for their xApps.
+
+
+The following is a list of projects hosted by this repo.
+
+.. toctree::
+   :maxdepth: 1
+
+   xapp_onboarder/index.rst
+   release-notes.rst
+
diff --git a/xapp_orchestrater/dev/docs/release-notes.rst b/xapp_orchestrater/dev/docs/release-notes.rst
new file mode 100644 (file)
index 0000000..0953210
--- /dev/null
@@ -0,0 +1,119 @@
+..
+.. Copyright (c) 2019 AT&T Intellectual Property.
+..
+.. Copyright (c) 2019 Nokia.
+..
+..
+.. Licensed under the Creative Commons Attribution 4.0 International
+..
+.. Public License (the "License"); you may not use this file except
+..
+.. in compliance with the License. You may obtain a copy of the License at
+..
+..
+..     https://creativecommons.org/licenses/by/4.0/
+..
+..
+.. Unless required by applicable law or agreed to in writing, documentation
+..
+.. 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.
+..
+
+
+Release-Notes
+=============
+
+
+This document provides the release notes for version 1.0.7 of xapp-onboarder.
+
+.. contents::
+   :depth: 3
+   :local:
+
+
+Version history
+---------------
+
++--------------------+--------------------+--------------------+--------------------+
+| **Date**           | **Ver.**           | **Author**         | **Comment**        |
+|                    |                    |                    |                    |
++--------------------+--------------------+--------------------+--------------------+
+| 2020-06-15         | 1.0.7              | Zhe Huang          | First version      |
+|                    |                    |                    |                    |
++--------------------+--------------------+--------------------+--------------------+
+
+
+Summary
+-------
+
+This is the first release version of the xapp onboarder.
+
+
+
+
+Release Data
+------------
+
+This is the first version of this component.
+
+
+
+
+Feature Additions
+^^^^^^^^^^^^^^^^^
+add RMR source name environment variable.
+add lable for VESPAMGR to report xapp name.
+add option to inject annotation.
+add option to inject command parameters.
+
+
+Bug Corrections
+^^^^^^^^^^^^^^^
+fix the xApp service name for appmgr backward compatibility. 
+
+Deliverables
+^^^^^^^^^^^^
+
+Software Deliverables
++++++++++++++++++++++
+
+The deliverable is a container that provides APIs for xapp onboarding.
+
+
+
+
+Documentation Deliverables
+++++++++++++++++++++++++++
+
+
+
+
+
+Known Limitations, Issues and Workarounds
+-----------------------------------------
+
+System Limitations
+^^^^^^^^^^^^^^^^^^
+
+
+
+Known Issues
+^^^^^^^^^^^^
+
+Workarounds
+^^^^^^^^^^^
+
+
+
+
+
+References
+----------
+
+
diff --git a/xapp_orchestrater/dev/docs/requirements-docs.txt b/xapp_orchestrater/dev/docs/requirements-docs.txt
new file mode 100644 (file)
index 0000000..09a0c1c
--- /dev/null
@@ -0,0 +1,5 @@
+sphinx
+sphinx-rtd-theme
+sphinxcontrib-httpdomain
+recommonmark
+lfdocs-conf
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/guide/config-file.json b/xapp_orchestrater/dev/docs/xapp_onboarder/guide/config-file.json
new file mode 100644 (file)
index 0000000..fcec5db
--- /dev/null
@@ -0,0 +1,100 @@
+{
+       "xapp_name": "mcxapp",
+       "version": "1.0.2",
+       "containers": [
+               {
+                       "name": "mcxapp",
+                       "image": {
+                               "registry": "nexus3.o-ran-sc.org:10002",
+                               "name": "o-ran-sc/ric-app-mc",
+                               "tag": "1.0.2"
+                       },
+                       "command": "/playpen/bin/container_start.sh"
+               }
+       ],
+       "livenessProbe": {
+           "exec": {
+               "command": ["/usr/local/bin/health_ck"]
+           },
+           "initialDelaySeconds": 5,
+           "periodSeconds": 15
+       },
+       "readinessProbe": {
+           "httpGet": {
+               "path": "ric/v1/health/alive",
+               "port": 8080
+           },
+           "initialDelaySeconds": 5,
+           "periodSeconds": 15
+       },
+       "messaging": {
+               "ports": [
+                       {   
+                               "name": "http",
+                               "container": "mcxapp",
+                               "port": 8080,
+                               "description": "http service"
+                       },
+                       {
+                               "name": "rmr-data",
+                               "container": "mcxapp",
+                               "port": 4560,
+                               "txMessages":
+                               [
+                                       "RIC_SUB_REQ",
+                                       "RIC_SUB_DEL_REQ"
+                               ],
+                               "rxMessages":
+                               [
+                                       "RIC_SUB_RESP",
+                                       "RIC_SUB_FAILURE",
+                                       "RIC_SUB_DEL_RESP",
+                                       "RIC_INDICATION"
+                               ],
+                               "policies": [1,2],
+                               "description": "rmr data port for mcxapp"
+                       },
+                       {
+                               "name": "rmr-route",
+                               "container": "mcxapp",
+                               "port": 4561,
+                               "description": "rmr route port for mcxapp"
+                       }
+               ]
+       },
+       "controls": {
+               "active": true,
+               "interfaceId": {
+                       "globalENBId": {
+                               "plmnId": 123456,
+                               "eNBId": 5678
+                       }
+               },
+               "ves_collector_address": "xapp-sandbox2.research.att.com:8888",
+               "measurement_interval": 10000,
+               "simulator_mode": "true",
+               "debug_mode": "true",
+               "local": {
+                       "host": ":8080"
+               },
+               "logger": {
+                       "level": 3
+               }
+       },
+       "metrics": [
+           {
+               "objectName": "UEEventStreamingCounters",
+               "objectInstance": "SgNBAdditionRequest",
+               "name": "SgNBAdditionRequest",
+               "type": "counter",
+               "description": "The total number of SG addition request events processed"
+           },
+           {
+               "objectName": "UEEventStreamingCounters",
+               "objectInstance": "SgNBAdditionRequestAcknowledge",
+               "name": "SgNBAdditionRequestAcknowledge",
+               "type": "counter",
+               "description": "The total number of SG addition request acknowledge events processed"
+           }
+       ]
+}
\ No newline at end of file
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/guide/descriptor.rst b/xapp_orchestrater/dev/docs/xapp_onboarder/guide/descriptor.rst
new file mode 100644 (file)
index 0000000..89f579c
--- /dev/null
@@ -0,0 +1,200 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+
+xApp descriptor
+===============
+
+
+Introduction
+------------
+
+The xApp descriptor is provided by the xApp developer. xApp descriptor includes all the basic and essential information for the RIC platform to manage the life cycle of the xApp. Information and configuration included in the xApp descriptor will be used to generate the xApp helm charts and define the data flows to the north and south bound traffics. xApp developer can also include self-defined internal parameters that will be consumed by the xApp in the xApp descriptor.
+
+The xApp descriptor comes with a config-file.json file that defines the behavior of the xApp, and optionally a schema.json JSON schema file that validates the self-defined parameters.
+
+Config File Structure
+---------------------
+The xApp descriptor config-file.json file follows a JSON structure. The following are the key sections that defines an xApp.
+
+
+* **xapp_name:** :red:`(REQUIRED)` this is the unique identifier to address an xApp. A valid xApp descriptor must includes the xapp_name attribute. The following is an example.
+
+  .. code-block::
+
+    "xapp_name": "example_xapp"
+
+* **version:** :red:`(REQUIRED)` this is the semantic version number of the xApp descriptor. It defines the version numbers of the xApp artifacts (e.g., xApp helm charts) that will be generated from the xApp descriptor. Together with the xapp\_name, they defines the unique identifier of an xApp artifact that can be on-boarded, distributed and deployed. The following is an example.
+
+  .. code-block::
+
+    "version": "1.0.0"
+
+* **containers:** :red:`(REQUIRED)` this section defines a list of containers that the xApp will run. For each container, a structure that defines the container name, image registry, image name, image tag, and the command that it runs is defined. :red:`The name and images are REQUIRED.` The  command field is optional. The following is an example that defines two containers.
+
+  .. code-block::
+    
+    "containers": [
+        {
+            "name": "example_container_1",
+            "image": {
+                "registry": "example_image_registry_1",
+                "name": "example_image_name_1",
+                "tag": "example_image_tag_1"
+            },
+            "command": "example_command_1"
+        },
+        {
+            "name": "example_container_2",
+            "image": {
+                "registry": "example_image_registry_2",
+                "name": "example_image_name_2",
+                "tag": "example_image_tag_2"
+            }
+        }
+    ]
+
+
+* **controls:** :green:`(OPTIONAL)` The control section holds the internal configuration of the xApp. Therefore, this section is xApp specific. This section can include arbitrary number of xApp defined parameters. The xApp consumes the parameters by reading the xApp descriptor file that will be injected into the container as a JSON file. An environment variable XAPP_DESCRIPTOR_PATH will point to the directory where the JSON file is mounted inside the container. :red:`If the controls section is not empty, the xApp developer must provide the additional schema file for this controls section.` Please refer to Schema for xApp Descriptor for creating such schema file. The following is an example for the controls section.
+
+  .. code-block::
+
+    "controls": {
+        "active": True,
+        "requestorId": 66,
+        "ranFunctionId": 1,
+        "ricActionId": 0,
+        "interfaceId": {
+            "globalENBId": {
+                "plmnId": "310150",
+                "eNBId": 202251
+            }
+        }
+    }
+
+
+* **metrics:** :green:`(OPTIONAL)` The metrics section of the xApp descriptor holds information about metrics provided by the xApp. :red:`Each metrics item requires the objectName, objectInstance, name, type and description of each counter.` The metrics section is required by VESPA manager (RIC platform component) and the actual metrics data are exposed to external servers via Prometheus VESPA interface. The following is an example.
+
+  .. code-block::
+
+    "metrics": [
+        {
+            "objectName": "UEEventStreamingCounters",
+            "objectInstance": "SgNBAdditionRequest",
+            "name": "SgNBAdditionRequest",
+            "type": "counter",
+            "description": "The total number of SG addition request events processed"
+        },
+        {
+            "objectName": "UEEventStreamingCounters",
+            "objectInstance": "SgNBAdditionRequestAcknowledge",
+            "name": "SgNBAdditionRequestAcknowledge",
+            "type": "counter",
+            "description": "The total number of SG addition request acknowledge events processed"
+        }
+    ]
+
+* **messaging:** :green:`(OPTIONAL)` This section defines the communication ports for each containers. It may define list of RX and TX message types, and the A1 policies for RMR communications implemented by this xApp. Each defined port will creates a K8S service port  that are mapped to the container at the same port number. :red:`This section requires ports that contains the port name, port number, which container it is for. For RMR port, it also requires tx and rx message types, and A1 policy list.`
+
+  .. note:: **Stop gap solution for bronze release:** The messaging section replaces the previously RMR section in the xApp descriptor. It requires appmgr to modify its codes to parse the new messaging section. Before the new version of appmgr is released, as a stop gap solution, we will also include a compatible RMR section with the same information in the xApp descriptor. Please refer to the stop-gap-MCxApp descriptor for example.
+
+
+  .. warning:: **Choosing port numbers:** In the bronze release appmgr is not consuming the port name defined in the messaging section yet. Please chose to use the default 4560 port for rmr-data and 4561 for rmr-route.
+
+  .. warning:: **Port naming convention:** Kubernetes requires the port name to be DNS compatible. Therefore, please choose a port name that contains only alphabetical characters (A-Z), numeric characters (0-9), the minus sign (-), and the period (.). Period characters are allowed only when they are used to delimit the components of domain style names.
+
+  The following is an example
+  
+  .. code-block::
+
+    "messaging": {
+        "ports": [
+            {  
+                "name": "http",
+                "container": "mcxapp",
+                "port": 8080,
+                "description": "http service"
+            },
+            {
+                "name": "rmr-data",
+                "container": "mcxapp",
+                "port": 4560,
+                "txMessages":
+                [
+                    "RIC_SUB_REQ",
+                    "RIC_SUB_DEL_REQ"
+                ],
+                "rxMessages":
+                [
+                    "RIC_SUB_RESP",
+                    "RIC_SUB_FAILURE",
+                    "RIC_SUB_DEL_RESP",
+                    "RIC_INDICATION"
+                ],
+                "policies": [1,2],
+                "description": "rmr data port for mcxapp"
+            },
+            {
+                "name": "rmr-route",
+                "container": "mcxapp",
+                "port": 4561,
+                "description": "rmr route port for mcxapp"
+            }
+        ]
+    },
+
+* **liveness probes:** :green:`(OPTIONAL)` The liveness probe section defines how liveness probe is defined in the xApp helm charts. You can provide ether a command or a http helm liveness probe definition in JSON format. :red:`This section requires initialDelaySeconds, periodSeconds, and either httpGet or exec.`
+  The following is an example for http-based liveness probes. 
+
+  .. code-block::
+
+    "livenessProbe": {
+        "exec": {
+            "command": ["/usr/local/bin/rmr_probe"]
+        },
+        "initialDelaySeconds": "5",
+        "periodSeconds": "15"
+    },
+    
+
+  The following is an example for rmr-based  liveness probes. 
+
+  .. code-block::
+
+    "livenessProbe": {
+        "exec": {
+            "command": ["/usr/local/bin/rmr_probe"]
+        },
+        "initialDelaySeconds": "5",
+        "periodSeconds": "15"
+    },
+
+* **readiness probes:** :green:`(OPTIONAL)` The readiness probe section defines how readiness probe is defined in the xApp helm charts. You can provide ether a command or a http helm readiness probe definition in JSON format. :red:`This section requires initialDelaySeconds, periodSeconds, and either httpGet or exec.`
+  The following is an example for http-based readiness probes.
+
+  .. code-block::
+
+    "readinessProbe": {
+        "httpGet": {
+            "path": "ric/v1/health/alive",
+            "port": "8080"
+        },
+        "initialDelaySeconds": "5",
+        "periodSeconds": "15"
+    },
+
+  The following is an example for rmr-based readiness probes.
+
+  .. code-block::
+
+    "readinessProbe": {
+        "exec": {
+            "command": ["/usr/local/bin/rmr_probe"]
+        },
+        "initialDelaySeconds": "5",
+        "periodSeconds": "15"
+    },
+
+
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/guide/embedded-schema.json b/xapp_orchestrater/dev/docs/xapp_onboarder/guide/embedded-schema.json
new file mode 100644 (file)
index 0000000..89dd7e1
--- /dev/null
@@ -0,0 +1,430 @@
+{
+       "$schema": "http://json-schema.org/draft-07/schema#",
+       "$id": "http://o-ran-sc.org/xapp_root.json",
+       "type": "object",
+       "title": "The xApp Root Schema",
+       "properties": {
+               "xapp_name": {
+                       "$id": "#/properties/xapp_name",
+                       "type": "string",
+                       "title": "The xApp Name",
+                       "default": "xapp",
+                       "examples": [
+                               "example_xapp"
+                       ]
+               },
+               "version": {
+                       "$id": "#/properties/version",
+                       "type": "string",
+                       "title": "The xApp version",
+                       "default": "1.0.0",
+                       "examples": [
+                               "1.0.0"
+                       ],
+                       "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
+               },
+               "containers": {
+                       "$id": "#/properties/containers",
+                       "type": "array",
+                       "title": "The Container Schema",
+                       "items": {
+                               "$id": "#/properties/containers/items",
+                               "type": "object",
+                               "title": "The Container Items Schema",
+                               "required": [
+                                       "name",
+                                       "image"
+                               ],
+                               "properties": {
+                                       "name": {
+                                               "$id": "#/properties/containers/items/properties/name",
+                                               "type": "string",
+                                               "title": "The xApp Container Name",
+                                               "default": "xapp",
+                                               "examples": [
+                                                       "xapp"
+                                               ]
+                                       },
+                                       "image": {
+                                               "$id": "#/properties/containers/items/properties/image",
+                                               "type": "object",
+                                               "title": "The Container Image",
+                                               "required": [
+                                                       "registry",
+                                                       "name",
+                                                       "tag"
+                                               ],
+                                               "properties": {
+                                                       "registry": {
+                                                               "$id": "#/properties/containers/items/properties/image/properties/registry",
+                                                               "type": "string",
+                                                               "title": "The xApp Image Registry",
+                                                               "default": "nexus3.o-ran-sc.org:10002",
+                                                               "examples": [
+                                                                       "nexus3.o-ran-sc.org:10002"
+                                                               ],
+                                                               "pattern": "^[A-Za-z0-9\\.-]{1,}\\.[A-Za-z]{1,}(?:\\:\\d+)?$"
+                                                       },
+                                                       "name": {
+                                                               "$id": "#/properties/containers/items/properties/image/properties/name",
+                                                               "type": "string",
+                                                               "title": "The xApp Image Name",
+                                                               "default": "xapp",
+                                                               "examples": [
+                                                                       "xapp"
+                                                               ]
+                                                       },
+                                                       "tag": {
+                                                               "$id": "#/properties/containers/items/properties/image/properties/tag",
+                                                               "type": "string",
+                                                               "title": "The xApp Image Tag",
+                                                               "default": "latest",
+                                                               "examples": [
+                                                                       "latest"
+                                                               ]
+                                                       }
+                                               }
+                                       },
+                                       "command": {
+                                               "$id": "#/properties/containers/items/properties/command",
+                                               "type": "string",
+                                               "title": "Command To Run The xApp Container",
+                                               "default": "command",
+                                               "examples": [
+                                                       "command"
+                                               ]
+                                       }
+                               }
+                       }
+               },
+        "livenessProbe": {
+               "$id": "#/properties/livenessprobe",
+            "type": "object",
+                       "title": "The Liveness Probe Definition",
+            "properties": {
+                "exec": {
+                                       "$id": "#/properties/livenessprobe/exec",
+                    "type": "object",
+                                       "title": "Script of Liveness Probe",
+                    "properties": {
+                         "command": {
+                                                        "$id": "#/properties/livenessprobe/exec/command",
+                             "type": "array",
+                             "items": [
+                                 {
+                                                                       "$id": "#/properties/livenessprobe/exec/command/item",
+                                                                       "type": "string",
+                                                                       "title": "The Command Item",
+                                                                       "default": "/bin/sh",
+                                                                       "examples": [
+                                                                               "/bin/sh"
+                                                                       ]
+                                 }
+                             ]
+                         }
+                    },
+                    "required": [
+                        "command"
+                    ]
+                },
+                "httpGet": {
+                                       "$id": "#/properties/livenessprobe/httpget",
+                    "type": "object",
+                                       "title": "Http of Liveness Probe",
+                    "properties": {
+                         "path": {
+                                                       "$id": "#/properties/livenessprobe/httpget/path",
+                                                       "type": "string",
+                                                       "title": "The Path of Http Liveness Probe",
+                                                       "default": "/health",
+                                                       "examples": [
+                                                               "/health"
+                                                       ]
+                         },
+                                                "port": {
+                                                       "$id": "#/properties/livenessprobe/httpget/port",
+                                                       "type": "integer",
+                                                       "title": "The Port of Http Liveness Probe",
+                                                       "default": 80,
+                                                       "examples": [
+                                                               80
+                                                       ]
+                         }
+                    },
+                    "required": [
+                        "path",
+                                       "port"
+                    ]
+                },
+                "initialDelaySeconds": {
+                    "$id": "#/properties/livenessprobe/initialdelayseconds",
+                                       "type": "integer",
+                                       "title": "Initial Delay of Liveness Probe",
+                                       "default": 5,
+                                       "examples": [
+                                               5
+                                       ]
+                },
+                "periodSeconds": {
+                    "$id": "#/properties/livenessprobe/periodseconds",
+                                       "type": "integer",
+                                       "title": "Period of Liveness Probe",
+                                       "default": 15,
+                                       "examples": [
+                                               15
+                                       ]
+                }
+            },
+                   "oneOf": [
+                     { 
+                                 "$id": "#/properties/livenessprobe/oneof/exec",
+                                 "required": ["exec", "initialDelaySeconds", "periodSeconds"]
+                         },
+                     { 
+                                 "$id": "#/properties/livenessprobe/oneof/httpget",
+                                 "required": ["httpGet", "initialDelaySeconds", "periodSeconds"]
+                         }
+                   ]
+        },
+        "readinessProbe": {
+               "$id": "#/properties/readinessprobe",
+            "type": "object",
+                       "title": "The Readiness Probe Definition",
+            "properties": {
+                "exec": {
+                                       "$id": "#/properties/readinessprobe/exec",
+                    "type": "object",
+                                       "title": "Script of Readiness Probe",
+                    "properties": {
+                         "command": {
+                                                        "$id": "#/properties/readinessprobe/exec/command",
+                             "type": "array",
+                             "items": [
+                                 {
+                                     "type": "string"
+                                 }
+                             ]
+                         }
+                    },
+                    "required": [
+                        "command"
+                    ]
+                },
+                "httpGet": {
+                                       "$id": "#/properties/readinessprobe/httpget",
+                    "type": "object",
+                                       "title": "Http of Readiness Probe",
+                    "properties": {
+                         "path": {
+                                                       "$id": "#/properties/readinessprobe/httpget/path",
+                                                       "type": "string",
+                                                       "title": "The Path of Http Readiness Probe",
+                                                       "default": "/health",
+                                                       "examples": [
+                                                               "/health"
+                                                       ]
+                         },
+                                                "port": {
+                                                       "$id": "#/properties/readinessprobe/httpget/port",
+                                                       "type": "integer",
+                                                       "title": "The Port of Http Readiness Probe",
+                                                       "default": 80,
+                                                       "examples": [
+                                                               80
+                                                       ]
+                         }
+                    },
+                    "required": [
+                        "path",
+                                       "port"
+                    ]
+                },
+                "initialDelaySeconds": {
+                    "$id": "#/properties/readinessprobe/initialdelayseconds",
+                                       "type": "integer",
+                                       "title": "Initial Delay of Readiness Probe",
+                                       "default": 5,
+                                       "examples": [
+                                               5
+                                       ]
+                },
+                "periodSeconds": {
+                    "$id": "#/properties/readinessprobe/periodseconds",
+                                       "type": "integer",
+                                       "title": "Period of Readiness Probe",
+                                       "default": 15,
+                                       "examples": [
+                                               15
+                                       ]
+                }
+            },
+                   "oneOf": [
+                     { 
+                                 "$id": "#/properties/readinessprobe/oneof/exec",
+                                 "required": ["exec", "initialDelaySeconds", "periodSeconds"]
+                         },
+                     { 
+                                 "$id": "#/properties/readinessprobe/oneof/httpget",
+                                 "required": ["httpGet", "initialDelaySeconds", "periodSeconds"]
+                         }
+                   ]
+        },     
+           "messaging": {
+                       "type": "object",
+                       "$id": "#/properties/messaging",
+                       "title": "The Messaging Schema",
+                       "properties": {
+                               "ports": {
+                               "$id": "#/properties/messaging/ports",
+                                       "type": "array",
+                                       "title": "The Ports for Messaging",
+                                       "items":{
+                                               "$id": "#/properties/messaging/ports/items",
+                                               "type": "object",
+                                               "title": "The Item of Port",
+                                               "required": ["name", "container", "port"],              
+                                           "dependencies": {
+                                             "txMessages": ["rxMessages", "policies"],
+                                                 "rxMessages": ["txMessages", "policies"],
+                                                 "policies": ["rxMessages", "txMessages"]
+                                           },
+                                               "properties": {
+                                                       "name": {
+                                                               "$id": "#/properties/messaging/ports/items/name",
+                                                               "type": "string",
+                                                               "title": "The Name of the Port",
+                                                               "default": "App",
+                                                               "examples": [
+                                                                       "App"
+                                                               ]
+                                                       },
+                                                       "container": {
+                                                               "$id": "#/properties/messaging/ports/items/container",
+                                                               "type": "string",
+                                                               "title": "The Container of the Port",
+                                                               "default": "xapp",
+                                                               "examples": [
+                                                                       "xapp"
+                                                               ]
+                                                       },
+                                                       "port": {
+                                                               "$id": "#/properties/messaging/ports/items/port",
+                                                               "type": "integer",
+                                                               "title": "The Port Number",
+                                                               "default": 8080,
+                                                               "examples": [
+                                                                       8080
+                                                               ]
+                                                       },
+                                                       "description": {
+                                                               "$id": "#/properties/messaging/ports/items/description",
+                                                               "type": "string",
+                                                               "title": "The description for the port",
+                                                               "default": "port description",
+                                                               "examples": [
+                                                                       "port description"
+                                                               ]
+                                                       },
+                                       "txMessages": {
+                                                               "$id": "#/properties/messaging/ports/items/txmessages",
+                                           "type": "array",
+                                                               "title": "The txMessage Types",
+                                           "items":{
+                                                                       "$id": "#/properties/messaging/ports/items//txmessages/item",
+                                                                       "type": "string",
+                                                                       "title": "The txMessage Types Item",
+                                                                       "default": "RIC_SUB",
+                                                                       "examples": [
+                                                                               "RIC_SUB"
+                                                                       ]
+                                                               }
+                                       },
+                                       "rxMessages": {
+                                                               "$id": "#/properties/messaging/ports/items/rxmessages",
+                                           "type": "array",
+                                                               "title": "The rxMessage Types",
+                                           "items":{
+                                                                       "$id": "#/properties/messaging/ports/items/rxmessages/item",
+                                                                       "type": "string",
+                                                                       "title": "The rxMessage Types Item",
+                                                                       "default": "RIC_SUB",
+                                                                       "examples": [
+                                                                               "RIC_SUB"
+                                                                       ]
+                                                               }
+                                       },
+                                       "policies": {
+                                                               "$id": "#/properties/messaging/ports/items/policies",
+                                           "type": "array",
+                                                               "title": "The Policies Types",
+                                           "items":{
+                                                                       "$id": "#/properties/messaging/ports/items/policies/item",
+                                                                       "type": "integer",
+                                                                       "title": "The Policy Types Item",
+                                                                       "default": 1,
+                                                                       "examples": [
+                                                                               1
+                                                                       ]
+                                                               }
+                                       }
+                                               }
+                                       }
+                               }
+                       },
+            "required": [
+                "ports"
+            ]
+                               
+               },
+               "metrics": {
+                       "type": "array",
+                       "$id": "#/properties/metrics",
+                       "title": "The Metrics Schema",
+                       "items": {
+                               "$id": "#/properties/metrics/items",
+                               "type": "object",
+                               "title": "The Metrics Items Schema",
+                               "required": [
+                                       "objectName",
+                                       "objectInstance",
+                                       "name",
+                                       "type",
+                                       "description"
+                               ],
+                               "properties": {
+                                       "objectName": {
+                                               "$id": "#/properties/metrics/items/objectname",
+                                               "type": "string",
+                                               "title": "The Object Name"
+                                       },
+                                       "objectInstance": {
+                                               "$id": "#/properties/metrics/items/objectinstance",
+                                               "type": "string",
+                                               "title": "The Object Instance"
+                                       },
+                                       "name": {
+                                               "$id": "#/properties/metrics/items/name",
+                                               "type": "string",
+                                               "title": "The Object Name"
+                                       },
+                                       "type": {
+                                               "$id": "#/properties/metrics/items/type",
+                                               "type": "string",
+                                               "title": "The Object Type"
+                                       },
+                                       "description": {
+                                               "$id": "#/properties/metrics/items/description",
+                                               "type": "string",
+                                               "title": "The Object Description"
+                                       }
+                               }
+                       }
+               },
+               "controls": {
+                       "required": [
+                               "__empty_control_section__"
+                       ]
+               }
+               
+       }
+}
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/guide/example.rst b/xapp_orchestrater/dev/docs/xapp_onboarder/guide/example.rst
new file mode 100644 (file)
index 0000000..094e7e4
--- /dev/null
@@ -0,0 +1,37 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+
+Step-by-step xApp Descriptor Design Example
+===========================================
+
+Step 1: Gather Information
+--------------------------
+Collect the information about the following items
+
+* xApp name
+* Version of the xApp descriptor
+* Details of the xApp containers
+* (Optional) xApp-specific configuration parameters
+* (Optional) Metrics produced
+* (Optional) Ports for messaging
+* (Optional) Liveness and readiness probes methods
+
+Step 2: Download config-file.json skeleton
+------------------------------------------
+Download the config-file.json file :download:`here <config-file.json>`
+
+Step 3: Change xapp_name and version
+------------------------------------
+In the config-file.json file, change the values for "xapp_name" and "version"
+
+.. note:: If xapp-onboarder is configured with ALLOW_REDEPLOY=False, you cannot reuse the same version number between onboarding.
+
+Step 4: Fill in the container information
+-----------------------------------------
+The container section in the config-file.json is a list of container properties structure. For each container, give it a unique name. Specify the docker image registry, docker image name, and docker iamge tag. Optionally. Please make sure that the docker registry is accessible from the RIC platform instance to which the xApp will be deployed. If you want to specify the contianer entry point, you can specify the command used to start the container.
+
+
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/guide/schema.rst b/xapp_orchestrater/dev/docs/xapp_onboarder/guide/schema.rst
new file mode 100644 (file)
index 0000000..301721b
--- /dev/null
@@ -0,0 +1,50 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+
+xApp Descriptor JSON Schema
+===========================
+
+Introduction
+------------
+
+JSON schema is used to describe the attributes and values in the xApp descriptor config-file.json file. The xApp onboarding process verifies the types and values of the xApp parameters in the descriptor. If mismatches are found, xApp onboarding will return failure. The schema file consists of two parts: sections that are static and cannot be changed for different xApp, and xApp specific controls section. When an operator is onboarding an xApp that defines a control section, he/she will provide the controls section schema with together with the xApp descriptor.
+
+The xapp_onboarder will combine the schema files into one.
+
+Control Section Schema
+----------------------
+.. note:: No control section schema is needed if your xApp doesn't need a controll section in the config-file.json.  
+
+You can submit arbitrary schema for the controls section. However, if the xApp descriptor contains a controls section, you have to provide the correct schema that describes it. If the xApp does not require a control section, you can ignore the control section schema. It is highly recommended to use draft-07 schema. The following is a skeleton schema that you can use
+
+.. code-block::
+
+  {
+      "$schema": "http://json-schema.org/draft-07/schema#",
+      "$id": "#/controls",
+      "type": "object",
+      "title": "Controls Section Schema",
+      "required": [
+          "REQUIRED_ITEM_1",
+          "REQUIRED_ITEM_2"
+      ],
+      "properties": {
+          "REQUIRED_ITEM_1": {REQUIRED_ITEM_1_SUB_SCHEMA},
+          "REQUIRED_ITEM_2": {REQUIRED_ITEM_2_SUB_SCHEMA}
+      }
+  }
+
+
+Embedded JOSN Schema
+--------------------
+The following JSON schema is provided by the xApp-onboarder. It defines the JSON file structure of the config-file.json file except the control section.
+Expand the following link to read more details.
+
+.. toggle-header::
+    :header: **embedded JSON schema**
+
+      .. literalinclude:: embedded-schema.json
+        :language: JSON
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/guide_index.rst b/xapp_orchestrater/dev/docs/xapp_onboarder/guide_index.rst
new file mode 100644 (file)
index 0000000..c01cb87
--- /dev/null
@@ -0,0 +1,18 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+
+xApp Descriptor Guide
+=====================
+
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Index:
+
+   guide/descriptor.rst
+   guide/schema.rst
+   guide/example.rst
+
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/images/onboard.png b/xapp_orchestrater/dev/docs/xapp_onboarder/images/onboard.png
new file mode 100644 (file)
index 0000000..8ac835d
Binary files /dev/null and b/xapp_orchestrater/dev/docs/xapp_onboarder/images/onboard.png differ
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/images/xapp-flow.png b/xapp_orchestrater/dev/docs/xapp_onboarder/images/xapp-flow.png
new file mode 100644 (file)
index 0000000..4827cf8
Binary files /dev/null and b/xapp_orchestrater/dev/docs/xapp_onboarder/images/xapp-flow.png differ
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/index.rst b/xapp_orchestrater/dev/docs/xapp_onboarder/index.rst
new file mode 100644 (file)
index 0000000..cad4bf2
--- /dev/null
@@ -0,0 +1,16 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+
+xApp Onboarder
+==============
+
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+   overview.rst
+   guide_index.rst
diff --git a/xapp_orchestrater/dev/docs/xapp_onboarder/overview.rst b/xapp_orchestrater/dev/docs/xapp_onboarder/overview.rst
new file mode 100644 (file)
index 0000000..2c653a3
--- /dev/null
@@ -0,0 +1,66 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+..
+.. Copyright (C) 2019 AT&T Intellectual Property
+
+Project Overview
+================
+
+Introduction
+------------
+
+xApp onboarder provides the xapp onboarding service to operators. It consumes the xApp descriptor and optionally additional schema file, and produces xApp helm charts.
+xApp onboarder also provides CLI tools for local testing and debuging. 
+
+
+.. image:: images/onboard.png
+   :scale: 50 %
+   :align: center
+
+
+
+Change logs
+-----------
++------------+--------------+-------------------------------------------------------------------------------------------------+
+| Version    | Date         | Description                                                                                     |
++============+==============+=================================================================================================+
+|1.0.0       | Mar 23 2020  | First release                                                                                   |
++------------+--------------+-------------------------------------------------------------------------------------------------+
+|1.0.1       | May 13 2020  | **Bug fix:** add a work-around for backward compatibility. Now xapp onboarder writes the xApp   |
+|            |              | descriptor and schema json files into xApp helm charts.                                         |
++------------+--------------+-------------------------------------------------------------------------------------------------+
+|1.0.7       | Jun 15 2020  | **Bug fix:**                                                                                    |
+|            |              | fix the xApp service name for appmgr backward compatibility.                                    |
+|            |              | **Feture add:**                                                                                 |
+|            |              | add RMR source name environment variable.                                                       |
+|            |              | add lable for VESPAMGR to report xapp name.                                                     |
+|            |              | add option to inject annotation.                                                                |
+|            |              | add option to inject command parameters.                                                        |
++------------+--------------+-------------------------------------------------------------------------------------------------+
+
+Configurations
+--------------
+
+xApp onboarder uses the following environment parameters to configurate its instance.
+
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| Enviroment Variable  |   Default Value      | Description                                                                                     |
++======================+======================+=================================================================================================+
+| CHART_WORKSPACE_PATH | /tmp/xapp_onboarder  | Temporary directory for xApp helm chart generation                                              |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| CHART_REPO_URL       | \http://0.0.0.0:8080 | URL for local helm repo that stores the onboarded xApp helm chart                               |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| HTTP_TIME_OUT        | 10                   | Timeout value for outgoing REST API calls                                                       |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| HELM_VERSION         | 2.12.3               | Version of the helm client                                                                      |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| HTTP_RETRY           | 3                    | Number of http retries for outgoing REST API calls                                              |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| ALLOW_REDEPLOY       | True                 | Whether to allow reusing version number when onboard xApps                                      |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| CHART_WORKSPACE_SIZE | 500 MB               | Size limit of the CHART_WORKSPACE_PATH temporary directory                                      |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| FLASK_PORT           | 8888                 | Port the xApp onboarder will listen to                                                          |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+
+| FLASK_DEBUG          | True                 | Enable HTTP server debug messages                                                               |
++----------------------+----------------------+-------------------------------------------------------------------------------------------------+                 
diff --git a/xapp_orchestrater/dev/releases/alpine3-mdclog-container.yaml b/xapp_orchestrater/dev/releases/alpine3-mdclog-container.yaml
new file mode 100644 (file)
index 0000000..d794fe3
--- /dev/null
@@ -0,0 +1,11 @@
+---
+distribution_type: container
+container_release_tag: 0.0.4
+container_pull_registry: nexus3.o-ran-sc.org:10004
+container_push_registry: nexus3.o-ran-sc.org:10002
+project: it/dev
+ref: fbe8feb865f614062dfc1e6fbc082033b0f1f4ec
+tag_release: false
+containers:
+    - name: bldr-alpine3-mdclog
+      version: 0.0.4
diff --git a/xapp_orchestrater/dev/releases/alpine3-rmr-container.yaml b/xapp_orchestrater/dev/releases/alpine3-rmr-container.yaml
new file mode 100644 (file)
index 0000000..71180a8
--- /dev/null
@@ -0,0 +1,11 @@
+---
+distribution_type: container
+container_release_tag: 4.1.2
+container_pull_registry: nexus3.o-ran-sc.org:10004
+container_push_registry: nexus3.o-ran-sc.org:10002
+project: it/dev
+ref: 477fb192e0957517bc2386cfa9f8c8c0de9f1d1b
+tag_release: false
+containers:
+    - name: bldr-alpine3-rmr
+      version: 4.1.2
diff --git a/xapp_orchestrater/dev/releases/container-release-ric-plt-xapponboarder.yaml b/xapp_orchestrater/dev/releases/container-release-ric-plt-xapponboarder.yaml
new file mode 100644 (file)
index 0000000..8b04aae
--- /dev/null
@@ -0,0 +1,10 @@
+---
+distribution_type: container
+container_release_tag: 1.0.7
+container_pull_registry: nexus3.o-ran-sc.org:10004
+container_push_registry: nexus3.o-ran-sc.org:10002
+project: it/dev
+ref: a77ec6df0a387fd5a5fc9f219a60604f9147b7cd
+containers:
+    - name: xapp-onboarder
+      version: 1.0.7
diff --git a/xapp_orchestrater/dev/tox.ini b/xapp_orchestrater/dev/tox.ini
new file mode 100644 (file)
index 0000000..4d1d9fe
--- /dev/null
@@ -0,0 +1,34 @@
+[tox]
+minversion = 2.0
+envlist =
+    docs,
+    docs-linkcheck,
+
+skipsdist = true
+
+[testenv:docs]
+basepython = python3
+deps = 
+    sphinx
+    sphinx-rtd-theme
+    sphinxcontrib-contentui
+    sphinxcontrib-httpdomain
+    recommonmark
+    lfdocs-conf
+    
+commands =
+    sphinx-build -W -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
+
+    echo "Generated docs available in {toxinidir}/docs/_build/html"
+
+whitelist_externals = echo
+
+[testenv:docs-linkcheck]
+basepython = python3
+deps = sphinx
+       sphinx-rtd-theme
+       sphinxcontrib-contentui
+       sphinxcontrib-httpdomain
+       recommonmark
+       lfdocs-conf
+commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck
diff --git a/xapp_orchestrater/dev/xapp_onboarder/MANIFEST.in b/xapp_orchestrater/dev/xapp_onboarder/MANIFEST.in
new file mode 100644 (file)
index 0000000..0547a50
--- /dev/null
@@ -0,0 +1,10 @@
+recursive-include * *.py
+recursive-include * *.yaml
+recursive-include * *.tpl
+recursive-include * *.conf
+recursive-include * *.pickle
+include xapp_onboarder/cli
+include xapp_onboarder/xapp_onboarder
+include README.md
+include LICENSES.txt
+include requirements.txt
diff --git a/xapp_orchestrater/dev/xapp_onboarder/README.md b/xapp_orchestrater/dev/xapp_onboarder/README.md
new file mode 100644 (file)
index 0000000..8ce97f7
--- /dev/null
@@ -0,0 +1,36 @@
+xApp Onboarder
+==============
+
+xApp onboarder onboards xApp to the near-rt RIC platform. The operators provides the xApp descriptors and their schemas, the xApp onboarder generates the xApp helm charts dynamically.
+
+## Install xapp_onboarder
+
+Run  [pip](https://pip.pypa.io/en/stable/) to install xapp_onboarder.
+
+```bash
+pip install xapp_onboarder
+```
+
+## Prerequisite Requirements
+A helm chart repo is needed to store the xApp helm charts. You can use [chartmuseum](https://github.com/helm/chartmuseum) for this purpose.
+Environment variables:
+* **FLASK_SERVER_NAME**: Address that the xapp_onboarder is listening on. Default http://0.0.0.0:8888
+* **CHART_REPO_URL**: helm chart repo URL. Default http://0.0.0.0:8080
+
+## Configurations
+Environment variables:
+* **CHART_WORKSPACE_PATH**: Temporary directory that will store the xApp helm chart artifacts. Default /tmp/xapp_onboarder
+* **CHART_WORKSPACE_SIZE**: Size limit of the temporary directory. Default 500MB
+* **ALLOW_REDEPLOY**: Enable or disable redeploying of xApp helm charts. Default True
+* **HTTP_TIME_OUT**: Timeout of all http requests. Default 10 
+* **HTTP_RETRY**: Number of retry xapp_onboarder will use for the http requests. Default 3
+
+## Run the API server
+```bash
+xapp_onboarder
+```
+## Run the CLI tool
+```bash
+cli
+```
diff --git a/xapp_orchestrater/dev/xapp_onboarder/charts/index-cache.yaml b/xapp_orchestrater/dev/xapp_onboarder/charts/index-cache.yaml
new file mode 100644 (file)
index 0000000..881a79b
--- /dev/null
@@ -0,0 +1,23 @@
+apiVersion: v1
+entries:
+  ueec:
+  - apiVersion: v1
+    appVersion: "1.0"
+    created: "2020-11-18T05:42:18.708541492Z"
+    description: Standard xApp Helm Chart
+    digest: cea7ed0a26dea4e24f44e8f281c5e4ad22029ba6ff891eededc8bba1d4cd2ee6
+    name: ueec
+    urls:
+    - charts/ueec-2.0.0.tgz
+    version: 2.0.0
+  - apiVersion: v1
+    appVersion: "1.0"
+    created: "2020-11-18T05:31:16.586130707Z"
+    description: Standard xApp Helm Chart
+    digest: f7be73dfcd8962eaeda5a042f484fae7d9ddf164d6fa129679c18006105888df
+    name: ueec
+    urls:
+    - charts/ueec-1.0.0.tgz
+    version: 1.0.0
+generated: "2020-11-18T05:42:19Z"
+serverInfo: {}
diff --git a/xapp_orchestrater/dev/xapp_onboarder/requirements.txt b/xapp_orchestrater/dev/xapp_onboarder/requirements.txt
new file mode 100644 (file)
index 0000000..bd8c85a
--- /dev/null
@@ -0,0 +1,23 @@
+aniso8601==8.0.0
+attrs==19.3.0
+certifi==2019.11.28
+chardet==3.0.4
+Click==7.0
+fire==0.2.1
+Flask==1.1.1
+flask-restplus==0.13.0
+idna==2.9
+importlib-metadata==1.5.0
+itsdangerous==1.1.0
+Jinja2==2.11.1
+jsonschema==3.2.0
+MarkupSafe==1.1.1
+pyrsistent==0.15.7
+pytz==2019.3
+PyYAML==5.3
+requests==2.23.0
+six==1.14.0
+termcolor==1.1.0
+urllib3==1.25.8
+Werkzeug==0.16.1
+zipp==3.0.0
diff --git a/xapp_orchestrater/dev/xapp_onboarder/setup.cfg b/xapp_orchestrater/dev/xapp_onboarder/setup.cfg
new file mode 100644 (file)
index 0000000..e1053b8
--- /dev/null
@@ -0,0 +1,19 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+[flake8]
+max-line-length = 160
+max-complexity = 10
diff --git a/xapp_orchestrater/dev/xapp_onboarder/setup.py b/xapp_orchestrater/dev/xapp_onboarder/setup.py
new file mode 100644 (file)
index 0000000..258d65c
--- /dev/null
@@ -0,0 +1,50 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+from setuptools import setup, find_packages
+
+with open("README.md", "r") as fh:
+    long_description = fh.read()
+
+with open('requirements.txt') as f:
+    requirements = f.read().splitlines()
+
+
+setup(
+    name='xapp_onboarder',
+    version='1.0.0',
+    description='RIC xApp onboarder',
+    long_description=long_description,
+    long_description_content_type="text/markdown",
+    url='https://gerrit.o-ran-sc.org/r/admin/repos/it/dev',
+    author='Zhe Huang',
+    author_email='zhehuang@research.att.com',
+    include_package_data=True,
+    packages=find_packages(),
+    package_data={'': ['*.yaml', '*.tpl', '*.conf', 'xapp_onboarder', 'cli']},
+    classifiers=[
+        "Programming Language :: Python :: 3",
+        "Operating System :: OS Independent",
+    ],
+    python_requires='>=3.6',
+    install_requires=requirements,
+    entry_points={
+        'console_scripts': [
+            'xapp_onboarder = xapp_onboarder.server.server:main',
+            'dms_cli = xapp_onboarder.server.cli:run'
+        ]
+    },
+)
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/tests/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/conftest.py b/xapp_orchestrater/dev/xapp_onboarder/tests/conftest.py
new file mode 100644 (file)
index 0000000..96b9877
--- /dev/null
@@ -0,0 +1,29 @@
+# tests/conftest.py
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import pytest
+from flask import Flask
+from xapp_onboarder.server.server import server
+
+@pytest.fixture
+def app() -> Flask:
+    """ Provides an instance of xapp onboarder """
+    server_instance = server()
+    assert isinstance(server_instance.app, Flask)
+    return server_instance.app
+
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/constants.py b/xapp_orchestrater/dev/xapp_onboarder/tests/constants.py
new file mode 100644 (file)
index 0000000..82bb011
--- /dev/null
@@ -0,0 +1,161 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+controls_schema_file = {
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "$id": "#/controls",
+    "type": "object",
+    "title": "Controls Section Schema",
+    "required": [
+        "test"
+    ],
+    "properties": {
+        "test": {
+            "$id": "#/controls/test",
+            "type": "string",
+            "title": "test",
+            "default": "test",
+            "examples": [
+                "test"
+            ]
+        }
+    }
+}
+
+config_file = {
+    "name": "test_xapp",
+    "version": "1.0.0",
+       "annotations": {
+         "prometheus.io/path": "/ric/v1/metrics",
+      "prometheus.io/port": "8080",
+      "prometheus.io/scrape": "true"
+       },
+    "containers": [
+        {
+            "name": "mcxapp",
+            "image": {
+                "registry": "nexus3.o-ran-sc.org:10002",
+                "name": "o-ran-sc/ric-app-mc",
+                "tag": "1.0.2"
+            },
+            "command": ["/bin/sh"],
+            "args": ["-c", "/playpen/bin/container_start.sh"]
+        }
+    ],
+    "livenessProbe": {
+        "exec": {
+            "command": ["/usr/local/bin/health_ck"]
+        },
+        "initialDelaySeconds": 5,
+        "periodSeconds": 15
+    },
+    "readinessProbe": {
+        "httpGet": {
+            "path": "ric/v1/health/alive",
+            "port": 8080
+        },
+        "initialDelaySeconds": 5,
+        "periodSeconds": 15
+    },
+    "messaging": {
+        "ports": [
+            {
+                "name": "http",
+                "container": "mcxapp",
+                "port": 8080,
+                "description": "http service"
+            },
+            {
+                "name": "rmr_data",
+                "container": "mcxapp",
+                "port": 4560,
+                "description": "rmr data port for mcxapp"
+            },
+            {
+                "name": "rmr_route",
+                "container": "mcxapp",
+                "port": 4561,
+                "description": "rmr route port for mcxapp"
+            }
+        ],
+        "maxSize": 2072,
+        "numWorkers": 1,
+        "txMessages": [
+            "RIC_SUB_REQ",
+            "RIC_SUB_DEL_REQ"
+        ],
+        "rxMessages": [
+            "RIC_SUB_RESP",
+            "RIC_SUB_FAILURE",
+            "RIC_SUB_DEL_RESP",
+            "RIC_INDICATION"
+        ],
+        "policies": [1, 2]
+    },
+    "controls": {
+        "test": "test"
+    },
+    "metrics": [
+        {
+            "objectName": "UEEventStreamingCounters",
+            "objectInstance": "SgNBAdditionRequest",
+            "name": "SgNBAdditionRequest",
+            "type": "counter",
+            "description": "The total number of SG addition request events processed"
+        },
+        {
+            "objectName": "UEEventStreamingCounters",
+            "objectInstance": "SgNBAdditionRequestAcknowledge",
+            "name": "SgNBAdditionRequestAcknowledge",
+            "type": "counter",
+            "description": "The total number of SG addition request acknowledge events processed"
+        }
+    ]
+}
+
+mock_json_body_url = {
+    'config-file.json_url': 'http://0.0.0.0:8080/config-file.json',
+    'controls-schema.json_url': 'http://0.0.0.0:8080/schema.json'
+}
+
+mock_json_body_url_without_controls = {
+    'config-file.json_url': 'http://0.0.0.0:8080/config-file.json'
+}
+
+mock_json_body = {
+    "config-file.json": config_file,
+    "controls-schema.json": controls_schema_file
+}
+
+mock_json_body_without_controls = {
+    "config-file.json": config_file
+}
+helm_repo_index_response = {'apiVersion': 'v1',
+                            'entries': {
+                                'test_xapp': [{
+                                    'apiVersion': 'v1',
+                                    'appVersion': '1.0',
+                                    'created': '2020-03-12T19:10:17.178396719Z',
+                                    'description': 'test xApp Helm Chart',
+                                    'digest': 'd77dfb3f008e5174e90d79bfe982ef85b5dc5930141f6a1bd9995b2fa35',
+                                    'name': 'test_xapp',
+                                    'urls': ['charts/test-1.0.0.tgz'],
+                                    'version': '1.0.0'
+                                }]
+                            },
+                            'generated': '2020-03-16T16:54:44Z',
+                            'serverInfo': {}
+                            }
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/mock_helm_repo/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/tests/mock_helm_repo/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/mock_helm_repo/mock_helm_repo.py b/xapp_orchestrater/dev/xapp_onboarder/tests/mock_helm_repo/mock_helm_repo.py
new file mode 100755 (executable)
index 0000000..999a6b7
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import pkg_resources
+import logging.config
+import yaml
+import json
+import os
+import tarfile
+from flask import Flask, jsonify, send_file
+from tests.constants import config_file, controls_schema_file, helm_repo_index_response
+from xapp_onboarder.server import settings
+
+
+logger_config = pkg_resources.resource_filename("xapp_onboarder", 'logging.conf')
+logging.config.fileConfig(logger_config)
+log = logging.getLogger(__name__)
+
+listen_address = '0.0.0.0:8080'
+app = Flask(__name__)
+app.config['SERVER_NAME'] = listen_address
+
+
+
+
+@app.route('/')
+def root_dir():
+    return {'health': 'OK'}
+
+@app.route('/index.yaml')
+def get_index():
+    return yaml.dump(helm_repo_index_response)
+
+@app.route('/api/charts', methods=['POST'])
+def upload_chart():
+    return {"saved": True}, 201
+
+@app.route('/api/charts/test_xapp/1.0.0', methods=['DELETE'])
+def delete_chart():
+    return {"deleted":True}, 200
+
+@app.route('/api/charts/test_xapp', methods=['GET'])
+def get_all_xapp_version():
+    test_xapp = helm_repo_index_response['entries']['test_xapp']
+    return jsonify(test_xapp), 200
+
+@app.route('/api/charts', methods=['GET'])
+def get_all_xapp():
+    return jsonify(helm_repo_index_response['entries']), 200
+
+@app.route('/charts/test_xapp-1.0.0.tgz', methods=['GET'])
+def download_xapp_helm_package():
+    if not os.path.exists(settings.MOCK_TEST_HELM_REPO_TEMP_DIR):
+        os.makedirs(settings.MOCK_TEST_HELM_REPO_TEMP_DIR)
+    with open(settings.MOCK_TEST_HELM_REPO_TEMP_DIR + '/values.yaml', 'w') as file:
+        file.write(json.dumps(helm_repo_index_response))
+
+    with tarfile.open(settings.MOCK_TEST_HELM_REPO_TEMP_DIR + '/test_xapp-1.0.0.tgz', "w:gz") as tar:
+        tar.addfile(tarfile.TarInfo("test_xapp/values.yaml"), open(settings.MOCK_TEST_HELM_REPO_TEMP_DIR + '/values.yaml'))
+
+    return send_file(settings.MOCK_TEST_HELM_REPO_TEMP_DIR + '/test_xapp-1.0.0.tgz', mimetype='application/zip')
+
+
+
+@app.route('/schema.json', methods=['GET'])
+def get_schema():
+
+
+    return controls_schema_file, 200
+
+@app.route('/config-file.json', methods=['GET'])
+def get_config_file():
+
+
+    return config_file, 200
+
+def run():
+    log.info('>>>>> Starting mock helm_repo at http://{}<<<<<'.format(listen_address))
+    app.run(debug=True)
+
+if __name__ == '__main__':
+    run()
+
+
+
+
+
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/test_api.py b/xapp_orchestrater/dev/xapp_onboarder/tests/test_api.py
new file mode 100644 (file)
index 0000000..23a50d6
--- /dev/null
@@ -0,0 +1,80 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+from http import HTTPStatus
+from tests.constants import mock_json_body, mock_json_body_url_without_controls, mock_json_body_url, mock_json_body_without_controls,  helm_repo_index_response
+
+
+def test_health(client):
+    response = client.get('/api/v1/health')
+    assert response.status_code == HTTPStatus.OK, 'Wrong status code'
+    assert response.json == {'status': 'OK'}, 'Improper response'
+
+def test_get_charts(client):
+    response = client.get('/api/v1/charts')
+    assert response.status_code == HTTPStatus.OK, 'Wrong status code'
+    assert response.content_type == 'application/json', 'Content type error'
+    assert sorted([repr(x) for x in response.json]) == sorted([repr(x) for x in helm_repo_index_response['entries']])
+
+def test_get_test_xapp_charts(client):
+    response = client.get('/api/v1/charts/xapp/test_xapp')
+    assert response.status_code == HTTPStatus.OK, 'Wrong status code'
+    assert response.content_type == 'application/json', 'Content type error'
+    assert sorted([repr(x) for x in response.json]) == sorted([repr(x) for x in helm_repo_index_response['entries']['test_xapp']])
+
+def test_get_test_xapp_charts_package(client):
+    response = client.get('/api/v1/charts/xapp/test_xapp/ver/1.0.0')
+    assert response.status_code == HTTPStatus.OK, 'Wrong status code'
+    assert response.content_type == 'application/gzip', 'Content type error'
+
+def test_get_test_xapp_charts_values_yaml(client):
+    response = client.get('/api/v1/charts/xapp/test_xapp/ver/1.0.0/values.yaml')
+    assert response.status_code == HTTPStatus.OK, 'Wrong status code'
+    assert response.content_type == 'text/x-yaml', 'Content type error'
+
+def test_onboard_post(client):
+    url = '/api/v1/onboard'
+    response = client.post(url, json=mock_json_body)
+    assert response.status_code == HTTPStatus.CREATED, 'Wrong status code'
+    assert response.content_type == 'application/json', 'Content type error'
+    assert response.json == {'status': 'Created'}, 'Onboard failed'
+
+def test_onboard_without_controls_post(client):
+    url = '/api/v1/onboard'
+    response = client.post(url, json=mock_json_body_without_controls)
+    assert response.status_code == HTTPStatus.BAD_REQUEST, 'Wrong status code'
+    assert response.content_type == 'application/json', 'Content type error'
+    assert response.json == {'error_message': "'__empty_control_section__' is a required property",
+                             'error_source': 'config-file.json',
+                             'status': 'Input payload validation failed'}, 'Onboard failed'
+
+
+def test_onboard_download_post(client):
+    url = '/api/v1/onboard/download'
+    response = client.post(url, json=mock_json_body_url)
+    assert response.status_code == HTTPStatus.CREATED, 'Wrong status code'
+    assert response.content_type == 'application/json', 'Content type error'
+    assert response.json == {'status': 'Created'}, 'Onboard failed'
+
+
+def test_onboard_download_without_controls_post(client):
+    url = '/api/v1/onboard/download'
+    response = client.post(url, json=mock_json_body_url_without_controls)
+    assert response.status_code == HTTPStatus.BAD_REQUEST, 'Wrong status code'
+    assert response.content_type == 'application/json', 'Content type error'
+    assert response.json == {'error_message': "'__empty_control_section__' is a required property",
+                             'error_source': 'config-file.json',
+                             'status': 'Input payload validation failed'}, 'Onboard failed'
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/test_helm_controller.py b/xapp_orchestrater/dev/xapp_onboarder/tests/test_helm_controller.py
new file mode 100644 (file)
index 0000000..1298d1e
--- /dev/null
@@ -0,0 +1,32 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+import os
+import shutil
+from xapp_onboarder.helm_controller.xApp_builder import xApp, xAppError
+from tests.constants import config_file, controls_schema_file
+from xapp_onboarder.server import settings
+
+
+def test_packaging_xapp(client):
+        chart_workspace_path = settings.CHART_WORKSPACE_PATH + '/test_xapp-1.0.0'
+        if os.path.exists(chart_workspace_path):
+                shutil.rmtree(chart_workspace_path)
+
+        xapp = xApp(config_file, controls_schema_file)
+        xapp.package_chart()
+        assert os.path.isfile(chart_workspace_path + '/test_xapp-1.0.0.tgz'), 'xApp packaging error'
+
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tests/test_trim_thread.py b/xapp_orchestrater/dev/xapp_onboarder/tests/test_trim_thread.py
new file mode 100644 (file)
index 0000000..f4ca4e7
--- /dev/null
@@ -0,0 +1,41 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+import time
+import os
+import shutil
+from xapp_onboarder.server import settings
+from xapp_onboarder.helm_controller.artifacts_manager import format_artifact_dir_size, get_dir_size, trim_artifact_dir
+def test_trim_thread():
+    path = settings.CHART_WORKSPACE_PATH
+    if os.path.exists(path):
+        shutil.rmtree(path)
+    os.makedirs(path)
+
+    size_limit = format_artifact_dir_size()
+    f = open(path+'/mock_size_file',"wb")
+    f.seek(int(size_limit)+100000000)
+    f.write(b"\0")
+    f.close()
+
+    artifact_dir_size = get_dir_size(start_path=path)
+    assert size_limit < artifact_dir_size, 'Fail to write large files'
+
+    trim_artifact_dir()
+    artifact_dir_size = get_dir_size(start_path=path)
+
+    assert size_limit > artifact_dir_size, 'Fail to trim'
+
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/tox.ini b/xapp_orchestrater/dev/xapp_onboarder/tox.ini
new file mode 100644 (file)
index 0000000..a66cd76
--- /dev/null
@@ -0,0 +1,44 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+[tox]
+envlist = py36-{local,lf}
+
+
+[testenv]
+deps=
+    pytest
+    pytest-flask
+    coverage
+    pytest-cov
+setenv =
+    PYTHONUNBUFFERED = 1
+    CHART_REPO_URL = http://0.0.0.0:8080
+    MOCK_TEST_MODE = True
+    lf: CHART_WORKSPACE_PATH = {toxworkdir}/.tmp/xapp_onboarder
+    lf: MOCK_TEST_HELM_REPO_TEMP_DIR = {toxworkdir}/.tmp/helm_repo
+
+commands_pre=
+    bash -c 'nohup python -m tests.mock_helm_repo.mock_helm_repo >/dev/null 2>&1 &'
+
+commands=
+    pytest --verbose --cov xapp_onboarder --cov-report xml --cov-report term-missing --cov-report html
+    coverage xml -i
+
+commands_post=
+    local: bash -c 'kill -9 $(ps -x | grep "tests.mock_helm_repo.mock_helm_repo" | grep -v grep | cut -d" " -f1)'
+
+whitelist_externals = bash
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/api_reference.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/api_reference.py
new file mode 100644 (file)
index 0000000..1f288e0
--- /dev/null
@@ -0,0 +1,34 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+
+from flask_restplus import Api
+from xapp_onboarder.server import settings
+
+log = logging.getLogger(__name__)
+
+api = Api(version='1.0', title='RIC xApp onboarder API',
+          description='APIs to manage the xApp helm charts')
+
+
+@api.errorhandler
+def default_error_handler(e):
+    message = 'An unhandled exception occurred.'
+    log.exception(message)
+
+    if not settings.FLASK_DEBUG:
+        return {'message': message}, 500
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/charts.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/charts.py
new file mode 100644 (file)
index 0000000..223a5be
--- /dev/null
@@ -0,0 +1,81 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+import io
+import tarfile
+from xapp_onboarder.repo_manager.repo_manager import repo_manager, RepoManagerError
+from xapp_onboarder.api.models.response_models import error_message_model, response
+
+log = logging.getLogger(__name__)
+
+
+def get_charts_list(xapp_chart_name=None):
+
+    if not repo_manager.is_repo_ready():
+        response_message = response(model=error_message_model, status_code=500,
+                                    error_source="xapp_onboarder",
+                                    error_message="Cannot connect to local helm repo.",
+                                    status="Service not ready.")
+        return response_message.get_return()
+
+    try:
+        content = repo_manager.get_xapp_list(xapp_chart_name=xapp_chart_name)
+    except RepoManagerError as err:
+        log.error(str(err))
+        response_message = response(model=error_message_model, status_code=err.status_code,
+                                    error_source="charts_fetcher",
+                                    error_message=str(err),
+                                    status="Fetching helm chart list failed")
+        return response_message.get_return()
+    return content, 200
+
+
+def download_chart_package(xapp_chart_name, version):
+
+    if not repo_manager.is_repo_ready():
+        response_message = response(model=error_message_model, status_code=500,
+                                    error_source="xapp_onboarder",
+                                    error_message="Cannot connect to local helm repo.",
+                                    status="Service not ready.")
+        return response_message.get_return()
+    try:
+        content = repo_manager.download_xapp_chart(xapp_chart_name=xapp_chart_name, version=version)
+    except RepoManagerError as err:
+        log.error(str(err))
+        response_message = response(model=error_message_model, status_code=err.status_code,
+                                    error_source="charts_fetcher",
+                                    error_message=str(err),
+                                    status="Downloading helm chart package failed")
+        return response_message.get_return()
+    return content, 200
+
+
+def download_values_yaml(xapp_chart_name, version):
+
+    content, status = download_chart_package(xapp_chart_name=xapp_chart_name, version=version)
+
+    if status != 200:
+        return content, status
+
+    file_stream = io.BytesIO(content)
+
+    with tarfile.open(fileobj=file_stream) as tar:
+        values_yaml_file = tar.extractfile(xapp_chart_name + '/values.yaml')
+        return_response = values_yaml_file.read()
+
+    return return_response, 200
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/charts_ep.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/charts_ep.py
new file mode 100644 (file)
index 0000000..16fbec7
--- /dev/null
@@ -0,0 +1,96 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+from flask import make_response
+from flask_restplus import Resource
+from xapp_onboarder.api.api_reference import api
+from xapp_onboarder.api.charts import get_charts_list, download_chart_package, download_values_yaml
+from xapp_onboarder.api.models.response_models import error_message_model
+
+log = logging.getLogger(__name__)
+ns = api.namespace('charts', description='Managing helm charts')
+
+
+@ns.route('')
+class ChartsList(Resource):
+
+    @api.response(200, 'Get helm chart list OK')
+    @api.response(500, 'Get helm chart list failed', error_message_model)
+    def get(self):
+        """
+        Returns the list of xApp helm charts that have been onboarded.
+        """
+
+        return get_charts_list()
+
+
+@ns.route('/xapp/<string:xapp_chart_name>')
+class VersionList(Resource):
+
+    @api.response(200, 'Get helm chart OK')
+    @api.response(500, 'Get helm chart failed', error_message_model)
+    def get(self, xapp_chart_name):
+        """
+        Returns the helm chart for the specified xApp.
+        """
+        return get_charts_list(xapp_chart_name=xapp_chart_name)
+
+
+@ns.route('/xapp/<string:xapp_chart_name>/ver/<string:version>')
+class ChartsFetcher(Resource):
+
+    @api.response(200, 'Get helm chart package OK')
+    @api.response(500, 'Get helm chart package failed', error_message_model)
+    @api.produces(['application/gzip'])
+    def get(self, xapp_chart_name, version):
+        """
+        Returns the helm chart for the specified xApp and version.
+        """
+
+        content, status = download_chart_package(xapp_chart_name=xapp_chart_name, version=version)
+
+        if status != 200:
+            return content, status
+
+        response = make_response(content)
+        response.headers.set("Content-Type", "application/gzip")
+        response.headers.set("Content-Disposition",
+                             "attachment; filename=\"" + xapp_chart_name + "-" + version + ".tgz\"")
+        return response
+
+
+@ns.route('/xapp/<string:xapp_chart_name>/ver/<string:version>/values.yaml')
+class ValuesYamlFetcher(Resource):
+
+    @api.response(200, 'Get helm chart values.yaml OK')
+    @api.response(500, 'Get helm chart values.yaml failed', error_message_model)
+    @api.produces(['text/x-yaml'])
+    def get(self, xapp_chart_name, version):
+        """
+        Returns the helm values.yaml file of the specified xApp and version.
+        """
+
+        content, status = download_values_yaml(xapp_chart_name=xapp_chart_name, version=version)
+
+        if status != 200:
+            return content, status
+
+        response = make_response(content)
+        response.headers.set("Content-Type", "text/x-yaml")
+        response.headers.set("Content-Disposition", "attachment; filename=\"values.yaml\"")
+
+        return response
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/health_check_ep.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/health_check_ep.py
new file mode 100644 (file)
index 0000000..23e8b5c
--- /dev/null
@@ -0,0 +1,43 @@
+###############################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+
+from flask_restplus import Resource
+from xapp_onboarder.api.api_reference import api
+from xapp_onboarder.api.models.response_models import status_message_model, error_message_model, response
+from xapp_onboarder.repo_manager.repo_manager import repo_manager
+
+log = logging.getLogger(__name__)
+ns = api.namespace('health', description='health check')
+
+
+@ns.route('')
+class HealthCheck(Resource):
+
+    @api.response(200, 'Health check OK', status_message_model)
+    @api.response(500, 'xApp onboarder is not ready', error_message_model)
+    def get(self):
+        """
+        Returns the health condition of the xApp onboarder
+        """
+        if not repo_manager.is_repo_ready():
+            response_message = response( model= error_message_model, status_code = 500,
+                                         error_source = "xapp_onboarder",
+                                         error_message = "Cannot connect to local helm repo.",
+                                         status = "Service not ready.")
+            return response_message.get_return()
+        return response(model = status_message_model, status_code = 200, status= "OK").get_return()
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/onboard_ep.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/endpoints/onboard_ep.py
new file mode 100644 (file)
index 0000000..6806bbf
--- /dev/null
@@ -0,0 +1,70 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+from flask import request
+from flask_restplus import Resource
+from xapp_onboarder.api.models import request_models
+from xapp_onboarder.api.api_reference import api
+from xapp_onboarder.api.models.response_models import status_message_model, error_message_model
+from xapp_onboarder.api.onboard import onboard, download_config_and_schema_and_onboard
+
+log = logging.getLogger(__name__)
+ns = api.namespace('onboard', description='onboard xApps')
+
+
+@ns.route('')
+class OnboardxApps(Resource):
+
+    # @api.response(200, 'Everything is fine')
+    # @api.response(500, 'temp is not ready')
+    # def get(self):
+    #     """
+    #     Return a list of xApp that have been onboarded and their versions.
+    #     """
+    #     if not repo_manager.is_repo_ready():
+    #         return {'status': 'not ready'}, 500
+    #     return {'status': 'OK'}, 200
+
+    @api.response(201, 'xApp onboard successfully.', status_message_model)
+    @api.response(400, 'xApp descriptor format error', error_message_model)
+    @api.response(500, 'xApp onboarder is not ready', error_message_model)
+    @api.expect(request_models.xapp_descriptor_post, validate=True)
+    def post(self):
+        """
+        Onboard xApp using the xApp descriptor and schema in the request body.
+        """
+        config_file = request.json.get('config-file.json')
+        controls_schema_file = request.json.get('controls-schema.json')
+
+        return onboard(config_file, controls_schema_file)
+
+
+@ns.route('/download')
+class OnboardxAppsDownload(Resource):
+
+    @api.response(201, 'xApp onboard successfully.', status_message_model)
+    @api.response(400, 'xApp descriptor format error', error_message_model)
+    @api.response(500, 'xApp onboarder is not ready', error_message_model)
+    @api.expect(request_models.xapp_descriptor_download_post, validate=True)
+    def post(self):
+        """
+        Onboard xApp after downloading the xApp descriptor and schema from the URLs.
+        """
+        config_file_url = request.json.get('config-file.json_url')
+        controls_schema_url = request.json.get('controls-schema.json_url')
+
+        return download_config_and_schema_and_onboard(config_file_url, controls_schema_url)
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/request_models.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/request_models.py
new file mode 100644 (file)
index 0000000..a7865a8
--- /dev/null
@@ -0,0 +1,35 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+from flask_restplus import fields
+from xapp_onboarder.api.api_reference import api
+
+xapp_descriptor_post = api.model('descriptor', {
+    'config-file.json': fields.Nested(
+        api.model('config', {
+            'name': fields.String(description='Name of the xApp chart', required=True),
+            'version': fields.String(description='Version of the xApp chart', required=True,
+                                     pattern='^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'),
+        }), required=True),
+    'controls-schema.json': fields.Raw(description='Controls schema file body', required=False),
+})
+
+
+xapp_descriptor_download_post = api.model('descriptor_remote', {
+    'config-file.json_url': fields.Url(description='URL to download the config-file.json file',  absolute=True, required=True),
+    'controls-schema.json_url': fields.Url(description='URL to download the controls schema.json file',  absolute=True, required=False),
+})
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/response_models.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/models/response_models.py
new file mode 100644 (file)
index 0000000..156b120
--- /dev/null
@@ -0,0 +1,41 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+from flask_restplus import fields, marshal
+from xapp_onboarder.api.api_reference import api
+
+error_message_model = api.model('error_message', {
+    'error_source': fields.String(description='source of the error', required=True),
+    'error_message': fields.String(description='source of the error', required=True),
+    'status': fields.String(description='http response message', required=True),
+})
+
+status_message_model = api.model('status', {
+    'status': fields.String(description='status of the service', required=True)
+})
+
+
+class response():
+
+    def __init__(self, model, status_code, status = "" , error_source = "", error_message = ""):
+        self.model = model
+        self.status = status
+        self.status_code = status_code
+        self.error_source = error_source
+        self.error_message = error_message
+
+    def get_return(self):
+        return marshal(self, self.model), self.status_code
\ No newline at end of file
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/onboard.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/api/onboard.py
new file mode 100644 (file)
index 0000000..71b8f62
--- /dev/null
@@ -0,0 +1,128 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+import json
+import copy
+from jsonschema import ValidationError, SchemaError
+from jsonschema import validate, Draft7Validator
+from xapp_onboarder.helm_controller.xApp_builder import xApp, xAppError
+from xapp_onboarder.server import settings
+from xapp_onboarder.repo_manager.repo_manager import requests_retry_session, repo_manager
+from xapp_onboarder.api.models.response_models import error_message_model, response, status_message_model
+from xapp_onboarder.helm_controller.xapp_schema import schema as xapp_schema
+
+log = logging.getLogger(__name__)
+
+
+def onboard(config_file, controls_schema_file):
+    if not repo_manager.is_repo_ready():
+        response_message = response(model=error_message_model, status_code=500,
+                                    error_source="xapp_onboarder",
+                                    error_message="Cannot connect to local helm repo.",
+                                    status="Service not ready.")
+        return response_message.get_return()
+
+    schema_file = copy.deepcopy(xapp_schema)
+
+    if controls_schema_file:
+        schema_file["properties"]["controls"] = controls_schema_file
+
+    try:
+        Draft7Validator.check_schema(schema_file)
+        validate(config_file, schema_file)
+    except ValidationError as err:
+        log.debug(err.message)
+        response_message = response(model=error_message_model, status_code=400,
+                                    error_source="config-file.json",
+                                    error_message=err.message,
+                                    status="Input payload validation failed")
+        return response_message.get_return()
+    except SchemaError as err:
+        log.debug(err.message)
+        response_message = response(model=error_message_model, status_code=400,
+                                    error_source="schema.json",
+                                    error_message=err.message,
+                                    status="Input payload validation failed")
+        return response_message.get_return()
+
+    try:
+        xapp = xApp(config_file, schema_file)
+        xapp.package_chart()
+        xapp.distribute_chart()
+    except xAppError as err:
+        log.error(str(err))
+        response_message = response(model=error_message_model, status_code=err.status_code,
+                                    error_source="xApp_builder",
+                                    error_message=str(err),
+                                    status="xApp onboarding failed")
+        return response_message.get_return()
+    return response(model=status_message_model, status_code=201, status="Created").get_return()
+
+
+def download_config_and_schema_and_onboard(config_file_url, controls_schema_url):
+    if not repo_manager.is_repo_ready():
+        response_message = response(model=error_message_model, status_code=500,
+                                    error_source="xapp_onboarder",
+                                    error_message="Cannot connect to local helm repo.",
+                                    status="Service not ready.")
+        return response_message.get_return()
+
+    session = requests_retry_session()
+    try:
+        response_content = session.get(config_file_url, timeout=settings.HTTP_TIME_OUT)
+    except Exception as err:
+        log.error(err.message)
+        response_message = response(model=error_message_model, status_code=500,
+                                    error_source="config-file.json",
+                                    error_message=err.message,
+                                    status="Downloading config-file.json failed")
+        return response_message.get_return()
+    else:
+        if response_content.status_code != 200:
+            error_message = "Wrong response code: {}, {}".format(response_content.status_code, response_content.content.decode("utf-8"))
+            log.error(error_message)
+            response_message = response(model=error_message_model, status_code=500,
+                                        error_source="config-file.json",
+                                        error_message=error_message,
+                                        status="Downloading config-file.json failed")
+            return response_message.get_return()
+        config_file = json.loads(response_content.content)
+
+    controls_schema_file = None
+    if controls_schema_url:
+        try:
+            response_content = session.get(controls_schema_url, timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            log.error(err.message)
+            response_message = response(model=error_message_model, status_code=500,
+                                        error_source="schema.json",
+                                        error_message=err.message,
+                                        status="Downloading schema.json failed")
+            return response_message.get_return()
+        else:
+            if response_content.status_code != 200:
+                error_message = "Wrong response code. {}, {}".format(response_content.status_code, response_content.content.decode("utf-8"))
+                log.error(error_message)
+                response_message = response(model=error_message_model, status_code=500,
+                                            error_source="schema.json",
+                                            error_message=error_message,
+                                            status="Downloading schema.json failed")
+                return response_message.get_return()
+            controls_schema_file = json.loads(response_content.content)
+
+
+    return onboard(config_file, controls_schema_file)
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/artifacts_manager.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/artifacts_manager.py
new file mode 100644 (file)
index 0000000..4369884
--- /dev/null
@@ -0,0 +1,100 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import os
+import logging
+import re
+import glob
+import threading
+import shutil
+from xapp_onboarder.server import settings
+
+log = logging.getLogger(__name__)
+
+
+def get_dir_size(start_path='.'):
+    total_size = 0
+
+    if os.path.isfile(start_path):
+        total_size += os.path.getsize(start_path)
+
+    if os.path.isdir(start_path):
+        for dirpath, dirnames, filenames in os.walk(start_path):
+            for f in filenames:
+                fp = os.path.join(dirpath, f)
+                # skip if it is symbolic link
+                if not os.path.islink(fp):
+                    total_size += os.path.getsize(fp)
+
+    return total_size
+
+
+def format_artifact_dir_size():
+    """ Converts integers to common size units used in computing """
+    artifact_dir_size_string = settings.CHART_WORKSPACE_SIZE
+    size_unit = re.sub('[0-9\s\.]', '', artifact_dir_size_string)
+    size_limit = re.sub('[A-Za-z\s\.]', '', artifact_dir_size_string)
+
+    bit_shift = {"B": 0,
+                 "kb": 7,
+                 "KB": 10,
+                 "mb": 17,
+                 "MB": 20,
+                 "gb": 27,
+                 "GB": 30,
+                 "TB": 40, }
+    return float(size_limit) * float(1 << bit_shift[size_unit])
+
+def trim_artifact_dir():
+    artifact_dir_size = get_dir_size(start_path=settings.CHART_WORKSPACE_PATH)
+    dir_limit = format_artifact_dir_size()
+
+    if artifact_dir_size > dir_limit:
+        dirs = sorted(glob.glob(settings.CHART_WORKSPACE_PATH + '/*'), key=os.path.getctime)
+        trim_dir = list()
+        remain_size = artifact_dir_size
+        for dir in dirs:
+            remain_size = remain_size - get_dir_size(start_path=dir)
+            trim_dir.append(dir)
+            if remain_size < dir_limit:
+                break
+        log.info("Trimming artifact directories: " + str(trim_dir))
+        for dir in trim_dir:
+            if os.path.isfile(dir):
+                os.remove(dir)
+            else:
+                shutil.rmtree(dir)
+
+
+class artifacts_manager():
+
+    def __init__(self):
+        self.timer_thread = threading.Timer(60.0, trim_artifact_dir)
+
+    def start_trim_thread(self):
+        if not settings.MOCK_TEST_MODE:
+            log.info("Artifact directory trimming thread started.")
+            self.timer_thread.start()
+
+
+    def cancel_trim_thread(self):
+        log.info("Artifact directory trimming thread stopped.")
+        self.timer_thread.cancel()
+
+    def start(self):
+        self.start_trim_thread()
+
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/xApp_builder.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/xApp_builder.py
new file mode 100644 (file)
index 0000000..a9ecf41
--- /dev/null
@@ -0,0 +1,300 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import logging
+import yaml
+import json
+import os
+import io
+import subprocess
+import shutil
+import re
+import copy
+import platform
+import tarfile
+import stat
+import sys
+from xapp_onboarder.server import settings
+from xapp_onboarder.repo_manager.repo_manager import repo_manager, RepoManagerError
+from pkg_resources import resource_filename
+from subprocess import PIPE, check_output, STDOUT
+from xapp_onboarder.repo_manager.repo_manager import requests_retry_session
+log = logging.getLogger(__name__)
+
+
+def indent(text, amount, ch=' '):
+    padding = amount * ch
+    return ''.join(padding + line for line in text.splitlines(True))
+
+
+class xAppError(Exception):
+    def __init__(self, message, status_code):
+        # Call the base class constructor with the parameters it needs
+        super().__init__(message)
+        self.status_code = status_code
+
+
+class xApp():
+    def __init__(self, config_file, schema_file):
+        self.config_file = config_file
+        self.schema_file = schema_file
+
+        if 'name' not in self.config_file:
+            raise xAppError(
+                "xApp chart name not found. (Caused by: config-file.json does not contain xapp_name attribute.)", 500)
+
+        if 'version' not in self.config_file:
+            raise xAppError(
+                "xApp chart version not found. (Caused by: config-file.json does not contain version attribute.)", 500)
+
+        self.chart_name = self.config_file['name']
+        self.chart_version = self.config_file['version']
+        self.configmap_config_json_file = copy.deepcopy(self.config_file)
+        self.chart_workspace_path = settings.CHART_WORKSPACE_PATH + '/' + self.chart_name + '-' + self.chart_version
+        if os.path.exists(self.chart_workspace_path):
+            shutil.rmtree(self.chart_workspace_path)
+        os.makedirs(self.chart_workspace_path)
+        shutil.copytree(resource_filename( 'xapp_onboarder', 'resources/xapp-std'), self.chart_workspace_path + '/' + self.chart_name)
+        self.setup_helm()
+
+    def setup_helm(self):
+        self.helm_client_path = 'helm'
+        try:
+            process = subprocess.run([self.helm_client_path], stdout=PIPE, stderr=PIPE, check=True)
+
+        except Exception as err:
+            print(err)
+            self.download_helm()
+            self.helm_client_path = settings.CHART_WORKSPACE_PATH + '/helm'
+
+    def download_helm(self):
+        if not os.path.isfile(settings.CHART_WORKSPACE_PATH + '/helm'):
+            log.info("Helm client missing. Trying to download it.")
+            helm_file_name = "helm-v{}-{}-amd64.tar.gz".format(settings.HELM_VERSION, platform.system().lower())
+            helm_download_link = "https://get.helm.sh/" + helm_file_name
+
+
+            try:
+                response = requests_retry_session().get(helm_download_link, timeout=settings.HTTP_TIME_OUT)
+            except Exception as err:
+                error_message = "Download helm client failed. (Caused by: " + str(err)+")"
+                log.error(error_message)
+                raise xAppError(error_message, 500)
+            else:
+                if response.status_code != 200:
+                    error_message = "Download helm chart failed. Helm repo return status code: "+ str(response.status_code)  +" "+ response.content.decode("utf-8")
+                    log.error(error_message)
+                    raise xAppError(error_message, 500)
+
+                file_stream = io.BytesIO(response.content)
+
+                with tarfile.open(fileobj=file_stream) as tar:
+                    helm_client = tar.extractfile(platform.system().lower() + "-amd64/helm")
+                    with open(settings.CHART_WORKSPACE_PATH+'/helm', 'wb') as file:
+                        file.write(helm_client.read())
+                st = os.stat(settings.CHART_WORKSPACE_PATH+'/helm')
+                os.chmod(settings.CHART_WORKSPACE_PATH+'/helm', st.st_mode | stat.S_IEXEC)
+
+
+
+
+    def recursive_convert_config_file(self, node_list=list()):
+        current_node = self.configmap_config_json_file
+        helm_value_path = '.Values'
+        for node in node_list:
+            current_node = current_node.get(node)
+            helm_value_path = helm_value_path + ' ' + "\"" + node + "\""
+
+        if type(current_node) is not dict:
+            raise TypeError("Recursive write was called on a leaf node.")
+
+        for item in current_node.keys():
+            if type(current_node.get(item)) is not dict:
+                current_node[item] = '{{ index '+ helm_value_path +' "'+ item + '" | toJson }}'
+            else:
+                new_node_list = node_list.copy()
+                new_node_list.append(item)
+                self.recursive_convert_config_file(new_node_list)
+
+
+    def append_config_to_config_map(self):
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/templates/appconfig.yaml', 'a') as outputfile:
+            self.recursive_convert_config_file()
+            config_file_json_text = json.dumps(self.configmap_config_json_file, indent=4)
+            indented_config_text = indent(config_file_json_text, 4)
+            indented_config_text = re.sub(r"\"{{", '{{', indented_config_text)
+            indented_config_text = re.sub(r"}}\"", '}}', indented_config_text)
+            indented_config_text = re.sub(r"\\", '', indented_config_text)
+            outputfile.write("  config-file.json: |\n")
+            outputfile.write(indented_config_text)
+            outputfile.write("\n  schema.json: |\n")
+            schema_json = json.dumps(self.schema_file, indent=4)
+            indented_schema_text = indent(schema_json, 4)
+            outputfile.write(indented_schema_text)
+
+
+# This is a work around for the bronze release to be backward compatible to the previous xapp standard helm template
+    def write_config_and_schema(self):
+        os.makedirs(self.chart_workspace_path + '/' + self.chart_name + '/descriptors')
+        os.makedirs(self.chart_workspace_path + '/' + self.chart_name + '/config')
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/descriptors/schema.json', 'w') as outfile:
+            json.dump(self.schema_file, outfile)
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/config/config-file.json', 'w') as outfile:
+            json.dump(self.config_file, outfile)
+
+
+
+    def add_probes_to_deployment(self):
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/templates/deployment.yaml', 'a') as outputfile:
+
+            for probes in ['readinessProbe', 'livenessProbe']:
+                if self.configmap_config_json_file.get(probes):
+                    probe_definition = self.configmap_config_json_file.get(probes)
+                    probe_definition_yaml = yaml.dump(probe_definition, width=1000)
+
+                    print(probe_definition_yaml)
+
+                    indented_probe_definition_yaml = indent(probe_definition_yaml, 12)
+                    indented_probe_definition_yaml = re.sub(r" \| toJson", '', indented_probe_definition_yaml)
+                    indented_probe_definition_yaml = re.sub(r"'", '', indented_probe_definition_yaml)
+                    outputfile.write("          "+probes+":\n")
+                    outputfile.write(indented_probe_definition_yaml)
+
+
+    def append_config_to_values_yaml(self):
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/values.yaml', 'a') as outputfile:
+            yaml.dump(self.config_file, outputfile, default_flow_style=False)
+
+
+    def change_chart_name_version(self):
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/Chart.yaml', 'r') as inputfile:
+            self.chart_yaml = yaml.load(inputfile, Loader=yaml.FullLoader)
+            self.chart_yaml['version'] = self.chart_version
+            self.chart_yaml['name'] = self.chart_name
+
+        with open(self.chart_workspace_path + '/' + self.chart_name + '/Chart.yaml', 'w') as outputfile:
+            yaml.dump(self.chart_yaml, outputfile, default_flow_style=False)
+
+
+    def helm_lint(self):
+        try:
+            process = subprocess.run([self.helm_client_path, "lint", self.chart_workspace_path + "/" + self.chart_name], stdout=PIPE, stderr=PIPE, check=True)
+
+        except OSError as err:
+            raise xAppError(
+                "xApp " + self.chart_name + '-' + self.chart_version + " helm lint failed. (Caused by: " + str(
+                    err) + ")", 500)
+        except subprocess.CalledProcessError as err:
+            raise xAppError(
+                "xApp " + self.chart_name + '-' + self.chart_version + " helm lint failed. (Caused by: " +
+                err.stderr.decode("utf-8") +  "\n" + err.stdout.decode("utf-8") + ")", 400)
+
+    def package_chart(self):
+        self.write_config_and_schema()
+        self.append_config_to_config_map()
+        self.append_config_to_values_yaml()
+        self.add_probes_to_deployment()
+        self.change_chart_name_version()
+        self.helm_lint()
+        try:
+            process = subprocess.run([self.helm_client_path, "package", self.chart_workspace_path + "/" + self.chart_name, "-d"
+                               ,self.chart_workspace_path], stdout=PIPE, stderr=PIPE, check=True)
+
+        except OSError as err:
+                raise xAppError("xApp "+ self.chart_name+'-'+self.chart_version +" packaging failed. (Caused by: "+str(err) +")", 500)
+        except subprocess.CalledProcessError as err:
+            raise xAppError(
+                "xApp " + self.chart_name + '-' + self.chart_version + " packaging failed. (Caused by: " +
+                    err.stderr.decode("utf-8") + ")", 500)
+
+
+
+    def distribute_chart(self):
+        try:
+            repo_manager.upload_chart(self)
+        except RepoManagerError as err:
+            raise xAppError( "xApp " + self.chart_name + '-' + self.chart_version + " distribution failed. (Caused by: " + str(err) + ")" , err.status_code)
+
+    def install_chart_package(xapp_chart_name, version, namespace, overridefile):
+        try: 
+          tar = tarfile.open(xapp_chart_name + "-" + version + ".tgz")
+          tar.extractall()
+          tar.close()
+          if overridefile != "":
+            process = subprocess.run(["helm", "install", xapp_chart_name, "./" + xapp_chart_name, "-f", overridefile, "--namespace=" + namespace], stdout=PIPE, stderr=PIPE, check=True)
+          else:
+            process = subprocess.run(["helm", "install", xapp_chart_name, "./" + xapp_chart_name, "--namespace=" + namespace], stdout=PIPE, stderr=PIPE, check=True)
+          status = 1
+        except subprocess.CalledProcessError as err:
+            print(err.stderr.decode())
+            status=0
+        except Exception as err:
+            print(err)
+            status = 0
+        subprocess.run(["rm", "-rf", xapp_chart_name ])
+        subprocess.run(["rm", "-rf", xapp_chart_name + "-" + version + ".tgz" ])
+        return status
+
+    def uninstall_chart_package(xapp_chart_name, namespace):
+
+        try:
+          process = subprocess.run(["helm", "delete", xapp_chart_name, "--namespace=" + namespace], stdout=PIPE, stderr=PIPE, check=True)
+          status = 1
+
+        except Exception as err:
+                print(err.stderr.decode())
+                status = 0
+
+        return status
+    def health_check_xapp(xapp_chart_name, namespace):
+       
+        try:
+          getpodname=subprocess.check_output("kubectl get po -n " + namespace + " |  grep -w " +  xapp_chart_name + " | awk '{print $1}'", shell=True).decode().strip("\n")
+          if getpodname=="":
+              print("No " + xapp_chart_name + " xapp found under " + namespace + " namespace.")
+              sys.exit()
+          process = subprocess.check_output("kubectl describe po " + getpodname +  " --namespace=" + namespace + "| grep -B 0 -A 5 'Conditions:'", shell=True).decode()
+
+          final= re.search("Initialized.*", process)
+          temp=final.group().split(' ',1)[1]
+          initialized=" ".join(temp.split())
+          
+          final= re.search("Ready.*", process)
+          temp=final.group().split(' ',1)[1]
+          ready=" ".join(temp.split())
+          
+          final= re.search("ContainersReady.*", process)
+          temp=final.group().split(' ',1)[1]
+          containersready=" ".join(temp.split())
+          
+          final= re.search("PodScheduled.*", process)
+          temp=final.group().split(' ',1)[1]
+          podscheduled=" ".join(temp.split())
+         
+          if "True"==initialized and "True"==podscheduled and "True"==containersready and "True"==ready:
+             print("Xapp health status : Healthy")
+          else:
+             print("Xapp health status : Unhealthy")
+             if "True"!=containersready:
+               print("ContainersReady=False, All the containers in the pod are not ready\n")
+             elif "True"!=initialized:
+               print("Initialized=False, Init containers have not yet started\n")
+             elif "True"!=podscheduled:
+               print("PodScheduled=False, Pod has not yet scheduled to node\n")
+             elif "True"!=ready:
+               print("Ready=False, Pod is not ready to serve any request\n")
+        except Exception as err:
+            print(err.output.decode())
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/xapp_schema.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/helm_controller/xapp_schema.py
new file mode 100644 (file)
index 0000000..f3f15b0
--- /dev/null
@@ -0,0 +1,483 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+schema = {
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "$id": "http://o-ran-sc.org/xapp_root.json",
+    "type": "object",
+    "title": "The xApp Root Schema",
+    "properties": {
+        "name": {
+            "$id": "#/properties/name",
+            "type": "string",
+            "title": "The xApp Name",
+            "default": "xapp",
+            "examples": [
+                "example_xapp"
+            ]
+        },
+        "version": {
+            "$id": "#/properties/version",
+            "type": "string",
+            "title": "The xApp version",
+            "default": "1.0.0",
+            "examples": [
+                "1.0.0"
+            ],
+            "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
+        },
+        "annotations": {
+            "$id": "#/properties/annotation",
+            "type": "object",
+            "title": "The k8s pod annotation",
+            "additionalProperties": {
+                "anyOf": [
+                    { "type": "string" },
+                    {
+                        "type": "array",
+                        "items": {
+                            "type": "object"
+                        }
+                    }
+                ]
+            }
+        },
+        "containers": {
+            "$id": "#/properties/containers",
+            "type": "array",
+            "title": "The Container Schema",
+            "items": {
+                "$id": "#/properties/containers/items",
+                "type": "object",
+                "title": "The Container Items Schema",
+                "required": [
+                    "name",
+                    "image"
+                ],
+                "properties": {
+                    "name": {
+                        "$id": "#/properties/containers/items/properties/name",
+                        "type": "string",
+                        "title": "The xApp Container Name",
+                        "default": "xapp",
+                        "examples": [
+                            "xapp"
+                        ]
+                    },
+                    "image": {
+                        "$id": "#/properties/containers/items/properties/image",
+                        "type": "object",
+                        "title": "The Container Image",
+                        "required": [
+                            "registry",
+                            "name",
+                            "tag"
+                        ],
+                        "properties": {
+                            "registry": {
+                                "$id": "#/properties/containers/items/properties/image/properties/registry",
+                                "type": "string",
+                                "title": "The xApp Image Registry",
+                                "default": "nexus3.o-ran-sc.org:10002",
+                                "examples": [
+                                    "nexus3.o-ran-sc.org:10002"
+                                ],
+                                "pattern": "^[A-Za-z0-9\\.-]{1,}\\.[A-Za-z]{1,}(?:\\:\\d+)?$"
+                            },
+                            "name": {
+                                "$id": "#/properties/containers/items/properties/image/properties/name",
+                                "type": "string",
+                                "title": "The xApp Image Name",
+                                "default": "xapp",
+                                "examples": [
+                                    "xapp"
+                                ]
+                            },
+                            "tag": {
+                                "$id": "#/properties/containers/items/properties/image/properties/tag",
+                                "type": "string",
+                                "title": "The xApp Image Tag",
+                                "default": "latest",
+                                "examples": [
+                                    "latest"
+                                ]
+                            }
+                        }
+                    },
+                    "command": {
+                        "$id": "#/properties/containers/items/properties/command",
+                        "type": "array",
+                        "items": [
+                            {
+                                "$id": "#/properties/containers/items/properties/command/item",
+                                "type": "string",
+                                "title": "The Command Item",
+                                "default": "/bin/sh",
+                                "examples": [
+                                    "/bin/sh"
+                                ]
+                            }
+                        ]
+                    },
+                    "args": {
+                        "$id": "#/properties/containers/items/properties/args",
+                        "type": "array",
+                        "items": [
+                            {
+                                "$id": "#/properties/containers/items/properties/args/item",
+                                "type": "string",
+                                "title": "The Command Arguement Item",
+                                "default": "-c",
+                                "examples": [
+                                    "-c"
+                                ]
+                            }
+                        ]
+                    }
+                }
+            }
+        },
+        "livenessProbe": {
+            "$id": "#/properties/livenessprobe",
+            "type": "object",
+            "title": "The Liveness Probe Definition",
+            "properties": {
+                "exec": {
+                    "$id": "#/properties/livenessprobe/exec",
+                    "type": "object",
+                    "title": "Script of Liveness Probe",
+                    "properties": {
+                        "command": {
+                            "$id": "#/properties/livenessprobe/exec/command",
+                            "type": "array",
+                            "items": [
+                                {
+                                    "$id": "#/properties/livenessprobe/exec/command/item",
+                                    "type": "string",
+                                    "title": "The Command Item",
+                                    "default": "/bin/sh",
+                                    "examples": [
+                                        "/bin/sh"
+                                    ]
+                                }
+                            ]
+                        }
+                    },
+                    "required": [
+                        "command"
+                    ]
+                },
+                "httpGet": {
+                    "$id": "#/properties/livenessprobe/httpget",
+                    "type": "object",
+                    "title": "Http of Liveness Probe",
+                    "properties": {
+                        "path": {
+                            "$id": "#/properties/livenessprobe/httpget/path",
+                            "type": "string",
+                            "title": "The Path of Http Liveness Probe",
+                            "default": "/health",
+                            "examples": [
+                                "/health"
+                            ]
+                        },
+                        "port": {
+                            "$id": "#/properties/livenessprobe/httpget/port",
+                            "type": "integer",
+                            "title": "The Port of Http Liveness Probe",
+                            "default": 80,
+                            "examples": [
+                                80
+                            ]
+                        }
+                    },
+                    "required": [
+                        "path",
+                        "port"
+                    ]
+                },
+                "initialDelaySeconds": {
+                    "$id": "#/properties/livenessprobe/initialdelayseconds",
+                    "type": "integer",
+                    "title": "Initial Delay of Liveness Probe",
+                    "default": 5,
+                    "examples": [
+                        5
+                    ]
+                },
+                "periodSeconds": {
+                    "$id": "#/properties/livenessprobe/periodseconds",
+                    "type": "integer",
+                    "title": "Period of Liveness Probe",
+                    "default": 15,
+                    "examples": [
+                        15
+                    ]
+                }
+            },
+            "oneOf": [
+                {
+                    "$id": "#/properties/livenessprobe/oneof/exec",
+                    "required": ["exec", "initialDelaySeconds", "periodSeconds"]
+                },
+                {
+                    "$id": "#/properties/livenessprobe/oneof/httpget",
+                    "required": ["httpGet", "initialDelaySeconds", "periodSeconds"]
+                }
+            ]
+        },
+        "readinessProbe": {
+            "$id": "#/properties/readinessprobe",
+            "type": "object",
+            "title": "The Readiness Probe Definition",
+            "properties": {
+                "exec": {
+                    "$id": "#/properties/readinessprobe/exec",
+                    "type": "object",
+                    "title": "Script of Readiness Probe",
+                    "properties": {
+                        "command": {
+                            "$id": "#/properties/readinessprobe/exec/command",
+                            "type": "array",
+                            "items": [
+                                {
+                                    "type": "string"
+                                }
+                            ]
+                        }
+                    },
+                    "required": [
+                        "command"
+                    ]
+                },
+                "httpGet": {
+                    "$id": "#/properties/readinessprobe/httpget",
+                    "type": "object",
+                    "title": "Http of Readiness Probe",
+                    "properties": {
+                        "path": {
+                            "$id": "#/properties/readinessprobe/httpget/path",
+                            "type": "string",
+                            "title": "The Path of Http Readiness Probe",
+                            "default": "/health",
+                            "examples": [
+                                "/health"
+                            ]
+                        },
+                        "port": {
+                            "$id": "#/properties/readinessprobe/httpget/port",
+                            "type": "integer",
+                            "title": "The Port of Http Readiness Probe",
+                            "default": 80,
+                            "examples": [
+                                80
+                            ]
+                        }
+                    },
+                    "required": [
+                        "path",
+                        "port"
+                    ]
+                },
+                "initialDelaySeconds": {
+                    "$id": "#/properties/readinessprobe/initialdelayseconds",
+                    "type": "integer",
+                    "title": "Initial Delay of Readiness Probe",
+                    "default": 5,
+                    "examples": [
+                        5
+                    ]
+                },
+                "periodSeconds": {
+                    "$id": "#/properties/readinessprobe/periodseconds",
+                    "type": "integer",
+                    "title": "Period of Readiness Probe",
+                    "default": 15,
+                    "examples": [
+                        15
+                    ]
+                }
+            },
+            "oneOf": [
+                {
+                    "$id": "#/properties/readinessprobe/oneof/exec",
+                    "required": ["exec", "initialDelaySeconds", "periodSeconds"]
+                },
+                {
+                    "$id": "#/properties/readinessprobe/oneof/httpget",
+                    "required": ["httpGet", "initialDelaySeconds", "periodSeconds"]
+                }
+            ]
+        },
+        "messaging": {
+            "type": "object",
+            "$id": "#/properties/messaging",
+            "title": "The Messaging Schema",
+            "properties": {
+                "ports": {
+                    "$id": "#/properties/messaging/ports",
+                    "type": "array",
+                    "title": "The Ports for Messaging",
+                    "items": {
+                        "$id": "#/properties/messaging/ports/items",
+                        "type": "object",
+                        "title": "The Item of Port",
+                        "required": ["name", "container", "port"],
+                        "dependencies": {
+                            "txMessages": ["rxMessages", "policies"],
+                            "rxMessages": ["txMessages", "policies"],
+                            "policies": ["rxMessages", "txMessages"]
+                        },
+                        "properties": {
+                            "name": {
+                                "$id": "#/properties/messaging/ports/items/name",
+                                "type": "string",
+                                "title": "The Name of the Port",
+                                "default": "App",
+                                "examples": [
+                                    "App"
+                                ]
+                            },
+                            "container": {
+                                "$id": "#/properties/messaging/ports/items/container",
+                                "type": "string",
+                                "title": "The Container of the Port",
+                                "default": "xapp",
+                                "examples": [
+                                    "xapp"
+                                ]
+                            },
+                            "port": {
+                                "$id": "#/properties/messaging/ports/items/port",
+                                "type": "integer",
+                                "title": "The Port Number",
+                                "default": 8080,
+                                "examples": [
+                                    8080
+                                ]
+                            },
+                            "description": {
+                                "$id": "#/properties/messaging/ports/items/description",
+                                "type": "string",
+                                "title": "The description for the port",
+                                "default": "port description",
+                                "examples": [
+                                    "port description"
+                                ]
+                            },
+                            "txMessages": {
+                                "$id": "#/properties/messaging/ports/items/txmessages",
+                                "type": "array",
+                                "title": "The txMessage Types",
+                                "items": {
+                                    "$id": "#/properties/messaging/ports/items//txmessages/item",
+                                    "type": "string",
+                                    "title": "The txMessage Types Item",
+                                    "default": "RIC_SUB",
+                                    "examples": [
+                                        "RIC_SUB"
+                                    ]
+                                }
+                            },
+                            "rxMessages": {
+                                "$id": "#/properties/messaging/ports/items/rxmessages",
+                                "type": "array",
+                                "title": "The rxMessage Types",
+                                "items": {
+                                    "$id": "#/properties/messaging/ports/items/rxmessages/item",
+                                    "type": "string",
+                                    "title": "The rxMessage Types Item",
+                                    "default": "RIC_SUB",
+                                    "examples": [
+                                        "RIC_SUB"
+                                    ]
+                                }
+                            },
+                            "policies": {
+                                "$id": "#/properties/messaging/ports/items/policies",
+                                "type": "array",
+                                "title": "The Policies Types",
+                                "items": {
+                                    "$id": "#/properties/messaging/ports/items/policies/item",
+                                    "type": "integer",
+                                    "title": "The Policy Types Item",
+                                    "default": 1,
+                                    "examples": [
+                                        1
+                                    ]
+                                }
+                            }
+                        }
+                    }
+                }
+            },
+            "required": [
+                "ports"
+            ]
+
+        },
+        "metrics": {
+            "type": "object",
+            "$id": "#/properties/metrics",
+            "title": "The Metrics Schema",
+            "items": {
+                "$id": "#/properties/metrics/items",
+                "type": "object",
+                "title": "The Metrics Items Schema",
+                "required": [
+                    "objectName",
+                    "objectInstance",
+                    "name",
+                    "type",
+                    "description"
+                ],
+                "properties": {
+                    "objectName": {
+                        "$id": "#/properties/metrics/items/objectname",
+                        "type": "string",
+                        "title": "The Object Name"
+                    },
+                    "objectInstance": {
+                        "$id": "#/properties/metrics/items/objectinstance",
+                        "type": "string",
+                        "title": "The Object Instance"
+                    },
+                    "name": {
+                        "$id": "#/properties/metrics/items/name",
+                        "type": "string",
+                        "title": "The Object Name"
+                    },
+                    "type": {
+                        "$id": "#/properties/metrics/items/type",
+                        "type": "string",
+                        "title": "The Object Type"
+                    },
+                    "description": {
+                        "$id": "#/properties/metrics/items/description",
+                        "type": "string",
+                        "title": "The Object Description"
+                    }
+                }
+            }
+        },
+        "controls": {
+            "required": [
+                "__empty_control_section__"
+            ]
+        }
+
+    }
+}
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/logging.conf b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/logging.conf
new file mode 100644 (file)
index 0000000..76ed704
--- /dev/null
@@ -0,0 +1,28 @@
+[loggers]
+keys=root, xapp_onboarder
+
+[handlers]
+keys=console
+
+[formatters]
+keys=simple
+
+[logger_root]
+level=DEBUG
+handlers=console
+
+[logger_xapp_onboarder]
+level=DEBUG
+handlers=console
+qualname=xapp_onboarder
+propagate=0
+
+[handler_console]
+class=StreamHandler
+level=DEBUG
+formatter=simple
+args=(sys.stdout,)
+
+[formatter_simple]
+format=%(asctime)s - %(levelname)s - %(message)s - %(name)s
+datefmt=
\ No newline at end of file
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/repo_manager/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/repo_manager/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/repo_manager/repo_manager.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/repo_manager/repo_manager.py
new file mode 100644 (file)
index 0000000..1596b55
--- /dev/null
@@ -0,0 +1,157 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import yaml
+import json
+from xapp_onboarder.server import settings
+import logging
+import requests
+import time
+from requests.adapters import HTTPAdapter
+from requests.packages.urllib3.util.retry import Retry
+
+log = logging.getLogger(__name__)
+
+def requests_retry_session(retries=3, backoff_factor=0.3, status_forcelist=(500, 502, 504, 400, 401, 409), session=None,):
+    session = session or requests.Session()
+    retry = Retry(
+        total=retries,
+        read=retries,
+        connect=retries,
+        backoff_factor=backoff_factor,
+        status_forcelist=status_forcelist,
+    )
+    adapter = HTTPAdapter(max_retries=retry)
+    session.mount('http://', adapter)
+    session.mount('https://', adapter)
+    return session
+
+
+
+class RepoManagerError(Exception):
+    def __init__(self, message, status_code):
+        # Call the base class constructor with the parameters it needs
+        super().__init__(message)
+        self.status_code = status_code
+
+
+class repoManager():
+    def __init__(self, repo_url):
+        self.repo_url = repo_url
+        self.__is_repo_ready__ = False
+        log.debug("Initialize connection to helm chart repo at "+self.repo_url)
+        t0 = time.time()
+        self.retry_session = requests_retry_session()
+        try:
+            response = self.retry_session.get(self.repo_url, timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            t1 = time.time()
+            log.error('Failed to connect to helm chart repo ' + self.repo_url + ' after ' + str(
+                settings.HTTP_RETRY) + ' retries and ' + str(t1 - t0) + ' seconds. (Caused by: ' + err.__class__.__name__ + ')')
+        else:
+            self.__is_repo_ready__ = True
+
+
+
+    def is_repo_ready(self):
+        return self.__is_repo_ready__
+
+    def get_index(self):
+        try:
+            response = self.retry_session.get(self.repo_url +'/index.yaml', timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            raise RepoManagerError("Get helm repo index failed. (Caused by: " + str(err)+")", 500)
+        else:
+            if response.status_code != 200:
+                raise RepoManagerError("Get helm repo index failed. Helm repo return status code: {}, {}".format(response.status_code, response.content.decode("utf-8")))
+            return yaml.load(response.content, Loader=yaml.FullLoader)
+
+    def upload_chart(self, xapp):
+
+        xapp_chart_index = self.get_index()
+        found_xapp = False
+        for chart in xapp_chart_index.get('entries', {}).get(xapp.chart_name, []):
+            if chart['version'] == xapp.chart_version:
+                found_xapp = True
+
+        if found_xapp:
+            if settings.ALLOW_REDEPLOY:
+                self.delete_chart(xapp)
+            else:
+                raise RepoManagerError("Upload helm chart failed. Redeploy xApp helm chart is not allowed.", 400)
+
+        headers = {'Content-Type': 'application/json'}
+        chart_package_path = xapp.chart_workspace_path + '/' + xapp.chart_name + '-' + xapp.chart_version + '.tgz'
+        with open(chart_package_path, mode='rb') as filereader:
+            fileContent = filereader.read()
+
+        try:
+            response = self.retry_session.post(self.repo_url +'/api/charts', headers=headers, data=fileContent, timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            raise RepoManagerError("Upload helm chart failed. (Caused by: " + str(err) + ")", 500)
+        else:
+            if response.status_code != 201:
+                raise RepoManagerError("Upload helm chart failed. Helm repo return status code: "+ str(response.status_code)  +" "+ response.content.decode("utf-8"), response.status_code)
+
+
+    def delete_chart(self, xapp):
+
+        headers = {'Content-Type': 'application/json'}
+
+        try:
+            response = self.retry_session.delete(self.repo_url +'/api/charts/' + xapp.chart_name
+                                                 + '/' + xapp.chart_version, headers=headers, timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            raise RepoManagerError("Delete helm chart failed." + str(err), 500)
+        else:
+            if response.status_code != 200:
+                response_dict = json.loads(response.content)
+                if xapp.chart_name+'-'+xapp.chart_version+'.tgz' not in response_dict["error"]:
+                    raise RepoManagerError("Delete helm chart failed. Helm repo return status code:" + str(response.status_code)  +" "+ response.content.decode("utf-8"),response.status_code)
+
+
+    def get_xapp_list(self, xapp_chart_name=None):
+
+        request_path = self.repo_url+'/api/charts'
+        if xapp_chart_name:
+            request_path = request_path +'/' + xapp_chart_name
+
+        try:
+            response = self.retry_session.get(request_path, timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            raise RepoManagerError("Get xApp charts list failed. (Caused by: " + str(err)+")", 500)
+        else:
+            if response.status_code != 200:
+                raise RepoManagerError("Get xApp charts list failed. Helm repo return status code: "+ str(response.status_code)  +" "+ response.content.decode("utf-8"), response.status_code)
+            return json.loads(response.content)
+
+
+    def download_xapp_chart(self, xapp_chart_name, version):
+
+        request_path = self.repo_url+'/charts/'+xapp_chart_name+'-'+version+'.tgz'
+        try:
+            response = self.retry_session.get(request_path, timeout=settings.HTTP_TIME_OUT)
+        except Exception as err:
+            raise RepoManagerError("Download helm chart failed. (Caused by: " + str(err)+")", 500)
+        else:
+            if response.status_code != 200:
+                raise RepoManagerError( "Download helm chart failed. Helm repo return status code: "+ str(response.status_code)  +" "+ response.content.decode("utf-8"), response.status_code)
+            return response.content
+
+
+
+
+repo_manager = repoManager(settings.CHART_REPO_URL)
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/Chart.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/Chart.yaml
new file mode 100644 (file)
index 0000000..2fb8da8
--- /dev/null
@@ -0,0 +1,20 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+apiVersion: v1
+appVersion: "1.0"
+description: Standard xApp Helm Chart
+name: xapp-std
+version: 0.0.1
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/_helpers.tpl b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/_helpers.tpl
new file mode 100644 (file)
index 0000000..d492ff8
--- /dev/null
@@ -0,0 +1,82 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "ricxapp.name" -}}
+  {{- default .Chart.Name .Values.name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "ricxapp.fullname" -}}
+  {{- $name := ( include "ricxapp.name" . ) -}}
+  {{- $fullname := ( printf "%s-%s" .Release.Namespace $name ) -}}
+  {{- default $fullname .Values.fullname | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "ricxapp.chart" -}}
+  {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{- define "ricxapp.namespace" -}}
+  {{- default .Release.Namespace .Values.nsPrefix -}}
+{{- end -}}
+
+{{- define "ricxapp.servicename.rmr" -}}
+  {{- $name := ( include "ricxapp.fullname" . ) -}}
+  {{- printf "service-%s-rmr" $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{- define "ricxapp.servicename.http" -}}
+  {{- $name := ( include "ricxapp.fullname" . ) -}}
+  {{- printf "service-%s-http" $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{- define "ricxapp.configmapname" -}}
+  {{- $name := ( include "ricxapp.fullname" . ) -}}
+  {{- printf "configmap-%s" $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{- define "ricxapp.servicename" -}}
+  {{- $name := ( include "ricxapp.fullname" . ) -}}
+  {{- printf "service-%s" $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{- define "ricxapp.deploymentname" -}}
+  {{- $name := ( include "ricxapp.fullname" . ) -}}
+  {{- printf "deployment-%s" $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+
+{{- define "ricxapp.containername" -}}
+  {{- $name := ( include "ricxapp.fullname" . ) -}}
+  {{- printf "container-%s" $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+
+{{- define "ricxapp.imagepullsecret" -}}
+  {{- $reponame := .repo -}}
+  {{- $postfix := $reponame | replace "." "-" | replace ":" "-" | replace "/" "-" | trunc 63 | trimSuffix "-" -}}
+  {{- printf "secret-%s" $postfix -}}
+{{- end -}}
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/appconfig.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/appconfig.yaml
new file mode 100644 (file)
index 0000000..03bc7e8
--- /dev/null
@@ -0,0 +1,21 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################'
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "ricxapp.configmapname" . }}-appconfig
+data:
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/appenv.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/appenv.yaml
new file mode 100644 (file)
index 0000000..3ab0003
--- /dev/null
@@ -0,0 +1,32 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "ricxapp.configmapname" . }}-appenv
+data:
+  {{- if .Values.appenv }}
+    {{- toYaml .Values.appenv | nindent 2 }}
+  {{- end }}
+  RMR_RTG_SVC: "4561"
+  RMR_SRC_ID: {{ include "ricxapp.servicename.rmr" . }}.{{ include "ricxapp.namespace" . }}
+  XAPP_DESCRIPTOR_PATH: {{ .Values.appconfig.path }}
+  DBAAS_SERVICE_HOST: "{{ .Values.ricplt.dbaasService }}"
+  DBAAS_SERVICE_PORT: "6379"
+  DBAAS_PORT_6379_TCP_ADDR: "{{ .Values.ricplt.dbaasService }}"
+  DBAAS_PORT_6379_TCP_PORT: "6379"
+  SERVICE_METRICSDB_HOST: "{{ .Values.ricplt.metricsdbService }}"
+  SERVICE_METRICSDB_PORT: "8086"
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/deployment.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/deployment.yaml
new file mode 100644 (file)
index 0000000..3c4c052
--- /dev/null
@@ -0,0 +1,117 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################'
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "ricxapp.fullname" . }}
+  labels:
+    app: {{ include "ricxapp.namespace" . }}-{{ include "ricxapp.name" . }}
+    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+    release: {{ .Release.Name }}
+    heritage: {{ .Release.Service }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  selector:
+    matchLabels:
+      app: {{ include "ricxapp.namespace" . }}-{{ include "ricxapp.name" . }}
+      release: {{ .Release.Name }}
+  template:
+    metadata:
+      {{- if .Values.annotations }}
+      annotations:
+        {{- range $key, $value := .Values.annotations }}
+          {{- if kindIs "string" $value }}
+        {{ $key }}: {{ $value | toPrettyJson }}
+          {{- else }}
+        {{ $key }}: |
+{{- $value | toPrettyJson | nindent 10 }}
+          {{- end }}
+        {{- end -}}
+      {{ end }}
+      labels:
+        app: {{ include "ricxapp.namespace" . }}-{{ include "ricxapp.name" . }}
+        kubernetes_name: {{ include "ricxapp.namespace" . }}_{{ include "ricxapp.name" . }}
+        release: {{ .Release.Name }}
+    spec:
+      hostname: {{ include "ricxapp.name" . }}
+      imagePullSecrets:
+{{- range .Values.containers }}
+        - name: {{ .image.registry | replace "." "-" | replace ":" "-" | replace "/" "-" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+      volumes:
+        - name: config-volume
+          configMap:
+            name: {{ include "ricxapp.configmapname" . }}-appconfig
+        {{- if .Values.controls.fileStorage }}
+        - name: diskwriter
+          hostPath: 
+            path: {{ .Values.storage.mountPath }}
+            type: DirectoryOrCreate
+        {{- end }}
+      containers:
+{{- $containers := .Values.containers }}
+{{- $ports := .Values.messaging.ports }}
+{{- range $container := $containers }}
+  {{- $portlist := list }}
+  {{- range $port := $ports }}
+    {{- if eq $port.container $container.name }}
+        {{- $portlist = append $portlist $port }}
+    {{- end }}
+  {{- end }}
+        - name: {{ $container.name }}
+          image: "{{ $container.image.registry }}/{{ $container.image.name }}:{{ $container.image.tag }}"
+          {{- if $container.command }}
+          command: [
+          {{- range $command := $container.command -}}
+          {{- $command | quote -}}
+          {{- if ne $command (last $container.command) }}
+          {{- print ", " -}}
+          {{- end -}}
+          {{- end -}}
+          {{- print "]" -}}
+          {{- end}}
+          {{- if $container.args }}
+          args: [
+          {{- range $arg := $container.args -}}
+          {{- $arg | quote -}}
+          {{- if ne $arg (last $container.args) }}
+          {{- print ", " -}}
+          {{- end -}}
+          {{- end -}}
+          {{- print "]" -}}
+          {{- end}}
+          imagePullPolicy: {{ $.Values.image_pull_policy }}
+  {{- if $portlist }}
+          ports:
+    {{- range $port := $portlist }}
+            - name: {{ $port.name }}
+              containerPort: {{ $port.port }}
+              protocol: TCP
+    {{- end }}
+  {{- end }}
+{{- end }}
+          volumeMounts:
+            - name: config-volume
+              mountPath: {{ .Values.appconfig.path }}
+            {{- if .Values.controls.fileStorage }}
+            - name: diskwriter
+              mountPath: {{ .Values.storage.mountPath }}
+            {{- end }}
+          envFrom:
+            - configMapRef:
+                name: {{ include "ricxapp.configmapname" . }}-appenv
+            - configMapRef:
+                name: dbaas-appconfig
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/service-http.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/service-http.yaml
new file mode 100644 (file)
index 0000000..32b7e58
--- /dev/null
@@ -0,0 +1,43 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#   Copyright (c) 2019 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.                                             #
+################################################################################
+{{- $topCtx :=  . }}
+{{- range .Values.messaging.ports  }}
+{{- if contains "rmr" .name }}
+{{ else }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "ricxapp.servicename" $topCtx }}-{{ .name }}
+  namespace: {{ include "ricxapp.namespace" $topCtx }}
+  labels:
+    app: {{ include "ricxapp.namespace" $topCtx }}-{{ include "ricxapp.name" $topCtx }}
+    chart: {{ $topCtx.Chart.Name }}-{{ $topCtx.Chart.Version | replace "+" "_" }}
+    release: {{ $topCtx.Release.Name }}
+    heritage: {{ $topCtx.Release.Service }}
+spec:
+  type: ClusterIP
+  ports:
+    - port: {{ .port }}
+      targetPort: {{ .name }}
+      protocol: TCP
+      name: {{ .name }}
+  selector:
+    app: {{ include "ricxapp.namespace" $topCtx }}-{{ include "ricxapp.name" $topCtx }}
+    release: {{ $topCtx.Release.Name }}
+{{- end }}
+{{- end }}
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/service-rmr.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/templates/service-rmr.yaml
new file mode 100644 (file)
index 0000000..8c7b656
--- /dev/null
@@ -0,0 +1,50 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#   Copyright (c) 2019 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.                                             #
+################################################################################
+
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "ricxapp.servicename.rmr" . }}
+  namespace: {{ include "ricxapp.namespace" . }}
+  labels:
+    app: {{ include "ricxapp.namespace" . }}-{{ include "ricxapp.name" . }}
+    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+    release: {{ .Release.Name }}
+    heritage: {{ .Release.Service }}
+spec:
+  type: ClusterIP
+  ports:
+  {{- range .Values.messaging.ports  }}
+  {{- if eq .name "rmrdata" }}
+    - port: {{ .port }}
+      targetPort: {{ .name }}
+      protocol: TCP
+      name: {{ .name }}
+  {{- end }}
+  {{- end }}
+  {{- range .Values.messaging.ports  }}
+  {{- if contains "rmr" .name }} {{- if ne .name "rmrdata" }}
+    - port: {{ .port }}
+      targetPort: {{ .name }}
+      protocol: TCP
+      name: {{ .name }}
+  {{- end }}
+  {{- end }}
+  {{- end }}
+  selector:
+    app: {{ include "ricxapp.namespace" . }}-{{ include "ricxapp.name" . }}
+    release: {{ .Release.Name }}
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/values.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/resources/xapp-std/values.yaml
new file mode 100644 (file)
index 0000000..12845d0
--- /dev/null
@@ -0,0 +1,60 @@
+################################################################################
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################'
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+ricplt:
+# This section is reserved for values imported from RIC Platform charts
+  dbaasService: "service-ricplt-dbaas-tcp.ricplt.svc.cluster.local"
+  metricsdbService: "service-metricsdb.ricplt.svc.cluster.local"
+  pltIngressUrl: "ricplt-entry"
+  xappIngressUrl: "ricxapp-entry"
+
+  appmgrRMRService: "service-ricplt-appmgr-rmr.ricplt.svc.cluster.local"
+  e2mgrRMRService: "service-ricplt-e2mgr-rmr.ricplt.svc.cluster.local"
+  e2termRMRService: "service-ricplt-e2term-rmr.ricplt.svc.cluster.local"
+  rtmgrRMRService: "service-ricplt-rtmgr-rmr.ricplt.svc.cluster.local"
+  a1mediatorRMRService: "service-ricplt-a1mediator-rmr.ricplt.svc.cluster.local"
+
+# Location of the xApp config files injected from the xApp descriptor
+appconfig:
+    path: /opt/ric/config
+
+# Location of volume based on HostPath of type Directory
+storage:
+    mountPath: /home/kpm/storage
+
+# Number of replica
+replicaCount: 1
+
+# Image pulling policy
+image_pull_policy: IfNotPresent
+
+# Environment variables that will be injected
+appenv: {}
+
+# Liveness probe definition. If empty, liveness probe will be disabled
+livenessProbe: {}
+
+# Readiness probe definition. If empty, readiness probe will be disabled
+readinessProbe: {}
+
+# Instance name. If empty, chart name will be used
+name: {}
+
+# Full instance name. If empty, full name will be constructed from name
+fullname: {}
+
+###############    The following are from the xApp descriptor     ###############
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/__init__.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/cli.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/cli.py
new file mode 100755 (executable)
index 0000000..03d0827
--- /dev/null
@@ -0,0 +1,171 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+
+import fire
+import json
+import os
+import pkg_resources
+import logging.config
+import operator
+
+from xapp_onboarder.api.charts import get_charts_list, download_chart_package, download_values_yaml
+from xapp_onboarder.repo_manager.repo_manager import repo_manager
+from xapp_onboarder.api.onboard import onboard, download_config_and_schema_and_onboard
+from xapp_onboarder.helm_controller.xApp_builder import xApp, xAppError
+
+log = logging.getLogger(__name__)
+
+
+class cli():
+    """This is the cli tool for xapp_onboarder."""
+
+    def get_charts_list(self, xapp_chart_name=''):
+        """Get the list of all onboarded xApps. To show all version of an xApp, use --xapp_chart_name to
+        specify the name."""
+        message, status = get_charts_list(xapp_chart_name=xapp_chart_name)
+
+        return json.dumps(message, indent=4, sort_keys=True)
+
+    def download_helm_chart(self, xapp_chart_name, version, output_path="."):
+        """Download the helm chart package of an xApp. Specify xApp name with --xapp_chart_name, version with
+        --version. Optionally use --output_path to specify the path to save the file."""
+        content, status = download_chart_package(xapp_chart_name=xapp_chart_name, version=version)
+
+        if status != 200:
+            return json.dumps(content, indent=4, sort_keys=True)
+
+        try:
+            if os.path.isabs(output_path):
+                path = output_path + '/' + xapp_chart_name + '-' + version + '.tgz'
+            else:
+                path = os.getcwd() + '/' + output_path + '/' + xapp_chart_name + '-' + version + '.tgz'
+
+            if not os.path.exists(os.path.dirname(path)):
+                os.makedirs(os.path.dirname(path))
+
+            with open(path, 'wb') as outputfile:
+                outputfile.write(content)
+        except Exception as err:
+            return err
+        return {"status": "OK"}
+
+    def download_values_yaml(self, xapp_chart_name, version, output_path="."):
+        """Download the values.yaml file that can be used to override parameters at runtime. Specify xApp name with
+        --xapp_chart_name, version with --version. Optionally use --output_path to specify the path to save the file.
+        """
+        content, status = download_values_yaml(xapp_chart_name=xapp_chart_name, version=version)
+
+        if status != 200:
+            return json.dumps(content, indent=4, sort_keys=True)
+
+        try:
+            if os.path.isabs(output_path):
+                path = output_path + '/values.yaml'
+            else:
+                path = os.getcwd() + '/' + output_path + '/values.yaml'
+
+            if not os.path.exists(os.path.dirname(path)):
+                os.makedirs(os.path.dirname(path))
+
+            with open(path, 'wb') as outputfile:
+                outputfile.write(content)
+        except Exception as err:
+            return err
+        return {"status": "OK"}
+
+    def health(self):
+        """Health check. If xapp onboarder is not ready, it return false."""
+        return repo_manager.is_repo_ready()
+
+    def install(self, xapp_chart_name, version, namespace,overridefile="" ):
+        """Installing the xapp using the charts name and version,optionally can provide the yaml file to override"""
+        resp = self.download_helm_chart(xapp_chart_name, version)
+
+        status = xApp.install_chart_package(xapp_chart_name=xapp_chart_name, version=version, namespace=namespace,overridefile=overridefile)
+        if status == 1:
+           return {"status": "OK"}
+        else:
+           return {"status": "NOT_OK"} 
+
+    def uninstall(self, xapp_chart_name ,namespace):
+        """Uninstalling the xapp using the charts name"""
+        status = xApp.uninstall_chart_package(xapp_chart_name=xapp_chart_name, namespace=namespace)
+        if status == 1:
+           return {"status": "OK"}
+        else:
+           print("No Xapp to uninstall")
+           return {"status": "NOT_OK"}
+
+    def upgrade(self, xapp_chart_name, old_version , new_version, namespace):
+        """Upgrading the xapp to the new version specified"""
+        resp = self.uninstall(xapp_chart_name, namespace) 
+        if resp["status"] == "OK":
+           status = self.install(xapp_chart_name, new_version, namespace)
+           if status["status"] == "OK":
+              return {"status": "OK"}
+           else:
+              self.uninstall(xapp_chart_name, namespace)
+              self.install(xapp_chart_name, old_version, namespace)
+              return {"status": "NOT_OK"}
+        else:
+           return {"status": "NOT_OK"}
+
+    def rollback(self, xapp_chart_name, new_version , old_version, namespace):
+        """Rollback the xapp to the version specified"""
+
+        resp = self.upgrade(xapp_chart_name, new_version, old_version, namespace) 
+
+        if resp["status"] == "OK":
+            return {"status": "OK"}
+        else:
+            return {"status": "NOT_OK"}
+
+    def onboard(self, config_file_path, shcema_file_path="../../../docs/xapp_onboarder/guide/embedded-schema.json"):
+        """Onboard an xApp with local descriptor files. Use --config_file_path to specify the path to
+        config-file.json file, --shcema_file_path to specify the path to schema.json file. """
+        try:
+            with open(config_file_path, 'r') as inputfile:
+                config_file = json.load(inputfile)
+
+            with open(shcema_file_path, 'r') as inputfile:
+                schema_file = json.load(inputfile)
+
+        except Exception as err:
+            return err
+
+        message, status = onboard(config_file, schema_file)
+        return json.dumps(message, indent=4, sort_keys=True)
+
+    def download_and_onboard(self, config_file_url, schema_file_url):
+        """Onboard an xApp with URLs pointing to the xApp descriptor files. Use --config_file_url to specify the
+        config-file.json URL, --schema_file_url to specify the schema.json URL. """
+        message, status = download_config_and_schema_and_onboard(config_file_url, schema_file_url)
+        return json.dumps(message, indent=4, sort_keys=True)
+    
+    def health_check(self, xapp_chart_name ,namespace):
+        """status check of the xapp using the charts name"""
+        xApp.health_check_xapp(xapp_chart_name=xapp_chart_name, namespace=namespace)
+
+
+def run():
+    logger_config = pkg_resources.resource_filename("xapp_onboarder", 'logging.conf')
+    logging.config.fileConfig(logger_config)
+    fire.Fire(cli(), name='xapp_onboarder')
+
+if __name__ == "__main__":
+
+    run()
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/server.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/server.py
new file mode 100644 (file)
index 0000000..838aba7
--- /dev/null
@@ -0,0 +1,61 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+import pkg_resources
+import logging.config
+from xapp_onboarder.server import settings
+import logging
+from flask import Flask, Blueprint
+from xapp_onboarder.api.api_reference import api
+from xapp_onboarder.api.endpoints.onboard_ep import ns as onboard_ns
+from xapp_onboarder.api.endpoints.health_check_ep import ns as health_check_ns
+from xapp_onboarder.api.endpoints.charts_ep import ns as charts_ns
+from xapp_onboarder.helm_controller.artifacts_manager import artifacts_manager
+
+log = logging.getLogger(__name__)
+
+class server(object):
+    def __init__(self):
+        self.app = Flask(__name__)
+        self.app.config['SWAGGER_UI_DOC_EXPANSION'] = settings.RESTPLUS_SWAGGER_UI_DOC_EXPANSION
+        self.app.config['RESTPLUS_VALIDATE'] = settings.RESTPLUS_VALIDATE
+        self.app.config['RESTPLUS_MASK_SWAGGER'] = settings.RESTPLUS_MASK_SWAGGER
+        self.app.config['ERROR_404_HELP'] = settings.RESTPLUS_ERROR_404_HELP
+        self.api = api
+        self.api_bp = Blueprint('api', __name__, url_prefix='/api/v1')
+        self.api.init_app(self.api_bp)
+        self.api.add_namespace(onboard_ns)
+        self.api.add_namespace(health_check_ns)
+        self.api.add_namespace(charts_ns)
+        self.app.register_blueprint(self.api_bp)
+        self.artifacts_manager = artifacts_manager()
+        self.artifacts_manager.start()
+
+    def run(self):
+        log.info('>>>>> Starting development xapp_onboarder at http://{}/api/v1/ <<<<<'.format(self.app.config['SERVER_NAME']))
+        self.app.run(debug=settings.FLASK_DEBUG, host='0.0.0.0', port=settings.FLASK_PORT)
+
+
+
+
+
+def main():
+    logger_config = pkg_resources.resource_filename("xapp_onboarder", 'logging.conf')
+    logging.config.fileConfig(logger_config)
+    server().run()
+
+if __name__ == "__main__":
+    main()
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/settings.py b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/server/settings.py
new file mode 100644 (file)
index 0000000..04100a5
--- /dev/null
@@ -0,0 +1,40 @@
+################################################################################
+#   Copyright (c) 2020 AT&T Intellectual Property.                             #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+
+import os
+
+# Flask settings
+FLASK_PORT = os.environ.get('FLASK_PORT') or '8888'
+FLASK_DEBUG = os.environ.get('FLASK_DEBUG') or True  # Do not use debug mode in production
+
+# Flask-Restplus settings
+RESTPLUS_SWAGGER_UI_DOC_EXPANSION = os.environ.get('RESTPLUS_SWAGGER_UI_DOC_EXPANSION') or 'list'
+RESTPLUS_VALIDATE = os.environ.get('RESTPLUS_VALIDATE') or True
+RESTPLUS_MASK_SWAGGER = os.environ.get('RESTPLUS_MASK_SWAGGER') or False
+RESTPLUS_ERROR_404_HELP = os.environ.get('RESTPLUS_ERROR_404_HELP') or False
+
+# xapp_onboarder settings
+CHART_WORKSPACE_PATH = os.environ.get('CHART_WORKSPACE_PATH') or '/tmp/xapp_onboarder'
+CHART_REPO_URL = os.environ.get('CHART_REPO_URL') or 'http://0.0.0.0:8080'
+HTTP_TIME_OUT = int(os.environ.get('HTTP_TIME_OUT') or 10)
+HELM_VERSION = os.environ.get('HELM_VERSION') or '2.12.3'
+HTTP_RETRY = os.environ.get('HTTP_RETRY') or 3
+ALLOW_REDEPLOY = os.environ.get('ALLOW_REDEPLOY') or True
+CHART_WORKSPACE_SIZE = os.environ.get('CHART_WORKSPACE_SIZE') or '500 MB'
+MOCK_TEST_MODE = os.environ.get('MOCK_TEST_MODE') or False
+MOCK_TEST_HELM_REPO_TEMP_DIR = os.environ.get('MOCK_TEST_HELM_REPO_TEMP_DIR') or '/tmp/mock_helm_repo'
+
+
diff --git a/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/xapp-onboarder-api.yaml b/xapp_orchestrater/dev/xapp_onboarder/xapp_onboarder/xapp-onboarder-api.yaml
new file mode 100644 (file)
index 0000000..71d599d
--- /dev/null
@@ -0,0 +1,329 @@
+# ==================================================================================
+#       Copyright (c) 2020 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#          http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+# ==================================================================================
+openapi: 3.0.1
+info:
+  title: RIC xApp onboarder API
+  description: APIs to manage the xApp helm charts
+  version: "1.0"
+servers:
+- url: /api/v1
+tags:
+- name: onboard
+  description: onboard xApps
+- name: health
+  description: health check
+- name: charts
+  description: Managing helm charts
+paths:
+  /charts:
+    get:
+      tags:
+      - charts
+      summary: Returns the list of xApp helm charts that have been onboarded
+      operationId: get_charts_list
+      responses:
+        200:
+          description: Get helm chart list OK
+          content:
+            application/json:
+              schema:
+                type: object
+        500:
+          description: Get helm chart list failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+
+  /charts/xapp/{xapp_chart_name}:
+    get:
+      tags:
+      - charts
+      summary: Returns the helm chart for the specified xApp
+      operationId: get_version_list
+      parameters:
+      - name: xapp_chart_name
+        in: path
+        required: true
+        schema:
+          type: string
+      responses:
+        200:
+          description: Get helm chart OK
+          content:
+            application/json:
+              schema:
+                type: object
+        500:
+          description: Get helm chart failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+
+  /charts/xapp/{xapp_chart_name}/ver/{version}:
+    get:
+      tags:
+      - charts
+      summary: Returns the helm chart for the specified xApp and version
+      operationId: get_charts_fetcher
+      parameters:
+      - name: xapp_chart_name
+        in: path
+        required: true
+        schema:
+          type: string
+      - name: version
+        in: path
+        required: true
+        schema:
+          type: string
+      responses:
+        200:
+          description: Get helm chart package OK
+          content:
+            application/json:
+              schema:
+                type: object
+        500:
+          description: Get helm chart package failed
+          content:
+            application/gzip:
+              schema:
+                $ref: '#/components/schemas/error_message'
+
+  /charts/xapp/{xapp_chart_name}/ver/{version}/values.yaml:
+    get:
+      tags:
+      - charts
+      summary: Returns the helm values
+      description: yaml file of the specified xApp and version.
+      operationId: get_values_yaml_fetcher
+      parameters:
+      - name: xapp_chart_name
+        in: path
+        required: true
+        schema:
+          type: string
+      - name: version
+        in: path
+        required: true
+        schema:
+          type: string
+      responses:
+        200:
+          description: Get helm chart values.yaml OK
+          content:
+            application/json:
+              schema:
+                type: object
+        500:
+          description: Get helm chart values.yaml failed
+          content:
+            text/x-yaml:
+              schema:
+                $ref: '#/components/schemas/error_message'
+
+  /health:
+    get:
+      tags:
+      - health
+      summary: Returns the health condition of the xApp onboarder
+      operationId: get_health_check
+      responses:
+        200:
+          description: Health check OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/status'
+        500:
+          description: xApp onboarder is not ready
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+
+  /onboard:
+    post:
+      tags:
+      - onboard
+      summary: Onboard xApp using the xApp descriptor and schema in the request body
+      operationId: post_onboardx_apps
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/descriptor'
+        required: true
+      responses:
+        201:
+          description: xApp onboard successfully.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/status'
+        400:
+          description: xApp descriptor format error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+        500:
+          description: xApp onboarder is not ready
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+      x-codegen-request-body-name: payload
+
+  /onboard/download:
+    post:
+      tags:
+      - onboard
+      summary: Onboard xApp after downloading the xApp descriptor and schema from
+        the URLs
+      operationId: post_onboardx_apps_download
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/descriptor_remote'
+        required: true
+      responses:
+        201:
+          description: xApp onboard successfully.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/status'
+        400:
+          description: xApp descriptor format error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+        500:
+          description: xApp onboarder is not ready
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_message'
+      x-codegen-request-body-name: payload
+
+components:
+  schemas:
+    descriptor:
+      required:
+      - config-file.json
+      type: object
+      properties:
+        config-file.json:
+          $ref: '#/components/schemas/config'
+        controls-schema.json:
+          type: object
+          properties: {}
+          description: Controls schema file body
+    config:
+      required:
+      - version
+      - name
+      - containers
+      type: object
+      properties:
+        name:
+          type: string
+          description: Name of the xApp chart
+        version:
+          pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
+          type: string
+          description: Version of the xApp chart
+        containers:
+          type: object
+          properties: {}
+          description: list of containers that the xApp will run
+        controls:
+          type: object
+          properties: {}
+          description: internal configuration of the xApp
+        metrics:
+          type: object
+          properties: {}
+          description: metrics provided by the xApp
+        messaging:
+          type: object
+          properties: {}
+          description: communication ports for each containers
+        livenessProbe:
+          type: object
+          properties: {}
+          description: liveness probe
+        readinessProbe:
+          type: object
+          properties: {}
+          description: readiness probe
+        rmr:
+          type: object
+          properties: {}
+          description: rmr info          
+    error_message:
+      required:
+      - error_message
+      - error_source
+      - status
+      type: object
+      properties:
+        error_source:
+          type: string
+          description: source of the error
+        error_message:
+          type: string
+          description: source of the error
+        status:
+          type: string
+          description: http response message
+    status:
+      required:
+      - status
+      type: object
+      properties:
+        status:
+          type: string
+          description: status of the service
+    descriptor_remote:
+      required:
+      - config-file.json_url
+      type: object
+      properties:
+        config-file.json_url:
+          type: string
+          description: URL to download the config-file.json file
+        controls-schema.json_url:
+          type: string
+          description: URL to download the controls schema.json file
+  responses:
+    MaskError:
+      description: When any error occurs on mask
+      content:
+        application/json:
+          schema:
+            type: object
+    ParseError:
+      description: When a mask can't be parsed
+      content:
+        application/json:
+          schema:
+            type: object
diff --git a/xapp_orchestrater/xapp_orchestrater.tgz b/xapp_orchestrater/xapp_orchestrater.tgz
deleted file mode 100644 (file)
index 40d2c9a..0000000
Binary files a/xapp_orchestrater/xapp_orchestrater.tgz and /dev/null differ