Fix/add use cases under SMO package 84/9384/7
authorxuegao <xue.gao@intl.att.com>
Mon, 24 Oct 2022 09:13:31 +0000 (11:13 +0200)
committerxuegao <xue.gao@intl.att.com>
Thu, 17 Nov 2022 07:51:07 +0000 (08:51 +0100)
Fix K8s use case and add Network Slicing use case under SMO package.

Issue-ID: INT-147
Signed-off-by: xuegao <xue.gao@intl.att.com>
Change-Id: I81fc33fe9e7f92a8962a1e5c0b2eff39f6d142b9
Signed-off-by: xuegao <xue.gao@intl.att.com>
60 files changed:
smo-install/helm-override/network-slicing/onap-override.yaml [new file with mode: 0644]
smo-install/helm-override/pythonsdk-tests/onap-override.yaml
smo-install/onap_oom
smo-install/oran_oom/Makefile
smo-install/scripts/layer-0/0-setup-helm3.sh
smo-install/scripts/sub-scripts/install-onap.sh
smo-install/test/pythonsdk/src/oransdk/aai/__init__.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/aai/aai.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/aai/service_design_and_creation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/aai/templates/aai_model_create.json.j2 [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/msb/__init__.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/msb/msb_microservice.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/oof/__init__.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/oof/oof.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/policy/templates/commission_k8s.json.j2
smo-install/test/pythonsdk/src/oransdk/policy/templates/create_instance_k8s.json.j2
smo-install/test/pythonsdk/src/oransdk/sdc/__init__.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/category_management.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/sdc.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/service.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/templates/component_declare_input.json.j2 [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_cs_properties_input.json.j2 [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_service_profile_input.json.j2 [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_slice_profile_input.json.j2 [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/so/__init__.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/so/so.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/utils/healthcheck.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/oransdk/utils/jinja.py
smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/aai_preparation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/msb_preparation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/oof_preparation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/sdc_preparation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/so_preparation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/uui_preparation.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/resources/eMBB.zip [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/resources/policies_option2.tar.gz [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/resources/subnetCapability.json [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/network_slicing/test_network_slicing.py [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/oran_tests/conftest.py [moved from smo-install/test/pythonsdk/src/orantests/conftest.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-1.0.0.tgz [new file with mode: 0755]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-ics-version-1.0.0.tgz [new file with mode: 0755]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/oru-app-1.0.0.tgz [new file with mode: 0644]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/faults-config/event-settings-du.json [moved from smo-install/test/pythonsdk/src/orantests/resources/faults-config/event-settings-du.json with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/faults-config/event-settings-ru.json [moved from smo-install/test/pythonsdk/src/orantests/resources/faults-config/event-settings-ru.json with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/network-simulators-topology/network-simulators-override.yaml [moved from smo-install/test/pythonsdk/src/orantests/resources/network-simulators-topology/network-simulators-override.yaml with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/resources/network-simulators-topology/network-simulators-topology-override.yaml [moved from smo-install/test/pythonsdk/src/orantests/resources/network-simulators-topology/network-simulators-topology-override.yaml with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/__init__.py [moved from smo-install/test/pythonsdk/src/orantests/smo/__init__.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/cl_usecase.py [moved from smo-install/test/pythonsdk/src/orantests/smo/cl_usecase.py with 97% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/dmaap.py [moved from smo-install/test/pythonsdk/src/orantests/smo/dmaap.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/network_simulators.py [moved from smo-install/test/pythonsdk/src/orantests/smo/network_simulators.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/nonrtric.py [moved from smo-install/test/pythonsdk/src/orantests/smo/nonrtric.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/onap.py [moved from smo-install/test/pythonsdk/src/orantests/smo/onap.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/smo/smo.py [moved from smo-install/test/pythonsdk/src/orantests/smo/smo.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/test_a1sim.py [moved from smo-install/test/pythonsdk/src/orantests/test_a1sim.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/test_apex_policy.py [moved from smo-install/test/pythonsdk/src/orantests/test_apex_policy.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/test_cl_apex.py [moved from smo-install/test/pythonsdk/src/orantests/test_cl_apex.py with 100% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/test_cl_k8s.py [moved from smo-install/test/pythonsdk/src/orantests/test_cl_k8s.py with 82% similarity]
smo-install/test/pythonsdk/src/orantests/oran_tests/test_o1.py [moved from smo-install/test/pythonsdk/src/orantests/test_o1.py with 100% similarity]
smo-install/test/pythonsdk/tox.ini
smo-install/tests_oom/Makefile

diff --git a/smo-install/helm-override/network-slicing/onap-override.yaml b/smo-install/helm-override/network-slicing/onap-override.yaml
new file mode 100644 (file)
index 0000000..d5ce917
--- /dev/null
@@ -0,0 +1,401 @@
+# Copyright © 2017 Amdocs, Bell Canada
+#
+# Modifications Copyright © 2021 AT&T
+#
+# 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.
+
+#################################################################
+# Global configuration overrides.
+#
+# These overrides will affect all helm charts (ie. applications)
+# that are listed below and are 'enabled'.
+#################################################################
+global:
+  # Change to an unused port prefix range to prevent port conflicts
+  # with other instances running within the same k8s cluster
+  repository: nexus3.onap.org:10001 #__docker_proxy__
+  nodePortPrefix: 302
+  nodePortPrefixExt: 304
+  masterPassword: secretpassword
+  addTestingComponents: true
+  cmpv2Enabled: false
+  flavor: unlimited
+  # ONAP Repository
+  # Uncomment the following to enable the use of a single docker
+  # repository but ONLY if your repository mirrors all ONAP
+  # docker images. This includes all images from dockerhub and
+  # any other repository that hosts images for ONAP components.
+  #repository: nexus3.onap.org:10001
+
+  # readiness check - temporary repo until images migrated to nexus3
+  readinessRepository: oomk8s
+  # logging agent - temporary repo until images migrated to nexus3
+  loggingRepository: docker.elastic.co
+
+  # image pull policy
+  pullPolicy: IfNotPresent
+
+  # override default mount path root directory
+  # referenced by persistent volumes and log files
+  persistence:
+    mountPath: /dockerdata-nfs
+
+  # flag to enable debugging - application support required
+  debugEnabled: false
+
+#################################################################
+# Enable/disable and configure helm charts (ie. applications)
+# to customize the ONAP deployment.
+#################################################################
+a1policymanagement:
+  enabled: false
+  rics:
+    - name: ric1
+      link: http://a1-sim-osc-0.nonrtric:8085
+      controller: controller1
+      managedElementIds:
+        - kista_1
+        - kista_2
+    - name: ric2
+      link: http://a1-sim-osc-1.nonrtric:8085
+      controller: controller1
+      managedElementIds:
+        - kista_1
+        - kista_2
+    - name: ric3
+      link: http://a1-sim-std-0.nonrtric:8085
+      controller: controller1
+      managedElementIds:
+        - kista_1
+        - kista_2
+    - name: ric4
+      link: http://a1-sim-std-1.nonrtric:8085
+      controller: controller1
+      managedElementIds:
+        - kista_1
+        - kista_2
+    - name: ric5
+      link: http://a1-sim-std2-0.nonrtric:8085
+      controller: controller1
+      managedElementIds:
+        - kista_1
+        - kista_2
+    - name: ric6
+      link: http://a1-sim-std2-1.nonrtric:8085
+      controller: controller1
+      managedElementIds:
+        - kista_1
+        - kista_2
+aaf:
+  enabled: true
+  aaf-service:
+    readiness:
+      initialDelaySeconds: 150
+aai:
+  enabled: true
+  flavorOverride: unlimited
+  global:
+    flavorOverride: unlimited
+    cassandra:
+      replicas: 1
+  aai-cassandra:
+    flavorOverride: unlimited
+    replicaCount: 1
+  aai-babel:
+    flavorOverride: unlimited
+  aai-data-router:
+    flavorOverride: unlimited
+  aai-elasticsearch:
+    flavorOverride: unlimited
+  aai-graphadmin:
+    flavorOverride: unlimited
+  aai-modelloader:
+    flavorOverride: unlimited
+  aai-resources:
+    flavorOverride: unlimited
+  aai-schema-service:
+    flavorOverride: unlimited
+  aai-search-data:
+    flavorOverride: unlimited
+  aai-sparky-be:
+    flavorOverride: unlimited
+    readiness:
+      initialDelaySeconds: 150
+      periodSeconds: 20
+      timeoutSeconds: 10
+  aai-traversal:
+    flavorOverride: unlimited
+appc:
+  enabled: false
+cassandra:
+  enabled: true
+  replicaCount: 1
+  config:
+    cluster_domain: cluster.local
+    heap:
+      max: 1G
+      min: 256M
+  liveness:
+    initialDelaySeconds: 60
+    periodSeconds: 20
+    timeoutSeconds: 10
+    successThreshold: 1
+    failureThreshold: 3
+    # necessary to disable liveness probe when setting breakpoints
+    # in debugger so K8s doesn't restart unresponsive container
+    enabled: true
+
+  readiness:
+    initialDelaySeconds: 120
+    periodSeconds: 20
+    timeoutSeconds: 10
+    successThreshold: 1
+    failureThreshold: 3
+cds:
+  enabled: false
+cli:
+  enabled: false
+contrib:
+  enabled: true
+  awx:
+    enabled: false
+  netbox:
+    enabled: false
+consul:
+  enabled: false
+  consul-server:
+    replicaCount: 1
+cps:
+  enabled: false
+dcaegen2:
+  enabled: false
+  dcae-bootstrap:
+    enabled: false
+  dcae-cloudify-manager:
+    enabled: false
+  dcae-config-binding-service:
+    enabled: false
+  dcae-dashboard:
+    enabled: false
+  dcae-deployment-handler:
+    enabled: false
+  dcae-healthcheck:
+    enabled: false
+  dcae-inventory-api:
+    enabled: false
+  dcae-policy-handler:
+    enabled: false
+  dcae-servicechange-handler:
+    enabled: false
+  dcae-ves-openapi-manager:
+    enabled: false
+dcaegen2-services:
+  enabled: true
+  dcae-bbs-eventprocessor-ms:
+    enabled: false
+  dcae-datafile-collector:
+    enabled: true
+  dcae-datalake-admin-ui:
+    enabled: false
+  dcae-datalake-des:
+    enabled: true
+  dcae-datalake-feeder:
+    enabled: true
+  dcae-heartbeat:
+    enabled: false
+  dcae-hv-ves-collector:
+    enabled: false
+  dcae-kpi-ms:
+    enabled: false
+  dcae-ms-healthcheck:
+    enabled: false
+  dcae-pm-mapper:
+    enabled: true
+  dcae-pmsh:
+    enabled: false
+  dcae-prh:
+    enabled: false
+  dcae-restconf-collector:
+    enabled: false
+  dcae-slice-analysis-ms:
+    enabled: true
+  dcae-snmptrap-collector:
+    enabled: false
+  dcae-son-handler:
+    enabled: false
+  dcae-tcagen2:
+    enabled: false
+  dcae-ves-collector:
+    enabled: true
+  dcae-ves-mapper:
+    enabled: false
+  dcae-ves-openapi-manager:
+    enabled: false
+
+dcaemod:
+  enabled: false
+holmes:
+  enabled: false
+dmaap:
+  enabled: true
+
+esr:
+  enabled: true
+log:
+  enabled: false
+  log-logstash:
+    replicaCount: 1
+mariadb-galera:
+  enabled: true
+  replicaCount: 1
+modeling:
+  enabled: false
+msb:
+  enabled: true
+multicloud:
+  enabled: true
+nbi:
+  enabled: false
+oof:
+  enabled: true
+platform:
+  enabled: false
+policy:
+  enabled: true
+  policy-api:
+    enabled: true
+  policy-pap:
+    enabled: true
+  policy-xacml-pdp:
+    enabled: true
+  policy-apex-pdp:
+    enabled: true
+  policy-drools-pdp:
+    enabled: false
+  policy-distribution:
+    enabled: false
+  policy-clamp-be:
+    enabled: true
+  policy-clamp-runtime-acm:
+    enabled: true
+  policy-clamp-ac-k8s-ppnt:
+    enabled: true
+  policy-gui:
+    enabled: false
+    image: onap/policy-gui:2.2.1
+  policy-nexus:
+    enabled: false
+  policy-clamp-ac-pf-ppnt:
+    enabled: true
+  policy-clamp-ac-http-ppnt:
+    enabled: true
+
+pomba:
+  enabled: false
+portal:
+  enabled: false
+robot:
+  enabled: false
+sdc:
+  enabled: true
+  sdc-be:
+    config:
+      javaOptions: "-Xmx1g -Xms512m"
+    liveness:
+      periodSeconds: 300
+      timeoutSeconds: 180
+    readiness:
+      periodSeconds: 300
+      timeoutSeconds: 240
+  sdc-fe:
+    resources:
+      small:
+        limits:
+          cpu: 1
+          memory: 2Gi
+        requests:
+          cpu: 100m
+          memory: 500Mi
+  sdc-wfd:
+    enabled: false
+  global:
+    sdc_cassandra:
+      replicaCount: 1
+
+sdnc:
+  enabled: true
+  replicaCount: 1
+  elasticsearch:
+    master:
+      replicaCount: 1
+  mysql:
+    replicaCount: 1
+  ueb-listener:
+    enabled: false
+  sdnc-ansible-server:
+    enabled: true
+  dgbuilder:
+    enabled: true
+  cds:
+    enabled: false
+  sdnc-web:
+    config:
+      topologyserver:
+        enabled: true
+        topologyserverUrl: http://topology.nonrtric:3001
+  config:
+    sdnr:
+      enabled: true
+      # mode: web - SDNC contains device manager only plus dedicated webserver service for ODLUX (default),
+      # mode: dm - SDNC contains sdnr device manager + ODLUX components
+      mode: dm
+      # sdnronly: true starts sdnc container with odl and sdnrwt features only
+      sdnronly: false
+      sdnrdbTrustAllCerts: true
+      mountpointRegistrarEnabled: true
+      mountpointStateProviderEnabled: true
+      netconfCallHome:
+        enabled: true
+      vesCollector:
+        enabled: true
+        tls:
+          enabled: true
+        trustAllCertificates: true
+        username: sample1
+        password: sample1
+        address: dcae-ves-collector.onap
+        port: 8443
+        eventLogMsgDetail: LONG
+sniro-emulator:
+  enabled: false
+
+strimzi:
+  enabled: true
+
+so:
+  enabled: true
+  so-catalog-db-adapter:
+    config:
+      openStackUserName: "the username"
+      openStackKeyStoneUrl: "http://10.12.25.2:5000/v3"
+      openStackEncryptedPasswordHere: "1DD1B3B4477FBAFAFEA617C575639C6F09E95446B5AE1F46C72B8FD960219ABB0DBA997790FCBB12"
+      openStackKeystoneVersion: "KEYSTONE_V3"
+uui:
+  enabled: true
+vfc:
+  enabled: false
+vid:
+  enabled: true
+vnfsdk:
+  enabled: false
+
index 0dc5aa3..0d3ae4a 100644 (file)
@@ -294,7 +294,8 @@ policy:
     repoList:
       helm:
         repos:
-          - repoName: chartmuseum
+          -
+            repoName: chartmuseum
             address: http://test-chartmuseum.test:8080
         protocols:
           - http
@@ -350,6 +351,11 @@ sdnc:
     enabled: true
   cds:
     enabled: false
+  sdnc-web:
+    config:
+      topologyserver:
+        enabled: true
+        topologyserverUrl: http://topology.nonrtric:3001
   config:
     sdnr:
       enabled: true
index 859b18d..7e4cced 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 859b18d1e92c4fe88681e91b0d549ea3118c5094
+Subproject commit 7e4cced6c92ffdbc480eb843592b0e500b350721
index 617cbe8..4db61f6 100644 (file)
@@ -28,7 +28,7 @@ ifneq "$(findstring v3,$(HELM_VER))" "v3"
        HELM_VER := $(shell $(HELM_BIN) version -c --template "{{.Client.SemVer}}")
 endif
 
-# use this if you would like to push onap charts to repo with other name
+# use this if you would like to cm-push onap charts to repo with other name
 # WARNING: Helm v3+ only
 # WARNING: Make sure to edit also requirements files
 HELM_REPO := local
@@ -82,7 +82,7 @@ lint-%: dep-%
 package-%: lint-%
        @mkdir -p $(PACKAGE_DIR)
 ifeq "$(findstring v3,$(HELM_VER))" "v3"
-       @if [ -f $*/Chart.yaml ]; then PACKAGE_NAME=$$($(HELM_BIN) package -d $(PACKAGE_DIR) $* | cut -d":" -f2) && $(HELM_BIN) push -f $$PACKAGE_NAME $(HELM_REPO); fi
+       @if [ -f $*/Chart.yaml ]; then PACKAGE_NAME=$$($(HELM_BIN) package -d $(PACKAGE_DIR) $* | cut -d":" -f2) && $(HELM_BIN) cm-push -f $$PACKAGE_NAME $(HELM_REPO); fi
 else
        @if [ -f $*/Chart.yaml ]; then $(HELM_BIN) package -d $(PACKAGE_DIR) $*; fi
        @$(HELM_BIN) repo index $(PACKAGE_DIR)
index b8b8508..684a3a3 100755 (executable)
@@ -33,13 +33,13 @@ sudo apt-get install git -y
 echo "Checking HELM ..."
 helm version
 
-TAR_VERSION=0.9.0
-echo "Downloading and installing helm-push v${TAR_VERSION} ..."
-TAR_FILE=helm-push_${TAR_VERSION}_linux_amd64.tar.gz
+TAR_VERSION=v0.10.3
+echo "Downloading and installing helm-push ${TAR_VERSION} ..."
+TAR_FILE=helm-push-${TAR_VERSION}.tar.gz
 HELM_PLUGINS=$(helm env HELM_PLUGINS)
 mkdir -p $HELM_PLUGINS/helm-push
 cd $HELM_PLUGINS/helm-push
-wget https://nexus.o-ran-sc.org/service/local/repositories/images/content/$TAR_FILE
+wget https://nexus.o-ran-sc.org/content/repositories/thirdparty/chartmuseum/helm-push/$TAR_VERSION/$TAR_FILE
 tar zxvf $TAR_FILE >/dev/null
 rm $TAR_FILE
 cd /tmp/
index 90febe3..c415c5a 100755 (executable)
@@ -27,7 +27,7 @@ SCRIPT=$(readlink -f "$0")
 SCRIPT_PATH=$(dirname "$SCRIPT")
 cd $SCRIPT_PATH
 
-helm push ../packages/strimzi-kafka-operator-helm-3-chart-0.28.0.tgz local
+helm cm-push ../packages/strimzi-kafka-operator-helm-3-chart-0.28.0.tgz local
 helm repo update
 helm install strimzi-kafka-operator local/strimzi-kafka-operator --namespace strimzi-system --version 0.28.0 --set watchAnyNamespace=true --create-namespace
 
diff --git a/smo-install/test/pythonsdk/src/oransdk/aai/__init__.py b/smo-install/test/pythonsdk/src/oransdk/aai/__init__.py
new file mode 100644 (file)
index 0000000..4fb5f70
--- /dev/null
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""ONAP AAI package."""
diff --git a/smo-install/test/pythonsdk/src/oransdk/aai/aai.py b/smo-install/test/pythonsdk/src/oransdk/aai/aai.py
new file mode 100644 (file)
index 0000000..2b66536
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Onap AAI module."""
+from onapsdk.aai.aai_element import AaiElement
+from onapsdk.configuration import settings
+
+class Aai(AaiElement):
+    """AAI healthcheck class."""
+
+    def healthcheck(self) -> str:
+        """AAI Model healthcheck.
+
+        Returns:
+           result of the health check
+        """
+        res = self.send_message_json("GET", "A&AI healthcheck", f"{self.url}/echo?action=long")
+        return res
+
+    @property
+    def url(self) -> str:
+        """Define the base url.
+
+        Returns:
+            the base url of the class
+
+        """
+        return f"{settings.AAI_URL}/aai/util"
diff --git a/smo-install/test/pythonsdk/src/oransdk/aai/service_design_and_creation.py b/smo-install/test/pythonsdk/src/oransdk/aai/service_design_and_creation.py
new file mode 100644 (file)
index 0000000..3a7655f
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Onap AAI model module."""
+from onapsdk.aai.service_design_and_creation import Model
+from oransdk.utils.jinja import jinja_env
+
+class AaiModel(Model):
+    """Model resource class."""
+
+    def create(self,
+               model_name: str,
+               model_version_id: str,
+               invariant_id: str) -> None:
+        """Create Model.
+
+        Args:
+            model_name (str): model name
+            model_version_id (str): model version id
+
+        """
+        self.send_message(
+            "PUT",
+            "Create A&AI service",
+            f"{self.base_url}{self.api_version}/service-design-and-creation/"
+            f"models/model/{invariant_id}",
+            data=jinja_env().get_template("aai_model_create.json.j2")
+            .render(
+                model_version=self.resource_version,
+                model_name=model_name,
+                version_id=model_version_id,
+                model_invariant_id=invariant_id
+            )
+        )
diff --git a/smo-install/test/pythonsdk/src/oransdk/aai/templates/aai_model_create.json.j2 b/smo-install/test/pythonsdk/src/oransdk/aai/templates/aai_model_create.json.j2
new file mode 100644 (file)
index 0000000..b15c1b8
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "model-vers": {
+    "model-ver": [
+      {
+        "model-version": "{{ model_version }}",
+        "model-name": "{{ model_name }}",
+        "model-version-id": "{{ version_id }}"
+      }]
+  },
+  "model-type": "resource",
+  "model-invariant-id": "{{ model_invariant_id }}"
+}
\ No newline at end of file
diff --git a/smo-install/test/pythonsdk/src/oransdk/msb/__init__.py b/smo-install/test/pythonsdk/src/oransdk/msb/__init__.py
new file mode 100644 (file)
index 0000000..9fb7183
--- /dev/null
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""ONAP MSB package."""
diff --git a/smo-install/test/pythonsdk/src/oransdk/msb/msb_microservice.py b/smo-install/test/pythonsdk/src/oransdk/msb/msb_microservice.py
new file mode 100644 (file)
index 0000000..28004fc
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Onap MSB module."""
+from onapsdk.configuration import settings
+from onapsdk.onap_service import OnapService
+from onapsdk.utils.headers_creator import headers_msb_creator
+
+class OranMsb(OnapService):
+    """MSB class."""
+
+    base_url = f"{settings.MSB_URL}/api/msdiscover/v1/services"
+    headers = headers_msb_creator(OnapService.headers)
+
+    def get_services(self) -> dict:
+        """
+        Get MSB instance services.
+
+        Returns:
+           the list of instance services
+
+        """
+        status = self.send_message_json('GET',
+                                        'Get status of MSB',
+                                        self.base_url,
+                                        headers=self.headers)
+        return status
+
+    def create_service(self, service_data) -> None:
+        """
+        Create an instance service.
+
+        Args:
+           service_data: the service to be created
+
+        """
+        self.send_message('POST', 'Create Instance Service', self.base_url, data=service_data, headers=self.headers)
+
+    def delete_service(self, service_name, version) -> None:
+        """
+        Delete an instance service.
+
+        Args:
+           service_name: the service to be deleted
+
+        """
+        url = f"{self.base_url}/{service_name}/version/{version}?namespace="
+        self.send_message('DELETE', 'Delete Instance Service', url, headers=self.headers)
diff --git a/smo-install/test/pythonsdk/src/oransdk/oof/__init__.py b/smo-install/test/pythonsdk/src/oransdk/oof/__init__.py
new file mode 100644 (file)
index 0000000..0d54734
--- /dev/null
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""ONAP OOF package."""
diff --git a/smo-install/test/pythonsdk/src/oransdk/oof/oof.py b/smo-install/test/pythonsdk/src/oransdk/oof/oof.py
new file mode 100644 (file)
index 0000000..f4b01a5
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Onap OOF module."""
+from onapsdk.configuration import settings
+from onapsdk.onap_service import OnapService
+
+class Oof(OnapService):
+    """OOF class."""
+
+    def get_versions(self) -> dict:
+        """
+        Get OOF HAS API supported versions.
+
+        Returns:
+           the list of supported versions
+
+        """
+        response = self.send_message_json('GET', 'Get OOF supported version', settings.OOF_URL)
+        return response
index 145ec78..80e78b4 100644 (file)
             "name": "K8sParticipant0"
           },
           "provider": "ONAP",
+          "uninitializedToPassiveTimeout": 300,
           "chart": {
             "repository": {
               "address": "{{chartmuseumIp}}",
-              "repoName": "chartmuseum",
-              "port": {{chartmuseumPort}},
-              "protocol": "http"
+              "repoName": "chartmuseum"
             },
             "namespace": "nonrtric",
             "chartId": {
           "metadata": {
             "common": true
           },
-          "default": 60,
+          "default": 300,
           "constraints": [
             {
               "greater_or_equal": 0
           "metadata": {
             "common": true
           },
-          "default": 60,
+          "default": 300,
           "constraints": [
             {
               "greater_or_equal": 0
index 33cb42c..e1d213f 100644 (file)
@@ -74,7 +74,8 @@
             "name": "K8sParticipant0"
           },
           "provider": "ONAP",
-          "chart": "{\"chartId\":{\"name\":\"{{chartName}}\",\"version\":\"{{chartVersion}}\"},\"namespace\":\"nonrtric\",\"releaseName\":\"{{releaseName}}\",\"repository\":{\"repoName\":\"chartmuseum\",\"address\":\"{{chartmuseumIp}}\",\"protocol\":\"http\",\"port\":{{chartmuseumPort}}}}"
+          "uninitializedToPassiveTimeout": 300,
+          "chart": "{\"chartId\":{\"name\":\"{{chartName}}\",\"version\":\"{{chartVersion}}\"},\"namespace\":\"nonrtric\",\"releaseName\":\"{{releaseName}}\",\"repository\":{\"repoName\":\"chartmuseum\",\"address\":\"{{chartmuseumIp}}\"}}}"
         },
         "metadata": {},
         "description": "Automation composition element for the K8S microservice for PMSH",
           "key_schema": null,
           "type": "integer",
           "name": "passiveToUninitializedTimeout",
-          "default_value": 60
+          "default_value": 300
         },
         "uninitializedToPassiveTimeout": {
           "required": false,
           "key_schema": null,
           "type": "integer",
           "name": "uninitializedToPassiveTimeout",
-          "default_value": 60
+          "default_value": 300
         },
         "participant_id": {
           "required": false,
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/__init__.py b/smo-install/test/pythonsdk/src/oransdk/sdc/__init__.py
new file mode 100644 (file)
index 0000000..7b35d18
--- /dev/null
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""ONAP SDC package."""
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/category_management.py b/smo-install/test/pythonsdk/src/oransdk/sdc/category_management.py
new file mode 100644 (file)
index 0000000..aee9f3c
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Onap SDC Category Management module."""
+import json
+from onapsdk.sdc.category_management import ServiceCategory
+
+class OranServiceCategory(ServiceCategory):
+    """Onap SDC Category Management module ."""
+
+    @classmethod
+    def create(cls, name: str) -> "BaseCategory":
+        """Create category instance.
+
+        Checks if category with given name exists and if it already
+            exists just returns category with given name.
+
+        Returns:
+            BaseCategory: Created category instance
+
+        """
+        category_obj: "BaseCategory" = cls(name)
+        if category_obj.exists():
+            return category_obj
+        cls.send_message_json("POST",
+                              f"Create {name} {cls.category_name()}",
+                              cls._base_create_url(),
+                              data=json.dumps({"name": name, "models": ["SDC AID"], "metadataKeys": []}),
+                              headers=cls.headers())
+        category_obj.exists()
+        return category_obj
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/sdc.py b/smo-install/test/pythonsdk/src/oransdk/sdc/sdc.py
new file mode 100644 (file)
index 0000000..a2ae1f5
--- /dev/null
@@ -0,0 +1,306 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2021 Samsung Electronics
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Onap Sdc module."""
+from time import sleep
+import onapsdk.constants as const
+from onapsdk.configuration import settings
+from onapsdk.exceptions import APIError, ResourceNotFound
+from onapsdk.onap_service import OnapService as Onap
+from onapsdk.sdc.properties import Input, NestedInput, ParameterError
+
+from onapsdk.sdc.vf import Vf
+from onapsdk.sdc.vsp import Vsp
+from onapsdk.sdc.vfc import Vfc
+from onapsdk.sdc.vendor import Vendor
+from oransdk.sdc.category_management import OranServiceCategory
+from oransdk.sdc.service import OranService
+
+class SdcTemplate(Onap):
+    """Onap Sdc Template class."""
+
+    def healthcheck(self) -> dict:
+        """Healchcheck SDC components.
+
+        Returns:
+            status of SDC components
+        """
+        status = self.send_message_json("GET",
+                                        "SDC Healchcheck",
+                                        f"{settings.SDC_FE_URL}/sdc1/feProxy/rest/healthCheck")
+
+        return status
+
+    def create_service_category(self, category_names) -> None:
+        """Create service category by names.
+
+        Args:
+            category_names : The list of category names
+        """
+        for cn in category_names:
+            self._logger.info('creating service category [%s]', cn)
+            OranServiceCategory.create(name=cn)
+
+
+    def create_vendor(self, vendor_name) -> dict:
+        """Create Vendor by names.
+
+        Args:
+            vendor_name : The vendor names
+        Returns:
+            the vendor
+        """
+        vendor = Vendor(vendor_name)
+        vendor.create()
+        try:
+            vendor.onboard()
+        except APIError as e:
+            self._logger.error("Exception during vendor onboarding: %s", e)
+            raise e
+        return vendor
+
+    def create_vsp(self, name, vendor, onboard=False) -> dict:
+        """Create vsp.
+
+        Args:
+            name : The vsp name
+            vendor : The vendor name
+            onboard : The onboard flag
+        Returns:
+            the vsp
+        """
+        self._logger.info("creating vsp: [%s:%s]", name, vendor)
+        retry = 0
+        done = False
+
+        vsp = Vsp(name=name, vendor=vendor)
+        if onboard:
+            while not done:
+                try:
+                    vsp.create()
+                    vsp.onboard()
+                except ResourceNotFound as e:
+                    self._logger.error("Failed to onboard %s : %s", name, e)
+                    retry = retry + 1
+                    if retry >= 5:
+                        raise e
+                except APIError as e:
+                    self._logger.error("Exception during vsp onboarding: %s", e)
+                    raise e
+                else:
+                    done = True
+        return vsp
+
+
+    def create_vf(self, name, category, subcategory, vendor, onboard=False) -> dict:
+        """Create vf.
+
+        Args:
+            name : The vf name
+            category :  The category name
+            subcategory : The subcategory name
+            vendor : The vendor name
+            onboard : The onboard flag
+        Returns:
+            the vf
+        """
+        self._logger.error("create vf: [%s:%s]", name, category)
+
+        vfc = Vfc('AllottedResource')  # seemd incorrect
+        vf = Vf(name=name, category=category, subcategory=subcategory, vendor=vendor)
+        self._logger.error("create vf 2: ")
+        vf.create()
+        if vf.status == const.DRAFT:
+            vf.add_resource(vfc)
+            self._logger.error("create vf 3:")
+            if onboard:
+                self.onboard_vf(vf)
+        return vf
+
+
+    def onboard_vf(self, vf) -> None:
+        """Onboard the vf.
+
+        Args:
+            vf : The vf to onboard
+        """
+        retry = 0
+        done = False
+        to = 2
+
+        while not done:
+            try:
+                vf.onboard()
+            except ResourceNotFound as e:
+                retry += 1
+                if retry > 5:
+                    raise e
+                sleep(to)
+                to = 2 * to + 1
+            else:
+                done = True
+        self._logger.info("onboarded vf: [%s]", vf.name)
+
+
+    def create_service(self, name, category, vnfs=None, properties=None, inputs=None, role=None, service_type=None) -> dict:
+        """Create service.
+
+        Args:
+             name : The service name
+             category :  The category name
+             vnfs : The list of vnfs
+             properties : the list of properties
+             role : the role value
+             service_type : the service type
+        Returns:
+             the created service
+        """
+        self._logger.info("create service: [%s:%s]", name, category)
+        retry = 0
+        done = False
+
+        if vnfs is None:
+            vnfs = []
+        if properties is None:
+            properties = []
+
+        srvc = OranService(name=name, category=category, properties=properties, inputs=inputs, role=role, service_type=service_type)
+        srvc.create()
+
+        while not done:
+            try:
+                if srvc.status == const.DRAFT:
+                    for vnf in vnfs:
+                        srvc.add_resource(vnf)
+
+                if srvc.status != const.DISTRIBUTED:
+                    srvc.onboard()
+            except ResourceNotFound as e:
+                retry += 1
+                if retry > 5:
+                    raise e
+            else:
+                done = True
+
+        return srvc
+
+    def create_service_1(self, name, category, vnfs=None, properties=None, inputs=None, complex_input=None, role=None, service_type=None) -> dict:
+        """Create slicing profile service.
+
+        Args:
+             name : The service name
+             category :  The category name
+             vnfs : The list of vnfs
+             properties : the list of properties
+             inputs : the list of inputs
+             complex_input : the predefined property type, that should be declared as input
+             role : the role value
+             service_type : the service type
+        Returns:
+             the created service
+        """
+        self._logger.info("create service: [%s:%s]", name, category)
+        retry = 0
+        done = False
+
+        if vnfs is None:
+            vnfs = []
+        if properties is None:
+            properties = []
+
+        srvc = OranService(name=name, category=category, inputs=inputs, complex_input=complex_input, properties=properties, role=role, service_type=service_type)
+        srvc.create()
+
+        while not done:
+            try:
+                if srvc.status == const.DRAFT:
+                    for vnf in vnfs:
+                        srvc.add_resource(vnf)
+                        for c in srvc.components:
+                            self.set_property_input_slice_ar(vnf, srvc, c)
+
+                if srvc.status != const.DISTRIBUTED:
+                    srvc.onboard()
+            except ResourceNotFound as e:
+                retry += 1
+                if retry > 5:
+                    raise e
+            else:
+                done = True
+
+        return srvc
+
+    def set_property_input_slice_ar(self, vnf, service, component) -> None:
+        """Get component property.
+
+        Args:
+            vnf: The vnf of the input
+            service : The service
+            component :  The component
+        """
+        self._logger.info("set property input slice ar: %s", component.name)
+        if component.name.startswith("Slice_AR"):
+            self._logger.info("get component Slice_AR 0")
+            cp = self.get_component_property(component, 'allottedresource0_providing_service_invariant_uuid')
+            if cp:
+                self._logger.info('setting value on property [%s]', cp)
+                service.declare_input(NestedInput(sdc_resource=vnf, input_obj=Input(unique_id="123",
+                                                                                    input_type=cp.property_type,
+                                                                                    name=cp.name,
+                                                                                    sdc_resource=vnf)))
+            else:
+                raise ParameterError('no property providing_service_invariant_uuid found')
+
+            cp = self.get_component_property(component, 'allottedresource0_providing_service_uuid')
+            if cp:
+                service.declare_input(NestedInput(sdc_resource=vnf, input_obj=Input(unique_id="123",
+                                                                                    input_type=cp.property_type,
+                                                                                    name=cp.name,
+                                                                                    sdc_resource=vnf)))
+            else:
+                raise ParameterError('no property providing_service_uuid found')
+
+    def get_component_property(self, component, name) -> dict:
+        """Get component property.
+
+        Args:
+             component : The component
+             name :  The property name
+        Returns:
+             the property
+        """
+        prop = None
+        try:
+            prop = list(filter(lambda x: x.name == name, component.properties))
+            if prop:
+                prop = prop[0]
+            else:
+                raise ParameterError('no property found')
+        except ParameterError as e:
+            self._logger.error("component [%s] has no property [%s]", component.name, name)
+            raise e
+
+        self._logger.error("retrived property [%s] for component [%s]", prop.name if prop else 'null', component.name)
+        return prop
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/service.py b/smo-install/test/pythonsdk/src/oransdk/sdc/service.py
new file mode 100644 (file)
index 0000000..a946e04
--- /dev/null
@@ -0,0 +1,207 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""SDC Service module."""
+
+from typing import Dict, Iterator, List, Optional, Union
+from onapsdk.exceptions import ResourceNotFound
+from onapsdk.sdc.component import Component
+from onapsdk.sdc.properties import Property, NestedInput
+from onapsdk.sdc.service import Service, ServiceInstantiationType
+from onapsdk.sdc.sdc_resource import SdcResource
+from onapsdk.utils.headers_creator import headers_sdc_creator
+from oransdk.utils.jinja import jinja_env
+
+
+class OranService(Service):  # pylint: disable=too-many-instance-attributes, too-many-public-methods
+    """ONAP Service Object used for SDC operations."""
+
+    def __init__(self, name: str = None, version: str = None, sdc_values: Dict[str, str] = None,  # pylint: disable=too-many-arguments
+                 resources: List[SdcResource] = None, properties: List[Property] = None, complex_input: Property = None,
+                 inputs: List[Union[Property, NestedInput]] = None,
+                 instantiation_type: Optional[ServiceInstantiationType] = \
+                     None,
+                 category: str = None, role: str = "", function: str = "", service_type: str = ""):
+        """
+        Initialize service object.
+
+        Args:
+            name (str, optional): the name of the service
+            version (str, optional): the version of the service
+            sdc_values (Dict[str, str], optional): dictionary of values
+                returned by SDC
+            resources (List[SdcResource], optional): list of SDC resources
+            properties (List[Property], optional): list of properties to add to service.
+                None by default.
+            inputs (List[Union[Property, NestedInput]], optional): list of inputs
+                to declare for service. It can be both Property or NestedInput object.
+                None by default.
+            instantiation_type (ServiceInstantiationType, optional): service instantiation
+                type. ServiceInstantiationType.A_LA_CARTE by default
+            category (str, optional): service category name
+            role (str, optional): service role
+            function (str, optional): service function. Empty by default
+            service_type (str, optional): service type. Empty by default
+            complex_input (List[Property], optional): internal defined property type, that needs to be declared as input.
+                None by default.
+
+        """
+        super().__init__(name=name, sdc_values=sdc_values, version=version, properties=properties,
+                         inputs=inputs, category=category, resources=resources,
+                         instantiation_type=instantiation_type, role=role, function=function, service_type=service_type)
+        self.complex_input = complex_input
+
+    @property
+    def components(self) -> Iterator[Component]:
+        """Resource components.
+
+        Iterate resource components.
+
+        Yields:
+            Component: Resource component object
+
+        """
+        for component_instance in self.send_message_json(\
+                "GET",
+                f"Get {self.name} resource inputs",
+                f"{self.resource_inputs_url}/filteredDataByParams?include=componentInstances"
+                ).get("componentInstances", []):
+            sdc_resource: "SdcResource" = None
+
+            if component_instance['originType'] == "ServiceProxy":
+                sdc_resource = SdcResource.import_from_sdc(self.send_message_json(\
+                            "GET",
+                            f"Get {self.name} component's SDC resource metadata",
+                            (f"{self.base_front_url}/sdc1/feProxy/rest/v1/catalog/services/"
+                             f"{component_instance['actualComponentUid']}/"
+                             "filteredDataByParams?include=metadata"))["metadata"])
+            else:
+                sdc_resource = SdcResource.import_from_sdc(self.send_message_json(\
+                    "GET",
+                    f"Get {self.name} component's SDC resource metadata",
+                    (f"{self.base_front_url}/sdc1/feProxy/rest/v1/catalog/resources/"
+                     f"{component_instance['actualComponentUid']}/"
+                     "filteredDataByParams?include=metadata"))["metadata"])
+
+            yield Component.create_from_api_response(api_response=component_instance,
+                                                     sdc_resource=sdc_resource,
+                                                     parent_sdc_resource=self)
+
+    def declare_complex_input(self, property_obj: Property) -> None:
+        """Declare complex input for resource's property.
+
+        For each property input can be declared.
+
+        Args:
+            property_obj (Property): Property to declare input
+
+        """
+        self._logger.debug("Declare input for Complex property")
+        if property_obj.property_type == "org.openecomp.datatypes.SliceProfile":
+            self._logger.debug("Declare input for SliceProfile")
+            self.send_message_json("POST",
+                                   f"Declare new input for {property_obj.name} property",
+                                   f"{self.resource_inputs_url}/create/inputs",
+                                   data=jinja_env().get_template(\
+                                   "sdc_add_slice_profile_input.json.j2").\
+                                       render(\
+                                           sdc_resource=self,
+                                           property=property_obj))
+        elif property_obj.property_type == "org.openecomp.datatypes.ServiceProfile":
+            self._logger.debug("Declare input for ServiceProfile")
+            self.send_message_json("POST",
+                                   f"Declare new input for {property_obj.name} property",
+                                   f"{self.resource_inputs_url}/create/inputs",
+                                   data=jinja_env().get_template(\
+                                       "sdc_add_service_profile_input.json.j2").\
+                                           render(\
+                                               sdc_resource=self,
+                                               property=property_obj))
+        elif property_obj.property_type == "org.openecomp.datatypes.CSProperties":
+            self._logger.debug("Declare input for CSProperties")
+            self.send_message_json("POST",
+                                   f"Declare new input for {property_obj.name} property",
+                                   f"{self.resource_inputs_url}/create/inputs",
+                                   data=jinja_env().get_template(\
+                                       "sdc_add_cs_properties_input.json.j2").\
+                                            render(\
+                                                sdc_resource=self,
+                                                property=property_obj))
+        else:
+            self._logger.error("Data type %s not supported", property_obj.property_type)
+
+    def declare_resource_input(self,
+                               input_to_declare: Property) -> None:
+        """Declare input for given property, nested input or component property object.
+
+        Call SDC FE API to declare input for given property.
+
+        Args:
+            input_declaration (Union[Property, NestedInput]): Property or ComponentProperty
+                to declare input or NestedInput object
+
+        Raises:
+            ParameterError: if the given property is not SDC resource property
+
+        """
+        self.send_message("POST",
+                          f"Declare new input for {input_to_declare.name} property",
+                          f"{self.resource_inputs_url}/create/inputs",
+                          data=jinja_env().get_template(\
+                              "component_declare_input.json.j2").\
+                                  render(\
+                                      component=input_to_declare.component,
+                                      property=input_to_declare))
+
+    def declare_resources_and_properties(self) -> None:
+        """Delcare resources and properties.
+
+        It declares also inputs.
+
+        """
+        for resource in self.resources:
+            self.add_resource(resource)
+        for property_to_add in self._properties_to_add:
+            self.add_property(property_to_add)
+        for input_to_add in self._inputs_to_add:
+            self.declare_input(input_to_add)
+        if self.complex_input is not None:
+            self.declare_complex_input(self.complex_input)
+
+
+    def get_distribution_status(self) -> dict:
+        """Get service distribution status."""
+        url = "{}/services/distribution/{}".format(self._base_create_url(),
+                                                   self.distribution_id)
+        headers = headers_sdc_creator(SdcResource.headers)
+        try:
+            result = self.send_message_json("GET",
+                                            "Check distribution for {}".format(
+                                                self.name),
+                                            url,
+                                            headers=headers)
+        except ResourceNotFound:
+            msg = f"No distributions found for {self.name} of {self.__class__.__name__}."
+            self._logger.debug(msg)
+        else:
+            return result
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/templates/component_declare_input.json.j2 b/smo-install/test/pythonsdk/src/oransdk/sdc/templates/component_declare_input.json.j2
new file mode 100644 (file)
index 0000000..fd0ee03
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  "componentInstanceInputsMap": {},
+  "componentInstanceProperties": {
+    "{{ component.unique_id }}": [
+      {
+        "constraints": null,
+        "defaultValue": null,
+        "description": "",
+        "name": "{{ property.name }}",
+        "origName": "{{ property.name }}",
+        "parentUniqueId": null,
+        "password": false,
+        "required": true,
+        "schema": {
+          "property": {}
+        },
+        "schemaType": null,
+        "type": "{{ property.property_type }}",
+        "uniqueId": "{{ property.unique_id }}",
+        {% if property.value is not none %}
+        "value":"{{ property.value }}",
+        {% else %}
+        "value":null,
+        {% endif %}
+        "definition": false,
+        "getInputValues": null,
+        "parentPropertyType": null,
+        "subPropertyInputPath": null,
+        "getPolicyValues": null,
+        "inputPath": null,
+        "metadata": null
+      }
+    ]
+  },
+  "groupProperties": {},
+  "policyProperties": {}
+}
\ No newline at end of file
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_cs_properties_input.json.j2 b/smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_cs_properties_input.json.j2
new file mode 100644 (file)
index 0000000..f8c6dfb
--- /dev/null
@@ -0,0 +1,435 @@
+{
+  "serviceProperties": {
+    "{{ sdc_resource.unique_identifier }}": [
+      {
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#coverageAreaList",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#coverageAreaList",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "coverageAreaList",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.coverageAreaList",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "coverageAreaList"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#expDataRateDL",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#expDataRateDL",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "expDataRateDL",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.expDataRateDL",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "expDataRateDL"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#expDataRateUL",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#expDataRateUL",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "expDataRateUL",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.expDataRateUL",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "expDataRateUL"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#latency",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#latency",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "latency",
+          "defaultValue": "30",
+          "derivedDataType": 0,
+          "valueObj": 30,
+          "value": "30",
+          "uniqueId": "{{ property.property_type }}.datatype.latency",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "latency"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#maxNumberofUEs",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#maxNumberofUEs",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "maxNumberofUEs",
+          "defaultValue": "1000",
+          "derivedDataType": 0,
+          "valueObj": 1000,
+          "value": "1000",
+          "uniqueId": "{{ property.property_type }}.datatype.maxNumberofUEs",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "maxNumberofUEs"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#resourceSharingLevel",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#resourceSharingLevel",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "Shared","Non-shared"]
+            }],
+          "description": "resourceSharingLevel",
+          "defaultValue": "Shared",
+          "derivedDataType": 0,
+          "valueObj": "Shared",
+          "value": "Shared",
+          "uniqueId": "{{ property.property_type }}.datatype.resourceSharingLevel",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "resourceSharingLevel"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#uEMobilityLevel",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#uEMobilityLevel",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "stationary","nomadic","restricted mobility","fully mobility"]
+            }],
+          "description": "uEMobilityLevel",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.uEMobilityLevel",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "uEMobilityLevel"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#useInterval",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#useInterval",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "useInterval",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.useInterval",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "useInterval"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      }]
+  }
+}
\ No newline at end of file
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_service_profile_input.json.j2 b/smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_service_profile_input.json.j2
new file mode 100644 (file)
index 0000000..621cd21
--- /dev/null
@@ -0,0 +1,493 @@
+{
+  "serviceProperties": {
+    "{{ sdc_resource.unique_identifier }}": [
+      {
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#coverageAreaTAList",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#coverageAreaTAList",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "coverageAreaTAList",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.coverageAreaTAList",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "coverageAreaTAList"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#dLThptPerUE",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#dLThptPerUE",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "dLThptPerUE",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.dLThptPerUE",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "dLThptPerUE"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#latency",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#latency",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "latency",
+          "defaultValue": "30",
+          "derivedDataType": 0,
+          "valueObj": 30,
+          "value": "30",
+          "uniqueId": "{{ property.property_type }}.datatype.latency",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "latency"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#maxNumberofUEs",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#maxNumberofUEs",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "maxNumberofUEs",
+          "defaultValue": "1000",
+          "derivedDataType": 0,
+          "valueObj": 1000,
+          "value": "1000",
+          "uniqueId": "{{ property.property_type }}.datatype.maxNumberofUEs",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "maxNumberofUEs"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#resourceSharingLevel",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#resourceSharingLevel",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "Shared","Non-shared"]
+            }],
+          "description": "resourceSharingLevel",
+          "defaultValue": "Shared",
+          "derivedDataType": 0,
+          "valueObj": "Shared",
+          "value": "Shared",
+          "uniqueId": "{{ property.property_type }}.datatype.resourceSharingLevel",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "resourceSharingLevel"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#sNSSAI",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#sNSSAI",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "sNSSAI",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.sNSSAI",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "sNSSAI"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#sST",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#sST",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "eMBB","uRLLC","mIot"]
+            }],
+          "description": "sST",
+          "defaultValue": "eMBB",
+          "derivedDataType": 0,
+          "valueObj": "eMBB",
+          "value": "eMBB",
+          "uniqueId": "{{ property.property_type }}.datatype.sST",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "sST"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#uEMobilityLevel",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#uEMobilityLevel",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "stationary","nomadic","restricted mobility","fully mobility"]
+            }],
+          "description": "uEMobilityLevel",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.uEMobilityLevel",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "uEMobilityLevel"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#uLThptPerUE",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#uLThptPerUE",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "uLThptPerUE",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.uLThptPerUE",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "uLThptPerUE"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      }]
+  }
+}
\ No newline at end of file
diff --git a/smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_slice_profile_input.json.j2 b/smo-install/test/pythonsdk/src/oransdk/sdc/templates/sdc_add_slice_profile_input.json.j2
new file mode 100644 (file)
index 0000000..0103583
--- /dev/null
@@ -0,0 +1,1117 @@
+{
+  "serviceProperties": {
+    "{{ sdc_resource.unique_identifier }}": [
+      {
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#activityFactor",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#activityFactor",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "activityFactor",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.activityFactor",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "activityFactor"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#areaTrafficCapDL",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#areaTrafficCapDL",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "areaTrafficCapDL",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.areaTrafficCapDL",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "areaTrafficCapDL"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#areaTrafficCapUL",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#areaTrafficCapUL",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "areaTrafficCapUL",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.areaTrafficCapUL",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "areaTrafficCapUL"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#cSAvailabilityTarget",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#cSAvailabilityTarget",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "cSAvailabilityTarget",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.cSAvailabilityTarget",
+          "password": false,
+          "definition": false,
+          "type": "float",
+          "name": "cSAvailabilityTarget"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#cSReliabilityMeanTime",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#cSReliabilityMeanTime",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "cSReliabilityMeanTime",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.cSReliabilityMeanTime",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "cSReliabilityMeanTime"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#coverageAreaTAList",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#coverageAreaTAList",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "coverageAreaTAList",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.coverageAreaTAList",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "coverageAreaTAList"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#expDataRate",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#expDataRate",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "expDataRate",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.expDataRate",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "expDataRate"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#expDataRateDL",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#expDataRateDL",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "expDataRateDL",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.expDataRateDL",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "expDataRateDL"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#expDataRateUL",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#expDataRateUL",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "expDataRateUL",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.expDataRateUL",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "expDataRateUL"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#latency",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#latency",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "latency",
+          "defaultValue": "30",
+          "derivedDataType": 0,
+          "valueObj": 30,
+          "value": "30",
+          "uniqueId": "{{ property.property_type }}.datatype.latency",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "latency"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#maxNumberofPDUSession",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#maxNumberofPDUSession",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "maxNumberofPDUSession",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.maxNumberofPDUSession",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "maxNumberofPDUSession"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#maxNumberofUEs",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#maxNumberofUEs",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "maxNumberofUEs",
+          "defaultValue": "1000",
+          "derivedDataType": 0,
+          "valueObj": 1000,
+          "value": "1000",
+          "uniqueId": "{{ property.property_type }}.datatype.maxNumberofUEs",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "maxNumberofUEs"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#msgSizeByte",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#msgSizeByte",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "msgSizeByte",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.msgSizeByte",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "msgSizeByte"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#overallUserDensity",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#overallUserDensity",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "overallUserDensity",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.overallUserDensity",
+          "password": false,
+          "definition": false,
+          "type": "integer",
+          "name": "overallUserDensity"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#pLMNIdList",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#pLMNIdList",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "pLMNIdList",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.pLMNIdList",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "pLMNIdList"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#resourceSharingLevel",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#resourceSharingLevel",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "Shared","Non-shared"]
+            }],
+          "description": "resourceSharingLevel",
+          "defaultValue": "Shared",
+          "derivedDataType": 0,
+          "valueObj": "Shared",
+          "value": "Shared",
+          "uniqueId": "{{ property.property_type }}.datatype.resourceSharingLevel",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "resourceSharingLevel"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#sNSSAI",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#sNSSAI",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "sNSSAI",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.sNSSAI",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "sNSSAI"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#sST",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": true,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#sST",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "eMBB","uRLLC","mIot"]
+            }],
+          "description": "sST",
+          "defaultValue": "eMBB",
+          "derivedDataType": 0,
+          "valueObj": "eMBB",
+          "value": "eMBB",
+          "uniqueId": "{{ property.property_type }}.datatype.sST",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "sST"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#survivalTime",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#survivalTime",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "survivalTime",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.survivalTime",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "survivalTime"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#transferIntervalTarget",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#transferIntervalTarget",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "description": "transferIntervalTarget",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.transferIntervalTarget",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "transferIntervalTarget"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      },{
+        "required": false,
+        "schemaType": "",
+        "propertiesName": "{{ property.name }}#uEMobilityLevel",
+        "inputPath": null,
+        "parentUniqueId": "{{ sdc_resource.unique_identifier }}",
+        "getPolicyValues": null,
+        "parentPropertyType": null,
+        "schema": {
+          "property": {
+            "required": false,
+            "description": null,
+            "password": false,
+            "definition": false,
+            "type": ""
+          }
+        },
+        "metadata": null,
+        "constraints": null,
+        "input": {
+          "canBeDeclared": true,
+          "required": false,
+          "parentName": "{{ property.name }}",
+          "propertiesName": "{{ property.name }}#uEMobilityLevel",
+          "toscaPresentation": {},
+          "isSelected": true,
+          "schema": {
+            "property": {}
+          },
+          "valueObjIsValid": true,
+          "constraints": [
+            {
+              "validValues": [
+                "stationary","nomadic","restricted mobility","fully mobility"]
+            }],
+          "description": "uEMobilityLevel",
+          "derivedDataType": 0,
+          "valueObj": null,
+          "value": null,
+          "uniqueId": "{{ property.property_type }}.datatype.uEMobilityLevel",
+          "password": false,
+          "definition": false,
+          "type": "string",
+          "name": "uEMobilityLevel"
+        },
+        "description": null,
+        "defaultValue": null,
+        "getInputValues": null,
+        "toscaGetFunctionType": null,
+        "value": null,
+        "uniqueId": "{{ sdc_resource.unique_identifier }}.{{ property.name }}",
+        "password": false,
+        "definition": false,
+        "origName": "{{ property.name }}",
+        "type": "{{ property.property_type }}",
+        "name": "{{ property.name }}",
+        "subPropertyInputPath": null
+      }]
+  }
+}
\ No newline at end of file
diff --git a/smo-install/test/pythonsdk/src/oransdk/so/__init__.py b/smo-install/test/pythonsdk/src/oransdk/so/__init__.py
new file mode 100644 (file)
index 0000000..9e553f6
--- /dev/null
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""ONAP SO package."""
diff --git a/smo-install/test/pythonsdk/src/oransdk/so/so.py b/smo-install/test/pythonsdk/src/oransdk/so/so.py
new file mode 100644 (file)
index 0000000..e2e9018
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Onap SO module."""
+from onapsdk.so.so_element import SoElement
+
+class OranSo(SoElement):
+    """So class."""
+
+    def healthcheck(self) -> dict:
+        """
+        Healthcheck SO main component.
+
+        Returns:
+           the status of SO components
+        """
+        status = self.send_message_json('GET',
+                                        'Get status of SO components',
+                                        f"{self.base_url}/manage/health",
+                                        headers=self.headers)
+        return status
diff --git a/smo-install/test/pythonsdk/src/oransdk/utils/healthcheck.py b/smo-install/test/pythonsdk/src/oransdk/utils/healthcheck.py
new file mode 100644 (file)
index 0000000..010d02a
--- /dev/null
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START=======================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+# Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+"""Module called by pytest."""
+import logging
+import logging.config
+
+from subprocess import check_output, run
+from requests import RequestException
+from onapsdk.configuration import settings
+from onapsdk.exceptions import ConnectionFailed, APIError
+from urllib3.exceptions import NewConnectionError
+from oransdk.aai.aai import Aai
+from oransdk.msb.msb_microservice import OranMsb
+from oransdk.oof.oof import Oof
+from oransdk.policy.clamp import ClampToscaTemplate
+from oransdk.policy.policy import OranPolicy
+from oransdk.sdc.sdc import SdcTemplate
+from oransdk.sdnc.sdnc import OranSdnc
+from oransdk.so.so import OranSo
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("Health check")
+
+clamp = ClampToscaTemplate(settings.CLAMP_BASICAUTH)
+sdnc = OranSdnc()
+policy = OranPolicy()
+aai = Aai()
+sdc = SdcTemplate()
+so = OranSo()
+msb = OranMsb()
+oof = Oof()
+
+class HealthCheck():
+    """Healthcheck class for ONAP component."""
+
+    @classmethod
+    def is_onap_up(cls, up_no) -> bool:
+        """Verify if ONAP platform is up or not."""
+        cmd = "kubectl get pods --field-selector 'status.phase=Failed' -n onap -o name | xargs kubectl delete -n onap"
+        run(cmd, shell=True, check=False)
+        cmd = "kubectl get pods --field-selector status.phase!=Running -n onap | wc -l"
+        result = check_output(cmd, shell=True).decode('utf-8')
+        logger.info("Number of Onap pods not in Running state (expected <= %s): %s", up_no, result)
+        if int(result) <= up_no:
+            logger.info("ONAP is Up")
+            return True
+        logger.info("ONAP is Down")
+        return False
+
+    @classmethod
+    def policy_component_ready(cls):
+        """Check if Policy components are ready."""
+        logger.info("Verify Policy components are ready")
+        try:
+            policy_ready = {"api_ready": False, "pap_ready": False, "apex_ready": False}
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        policy_status = policy.get_components_status(settings.POLICY_BASICAUTH)
+        if (policy_status["api"]["healthy"] and not policy_ready["api_ready"]):
+            logger.info("Policy Api is ready")
+            policy_ready["api_ready"] = True
+        if (policy_status["pap"]["healthy"] and not policy_ready["pap_ready"]):
+            logger.info("Policy Pap is ready")
+            policy_ready["pap_ready"] = True
+        if (len(policy_status["pdps"]["apex"]) > 0 and policy_status["pdps"]["apex"][0]["healthy"] == "HEALTHY" and not policy_ready["apex_ready"]):
+            logger.info("Policy Apex is ready")
+            policy_ready["apex_ready"] = True
+        return policy_ready["api_ready"] and policy_ready["pap_ready"] and policy_ready["apex_ready"]
+
+    @classmethod
+    def sdnc_component_ready(cls):
+        """Check if SDNC component is ready."""
+        logger.info("Verify SDNC component is ready")
+
+        try:
+            response = OranSdnc.get_events(settings.SDNC_BASICAUTH, "test")
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        return response.status_code == 200
+
+    @classmethod
+    def clamp_component_ready(cls):
+        """Check if Clamp component is ready."""
+        logger.info("Verify Clamp component is ready")
+        try:
+            response = clamp.get_template_instance()
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        return response["automationCompositionList"] is not None
+
+    @classmethod
+    def sdc_component_ready(cls):
+        """Check if SDC component is ready."""
+        logger.info("Verify SDC component is ready")
+
+        try:
+            response = sdc.healthcheck()
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+
+        so_ready = {"BE": False, "CASSANDRA": False, "ON_BOARDING": False, "JANUSGRAPH": False}
+        so_list = response["componentsInfo"]
+        for so_status in so_list:
+            if (so_status["healthCheckComponent"] == "BE" and so_status["healthCheckStatus"] == "UP"):
+                so_ready["BE"] = True
+            if (so_status["healthCheckComponent"] == "CASSANDRA" and so_status["healthCheckStatus"] == "UP"):
+                so_ready["CASSANDRA"] = True
+            if (so_status["healthCheckComponent"] == "ON_BOARDING" and so_status["healthCheckStatus"] == "UP"):
+                so_ready["ON_BOARDING"] = True
+            if (so_status["healthCheckComponent"] == "JANUSGRAPH" and so_status["healthCheckStatus"] == "UP"):
+                so_ready["JANUSGRAPH"] = True
+
+        return so_ready["BE"] and so_ready["CASSANDRA"] and so_ready["ON_BOARDING"] and so_ready["JANUSGRAPH"]
+
+    @classmethod
+    def aai_component_ready(cls):
+        """Check if AAI component is ready."""
+        logger.info("Verify AAI component is ready")
+
+        try:
+            response = aai.healthcheck()
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        return "Successful health check:OK" in str(response)
+
+    @classmethod
+    def so_component_ready(cls):
+        """Check if SO component is ready."""
+        logger.info("Verify SO component is ready")
+
+        try:
+            response = so.healthcheck()
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        return response["status"] == "UP"
+
+    @classmethod
+    def msb_component_ready(cls):
+        """Check if MSB component is ready."""
+        logger.info("Verify MSB component is ready")
+
+        try:
+            response = msb.get_services()
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        return response is not None and len(response) > 0
+
+    @classmethod
+    def oof_component_ready(cls):
+        """Check if OOF component is ready."""
+        logger.info("Verify OOF component is ready")
+
+        try:
+            response = oof.get_versions()
+        except (RequestException, NewConnectionError, ConnectionFailed, APIError) as e:
+            logger.error(e)
+            return False
+        return response["versions"] is not None
index f0ab6d6..64004da 100644 (file)
@@ -46,7 +46,9 @@ def jinja_env() -> Environment:
     return Environment(autoescape=select_autoescape(['html', 'htm', 'xml']),
                        loader=ChoiceLoader([
                            PackageLoader("oransdk.a1sim"),
+                           PackageLoader("oransdk.aai"),
                            PackageLoader("oransdk.dmaap"),
                            PackageLoader("oransdk.enrichmentservice"),
-                           PackageLoader("oransdk.policy")
+                           PackageLoader("oransdk.policy"),
+                           PackageLoader("oransdk.sdc")
                        ]))
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/aai_preparation.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/aai_preparation.py
new file mode 100644 (file)
index 0000000..6ba270f
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Configure AAI for Network Slicing option2 test."""
+import logging
+import logging.config
+
+from onapsdk.aai.business.customer import Customer
+from onapsdk.configuration import settings
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("####################### Start AAI Preparation")
+
+class AaiPreparation():
+    """Can be used to prepare AAI for Network Slicing usecase option2."""
+
+    @classmethod
+    def prepare_aai(cls):
+        """Prepare AAI for network slicing use case."""
+        logger.info("####################### Start to prepare AAI")
+        aai = Customer("5GCustomer", "5GCustomer", "INFRA")
+        aai.create("5GCustomer", "5GCustomer", "INFRA")
+        aai.subscribe_service("5G")
+
+    @classmethod
+    def cleanup_aai(cls):
+        """Clean up AAI settings."""
+        logger.info("####################### Start to clean up AAI settings")
+        aai = Customer.get_by_global_customer_id("5GCustomer")
+        aai.delete()
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/msb_preparation.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/msb_preparation.py
new file mode 100644 (file)
index 0000000..73253b1
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Create MSB Templates for Network Slicing option2 test."""
+import logging
+import logging.config
+import subprocess
+from subprocess import check_output
+from onapsdk.configuration import settings
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("####################### Start MSB Preparation")
+
+class MsbPreparation():
+    """Can be used to prepare MSB for Network Slicing usecase option2."""
+
+    @classmethod
+    def prepare_msb(cls):
+        """Register services to msb."""
+        logger.info("####################### Start to register SO instance service")
+        so_pod = subprocess.run("kubectl get svc -n onap so | grep so | awk '{print $3}' ", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+        content = "{ \"url\": \"/onap/so/infra/e2eServiceInstances/v3\",\"nodes\": [{\"nodeId\": \"_v3_so-serviceInstances_" + so_pod + "_8080\", \
+                  \"checkUrl\": \"\",\"status\": \"passing\",\"ha_role\": \"\",\"checkType\": \"\",\"ip\": \""+ so_pod +"\",\"port\": \"8080\", \
+                  \"tls_skip_verify\": true}],\"status\": \"1\",\"publish_port\": \"\",\"lb_policy\": \"ip_hash\",\"serviceName\": \
+                  \"so-serviceInstances\",\"metadata\": [],\"network_plane_type\": \"\", \"version\": \"v3\",\"labels\": [],\"namespace\": \"\", \
+                  \"enable_ssl\": false,\"path\": \"\",\"protocol\": \"REST\",\"host\": \"\",\"visualRange\": \"1\",\"is_manual\": true}"
+        cmd = f"curl -sk --noproxy \"*\" -X POST {settings.MSB_URL}/api/msdiscover/v1/services -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d '{content}'"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        logger.info("####################### Start to register SO orchestration tasks")
+        content = "{ \"url\": \"/onap/so/infra/orchestrationTasks/v4\",\"nodes\": [{\"nodeId\": \"_v4_so-orchestrationTasks_" + so_pod + "_8080\", \
+                  \"checkUrl\": \"\",\"status\": \"passing\",\"ha_role\": \"\",\"checkType\": \"\",\"ip\": \""+ so_pod +"\",\"port\": \"8080\", \
+                  \"tls_skip_verify\": true}],\"status\": \"1\",\"publish_port\": \"\",\"lb_policy\": \"ip_hash\",\"serviceName\": \
+                  \"so-orchestrationTasks\",\"metadata\": [],\"network_plane_type\": \"\", \"version\": \"v4\",\"labels\": [],\"namespace\": \"\", \
+                  \"enable_ssl\": false,\"path\": \"\",\"protocol\": \"REST\",\"host\": \"\",\"visualRange\": \"1\",\"is_manual\": true}"
+        cmd = f"curl -sk --noproxy \"*\" -X POST {settings.MSB_URL}/api/msdiscover/v1/services -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d '{content}'"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        logger.info("####################### Start to register AAI business instance service")
+        aai_pod = subprocess.run("kubectl get svc -n onap aai | grep aai | awk '{print $3}' ", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+        content = '{"url": "/aai/v13/business", "nodes": [{"nodeId": "_v13_aai-business_' + aai_pod + '_8443", \
+                  "checkUrl": "","status": "passing","ha_role": "","checkType": "","ip": "' + aai_pod + '", "port": "8443", \
+                  "tls_skip_verify": true}],"status": "1","publish_port": "","lb_policy": "", "serviceName": "aai-business","metadata": \
+                  [],"network_plane_type": "","version": "v13","labels": [],"namespace": "","enable_ssl": true,"path": "","protocol": \
+                  "REST","host": "","visualRange": "1","is_manual": true}'
+        cmd = f"curl -sk --noproxy \"*\" -X POST {settings.MSB_URL}/api/msdiscover/v1/services -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d '{content}'"
+        check_output(cmd, shell=True).decode('utf-8')
+
+    @classmethod
+    def cleanup_msb(cls):
+        """Rollback msb settings."""
+        logger.info("####################### Start to remove SO instance service")
+        cmd = f"curl -sk --noproxy \"*\" -X DELETE {settings.MSB_URL}/api/msdiscover/v1/services -H  \"accept: application/json\" -H  \"Content-Type: application/json\" "
+        check_output(cmd, shell=True).decode('utf-8')
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/oof_preparation.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/oof_preparation.py
new file mode 100644 (file)
index 0000000..dd284e6
--- /dev/null
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Prepare OOF for Network Slicing option2 test."""
+import os
+import logging
+import logging.config
+import subprocess
+import sys
+from subprocess import check_output
+from onapsdk.configuration import settings
+from oransdk.policy.policy import OranPolicy
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("####################### Start OOF Preparation")
+
+# Set working dir as python script location
+abspath = os.path.abspath(__file__)
+dname = os.path.dirname(abspath)
+os.chdir(dname)
+
+class OofPreparation():
+    """Can be used to prepare OOF for Network Slicing usecase option2."""
+
+    @classmethod
+    def prepare_oof(cls, nst_name, an_nsst_name, tn_nsst_name):
+        """Prepare OOF, create optimization policies."""
+        # copy policy creation package to oof pod
+        logger.info("####################### copy policy generation package to OOF pod:%s", dname)
+        oof_pod = subprocess.run("kubectl get pods -n onap | awk '{print $1}' | grep  onap-oof-[a-z0-9]*-[a-z0-9]*$", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+        cmd = f"kubectl cp ../resources/policies_option2.tar.gz -n onap {oof_pod}:/opt/osdf"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- tar -xvf policies_option2.tar.gz"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        # run python command to create policies
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py create_policy_types policy_types"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py create_and_push_policies nst_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py generate_nsi_policies {nst_name}"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py create_and_push_policies gen_nsi_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py generate_nssi_policies {an_nsst_name} minimize latency"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py create_and_push_policies gen_nssi_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py generate_nssi_policies {tn_nsst_name}  minimize latency"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py create_and_push_policies gen_nssi_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        #Verify policies created
+        policy = OranPolicy()
+        policy_status_list = policy.get_policy_status(settings.POLICY_BASICAUTH)
+        if len(policy_status_list) != 20:
+            logger.info("####################### Policy created failed. 20 policies expected, but only %s found. Please verify manually.", str(len(policy_status_list)))
+            sys.exit('OOF preparation failed. Exception while creating policies. Please check the policies manually.')
+
+    @classmethod
+    def cleanup_oof(cls):
+        """Delete OOF optimization policies."""
+        oof_pod = subprocess.run("kubectl get pods -n onap | awk '{print $1}' | grep  onap-oof-[a-z0-9]*-[a-z0-9]*$", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+
+        # run python command to create policies
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py delete_policies nst_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        #python3 policy_utils.py create_and_push_policies gen_nsi_policies
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py delete_policies gen_nsi_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        #python3 policy_utils.py create_and_push_policies gen_nssi_policies
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- python3 policies_option2/policy_utils.py delete_policies gen_nssi_policies"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        # run python command to create policies
+        logger.info("####################### copy policy generation package to OOF pod:%s", dname)
+        cmd = f"kubectl exec -ti -n onap {oof_pod} -- rm -rf policies_option2"
+        check_output(cmd, shell=True).decode('utf-8')
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/sdc_preparation.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/sdc_preparation.py
new file mode 100644 (file)
index 0000000..08493e3
--- /dev/null
@@ -0,0 +1,392 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2021 Samsung Electronics
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Create SDC Templates for Network Slicing option2 test."""
+import logging
+import logging.config
+from time import sleep
+import os
+from onapsdk.sdc.vfc import Vfc
+from onapsdk.sdc.vf import Vf
+import onapsdk.constants as const
+from onapsdk.configuration import settings
+from onapsdk.exceptions import ResourceNotFound
+from onapsdk.sdc.properties import Property, ParameterError
+from waiting import wait
+from oransdk.aai.service_design_and_creation import AaiModel
+from oransdk.sdc.sdc import SdcTemplate
+from oransdk.sdc.service import OranService
+
+# Set working dir as python script location
+abspath = os.path.abspath(__file__)
+dname = os.path.dirname(abspath)
+os.chdir(dname)
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("####################### Start SDC Preparation")
+service_dict = {}
+service_list = []
+
+class SdcPreparation():
+    """Can be used to prepare SDC for Network Slicing usecase option2."""
+
+    def __init__(self, suffix: str = None):
+        """
+        Initialize SDC preparation object.
+
+        Args:
+            suffix (str, optional): the suffix of the SDC template names
+
+        """
+        if suffix is None:
+            self.suffix = ""
+        else:
+            self.suffix = suffix
+
+    def prepare_sdc(self) -> dict:
+        """Create SDC templates."""
+        # Populate AAI needed value
+
+        sdc = SdcTemplate()
+        vendor = sdc.create_vendor('ONAP')
+        sdc.create_vsp('test1', vendor)
+
+        # 0.create custom categories
+        logger.info("####################### create custom categories")
+        sdc.create_service_category(['CST', 'ServiceProfile', 'AN SliceProfile', 'CN SliceProfile', 'TN SliceProfile',
+                                     'NST', 'TN BH NSST', 'TN Network Requirement', 'AN NF NSST', 'CN NSST', 'Allotted Resource'])
+
+
+        vf_tn_bh_ar = self.create_tn_resources(sdc, vendor)
+        vf_embban_nf_ar = self.create_an_resources(sdc, vendor)
+        vf_embbcn_external_ar = self.create_cn_resources(sdc, vendor)
+        self.create_nst(sdc, vf_embbcn_external_ar, vf_embban_nf_ar, vf_tn_bh_ar)
+
+        vf_slice_ar = self.create_slice_ar(sdc, vendor)
+
+        srv_slice_profile_an_o2 = self.create_an_slice_profiles(sdc, vf_slice_ar)
+        srv_slice_profile_tn = self.create_tn_slice_profiles(sdc, vf_slice_ar)
+        srv_slice_profile_cn = self.create_cn_slice_profiles(sdc, vf_slice_ar)
+        srv_profile_o2 = self.create_service_profile(sdc, vf_slice_ar, srv_slice_profile_cn, srv_slice_profile_tn, srv_slice_profile_an_o2)
+        cst = self.create_cst(sdc, srv_profile_o2)
+        wait(lambda: self.verify_distribution(), sleep_seconds=60, timeout_seconds=3600, waiting_for="All services distributed successfully")
+        return [cst.identifier, cst.unique_uuid, srv_profile_o2.identifier]
+
+    def create_tn_resources(self, sdc, vendor) -> dict:
+        """Create TN related resources."""
+        # 1.Create TN_Network_Requirement Service
+        logger.info("####################### create TN_Network_Requirement Service")
+        props = [Property('ConnectionLink', 'string'),
+                 Property('jitter', 'string', value='10'),
+                 Property('latency', 'integer', value=10),
+                 Property('maxBandwith', 'integer', value=1000)]
+
+        srv_tn_network = sdc.create_service(self.updated_name('TN_Network_Requirement'), 'TN Network Requirement', properties=props,
+                                            inputs=[Property('ConnectionLink', 'string')])
+        service_dict[srv_tn_network.identifier] = False
+        service_list.append(srv_tn_network)
+
+        # 2.Create TN_Network_Req_AR
+        logger.info("####################### create TN_Network_Req_AR")
+        vf = sdc.create_vf(self.updated_name('TN_Network_Req_AR'), 'Allotted Resource', 'Allotted Resource', vendor)
+        for c in vf.components:
+            if c.name == 'AllottedResource 0':
+                c.get_property('providing_service_invariant_uuid').value = srv_tn_network.unique_uuid
+                c.get_property('providing_service_uuid').value = srv_tn_network.identifier
+                c.get_property('providing_service_name').value = srv_tn_network.name
+                break
+        sdc.onboard_vf(vf)
+
+        # 3.Create Tn_ONAP_internal_BH Service
+        logger.info("####################### create Tn_ONAP_internal_BH Service")
+        props = [Property('pLMNIdList', 'string', value='39-00'),
+                 Property('jitter', 'string', value='10'),
+                 Property('latency', 'integer', value=10),
+                 Property('maxBandwith', 'integer', value=1000)]
+
+        srv_tn_bh = sdc.create_service(self.updated_name('Tn_ONAP_internal_BH'), 'TN BH NSST', vnfs=[vf],
+                                       role='ONAP_internal', properties=props)
+        service_dict[srv_tn_bh.identifier] = False
+        service_list.append(srv_tn_bh)
+
+        # 6.Create Tn_BH_AR
+        logger.info("####################### Create Tn_BH_AR")
+        vf_tn_bh_ar = sdc.create_vf(self.updated_name('Tn_BH_AR'), 'Allotted Resource', 'Allotted Resource', vendor)
+        for c in vf_tn_bh_ar.components:
+            if c.name == 'AllottedResource 0':
+                c.get_property('providing_service_invariant_uuid').value = srv_tn_bh.unique_uuid
+                c.get_property('providing_service_uuid').value = srv_tn_bh.identifier
+                c.get_property('providing_service_name').value = srv_tn_bh.name
+                break
+        sdc.onboard_vf(vf_tn_bh_ar)
+        return vf_tn_bh_ar
+
+    def create_an_resources(self, sdc, vendor) -> dict:
+        """Create AN related resources."""
+        # 4.Create EmbbAn_NF Service Template
+        logger.info("####################### create EmbbAn_NF Service Template")
+        props = [Property('anNSSCap', 'org.openecomp.datatypes.NSSCapabilities')]
+        srv_embban_nf = sdc.create_service(self.updated_name('EmbbAn_NF'), 'AN NF NSST', role='huawei', service_type='embb', properties=props)
+        service_dict[srv_embban_nf.identifier] = False
+        service_list.append(srv_embban_nf)
+
+        # 7.Create EmbbAn_NF_AR
+        logger.info("####################### create EmbbAn_NF_AR")
+        vf_embban_nf_ar = sdc.create_vf(self.updated_name('EmbbAn_NF_AR'), 'Allotted Resource', 'Allotted Resource', vendor)
+        for c in vf_embban_nf_ar.components:
+            if c.name == 'AllottedResource 0':
+                c.get_property('providing_service_invariant_uuid').value = srv_embban_nf.unique_uuid
+                c.get_property('providing_service_uuid').value = srv_embban_nf.identifier
+                c.get_property('providing_service_name').value = srv_embban_nf.name
+                break
+        sdc.onboard_vf(vf_embban_nf_ar)
+        return vf_embban_nf_ar
+
+    def create_cn_resources(self, sdc, vendor) -> dict:
+        """Create CN related resources."""
+        # 5.Create EmbbCn_External Service Template
+        logger.info("####################### create EmbbCn_External Service Template")
+        srv_embbcn = OranService(name=self.updated_name('EmbbCn_External'),
+                                 category='CN NSST',
+                                 role='huawei',
+                                 service_type='embb',
+                                 properties=[Property('cnCap', 'org.openecomp.datatypes.NSSCapabilities',\
+                                                      value="{\\\"latency\\\":20,\\\"maxNumberofUEs\\\":10000,\
+                                                              \\\"resourceSharingLevel\\\":\\\"Shared\\\",\\\"sST\\\":\\\"eMBB\\\",\
+                                                              \\\"activityFactor\\\":30,\\\"areaTrafficCapDL\\\":800,\
+                                                              \\\"areaTrafficCapUL\\\":800,\\\"expDataRateDL\\\":1000,\
+                                                              \\\"survivalTime\\\":10,\\\"uEMobilityLevel\\\":\\\"stationary\\\",\
+                                                              \\\"expDataRateUL\\\":1000,\\\"pLMNIdList\\\":\\\"39-00\\\"}")])
+
+        srv_embbcn.create()
+
+        if srv_embbcn.status == const.DRAFT:
+            srv_embbcn.add_deployment_artifact(artifact_type="WORKFLOW", artifact_name="eMBB.zip", artifact="../resources/eMBB.zip",
+                                               artifact_label="abc")
+
+        if srv_embbcn.status != const.DISTRIBUTED:
+            done = False
+            retry = 0
+            to = 1
+            while not done:
+                try:
+                    srv_embbcn.onboard()
+                except ResourceNotFound as e:
+                    retry += 1
+                    if retry > 5:
+                        raise e
+                    to = 2 * to + 1
+                    sleep(to)
+                else:
+                    done = True
+        service_dict[srv_embbcn.identifier] = False
+        service_list.append(srv_embbcn)
+
+        # 8.EmbbCn_External_AR
+        logger.info("####################### create EmbbCn_External_AR")
+        vf_embbcn_external_ar = sdc.create_vf(self.updated_name('EmbbCn_External_AR'), 'Allotted Resource', 'Allotted Resource', vendor)
+        for c in vf_embbcn_external_ar.components:
+            if c.name == 'AllottedResource 0':
+                c.get_property('providing_service_invariant_uuid').value = srv_embbcn.unique_uuid
+                c.get_property('providing_service_uuid').value = srv_embbcn.identifier
+                c.get_property('providing_service_name').value = srv_embbcn.name
+                break
+        sdc.onboard_vf(vf_embbcn_external_ar)
+        return vf_embbcn_external_ar
+
+    def create_nst(self, sdc, vf_embbcn_external_ar, vf_embban_nf_ar, vf_tn_bh_ar) -> None:
+        """Create NST."""
+        # 9.Create EmbbNst_O2 Service Template
+        logger.info("####################### create service EmbbNst_O2")
+        props = [Property('latency', 'integer', value=20),
+                 Property('maxNumberofUEs', 'integer', value=1000),
+                 Property('maxNumberofConns', 'integer', value=100000),
+                 Property('resourceSharingLevel', 'string', value='Shared'),
+                 Property('sST', 'string', value='eMBB'),
+                 Property('activityFactor', 'integer', value=60),
+                 Property('availability', 'float', value=0.6),
+                 Property('dLThptPerSlice', 'integer', value=1000),
+                 Property('uLThptPerSlice', 'integer', value=1000),
+                 Property('jitter', 'integer', value=10),
+                 Property('survivalTime', 'integer', value=10),
+                 Property('uEMobilityLevel', 'string', value='stationary'),
+                 Property('pLMNIdList', 'string', value='39-00'),
+                 Property('reliability', 'string', value='99%')]
+        nst = sdc.create_service(self.updated_name('EmbbNst_O2'),
+                                 'NST',
+                                 role='option2',
+                                 vnfs=[vf_embbcn_external_ar, vf_embban_nf_ar, vf_tn_bh_ar],
+                                 properties=props)
+        service_dict[nst.identifier] = False
+        service_list.append(nst)
+
+    def create_slice_ar(self, sdc, vendor) -> dict:
+        """Create Slice AR."""
+        # 10. create Slice_AR
+        logger.info("####################### create Slice_AR")
+
+        vfc = Vfc('AllottedResource')
+        vf_slice_ar = Vf(name=self.updated_name('Slice_AR'), category='Allotted Resource', subcategory='Allotted Resource', vendor=vendor)
+        vf_slice_ar.create()
+        if vf_slice_ar.status == const.DRAFT:
+            vf_slice_ar.add_resource(vfc)
+
+        for c in vf_slice_ar.components:
+            if c.name == 'AllottedResource 0':
+                cp = sdc.get_component_property(c, 'providing_service_invariant_uuid')
+                if cp:
+                    logger.info('declare input for property [%s]', cp)
+                    vf_slice_ar.declare_input(cp)
+                else:
+                    raise ParameterError('no property providing_service_invariant_uuid found')
+
+                cp = sdc.get_component_property(c, 'providing_service_uuid')
+                if cp:
+                    logger.info('declare input for property [%s]', cp)
+                    vf_slice_ar.declare_input(cp)
+                else:
+                    raise ParameterError('no property providing_service_uuid found')
+
+                break
+
+        sdc.onboard_vf(vf_slice_ar)
+        # AAI bug workaround: create Slice_ar in AAI DB before SO distribution, otherwise service will not be deployed to AAI succesfully
+        aai = AaiModel(invariant_id=vf_slice_ar.unique_uuid, model_type="resource", resource_version=vf_slice_ar.version)
+        aai.create(vf_slice_ar.name, vf_slice_ar.identifier, aai.invariant_id)
+        return vf_slice_ar
+
+    def create_an_slice_profiles(self, sdc, vf_slice_ar) -> dict:
+        """Create AN Slice profile."""
+        # 11.Create SliceProfile_AN_O2 Service Template
+        logger.info("####################### create SliceProfile_AN_O2 Service Template")
+        an_slice_profile = [Property('ipAddress', 'string'),
+                            Property('logicInterfaceId', 'string'),
+                            Property('nextHopInfo', 'string')]
+        complex_property = Property('anSP', 'org.openecomp.datatypes.SliceProfile')
+        srv_slice_profile_an_o2 = sdc.create_service_1(self.updated_name('SliceProfile_AN_O2'),
+                                                       'AN SliceProfile',
+                                                       properties=an_slice_profile,
+                                                       inputs=an_slice_profile,
+                                                       complex_input=complex_property,
+                                                       vnfs=[vf_slice_ar])
+        service_dict[srv_slice_profile_an_o2.identifier] = False
+        service_list.append(srv_slice_profile_an_o2)
+        return srv_slice_profile_an_o2
+
+    def create_tn_slice_profiles(self, sdc, vf_slice_ar) -> dict:
+        """Create TN Slice profile."""
+        # 12.Create SliceProfile_TN Service Template
+        logger.info('####################### create service SliceProfile_TN')
+        tn_slice_profile = [Property('jitter', 'string'),
+                            Property('latency', 'integer'),
+                            Property('pLMNIdList', 'string'),
+                            Property('sNSSAI', 'string'),
+                            Property('sST', 'integer'),
+                            Property('maxBandwidth', 'integer')]
+
+        srv_slice_profile_tn = sdc.create_service_1(self.updated_name('SliceProfile_TN'),
+                                                    'TN SliceProfile',
+                                                    vnfs=[vf_slice_ar],
+                                                    inputs=tn_slice_profile,
+                                                    properties=tn_slice_profile)
+        service_dict[srv_slice_profile_tn.identifier] = False
+        service_list.append(srv_slice_profile_tn)
+        return srv_slice_profile_tn
+
+    def create_cn_slice_profiles(self, sdc, vf_slice_ar) -> dict:
+        """Create CN Slice profile."""
+        # 13.Create SliceProfile_CN Service Template
+        logger.info('####################### create slice SliceProfile_CN')
+        cn_slice_profile = [Property('ipAddress', 'string'),
+                            Property('logicInterfaceId', 'string'),
+                            Property('nextHopInfo', 'string')]
+        srv_slice_profile_cn = sdc.create_service_1(self.updated_name('SliceProfile_CN'),
+                                                    'CN SliceProfile',
+                                                    vnfs=[vf_slice_ar],
+                                                    inputs=cn_slice_profile,
+                                                    properties=cn_slice_profile)
+        service_dict[srv_slice_profile_cn.identifier] = False
+        service_list.append(srv_slice_profile_cn)
+        return srv_slice_profile_cn
+
+    def create_service_profile(self, sdc, vf_slice_ar, srv_slice_profile_cn, srv_slice_profile_tn, srv_slice_profile_an_o2) -> dict:
+        """Create Slice profile."""
+        # 14.Create ServiceProfile_O2 Service Template
+        logger.info('####################### create service ServiceProfile O2')
+        service_props = Property('spProp', 'org.openecomp.datatypes.ServiceProfile')
+        srv_profile_o2 = sdc.create_service_1(self.updated_name('ServiceProfile_O2'),
+                                              'ServiceProfile',
+                                              properties=[service_props],
+                                              complex_input=service_props,
+                                              vnfs=[vf_slice_ar, srv_slice_profile_cn, srv_slice_profile_tn, srv_slice_profile_an_o2],
+                                              role='option2')
+        service_dict[srv_profile_o2.identifier] = False
+        service_list.append(srv_profile_o2)
+        return srv_profile_o2
+
+    def create_cst(self, sdc, srv_profile_o2) -> dict:
+        """Create CST."""
+        # 15.Create CST_O2 Service Template
+        logger.info('####################### create service CST O2')
+        cs_prop = Property('csProp', 'org.openecomp.datatypes.CSProperties')
+        cst = sdc.create_service_1(self.updated_name('CST_O2'),
+                                   'CST',
+                                   role='option2',
+                                   service_type='embb',
+                                   vnfs=[srv_profile_o2],
+                                   properties=[cs_prop],
+                                   complex_input=cs_prop)
+        service_dict[cst.identifier] = False
+        service_list.append(cst)
+        return cst
+
+    def updated_name(self, name) -> str:
+        """Adding suffix for the name."""
+        return name + self.suffix
+
+    @classmethod
+    def verify_distribution(cls) -> bool:
+        """Verify the distribution of all the services."""
+        for service in service_list:
+            logger.info('####################### verify service:%s', service.name)
+            if service_dict[service.identifier]:
+                continue
+            so_ready = False
+            aai_ready = False
+            result = service.get_distribution_status()
+            for element in result['distributionStatusList']:
+                if (element['omfComponentID'] == "SO-COpenSource-Env11" and (element['status'] == "DEPLOY_OK" or element['status'] == const.DOWNLOAD_OK)):
+                    so_ready = True
+                if (element['omfComponentID'] == "aai-ml" and element['status'] == "DEPLOY_OK"):
+                    aai_ready = True
+            if so_ready and aai_ready:
+                service_dict[service.identifier] = True
+                logger.info('####################### service %s distributed successfully to SO and AAI', service.name)
+
+        res = True
+        for value in service_dict.values():
+            res = res and value
+            logger.info('####################### res is:%s, value is:%s', str(res), str(value))
+        return res
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/so_preparation.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/so_preparation.py
new file mode 100644 (file)
index 0000000..14cb550
--- /dev/null
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Prepare SO for Network Slicing option2 test."""
+import logging
+import logging.config
+import os
+import subprocess
+from subprocess import check_output
+from onapsdk.configuration import settings
+
+# Set working dir as python script location
+abspath = os.path.abspath(__file__)
+dname = os.path.dirname(abspath)
+os.chdir(dname)
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("####################### Start SO Preparation")
+
+class SoPreparation():
+    """Can be used to prepare SO for Network Slicing usecase option2."""
+
+    @classmethod
+    def prepare_so(cls, cst_id, sp_id):
+        """Update So catalog db.
+
+        Args:
+            cst_id (str): The CST uuid of from the SDC Template creation step.
+            sp_id (str): The ServiceProfile uuid from the SDC Template creation step.
+        """
+        logger.info("####################### Start to update SO catalog DB")
+        cmd = "kubectl get secret/onap-mariadb-galera-db-root-password -n onap -o jsonpath={.data.password} | base64 --decode"
+        pw = check_output(cmd, shell=True).decode('utf-8')
+        #logger.info("####################### pass is:%s", pw)
+
+        # populate communication service actions
+        sql = f"INSERT INTO  \
+              catalogdb.service_recipe(ACTION, VERSION_STR, DESCRIPTION, ORCHESTRATION_URI, SERVICE_PARAM_XSD, \
+              RECIPE_TIMEOUT, SERVICE_TIMEOUT_INTERIM, SERVICE_MODEL_UUID) \
+              VALUES ('createInstance', '1', 'Custom recipe to create communication service-instance if no custom BPMN flow is found', \
+              '/mso/async/services/CreateCommunicationService', NULL, 180, NULL, '{cst_id}');"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        sql = f"INSERT INTO  \
+              catalogdb.service_recipe(ACTION, VERSION_STR, DESCRIPTION, ORCHESTRATION_URI, SERVICE_PARAM_XSD, \
+              RECIPE_TIMEOUT, SERVICE_TIMEOUT_INTERIM, SERVICE_MODEL_UUID) \
+              VALUES ('deleteInstance', '1', 'Custom recipe to delete communication service if no custom BPMN flow is found', \
+              '/mso/async/services/DeleteCommunicationService', NULL, 180, NULL, '{cst_id}');"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        sql = f"INSERT INTO  \
+              catalogdb.service_recipe(ACTION, VERSION_STR, DESCRIPTION, ORCHESTRATION_URI, SERVICE_PARAM_XSD, \
+              RECIPE_TIMEOUT, SERVICE_TIMEOUT_INTERIM, SERVICE_MODEL_UUID) \
+              VALUES ('activateInstance', '1.0', 'activate communication service', '/mso/async/services/ActivateCommunicationService', \
+              NULL, 180, NULL, '{cst_id}');"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        # populate slice service actions
+        sql = f"INSERT INTO  \
+              catalogdb.service_recipe(ACTION, VERSION_STR, DESCRIPTION, ORCHESTRATION_URI, SERVICE_PARAM_XSD, \
+              RECIPE_TIMEOUT, SERVICE_TIMEOUT_INTERIM, SERVICE_MODEL_UUID) \
+              VALUES ('createInstance', '1', 'Custom recipe to create slice service-instance if no custom BPMN flow is found', \
+              '/mso/async/services/CreateSliceService', NULL, 180, NULL, '{sp_id}');"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        sql = f"INSERT INTO  \
+              catalogdb.service_recipe(ACTION, VERSION_STR, DESCRIPTION, ORCHESTRATION_URI, SERVICE_PARAM_XSD, \
+              RECIPE_TIMEOUT, SERVICE_TIMEOUT_INTERIM, SERVICE_MODEL_UUID) \
+              VALUES ('deleteInstance', '1', 'Custom recipe to create slice service-instance if no custom BPMN flow is found', \
+              '/mso/async/services/DeleteSliceService', NULL, 180, NULL, '{sp_id}');"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        sql = f"INSERT INTO  \
+              catalogdb.service_recipe(ACTION, VERSION_STR, DESCRIPTION, ORCHESTRATION_URI, SERVICE_PARAM_XSD, \
+              RECIPE_TIMEOUT, SERVICE_TIMEOUT_INTERIM, SERVICE_MODEL_UUID) \
+              VALUES ('activateInstance', '1.0', 'Gr api recipe to activate service-instance', \
+              '/mso/async/services/ActivateSliceService', NULL, 180, NULL, '{sp_id}');"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        logger.info("####################### Start to copy subnetCapability.json to SO main pod")
+        so_pod = subprocess.run("kubectl get pods -n onap | awk '{print $1}' | grep  onap-so-[a-z0-9]*-[a-z0-9]*$", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+        cmd = f"kubectl cp ../resources/subnetCapability.json -n onap {so_pod}:/app"
+        check_output(cmd, shell=True).decode('utf-8')
+
+    @classmethod
+    def cleanup_so(cls, cst_id, sp_id):
+        """Clean up So configuration.
+
+        Args:
+            cst_id (str): The CST uuid of from the SDC Template creation step.
+            sp_id (str): The ServiceProfile uuid from the SDC Template creation step.
+        """
+        logger.info("####################### Start to clean up SO catalog DB")
+        cmd = "kubectl get secret/onap-mariadb-galera-db-root-password -n onap -o jsonpath={.data.password} | base64 --decode"
+        pw = check_output(cmd, shell=True).decode('utf-8')
+
+        # remove communication service actions
+        sql = f"Delete from  service_recipe where SERVICE_MODEL_UUID=\"{cst_id}\";"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        # remove slice service actions
+        sql = f"Delete from  service_recipe where SERVICE_MODEL_UUID=\"{sp_id}\";"
+        cmd = f"kubectl -n onap exec onap-mariadb-galera-0 -- mysql -uroot -p{pw} -D catalogdb -e \"{sql}\""
+        check_output(cmd, shell=True).decode('utf-8')
+
+        logger.info("####################### Start to remove subnetCapability.json to SO main pod")
+        so_pod = subprocess.run("kubectl get pods -n onap | awk '{print $1}' | grep  onap-so-[a-z0-9]*-[a-z0-9]*$", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+        cmd = f"kubectl -n onap exec {so_pod} -- rm -f /app/subnetCapability.json -n onap"
+        check_output(cmd, shell=True).decode('utf-8')
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/uui_preparation.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/preparation/uui_preparation.py
new file mode 100644 (file)
index 0000000..62895e0
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Update UUI configuration for Network Slicing option2 test."""
+import logging
+import logging.config
+import subprocess
+from subprocess import check_output
+from onapsdk.configuration import settings
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("####################### Start UUI Preparation")
+
+class UuiPreparation():
+    """Can be used to prepare UUI for Network Slicing usecase option2."""
+
+    @classmethod
+    def prepare_uui(cls, cst_uuid, cst_invariant_id):
+        """Register services to uui."""
+        logger.info("####################### Start to update uui settings")
+        uui_pod = subprocess.run("kubectl get pod -n onap | grep uui-server | awk '{print $1}' ", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+
+        cmd = f"kubectl exec -ti -n onap {uui_pod} -- sed -i 's/8ee5926d-720b-4bb2-86f9-d20e921c143b/{cst_uuid}/g' /home/uui/config/slicing.properties"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {uui_pod} -- sed -i 's/e75698d9-925a-4cdd-a6c0-edacbe6a0b51/{cst_invariant_id}/g' /home/uui/config/slicing.properties"
+        check_output(cmd, shell=True).decode('utf-8')
+
+    @classmethod
+    def cleanup_uui(cls, cst_uuid, cst_invariant_id):
+        """Rollback uui settings."""
+        logger.info("####################### Start to rollback uui settings")
+        uui_pod = subprocess.run("kubectl get pod -n onap | grep uui-server | awk '{print $1}' ", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
+
+        cmd = f"kubectl exec -ti -n onap {uui_pod} -- sed -i 's/{cst_uuid}/8ee5926d-720b-4bb2-86f9-d20e921c143b/g' /home/uui/config/slicing.properties"
+        check_output(cmd, shell=True).decode('utf-8')
+
+        cmd = f"kubectl exec -ti -n onap {uui_pod} -- sed -i 's/{cst_invariant_id}/e75698d9-925a-4cdd-a6c0-edacbe6a0b51/g' /home/uui/config/slicing.properties"
+        check_output(cmd, shell=True).decode('utf-8')
+        logger.info("####################### UUI settings rollback successfully")
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/eMBB.zip b/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/eMBB.zip
new file mode 100644 (file)
index 0000000..c8217c5
Binary files /dev/null and b/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/eMBB.zip differ
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/policies_option2.tar.gz b/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/policies_option2.tar.gz
new file mode 100644 (file)
index 0000000..f6c16cd
Binary files /dev/null and b/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/policies_option2.tar.gz differ
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/subnetCapability.json b/smo-install/test/pythonsdk/src/orantests/network_slicing/resources/subnetCapability.json
new file mode 100644 (file)
index 0000000..9da0846
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "AN_NF": {
+    "latency": 5,
+    "maxNumberofUEs": 200,
+    "maxThroughput": 90,
+    "termDensity": 40
+  },
+  "AN": {
+    "latency": 20,
+    "maxNumberofUEs": 100,
+    "maxThroughput": 150,
+    "termDensity": 50
+  },
+  "CN": {
+    "latency": 10,
+    "maxThroughput": 50,
+    "maxNumberofConns": 100
+  },
+  "TN_FH": {
+    "latency": 10,
+    "maxThroughput": 90
+  },
+  "TN_MH": {
+    "latency": 5,
+    "maxThroughput": 90
+  },
+  "TN_BH": {
+    "latency": 10,
+    "maxThroughput": 100
+  }
+}
\ No newline at end of file
diff --git a/smo-install/test/pythonsdk/src/orantests/network_slicing/test_network_slicing.py b/smo-install/test/pythonsdk/src/orantests/network_slicing/test_network_slicing.py
new file mode 100644 (file)
index 0000000..54fb735
--- /dev/null
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+###
+# ============LICENSE_START===================================================
+# ORAN SMO PACKAGE - PYTHONSDK TESTS
+# ================================================================================
+#  Copyright (C) 2022 AT&T Intellectual Property. All rights
+#                             reserved.
+# ============================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+#
+###
+"""Network Slicing option2 test module."""
+
+import logging
+import logging.config
+import pytest
+from onapsdk.configuration import settings
+from preparation.aai_preparation import AaiPreparation
+from preparation.oof_preparation import OofPreparation
+from preparation.sdc_preparation import SdcPreparation
+from preparation.so_preparation import SoPreparation
+from preparation.msb_preparation import MsbPreparation
+from preparation.uui_preparation import UuiPreparation
+
+logging.config.dictConfig(settings.LOG_CONFIG)
+logger = logging.getLogger("Test Network Slicing usecase Option2")
+sdc_template_suffix = ""
+sdcPreparation = SdcPreparation(sdc_template_suffix)
+soPreparation = SoPreparation()
+aaiPreparation = AaiPreparation()
+oofPreparation = OofPreparation()
+msbPreparation = MsbPreparation()
+uuiPreparation = UuiPreparation()
+
+@pytest.fixture(scope="module", autouse=True)
+def pre_config():
+    """Set the onap components before executing the tests."""
+    logger.info("Test class setup for Network Slicing usecase Option2")
+
+    logger.info("PreConfig Step1: Create SDC Templates")
+    res = sdcPreparation.prepare_sdc()
+    cst_id = res[0]
+    cst_invariant_id = res[1]
+    sp_id = res[2]
+    logger.info("SDC Templates created successfully, cst_id:" + cst_id + "; sp_id:" + sp_id + "; cst_invariant_id:" + cst_invariant_id)
+
+    logger.info("PreConfig Step2: AAI Configuration")
+    aaiPreparation.prepare_aai()
+    logger.info("AAI Configured successfully")
+
+    #cst_id = "test"
+    #cst_invariant_id = "test"
+    #sp_id = "03d396bf-0246-4d48-817a-b219cc2e7a5a"
+    logger.info("PreConfig Step3: SO Configuration")
+    soPreparation.prepare_so(cst_id, sp_id)
+    logger.info("SO Configured successfully")
+
+    logger.info("PreConfig Step4: OOF Configuration - Optimization Policy Creation")
+    oofPreparation.prepare_oof(sdcPreparation.updated_name("EmbbNst_O2"), sdcPreparation.updated_name("EmbbAn_NF"), sdcPreparation.updated_name("Tn_ONAP_internal_BH"))
+    logger.info("OOF Configured successfully")
+
+    logger.info("PreConfig Step5: MSB Configuration - Create msb services")
+    msbPreparation.prepare_msb()
+    logger.info("MSB Configured successfully")
+
+    logger.info("PreConfig Step6: UUI Configuration - Update uui settings")
+    uuiPreparation.prepare_uui(cst_id, cst_invariant_id)
+    logger.info("UUI Configured successfully")
+
+    ### Cleanup code
+    yield
+    logger.info("Start to cleanup user case specific configurations")
+    #aaiPreparation.cleanup_aai()
+    #soPreparation.cleanup_so()
+    #oofPreparation.cleanup_oof()
+    #msbPreparation.cleanup_msb()
+    #uuiPreparation.cleanup_uui(cst_id, cst_invariant_id)
+    logger.info("Test Session cleanup done")
+
+def test_network_slicing_option2():
+    """The Network Slicing option2 usecase."""
+    logger.info("Good")
diff --git a/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-1.0.0.tgz b/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-1.0.0.tgz
new file mode 100755 (executable)
index 0000000..b82abf2
Binary files /dev/null and b/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-1.0.0.tgz differ
diff --git a/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-ics-version-1.0.0.tgz b/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-ics-version-1.0.0.tgz
new file mode 100755 (executable)
index 0000000..b78e502
Binary files /dev/null and b/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/odu-app-ics-version-1.0.0.tgz differ
diff --git a/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/oru-app-1.0.0.tgz b/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/oru-app-1.0.0.tgz
new file mode 100644 (file)
index 0000000..d1c8117
Binary files /dev/null and b/smo-install/test/pythonsdk/src/orantests/oran_tests/resources/cl-test-helm-chart/oru-app-1.0.0.tgz differ
@@ -41,7 +41,7 @@ class ClCommissioningUtils():
     def clean_instance(cls, usecase_name):
         """Clean template instance."""
         clamp.change_instance_status("UNINITIALISED", usecase_name, "1.2.3")
-        wait(lambda: clamp.verify_instance_status("UNINITIALISED"), sleep_seconds=5, timeout_seconds=60,
+        wait(lambda: clamp.verify_instance_status("UNINITIALISED"), sleep_seconds=5, timeout_seconds=300,
              waiting_for="Clamp instance switches to UNINITIALISED")
 
         logger.info("Delete Instance")
@@ -63,7 +63,7 @@ class ClCommissioningUtils():
 
         logger.info("Change Instance Status to PASSIVE")
         clamp.change_instance_status("PASSIVE", usecase_name, "1.2.3")
-        wait(lambda: clamp.verify_instance_status("PASSIVE"), sleep_seconds=5, timeout_seconds=60,
+        wait(lambda: clamp.verify_instance_status("PASSIVE"), sleep_seconds=5, timeout_seconds=300,
              waiting_for="Clamp instance switches to PASSIVE")
 
         return True
@@ -23,7 +23,7 @@
 ###
 """Closed Loop Apex usecase tests module."""
 # This usecase has limitations due to Clamp issue.
-# 1. make sure using the policy-clamp-be version 6.2.0-snapshot-latest at this the moment
+# 1. make sure using the policy-k8s-participant version is higher than 6.3.0
 import time
 import logging.config
 import subprocess
@@ -46,10 +46,8 @@ logger = logging.getLogger("test Control Loops for Clamp K8S usecase")
 clcommissioning_utils = ClCommissioningUtils()
 clamp = ClampToscaTemplate(settings.CLAMP_BASICAUTH)
 
-chartmuseum_port = "8080"
 usecase_name = "script_usecase"
 chartmuseum_ip = "http://test-chartmuseum.test:8080"
-global app_name
 
 @pytest.fixture(autouse=True)
 def setup_simulators(request):
@@ -62,9 +60,7 @@ def setup_simulators(request):
     logger.info("Add the remote repo to Clamp k8s pod")
     k8s_pod = subprocess.run("kubectl get pods -n onap | grep k8s | awk '{print $1}'", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
 
-    repo_url = subprocess.run("kubectl get services -n test | grep test-chartmuseum | awk '{print $3}'", shell=True, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()+":8080"
-    logger.info("k8s: %s, repo_url:%s", k8s_pod, repo_url)
-    cmd = f"kubectl exec -it -n onap {k8s_pod} -- sh -c \"helm repo add chartmuseum http://{repo_url}\""
+    cmd = f"kubectl exec -it -n onap {k8s_pod} -- sh -c \"helm repo add chartmuseum http://test-chartmuseum.test:8080\""
     check_output(cmd, shell=True).decode('utf-8')
     cmd = f"kubectl exec -it -n onap {k8s_pod} -- sh -c \"helm repo update\""
     check_output(cmd, shell=True).decode('utf-8')
@@ -78,7 +74,7 @@ def setup_simulators(request):
     yield
     # Finish and delete the cl instance
     clcommissioning_utils.clean_instance(usecase_name)
-    wait(lambda: is_rapp_down(app_name), sleep_seconds=5, timeout_seconds=60, waiting_for="Rapp is down")
+    wait(lambda: is_rapp_down(pytest.app_name), sleep_seconds=5, timeout_seconds=60, waiting_for="Rapp is down")
     # Remove the remote repo to Clamp k8s pod
     cmd = f"kubectl exec -it -n onap {k8s_pod} -- sh -c \"helm repo remove chartmuseum\""
     check_output(cmd, shell=True).decode('utf-8')
@@ -147,45 +143,42 @@ def is_rapp_down(appname) -> bool:
     return False
 
 def test_cl_oru_app_deploy():
+    """The Closed Loop O-RU Fronthaul Recovery usecase Apex version."""
     chart_version = "1.0.0"
     chart_name = "oru-app"
-    release_name = "oru-app"
-    global app_name
-    app_name = chart_name
-    """The Closed Loop O-RU Fronthaul Recovery usecase Apex version."""
+    release_name = "nonrtric"
+    pytest.app_name = chart_name
     logger.info("Upload tosca to commissioning")
-    commissioning_payload = jinja_env().get_template("commission_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartmuseumPort=chartmuseum_port, chartVersion=chart_version, chartName=chart_name, releaseName=release_name)
-    instance_payload = jinja_env().get_template("create_instance_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartmuseumPort=chartmuseum_port, chartVersion=chart_version, chartName=chart_name, releaseName=release_name, instanceName=usecase_name)
+    commissioning_payload = jinja_env().get_template("commission_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartVersion=chart_version, chartName=chart_name, releaseName=release_name)
+    instance_payload = jinja_env().get_template("create_instance_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartVersion=chart_version, chartName=chart_name, releaseName=release_name, instanceName=usecase_name)
     assert clcommissioning_utils.create_instance(usecase_name, commissioning_payload, instance_payload) is True
 
     logger.info("Check if oru-app is up")
     wait(lambda: is_rapp_up(chart_name), sleep_seconds=5, timeout_seconds=300, waiting_for="Oru app to be up")
 
 def test_cl_odu_app_smo_deploy():
+    """The O-DU Slice Assurance SMO Version use case."""
     chart_version = "1.0.0"
     chart_name = "odu-app"
     release_name = "odu-app"
-    global app_name
-    app_name = chart_name
-    """The O-DU Slice Assurance SMO Version use case."""
+    pytest.app_name = chart_name
     logger.info("Upload tosca to commissioning")
-    commissioning_payload = jinja_env().get_template("commission_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartmuseumPort=chartmuseum_port, chartVersion=chart_version, chartName=chart_name, releaseName=release_name)
-    instance_payload = jinja_env().get_template("create_instance_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartmuseumPort=chartmuseum_port, chartVersion=chart_version, chartName=chart_name, releaseName=release_name, instanceName=usecase_name)
+    commissioning_payload = jinja_env().get_template("commission_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartVersion=chart_version, chartName=chart_name, releaseName=release_name)
+    instance_payload = jinja_env().get_template("create_instance_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartVersion=chart_version, chartName=chart_name, releaseName=release_name, instanceName=usecase_name)
     assert clcommissioning_utils.create_instance(usecase_name, commissioning_payload, instance_payload) is True
 
     logger.info("Check if odu-app smo version is up")
     wait(lambda: is_rapp_up(chart_name), sleep_seconds=5, timeout_seconds=300, waiting_for="Odu app smo version to be up")
 
 def test_cl_odu_app_ics_deploy():
+    """The O-DU Slice Assurance ICS Version use case."""
     chart_version = "1.0.0"
     chart_name = "odu-app-ics-version"
     release_name = "odu-app-ics-version"
-    global app_name
-    app_name = chart_name
-    """The O-DU Slice Assurance ICS Version use case."""
+    pytest.app_name = chart_name
     logger.info("Upload tosca to commissioning")
-    commissioning_payload = jinja_env().get_template("commission_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartmuseumPort=chartmuseum_port, chartVersion=chart_version, chartName=chart_name, releaseName=release_name)
-    instance_payload = jinja_env().get_template("create_instance_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartmuseumPort=chartmuseum_port, chartVersion=chart_version, chartName=chart_name, releaseName=release_name, instanceName=usecase_name)
+    commissioning_payload = jinja_env().get_template("commission_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartVersion=chart_version, chartName=chart_name, releaseName=release_name)
+    instance_payload = jinja_env().get_template("create_instance_k8s.json.j2").render(chartmuseumIp=chartmuseum_ip, chartVersion=chart_version, chartName=chart_name, releaseName=release_name, instanceName=usecase_name)
     assert clcommissioning_utils.create_instance(usecase_name, commissioning_payload, instance_payload) is True
 
     logger.info("Check if odu-app ics version is up")
index 3931d70..53b7696 100644 (file)
@@ -8,7 +8,7 @@ deps =
     pytest==6.2.5
     pytest-cov==2.10.1
     pydocstyle==5.1.1
-    onapsdk==9.0.0
+    onapsdk==9.4.0
     waiting==1.4.1
     markupsafe==2.0.1
 passenv = *
@@ -22,7 +22,7 @@ setenv =
 
 [testenv:pylint]
 basepython=python3.8
-commands = pylint --disable=invalid-name,line-too-long,too-few-public-methods,import-error,unnecessary-lambda src/
+commands = pylint --ignore-imports=yes --min-similarity-lines=5 --disable=invalid-name,line-too-long,too-few-public-methods,import-error,unnecessary-lambda,too-many-arguments src/
 setenv =
     PYTHONPATH = $PYTHONPATH:{toxinidir}/src
     ONAP_PYTHON_SDK_SETTINGS=orantests.configuration.settings
@@ -36,7 +36,14 @@ setenv =
 
 [testenv:oran-tests]
 basepython=python3.8
-commands = pytest -v --junit-xml=reports/junit/oran-tests.xml src/orantests/
+commands = pytest -v --junit-xml=reports/junit/oran-tests.xml src/orantests/oran_tests
 setenv =
     PYTHONPATH = $PYTHONPATH:{toxinidir}/src
     ONAP_PYTHON_SDK_SETTINGS=orantests.configuration.settings
+
+[testenv:ns-tests]
+basepython=python3.8
+commands = pytest -v --junit-xml=reports/junit/nt-tests.xml src/orantests/network_slicing
+setenv =
+    PYTHONPATH = $PYTHONPATH:{toxinidir}/src
+    ONAP_PYTHON_SDK_SETTINGS=orantests.configuration.settings
\ No newline at end of file
index c2bb6f7..3db2e12 100644 (file)
@@ -28,7 +28,7 @@ ifneq "$(findstring v3,$(HELM_VER))" "v3"
        HELM_VER := $(shell $(HELM_BIN) version -c --template "{{.Client.SemVer}}")
 endif
 
-# use this if you would like to push onap charts to repo with other name
+# use this if you would like to cm-push onap charts to repo with other name
 # WARNING: Helm v3+ only
 # WARNING: Make sure to edit also requirements files
 HELM_REPO := local
@@ -82,7 +82,7 @@ lint-%: dep-%
 package-%: lint-%
        @mkdir -p $(PACKAGE_DIR)
 ifeq "$(findstring v3,$(HELM_VER))" "v3"
-       @if [ -f $*/Chart.yaml ]; then PACKAGE_NAME=$$($(HELM_BIN) package -d $(PACKAGE_DIR) $* | cut -d":" -f2) && $(HELM_BIN) push -f $$PACKAGE_NAME $(HELM_REPO); fi
+       @if [ -f $*/Chart.yaml ]; then PACKAGE_NAME=$$($(HELM_BIN) package -d $(PACKAGE_DIR) $* | cut -d":" -f2) && $(HELM_BIN) cm-push -f $$PACKAGE_NAME $(HELM_REPO); fi
 else
        @if [ -f $*/Chart.yaml ]; then $(HELM_BIN) package -d $(PACKAGE_DIR) $*; fi
        @$(HELM_BIN) repo index $(PACKAGE_DIR)