added oran ric test head 00/1300/1
authorRohan Patel <rp5811@att.com>
Thu, 31 Oct 2019 20:19:21 +0000 (16:19 -0400)
committerRohan Patel <rp5811@att.com>
Thu, 31 Oct 2019 20:19:49 +0000 (16:19 -0400)
Change-Id: I7a365e056118cc7500bb18791f7e09ac332294ba
Signed-off-by: Rohan Patel <rp5811@att.com>
15 files changed:
oran-ric-test-head/Dockerfile [new file with mode: 0644]
oran-ric-test-head/Jenkinsfile [new file with mode: 0644]
oran-ric-test-head/LICENSE.txt [new file with mode: 0644]
oran-ric-test-head/config.json [new file with mode: 0644]
oran-ric-test-head/helm/ric-test-head/.helmignore [new file with mode: 0644]
oran-ric-test-head/helm/ric-test-head/Chart.yaml [new file with mode: 0644]
oran-ric-test-head/helm/ric-test-head/templates/deployment.yaml [new file with mode: 0644]
oran-ric-test-head/helm/ric-test-head/templates/service.yaml [new file with mode: 0644]
oran-ric-test-head/helm/ric-test-head/values.yaml [new file with mode: 0644]
oran-ric-test-head/mock_server/index.js [new file with mode: 0644]
oran-ric-test-head/mock_server/package.json [new file with mode: 0644]
oran-ric-test-head/opt/cert/certInfo.txt [new file with mode: 0644]
oran-ric-test-head/pip-requirements.txt [new file with mode: 0644]
oran-ric-test-head/ric-test-head.py [new file with mode: 0644]
oran-ric-test-head/workflows/Deploy_xAPP_Test.bpmn [new file with mode: 0644]

