From ef768a7c864f0d807d8696449f5eed7a4552316f Mon Sep 17 00:00:00 2001 From: Steve Smokowski Date: Thu, 9 Feb 2017 15:43:35 -0500 Subject: [PATCH] Initial OpenECOMP A&AI Model Loader commit Change-Id: Iae343fa01ecc701919703fb7d61727555371321d Signed-off-by: Steve Smokowski --- .gitignore | 6 + .gitreview | 4 + License.txt | 22 + Readme.md | 47 + pom.xml | 372 +++ src/main/docker/.dockerignore | 2 + src/main/docker/Dockerfile | 52 + src/main/docker/startup.sh | 27 + src/main/docker/update_config.sh | 151 ++ .../modelloader/config/ModelLoaderConfig.java | 235 ++ .../org/openecomp/modelloader/entity/Artifact.java | 44 + .../modelloader/entity/ArtifactHandler.java | 37 + .../openecomp/modelloader/entity/ArtifactType.java | 25 + .../entity/catalog/VnfCatalogArtifact.java | 31 + .../entity/catalog/VnfCatalogArtifactHandler.java | 184 ++ .../modelloader/entity/model/ModelArtifact.java | 60 + .../entity/model/ModelArtifactHandler.java | 133 ++ .../entity/model/ModelArtifactParser.java | 197 ++ .../modelloader/entity/model/ModelSorter.java | 233 ++ .../notification/DistributionStatusMsg.java | 75 + .../modelloader/notification/EventCallback.java | 286 +++ .../modelloader/restclient/AaiRestClient.java | 400 ++++ .../modelloader/service/ModelLoaderInterface.java | 53 + .../modelloader/service/ModelLoaderMsgs.java | 102 + .../modelloader/service/ModelLoaderService.java | 174 ++ .../modelloader/util/JsonXmlConverter.java | 79 + src/main/resources/aai-os-cert.p12 | Bin 0 -> 4357 bytes src/main/resources/logback.xml | 195 ++ src/main/resources/model-loader.properties | 43 + .../filemonitor/FileMonitorMsgs.properties | 81 + .../modelloader/service/ModelLoaderMsgs.properties | 112 + src/main/resources/schema/aai_schema_v8.xsd | 2462 ++++++++++++++++++++ src/main/resources/schema/vnfcatalog.xsd | 127 + src/main/webapp/WEB-INF/applicationContext.xml | 9 + src/main/webapp/WEB-INF/rest-servlet.xml | 12 + src/main/webapp/WEB-INF/web.xml | 20 + .../modelloader/config/ModelLoaderConfigTest.java | 122 + .../catalog/VnfCatalogArtifactHandlerTest.java | 98 + .../entity/model/ModelArtifactParserTest.java | 151 ++ .../modelloader/entity/model/ModelSorterTest.java | 133 ++ .../modelloader/restclient/AAIRestClientTest.java | 119 + .../service/ModelLoaderServiceTest.java | 115 + .../modelloader/util/JsonXmlConverterTest.java | 79 + src/test/resources/logback-test.xml | 37 + .../model-loader-empty-auth-password.properties | 43 + .../model-loader-no-auth-password.properties | 41 + src/test/resources/model-loader.properties | 43 + src/test/resources/models/complete-model.xml | 500 ++++ .../resources/models/named-query-wan-connector.xml | 90 + src/test/resources/models/vnf-model.json | 10 + src/test/resources/models/vnf-model.xml | 27 + src/test/resources/models/wan-connector-model.xml | 186 ++ src/test/resources/vnfcatalogexample.xml | 1878 +++++++++++++++ 53 files changed, 9764 insertions(+) create mode 100644 .gitignore create mode 100644 .gitreview create mode 100644 License.txt create mode 100644 Readme.md create mode 100644 pom.xml create mode 100644 src/main/docker/.dockerignore create mode 100644 src/main/docker/Dockerfile create mode 100644 src/main/docker/startup.sh create mode 100644 src/main/docker/update_config.sh create mode 100644 src/main/java/org/openecomp/modelloader/config/ModelLoaderConfig.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/Artifact.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/ArtifactHandler.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/ArtifactType.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifact.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandler.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java create mode 100644 src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java create mode 100644 src/main/java/org/openecomp/modelloader/notification/DistributionStatusMsg.java create mode 100644 src/main/java/org/openecomp/modelloader/notification/EventCallback.java create mode 100644 src/main/java/org/openecomp/modelloader/restclient/AaiRestClient.java create mode 100644 src/main/java/org/openecomp/modelloader/service/ModelLoaderInterface.java create mode 100644 src/main/java/org/openecomp/modelloader/service/ModelLoaderMsgs.java create mode 100644 src/main/java/org/openecomp/modelloader/service/ModelLoaderService.java create mode 100644 src/main/java/org/openecomp/modelloader/util/JsonXmlConverter.java create mode 100644 src/main/resources/aai-os-cert.p12 create mode 100644 src/main/resources/logback.xml create mode 100644 src/main/resources/model-loader.properties create mode 100644 src/main/resources/org/openecomp/modelloader/filemonitor/FileMonitorMsgs.properties create mode 100644 src/main/resources/org/openecomp/modelloader/service/ModelLoaderMsgs.properties create mode 100644 src/main/resources/schema/aai_schema_v8.xsd create mode 100644 src/main/resources/schema/vnfcatalog.xsd create mode 100644 src/main/webapp/WEB-INF/applicationContext.xml create mode 100644 src/main/webapp/WEB-INF/rest-servlet.xml create mode 100644 src/main/webapp/WEB-INF/web.xml create mode 100644 src/test/java/org/openecomp/modelloader/config/ModelLoaderConfigTest.java create mode 100644 src/test/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandlerTest.java create mode 100644 src/test/java/org/openecomp/modelloader/entity/model/ModelArtifactParserTest.java create mode 100644 src/test/java/org/openecomp/modelloader/entity/model/ModelSorterTest.java create mode 100644 src/test/java/org/openecomp/modelloader/restclient/AAIRestClientTest.java create mode 100644 src/test/java/org/openecomp/modelloader/service/ModelLoaderServiceTest.java create mode 100644 src/test/java/org/openecomp/modelloader/util/JsonXmlConverterTest.java create mode 100644 src/test/resources/logback-test.xml create mode 100644 src/test/resources/model-loader-empty-auth-password.properties create mode 100644 src/test/resources/model-loader-no-auth-password.properties create mode 100644 src/test/resources/model-loader.properties create mode 100644 src/test/resources/models/complete-model.xml create mode 100644 src/test/resources/models/named-query-wan-connector.xml create mode 100644 src/test/resources/models/vnf-model.json create mode 100644 src/test/resources/models/vnf-model.xml create mode 100644 src/test/resources/models/wan-connector-model.xml create mode 100644 src/test/resources/vnfcatalogexample.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f402f8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.classpath +.project +.settings/ +target/ +logs/ +debug-logs/ \ No newline at end of file diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..01d111b --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=gerrit.openecomp.org +port=29418 +project=aai/model-loader diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..17cfdd5 --- /dev/null +++ b/License.txt @@ -0,0 +1,22 @@ + ============LICENSE_START======================================================= + MODEL LOADER SERVICE + ================================================================================ + Copyright © 2017 AT&T Intellectual Property. + Copyright © 2017 Amdocs + 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========================================================= + + ECOMP and OpenECOMP are trademarks + and service marks of AT&T Intellectual Property. \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..758b3a7 --- /dev/null +++ b/Readme.md @@ -0,0 +1,47 @@ +# Introduction + +The A&AI Model Loader Service is an application that facilitates +distribution, ingestion of new service and resource models, and vnf +catalogs from the SDC to the A&AI. + +## Features + +The Model Loader: + +* registers with the SDC to receive notification events +* polls the UEB/DMaap cluster for notification events +* downloads artifacts from SDC upon receipt of a distribution event +* pushes distribution components to A&AI + +## Compiling Model Loader + +Model Loader can be compiled by running `mvn clean install` + +## Running Model Loader + +### Create a config file with the following key/values: + +``` +DISTR_CLIENT_ASDC_ADDRESS= +DISTR_CLIENT_CONSUMER_GROUP= ;; Uniquely identiy this group of model loaders. +DISTR_CLIENT_CONSUMER_ID= ;; Uniquely identiythis model loader. +DISTR_CLIENT_ENVIRONMENT_NAME= ;; Environment name configured on the SDC +DISTR_CLIENT_PASSWORD= ;; Password to connect to SDC +DISTR_CLIENT_USER= ;; User name to connect to SDC + +APP_SERVER_BASE_URL=https://:8443 ;; AAI Address (URL) +APP_SERVER_AUTH_USER= ;; User name to connect to AAI +APP_SERVER_AUTH_PASSWORD= ;; Password to connect to AAi + +``` + +### Docker + +#### Build your own Model Loader docker image and create docker containers +1. mvn clean package docker:build ;; Build a docker image of Model Loader +2. sudo docker images ;; list docker images and check if the image you build is listed. +3. sudo docker run --env-file /opt/jetty/jetty*/bin/startup.sh + + +#### Retrieve logs from stopped container +* docker cp :/opt/jetty/jetty-distribution-9.3.9.v20160517/logs/AAI-ML/error.log /tmp/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2228b40 --- /dev/null +++ b/pom.xml @@ -0,0 +1,372 @@ + + + + 4.0.0 + org.openecomp.aai.model-loader + model-loader + 1.0.0-SNAPSHOT + war + + + ${basedir}/target + ${dockerurl} + ${dockertag} + ${dockerlogin} + ${dockerpassword} + ${dockerregistry} + provided + google_checks.xml + 1.8 + 1.8 + + + + + maven-central + maven-central + http://central.maven.org/maven2/ + + true + never + + + false + + + + ecomp-nexus + ecomp-nexus + https://ecomp-nexus:8443/repository/maven-releases/ + + true + never + + + false + + + + + + + + + org.mockito + mockito-all + 1.10.19 + test + + + org.powermock + powermock-module-junit4 + 1.6.2 + test + + + org.powermock + powermock-api-mockito + 1.6.2 + test + + + org.powermock + powermock-module-javaagent + 1.6.2 + test + + + org.powermock + powermock-module-junit4-rule-agent + 1.6.2 + test + + + + javax.xml.bind + jaxb-api + 2.2.11 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + com.sun.xml.bind + jaxb-core + 2.2.11 + + + com.sun.xml.bind + jaxb-xjc + 2.2.11 + + + org.eclipse.persistence + org.eclipse.persistence.moxy + 2.6.2 + compile + + + com.sun.jersey + jersey-client + 1.18 + + + + org.openecomp.cl + common-logging + 1.0.0-SNAPSHOT + + + + org.openecomp.sdc + sdc-distribution-client + 1.1.2 + + + org.json + json + 20131018 + + + + org.eclipse.jetty + jetty-security + 9.3.8.RC0 + + + + org.springframework + spring-webmvc + 4.0.0.RELEASE + + + jline + jline + 2.12.1 + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.5.1 + + + copy-agent + process-test-classes + + copy + + + + + org.powermock + powermock-module-javaagent + 1.6.2 + ${project.build.directory}/agents + powermock-javaagent.jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + -javaagent:${project.build.directory}/agents/powermock-javaagent.jar + -noverify + + + + org.codehaus.mojo + jaxb2-maven-plugin + 2.2 + + + xjc + + xjc + + + + + false + ${project.build.directory}/generated-sources + + ${project.basedir}/src/main/resources/schema + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + copy-docker-file + package + + copy-resources + + + target + true + + + ${basedir}/src/main/docker + true + + **/* + + + + + + + + + com.spotify + docker-maven-plugin + 0.4.11 + + ${docker.url} + ${docker.registry} + + ${docker.login} + ${docker.password} + + ${docker.registry}/ecomp/${project.artifactId} + ${docker.location} + https://${docker.registry} + + ${docker.imagetag} + latest + + true + + + + + com.blackducksoftware.integration + hub-maven-plugin + 1.0.4 + false + + ${project.basedir/target} + + + + create-bdio-file + package + + createHubOutput + + + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.3 + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + checkstyle + + + + + + + + + + + org.codehaus.mojo + license-maven-plugin + 1.10 + + false + + **.json + **.properties + + ============LICENSE_START======================================================= + ============LICENSE_END========================================================= + ================================================================================ + apache_v2 + 2017 + AT&T Intellectual Property. All rights reserved. + MODEL LOADER SERVICE + true + true + true + true + + . + + + **/*.json + + + xml + properties + xml + java + + + + + first + + update-file-header + + process-sources + + + + + + + diff --git a/src/main/docker/.dockerignore b/src/main/docker/.dockerignore new file mode 100644 index 0000000..1128374 --- /dev/null +++ b/src/main/docker/.dockerignore @@ -0,0 +1,2 @@ +*.war +*.jsonld \ No newline at end of file diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile new file mode 100644 index 0000000..4c2fe1a --- /dev/null +++ b/src/main/docker/Dockerfile @@ -0,0 +1,52 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +FROM ubuntu:14.04 +ARG jettyrel=9.3.9.v20160517 +ARG jettydist=jetty-distribution-${jettyrel} +ARG jettybase=/opt/jetty + +RUN apt-get update && apt-get --force-yes -y -f install wget + +# Install java8 +RUN apt-get install -y software-properties-common + +# sudo -E is required to preserve the environment +# If you remove that line, it will most like freeze at this step + +RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk + +# Setup JAVA_HOME, this is useful for docker commandline + +ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64 +RUN export JAVA_HOME + +RUN wget http://central.maven.org/maven2/org/eclipse/jetty/jetty-distribution/${jettyrel}/${jettydist}.tar.gz +RUN gunzip ${jettydist}.tar.gz && tar xvf ${jettydist}.tar + +COPY model-loader* $jettydist/webapps/model-loader/ + +COPY startup.sh update_config.sh ${jettydist}/bin/ +RUN chmod 700 ${jettydist}/bin/startup.sh && chmod 700 ${jettydist}/bin/update_config.sh +RUN mkdir -p ${jettybase} +RUN mv ${jettydist} ${jettybase}/${jettydist} +RUN rm -rf $jettybase/$jettydist/demo-base + +CMD /opt/jetty/*/bin/startup.sh diff --git a/src/main/docker/startup.sh b/src/main/docker/startup.sh new file mode 100644 index 0000000..22950cd --- /dev/null +++ b/src/main/docker/startup.sh @@ -0,0 +1,27 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +BIN_DIR=`dirname $0` + +echo "Checking environment for configuration options" +$BIN_DIR/update_config.sh + +echo "Starting up model loader..." +$BIN_DIR/jetty.sh run > /dev/null 2>&1 \ No newline at end of file diff --git a/src/main/docker/update_config.sh b/src/main/docker/update_config.sh new file mode 100644 index 0000000..77916ed --- /dev/null +++ b/src/main/docker/update_config.sh @@ -0,0 +1,151 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# +# This script will update the config file, with config values supplied +# through environment variables, if set +# + +CONFIG_FILE=`dirname $0`/../webapps/model-loader/WEB-INF/classes/model-loader.properties + +# Distribution client configuration +ENVVAR=DISTR_CLIENT_ACTIVE_SERVER_TLS_AUTH +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.ACTIVE_SERVER_TLS_AUTH/s/.*/ml.distribution.ACTIVE_SERVER_TLS_AUTH=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_ASDC_ADDRESS +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.ASDC_ADDRESS/s/.*/ml.distribution.ASDC_ADDRESS=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_CONSUMER_GROUP +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.CONSUMER_GROUP/s/.*/ml.distribution.CONSUMER_GROUP=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_CONSUMER_ID +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.CONSUMER_ID/s/.*/ml.distribution.CONSUMER_ID=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_ENVIRONMENT_NAME +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.ENVIRONMENT_NAME/s/.*/ml.distribution.ENVIRONMENT_NAME=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_KEYSTORE_PASSWORD +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.KEYSTORE_PASSWORD/s/.*/ml.distribution.KEYSTORE_PASSWORD=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_KEYSTORE_FILE +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.KEYSTORE_FILE/s/.*/ml.distribution.KEYSTORE_FILE=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_PASSWORD +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.PASSWORD/s/.*/ml.distribution.PASSWORD=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_POLLING_INTERVAL +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.POLLING_INTERVAL/s/.*/ml.distribution.POLLING_INTERVAL=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_POLLING_TIMEOUT +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.POLLING_TIMEOUT/s/.*/ml.distribution.POLLING_TIMEOUT=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_USER +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.USER/s/.*/ml.distribution.USER=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=DISTR_CLIENT_ARTIFACT_TYPES +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.distribution.ARTIFACT_TYPES/s/.*/ml.distribution.ARTIFACT_TYPES=$ENVVALUE/" $CONFIG_FILE; + + +# Model Loader Application Server REST Client Configuration +ENVVAR=APP_SERVER_BASE_URL +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.BASE_URL/s/.*/ml.aai.BASE_URL=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_MODEL_URL +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.MODEL_URL/s/.*/ml.aai.MODEL_URL=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_NAMED_QUERY_URL +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.NAMED_QUERY_URL/s/.*/ml.aai.NAMED_QUERY_URL=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_VNF_IMAGE_URL +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.VNF_IMAGE_URL/s/.*/ml.aai.VNF_IMAGE_URL=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_KEYSTORE_FILE +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.KEYSTORE_FILE/s/.*/ml.aai.KEYSTORE_FILE=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_KEYSTORE_PASSWORD +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.KEYSTORE_PASSWORD/s/.*/ml.aai.KEYSTORE_PASSWORD=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_AUTH_USER +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.AUTH_USER/s/.*/ml.aai.AUTH_USER=$ENVVALUE/" $CONFIG_FILE; + +ENVVAR=APP_SERVER_AUTH_PASSWORD +ENVVALUE=${!ENVVAR} +ENVVALUE=${ENVVALUE//\//\\/} +[ -z ${!ENVVAR+x} ] \ + || sed -i "/ml.aai.AUTH_PASSWORD/s/.*/ml.aai.AUTH_PASSWORD=$ENVVALUE/" $CONFIG_FILE; diff --git a/src/main/java/org/openecomp/modelloader/config/ModelLoaderConfig.java b/src/main/java/org/openecomp/modelloader/config/ModelLoaderConfig.java new file mode 100644 index 0000000..26f13ad --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/config/ModelLoaderConfig.java @@ -0,0 +1,235 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.config; + +import org.eclipse.jetty.util.security.Password; +import org.openecomp.sdc.api.consumer.IConfiguration; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +public class ModelLoaderConfig implements IConfiguration { + + // Configuration file structure + public static final String PREFIX_MODEL_LOADER_CONFIG = "ml"; + public static final String PREFIX_DISTRIBUTION_CLIENT = + PREFIX_MODEL_LOADER_CONFIG + ".distribution."; + public static final String PREFIX_AAI = PREFIX_MODEL_LOADER_CONFIG + ".aai."; + public static final String PREFIX_DEBUG = PREFIX_MODEL_LOADER_CONFIG + ".debug."; + + // Configuration file properties + protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH = + PREFIX_DISTRIBUTION_CLIENT + "ACTIVE_SERVER_TLS_AUTH"; + protected static final String PROP_ML_DISTRIBUTION_ASDC_ADDRESS = PREFIX_DISTRIBUTION_CLIENT + + "ASDC_ADDRESS"; + protected static final String PROP_ML_DISTRIBUTION_CONSUMER_GROUP = PREFIX_DISTRIBUTION_CLIENT + + "CONSUMER_GROUP"; + protected static final String PROP_ML_DISTRIBUTION_CONSUMER_ID = PREFIX_DISTRIBUTION_CLIENT + + "CONSUMER_ID"; + protected static final String PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME = PREFIX_DISTRIBUTION_CLIENT + + "ENVIRONMENT_NAME"; + protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD = PREFIX_DISTRIBUTION_CLIENT + + "KEYSTORE_PASSWORD"; + protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_FILE = PREFIX_DISTRIBUTION_CLIENT + + "KEYSTORE_FILE"; + protected static final String PROP_ML_DISTRIBUTION_PASSWORD = PREFIX_DISTRIBUTION_CLIENT + + "PASSWORD"; + protected static final String PROP_ML_DISTRIBUTION_POLLING_INTERVAL = PREFIX_DISTRIBUTION_CLIENT + + "POLLING_INTERVAL"; + protected static final String PROP_ML_DISTRIBUTION_POLLING_TIMEOUT = PREFIX_DISTRIBUTION_CLIENT + + "POLLING_TIMEOUT"; + protected static final String PROP_ML_DISTRIBUTION_USER = PREFIX_DISTRIBUTION_CLIENT + "USER"; + protected static final String PROP_ML_DISTRIBUTION_ARTIFACT_TYPES = PREFIX_DISTRIBUTION_CLIENT + + "ARTIFACT_TYPES"; + + protected static final String PROP_AAI_BASE_URL = PREFIX_AAI + "BASE_URL"; + protected static final String PROP_AAI_KEYSTORE_FILE = PREFIX_AAI + "KEYSTORE_FILE"; + protected static final String PROP_AAI_KEYSTORE_PASSWORD = PREFIX_AAI + "KEYSTORE_PASSWORD"; + protected static final String PROP_AAI_MODEL_RESOURCE_URL = PREFIX_AAI + "MODEL_URL"; + protected static final String PROP_AAI_NAMED_QUERY_RESOURCE_URL = PREFIX_AAI + "NAMED_QUERY_URL"; + protected static final String PROP_AAI_VNF_IMAGE_RESOURCE_URL = PREFIX_AAI + "VNF_IMAGE_URL"; + protected static final String PROP_AAI_AUTHENTICATION_USER = PREFIX_AAI + "AUTH_USER"; + protected static final String PROP_AAI_AUTHENTICATION_PASSWORD = PREFIX_AAI + "AUTH_PASSWORD"; + + protected static final String PROP_DEBUG_INGEST_SIMULATOR = PREFIX_DEBUG + "INGEST_SIMULATOR"; + + private Properties modelLoaderProperties = null; + + private String certLocation = "."; + + private List artifactTypes = null; + + /** + * This is the class constructor. + * + * @param modelLoaderProperties properties needed to be configured for the model loader + * @param certLocation location of the certificate + */ + public ModelLoaderConfig(Properties modelLoaderProperties) { + this.modelLoaderProperties = modelLoaderProperties; + + String aaiKeystoreFile = modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_FILE); + if(aaiKeystoreFile != null){ + URL keystoreURL = this.getClass().getClassLoader().getResource(aaiKeystoreFile); + if(keystoreURL != null){ + File fKeystoreLocation = new File(keystoreURL.getPath()); + this.certLocation = fKeystoreLocation.getParent(); + } + } + + // Get list of artifacts + artifactTypes = new ArrayList(); + if (modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES) != null) { + String[] artTypeList = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES) + .split(","); + for (String artType : artTypeList) { + artifactTypes.add(artType); + } + } + } + + @Override + public boolean activateServerTLSAuth() { + String value = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH); + return value == null ? false : Boolean.parseBoolean(value); + } + + @Override + public String getAsdcAddress() { + return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ASDC_ADDRESS); + } + + @Override + public String getConsumerGroup() { + return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_CONSUMER_GROUP); + } + + @Override + public String getConsumerID() { + return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_CONSUMER_ID); + } + + @Override + public String getEnvironmentName() { + return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME); + } + + @Override + public String getKeyStorePassword() { + return Password + .deobfuscate(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD)); + } + + @Override + public String getKeyStorePath() { + return certLocation + modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_KEYSTORE_FILE); + } + + @Override + public String getPassword() { + return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_PASSWORD)); + } + + @Override + public int getPollingInterval() { + return Integer + .parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_INTERVAL)); + } + + @Override + public int getPollingTimeout() { + return Integer + .parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_TIMEOUT)); + } + + @Override + public List getRelevantArtifactTypes() { + return artifactTypes; + } + + @Override + public String getUser() { + return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_USER); + } + + public String getAaiKeyStorePath() { + return certLocation + "/" + modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_FILE); + } + + public String getAaiKeyStorePassword() { + return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_PASSWORD)); + } + + public String getAaiBaseUrl() { + return modelLoaderProperties.getProperty(PROP_AAI_BASE_URL); + } + + public String getAaiModelUrl() { + return modelLoaderProperties.getProperty(PROP_AAI_MODEL_RESOURCE_URL); + } + + public String getAaiNamedQueryUrl() { + return modelLoaderProperties.getProperty(PROP_AAI_NAMED_QUERY_RESOURCE_URL); + } + + public String getAaiVnfImageUrl() { + return modelLoaderProperties.getProperty(PROP_AAI_VNF_IMAGE_RESOURCE_URL); + } + + public String getAaiAuthenticationUser() { + return modelLoaderProperties.getProperty(PROP_AAI_AUTHENTICATION_USER); + } + + /** + * @return password for AAI authentication that has been reverse-engineered + * from its obfuscated form. + */ + public String getAaiAuthenticationPassword() { + String password = Password + .deobfuscate(modelLoaderProperties.getProperty(PROP_AAI_AUTHENTICATION_PASSWORD)); + + if ((password != null) && (password.equals(""))) { + return null; + } + + return password; + } + + /** + * @return a boolean value indicating whether the simulator is enabled. + */ + public boolean getIngestSimulatorEnabled() { + String propValue = modelLoaderProperties.getProperty(PROP_DEBUG_INGEST_SIMULATOR); + + if (propValue == null) { + return false; + } + + if (propValue.compareToIgnoreCase("enabled") == 0) { + return true; + } + + return false; + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/Artifact.java b/src/main/java/org/openecomp/modelloader/entity/Artifact.java new file mode 100644 index 0000000..fb0ec9f --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/Artifact.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity; + +public abstract class Artifact { + + private String payload; + private ArtifactType type; + + public ArtifactType getType() { + return type; + } + + public void setType(ArtifactType type) { + this.type = type; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + +} diff --git a/src/main/java/org/openecomp/modelloader/entity/ArtifactHandler.java b/src/main/java/org/openecomp/modelloader/entity/ArtifactHandler.java new file mode 100644 index 0000000..16f2c87 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/ArtifactHandler.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity; + +import org.openecomp.modelloader.config.ModelLoaderConfig; + +import java.util.List; + +public abstract class ArtifactHandler { + + protected ModelLoaderConfig config; + + public ArtifactHandler(ModelLoaderConfig config) { + this.config = config; + } + + public abstract boolean pushArtifacts(List artifacts, String distributionId); + +} diff --git a/src/main/java/org/openecomp/modelloader/entity/ArtifactType.java b/src/main/java/org/openecomp/modelloader/entity/ArtifactType.java new file mode 100644 index 0000000..8977e3c --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/ArtifactType.java @@ -0,0 +1,25 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity; + +public enum ArtifactType { + MODEL, NAMED_QUERY, VNF_CATALOG; +} diff --git a/src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifact.java b/src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifact.java new file mode 100644 index 0000000..b2e1fdb --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifact.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.catalog; + +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.ArtifactType; + +public class VnfCatalogArtifact extends Artifact { + public VnfCatalogArtifact(String payload) { + setPayload(payload); + setType(ArtifactType.VNF_CATALOG); + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandler.java b/src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandler.java new file mode 100644 index 0000000..189b069 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandler.java @@ -0,0 +1,184 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.catalog; + +import com.sun.jersey.api.client.ClientResponse; + +import generated.VnfCatalog; +import generated.VnfCatalog.PartNumberList; + +import inventory.aai.openecomp.org.v8.VnfImage; + +import org.eclipse.persistence.jaxb.MarshallerProperties; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.ArtifactHandler; +import org.openecomp.modelloader.restclient.AaiRestClient; +import org.openecomp.modelloader.restclient.AaiRestClient.MimeType; +import org.openecomp.modelloader.service.ModelLoaderMsgs; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.ws.rs.core.Response; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + + +public class VnfCatalogArtifactHandler extends ArtifactHandler { + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(VnfCatalogArtifactHandler.class.getName()); + + public VnfCatalogArtifactHandler(ModelLoaderConfig config) { + super(config); + } + + @Override + public boolean pushArtifacts(List artifacts, String distributionId) { + for (Artifact art : artifacts) { + VnfCatalogArtifact vnfCatalog = (VnfCatalogArtifact) art; + String artifactPayload = vnfCatalog.getPayload(); + + AaiRestClient restClient = new AaiRestClient(this.config); + List putImages = new ArrayList(); + + try { + JAXBContext inputContext = JAXBContext.newInstance(VnfCatalog.class); + Unmarshaller unmarshaller = inputContext.createUnmarshaller(); + StringReader reader = new StringReader(artifactPayload); + VnfCatalog cat = (VnfCatalog) unmarshaller.unmarshal(reader); + + int numParts = cat.getPartNumberList().size(); + + for (int i = 0; i < numParts; i++) { + + PartNumberList pnl = cat.getPartNumberList().get(i); + + String application = pnl.getVendorInfo().getVendorModel(); + String applicationVendor = pnl.getVendorInfo().getVendorName(); + + int numVersions = pnl.getSoftwareVersionList().size(); + + for (int j = 0; j < numVersions; j++) { + String applicationVersion = pnl.getSoftwareVersionList().get(j).getSoftwareVersion(); + + String imageId = "vnf image " + applicationVendor + " " + application + " " + + applicationVersion; + + String getUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + + "?application-vendor=" + applicationVendor + "&application=" + application + + "&application-version=" + applicationVersion; + + ClientResponse tryGet = restClient.getResource(getUrl, distributionId, MimeType.JSON); + if (tryGet == null) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Ingestion failed on " + imageId + ". Rolling back distribution."); + failureCleanup(putImages, restClient, distributionId); + return false; + } + if (tryGet.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) { + // this vnf-image not already in the db, need to add + // only do this on 404 bc other error responses could mean there + // are problems that + // you might not want to try to PUT against + + VnfImage image = new VnfImage(); + image.setApplication(application); + image.setApplicationVendor(applicationVendor); + image.setApplicationVersion(applicationVersion); + String uuid = UUID.randomUUID().toString(); + image.setUuid(uuid); // need to create uuid + + System.setProperty("javax.xml.bind.context.factory", + "org.eclipse.persistence.jaxb.JAXBContextFactory"); + JAXBContext jaxbContext = JAXBContext.newInstance(VnfImage.class); + Marshaller marshaller = jaxbContext.createMarshaller(); + marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json"); + marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false); + marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false); + StringWriter writer = new StringWriter(); + marshaller.marshal(image, writer); + String payload = writer.toString(); + + String putUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + + uuid; + + ClientResponse putResp = restClient.putResource(putUrl, payload, distributionId, + MimeType.JSON); + if (putResp == null + || putResp.getStatus() != Response.Status.CREATED.getStatusCode()) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Ingestion failed on vnf-image " + imageId + ". Rolling back distribution."); + failureCleanup(putImages, restClient, distributionId); + return false; + } + putImages.add(image); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested."); + } else if (tryGet.getStatus() == Response.Status.OK.getStatusCode()) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + imageId + " already exists. Skipping ingestion."); + } else { + // if other than 404 or 200, something went wrong + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Ingestion failed on vnf-image " + imageId + " with status " + tryGet.getStatus() + + ". Rolling back distribution."); + failureCleanup(putImages, restClient, distributionId); + return false; + } + } + } + + } catch (JAXBException e) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Ingestion failed. " + e.getMessage() + ". Rolling back distribution."); + failureCleanup(putImages, restClient, distributionId); + return false; + } + } + + return true; + } + + /* + * if something fails in the middle of ingesting the catalog we want to + * rollback any changes to the db + */ + private void failureCleanup(List putImages, AaiRestClient restClient, String transId) { + for (VnfImage image : putImages) { + String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + + image.getUuid(); + restClient.getAndDeleteResource(url, transId); // try to delete the image, + // if something goes wrong + // we can't really do + // anything here + } + } + +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java new file mode 100644 index 0000000..904dba9 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.model; + +import org.openecomp.modelloader.entity.Artifact; + +import java.util.HashSet; +import java.util.Set; + +public class ModelArtifact extends Artifact { + + String nameVersionId; + Set referencedModelIds = new HashSet(); + + public String getNameVersionId() { + return nameVersionId; + } + + public void setNameVersionId(String nameVersionId) { + this.nameVersionId = nameVersionId; + } + + public Set getDependentModelIds() { + return referencedModelIds; + } + + public void addDependentModelId(String dependentModelId) { + this.referencedModelIds.add(dependentModelId); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("NameVersId=" + nameVersionId + "(" + getType().toString() + ") ==> "); + for (String dep : referencedModelIds) { + sb.append(dep + " "); + } + + return sb.toString(); + } + +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java new file mode 100644 index 0000000..fb269b1 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java @@ -0,0 +1,133 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.model; + +import com.sun.jersey.api.client.ClientResponse; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.ArtifactHandler; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.restclient.AaiRestClient; +import org.openecomp.modelloader.service.ModelLoaderMsgs; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.core.Response; + +public class ModelArtifactHandler extends ArtifactHandler { + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(ArtifactHandler.class.getName()); + + public ModelArtifactHandler(ModelLoaderConfig config) { + super(config); + } + + @Override + public boolean pushArtifacts(List artifacts, String distributionId) { + ModelSorter modelSorter = new ModelSorter(); + List sortedModelArtifacts = modelSorter.sort(artifacts); + + // Push the ordered list of model artifacts to A&AI. If one fails, we need + // to roll back + // the changes. + List completedModels = new ArrayList(); + AaiRestClient aaiClient = new AaiRestClient(config); + + for (Artifact art : sortedModelArtifacts) { + ModelArtifact model = (ModelArtifact) art; + ClientResponse getResponse = aaiClient.getResource(getUrl(model), distributionId, + AaiRestClient.MimeType.XML); + if ((getResponse == null) + || (getResponse.getStatus() != Response.Status.OK.getStatusCode())) { + // Only attempt the PUT if the model doesn't already exist + ClientResponse putResponse = aaiClient.putResource(getUrl(model), model.getPayload(), + distributionId, AaiRestClient.MimeType.XML); + if ((putResponse != null) + && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode())) { + completedModels.add(model); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, model.getType().toString() + " " + + model.getNameVersionId() + " successfully ingested."); + } else { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Ingestion failed for " + model.getType().toString() + " " + model.getNameVersionId() + + ". Rolling back distribution."); + + for (ModelArtifact modelToDelete : completedModels) { + // Best effort to delete. Nothing we can do in the event this fails. + aaiClient.getAndDeleteResource(getUrl(modelToDelete), distributionId); + } + + return false; + } + } else { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, model.getType().toString() + " " + + model.getNameVersionId() + " already exists. Skipping ingestion."); + } + } + + return true; + } + + private String getUrl(ModelArtifact model) { + String baseUrl = config.getAaiBaseUrl().trim(); + String subUrl = null; + if (model.getType().equals(ArtifactType.MODEL)) { + subUrl = config.getAaiModelUrl().trim(); + } else { + subUrl = config.getAaiNamedQueryUrl().trim(); + } + + if ((!baseUrl.endsWith("/")) && (!subUrl.startsWith("/"))) { + baseUrl = baseUrl + "/"; + } + + if (baseUrl.endsWith("/") && subUrl.startsWith("/")) { + baseUrl = baseUrl.substring(0, baseUrl.length() - 1); + } + + if (!subUrl.endsWith("/")) { + subUrl = subUrl + "/"; + } + + String url = baseUrl + subUrl + model.getNameVersionId(); + return url; + } + + /** + * This method is used for the test REST interface to load models without an + * ASDC. + * + * @param payload content of the request + */ + public void loadModelTest(byte[] payload) { + List modelArtifacts = new ArrayList(); + ModelArtifactParser parser = new ModelArtifactParser(); + modelArtifacts.addAll(parser.parse(payload, "Test-Artifact")); + ModelSorter modelSorter = new ModelSorter(); + List sortedModelArtifacts = modelSorter.sort(modelArtifacts); + pushArtifacts(sortedModelArtifacts, "Test-Distribution"); + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java new file mode 100644 index 0000000..625145f --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java @@ -0,0 +1,197 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.model; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.service.ModelLoaderMsgs; +import org.openecomp.modelloader.util.JsonXmlConverter; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +public class ModelArtifactParser { + + private static String MODELS_ELEMENT = "models"; + private static String MODEL_ELEMENT = "model"; + private static String NAMED_QUERIES_ELEMENT = "named-queries"; + private static String NAMED_QUERY_ELEMENT = "named-query"; + private static String MODEL_NAME_VERSION_ID = "model-name-version-id"; + private static String NAMED_QUERY_VERSION_ID = "named-query-uuid"; + private static String RELATIONSHIP_DATA = "relationship-data"; + private static String RELATIONSHIP_KEY = "relationship-key"; + private static String RELATIONSHIP_VALUE = "relationship-value"; + private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-name-version-id"; + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(ModelArtifactParser.class.getName()); + + /** + * This method parses the given artifact payload in byte array format and + * generates a list of model artifacts according to the content. + * + * @param artifactPayload + * artifact content to be parsed + * @param artifactName + * name of the artifact + * @return a list of model artifacts + */ + public List parse(byte[] artifactPayload, String artifactName) { + String payload = new String(artifactPayload); + List modelList = new ArrayList(); + + try { + // Artifact could be JSON or XML + if (JsonXmlConverter.isValidJson(payload)) { + payload = JsonXmlConverter.convertJsonToXml(payload); + } + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(payload)); + Document doc = builder.parse(is); + + if ((doc.getDocumentElement().getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) + || (doc.getDocumentElement().getNodeName().equalsIgnoreCase(NAMED_QUERY_ELEMENT))) { + ModelArtifact model = parseModel(doc.getDocumentElement(), payload); + if (model != null) { + modelList.add(model); + } else { + // TODO: A WARN message? + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Unable to parse artifact " + artifactName); + } + } else if ((doc.getDocumentElement().getNodeName().equalsIgnoreCase(MODELS_ELEMENT)) + || (doc.getDocumentElement().getNodeName().equalsIgnoreCase(NAMED_QUERIES_ELEMENT))) { + // The complete set of models/named-queries were contained in this + // artifact + NodeList nodeList = doc.getDocumentElement().getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + if ((childNode.getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) + || (childNode.getNodeName().equalsIgnoreCase(NAMED_QUERY_ELEMENT))) { + String modelPayload = nodeToString(childNode); + ModelArtifact model = parseModel(childNode, modelPayload); + if (model != null) { + modelList.add(model); + } else { + // TODO: A WARN message? + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Unable to parse artifact " + artifactName); + modelList.clear(); + break; + } + } + } + } + } catch (Exception ex) { + // This may not be an error. We may be receiving an artifact that is + // unrelated + // to models. In this case, we just ignore it. + // TODO: A WARN message? + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Unable to parse artifact " + artifactName + ": " + ex.getLocalizedMessage()); + } + + return modelList; + } + + private ModelArtifact parseModel(Node modelNode, String payload) { + ModelArtifact model = new ModelArtifact(); + model.setPayload(payload); + + if (modelNode.getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) { + model.setType(ArtifactType.MODEL); + } else { + model.setType(ArtifactType.NAMED_QUERY); + } + + parseNode(modelNode, model); + + if (model.getNameVersionId() == null) { + return null; + } + + return model; + } + + private void parseNode(Node node, ModelArtifact model) { + if (node.getNodeName().equalsIgnoreCase(MODEL_NAME_VERSION_ID)) { + model.setNameVersionId(node.getTextContent().trim()); + } else if (node.getNodeName().equalsIgnoreCase(NAMED_QUERY_VERSION_ID)) { + model.setNameVersionId(node.getTextContent().trim()); + } else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { + parseRelationshipNode(node, model); + } else { + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + parseNode(childNode, model); + } + } + } + + private void parseRelationshipNode(Node node, ModelArtifact model) { + String key = null; + String value = null; + + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { + key = childNode.getTextContent().trim(); + } else if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { + value = childNode.getTextContent().trim(); + } + } + + if ((key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY))) { + if (value != null) { + model.addDependentModelId(value); + } + } + } + + private String nodeToString(Node node) throws TransformerException { + StringWriter sw = new StringWriter(); + Transformer transfomer = TransformerFactory.newInstance().newTransformer(); + transfomer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + transfomer.transform(new DOMSource(node), new StreamResult(sw)); + return sw.toString(); + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java new file mode 100644 index 0000000..4dcda71 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java @@ -0,0 +1,233 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.model; + +import jline.internal.Log; + +import org.openecomp.modelloader.entity.Artifact; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +/** + * Utility class to sort the given Models according to their dependencies. + * Example: Given a list of Models [A, B, C] where B depends on A, and A depends + * on C, the sorted result will be [C, A, B] + */ +public class ModelSorter { + + /** + * Wraps a Model object to form dependencies other Models using Edges. + */ + static class Node { + private final ModelArtifact model; + private final HashSet inEdges; + private final HashSet outEdges; + + public Node(ModelArtifact model) { + this.model = model; + inEdges = new HashSet(); + outEdges = new HashSet(); + } + + public Node addEdge(Node node) { + Edge edge = new Edge(this, node); + outEdges.add(edge); + node.inEdges.add(edge); + return this; + } + + @Override + public String toString() { + return model.getNameVersionId(); + } + + @Override + public boolean equals(Object other) { + ModelArtifact otherModel = ((Node) other).model; + return this.model.getNameVersionId().equals(otherModel.getNameVersionId()); + } + + @Override + public int hashCode() { + return this.model.getNameVersionId().hashCode(); + + } + } + + /** + * Represents a dependency between two Nodes. + */ + static class Edge { + public final Node from; + public final Node to; + + public Edge(Node from, Node to) { + this.from = from; + this.to = to; + } + + @Override + public boolean equals(Object obj) { + Edge edge = (Edge) obj; + return edge.from == from && edge.to == to; + } + } + + /** + * Returns the list of models sorted by order of dependency. + * + * @param originalList + * the list that needs to be sorted + * @return a list of sorted models + */ + public List sort(List originalList) { + + if (originalList.size() <= 1) { + return originalList; + } + + Collection nodes = createNodes(originalList); + Collection sortedNodes = sortNodes(nodes); + + List sortedModelsList = new ArrayList(sortedNodes.size()); + for (Node node : sortedNodes) { + sortedModelsList.add(node.model); + } + + return sortedModelsList; + } + + /** + * Create nodes from the list of models and their dependencies. + * + * @param models + * what the nodes creation is based upon + * @return Collection of Node objects + */ + private Collection createNodes(Collection models) { + + // load list of models into a map, so we can later replace referenceIds with + // real Models + HashMap versionIdToModelMap = new HashMap(); + for (Artifact art : models) { + ModelArtifact ma = (ModelArtifact) art; + versionIdToModelMap.put(ma.getNameVersionId(), ma); + } + + HashMap nodes = new HashMap(); + // create a node for each model and its referenced models + for (Artifact art : models) { + ModelArtifact model = (ModelArtifact) art; + + // node might have been created by another model referencing it + Node node = nodes.get(model.getNameVersionId()); + + if (null == node) { + node = new Node(model); + nodes.put(model.getNameVersionId(), node); + } + + for (String referencedModelId : model.getDependentModelIds()) { + // node might have been created by another model referencing it + Node referencedNode = nodes.get(referencedModelId); + + if (null == referencedNode) { + // create node + ModelArtifact referencedModel = versionIdToModelMap.get(referencedModelId); + if (referencedModel == null) { + Log.debug("ignoring " + referencedModelId); + continue; // referenced model not supplied, no need to sort it + } + referencedNode = new Node(referencedModel); + nodes.put(referencedModelId, referencedNode); + } + referencedNode.addEdge(node); + } + } + + return nodes.values(); + } + + /** + * Sorts the given Nodes by order of dependency. + * + * @param originalList + * the collection of nodes to be sorted + * @return a sorted collection of the given nodes + */ + private Collection sortNodes(Collection unsortedNodes) { + + // L <- Empty list that will contain the sorted elements + ArrayList nodeList = new ArrayList(); + + // S <- Set of all nodes with no incoming edges + HashSet nodeSet = new HashSet(); + for (Node unsortedNode : unsortedNodes) { + if (unsortedNode.inEdges.size() == 0) { + nodeSet.add(unsortedNode); + } + } + + // while S is non-empty do + while (!nodeSet.isEmpty()) { + // remove a node n from S + Node node = nodeSet.iterator().next(); + nodeSet.remove(node); + + // insert n into L + nodeList.add(node); + + // for each node m with an edge e from n to m do + for (Iterator it = node.outEdges.iterator(); it.hasNext();) { + // remove edge e from the graph + Edge edge = it.next(); + Node to = edge.to; + it.remove();// Remove edge from n + to.inEdges.remove(edge);// Remove edge from m + + // if m has no other incoming edges then insert m into S + if (to.inEdges.isEmpty()) { + nodeSet.add(to); + } + } + } + // Check to see if all edges are removed + boolean cycle = false; + for (Node node : unsortedNodes) { + if (!node.inEdges.isEmpty()) { + cycle = true; + break; + } + } + if (cycle) { + throw new RuntimeException( + "Circular dependency present between models, topological sort not possible"); + } + + return nodeList; + } + +} diff --git a/src/main/java/org/openecomp/modelloader/notification/DistributionStatusMsg.java b/src/main/java/org/openecomp/modelloader/notification/DistributionStatusMsg.java new file mode 100644 index 0000000..6079d5d --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/notification/DistributionStatusMsg.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.notification; + +import org.openecomp.sdc.api.consumer.IDistributionStatusMessage; +import org.openecomp.sdc.utils.DistributionStatusEnum; + +public class DistributionStatusMsg implements IDistributionStatusMessage { + private DistributionStatusEnum status; + private String distributionId; + private String consumerId; + private String artifactUrl; + + /** + * Creates a new DistributionStatusMsg instance. + * + * @param status - The distribution status to be reported. + * @param distributionId - The identifier of the distribution who's status is being rported on. + * @param consumerId - Identifier of the consumer associated with the distribution. + * @param artifactUrl - Resource identifier for the artifact. + */ + public DistributionStatusMsg(DistributionStatusEnum status, + String distributionId, + String consumerId, + String artifactUrl) { + this.status = status; + this.distributionId = distributionId; + this.consumerId = consumerId; + this.artifactUrl = artifactUrl; + } + + @Override + public long getTimestamp() { + long currentTimeMillis = System.currentTimeMillis(); + return currentTimeMillis; + } + + @Override + public DistributionStatusEnum getStatus() { + return status; + } + + @Override + public String getDistributionID() { + return distributionId; + } + + @Override + public String getConsumerID() { + return consumerId; + } + + @Override + public String getArtifactURL() { + return artifactUrl; + } +} diff --git a/src/main/java/org/openecomp/modelloader/notification/EventCallback.java b/src/main/java/org/openecomp/modelloader/notification/EventCallback.java new file mode 100644 index 0000000..3b32315 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/notification/EventCallback.java @@ -0,0 +1,286 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.notification; + +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.consumer.IDistributionStatusMessage; +import org.openecomp.sdc.api.consumer.INotificationCallback; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.api.notification.IResourceInstance; +import org.openecomp.sdc.api.results.IDistributionClientDownloadResult; +import org.openecomp.sdc.api.results.IDistributionClientResult; +import org.openecomp.sdc.utils.ArtifactTypeEnum; +import org.openecomp.sdc.utils.DistributionActionResultEnum; +import org.openecomp.sdc.utils.DistributionStatusEnum; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.cl.mdc.MdcContext; +import org.openecomp.cl.mdc.MdcOverride; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.catalog.VnfCatalogArtifact; +import org.openecomp.modelloader.entity.catalog.VnfCatalogArtifactHandler; +import org.openecomp.modelloader.entity.model.ModelArtifactHandler; +import org.openecomp.modelloader.entity.model.ModelArtifactParser; +import org.openecomp.modelloader.service.ModelLoaderMsgs; +import org.slf4j.MDC; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +public class EventCallback implements INotificationCallback { + + private IDistributionClient client; + private ModelLoaderConfig config; + private static Logger logger = LoggerFactory.getInstance() + .getLogger(EventCallback.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance() + .getAuditLogger(EventCallback.class.getName()); + private static Logger metricsLogger = LoggerFactory.getInstance() + .getMetricsLogger(EventCallback.class.getName()); + + private static SimpleDateFormat dateFormatter = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + public EventCallback(IDistributionClient client, ModelLoaderConfig config) { + this.client = client; + this.config = config; + } + + @Override + public void activateCallback(INotificationData data) { + // Init MDC + MdcContext.initialize(data.getDistributionID(), "ModelLoader", "", "Event-Bus", ""); + + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Received distribution " + data.getDistributionID()); + + boolean success = true; + List artifacts = getArtifacts(data); + List modelArtifacts = new ArrayList(); + List catalogArtifacts = new ArrayList(); + ModelArtifactParser modelArtParser = new ModelArtifactParser(); + + for (IArtifactInfo artifact : artifacts) { + // Grab the current time so we can measure the download time for the + // metrics log + long startTimeInMs = System.currentTimeMillis(); + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + // Download Artifact + IDistributionClientDownloadResult downloadResult = client.download(artifact); + + // Generate metrics log + metricsLogger.info(ModelLoaderMsgs.DOWNLOAD_COMPLETE, null, override, + artifact.getArtifactName(), downloadResult.getDistributionActionResult().toString()); + + if (downloadResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + publishDownloadFailure(data, artifact, downloadResult.getDistributionMessageResult()); + success = false; + break; + } + + logger.debug("Artifact: " + artifact.getArtifactName() + " Payload:\n" + new String(downloadResult.getArtifactPayload())); + + publishDownloadSuccess(data, artifact, downloadResult); + + if ((artifact.getArtifactType() + .compareToIgnoreCase(ArtifactTypeEnum.MODEL_INVENTORY_PROFILE.toString()) == 0) + || (artifact.getArtifactType() + .compareToIgnoreCase(ArtifactTypeEnum.MODEL_QUERY_SPEC.toString()) == 0)) { + modelArtifacts.addAll(modelArtParser.parse(downloadResult.getArtifactPayload(), + downloadResult.getArtifactName())); + } else if (artifact.getArtifactType() + .compareToIgnoreCase(ArtifactTypeEnum.VNF_CATALOG.toString()) == 0) { + catalogArtifacts + .add(new VnfCatalogArtifact(new String(downloadResult.getArtifactPayload()))); + } + } + + String statusString = "SUCCESS"; + if (success) { + ModelArtifactHandler modelHandler = new ModelArtifactHandler(config); + boolean modelDeploySuccess = modelHandler.pushArtifacts(modelArtifacts, + data.getDistributionID()); + + VnfCatalogArtifactHandler catalogHandler = new VnfCatalogArtifactHandler(config); + boolean catalogDeploySuccess = catalogHandler.pushArtifacts(catalogArtifacts, + data.getDistributionID()); + + for (IArtifactInfo artifact : artifacts) { + if ((artifact.getArtifactType() + .compareToIgnoreCase(ArtifactTypeEnum.MODEL_INVENTORY_PROFILE.toString()) == 0) + || (artifact.getArtifactType() + .compareToIgnoreCase(ArtifactTypeEnum.MODEL_QUERY_SPEC.toString()) == 0)) { + if (modelDeploySuccess) { + publishDeploySuccess(data, artifact); + } else { + publishDeployFailure(data, artifact); + statusString = "FAILURE"; + } + } else if (artifact.getArtifactType() + .compareToIgnoreCase(ArtifactTypeEnum.VNF_CATALOG.toString()) == 0) { + if (catalogDeploySuccess) { + publishDeploySuccess(data, artifact); + } else { + publishDeployFailure(data, artifact); + statusString = "FAILURE"; + } + } + } + } + + auditLogger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Processed distribution " + data.getDistributionID() + " (" + statusString + ")"); + MDC.clear(); + } + + private List getArtifacts(INotificationData data) { + List artifacts = new ArrayList(); + List resources = data.getResources(); + + if (data.getServiceArtifacts() != null) { + artifacts.addAll(data.getServiceArtifacts()); + } + + if (resources != null) { + for (IResourceInstance resource : resources) { + if (resource.getArtifacts() != null) { + artifacts.addAll(resource.getArtifacts()); + } + } + } + + return artifacts; + } + + private void publishDownloadFailure(INotificationData data, IArtifactInfo artifact, + String errorMessage) { + // Grab the current time so we can measure the download time for the metrics + // log + long startTimeInMs = System.currentTimeMillis(); + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + IDistributionClientResult sendDownloadStatus = client.sendDownloadStatus( + buildStatusMessage(client, data, artifact, DistributionStatusEnum.DOWNLOAD_ERROR)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "download failure", + artifact.getArtifactName(), sendDownloadStatus.getDistributionActionResult().toString()); + + if (sendDownloadStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish download failure status: " + + sendDownloadStatus.getDistributionMessageResult()); + } + + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to download artifact " + artifact.getArtifactName() + ": " + errorMessage); + } + + private void publishDownloadSuccess(INotificationData data, IArtifactInfo artifact, + IDistributionClientDownloadResult downloadResult) { + // Grab the current time so we can measure the download time for the metrics + // log + long startTimeInMs = System.currentTimeMillis(); + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + IDistributionClientResult sendDownloadStatus = client.sendDownloadStatus( + buildStatusMessage(client, data, artifact, DistributionStatusEnum.DOWNLOAD_OK)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "download success", + artifact.getArtifactName(), sendDownloadStatus.getDistributionActionResult().toString()); + + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Downloaded artifact: " + artifact.getArtifactName()); + + if (sendDownloadStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish download success status: " + + sendDownloadStatus.getDistributionMessageResult()); + } + + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Downloaded artifact:\n"); + sb.append("ArtInfo_Art_Name: " + artifact.getArtifactName()); + sb.append("\nArtInfo_Art_description: " + artifact.getArtifactDescription()); + sb.append("\nArtInfo_Art_CheckSum: " + artifact.getArtifactChecksum()); + sb.append("\nArtInfo_Art_Url: " + artifact.getArtifactURL()); + sb.append("\nArtInfo_Art_Type: " + artifact.getArtifactType()); + sb.append("\nArtInfo_Serv_description: " + data.getServiceDescription()); + sb.append("\nArtInfo_Serv_Name: " + data.getServiceName()); + sb.append("\nGet_serviceVersion: " + data.getServiceVersion()); + sb.append("\nGet_Service_UUID: " + data.getServiceUUID()); + sb.append("\nArtInfo_DistributionId: " + data.getDistributionID()); + logger.debug(sb.toString()); + } + } + + private void publishDeployFailure(INotificationData data, IArtifactInfo artifact) { + // Grab the current time so we can measure the download time for the metrics + // log + long startTimeInMs = System.currentTimeMillis(); + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + IDistributionClientResult sendStatus = client.sendDeploymentStatus( + buildStatusMessage(client, data, artifact, DistributionStatusEnum.DEPLOY_ERROR)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy failure", + artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); + + if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish deploy failure status: " + sendStatus.getDistributionMessageResult()); + } + } + + private void publishDeploySuccess(INotificationData data, IArtifactInfo artifact) { + // Grab the current time so we can measure the download time for the metrics + // log + long startTimeInMs = System.currentTimeMillis(); + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + IDistributionClientResult sendStatus = client.sendDownloadStatus( + buildStatusMessage(client, data, artifact, DistributionStatusEnum.DEPLOY_OK)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy success", + artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); + + if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish deploy success status: " + sendStatus.getDistributionMessageResult()); + } + } + + private IDistributionStatusMessage buildStatusMessage(IDistributionClient client, + INotificationData data, IArtifactInfo artifact, DistributionStatusEnum status) { + IDistributionStatusMessage statusMessage = new DistributionStatusMsg(status, + data.getDistributionID(), client.getConfiguration().getConsumerID(), + artifact.getArtifactURL()); + + return statusMessage; + } + +} diff --git a/src/main/java/org/openecomp/modelloader/restclient/AaiRestClient.java b/src/main/java/org/openecomp/modelloader/restclient/AaiRestClient.java new file mode 100644 index 0000000..e13bdbd --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/restclient/AaiRestClient.java @@ -0,0 +1,400 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.restclient; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.LoggingFilter; +import com.sun.jersey.client.urlconnection.HTTPSProperties; +import org.openecomp.cl.api.LogFields; +import org.openecomp.cl.api.LogLine; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.cl.mdc.MdcContext; +import org.openecomp.cl.mdc.MdcOverride; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.service.ModelLoaderMsgs; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.StringReader; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.X509Certificate; +import java.text.SimpleDateFormat; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.Response; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +public class AaiRestClient { + public enum MimeType { + XML("application/xml"), JSON("application/json"); + + private String httpType; + + MimeType(String httpType) { + this.httpType = httpType; + } + + String getHttpHeaderType() { + return httpType; + } + } + + private static String HEADER_TRANS_ID = "X-TransactionId"; + private static String HEADER_FROM_APP_ID = "X-FromAppId"; + private static String HEADER_AUTHORIZATION = "Authorization"; + private static String ML_APP_NAME = "ModelLoader"; + private static String RESOURCE_VERSION_PARAM = "resource-version"; + + private static SimpleDateFormat dateFormatter = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(AaiRestClient.class.getName()); + private static Logger metricsLogger = LoggerFactory.getInstance() + .getMetricsLogger(AaiRestClient.class.getName()); + + private ModelLoaderConfig config = null; + + public AaiRestClient(ModelLoaderConfig config) { + this.config = config; + } + + /** + * Send a PUT request to the A&AI. + * + * @param url + * - the url + * @param transId + * - transaction ID + * @param payload + * - the XML or JSON payload for the request + * @param mimeType + * - the content type (XML or JSON) + * @return ClientResponse + */ + public ClientResponse putResource(String url, String payload, String transId, MimeType mimeType) { + ClientResponse result = null; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + long startTimeInMs = 0; + MdcOverride override = new MdcOverride(); + + try { + Client client = setupClient(); + + baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + if (logger.isDebugEnabled()) { + client.addFilter(new LoggingFilter(ps)); + } + + // Grab the current time so that we can use it for metrics purposes later. + startTimeInMs = System.currentTimeMillis(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + if (useBasicAuth()) { + result = client.resource(url).header(HEADER_TRANS_ID, transId) + .header(HEADER_FROM_APP_ID, ML_APP_NAME) + .header(HEADER_AUTHORIZATION, getAuthenticationCredentials()) + .type(mimeType.getHttpHeaderType()).put(ClientResponse.class, payload); + } else { + result = client.resource(url).header(HEADER_TRANS_ID, transId) + .header(HEADER_FROM_APP_ID, ML_APP_NAME).type(mimeType.getHttpHeaderType()) + .put(ClientResponse.class, payload); + } + } catch (Exception ex) { + logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "PUT", url, ex.getLocalizedMessage()); + return null; + } finally { + if (logger.isDebugEnabled()) { + logger.debug(baos.toString()); + } + } + + if ((result != null) && ((result.getStatus() == Response.Status.CREATED.getStatusCode()) + || (result.getStatus() == Response.Status.OK.getStatusCode()))) { + logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "PUT", url, + Integer.toString(result.getStatus())); + metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, + result.getResponseStatus().toString()), + override, "PUT", url, Integer.toString(result.getStatus())); + } else { + // If response is not 200 OK, then additionally log the reason + String respMsg = result.getEntity(String.class); + if (respMsg == null) { + respMsg = result.getStatusInfo().getReasonPhrase(); + } + logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, "PUT", url, + Integer.toString(result.getStatus()), respMsg); + metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, + result.getResponseStatus().toString()), + override, "PUT", url, Integer.toString(result.getStatus()), respMsg); + } + + return result; + } + + /** + * Send a DELETE request to the A&AI. + * + * @param url + * - the url + * @param resourceVersion + * - the resource-version of the model to delete + * @param transId + * - transaction ID + * @return ClientResponse + */ + public ClientResponse deleteResource(String url, String resourceVersion, String transId) { + ClientResponse result = null; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + long startTimeInMs = 0; + MdcOverride override = new MdcOverride(); + + try { + Client client = setupClient(); + + baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + if (logger.isDebugEnabled()) { + client.addFilter(new LoggingFilter(ps)); + } + + // Grab the current time so that we can use it for metrics purposes later. + startTimeInMs = System.currentTimeMillis(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + if (useBasicAuth()) { + result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion) + .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME) + .header(HEADER_AUTHORIZATION, getAuthenticationCredentials()) + .delete(ClientResponse.class); + } else { + result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion) + .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME) + .delete(ClientResponse.class); + } + } catch (Exception ex) { + logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "DELETE", url, ex.getLocalizedMessage()); + return null; + } finally { + if (logger.isDebugEnabled()) { + logger.debug(baos.toString()); + } + } + + logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "DELETE", url, + Integer.toString(result.getStatus())); + metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField( + LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()), + override, "DELETE", url, Integer.toString(result.getStatus())); + + return result; + } + + /** + * Send a GET request to the A&AI for a resource. + * + * @param url + * - the url to use + * @param transId + * - transaction ID + * @return ClientResponse + */ + public ClientResponse getResource(String url, String transId, MimeType mimeType) { + ClientResponse result = null; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + long startTimeInMs = 0; + MdcOverride override = new MdcOverride(); + + try { + Client client = setupClient(); + + baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + if (logger.isDebugEnabled()) { + client.addFilter(new LoggingFilter(ps)); + } + + // Grab the current time so that we can use it for metrics purposes later. + startTimeInMs = System.currentTimeMillis(); + override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); + + if (useBasicAuth()) { + result = client.resource(url).header(HEADER_TRANS_ID, transId) + .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType()) + .header(HEADER_AUTHORIZATION, getAuthenticationCredentials()).get(ClientResponse.class); + } else { + result = client.resource(url).header(HEADER_TRANS_ID, transId) + .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType()) + .get(ClientResponse.class); + + } + } catch (Exception ex) { + logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, ex.getLocalizedMessage()); + return null; + } finally { + if (logger.isDebugEnabled()) { + logger.debug(baos.toString()); + } + } + + logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "GET", url, + Integer.toString(result.getStatus())); + metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField( + LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()), + override, "GET", url, Integer.toString(result.getStatus())); + + return result; + } + + /** + * Does a GET on a resource to retrieve the resource version, and then DELETE + * that version. + * + * @param url + * - the url + * @param transId + * - transaction ID + * @return ClientResponse + */ + public ClientResponse getAndDeleteResource(String url, String transId) { + // First, GET the model + ClientResponse getResponse = getResource(url, transId, MimeType.XML); + if ((getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode())) { + return getResponse; + } + + // Delete the model using the resource version in the response + String resVersion = null; + try { + resVersion = getResourceVersion(getResponse); + } catch (Exception e) { + logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, e.getLocalizedMessage()); + return null; + } + + return deleteResource(url, resVersion, transId); + } + + private Client setupClient() throws IOException, GeneralSecurityException { + ClientConfig clientConfig = new DefaultClientConfig(); + + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String string, SSLSession ssls) { + return true; + } + }); + + // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } }; + + SSLContext ctx = SSLContext.getInstance("TLS"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + FileInputStream fin = new FileInputStream(config.getAaiKeyStorePath()); + KeyStore ks = KeyStore.getInstance("PKCS12"); + char[] pwd = config.getAaiKeyStorePassword().toCharArray(); + ks.load(fin, pwd); + kmf.init(ks, pwd); + + ctx.init(kmf.getKeyManagers(), trustAllCerts, null); + clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, + new HTTPSProperties(new HostnameVerifier() { + @Override + public boolean verify(String theString, SSLSession sslSession) { + return true; + } + }, ctx)); + + Client client = Client.create(clientConfig); + + return client; + } + + private String getResourceVersion(ClientResponse response) + throws ParserConfigurationException, SAXException, IOException { + String respData = response.getEntity(String.class); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(respData)); + Document doc = builder.parse(is); + + NodeList nodeList = doc.getDocumentElement().getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node currentNode = nodeList.item(i); + if (currentNode.getNodeName().equals(RESOURCE_VERSION_PARAM)) { + return currentNode.getTextContent(); + } + } + + return null; + } + + private String getAuthenticationCredentials() { + + String usernameAndPassword = config.getAaiAuthenticationUser() + ":" + + config.getAaiAuthenticationPassword(); + return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes()); + } + + public boolean useBasicAuth() { + return (config.getAaiAuthenticationUser() != null) + && (config.getAaiAuthenticationPassword() != null); + } +} diff --git a/src/main/java/org/openecomp/modelloader/service/ModelLoaderInterface.java b/src/main/java/org/openecomp/modelloader/service/ModelLoaderInterface.java new file mode 100644 index 0000000..689115e --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/service/ModelLoaderInterface.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.service; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +public interface ModelLoaderInterface { + + @GET + @Path("/loadModel/{modelid}") + public Response loadModel(@PathParam("modelid") String modelid); + + @PUT + @Path("/saveModel/{modelid}/{modelname}") + public Response saveModel(@PathParam("modelid") String modelid, + @PathParam("modelname") String modelname); + + @POST + @Consumes("application/xml") + @Produces("application/xml") + @Path("/ingestModel/{modelid}") + public Response ingestModel(@PathParam("modelid") String modelid, @Context HttpServletRequest req, + String payload) throws IOException; +} diff --git a/src/main/java/org/openecomp/modelloader/service/ModelLoaderMsgs.java b/src/main/java/org/openecomp/modelloader/service/ModelLoaderMsgs.java new file mode 100644 index 0000000..b81c541 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/service/ModelLoaderMsgs.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.service; + +import com.att.eelf.i18n.EELFResourceManager; + +import org.openecomp.cl.eelf.LogMessageEnum; + +public enum ModelLoaderMsgs implements LogMessageEnum { + + /** + * Arguments: None. + */ + LOADING_CONFIGURATION, + + /** + * Arguments: None. + */ + STOPPING_CLIENT, + + /** + * Arguments: {0} = message. + */ + INITIALIZING, + + /** + * Arguments: {0} = reason. + */ + ASDC_CONNECTION_ERROR, + + /** + * Arguments: {0} = message. + */ + DISTRIBUTION_EVENT, + + /** + * Arguments: {0} = error message. + */ + DISTRIBUTION_EVENT_ERROR, + + /** + * Arguments: {0} = request type. + * {1} = endpoint. + * {2} = result code. + */ + AAI_REST_REQUEST_SUCCESS, + + /** + * Arguments: {0} = request type. + * {1} = endpoint. + * {2} = result code. + * {3} = result. + * message + */ + AAI_REST_REQUEST_UNSUCCESSFUL, + + /** + * Arguments: {0} = request type. + * {1} = endpoint. + * {2} = error message. + */ + AAI_REST_REQUEST_ERROR, + + /** + * Arguments: {0} = artifact name. + * {1} = result. + */ + DOWNLOAD_COMPLETE, + + /** + * Arguments: {0} = event. + * {1} = artifact name. + * {2} = result. + */ + EVENT_PUBLISHED; + + /** + * Load message bundle (ModelLoaderMsgs.properties file) + */ + static { + EELFResourceManager.loadMessageBundle("org/openecomp/modelloader/service/ModelLoaderMsgs"); + } + +} diff --git a/src/main/java/org/openecomp/modelloader/service/ModelLoaderService.java b/src/main/java/org/openecomp/modelloader/service/ModelLoaderService.java new file mode 100644 index 0000000..16aba7e --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/service/ModelLoaderService.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.service; + +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.results.IDistributionClientResult; +import org.openecomp.sdc.impl.DistributionClientFactory; +import org.openecomp.sdc.utils.DistributionActionResultEnum; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.model.ModelArtifactHandler; +import org.openecomp.modelloader.notification.EventCallback; + +import java.io.IOException; +import java.util.Properties; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Response; + +/** + * Service class in charge of managing the negotiating model loading + * capabilities between AAI and an ASDC. + */ +public class ModelLoaderService implements ModelLoaderInterface { + + protected static String CONFIG_FILE = "model-loader.properties"; + + private IDistributionClient client; + private ModelLoaderConfig config; + + static Logger logger = LoggerFactory.getInstance().getLogger(ModelLoaderService.class.getName()); + + /** + * Responsible for loading configuration files and calling initialization. + */ + @PostConstruct + protected void start() { + // Load model loader system configuration + logger.info(ModelLoaderMsgs.LOADING_CONFIGURATION); + Properties configProperties = new Properties(); + try { + configProperties.load(this.getClass().getClassLoader().getResourceAsStream(CONFIG_FILE)); + } catch (IOException e) { + String errorMsg = "Failed to load configuration: " + e.getMessage(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + shutdown(); + } + + config = new ModelLoaderConfig(configProperties); + init(); + } + + /** + * Responsible for stopping the connection to the distribution client before + * the resource is destroyed. + */ + @PreDestroy + protected void preShutdownOperations() { + logger.info(ModelLoaderMsgs.STOPPING_CLIENT); + if (client != null) { + client.stop(); + } + } + + /** + * Responsible for loading configuration files, initializing model + * distribution clients, and starting them. + */ + protected void init() { + // Initialize distribution client + logger.debug(ModelLoaderMsgs.INITIALIZING, "Initializing distribution client..."); + client = DistributionClientFactory.createDistributionClient(); + IDistributionClientResult initResult = client.init(config, new EventCallback(client, config)); + if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + String errorMsg = "Failed to initialize distribution client: " + + initResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + shutdown(); + } + + // Start distribution client + logger.debug(ModelLoaderMsgs.INITIALIZING, "Starting distribution client..."); + IDistributionClientResult startResult = client.start(); + if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + String errorMsg = "Failed to start distribution client: " + + startResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + shutdown(); + } + + logger.debug(ModelLoaderMsgs.INITIALIZING, + "Succcessfully loaded service: " + this.getClass().getSimpleName()); + } + + /** + * Shut down the process. + */ + private void shutdown() { + preShutdownOperations(); + + // TODO: Find a better way to shut down the model loader. + try { + // Give logs time to write to file + Thread.sleep(2000); + } catch (InterruptedException e) { + // Nothing we can do at this point + } + + Runtime.getRuntime().halt(1); + } + + /** (non-Javadoc) + * @see org.openecomp.modelloader.service.ModelLoaderInterface#loadModel(java.lang.String) + */ + @Override + public Response loadModel(String modelid) { + Response response = Response.ok("{\"model_loaded\":\"" + modelid + "\"}").build(); + + return response; + } + + /** (non-Javadoc) + * @see org.openecomp.modelloader.service.ModelLoaderInterface#saveModel(java.lang.String, java.lang.String) + */ + @Override + public Response saveModel(String modelid, String modelname) { + Response response = Response.ok("{\"model_saved\":\"" + modelid + "-" + modelname + "\"}") + .build(); + + return response; + } + + @Override + public Response ingestModel(String modelid, HttpServletRequest req, String payload) + throws IOException { + Response response; + + if (config.getIngestSimulatorEnabled()) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Received test artifact"); + + ModelArtifactHandler handler = new ModelArtifactHandler(config); + handler.loadModelTest(payload.getBytes()); + + response = Response.ok().build(); + } else { + logger.debug("Simulation interface disabled"); + response = Response.serverError().build(); + } + + return response; + } +} diff --git a/src/main/java/org/openecomp/modelloader/util/JsonXmlConverter.java b/src/main/java/org/openecomp/modelloader/util/JsonXmlConverter.java new file mode 100644 index 0000000..ca63b23 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/util/JsonXmlConverter.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.util; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.XML; + +public class JsonXmlConverter { + + /** + * Determines whether or not the supplied text string represents a valid + * JSON structure or not. + * + * @param text - The text to be evaluated. + * + * @return - true if the string represents a valid JSON object, + * false, otherwise. + */ + public static boolean isValidJson(String text) { + try { + new JSONObject(text); + } catch (JSONException ex) { + try { + new JSONArray(text); + } catch (JSONException ex1) { + return false; + } + } + + return true; + } + + /** + * Takes a text string representing a valid JSON structure and converts it to + * an equivalent XML string. + * + * @param jsonText - The JSON string to convert to XML. + * + * @return - An XML string representation of the supplied JSON string. + */ + public static String convertJsonToXml(String jsonText) { + JSONObject jsonObj = new JSONObject(jsonText); + String xmlText = XML.toString(jsonObj); + return xmlText; + } + + /** + * Takes a text string representing a valid XML structure and converts it to + * an equivalent JSON string. + * + * @param xmlText - The XML string to convert to JSON. + * + * @return - A JSON string representation of the supplied XML string. + */ + public static String convertXmlToJson(String xmlText) { + JSONObject jsonObj = XML.toJSONObject(xmlText); + return jsonObj.toString(); + } +} diff --git a/src/main/resources/aai-os-cert.p12 b/src/main/resources/aai-os-cert.p12 new file mode 100644 index 0000000000000000000000000000000000000000..ee57120fa0d5e5089c351930e668b87bde52e7e6 GIT binary patch literal 4357 zcmY+GWl$81w}%CmZdkg(C0E#`yX!?3kPbmgq(Mqj$wj1F=|(!2TsoHS6cD5v$wfi9 zzBBjU|Ggj1oSEl0=X`yBkWg|AObjeYC>aU|pBJtUM-yYc}@Tc-6n*90=X8$wx6RfnjED!$OUCM_G~*B8_-8GV{s ziZYnh-o^U3PKG!OGY?g9=RQL%$nnff&PK7}*S@JIzHGo$pxZIa(?O}NpfXuPs&*=* zvu>YHw3mpeHo3nhSYjRSo_p1QRE^EjQ4P9&}u=2oS>}^u+w;pvnmd;bGO_s`h zuohz_9*s$;l*0uXe!bN-!E?FpY-wdN^dHkAVoMwkpInKq-^nlVKWrIQ#@9isexbK0 zSP+Qd&PjcqKS~3fz+2Xj%Q6LaMg|1cd>PJJ0K2TAC+$X@M7@0w3%@u}S@)3ovS;Ll z${i{3Ezk2AI@RYSRrij+TDFrTcg@zNew!#RWa1sBLaW#jm7TPUi7xGwAHLFhO@KL_cKJ_$foWyun6h{`m3?gJU3Lcq&SbMsBb#9#b zHvJSMYu}A`XLn20&(W>#^cs{fl}Fj12v>?ougHZDwkgPsFz1*F=zvS#FK9~h!Ms)g`>_pQ z(~Ms|RY5;ZVW9We#1&B5_BHEF`I!UQEHxd(*_FNDi(l;~8QOAPM$-ce{gbf?j zt}}Oe5YnI24y!k4=v<8!9~Hq*%LxH?crdpdh9m}tWCb2-!3W~2o3aw2FLTldQ9WgW z9a0}F-Wz}2*Y2Qz#B@<(4s%tc$m6O~W%P&w$*C79mzXw0*dt{b`!#J|qyDij86-6) zfDlQJq9k~@jz1#wEjC%lsN#f4zvYRjGo0ep2L>3*QX&qWE@*olY#S0_RgraXzL%4} zbN3f@h-n1-C%n4o1|j+#cuOAc7G!(2JOlJHKl(~KC!Tc^~GV)bJhPQrq&lB(h9?*fKuWrxh!JOvT7gc2&&*2SVa`o_1lW~10& zJizmln{QCG7$VOK+6rH%i568UmQfloVY~WrNy1az+qI9YxHI)HbntT6+?mIwXsStB z3Civ)5%Ng@t+KT$C>n)run%mYBJ&#k4mND(ajKQ2n&D?+grwx2$!!abd`Fc7a%+Y5 zVONJ{F}ytUa)(z)?iNR1bGHXO3o5_yZ5$!9Rb3eKsRN7$;0OQlx;&aJ!60~G*v}et zEAV4jHAN#ew2&h-k(YX&UpM}zGUckh=T**_22KEL-qU26HSlgpAl!|~TXO!= z6H71C%X9vp<-BPTYLSMulsqe+k~9iUy=d*-%S*rzELT3OpZh0>#!*XrVs`g#G)(pt z|F1#7r+(gBRjxE?k!SuMTDK8<)G4!7ruTP3K51@yfZ4@J*qd9 z9GPejpmng)M&N>>vwo3#5a~Mi-ZSf`0p1%01bg-Oi1&PC-h4 zI|o~~r^?voQa~LuirPb5TO_4c7&ML$V$0(TILT-SUXIRJV{CmxU47qG+i<^0mPN;R z$HF(`k<v~_$Rb?flRvtN53hzB1US7lr5 zkLJscq9j>q$*>f}(=e--KbH@AfU>yMrgr03965k`<$Os?Q<-jYXD%wES)A{kB{L6+E6%UFbq4+)jM`(GW`1OEL{OZ5B{O^?D5dM$e z2rw}JhOU31;68!jyC` zJJ36mFFRL1Z@J2~*UL?|Ctw&ElVv-hOh<&M`-o} zN=>ykkSVstDFrrx9=uoe%I6wcWN;b>x}_8omAQWu=vJ7lrxUbzU+iMXNwRBXsVppf zb9gefemo003b?c1qfH2yKe>tOY5CCIKItVNCUN4v3E0G)0?G)ZZyNd0zJT1c-86Y0 zM&k_mh~(Vkx~B02bM=1P{QThXwub`c-?=`XLj0LmdVB1w(n0+ziAhcA6G>j`+~UOZ zKI^9;RpnuMWmjc6L2l@*ZzFMum;ABDW>PZ-mxV%E46Ps!-^r_|jbc}4#xZ433?5uTFPzR@JesCbjM%!I!MGa`TU8 zs=!}M1FWympFuNn6XUGjM!pV1D&qdxN*oukQs50(k|2mB!_hM$!ZzPI5s^AdJELEo z>>mFRXQ3{0E6WD%$zG=csxmoKs7qvcv^FQQD4rXP0vle^+xd)h9?-$ViDvAMi%606 z-So&At?Iq}FRYGd3Vd}M9CY44@S*a0l0-lYYq~4pty?m>1K)Dp>Pw|L^BYRXc(L(+ z6vc0+JEw->d|0N@IH97+bLg=&PC8O7iR;|0we-XFf{Z>Jbyi~g-;>Gv{9i^tMlgZ~ zw8N@Xjtc7eOUm=|8b44<4mb`_{zu4rF;4n9wp5$1@V3cr%{oQ4*Eq%N;u+IELf2;bK( z6IOO6Y79hc%aUE=_w{EwenJj0GWRL;+=ROw&J{z=?8Np(#(FvyB)W(hK3z=!tC1I> zRSMqwWhB0@jf5c~!bZc0z`7c`?){yUPNx#YD;l6mFbTG`Z%lKEuFWBRliL=pFF2(a z3p-U)`{W8ih|l;G6#PVf8bwrUL@@bAm^Gj5Q?{_Q(2+F%N>|RQM*lea)dW7Vzrfv9X;09sr(?k zcqBSC7+~k?IJh6-+gr+V4>0G$LBSn%mpB@JPGu>7+{4xe-Bv~IA`%E)ZM6C3O$?chb&0?IzI%^7Gj+1KbYHl4V zPd}=`I=Ez_VtV=(SI{rxSOCzvx*vv3Q=+*hdGlU-W3}MM-1EA)caf}Cic9>ua#MOh z@Oo|)U%Fs~{VoYQK4}6uPljxhqcSpFK>7c9?6@fqI?`f&* zA467o<~lO^#LxjxZa|5jL)^n$4#hv1^Iye5WjzMsJDK{~dKV+wwr{soN03}MZwoD( zJj%p?iNymqxlqt+m{9VEr&VT!2I{pJBApl1{3CC<)=uZkJI3v<_=R}f>8Wrrkq9qP zub5ZfK=0ji!BD)9-C@BHzG%*Yaf;v`DkVyH)7uPYy3Ju59I#Oeeab~$1VuO6ILW^8 z`&3q_!%_d&XkF(xmB5~&cQ=);3n*-inFX;FZ~QYPh0pX(k-NX&ow}r+#AyC5`S0gLgGh6~v zJCJ~Zj&pc(@HU1yS=ZmKFUA(m z?2v-5!RZw?^{A{_iOpu%Xry-)qJvOBkh$rzoqb^Osz_gh+wIKi?8*Dc`?WwriOdJJfZQp(Z|PX`lV$(0CaO{K{Rviq>H5%=~8D;ubGJCfLy-V zWjl@%Ge+gMiVE8BA=z5FHl>?3aXd(VnHb|tS(o^QBsje{!=FXuLpv%<;hLq(0%oKL!rNz^E;^m^+UbCB~)FV23k zWz}HN_TwlFyw}$9LnnxZ25vhQzLZCPqln#wF5jGul}VbuKnQz%6MWTzRw0xzD(9<9 zJN1uZ-=(SuOwSbQINb2pu}mnmACAsDqdEr`k-c`eE;Rp6p5Z<1yRh_4QD)jhs2O zJbA(CWeBAHym(FDe_H^S_Ll}f4UX#nhQAuwLL_E7Skp46DH(JywX~2fjZ*Wvvb4^r0|Lnbi2KQZPQt| zrh;fRwBdtHoyTDx7dzGYQ;Hz>Qn2bl6<<=M<;v02orfS64W{Yz{+}pC_!|fm!Un;|!R8~u s!lcK30s!`$(Z1lZj{F4bjFD-@{t`5Fq;~?qQ!4r1OqX>o@o!7}FACd2%K!iX literal 0 HcmV?d00001 diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..48233fe --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ${defaultPattern} + + + + + + + + + + + ${logDirectory}/${generalLogName}.log + + ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip + 60 + + + ${errorLogPattern} + + + + + + INFO + + 256 + + + + + + ${logDirectory}/${auditLogName}.log + + ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip + 60 + + + ${auditMetricPattern} + + + + 256 + + + + + + ${logDirectory}/${metricsLogName}.log + + ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip + 60 + + + ${auditMetricPattern} + + + + 256 + + + + + + ${logDirectory}/${debugLogName}.log + + ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip + 60 + + + ${errorLogPattern} + + + + 256 + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/model-loader.properties b/src/main/resources/model-loader.properties new file mode 100644 index 0000000..7b8f63d --- /dev/null +++ b/src/main/resources/model-loader.properties @@ -0,0 +1,43 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# Model Loader Distribution Client Configuration +ml.distribution.ACTIVE_SERVER_TLS_AUTH=false +ml.distribution.ASDC_ADDRESS= +ml.distribution.CONSUMER_GROUP=aai-ml-group +ml.distribution.CONSUMER_ID=aai-ml +ml.distribution.ENVIRONMENT_NAME= +ml.distribution.KEYSTORE_PASSWORD= +ml.distribution.KEYSTORE_FILE=asdc-client.jks +ml.distribution.PASSWORD= +ml.distribution.POLLING_INTERVAL=30 +ml.distribution.POLLING_TIMEOUT=20 +ml.distribution.USER=ci +ml.distribution.ARTIFACT_TYPES=MODEL_INVENTORY_PROFILE,MODEL_QUERY_SPEC,VNF_CATALOG + +# Model Loader AAI REST Client Configuration +ml.aai.BASE_URL= +ml.aai.MODEL_URL=/aai/v8/service-design-and-creation/models/model/ +ml.aai.NAMED_QUERY_URL=/aai/v8/service-design-and-creation/named-queries/named-query/ +ml.aai.VNF_IMAGE_URL=/aai/v8/service-design-and-creation/vnf-images +ml.aai.KEYSTORE_FILE=aai-os-cert.p12 +ml.aai.KEYSTORE_PASSWORD= +ml.aai.AUTH_USER=ModelLoader +ml.aai.AUTH_PASSWORD= diff --git a/src/main/resources/org/openecomp/modelloader/filemonitor/FileMonitorMsgs.properties b/src/main/resources/org/openecomp/modelloader/filemonitor/FileMonitorMsgs.properties new file mode 100644 index 0000000..9abd55c --- /dev/null +++ b/src/main/resources/org/openecomp/modelloader/filemonitor/FileMonitorMsgs.properties @@ -0,0 +1,81 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has atleast one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## + +#AVAILABILITY ERRORS + +LOADING_FROM_FILE=\ + FILEMON2001I|\ + Loading service properties from file {0}|\ + None. Attempting to load file|\ + Attempting to load service properties from the given service file + +FILE_SUCCESSFULLY_LOADED=\ + FILEMON2002I|\ + File {0} is loaded into the map and the corresponding system properties have been refreshed|\ + None. Successfully loaded file|\ + The given service file and its properties were successfully loaded + +FILE_CANNOT_BE_LOADED=\ + FILEMON2003E|\ + File {0} cannot be loaded into the map|\ + Please check the file permissions and format of the file|\ + Unable to load the given service file due to an error + +CANNOT_READ_FILE_STREAM=\ + FILEMON2004E|\ + Error reading the file stream for file {0}|\ + Please ensure that the file exists and the permissions are set correctly|\ + Unable to read the file stream for the given file + +#UNKNOWN ERRORS + +FILE_LISTENER_ATTACH_FAILED=\ + FILEMON9002W|\ + Unable to attach file change listener to file {0} due to an internal error|\ + Failed to attach file change listener to the given file. Please check the reported exception for details|\ + The file will not be actively monitored for changes + + +PROP_MAP_CREATION_FAILED=\ + FILEMON9001E|\ + Internal Error occurred while creating property map for service files|\ + Error occurred due to an internal issue. Please check the reported exception for details |\ + Failed to create a property map for the service files diff --git a/src/main/resources/org/openecomp/modelloader/service/ModelLoaderMsgs.properties b/src/main/resources/org/openecomp/modelloader/service/ModelLoaderMsgs.properties new file mode 100644 index 0000000..53c96dc --- /dev/null +++ b/src/main/resources/org/openecomp/modelloader/service/ModelLoaderMsgs.properties @@ -0,0 +1,112 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has at least one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## + +# INFO Level Logs +LOADING_CONFIGURATION=\ + MDLSVC0001I|\ + Loading configuration |\ + None. Attempting to load configuration|\ + Attempting to load Model Loader Service configuration + +STOPPING_CLIENT=\ + MDLSVC0002I|\ + Stopping distribution client|\ + None. Stopping service|\ + Stopping the Model Service distribution client + +DISTRIBUTION_EVENT=\ + MDLSVC0003I|\ + Distribution event: {0}|\ + None. Processing distribution.|\ + A distribution event was received from the ASDC + +AAI_REST_REQUEST_SUCCESS=\ + MDLSVC0004I|\ + Sent {0} request to {1}. Response: {2}|\ + None. Successfully sent REST request to AAI.|\ + The given request was sent to the specified endpoint. + +AAI_REST_REQUEST_UNSUCCESSFUL=\ + MDLSVC0005I|\ + Sent {0} request to {1}. Response code: {2}, Response message: {3}|\ + REST request to AAI unsuccessful. Check response code, and message. |\ + The given request was unsuccessful. + +DOWNLOAD_COMPLETE=\ + MDLSVC0006I|\ + Download of artifact {0} from ASDC complete. Result: {1}|\ + None.|\ + An artifact was downloaded from the ASDC + +EVENT_PUBLISHED=\ + MDLSVC0007I|\ + Published {0} event for artifact {1}. Result: {2}|\ + None.|\ + An event was published to the event bus + +# ERROR Level Logs +ASDC_CONNECTION_ERROR=\ + MDLSVC2001E|\ + Unable to register with ASDC: {0}|\ + Check configuration. Check network connection to ASDC|\ + During initialization, was not able to register with the configured ASDC instance + +DISTRIBUTION_EVENT_ERROR=\ + MDLSVC2002E|\ + Distribution event error: {0}|\ + Check configuration. Check network connection to ASDC and UEB|\ + A failure occurred processing a distribution event + +AAI_REST_REQUEST_ERROR=\ + MDLSVC2003E|\ + Failed to send {0} request to {1}: {2}|\ + Check configuration. Check network connection to AAI.|\ + A failure occurred attempting to send a request to the AAI + +# DEBUG Level Logs +INITIALIZING=\ + MDLSVC0001D|\ + init(): {0}|\ + None. Initializing service|\ + Debug information during model loader initialization + + diff --git a/src/main/resources/schema/aai_schema_v8.xsd b/src/main/resources/schema/aai_schema_v8.xsd new file mode 100644 index 0000000..66bc3db --- /dev/null +++ b/src/main/resources/schema/aai_schema_v8.xsd @@ -0,0 +1,2462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/schema/vnfcatalog.xsd b/src/main/resources/schema/vnfcatalog.xsd new file mode 100644 index 0000000..9789124 --- /dev/null +++ b/src/main/resources/schema/vnfcatalog.xsd @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/applicationContext.xml b/src/main/webapp/WEB-INF/applicationContext.xml new file mode 100644 index 0000000..efca1ce --- /dev/null +++ b/src/main/webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/rest-servlet.xml b/src/main/webapp/WEB-INF/rest-servlet.xml new file mode 100644 index 0000000..e976951 --- /dev/null +++ b/src/main/webapp/WEB-INF/rest-servlet.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..7be34e7 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,20 @@ + + + model-loader + + + + org.springframework.web.context.ContextLoaderListener + + + + + rest + org.springframework.web.servlet.DispatcherServlet + 1 + + + rest + / + + \ No newline at end of file diff --git a/src/test/java/org/openecomp/modelloader/config/ModelLoaderConfigTest.java b/src/test/java/org/openecomp/modelloader/config/ModelLoaderConfigTest.java new file mode 100644 index 0000000..4018f14 --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/config/ModelLoaderConfigTest.java @@ -0,0 +1,122 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.Properties; + +import org.eclipse.jetty.util.security.Password; +import org.junit.Test; +import org.openecomp.modelloader.restclient.AaiRestClient; + +import org.openecomp.sdc.utils.ArtifactTypeEnum; + +public class ModelLoaderConfigTest { + + @Test + public void testYangModelArtifactType() { + Properties props = new Properties(); + props.setProperty("ml.distribution.ARTIFACT_TYPES", + "MODEL_INVENTORY_PROFILE,MODEL_QUERY_SPEC,VNF_CATALOG"); + ModelLoaderConfig config = new ModelLoaderConfig(props); + + List types = config.getRelevantArtifactTypes(); + + System.out.println("ArtifactType: " + types.get(0)); + assertEquals(0, + types.get(0).compareToIgnoreCase(ArtifactTypeEnum.MODEL_INVENTORY_PROFILE.toString())); + + System.out.println("ArtifactType: " + types.get(1)); + assertEquals(0, types.get(1).compareToIgnoreCase(ArtifactTypeEnum.MODEL_QUERY_SPEC.toString())); + + System.out.println("ArtifactType: " + types.get(2)); + assertEquals(0, types.get(2).compareToIgnoreCase(ArtifactTypeEnum.VNF_CATALOG.toString())); + + assertEquals(3, types.size()); + } + + @Test + public void testDecryptPassword() { + Properties props = new Properties(); + String testPass = "youshallnotpass"; + String encryptedTestPass = Password.obfuscate(testPass); + + System.out.println("Encrypt " + testPass + " ==> " + encryptedTestPass); + + props.put(ModelLoaderConfig.PROP_ML_DISTRIBUTION_PASSWORD, encryptedTestPass); + ModelLoaderConfig config = new ModelLoaderConfig(props); + + assertEquals(testPass, config.getPassword()); + } + + @Test + public void testDecryptKeystorePassword() { + Properties props = new Properties(); + String testPass = "youshallnotpass"; + String encryptedTestPass = Password.obfuscate(testPass); + + System.out.println("Encrypt " + testPass + " ==> " + encryptedTestPass); + + props.put(ModelLoaderConfig.PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD, encryptedTestPass); + ModelLoaderConfig config = new ModelLoaderConfig(props); + + assertEquals(testPass, config.getKeyStorePassword()); + } + + @Test + public void testDecryptAAIPassword() { + + Properties props = new Properties(); + String testPassword = "myvoiceismypassword"; + String encryptedTestPassword = Password.obfuscate(testPassword); + + props.put(ModelLoaderConfig.PROP_AAI_AUTHENTICATION_PASSWORD, encryptedTestPassword); + ModelLoaderConfig config = new ModelLoaderConfig(props); + + assertEquals(testPassword, config.getAaiAuthenticationPassword()); + } + + @Test + public void testNoAAIAuth() throws IOException { + + Properties props = new Properties(); + props.load( + new FileInputStream("src/test/resources/model-loader-empty-auth-password.properties")); + + ModelLoaderConfig config = new ModelLoaderConfig(props); + AaiRestClient aaiClient = new AaiRestClient(config); + + assertFalse("Empty AAI Password should result in no basic authentication", + aaiClient.useBasicAuth()); + + props.load(new FileInputStream("src/test/resources/model-loader-no-auth-password.properties")); + config = new ModelLoaderConfig(props); + aaiClient = new AaiRestClient(config); + + assertFalse("No AAI Password should result in no basic authentication", + aaiClient.useBasicAuth()); + } +} diff --git a/src/test/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandlerTest.java b/src/test/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandlerTest.java new file mode 100644 index 0000000..1b1d955 --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/entity/catalog/VnfCatalogArtifactHandlerTest.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.catalog; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.restclient.AaiRestClient; +import org.openecomp.modelloader.restclient.AaiRestClient.MimeType; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.sun.jersey.api.client.ClientResponse; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ VnfCatalogArtifactHandler.class, ClientResponse.class, AaiRestClient.class }) +public class VnfCatalogArtifactHandlerTest { + + protected static String CONFIG_FILE = "model-loader.properties"; + + @Test + public void testWithMocks() throws Exception { + + Properties configProperties = new Properties(); + try { + configProperties.load(this.getClass().getClassLoader().getResourceAsStream(CONFIG_FILE)); + } catch (IOException e) { + fail(); + } + ModelLoaderConfig config = new ModelLoaderConfig(configProperties); + + ClientResponse mockGetResp = PowerMockito.mock(ClientResponse.class); + PowerMockito.when(mockGetResp.getStatus()).thenReturn(200).thenReturn(200).thenReturn(404) + .thenReturn(404).thenReturn(200); // only second two will be PUT + ClientResponse mockPutResp = PowerMockito.mock(ClientResponse.class); + PowerMockito.when(mockPutResp.getStatus()).thenReturn(201); + + AaiRestClient mockRestClient = PowerMockito.mock(AaiRestClient.class); + PowerMockito.whenNew(AaiRestClient.class).withAnyArguments().thenReturn(mockRestClient); + PowerMockito.when(mockRestClient.getResource(Mockito.anyString(), Mockito.anyString(), + Mockito.any(MimeType.class))).thenReturn(mockGetResp); + PowerMockito.when(mockRestClient.putResource(Mockito.anyString(), Mockito.anyString(), + Mockito.anyString(), Mockito.any(MimeType.class))).thenReturn(mockPutResp); + + VnfCatalogArtifactHandler vnfCAH = new VnfCatalogArtifactHandler(config); + + String examplePath = "src/test/resources/vnfcatalogexample.xml"; + + byte[] encoded = Files.readAllBytes(Paths.get(examplePath)); + String payload = new String(encoded, "utf-8"); + + VnfCatalogArtifact artifact = new VnfCatalogArtifact(payload); + List artifacts = new ArrayList(); + artifacts.add(artifact); + + String distributionID = "test"; + + assertTrue(vnfCAH.pushArtifacts(artifacts, distributionID)); + // times(2) bc with above get returns should only get to this part twice + ArgumentCaptor argument = ArgumentCaptor.forClass(String.class); + Mockito.verify(mockRestClient, Mockito.times(2)).putResource(Mockito.anyString(), + argument.capture(), Mockito.anyString(), Mockito.any(MimeType.class)); + assertTrue(argument.getAllValues().get(0).contains("5.2.5")); + assertTrue(argument.getAllValues().get(1).contains("5.2.4")); + } +} diff --git a/src/test/java/org/openecomp/modelloader/entity/model/ModelArtifactParserTest.java b/src/test/java/org/openecomp/modelloader/entity/model/ModelArtifactParserTest.java new file mode 100644 index 0000000..448e5d3 --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/entity/model/ModelArtifactParserTest.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.model; + +import static org.junit.Assert.assertTrue; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +import org.junit.Test; +import org.openecomp.modelloader.entity.Artifact; + +public class ModelArtifactParserTest { + + @Test + public void testParseModelFileNoDeps() throws Exception { + final String MODEL_FILE = "src/test/resources/models/vnf-model.xml"; + + try { + byte[] xmlBytes = Files.readAllBytes(Paths.get(MODEL_FILE)); + + ModelArtifactParser parser = new ModelArtifactParser(); + List modelList = parser.parse(xmlBytes, "test-artifact"); + + assertTrue(modelList.size() == 1); + + ModelArtifact model = (ModelArtifact) modelList.get(0); + System.out.println(model.toString()); + + assertTrue(model.getNameVersionId().equalsIgnoreCase("model-vid")); + assertTrue(model.getType().toString().equalsIgnoreCase("MODEL")); + assertTrue(model.getDependentModelIds().size() == 0); + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } + } + + @Test + public void testParseModelFileDeps() throws Exception { + final String MODEL_FILE = "src/test/resources/models/wan-connector-model.xml"; + + try { + byte[] xmlBytes = Files.readAllBytes(Paths.get(MODEL_FILE)); + + ModelArtifactParser parser = new ModelArtifactParser(); + List modelList = parser.parse(xmlBytes, "test-artifact"); + + assertTrue(modelList.size() == 1); + + ModelArtifact model = (ModelArtifact) modelList.get(0); + System.out.println(model.toString()); + + assertTrue(model.getNameVersionId().equalsIgnoreCase("93d9d45d-7eec-4371-9083-675e4c353de3")); + assertTrue(model.getType().toString().equalsIgnoreCase("MODEL")); + assertTrue(model.getDependentModelIds().size() == 7); + assertTrue(model.getDependentModelIds().contains("d09dd9da-0148-46cd-a947-591afc844d24")); + assertTrue(model.getDependentModelIds().contains("ae16244f-4d29-4801-a559-e25f2db2a4c3")); + assertTrue(model.getDependentModelIds().contains("a6d9de88-4046-4b78-a59e-5691243d292a")); + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } + } + + @Test + public void testParseCompleteModel() throws Exception { + final String MODEL_FILE = "src/test/resources/models/complete-model.xml"; + + try { + byte[] xmlBytes = Files.readAllBytes(Paths.get(MODEL_FILE)); + + ModelArtifactParser parser = new ModelArtifactParser(); + List modelList = parser.parse(xmlBytes, "test-artifact"); + + for (Artifact art : modelList) { + ModelArtifact model = (ModelArtifact) art; + System.out.println(model.toString()); + } + + assertTrue(modelList.size() == 14); + + ModelArtifact modelVdc = (ModelArtifact) modelList.get(0); + assertTrue( + modelVdc.getNameVersionId().equalsIgnoreCase("997fc7-fca1-451f-b953-9a1e6197b4d6")); + assertTrue(modelVdc.getType().toString().equalsIgnoreCase("MODEL")); + assertTrue(modelVdc.getDependentModelIds().size() == 1); + assertTrue(modelVdc.getDependentModelIds().contains("93d9d45d-7eec-4371-9083-675e4c353de3")); + + ModelArtifact modelPserver = (ModelArtifact) modelList.get(9); + assertTrue( + modelPserver.getNameVersionId().equalsIgnoreCase("f2b24d95-c582-48d5-b2d6-c5b3a94ce812")); + assertTrue(modelPserver.getType().toString().equalsIgnoreCase("MODEL")); + assertTrue(modelPserver.getDependentModelIds().size() == 2); + assertTrue( + modelPserver.getDependentModelIds().contains("35be1acf-1298-48c6-a128-66850083b8bd")); + assertTrue( + modelPserver.getDependentModelIds().contains("759dbd4a-2473-46f3-a932-48d987c9b4a1")); + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } + } + + @Test + public void testParseNamedQuery() throws Exception { + final String MODEL_FILE = "src/test/resources/models/named-query-wan-connector.xml"; + + try { + byte[] xmlBytes = Files.readAllBytes(Paths.get(MODEL_FILE)); + + ModelArtifactParser parser = new ModelArtifactParser(); + List modelList = parser.parse(xmlBytes, "test-artifact"); + + assertTrue(modelList.size() == 1); + + ModelArtifact model = (ModelArtifact) modelList.get(0); + System.out.println(model.toString()); + + assertTrue(model.getNameVersionId().equalsIgnoreCase("94cac189-8d88-4d63-a194-f44214e080ff")); + assertTrue(model.getType().toString().equalsIgnoreCase("NAMED_QUERY")); + assertTrue(model.getDependentModelIds().size() == 4); + assertTrue(model.getDependentModelIds().contains("d09dd9da-0148-46cd-a947-591afc844d24")); + assertTrue(model.getDependentModelIds().contains("997fc7-fca1-451f-b953-9a1e6197b4d6")); + assertTrue(model.getDependentModelIds().contains("897df7ea-8938-42b0-bc57-46e913a4d93b")); + assertTrue(model.getDependentModelIds().contains("f2b24d95-c582-48d5-b2d6-c5b3a94ce812")); + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } + } +} diff --git a/src/test/java/org/openecomp/modelloader/entity/model/ModelSorterTest.java b/src/test/java/org/openecomp/modelloader/entity/model/ModelSorterTest.java new file mode 100644 index 0000000..dea537f --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/entity/model/ModelSorterTest.java @@ -0,0 +1,133 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.entity.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.openecomp.modelloader.entity.Artifact; + +public class ModelSorterTest { + + @Test + public void noModels() { + + List emptyList = Collections.emptyList(); + + ModelSorter sorter = new ModelSorter(); + sorter = new ModelSorter(); + + List sortedList = sorter.sort(emptyList); + assertNotNull(sortedList); + assertEquals(0, sortedList.size()); + + } + + @Test + public void singleModel() { + + List modelList = new ArrayList(); + + ModelArtifact model = new ModelArtifact(); + model.setNameVersionId("aaaaa"); + model.addDependentModelId("xyz"); + modelList.add(model); + + ModelSorter sorter = new ModelSorter(); + sorter = new ModelSorter(); + + List sortedList = sorter.sort(modelList); + assertNotNull(sortedList); + assertEquals(1, sortedList.size()); + + } + + /** + * + * depends on depends on B ------> A -------> C + * + * + * Input list = a, b, c Sorted list = c, a, b + * + */ + @Test + public void multipleModels() { + + List modelList = new ArrayList(); + + ModelArtifact aaaa = new ModelArtifact(); + aaaa.setNameVersionId("aaaa"); + aaaa.addDependentModelId("cccc"); + + ModelArtifact bbbb = new ModelArtifact(); + bbbb.setNameVersionId("bbbb"); + bbbb.addDependentModelId("aaaa"); + + ModelArtifact cccc = new ModelArtifact(); + cccc.setNameVersionId("cccc"); + + modelList.add(aaaa); + modelList.add(bbbb); + modelList.add(cccc); + + ModelSorter sorter = new ModelSorter(); + sorter = new ModelSorter(); + + List sortedList = sorter.sort(modelList); + assertNotNull(sortedList); + assertEquals(3, sortedList.size()); + + assertEquals(cccc, sortedList.get(0)); + assertEquals(aaaa, sortedList.get(1)); + assertEquals(bbbb, sortedList.get(2)); + } + + @Test(expected = RuntimeException.class) + public void circularDependency() { + + List modelList = new ArrayList(); + + ModelArtifact aaaa = new ModelArtifact(); + aaaa.setNameVersionId("aaaa"); + aaaa.addDependentModelId("bbbb"); + + ModelArtifact bbbb = new ModelArtifact(); + bbbb.setNameVersionId("bbbb"); + bbbb.addDependentModelId("aaaa"); + + modelList.add(aaaa); + modelList.add(bbbb); + + ModelSorter sorter = new ModelSorter(); + sorter = new ModelSorter(); + + List sortedList = sorter.sort(modelList); + assertNotNull(sortedList); + assertEquals(3, sortedList.size()); + + } + +} diff --git a/src/test/java/org/openecomp/modelloader/restclient/AAIRestClientTest.java b/src/test/java/org/openecomp/modelloader/restclient/AAIRestClientTest.java new file mode 100644 index 0000000..08d7afe --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/restclient/AAIRestClientTest.java @@ -0,0 +1,119 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.restclient; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.entity.model.ModelArtifact; + +public class AAIRestClientTest { + + // This test requires a running A&AI system. Uncomment to test locally. + /* + * @Test public void testRestClient() throws Exception { final String + * MODEL_FILE = "src/test/resources/models/vnf-model.xml"; + * + * Properties props = new Properties(); + * props.setProperty("ml.distribution.ARTIFACT_TYPES", + * "MODEL_INVENTORY_PROFILE,MODEL_QUERY_SPEC,VNF_CATALOG"); + * props.setProperty("ml.aai.BASE_URL", "https://127.0.0.1:4321"); + * props.setProperty("ml.aai.MODEL_URL", + * "/aai/v8/service-design-and-creation/models/model/"); + * props.setProperty("ml.aai.KEYSTORE_FILE", "aai-client-cert.p12"); + * props.setProperty("ml.aai.KEYSTORE_PASSWORD", + * "OBF:1i9a1u2a1unz1lr61wn51wn11lss1unz1u301i6o"); + * + * ModelLoaderConfig config = new ModelLoaderConfig(props, ""); + * + * String payload = readFile(MODEL_FILE); System.out.println("FILE:" + + * payload); + * + * File xmlFile = new File(MODEL_FILE); DocumentBuilderFactory dbFactory = + * DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = + * dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(xmlFile); + * + * // Get the ID of the model String modelId = null; NodeList nodeList = + * doc.getDocumentElement().getChildNodes(); for (int i = 0; i < + * nodeList.getLength(); i++) { Node currentNode = nodeList.item(i); if + * (currentNode.getNodeName().equals("model-name-version-id")) { modelId = + * currentNode.getTextContent(); break; } } + * + * // Add the model try { ModelArtifact model = new ModelArtifact(); + * model.setNameVersionId(modelId); model.setType(ArtifactType.MODEL); + * model.setPayload(payload); + * + * AAIRestClient aaiClient = new AAIRestClient(config); + * + * // GET model System.out.println("Calling GET API ..."); ClientResponse + * getResponse = aaiClient.getResource(getURL(model, config), + * "example-trans-id-0", AAIRestClient.MimeType.XML); System.out.println( + * "GET result: " + getResponse.getStatus()); + * assertTrue(getResponse.getStatus() == + * Response.Status.NOT_FOUND.getStatusCode()); + * + * // Add the model System.out.println("Calling PUT API ..."); ClientResponse + * res = aaiClient.putResource(getURL(model, config), model.getPayload(), + * "example-trans-id-1", AAIRestClient.MimeType.XML); System.out.println( + * "PUT result: " + res.getStatus()); assertTrue(res.getStatus() == + * Response.Status.CREATED.getStatusCode()); + * + * // Delete the model System.out.println("Calling DELETE API ..."); res = + * aaiClient.getAndDeleteResource(getURL(model, config), + * "example-trans-id-3"); System.out.println("DELETE result: " + + * res.getStatus()); assertTrue(res.getStatus() == + * Response.Status.NO_CONTENT.getStatusCode()); } catch (Exception e) { + * e.printStackTrace(); } } + */ + + static String readFile(String path) throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded); + } + + private String getURL(ModelArtifact model, ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = null; + if (model.getType().equals(ArtifactType.MODEL)) { + subURL = config.getAaiModelUrl().trim(); + } else { + subURL = config.getAaiNamedQueryUrl().trim(); + } + + if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + baseURL = baseURL + "/"; + } + + if (baseURL.endsWith("/") && subURL.startsWith("/")) { + baseURL = baseURL.substring(0, baseURL.length() - 1); + } + + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } + + String url = baseURL + subURL + model.getNameVersionId(); + return url; + } +} diff --git a/src/test/java/org/openecomp/modelloader/service/ModelLoaderServiceTest.java b/src/test/java/org/openecomp/modelloader/service/ModelLoaderServiceTest.java new file mode 100644 index 0000000..c2893a9 --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/service/ModelLoaderServiceTest.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.service; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.notification.EventCallback; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.results.IDistributionClientResult; +import org.openecomp.sdc.impl.DistributionClientFactory; +import org.openecomp.sdc.utils.DistributionActionResultEnum; + +@PrepareForTest({ DistributionClientFactory.class }) +@RunWith(PowerMockRunner.class) +public class ModelLoaderServiceTest { + + /* + * //TODO this should be re-added once we come up with a strategy to fail + * gracefully + * + * @Test public void testNonExistentConfiguration(){ + * ModelLoaderService.CONFIG_LOCATION = "FAKELOCATION"; + * + * try{ new ModelLoaderService().start(); }catch(RuntimeException e){ + * assertTrue("Got unexpected message from error log", + * e.getMessage().contains("Failed to load configuration")); return; } + * + * fail("Expecting runtime exception"); } + */ + + @Test + public void testConfigureStartDistributionClient() { + PowerMockito.mockStatic(DistributionClientFactory.class); + + IDistributionClient mockClient = mock(IDistributionClient.class); + ModelLoaderConfig mockConfig = mock(ModelLoaderConfig.class); + + when(DistributionClientFactory.createDistributionClient()).thenReturn(mockClient); + + IDistributionClientResult result = mock(IDistributionClientResult.class); + + when(result.getDistributionActionResult()).thenReturn(DistributionActionResultEnum.SUCCESS); + when(mockClient.init(Matchers. any(), Matchers. any())) + .thenReturn(result); + when(mockClient.start()).thenReturn(result); + + new ModelLoaderService().init(); + + // Validate that the client was initialized and started + verify(mockClient, times(1)).init(Matchers. any(), + Matchers. any()); + verify(mockClient, times(1)).start(); + } + + @Test + public void testInitializeButNotStarted() { + PowerMockito.mockStatic(DistributionClientFactory.class); + + IDistributionClient mockClient = mock(IDistributionClient.class); + ModelLoaderConfig mockConfig = mock(ModelLoaderConfig.class); + + DistributionActionResultEnum failureReason = DistributionActionResultEnum.ASDC_CONNECTION_FAILED; + + when(DistributionClientFactory.createDistributionClient()).thenReturn(mockClient); + + IDistributionClientResult initResult = mock(IDistributionClientResult.class); + when(initResult.getDistributionActionResult()).thenReturn(DistributionActionResultEnum.SUCCESS); + IDistributionClientResult startResult = mock(IDistributionClientResult.class); + when(startResult.getDistributionActionResult()).thenReturn(failureReason); + + when(mockClient.init(Matchers. any(), Matchers. any())) + .thenReturn(initResult); + when(mockClient.start()).thenReturn(startResult); + + // TODO this should be re-added once we come up with a strategy to fail + // gracefully + /* + * try{ new ModelLoaderService().init(mockConfig); }catch(RuntimeException + * e){ assertTrue(e.getMessage().contains(failureReason.toString())); + * return; } + * + * fail("Expecting runtime exception with failure: " + + * failureReason.toString()); + */ + } +} diff --git a/src/test/java/org/openecomp/modelloader/util/JsonXmlConverterTest.java b/src/test/java/org/openecomp/modelloader/util/JsonXmlConverterTest.java new file mode 100644 index 0000000..4654c93 --- /dev/null +++ b/src/test/java/org/openecomp/modelloader/util/JsonXmlConverterTest.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * MODEL LOADER SERVICE + * ================================================================================ + * Copyright (C) 2017 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========================================================= + */ + +package org.openecomp.modelloader.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.nio.file.Files; +import java.nio.file.Paths; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class JsonXmlConverterTest { + + @Test + public void testConversion() throws Exception { + final String XML_MODEL_FILE = "src/test/resources/models/vnf-model.xml"; + final String JSON_MODEL_FILE = "src/test/resources/models/vnf-model.json"; + + try { + byte[] encoded = Files.readAllBytes(Paths.get(XML_MODEL_FILE)); + String originalXML = new String(encoded); + + assertFalse(JsonXmlConverter.isValidJson(originalXML)); + + encoded = Files.readAllBytes(Paths.get(JSON_MODEL_FILE)); + String originalJSON = new String(encoded); + + assertTrue(JsonXmlConverter.isValidJson(originalJSON)); + + String xmlFromJson = JsonXmlConverter.convertJsonToXml(originalJSON); + + // Spot check one of the attributes + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(new ByteArrayInputStream(xmlFromJson.getBytes())); + NodeList nodeList = doc.getDocumentElement().getChildNodes(); + + String modelVid = "notFound"; + for (int i = 0; i < nodeList.getLength(); i++) { + Node currentNode = nodeList.item(i); + if (currentNode.getNodeName().equals("model-name-version-id")) { + modelVid = currentNode.getTextContent(); + break; + } + } + + assertTrue(modelVid.equals("model-vid")); + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } + } +} diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..1252135 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,37 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + diff --git a/src/test/resources/model-loader-empty-auth-password.properties b/src/test/resources/model-loader-empty-auth-password.properties new file mode 100644 index 0000000..69f3da1 --- /dev/null +++ b/src/test/resources/model-loader-empty-auth-password.properties @@ -0,0 +1,43 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# Model Loader Distribution Client Configuration +ml.distribution.ACTIVE_SERVER_TLS_AUTH=false +ml.distribution.ASDC_ADDRESS= +ml.distribution.CONSUMER_GROUP=aai-ml-group-test +ml.distribution.CONSUMER_ID=aai-ml-id-test +ml.distribution.ENVIRONMENT_NAME= +ml.distribution.KEYSTORE_PASSWORD= +ml.distribution.KEYSTORE_FILE=asdc-client.jks +ml.distribution.PASSWORD= +ml.distribution.POLLING_INTERVAL=30 +ml.distribution.POLLING_TIMEOUT=20 +ml.distribution.USER=ci +ml.distribution.ARTIFACT_TYPES=MODEL_INVENTORY_PROFILE,MODEL_QUERY_SPEC,VNF_CATALOG + +# Model Loader AAI REST Client Configuration +ml.aai.BASE_URL= +ml.aai.MODEL_URL=/aai/v8/service-design-and-creation/models/model/ +ml.aai.NAMED_QUERY_URL=/aai/v8/service-design-and-creation/named-queries/named-query/ +ml.aai.VNF_IMAGE_URL=/aai/v8/service-design-and-creation/vnf-images +ml.aai.KEYSTORE_FILE=aai-client-cert.p12 +ml.aai.KEYSTORE_PASSWORD= +ml.aai.AUTH_USER=ModelLoader +ml.aai.AUTH_PASSWORD= diff --git a/src/test/resources/model-loader-no-auth-password.properties b/src/test/resources/model-loader-no-auth-password.properties new file mode 100644 index 0000000..8d59db1 --- /dev/null +++ b/src/test/resources/model-loader-no-auth-password.properties @@ -0,0 +1,41 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# Model Loader Distribution Client Configuration +ml.distribution.ACTIVE_SERVER_TLS_AUTH=false +ml.distribution.ASDC_ADDRESS= +ml.distribution.CONSUMER_GROUP=aai-ml-group-test +ml.distribution.CONSUMER_ID=aai-ml-id-test +ml.distribution.ENVIRONMENT_NAME= +ml.distribution.KEYSTORE_PASSWORD= +ml.distribution.KEYSTORE_FILE=asdc-client.jks +ml.distribution.PASSWORD= +ml.distribution.POLLING_INTERVAL=30 +ml.distribution.POLLING_TIMEOUT=20 +ml.distribution.USER=ci +ml.distribution.ARTIFACT_TYPES=MODEL_INVENTORY_PROFILE,MODEL_QUERY_SPEC,VNF_CATALOG + +# Model Loader AAI REST Client Configuration +ml.aai.BASE_URL= +ml.aai.MODEL_URL=/aai/v8/service-design-and-creation/models/model/ +ml.aai.NAMED_QUERY_URL=/aai/v8/service-design-and-creation/named-queries/named-query/ +ml.aai.VNF_IMAGE_URL=/aai/v8/service-design-and-creation/vnf-images +ml.aai.KEYSTORE_FILE=aai-client-cert.p12 +ml.aai.KEYSTORE_PASSWORD= diff --git a/src/test/resources/model-loader.properties b/src/test/resources/model-loader.properties new file mode 100644 index 0000000..69f3da1 --- /dev/null +++ b/src/test/resources/model-loader.properties @@ -0,0 +1,43 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# Model Loader Distribution Client Configuration +ml.distribution.ACTIVE_SERVER_TLS_AUTH=false +ml.distribution.ASDC_ADDRESS= +ml.distribution.CONSUMER_GROUP=aai-ml-group-test +ml.distribution.CONSUMER_ID=aai-ml-id-test +ml.distribution.ENVIRONMENT_NAME= +ml.distribution.KEYSTORE_PASSWORD= +ml.distribution.KEYSTORE_FILE=asdc-client.jks +ml.distribution.PASSWORD= +ml.distribution.POLLING_INTERVAL=30 +ml.distribution.POLLING_TIMEOUT=20 +ml.distribution.USER=ci +ml.distribution.ARTIFACT_TYPES=MODEL_INVENTORY_PROFILE,MODEL_QUERY_SPEC,VNF_CATALOG + +# Model Loader AAI REST Client Configuration +ml.aai.BASE_URL= +ml.aai.MODEL_URL=/aai/v8/service-design-and-creation/models/model/ +ml.aai.NAMED_QUERY_URL=/aai/v8/service-design-and-creation/named-queries/named-query/ +ml.aai.VNF_IMAGE_URL=/aai/v8/service-design-and-creation/vnf-images +ml.aai.KEYSTORE_FILE=aai-client-cert.p12 +ml.aai.KEYSTORE_PASSWORD= +ml.aai.AUTH_USER=ModelLoader +ml.aai.AUTH_PASSWORD= diff --git a/src/test/resources/models/complete-model.xml b/src/test/resources/models/complete-model.xml new file mode 100644 index 0000000..f6aaf1e --- /dev/null +++ b/src/test/resources/models/complete-model.xml @@ -0,0 +1,500 @@ + + + + + 997fc7-fca1-451f-b953-9a1e6197b4d6 + + widget + vdc + 897df7ea-8938-42b0-bc57-46e913a4d93b + v1.0 + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/ccb3a5a4-1722-4213-8785-2b6b5527d453/ + + + model-element.model-element-uuid + + ccb3a5a4-1722-4213-8785-2b6b5527d453 + + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + 8da97b81-e0e9-4157-a4cd-af3ba52871d6 + + resource + vDbe + 77b83c95-7707-4624-8bfe-9110b9c2dc88 + v1.0 + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/fc3a2260-d0ee-4c8e-b7e9-74791d7c5721/ + + + model-element.model-element-uuid + + fc3a2260-d0ee-4c8e-b7e9-74791d7c5721 + + + + element-choice-set.element-choice-set-uuid + + 646ee687-1475-419d-bd10-f3760d5430dc + + + + constrained-element-set.constrained-element-set-uuid + + 999 + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + d09dd9da-0148-46cd-a947-591afc844d24 + + widget + connector + 63ac2806-4d47-467f-bf9d-5a8a83a13cac + v1.0 + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/df2e4cc0-18ca-4046-9c1b-2abec86a58d6/ + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + 93a6166f-b3d5-4f06-b4ba-aed48d009ad9 + + widget + generic-vnf + acc6edd8-a8d4-4b93-afaa-0994068be14c + v1.0 + 1463175177 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/88a0e5fd-0254-41dc-a9d5-7a7db446f2f3/ + + + model-element.model-element-uuid + + 88a0e5fd-0254-41dc-a9d5-7a7db446f2f3 + + + + model.model-name-version-id + 8da97b81-e0e9-4157-a4cd-af3ba52871d6 + + + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/baefe75b-30f2-43d2-bd73-553f65ea1405/ + + + model-element.model-element-uuid + + baefe75b-30f2-43d2-bd73-553f65ea1405 + + + + model.model-name-version-id + a6d9de88-4046-4b78-a59e-5691243d292a + + + + + + + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + + resource + ipe + 323ac9c1-b345-44a2-9d07-dd7653137705 + v1.0 + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/746b864c-333b-4da9-806e-c70f883f8c9d/ + + + model-element.model-element-uuid + + 746b864c-333b-4da9-806e-c70f883f8c9d + + + + element-choice-set.element-choice-set-uuid + + 1c69d7dc-ddf1-4cf3-86dd-929aa886429c + + + + constrained-element-set.constrained-element-set-uuid + + 999 + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + 93d9d45d-7eec-4371-9083-675e4c353de3 + + service + wan-connector + e4a9901b-6c94-4e07-b8d8-b877d3df554c + v1.0 + Connects a customer vpn to the border elements of + an AT&T product + 1463175188 + + + + 35be1acf-1298-48c6-a128-66850083b8bd + + resource + pBgf + 897fb848-3b38-4d0d-a6a7-2543070fc450 + v1.0 + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/d985355f-a162-493b-8cb9-0b5b948bb7b0/ + + + model-element.model-element-uuid + + d985355f-a162-493b-8cb9-0b5b948bb7b0 + + + + element-choice-set.element-choice-set-uuid + + 646ee687-1475-419d-bd10-f3760d5430dc + + + + constrained-element-set.constrained-element-set-uuid + + 999 + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + a6d9de88-4046-4b78-a59e-5691243d292a + + resource + vSbg + 326690fa-9747-4ebd-9d9f-a5ef02943e1a + v1.0 + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/b989a7b6-907a-431d-b54e-262d29c45b6f/ + + + model-element.model-element-uuid + + b989a7b6-907a-431d-b54e-262d29c45b6f + + + + element-choice-set.element-choice-set-uuid + + 646ee687-1475-419d-bd10-f3760d5430dc + + + + constrained-element-set.constrained-element-set-uuid + + 999 + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + ae16244f-4d29-4801-a559-e25f2db2a4c3 + + resource + l2-bridge-for-wan-connector + 9494e925-04a0-4f52-983b-36fa8f75d97e + v1.0 + An l2-bridge used by a wan connector connects an + ipe to a product border element + 1463175188 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/061f2f1d-d76f-4b4a-810c-1f9a452a4db3/ + + + model-element.model-element-uuid + + 061f2f1d-d76f-4b4a-810c-1f9a452a4db3 + + + + model-element.model-element-uuid + + df2e4cc0-18ca-4046-9c1b-2abec86a58d6 + + + + model.model-name-version-id + 93d9d45d-7eec-4371-9083-675e4c353de3 + + + + + + + f2b24d95-c582-48d5-b2d6-c5b3a94ce812 + + widget + pserver + a033a95f-93af-4dc6-811e-f818baf13ef1 + v1.0 + 1463175178 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/5eab2693-78ec-446a-afe4-14332e348246/ + + + model-element.model-element-uuid + + 5eab2693-78ec-446a-afe4-14332e348246 + + + + model.model-name-version-id + 35be1acf-1298-48c6-a128-66850083b8bd + + + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/f7659dac-6311-45b6-b483-60b39364a85a/ + + + model-element.model-element-uuid + + f7659dac-6311-45b6-b483-60b39364a85a + + + + model.model-name-version-id + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + + + + + + + 53be71b0-c689-4841-9fe6-c7fab529d310 + + widget + p-interface + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + v1.0 + 1463175178 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/f118b348-1231-4895-ad26-0b227253cdf0/ + + + model-element.model-element-uuid + + f118b348-1231-4895-ad26-0b227253cdf0 + + + + model-element.model-element-uuid + + f7659dac-6311-45b6-b483-60b39364a85a + + + + model.model-name-version-id + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + + + + + + + 706c7e05-8faf-4258-acca-8e4cf556961d + + widget + l-interface + 92e579cc-eb63-490f-b9eb-16b7af2660c7 + v1.0 + 1463175178 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/82f1cf8a-470b-4aaa-a1eb-27b83ba8f176/ + + + model-element.model-element-uuid + + 82f1cf8a-470b-4aaa-a1eb-27b83ba8f176 + + + + model-element.model-element-uuid + + f7659dac-6311-45b6-b483-60b39364a85a + + + + model.model-name-version-id + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + + + + + + + 897df7ea-8938-42b0-bc57-46e913a4d93b + + widget + logical-link + c575bd11-6907-4b44-82d8-f55294fff63f + v1.0 + 1463175143 + + + + f749dc48-4f58-4601-9d3e-605a06a0899e + + widget + vlan + 76544264-9287-45c6-871b-6e7a456a9f32 + v1.0 + 1463175178 + + + model-element + https://localhost:8443/aai/v7/service-design-and-creation/model-elements/model-element/fd994cef-bc62-460f-bd21-cc8c07fbccc4/ + + + model-element.model-element-uuid + + fd994cef-bc62-460f-bd21-cc8c07fbccc4 + + + + model-element.model-element-uuid + + f7659dac-6311-45b6-b483-60b39364a85a + + + + model.model-name-version-id + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + + + + + + diff --git a/src/test/resources/models/named-query-wan-connector.xml b/src/test/resources/models/named-query-wan-connector.xml new file mode 100644 index 0000000..d0d5a05 --- /dev/null +++ b/src/test/resources/models/named-query-wan-connector.xml @@ -0,0 +1,90 @@ + + + + 94cac189-8d88-4d63-a194-f44214e080ff + + wan-connector + v1.0 + Named Query - Wan Connector + + + + + model + + + model.model-name-version-id + d09dd9da-0148-46cd-a947-591afc844d24 + + + + + + + + + model + + + model.model-name-version-id + 997fc7-fca1-451f-b953-9a1e6197b4d6 + + + + + + + + + model + + + model.model-name-version-id + + 897df7ea-8938-42b0-bc57-46e913a4d93b + + + + + + + + + model + + + model.model-name-version-id + + f2b24d95-c582-48d5-b2d6-c5b3a94ce812 + + + + + + + + + + + + + + diff --git a/src/test/resources/models/vnf-model.json b/src/test/resources/models/vnf-model.json new file mode 100644 index 0000000..5bebe59 --- /dev/null +++ b/src/test/resources/models/vnf-model.json @@ -0,0 +1,10 @@ +{ + "model": + { + "model-name-version-id":"model-vid", + "model-type":"widget", + "model-version":"v1.0", + "model-id":"model-id", + "model-name":"generic-vnf" + } +} diff --git a/src/test/resources/models/vnf-model.xml b/src/test/resources/models/vnf-model.xml new file mode 100644 index 0000000..616f4b9 --- /dev/null +++ b/src/test/resources/models/vnf-model.xml @@ -0,0 +1,27 @@ + + + + model-id + widget + generic-vnf + v1.0 + model-vid + diff --git a/src/test/resources/models/wan-connector-model.xml b/src/test/resources/models/wan-connector-model.xml new file mode 100644 index 0000000..5e3ff10 --- /dev/null +++ b/src/test/resources/models/wan-connector-model.xml @@ -0,0 +1,186 @@ + + + + e4a9901b-6c94-4e07-b8d8-b877d3df554c + service + wan-connector + v1.0 + 93d9d45d-7eec-4371-9083-675e4c353de3 + + Connects a customer vpn to the border elements of an + AT&T product + + + a + vpn-id + + + b + product + + + + + true + unbounded + + + model + + + model.model-name-version-id + d09dd9da-0148-46cd-a947-591afc844d24 + + + + + + + true + unbounded + + + model + + + model.model-name-version-id + 997fc7-fca1-451f-b953-9a1e6197b4d6 + + + + + + + true + unbounded + + + model + + + model.model-name-version-id + + ae16244f-4d29-4801-a559-e25f2db2a4c3 + + + + + + + + logical-link + 999 + + combination + AND + + + A + 1 + + + unbounded + false + + + model + + + model.model-name-version-id + + 759dbd4a-2473-46f3-a932-48d987c9b4a1 + + + + + + l-interface|p-interface|pserver + + + + + + + B + 1 + + + unbounded + false + + + model + + + model.model-name-version-id + + 8da97b81-e0e9-4157-a4cd-af3ba52871d6 + + + + + + + unbounded + false + + + model + + + model.model-name-version-id + + a6d9de88-4046-4b78-a59e-5691243d292a + + + + + + + unbounded + false + + + model + + + model.model-name-version-id + + 35be1acf-1298-48c6-a128-66850083b8bd + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/vnfcatalogexample.xml b/src/test/resources/vnfcatalogexample.xml new file mode 100644 index 0000000..1557efa --- /dev/null +++ b/src/test/resources/vnfcatalogexample.xml @@ -0,0 +1,1878 @@ + + + + + FortiGate-VM00 + FW + + FORTINET + FortiGate-VM00 + VM00 + + + 1 + 1 + 1 + + + 1 + GB + 1 + 1 + + + 2 + GB + 2 + 32 + + + 5.2.7 + 0 + IMAGE + 1c59a521885c465004456f74d003726c + fortinet-FW-IMG-5.2.7.qcow2 + + + 5.2.5 + 1 + IMAGE + C4D2CBE51669796E48623E006782F7DC + fortinet-FW-IMG-5.2.5.qcow2 + + + 5.2.4 + 2 + IMAGE + 4987E1E743FD641C879E1D3C5D50BCE0 + fortinet-FW-IMG-5.2.4.qcow2 + + + APPID + + + IPS-IDS + + + URLF + + + Anti-Virus + + + FortiGate-VM00 + FALSE + + + + FortiGate-VM01 + FW + + FORTINET + FortiGate-VM01 + VM01 + + + 1 + 1 + 1 + + + 2 + GB + 1 + 2 + + + 2 + GB + 2 + 32 + + + 5.2.7 + 0 + IMAGE + 1c59a521885c465004456f74d003726c + fortinet-FW-IMG-5.2.7.qcow2 + + + 5.2.5 + 1 + IMAGE + C4D2CBE51669796E48623E006782F7DC + fortinet-FW-IMG-5.2.5.qcow2 + + + 5.2.4 + 2 + IMAGE + 4987E1E743FD641C879E1D3C5D50BCE0 + fortinet-FW-IMG-5.2.4.qcow2 + + + APPID + + + IPS-IDS + + + URLF + + + Anti-Virus + + + FortiGate-VM01 + FALSE + + + + FortiGate-VM02 + FW + + FORTINET + FortiGate-VM02 + VM02 + + + 2 + 1 + 2 + + + 4 + GB + 1 + 4 + + + 4 + GB + 2 + 32 + + + 5.2.7 + 0 + IMAGE + 1c59a521885c465004456f74d003726c + fortinet-FW-IMG-5.2.7.qcow2 + + + 5.2.5 + 1 + IMAGE + C4D2CBE51669796E48623E006782F7DC + fortinet-FW-IMG-5.2.5.qcow2 + + + 5.2.4 + 2 + IMAGE + 4987E1E743FD641C879E1D3C5D50BCE0 + fortinet-FW-IMG-5.2.4.qcow2 + + + APPID + + + IPS-IDS + + + URLF + + + Anti-Virus + + + FortiGate-VM02 + FALSE + + + + FortiGate-VM04 + FW + + FORTINET + FortiGate-VM04 + VM04 + + + 4 + 1 + 4 + + + 6 + GB + 1 + 6 + + + 8 + GB + 2 + 32 + + + 5.2.7 + 0 + IMAGE + 1c59a521885c465004456f74d003726c + fortinet-FW-IMG-5.2.7.qcow2 + + + 5.2.5 + 1 + IMAGE + C4D2CBE51669796E48623E006782F7DC + fortinet-FW-IMG-5.2.5.qcow2 + + + 5.2.4 + 2 + IMAGE + 4987E1E743FD641C879E1D3C5D50BCE0 + fortinet-FW-IMG-5.2.4.qcow2 + + + APPID + + + IPS-IDS + + + URLF + + + Anti-Virus + + + FortiGate-VM04 + FALSE + + + + FortiGate-VM08 + FW + + FORTINET + FortiGate-VM08 + VM08 + + + 8 + 1 + 8 + + + 12 + GB + 1 + 12 + + + 16 + GB + 2 + 32 + + + 5.2.7 + 0 + IMAGE + 1c59a521885c465004456f74d003726c + fortinet-FW-IMG-5.2.7.qcow2 + + + 5.2.5 + 1 + IMAGE + C4D2CBE51669796E48623E006782F7DC + fortinet-FW-IMG-5.2.5.qcow2 + + + 5.2.4 + 2 + IMAGE + 4987E1E743FD641C879E1D3C5D50BCE0 + fortinet-FW-IMG-5.2.4.qcow2 + + + APPID + + + IPS-IDS + + + URLF + + + Anti-Virus + + + FortiGate-VM08 + FALSE + + + + L-CSR-10M-APP-1Y + RT + + CISCO + L-CSR-10M-APP-1Y + L-CSR-10M-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-10M-APP-1Y + TRUE + + + + L-CSR-50M-APP-1Y + RT + + CISCO + L-CSR-50M-APP-1Y + L-CSR-50M-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-50M-APP-1Y + TRUE + + + + L-CSR-100M-APP-1Y + RT + + CISCO + L-CSR-100M-APP-1Y + L-CSR-100M-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-100M-APP-1Y + TRUE + + + + L-CSR-250M-APP-1Y + RT + + CISCO + L-CSR-250M-APP-1Y + L-CSR-250M-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-250M-APP-1Y + TRUE + + + + L-CSR-500M-APP-1Y + RT + + CISCO + L-CSR-500M-APP-1Y + L-CSR-500M-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-500M-APP-1Y + TRUE + + + + L-CSR-1G-APP-1Y + RT + + CISCO + L-CSR-1G-APP-1Y + L-CSR-1G-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-1G-APP-1Y + TRUE + + + + L-CSR-2.5G-APP-1Y + RT + + CISCO + L-CSR-2.5G-APP-1Y + L-CSR-2.5G-APP-1Y + + + 1 + 1 + 1 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 3.16.1aS + 0 + IMAGE + cisco-RT-IMG-csr1000v-universalk9.03.16.01a.S.155-3.S1a-ext.qcow2 + D034E0BC74A84EFFE667113E5ABAC6E1 + + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + Enhanced Interior Gateway Routing Protocol (EIGRP) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + HSRP + + + VRRP + + + L-CSR-2.5G-APP-1Y + TRUE + + + + VCX-SUB-00255-U + WX + + RIVERBED + VCX-SUB-00255-U + VCX-SUB-00255-U + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-U + TRUE + + + + VCX-SUB-00255-L + WX + + RIVERBED + VCX-SUB-00255-L + VCX-SUB-00255-L + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-L + TRUE + + + + VCX-SUB-00255-M + WX + + RIVERBED + VCX-SUB-00255-M + VCX-SUB-00255-M + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-M + TRUE + + + + VCX-SUB-00255-H + WX + + RIVERBED + VCX-SUB-00255-H + VCX-SUB-00255-H + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-H + TRUE + + + + VCX-SUB-00555-L + WX + + RIVERBED + VCX-SUB-00555-L + VCX-SUB-00555-L + + + 2 + 1 + 2 + + + 4 + GB + 2 + 4 + + + 80 + GB + 80 + 80 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00555-L + TRUE + + + + VCX-SUB-00555-M + WX + + RIVERBED + VCX-SUB-00555-M + VCX-SUB-00555-M + + + 2 + 1 + 2 + + + 4 + GB + 2 + 4 + + + 80 + GB + 80 + 80 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00555-M + TRUE + + + + VCX-SUB-00555-H + WX + + RIVERBED + VCX-SUB-00555-H + VCX-SUB-00555-H + + + 2 + 1 + 2 + + + 4 + GB + 2 + 4 + + + 80 + GB + 80 + 80 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00555-H + TRUE + + + + VCX-SUB-00755-L + WX + + RIVERBED + VCX-SUB-00755-L + VCX-SUB-00755-L + + + 4 + 2 + 4 + + + 8 + GB + 4 + 8 + + + 150 + GB + 150 + 150 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00755-L + TRUE + + + + VCX-SUB-00755-M + WX + + RIVERBED + VCX-SUB-00755-M + VCX-SUB-00755-M + + + 4 + 2 + 4 + + + 8 + GB + 4 + 8 + + + 150 + GB + 150 + 150 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00755-M + TRUE + + + + VCX-SUB-00755-H + WX + + RIVERBED + VCX-SUB-00755-H + VCX-SUB-00755-H + + + 4 + 2 + 4 + + + 8 + GB + 4 + 8 + + + 150 + GB + 150 + 150 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00755-H + TRUE + + + + VCX-SUB-00255-UB + WX + + RIVERBED + VCX-SUB-00255-UB + VCX-SUB-00255-UB + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-UB + TRUE + + + + VCX-SUB-00255-LB + WX + + RIVERBED + VCX-SUB-00255-LB + VCX-SUB-00255-LB + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-LB + TRUE + + + + VCX-SUB-00255-MB + WX + + RIVERBED + VCX-SUB-00255-MB + VCX-SUB-00255-MB + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-MB + TRUE + + + + VCX-SUB-00255-HB + WX + + RIVERBED + VCX-SUB-00255-HB + VCX-SUB-00255-HB + + + 2 + 1 + 2 + + + 2 + GB + 2 + 2 + + + 50 + GB + 50 + 50 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00255-HB + TRUE + + + + VCX-SUB-00555-LB + WX + + RIVERBED + VCX-SUB-00555-LB + VCX-SUB-00555-LB + + + 2 + 1 + 2 + + + 4 + GB + 2 + 4 + + + 80 + GB + 80 + 80 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00555-LB + TRUE + + + + VCX-SUB-00555-MB + WX + + RIVERBED + VCX-SUB-00555-MB + VCX-SUB-00555-MB + + + 2 + 1 + 2 + + + 4 + GB + 2 + 4 + + + 80 + GB + 80 + 80 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00555-MB + TRUE + + + + VCX-SUB-00555-HB + WX + + RIVERBED + VCX-SUB-00555-HB + VCX-SUB-00555-HB + + + 2 + 1 + 2 + + + 4 + GB + 2 + 4 + + + 80 + GB + 80 + 80 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00555-HB + TRUE + + + + VCX-SUB-00755-LB + WX + + RIVERBED + VCX-SUB-00755-LB + VCX-SUB-00755-LB + + + 4 + 2 + 4 + + + 8 + GB + 4 + 8 + + + 150 + GB + 150 + 150 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00755-LB + TRUE + + + + VCX-SUB-00755-MB + WX + + RIVERBED + VCX-SUB-00755-MB + VCX-SUB-00755-MB + + + 4 + 2 + 4 + + + 8 + GB + 4 + 8 + + + 150 + GB + 150 + 150 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00755-MB + TRUE + + + + VCX-SUB-00755-HB + WX + + RIVERBED + VCX-SUB-00755-HB + VCX-SUB-00755-HB + + + 4 + 2 + 4 + + + 8 + GB + 4 + 8 + + + 150 + GB + 150 + 150 + + + 9.2.0 + 0 + IMAGE + 386CF5D3482F068EC9C480B51F6BCE42 + riverbed-WX-IMG-9.2.0.qcow2 + + + TCP OPTIMIZATION + + + APPLICATION OPTIMIZATION + + + VCX-SUB-00755-HB + TRUE + + + + JUN-vSRX-15X + RT + + JUNIPER + JUN-vSRX-15X + VSRX + + + 2 + 2 + 2 + + + 4 + GB + 4 + 4 + + + 8 + GB + 8 + 8 + + + 15.1X49-D40.6 + 0 + IMAGE + media-vsrx-vmdisk-15.1X49-D40.6.qcow2 + 4b874dbd75fc83dc2494b90b2012d514 + + + IPv6 + + + NetFLOW v9 + + + NTP + + + SNMP + + + GRE Tunnel + + + Border Gateway Protocol (BGP) + + + Open Shortest Path First (OSPF) + + + NAT + + + DHCP Server + + + DHCP Relay + + + VRF-Lite + + + COS + + + Multicast + + + VRRP + + + JUN-vSRX-15X + FALSE + + + -- 2.16.6