diff --git a/oran-ric-test-head/Dockerfile b/oran-ric-test-head/Dockerfile
new file mode 100644 (file)
index 0000000..86f740d
--- /dev/null
@@ -0,0 +1,13 @@
+FROM python:2.7\r
+\r
+RUN python --version\r
+\r
+ADD pip-requirements.txt pip-requirements.txt\r
+ADD ric-test-head.py ric-test-head.py\r
+ADD config.json config.json\r
+\r
+RUN mkdir -p /otf/logs\r
+\r
+RUN python -m pip install -r pip-requirements.txt\r
+\r
+ENTRYPOINT ["python", "ric-test-head.py"]\r
diff --git a/oran-ric-test-head/Jenkinsfile b/oran-ric-test-head/Jenkinsfile
new file mode 100644 (file)
index 0000000..f5defc2
--- /dev/null
@@ -0,0 +1,141 @@
+#!/usr/bin/env groovy\r
+\r
+\r
+properties([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [\r
+        [$class: 'hudson.model.StringParameterDefinition', name: 'PHASE', defaultValue: "BUILD"],\r
+        [$class: 'hudson.model.StringParameterDefinition', name: 'ENV', defaultValue: "dev"],\r
+        [$class: 'hudson.model.StringParameterDefinition', name: 'MECHID', defaultValue: "m13591_otf_dev"],\r
+        [$class: 'hudson.model.StringParameterDefinition', name: 'KUBE_CONFIG', defaultValue: "kubeConfig-dev"],\r
+        [$class: 'hudson.model.StringParameterDefinition', name: 'TILLER_NAMESPACE', defaultValue: "com-att-ecomp-otf-dev"]\r
+]]])\r
+\r
+\r
+echo "Build branch: ${env.BRANCH_NAME}"\r
+\r
+node("docker"){\r
+       stage 'Checkout'\r
+       checkout scm\r
+       PHASES=PHASE.tokenize( '_' );\r
+       echo "PHASES : " + PHASES\r
+\r
+\r
+       ARTIFACT_ID="ric-test-head";\r
+       VERSION="Camile.2.0";\r
+       NAMESPACE="com.att.ecomp.otf"\r
+       DOCKER_REGISTRY="dockercentral.it.att.com:5100"\r
+\r
+  if( ENV.equalsIgnoreCase("dev") ){\r
+    IMAGE_NAME=DOCKER_REGISTRY + "/" + NAMESPACE + ".dev" + "/" + ARTIFACT_ID +  ":" + VERSION\r
+\r
+  }\r
+  if( ENV.equalsIgnoreCase("prod") || ENV.equalsIgnoreCase("prod-dr")){\r
+    IMAGE_NAME=DOCKER_REGISTRY + "/" + NAMESPACE + ".prod" + "/" + ARTIFACT_ID +  ":" + VERSION\r
+\r
+  }\r
+\r
+  if( ENV.equalsIgnoreCase("st") ){\r
+    IMAGE_NAME=DOCKER_REGISTRY + "/" + NAMESPACE + ".st" + "/" + ARTIFACT_ID +  ":" + VERSION\r
+\r
+  }\r
+\r
+       echo "Artifact: " + IMAGE_NAME\r
+\r
+       withEnv(["PATH=${env.PATH}:${env.WORKSPACE}/linux-amd64", "HELM_HOME=${env.WORKSPACE}"]) {\r
+\r
+               echo "PATH=${env.PATH}"\r
+               echo "HELM_HOME=${env.HELM_HOME}"\r
+\r
+               if (PHASES.contains("BUILD")){\r
+\r
+                       stage 'Publish Artifact'\r
+\r
+                               withCredentials([usernamePassword(credentialsId: MECHID, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {\r
+\r
+                               echo "Artifact: " + IMAGE_NAME\r
+\r
+                               sh """\r
+                                       docker login $DOCKER_REGISTRY --username $USERNAME --password $PASSWORD\r
+                                       docker build -t $IMAGE_NAME .\r
+                                       docker push $IMAGE_NAME\r
+                               """\r
+                               }\r
+\r
+               }\r
+\r
+               if (PHASES.contains("DEPLOY") || PHASES.contains("UNDEPLOY")) {\r
+\r
+                       stage 'Init Helm'\r
+\r
+                       //check if helm exists if not install\r
+                       if(fileExists('linux-amd64/helm')){\r
+                               sh """\r
+                                       echo "helm is already installed"\r
+                               """\r
+                       }\r
+                       else{\r
+                       //download helm\r
+                               sh """\r
+                                       echo "installing helm"\r
+                                       wget  https://storage.googleapis.com/kubernetes-helm/helm-v2.14.3-linux-amd64.tar.gz\r
+                                       tar -xf helm-v2.14.3-linux-amd64.tar.gz\r
+                                       rm helm-v2.14.3-linux-amd64.tar.gz\r
+                               """\r
+                       }\r
+\r
+                       withCredentials([file(credentialsId: KUBE_CONFIG, variable: 'KUBECONFIG')]) {\r
+\r
+                               dir('helm'){\r
+                               //check if charts are valid, and then perform dry run, if successful then upgrade/install charts\r
+\r
+                                       if (PHASES.contains("UNDEPLOY") ) {\r
+                                               stage 'Undeploy'\r
+\r
+                                               sh """\r
+                                                       helm delete --tiller-namespace=$TILLER_NAMESPACE --purge $ARTIFACT_ID\r
+                                               """\r
+                                       }\r
+\r
+                               //NOTE Double quotes are used below to access groovy variables like artifact_id and tiller_namespace\r
+                       if (PHASES.contains("DEPLOY") ){\r
+                               stage 'Deploy'\r
+                                                       withCredentials([usernamePassword(credentialsId: MECHID, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {\r
+\r
+                                                               sh """\r
+                                                                       echo "Validate Yaml"\r
+                                                                       helm lint $ARTIFACT_ID\r
+\r
+                                                                       echo "View Helm Templates"\r
+                                                                       helm template $ARTIFACT_ID --set appName=$ARTIFACT_ID \\r
+                  --set appName=$ARTIFACT_ID \\r
+                  --set version=$VERSION  \\r
+                  --set env=$ENV \\r
+                  --set image=$IMAGE_NAME \\r
+                  --set namespace=$TILLER_NAMESPACE\r
+\r
+                                                                       echo "Perform Dry Run Of Install"\r
+                                                                       helm upgrade --tiller-namespace=$TILLER_NAMESPACE --install --dry-run $ARTIFACT_ID $ARTIFACT_ID \\r
+                  --set appName=$ARTIFACT_ID \\r
+                  --set version=$VERSION  \\r
+                  --set env=$ENV \\r
+                  --set image=$IMAGE_NAME \\r
+                  --set namespace=$TILLER_NAMESPACE\r
+\r
+\r
+                                                                       echo "Helm Install/Upgrade"\r
+                                                               helm upgrade --tiller-namespace=$TILLER_NAMESPACE --install $ARTIFACT_ID $ARTIFACT_ID \\r
+                    --set appName=$ARTIFACT_ID \\r
+                    --set version=$VERSION  \\r
+                    --set env=$ENV \\r
+                    --set image=$IMAGE_NAME \\r
+                    --set namespace=$TILLER_NAMESPACE\r
+\r
+                                                               """\r
+                                                       }\r
+                       }\r
+\r
+                               }\r
+                       }\r
+       }\r
+\r
+       }\r
+}\r
diff --git a/oran-ric-test-head/LICENSE.txt b/oran-ric-test-head/LICENSE.txt
new file mode 100644 (file)
index 0000000..aa73a11
--- /dev/null
@@ -0,0 +1,28 @@
+Unless otherwise specified, all software contained herein is licensed\r
+under the Apache License, Version 2.0 (the "Software License");\r
+you may not use this software except in compliance with the Software\r
+License. You may obtain a copy of the Software License at\r
+\r
+http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+Unless required by applicable law or agreed to in writing, software\r
+distributed under the Software License is distributed on an "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+See the Software License for the specific language governing permissions\r
+and limitations under the Software License.\r
+\r
+\r
+\r
+Unless otherwise specified, all documentation contained herein is licensed\r
+under the Creative Commons License, Attribution 4.0 Intl. (the\r
+"Documentation License"); you may not use this documentation except in\r
+compliance with the Documentation License. You may obtain a copy of the\r
+Documentation License at\r
+\r
+https://creativecommons.org/licenses/by/4.0/\r
+\r
+Unless required by applicable law or agreed to in writing, documentation\r
+distributed under the Documentation License is distributed on an "AS IS"\r
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+implied. See the Documentation License for the specific language governing\r
+permissions and limitations under the Documentation License.
\ No newline at end of file
diff --git a/oran-ric-test-head/config.json b/oran-ric-test-head/config.json
new file mode 100644 (file)
index 0000000..95e4359
--- /dev/null
@@ -0,0 +1,10 @@
+{\r
+  "base_address": "http://localhost:3000",\r
+  "actions_path": {\r
+    "alive": "/appmgr/ric/v1/health/alive",\r
+    "ready": "/appmgr/ric/v1/health/ready",\r
+    "list": "/appmgr/ric/v1/xapps",\r
+    "deploy": "/appmgr/ric/v1/xapps",\r
+    "delete": "/appmgr/ric/v1/xapps/"\r
+   }\r
+}
\ No newline at end of file
diff --git a/oran-ric-test-head/helm/ric-test-head/.helmignore b/oran-ric-test-head/helm/ric-test-head/.helmignore
new file mode 100644 (file)
index 0000000..daebc7d
--- /dev/null
@@ -0,0 +1,21 @@
+# Patterns to ignore when building packages.\r
+# This supports shell glob matching, relative path matching, and\r
+# negation (prefixed with !). Only one pattern per line.\r
+.DS_Store\r
+# Common VCS dirs\r
+.git/\r
+.gitignore\r
+.bzr/\r
+.bzrignore\r
+.hg/\r
+.hgignore\r
+.svn/\r
+# Common backup files\r
+*.swp\r
+*.bak\r
+*.tmp\r
+*~\r
+# Various IDEs\r
+.project\r
+.idea/\r
+*.tmproj\r
diff --git a/oran-ric-test-head/helm/ric-test-head/Chart.yaml b/oran-ric-test-head/helm/ric-test-head/Chart.yaml
new file mode 100644 (file)
index 0000000..f26e1ae
--- /dev/null
@@ -0,0 +1,5 @@
+apiVersion: v1\r
+appVersion: "1.0"\r
+description: A Helm chart for the Ping Server Virtual Test Head \r
+name: oran-ric-test-head\r
+version: 0.0.1\r
diff --git a/oran-ric-test-head/helm/ric-test-head/templates/deployment.yaml b/oran-ric-test-head/helm/ric-test-head/templates/deployment.yaml
new file mode 100644 (file)
index 0000000..4c38c37
--- /dev/null
@@ -0,0 +1,113 @@
+apiVersion: extensions/v1beta1\r
+kind: Deployment\r
+metadata:\r
+  name: {{ .Values.appName}}\r
+  namespace: {{.Values.namespace}}\r
+  labels:\r
+    app: {{ .Values.appName}}\r
+    version: {{.Values.version}}\r
+spec:\r
+  revisionHistoryLimit: 1\r
+  minReadySeconds: 10\r
+  strategy:\r
+  # indicate which strategy we want for rolling update\r
+    type: RollingUpdate\r
+    rollingUpdate:\r
+      maxSurge: 0\r
+      maxUnavailable: 1\r
+  replicas: {{ .Values.replicas}}\r
+  selector:\r
+    matchLabels:\r
+      app: {{ .Values.appName}}\r
+      version: {{.Values.version}}\r
+  template:\r
+    metadata:\r
+      labels:\r
+        app: {{ .Values.appName}}\r
+        version: {{.Values.version}}\r
+    spec:\r
+      serviceAccount: default\r
+      volumes:\r
+      - name: {{ .Values.appName}}-cert-volume\r
+        secret:\r
+          secretName: {{.Values.sharedCert}}\r
+          optional: true\r
+          items:\r
+          - key: PEM_CERT\r
+            path: otf.pem\r
+          - key: PEM_KEY\r
+            path: privateKey.pem\r
+      {{ if or (eq .Values.env "st") (eq .Values.env "prod-dr")}}\r
+      {{else}}\r
+      - name: logging-pvc\r
+        persistentVolumeClaim:\r
+          {{if eq .Values.env "prod"}}\r
+          claimName: {{ .Values.pvc.prod | quote }}\r
+          {{ else }}\r
+          claimName: {{ .Values.pvc.dev | quote }}\r
+          {{ end }}\r
+      {{end}}\r
+      containers:\r
+      - name: {{ .Values.appName}}\r
+        image: {{ .Values.image}}\r
+        imagePullPolicy: Always\r
+        ports:\r
+        - name: http\r
+          containerPort: 5000\r
+          nodePort: {{.Values.nodePort}}\r
+          protocol: TCP\r
+        {{ if eq .Values.env "st"}}\r
+        resources:\r
+          limits: \r
+            memory: "512Mi"\r
+            cpu: "500m"\r
+          requests:\r
+            memory: "256Mi"\r
+            cpu: "100m"\r
+        {{else}}   \r
+        resources:\r
+          limits:\r
+            memory: "1Gi"\r
+            cpu: "1"\r
+          requests:\r
+            memory: "1Gi"\r
+            cpu: "1"\r
+        {{end}}\r
+        env:\r
+        - name: NAMESPACE\r
+          value: {{.Values.namespace}}\r
+        - name: APP_NAME\r
+          value: {{ .Values.appName}}\r
+        - name: APP_VERSION\r
+          value: {{.Values.version}}\r
+        volumeMounts:\r
+        - name: {{.Values.appName}}-cert-volume\r
+          mountPath: /opt/cert\r
+        {{ if or (eq .Values.env "st") (eq .Values.env "prod-dr")}}\r
+        {{else}}\r
+        - name: logging-pvc\r
+          mountPath: "/otf/logs"\r
+        {{end}}  \r
+        livenessProbe:\r
+          httpGet:\r
+            path: {{.Values.health}}\r
+            port: http\r
+            scheme: HTTP\r
+            httpHeaders:\r
+              - name: X-Custom-Header\r
+                value: Alive\r
+          initialDelaySeconds: 30\r
+          timeoutSeconds: 30\r
+          periodSeconds: 30\r
+        readinessProbe:\r
+          httpGet:\r
+            path: {{.Values.health}}\r
+            port: http\r
+            scheme: HTTP\r
+            httpHeaders:\r
+              - name: X-Custom-Header\r
+                value: Ready\r
+          initialDelaySeconds: 30\r
+          timeoutSeconds: 30\r
+          periodSeconds: 30\r
+      restartPolicy: Always\r
diff --git a/oran-ric-test-head/helm/ric-test-head/templates/service.yaml b/oran-ric-test-head/helm/ric-test-head/templates/service.yaml
new file mode 100644 (file)
index 0000000..f3bcfab
--- /dev/null
@@ -0,0 +1,18 @@
+apiVersion: v1\r
+kind: Service\r
+metadata:\r
+  name: {{ .Values.appName }}\r
+  namespace: {{ .Values.namespace}}\r
+  labels:\r
+    app: {{ .Values.appName }}\r
+    version: {{ .Values.version}}\r
+spec:\r
+  type: NodePort\r
+  ports:\r
+  - name: http\r
+    port: 5000\r
+    protocol: TCP\r
+    nodePort: {{ .Values.nodePort}}\r
+  selector:\r
+    app: {{ .Values.appName }}\r
+    version: {{ .Values.version}}\r
diff --git a/oran-ric-test-head/helm/ric-test-head/values.yaml b/oran-ric-test-head/helm/ric-test-head/values.yaml
new file mode 100644 (file)
index 0000000..6c5d067
--- /dev/null
@@ -0,0 +1,12 @@
+appName: ric-test-head\r
+env: dev\r
+version: 0.0.1-SNAPSHOT\r
+image: ric-test-head:0.0.1-SNAPSHOT\r
+namespace: org-oran-otf\r
+nodePort: 32323\r
+replicas: 1\r
+health : /otf/vth/oran/v1/health\r
+sharedCert: otf-cert-secret-builder\r
+pvc:\r
+  dev: org-oran-otf-dev-logs-pv\r
+  prod: org-oran-otf-prod-logs-pv\r
diff --git a/oran-ric-test-head/mock_server/index.js b/oran-ric-test-head/mock_server/index.js
new file mode 100644 (file)
index 0000000..255591a
--- /dev/null
@@ -0,0 +1,31 @@
+const express = require('express')\r
+const app = express()\r
+const port = 3000\r
+\r
+app.get('/', (req, res) => res.send('Hello World!'))\r
+\r
+app.get('/appmgr/ric/v1/health/ready',function(req,res){\r
+    res.sendStatus(200)\r
+})\r
+\r
+app.get('/appmgr/ric/v1/health/alive',function(req,res){\r
+    res.sendStatus(200)\r
+})\r
+\r
+app.get('/appmgr/ric/v1/xapps',function(req,res){\r
+    res.status(200)\r
+    res.send([{"name":"admin-xapp","status":"deployed","version":"1.0","instances":null},{"name":"mcxapp","status":"deployed","version":"1.0","instances":[{"name":"mcxapp-649d7494-h5tjb","status":"running","ip":"service-ricxapp-mcxapp-rmr.ricxapp","port":4560,"txMessages":null,"rxMessages":["RIC_SUB_RESP","RIC_SUB_FAILURE","RIC_SUB_DEL_RESP","RIC_SUB_DEL_FAILURE","RIC_INDICATION"]}]},{"name":"ueec","status":"deployed","version":"1.0","instances":[{"name":"ueec-6675694b75-jtnz6","status":"running","ip":"service-ricxapp-ueec-rmr.ricxapp","port":4560,"txMessages":["RIC_SUB_REQ","RIC_SUB_DEL_REQ"],"rxMessages":["RIC_SUB_RESP","RIC_SUB_FAILURE","RIC_SUB_DEL_RESP","RIC_SUB_DEL_FAILURE","RIC_INDICATION"]}]}])\r
+})\r
+\r
+app.post('/appmgr/ric/v1/xapps', function(req,res){\r
+    res.statusMessage = 'Created'\r
+    res.status(201)\r
+    res.send({"result_output":{"name":"anr","status":"deployed","version":"1.0","instances":[{"name":"anr-7d4c47b4bb-jlslm","status":"running","ip":"service-ricxapp-anr-rmr.ricxapp","port":4560,"txMessages":null,"rxMessages":["RIC_SGNB_ADDITION_REQ","RIC_RRC_TRANSFER"]}]}})\r
+})\r
+\r
+app.delete('/appmgr/ric/v1/xapps/:name',function(req,res){\r
+    res.sendStatus(204)\r
+})\r
+\r
+app.listen(port, () => console.log(`Example app listening on port ${port}!`))\r
+\r
diff --git a/oran-ric-test-head/mock_server/package.json b/oran-ric-test-head/mock_server/package.json
new file mode 100644 (file)
index 0000000..f699513
--- /dev/null
@@ -0,0 +1,14 @@
+{\r
+  "name": "mock_server",\r
+  "version": "1.0.0",\r
+  "description": "mock server for RIC",\r
+  "main": "index.js",\r
+  "scripts": {\r
+    "test": "echo \"Error: no test specified\" && exit 1"\r
+  },\r
+  "author": "",\r
+  "license": "ISC",\r
+  "dependencies": {\r
+    "express": "^4.17.1"\r
+  }\r
+}\r
diff --git a/oran-ric-test-head/opt/cert/certInfo.txt b/oran-ric-test-head/opt/cert/certInfo.txt
new file mode 100644 (file)
index 0000000..0799b0b
--- /dev/null
@@ -0,0 +1 @@
+add certs here. requires two pem files (Cert and key)\r
diff --git a/oran-ric-test-head/pip-requirements.txt b/oran-ric-test-head/pip-requirements.txt
new file mode 100644 (file)
index 0000000..4fbe8e7
--- /dev/null
@@ -0,0 +1,6 @@
+flask\r
+flask-cors\r
+paramiko\r
+FLASK\r
+FLASK-CORS\r
+requests\r
diff --git a/oran-ric-test-head/ric-test-head.py b/oran-ric-test-head/ric-test-head.py
new file mode 100644 (file)
index 0000000..f80d3d3
--- /dev/null
@@ -0,0 +1,117 @@
+#   Copyright (c) 2019 AT&T Intellectual Property.                             #\r
+#                                                                              #\r
+#   Licensed under the Apache License, Version 2.0 (the "License");            #\r
+#   you may not use this file except in compliance with the License.           #\r
+#   You may obtain a copy of the License at                                    #\r
+#                                                                              #\r
+#       http://www.apache.org/licenses/LICENSE-2.0                             #\r
+#                                                                              #\r
+#   Unless required by applicable law or agreed to in writing, software        #\r
+#   distributed under the License is distributed on an "AS IS" BASIS,          #\r
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #\r
+#   See the License for the specific language governing permissions and        #\r
+#   limitations under the License.                                             #\r
+################################################################################\r
+\r
+import datetime\r
+import json\r
+import logging\r
+from logging import FileHandler\r
+\r
+import requests\r
+from flask import Flask, request, jsonify\r
+\r
+#redirect http to https\r
+app = Flask(__name__)\r
+\r
+\r
+# Prevents print statement every time an endpoint is triggered.\r
+logging.getLogger("werkzeug").setLevel(logging.WARNING)\r
+\r
+def unix_time_millis(dt):\r
+       epoch = datetime.datetime.utcfromtimestamp(0)\r
+       return (dt - epoch).total_seconds() * 1000.0\r
+\r
+\r
+@app.route("/otf/vth/oran/v1/health", methods=['GET'])\r
+def getHealth():\r
+       return "UP"\r
+\r
+@app.route("/otf/vth/oran/ric/v1", methods =['POST'])\r
+def executeRicRequest():\r
+\r
+       responseData = {\r
+               'vthResponse': {\r
+                       'testDuration': '',\r
+                       'dateTimeUTC': datetime.datetime.now(),\r
+                       'abstractMessage': '',\r
+                       'resultData': {}\r
+               }\r
+       }\r
+\r
+       startTime = unix_time_millis(datetime.datetime.now())\r
+\r
+       try:\r
+               if not request.is_json:\r
+                       raise ValueError("request must be json")\r
+\r
+               requestData = request.get_json()\r
+\r
+               app.logger.info("Ric requestData:"+str(requestData))\r
+\r
+               action = requestData['action'].lower()\r
+               possibleActions = ['alive','ready','list', 'deploy','delete']\r
+               responseData['vthResponse']['abstractMessage'] = 'Result from {}'.format(action)\r
+\r
+               if action not in possibleActions:\r
+                       raise KeyError("invalid action")\r
+               if (action == 'deploy' or action == 'delete') and 'name' not in requestData:\r
+                       raise KeyError("must include name")\r
+\r
+               with open('config.json') as configFile:\r
+                       config = json.load(configFile)\r
+\r
+               baseAddress=  config['base_address']\r
+\r
+               if action == 'alive' or action == 'ready':\r
+                       res = requests.get(baseAddress+config['actions_path'][action])\r
+                       responseData['vthResponse']['resultData']['statusCode'] = res.status_code\r
+                       responseData['vthResponse']['resultData']['resultOutput'] = res.text\r
+               elif action == 'list':\r
+                       res = requests.get(baseAddress+config['actions_path'][action])\r
+                       responseData['vthResponse']['resultData']['statusCode'] = res.status_code\r
+                       responseData['vthResponse']['resultData']['resultOutput'] = res.json()\r
+               elif action == 'deploy':\r
+                       payload = {'name': requestData['name']}\r
+                       res = requests.post(baseAddress+config['actions_path'][action], data=payload)\r
+                       responseData['vthResponse']['resultData']['statusCode'] = res.status_code\r
+                       responseData['vthResponse']['resultData']['resultOutput'] = res.json()\r
+               elif action == 'delete':\r
+                       path= baseAddress+config['actions_path'][action]+"{}".format(requestData['name'])\r
+                       res = requests.delete(path)\r
+                       responseData['vthResponse']['resultData']['resultOutput'] = res.text\r
+                       responseData['vthResponse']['resultData']['statusCode'] = res.status_code\r
+\r
+       except Exception as ex:\r
+               endTime = unix_time_millis(datetime.datetime.now())\r
+               totalTime = endTime - startTime\r
+               responseData['vthResponse']['testDuration'] = totalTime\r
+               responseData['vthResponse']['abstractMessage'] = str(ex)\r
+               return jsonify(responseData)\r
+\r
+       endTime = unix_time_millis(datetime.datetime.now())\r
+       totalTime= endTime-startTime\r
+\r
+       responseData['vthResponse']['testDuration'] = totalTime\r
+\r
+       return jsonify(responseData),200\r
+\r
+if __name__ == '__main__':\r
+       # logHandler = FileHandler('otf/logs/pingVTH.log', mode='a')\r
+       logHandler = FileHandler('ricVTH.log', mode='a')\r
+       logHandler.setLevel(logging.INFO)\r
+       app.logger.setLevel(logging.INFO)\r
+       app.logger.addHandler(logHandler)\r
+       # context = ('opt/cert/otf.pem', 'opt/cert/privateKey.pem')\r
+       # app.run(debug = False, host = '0.0.0.0', port = 5000, ssl_context = context)\r
+       app.run(debug = False, host = '0.0.0.0', port = 5000)\r
diff --git a/oran-ric-test-head/workflows/Deploy_xAPP_Test.bpmn b/oran-ric-test-head/workflows/Deploy_xAPP_Test.bpmn
new file mode 100644 (file)
index 0000000..bf2b3d9
--- /dev/null
@@ -0,0 +1,463 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_0cpfikh" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.1">
+  <bpmn:process id="Deploy_xAPP_Test" name="Deploy xAPP Test" isExecutable="true">
+    <bpmn:startEvent id="StartEvent_1" camunda:asyncBefore="true">
+      <bpmn:outgoing>SequenceFlow_0st7o3p</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:sequenceFlow id="SequenceFlow_0st7o3p" sourceRef="StartEvent_1" targetRef="ScriptTask_08k2jy1" />
+    <bpmn:sequenceFlow id="SequenceFlow_0j9397y" sourceRef="ready" targetRef="verify_ready" />
+    <bpmn:sequenceFlow id="SequenceFlow_0e1kt1e" sourceRef="verify_ready" targetRef="ExclusiveGateway_1u1b164" />
+    <bpmn:sequenceFlow id="SequenceFlow_0zxo4fr" name="Ready" sourceRef="ExclusiveGateway_1u1b164" targetRef="first_list">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${ready}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="SequenceFlow_1chkfad" name="Not Ready" sourceRef="ExclusiveGateway_1u1b164" targetRef="mark_failure" />
+    <bpmn:sequenceFlow id="SequenceFlow_0s6ntyv" sourceRef="first_list" targetRef="alreadyDeployed" />
+    <bpmn:sequenceFlow id="SequenceFlow_1oze54u" sourceRef="deploy" targetRef="IntermediateThrowEvent_0aoxbne" />
+    <bpmn:sequenceFlow id="SequenceFlow_07jnolr" sourceRef="second_list" targetRef="verify_deploy" />
+    <bpmn:sequenceFlow id="SequenceFlow_08wazou" sourceRef="verify_deploy" targetRef="ExclusiveGateway_05eh6vk" />
+    <bpmn:sequenceFlow id="SequenceFlow_0nfij3v" name="xAPP deploy failed" sourceRef="ExclusiveGateway_05eh6vk" targetRef="mark_failure" />
+    <bpmn:sequenceFlow id="SequenceFlow_18bpwal" sourceRef="mark_success" targetRef="log_test_result" />
+    <bpmn:sequenceFlow id="SequenceFlow_07rma3l" sourceRef="IntermediateThrowEvent_0aoxbne" targetRef="second_list" />
+    <bpmn:sequenceFlow id="SequenceFlow_01cc25d" sourceRef="log_test_result" targetRef="EndEvent_0lg4zm4" />
+    <bpmn:sequenceFlow id="SequenceFlow_1u9jrl1" sourceRef="mark_failure" targetRef="log_test_result" />
+    <bpmn:sequenceFlow id="SequenceFlow_08hkwrc" name="xAPP deployed" sourceRef="ExclusiveGateway_05eh6vk" targetRef="mark_success">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${deployed}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="SequenceFlow_18luk66" sourceRef="ScriptTask_08k2jy1" targetRef="ExclusiveGateway_10o6bsf" />
+    <bpmn:sequenceFlow id="SequenceFlow_1y69zdb" sourceRef="ExclusiveGateway_10o6bsf" targetRef="ready">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${validInput}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="SequenceFlow_0g7zkcv" name="Bad Input" sourceRef="ExclusiveGateway_10o6bsf" targetRef="mark_failure" />
+    <bpmn:sequenceFlow id="SequenceFlow_08v4jva" name="Not Deployed" sourceRef="ExclusiveGateway_0ridg34" targetRef="deploy">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!alreadyDeployed}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="SequenceFlow_0dscvt7" name="Already Deployed" sourceRef="ExclusiveGateway_0ridg34" targetRef="mark_failure" />
+    <bpmn:sequenceFlow id="SequenceFlow_0i3et2n" sourceRef="alreadyDeployed" targetRef="ExclusiveGateway_0ridg34" />
+    <bpmn:scriptTask id="verify_ready" name="Verify xAPP Manager is Ready" scriptFormat="JavaScript">
+      <bpmn:incoming>SequenceFlow_0j9397y</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0e1kt1e</bpmn:outgoing>
+      <bpmn:script>var System = java.lang.System 
+
+var readyVthId = 'ready'
+var testData = execution.getVariable("testData")
+var vthInput = execution.getVariable("vthInput")
+var ready = false;
+var testResultMessage = "RIC VTH reported that xAppManager is not ready."
+
+
+
+try {
+  //get output from ready call
+  var testExecution = execution.getVariable('otf-execution-testExecution');
+  var data = null;
+  testExecution.testHeadResults.forEach(function(item, index, array) {
+    if(item.bpmnVthTaskId == readyVthId ){
+      data = item['testHeadResponse']['vthResponse']['resultData']['statusCode'];
+    }
+  })
+  
+  if(data === 200){
+    ready = true
+    testResultMessage = "RIC VTH reported that xAppManager is ready."
+  }
+  
+}
+catch(err) {
+  ready = false
+}
+
+execution.setVariable("ready", ready);
+execution.setVariable("testResultMessage", testResultMessage);</bpmn:script>
+    </bpmn:scriptTask>
+    <bpmn:scriptTask id="mark_failure" name="Mark Test Failure" scriptFormat="JavaScript">
+      <bpmn:incoming>SequenceFlow_1chkfad</bpmn:incoming>
+      <bpmn:incoming>SequenceFlow_0nfij3v</bpmn:incoming>
+      <bpmn:incoming>SequenceFlow_0g7zkcv</bpmn:incoming>
+      <bpmn:incoming>SequenceFlow_0dscvt7</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_1u9jrl1</bpmn:outgoing>
+      <bpmn:script>execution.setVariable("testResult", "FAILED")</bpmn:script>
+    </bpmn:scriptTask>
+    <bpmn:scriptTask id="mark_success" name="Mark Test Success" scriptFormat="JavaScript">
+      <bpmn:incoming>SequenceFlow_08hkwrc</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_18bpwal</bpmn:outgoing>
+      <bpmn:script>execution.setVariable("testResult", "SUCCESS")</bpmn:script>
+    </bpmn:scriptTask>
+    <bpmn:scriptTask id="verify_deploy" name="Compare xAPP list and validate test" scriptFormat="JavaScript">
+      <bpmn:incoming>SequenceFlow_07jnolr</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_08wazou</bpmn:outgoing>
+      <bpmn:script>var System = java.lang.System 
+
+var deploy = 'deploy'
+var secondList = 'second_list'
+var testData = execution.getVariable("testData")
+var vthInput = execution.getVariable("vthInput")
+var deployed = false;
+var testResultMessage = "RIC VTH reported that xApp is not deployed."
+var appName = testData['appName']
+
+
+
+try {
+  //get output from deploy call
+  var testExecution = execution.getVariable('otf-execution-testExecution');
+  data = null;
+  testExecution.testHeadResults.forEach(function(item, index, array) {
+    if(item.bpmnVthTaskId == deploy ){
+      data = item['testHeadResponse']['vthResponse']['resultData']['statusCode'];
+    }
+  })
+
+  if(data === 201){
+    testResultMessage = "RIC VTH reported that xAppManager deployment call succeeded."
+
+    //get output from secondList call
+    var testExecution = execution.getVariable('otf-execution-testExecution');
+    data = null;
+    testExecution.testHeadResults.forEach(function(item, index, array) {
+      if(item.bpmnVthTaskId == secondList ){
+        data = item['testHeadResponse']['vthResponse']['resultData']['resultOutput'];
+      }
+    })
+
+    instance = null
+    data.forEach(function(item, index, array) {
+      if(item.name === appName){
+        instance = item
+        testResultMessage = "RIC VTH reported that xApp is present."
+      }
+    })
+
+    if(instance !== null &amp;&amp; instance.status === 'deployed'){
+      deployed = true
+      testResultMessage = "RIC VTH reported that xApp is deployed."
+      testDetails = execution.getVariable("testDetails")
+      testDetails.put("instance", instance);
+      execution.setVariable("testDetails", testDetails)
+    }  
+    else{
+      deployed = false
+      testResultMessage = "RIC VTH reported that xApp was deployed, but xApp instance was either null or not deployed. See vth results for further information."
+    }
+
+  }
+  
+}
+catch(err) {
+  deployed = false
+  testResultMessage = "Couldn't verify is xApp was deployed. Check Test Results"  + err
+}
+
+execution.setVariable("deployed", deployed);
+execution.setVariable("testResultMessage", testResultMessage);</bpmn:script>
+    </bpmn:scriptTask>
+    <bpmn:scriptTask id="ScriptTask_08k2jy1" name="Verify Inputs" scriptFormat="JavaScript">
+      <bpmn:incoming>SequenceFlow_0st7o3p</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_18luk66</bpmn:outgoing>
+      <bpmn:script>var System = java.lang.System 
+
+var deployVthId = 'deploy'
+var testData = execution.getVariable("testData")
+var vthInput = execution.getVariable("vthInput")
+var validInput = false;
+var testResultMessage = "";
+
+try{
+
+  var appName = testData['appName'];
+  var waitDurationSec = testData['waitDurationSec'];
+
+  if(typeof appName  !== 'string' || appName.trim() === ''){
+    System.out.println("appName is not a string, or empty string")
+    throw Error("appName is not a string, or empty string")
+  }
+
+  if(typeof waitDurationSec !== 'number' || waitDurationSec &lt; 0){
+    System.out.println("not a number")
+    throw Error("waitDurationSec is not a number greater than 0")
+  }
+
+  validInput = true
+
+  vthInput[deployVthId].name = appName
+  var timer = "PT" + waitDurationSec + "S"
+  System.out.println("timer " + timer)
+  execution.setVariable("timer", timer)
+}
+catch(err){
+  System.out.println(err)
+  validInput = false
+  testResultMessage = "Invalid input params. error: " + err;
+  execution.setVariable("testResult", "FAILED");
+}
+
+execution.setVariable("validInput", validInput)
+execution.setVariable("testResultMessage", testResultMessage)</bpmn:script>
+    </bpmn:scriptTask>
+    <bpmn:scriptTask id="alreadyDeployed" name="Check if xAPP is already deployed" scriptFormat="JavaScript">
+      <bpmn:incoming>SequenceFlow_0s6ntyv</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0i3et2n</bpmn:outgoing>
+      <bpmn:script>var System = java.lang.System 
+
+var firstList = 'first_list'
+var testData = execution.getVariable("testData")
+var vthInput = execution.getVariable("vthInput")
+var alreadyDeployed = true;
+var testResultMessage = "RIC VTH reported that xApp is already deployed."
+var appName = testData['appName']
+
+
+
+try {
+  //get output from firstList call
+  var testExecution = execution.getVariable('otf-execution-testExecution');
+  var data = null;
+  testExecution.testHeadResults.forEach(function(item, index, array) {
+    if(item.bpmnVthTaskId == firstList ){
+      data = item['testHeadResponse']['vthResponse']['resultData']['resultOutput'];
+    }
+  })
+
+  var instance = null
+  data.forEach(function(item, index, array) {
+    if(item.name === appName){
+      instance = item
+      testResultMessage = "RIC VTH reported that xApp is already present."
+    }
+  })
+
+  if(instance === null){
+    alreadyDeployed = false
+    testResultMessage = "RIC VTH reported that xApp is not present."
+  }  
+
+  
+}
+catch(err) {
+  alreadyDeployed = true
+  testResultMessage = "Couldn't verify is xApp was already deployed."
+}
+
+execution.setVariable("alreadyDeployed", alreadyDeployed);
+execution.setVariable("testResultMessage", testResultMessage);</bpmn:script>
+    </bpmn:scriptTask>
+    <bpmn:exclusiveGateway id="ExclusiveGateway_1u1b164" default="SequenceFlow_1chkfad">
+      <bpmn:incoming>SequenceFlow_0e1kt1e</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0zxo4fr</bpmn:outgoing>
+      <bpmn:outgoing>SequenceFlow_1chkfad</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:exclusiveGateway id="ExclusiveGateway_05eh6vk" default="SequenceFlow_0nfij3v">
+      <bpmn:incoming>SequenceFlow_08wazou</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0nfij3v</bpmn:outgoing>
+      <bpmn:outgoing>SequenceFlow_08hkwrc</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:exclusiveGateway id="ExclusiveGateway_10o6bsf" default="SequenceFlow_0g7zkcv">
+      <bpmn:incoming>SequenceFlow_18luk66</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_1y69zdb</bpmn:outgoing>
+      <bpmn:outgoing>SequenceFlow_0g7zkcv</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:exclusiveGateway id="ExclusiveGateway_0ridg34" default="SequenceFlow_0dscvt7">
+      <bpmn:incoming>SequenceFlow_0i3et2n</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_08v4jva</bpmn:outgoing>
+      <bpmn:outgoing>SequenceFlow_0dscvt7</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:intermediateCatchEvent id="IntermediateThrowEvent_0aoxbne">
+      <bpmn:incoming>SequenceFlow_1oze54u</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_07rma3l</bpmn:outgoing>
+      <bpmn:timerEventDefinition>
+        <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">${timer}</bpmn:timeDuration>
+      </bpmn:timerEventDefinition>
+    </bpmn:intermediateCatchEvent>
+    <bpmn:endEvent id="EndEvent_0lg4zm4">
+      <bpmn:incoming>SequenceFlow_01cc25d</bpmn:incoming>
+      <bpmn:terminateEventDefinition />
+    </bpmn:endEvent>
+    <bpmn:serviceTask id="ready" name="VTH:RIC:Ready" camunda:delegateExpression="${callTestHeadDelegate}">
+      <bpmn:incoming>SequenceFlow_1y69zdb</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0j9397y</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:serviceTask id="first_list" name="VTH:RIC:List" camunda:delegateExpression="${callTestHeadDelegate}">
+      <bpmn:incoming>SequenceFlow_0zxo4fr</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0s6ntyv</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:serviceTask id="deploy" name="VTH:RIC:Deploy" camunda:delegateExpression="${callTestHeadDelegate}">
+      <bpmn:incoming>SequenceFlow_08v4jva</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_1oze54u</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:serviceTask id="second_list" name="VTH:RIC:List" camunda:delegateExpression="${callTestHeadDelegate}">
+      <bpmn:incoming>SequenceFlow_07rma3l</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_07jnolr</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:serviceTask id="log_test_result" name="UTIL:LogTestResult" camunda:delegateExpression="${logTestResultDelegate}">
+      <bpmn:incoming>SequenceFlow_18bpwal</bpmn:incoming>
+      <bpmn:incoming>SequenceFlow_1u9jrl1</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_01cc25d</bpmn:outgoing>
+    </bpmn:serviceTask>
+  </bpmn:process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Deploy_xAPP_Test">
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="156" y="190" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_01o5d6n_di" bpmnElement="verify_ready">
+        <dc:Bounds x="660" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ExclusiveGateway_1u1b164_di" bpmnElement="ExclusiveGateway_1u1b164" isMarkerVisible="true">
+        <dc:Bounds x="804" y="183" width="50" height="50" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="IntermediateCatchEvent_0o4pf4x_di" bpmnElement="IntermediateThrowEvent_0aoxbne">
+        <dc:Bounds x="1455" y="190" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ExclusiveGateway_05eh6vk_di" bpmnElement="ExclusiveGateway_05eh6vk" isMarkerVisible="true">
+        <dc:Bounds x="1884" y="183" width="50" height="50" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_0iya1du_di" bpmnElement="mark_failure">
+        <dc:Bounds x="1859" y="423" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_1dygfw7_di" bpmnElement="mark_success">
+        <dc:Bounds x="2069" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="EndEvent_15niqin_di" bpmnElement="EndEvent_0lg4zm4">
+        <dc:Bounds x="2407" y="190" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_0qmq6pn_di" bpmnElement="verify_deploy">
+        <dc:Bounds x="1728" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Task_0smfzp7_di" bpmnElement="ready">
+        <dc:Bounds x="508" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Task_0p2tcjd_di" bpmnElement="first_list">
+        <dc:Bounds x="905" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Task_14wupjq_di" bpmnElement="deploy">
+        <dc:Bounds x="1288" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Task_1wygysw_di" bpmnElement="second_list">
+        <dc:Bounds x="1563" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Task_0lcfr55_di" bpmnElement="log_test_result">
+        <dc:Bounds x="2253" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_08k2jy1_di" bpmnElement="ScriptTask_08k2jy1">
+        <dc:Bounds x="240" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ExclusiveGateway_10o6bsf_di" bpmnElement="ExclusiveGateway_10o6bsf" isMarkerVisible="true">
+        <dc:Bounds x="381" y="183" width="50" height="50" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ExclusiveGateway_0ridg34_di" bpmnElement="ExclusiveGateway_0ridg34" isMarkerVisible="true">
+        <dc:Bounds x="1165" y="183" width="50" height="50" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_0snkxz0_di" bpmnElement="alreadyDeployed">
+        <dc:Bounds x="1040" y="168" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="SequenceFlow_0st7o3p_di" bpmnElement="SequenceFlow_0st7o3p">
+        <di:waypoint x="192" y="208" />
+        <di:waypoint x="240" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0j9397y_di" bpmnElement="SequenceFlow_0j9397y">
+        <di:waypoint x="608" y="208" />
+        <di:waypoint x="660" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0e1kt1e_di" bpmnElement="SequenceFlow_0e1kt1e">
+        <di:waypoint x="760" y="208" />
+        <di:waypoint x="804" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0zxo4fr_di" bpmnElement="SequenceFlow_0zxo4fr">
+        <di:waypoint x="854" y="208" />
+        <di:waypoint x="905" y="208" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="854" y="189" width="33" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1chkfad_di" bpmnElement="SequenceFlow_1chkfad">
+        <di:waypoint x="829" y="233" />
+        <di:waypoint x="829" y="463" />
+        <di:waypoint x="1859" y="463" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="839" y="347" width="53" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0s6ntyv_di" bpmnElement="SequenceFlow_0s6ntyv">
+        <di:waypoint x="1005" y="208" />
+        <di:waypoint x="1040" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1oze54u_di" bpmnElement="SequenceFlow_1oze54u">
+        <di:waypoint x="1388" y="208" />
+        <di:waypoint x="1455" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_07jnolr_di" bpmnElement="SequenceFlow_07jnolr">
+        <di:waypoint x="1663" y="208" />
+        <di:waypoint x="1728" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_08wazou_di" bpmnElement="SequenceFlow_08wazou">
+        <di:waypoint x="1828" y="208" />
+        <di:waypoint x="1884" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0nfij3v_di" bpmnElement="SequenceFlow_0nfij3v">
+        <di:waypoint x="1909" y="233" />
+        <di:waypoint x="1909" y="423" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1924" y="272" width="63" height="27" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_18bpwal_di" bpmnElement="SequenceFlow_18bpwal">
+        <di:waypoint x="2169" y="208" />
+        <di:waypoint x="2253" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_07rma3l_di" bpmnElement="SequenceFlow_07rma3l">
+        <di:waypoint x="1491" y="208" />
+        <di:waypoint x="1563" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_01cc25d_di" bpmnElement="SequenceFlow_01cc25d">
+        <di:waypoint x="2353" y="208" />
+        <di:waypoint x="2407" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1u9jrl1_di" bpmnElement="SequenceFlow_1u9jrl1">
+        <di:waypoint x="1959" y="463" />
+        <di:waypoint x="2303" y="463" />
+        <di:waypoint x="2303" y="248" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_08hkwrc_di" bpmnElement="SequenceFlow_08hkwrc">
+        <di:waypoint x="1934" y="208" />
+        <di:waypoint x="2069" y="208" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1964" y="190" width="75" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_18luk66_di" bpmnElement="SequenceFlow_18luk66">
+        <di:waypoint x="340" y="208" />
+        <di:waypoint x="381" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1y69zdb_di" bpmnElement="SequenceFlow_1y69zdb">
+        <di:waypoint x="431" y="208" />
+        <di:waypoint x="508" y="208" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0g7zkcv_di" bpmnElement="SequenceFlow_0g7zkcv">
+        <di:waypoint x="406" y="233" />
+        <di:waypoint x="406" y="463" />
+        <di:waypoint x="1859" y="463" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="416" y="360" width="49" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_08v4jva_di" bpmnElement="SequenceFlow_08v4jva">
+        <di:waypoint x="1215" y="208" />
+        <di:waypoint x="1288" y="208" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1218" y="190" width="67" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0dscvt7_di" bpmnElement="SequenceFlow_0dscvt7">
+        <di:waypoint x="1190" y="233" />
+        <di:waypoint x="1190" y="463" />
+        <di:waypoint x="1859" y="463" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1205" y="357" width="86" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0i3et2n_di" bpmnElement="SequenceFlow_0i3et2n">
+        <di:waypoint x="1140" y="208" />
+        <di:waypoint x="1165" y="208" />
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>