diff options
author | Steve Smokowski <ss835w@att.com> | 2017-02-09 15:43:35 -0500 |
---|---|---|
committer | Steve Smokowski <ss835w@att.com> | 2017-02-09 15:44:01 -0500 |
commit | ef768a7c864f0d807d8696449f5eed7a4552316f (patch) | |
tree | 1883d5cdf446ed9b22d06cd3f4472e89e96b9a40 /src/main | |
parent | 7c4d2c54ff5bf1095ca7cf031f7eea96d690f9fc (diff) |
Initial OpenECOMP A&AI Model Loader commit
Change-Id: Iae343fa01ecc701919703fb7d61727555371321d
Signed-off-by: Steve Smokowski <ss835w@att.com>
Diffstat (limited to 'src/main')
31 files changed, 5641 insertions, 0 deletions
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<String> 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<String>(); + 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<String> 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<Artifact> 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<Artifact> artifacts, String distributionId) { + for (Artifact art : artifacts) { + VnfCatalogArtifact vnfCatalog = (VnfCatalogArtifact) art; + String artifactPayload = vnfCatalog.getPayload(); + + AaiRestClient restClient = new AaiRestClient(this.config); + List<VnfImage> putImages = new ArrayList<VnfImage>(); + + 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<VnfImage> 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<String> referencedModelIds = new HashSet<String>(); + + public String getNameVersionId() { + return nameVersionId; + } + + public void setNameVersionId(String nameVersionId) { + this.nameVersionId = nameVersionId; + } + + public Set<String> 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<Artifact> artifacts, String distributionId) { + ModelSorter modelSorter = new ModelSorter(); + List<Artifact> 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<ModelArtifact> completedModels = new ArrayList<ModelArtifact>(); + 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<Artifact> modelArtifacts = new ArrayList<Artifact>(); + ModelArtifactParser parser = new ModelArtifactParser(); + modelArtifacts.addAll(parser.parse(payload, "Test-Artifact")); + ModelSorter modelSorter = new ModelSorter(); + List<Artifact> 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<Artifact> parse(byte[] artifactPayload, String artifactName) { + String payload = new String(artifactPayload); + List<Artifact> modelList = new ArrayList<Artifact>(); + + 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<Edge> inEdges; + private final HashSet<Edge> outEdges; + + public Node(ModelArtifact model) { + this.model = model; + inEdges = new HashSet<Edge>(); + outEdges = new HashSet<Edge>(); + } + + 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<Artifact> sort(List<Artifact> originalList) { + + if (originalList.size() <= 1) { + return originalList; + } + + Collection<Node> nodes = createNodes(originalList); + Collection<Node> sortedNodes = sortNodes(nodes); + + List<Artifact> sortedModelsList = new ArrayList<Artifact>(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<Node> createNodes(Collection<Artifact> models) { + + // load list of models into a map, so we can later replace referenceIds with + // real Models + HashMap<String, ModelArtifact> versionIdToModelMap = new HashMap<String, ModelArtifact>(); + for (Artifact art : models) { + ModelArtifact ma = (ModelArtifact) art; + versionIdToModelMap.put(ma.getNameVersionId(), ma); + } + + HashMap<String, Node> nodes = new HashMap<String, Node>(); + // 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<Node> sortNodes(Collection<Node> unsortedNodes) { + + // L <- Empty list that will contain the sorted elements + ArrayList<Node> nodeList = new ArrayList<Node>(); + + // S <- Set of all nodes with no incoming edges + HashSet<Node> nodeSet = new HashSet<Node>(); + 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<Edge> 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<IArtifactInfo> artifacts = getArtifacts(data); + List<Artifact> modelArtifacts = new ArrayList<Artifact>(); + List<Artifact> catalogArtifacts = new ArrayList<Artifact>(); + 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<IArtifactInfo> getArtifacts(INotificationData data) { + List<IArtifactInfo> artifacts = new ArrayList<IArtifactInfo>(); + List<IResourceInstance> 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 Binary files differnew file mode 100644 index 0000000..ee57120 --- /dev/null +++ b/src/main/resources/aai-os-cert.p12 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 @@ +<!-- + ============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========================================================= + --> + +<configuration scan="true" scanPeriod="3 seconds" debug="false"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + + <property name="logDir" value="logs" /> + + + <!-- specify the component name <ECOMP-component-name>::= "MSO" | "DCAE" + | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" --> + <property name="componentName" value="AAI-ML"></property> + + <!-- default eelf log file names --> + <property name="generalLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + + <property name="errorLogPattern" + value="%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%mdc{RequestId}|%thread|ModelLoader|%mdc{PartnerName}|%logger||%.-5level|%msg%n" /> + <property name="auditMetricPattern" value="%m%n" /> + + <property name="logDirectory" value="${logDir}/${componentName}" /> + + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> + + <!-- The EELFAppender is used to record events to the general application + log --> + + <appender name="EELF" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip</fileNamePattern> + <maxHistory>60</maxHistory> + </rollingPolicy> + <encoder> + <pattern>${errorLogPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELF" class="ch.qos.logback.classic.AsyncAppender"> + <!-- deny all events with a level below INFO, that is TRACE and DEBUG --> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + <queueSize>256</queueSize> + <appender-ref ref="EELF" /> + </appender> + + + <appender name="EELFAudit" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip</fileNamePattern> + <maxHistory>60</maxHistory> + </rollingPolicy> + <encoder> + <pattern>${auditMetricPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + + + <appender name="EELFMetrics" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip</fileNamePattern> + <maxHistory>60</maxHistory> + </rollingPolicy> + <encoder> + <pattern>${auditMetricPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics" /> + </appender> + + + <appender name="EELFDebug" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${debugLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip</fileNamePattern> + <maxHistory>60</maxHistory> + </rollingPolicy> + <encoder> + <pattern>${errorLogPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + <logger name="com.att.eelf" level="info" additivity="false"> + <appender-ref ref="asyncEELF" /> + <appender-ref ref="asyncEELFDebug" /> + </logger> + + <logger name="com.att.eelf.security" level="info" additivity="false"> + <appender-ref ref="asyncEELFSecurity" /> + </logger> + <logger name="com.att.eelf.perf" level="info" additivity="false"> + <appender-ref ref="asyncEELFPerformance" /> + </logger> + <logger name="com.att.eelf.server" level="info" additivity="false"> + <appender-ref ref="asyncEELFServer" /> + </logger> + <logger name="com.att.eelf.policy" level="info" additivity="false"> + <appender-ref ref="asyncEELFPolicy" /> + </logger> + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + </logger> + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + </logger> + + <!-- Spring related loggers --> + <logger name="org.springframework" level="WARN" /> + <logger name="org.springframework.beans" level="WARN" /> + <logger name="org.springframework.web" level="WARN" /> + <logger name="com.blog.spring.jms" level="WARN" /> + + <logger name="com.att" level="INFO" /> + + <!-- Model Loader loggers --> + <logger name="org.openecomp.modelloader" level="INFO" /> + + <!-- Other Loggers that may help troubleshoot --> + <logger name="net.sf" level="WARN" /> + <logger name="org.apache.commons.httpclient" level="WARN" /> + <logger name="org.apache.commons" level="WARN" /> + <logger name="org.apache.coyote" level="WARN" /> + <logger name="org.apache.jasper" level="WARN" /> + + <!-- Camel Related Loggers (including restlet/servlet/jaxrs/cxf logging. + May aid in troubleshooting) --> + <logger name="org.apache.camel" level="WARN" /> + <logger name="org.apache.cxf" level="WARN" /> + <logger name="org.apache.camel.processor.interceptor" level="WARN" /> + <logger name="org.apache.cxf.jaxrs.interceptor" level="WARN" /> + <logger name="org.apache.cxf.service" level="WARN" /> + <logger name="org.restlet" level="WARN" /> + <logger name="org.apache.camel.component.restlet" level="WARN" /> + + <!-- logback internals logging --> + <logger name="ch.qos.logback.classic" level="WARN" /> + <logger name="ch.qos.logback.core" level="WARN" /> + + <root> + <appender-ref ref="asyncEELF" /> + <!-- <appender-ref ref="asyncEELFDebug" /> --> + </root> + +</configuration> 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 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + ============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========================================================= + --> + +<xs:schema elementFormDefault="qualified" version="1.0" + targetNamespace="http://org.openecomp.aai.inventory/v8" xmlns:tns="http://org.openecomp.aai.inventory/v8" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:element name="inventory-item-data"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-name" type="xs:string" + minOccurs="0" /> + <xs:element name="property-value" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="inventory-item"> + <xs:complexType> + <xs:sequence> + <xs:element name="inventory-item-type" type="xs:string" + minOccurs="0" /> + <xs:element name="inventory-item-link" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:inventory-item-data" minOccurs="0" + maxOccurs="unbounded" /> + <xs:element ref="tns:tagged-inventory-item-list" + minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="tagged-inventory-item-list"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:inventory-item" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="edge-tag-query-result"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:tagged-inventory-item-list" + minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="start-node-filter"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-name" type="xs:string" + minOccurs="0" /> + <xs:element name="property-value" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="include-node-filter"> + <xs:complexType> + <xs:sequence> + <xs:element name="include-node-type" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="secondary-filter"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-name" type="xs:string" + minOccurs="0" /> + <xs:element name="filter-type" type="xs:string" + minOccurs="0" /> + <xs:element name="property-value" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="edge-tag-query-request"> + <xs:complexType> + <xs:sequence> + <xs:element name="edge-tag" type="xs:string" minOccurs="0" /> + <xs:element name="result-detail" type="xs:string" + minOccurs="0" /> + <xs:element name="start-node-type" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:start-node-filter" minOccurs="0" + maxOccurs="unbounded" /> + <xs:element ref="tns:include-node-filter" minOccurs="0" + maxOccurs="unbounded" /> + <xs:element ref="tns:secondary-filter" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="result-data"> + <xs:complexType> + <xs:sequence> + <xs:element name="resource-type" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-link" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="search-results"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:result-data" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="relationship-data"> + <xs:complexType> + <xs:sequence> + <xs:element name="relationship-key" type="xs:string" /> + <xs:element name="relationship-value" type="xs:string" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="related-to-property"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-key" type="xs:string" + minOccurs="0" /> + <xs:element name="property-value" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="relationship"> + <xs:complexType> + <xs:sequence> + <xs:element name="related-to" type="xs:string" minOccurs="0" /> + <xs:element name="related-link" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-data" minOccurs="0" + maxOccurs="unbounded" /> + <xs:element ref="tns:related-to-property" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="relationship-list"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:relationship" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="oam-network"> + <xs:complexType> + <xs:sequence> + <xs:element name="network-uuid" type="xs:string" /> + <xs:element name="network-name" type="xs:string" /> + <xs:element name="cvlan-tag" type="xs:unsignedInt" /> + <xs:element name="ipv4-oam-gateway-address" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-gateway-address-prefix-length" + type="xs:int" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="oam-networks"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:oam-network" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="dvs-switch"> + <xs:complexType> + <xs:sequence> + <xs:element name="switch-name" type="xs:string" /> + <xs:element name="vcenter-url" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="dvs-switches"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:dvs-switch" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="availability-zone"> + <xs:complexType> + <xs:sequence> + <xs:element name="availability-zone-name" type="xs:string" /> + <xs:element name="hypervisor-type" type="xs:string" /> + <xs:element name="operational-state" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="az-and-dvs-switches"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:dvs-switches" minOccurs="0" /> + <xs:element ref="tns:availability-zone" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="sdn-zone-response"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:oam-networks" minOccurs="0" /> + <xs:element ref="tns:az-and-dvs-switches" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="search"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:edge-tag-query-result" minOccurs="0" /> + <xs:element ref="tns:edge-tag-query-request" minOccurs="0" /> + <xs:element ref="tns:search-results" minOccurs="0" /> + <xs:element ref="tns:sdn-zone-response" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="update-node-key"> + <xs:complexType> + <xs:sequence> + <xs:element name="key-name" type="xs:string" minOccurs="0" /> + <xs:element name="key-value" type="xs:string" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="action-data"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-name" type="xs:string" + minOccurs="0" /> + <xs:element name="property-value" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="action"> + <xs:complexType> + <xs:sequence> + <xs:element name="action-type" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:action-data" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="update"> + <xs:complexType> + <xs:sequence> + <xs:element name="update-node-type" type="xs:string" /> + <xs:element ref="tns:update-node-key" minOccurs="0" + maxOccurs="unbounded" /> + <xs:element name="update-node-uri" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:action" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="key-data"> + <xs:complexType> + <xs:sequence> + <xs:element name="key-name" type="xs:string" minOccurs="0" /> + <xs:element name="key-value" type="xs:string" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="notify"> + <xs:complexType> + <xs:sequence> + <xs:element name="event-id" type="xs:string" /> + <xs:element name="node-type" type="xs:string" minOccurs="0" /> + <xs:element name="event-trigger" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:key-data" minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="selflink" type="xs:string" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="actions"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:update" minOccurs="0" /> + <xs:element ref="tns:notify" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="ctag-pool"> + <xs:complexType> + <xs:sequence> + <xs:element name="target-pe" type="xs:string" /> + <xs:element name="availability-zone-name" type="xs:string" /> + <xs:element name="ctag-pool-purpose" type="xs:string" /> + <xs:element name="ctag-values" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="ctag-pools"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:ctag-pool" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="complex"> + <xs:complexType> + <xs:sequence> + <xs:element name="physical-location-id" type="xs:string" /> + <xs:element name="data-center-code" type="xs:string" + minOccurs="0" /> + <xs:element name="complex-name" type="xs:string" + minOccurs="0" /> + <xs:element name="identity-url" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="physical-location-type" type="xs:string" /> + <xs:element name="street1" type="xs:string" /> + <xs:element name="street2" type="xs:string" minOccurs="0" /> + <xs:element name="city" type="xs:string" /> + <xs:element name="state" type="xs:string" minOccurs="0" /> + <xs:element name="postal-code" type="xs:string" /> + <xs:element name="country" type="xs:string" /> + <xs:element name="region" type="xs:string" /> + <xs:element name="latitude" type="xs:string" minOccurs="0" /> + <xs:element name="longitude" type="xs:string" minOccurs="0" /> + <xs:element name="elevation" type="xs:string" minOccurs="0" /> + <xs:element name="lata" type="xs:string" minOccurs="0" /> + <xs:element ref="tns:ctag-pools" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="complexes"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:complex" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="volume-group"> + <xs:complexType> + <xs:sequence> + <xs:element name="volume-group-id" type="xs:string" /> + <xs:element name="volume-group-name" type="xs:string" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="vnf-type" type="xs:string" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="volume-groups"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:volume-group" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="volume"> + <xs:complexType> + <xs:sequence> + <xs:element name="volume-id" type="xs:string" /> + <xs:element name="volume-selflink" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="volumes"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:volume" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="l3-interface-ipv4-address-list"> + <xs:complexType> + <xs:sequence> + <xs:element name="l3-interface-ipv4-address" type="xs:string" /> + <xs:element name="l3-interface-ipv4-prefix-length" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="vlan-id-inner" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="vlan-id-outer" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="is-floating" type="xs:boolean" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-network-id" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-subnet-id" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="l3-interface-ipv6-address-list"> + <xs:complexType> + <xs:sequence> + <xs:element name="l3-interface-ipv6-address" type="xs:string" /> + <xs:element name="l3-interface-ipv6-prefix-length" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="vlan-id-inner" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="vlan-id-outer" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="is-floating" type="xs:boolean" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-network-id" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-subnet-id" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vlan"> + <xs:complexType> + <xs:sequence> + <xs:element name="vlan-interface" type="xs:string" /> + <xs:element name="vlan-id-inner" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="vlan-id-outer" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-value" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-units" type="xs:string" + minOccurs="0" /> + <xs:element name="vlan-description" type="xs:string" + minOccurs="0" /> + <xs:element name="backdoor-connection" type="xs:string" + minOccurs="0" /> + <xs:element name="vpn-id" type="xs:string" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l3-interface-ipv4-address-list" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element ref="tns:l3-interface-ipv6-address-list" + minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vlans"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vlan" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="sriov-vf"> + <xs:complexType> + <xs:sequence> + <xs:element name="pci-id" type="xs:string" /> + <xs:element name="vf-vlan-filter" type="xs:string" + minOccurs="0" /> + <xs:element name="vf-mac-filter" type="xs:string" + minOccurs="0" /> + <xs:element name="vf-vlan-strip" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-vlan-anti-spoof-check" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-mac-anti-spoof-check" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-mirrors" type="xs:string" minOccurs="0" /> + <xs:element name="vf-broadcast-allow" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-unknown-multicast-allow" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-unknown-unicast-allow" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-insert-stag" type="xs:boolean" + minOccurs="0" /> + <xs:element name="vf-link-status" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-network-id" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="sriov-vfs"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:sriov-vf" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="l-interface"> + <xs:complexType> + <xs:sequence> + <xs:element name="interface-name" type="xs:string" /> + <xs:element name="interface-role" type="xs:string" + minOccurs="0" /> + <xs:element name="v6-wan-link-ip" type="xs:string" + minOccurs="0" /> + <xs:element name="selflink" type="xs:string" minOccurs="0" /> + <xs:element name="interface-id" type="xs:string" + minOccurs="0" /> + <xs:element name="macaddr" type="xs:string" minOccurs="0" /> + <xs:element name="network-name" type="xs:string" + minOccurs="0" /> + <xs:element name="management-option" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:vlans" minOccurs="0" /> + <xs:element ref="tns:sriov-vfs" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l3-interface-ipv4-address-list" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element ref="tns:l3-interface-ipv6-address-list" + minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="l-interfaces"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:l-interface" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vserver"> + <xs:complexType> + <xs:sequence> + <xs:element name="vserver-id" type="xs:string" /> + <xs:element name="vserver-name" type="xs:string" /> + <xs:element name="vserver-name2" type="xs:string" + minOccurs="0" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="vserver-selflink" type="xs:string" /> + <xs:element name="in-maint" type="xs:boolean" /> + <xs:element name="is-closed-loop-disabled" type="xs:boolean" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:volumes" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vservers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vserver" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="tenant"> + <xs:complexType> + <xs:sequence> + <xs:element name="tenant-id" type="xs:string" /> + <xs:element name="tenant-name" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:vservers" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="tenants"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:tenant" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="flavor"> + <xs:complexType> + <xs:sequence> + <xs:element name="flavor-id" type="xs:string" /> + <xs:element name="flavor-name" type="xs:string" /> + <xs:element name="flavor-vcpus" type="xs:int" minOccurs="0" /> + <xs:element name="flavor-ram" type="xs:int" minOccurs="0" /> + <xs:element name="flavor-disk" type="xs:int" minOccurs="0" /> + <xs:element name="flavor-ephemeral" type="xs:int" + minOccurs="0" /> + <xs:element name="flavor-swap" type="xs:string" + minOccurs="0" /> + <xs:element name="flavor-is-public" type="xs:boolean" + minOccurs="0" /> + <xs:element name="flavor-selflink" type="xs:string" /> + <xs:element name="flavor-disabled" type="xs:boolean" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="flavors"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:flavor" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="group-assignment"> + <xs:complexType> + <xs:sequence> + <xs:element name="group-id" type="xs:string" /> + <xs:element name="group-type" type="xs:string" /> + <xs:element name="group-name" type="xs:string" /> + <xs:element name="group-description" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="group-assignments"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:group-assignment" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="snapshot"> + <xs:complexType> + <xs:sequence> + <xs:element name="snapshot-id" type="xs:string" /> + <xs:element name="snapshot-name" type="xs:string" + minOccurs="0" /> + <xs:element name="snapshot-architecture" type="xs:string" + minOccurs="0" /> + <xs:element name="snapshot-os-distro" type="xs:string" + minOccurs="0" /> + <xs:element name="snapshot-os-version" type="xs:string" + minOccurs="0" /> + <xs:element name="application" type="xs:string" + minOccurs="0" /> + <xs:element name="application-vendor" type="xs:string" + minOccurs="0" /> + <xs:element name="application-version" type="xs:string" + minOccurs="0" /> + <xs:element name="snapshot-selflink" type="xs:string" + minOccurs="0" /> + <xs:element name="prev-snapshot-id" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="snapshots"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:snapshot" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="metadatum"> + <xs:complexType> + <xs:sequence> + <xs:element name="metaname" type="xs:string" /> + <xs:element name="metaval" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="metadata"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:metadatum" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="image"> + <xs:complexType> + <xs:sequence> + <xs:element name="image-id" type="xs:string" /> + <xs:element name="image-name" type="xs:string" /> + <xs:element name="image-architecture" type="xs:string" + minOccurs="0" /> + <xs:element name="image-os-distro" type="xs:string" /> + <xs:element name="image-os-version" type="xs:string" /> + <xs:element name="application" type="xs:string" + minOccurs="0" /> + <xs:element name="application-vendor" type="xs:string" + minOccurs="0" /> + <xs:element name="application-version" type="xs:string" + minOccurs="0" /> + <xs:element name="image-selflink" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:metadata" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="images"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:image" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="availability-zones"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:availability-zone" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="cloud-region"> + <xs:complexType> + <xs:sequence> + <xs:element name="cloud-owner" type="xs:string" /> + <xs:element name="cloud-region-id" type="xs:string" /> + <xs:element name="cloud-type" type="xs:string" minOccurs="0" /> + <xs:element name="owner-defined-type" type="xs:string" + minOccurs="0" /> + <xs:element name="cloud-region-version" type="xs:string" + minOccurs="0" /> + <xs:element name="identity-url" type="xs:string" + minOccurs="0" /> + <xs:element name="cloud-zone" type="xs:string" minOccurs="0" /> + <xs:element name="complex-name" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:volume-groups" minOccurs="0" /> + <xs:element ref="tns:tenants" minOccurs="0" /> + <xs:element ref="tns:flavors" minOccurs="0" /> + <xs:element ref="tns:group-assignments" minOccurs="0" /> + <xs:element ref="tns:snapshots" minOccurs="0" /> + <xs:element ref="tns:images" minOccurs="0" /> + <xs:element ref="tns:dvs-switches" minOccurs="0" /> + <xs:element ref="tns:oam-networks" minOccurs="0" /> + <xs:element ref="tns:availability-zones" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="cloud-regions"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:cloud-region" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="network-profile"> + <xs:complexType> + <xs:sequence> + <xs:element name="nm-profile-name" type="xs:string" /> + <xs:element name="community-string" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="network-profiles"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:network-profile" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="p-interface"> + <xs:complexType> + <xs:sequence> + <xs:element name="interface-name" type="xs:string" /> + <xs:element name="speed-value" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-units" type="xs:string" + minOccurs="0" /> + <xs:element name="port-description" type="xs:string" + minOccurs="0" /> + <xs:element name="equipment-identifier" type="xs:string" + minOccurs="0" /> + <xs:element name="interface-role" type="xs:string" + minOccurs="0" /> + <xs:element name="interface-type" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="p-interfaces"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:p-interface" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="lag-interface"> + <xs:complexType> + <xs:sequence> + <xs:element name="interface-name" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-value" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-units" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="lag-interfaces"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:lag-interface" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="pserver"> + <xs:complexType> + <xs:sequence> + <xs:element name="hostname" type="xs:string" /> + <xs:element name="ptnii-equip-name" type="xs:string" + minOccurs="0" /> + <xs:element name="number-of-cpus" type="xs:int" + minOccurs="0" /> + <xs:element name="disk-in-gigabytes" type="xs:int" + minOccurs="0" /> + <xs:element name="ram-in-megabytes" type="xs:int" + minOccurs="0" /> + <xs:element name="equip-type" type="xs:string" minOccurs="0" /> + <xs:element name="equip-vendor" type="xs:string" + minOccurs="0" /> + <xs:element name="equip-model" type="xs:string" + minOccurs="0" /> + <xs:element name="fqdn" type="xs:string" minOccurs="0" /> + <xs:element name="pserver-selflink" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-address" type="xs:string" + minOccurs="0" /> + <xs:element name="serial-number" type="xs:string" + minOccurs="0" /> + <xs:element name="pserver-id" type="xs:string" minOccurs="0" /> + <xs:element name="internet-topology" type="xs:string" + minOccurs="0" /> + <xs:element name="in-maint" type="xs:boolean" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="pserver-name2" type="xs:string" + minOccurs="0" /> + <xs:element name="purpose" type="xs:string" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:p-interfaces" minOccurs="0" /> + <xs:element ref="tns:lag-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="pservers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:pserver" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="virtual-data-center"> + <xs:complexType> + <xs:sequence> + <xs:element name="vdc-id" type="xs:string" /> + <xs:element name="vdc-name" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="virtual-data-centers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:virtual-data-center" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="cloud-infrastructure"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:complexes" minOccurs="0" /> + <xs:element ref="tns:cloud-regions" minOccurs="0" /> + <xs:element ref="tns:network-profiles" minOccurs="0" /> + <xs:element ref="tns:pservers" minOccurs="0" /> + <xs:element ref="tns:virtual-data-centers" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="license-key-resource"> + <xs:complexType> + <xs:sequence> + <xs:element name="uuid" type="xs:string" /> + <xs:element name="assignment-type" type="xs:string" + minOccurs="0" /> + <xs:element name="assignment-status" type="xs:string" + minOccurs="0" /> + <xs:element name="assignment-group-uuid" type="xs:string" /> + <xs:element name="assignment-date" type="xs:string" + minOccurs="0" /> + <xs:element name="name" type="xs:string" minOccurs="0" /> + <xs:element name="model-uuid" type="xs:string" minOccurs="0" /> + <xs:element name="model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key-file-url" type="xs:string" + minOccurs="0" /> + <xs:element name="supplier-release-list" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="license-key-resources"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:license-key-resource" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="license-management"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:license-key-resources" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="connector"> + <xs:complexType> + <xs:sequence> + <xs:element name="resource-instance-id" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:metadata" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="connectors"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:connector" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-instance"> + <xs:complexType> + <xs:sequence> + <xs:element name="service-instance-id" type="xs:string" /> + <xs:element name="service-instance-name" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="bandwidth-total" type="xs:string" + minOccurs="0" /> + <xs:element name="bandwidth-up-wan1" type="xs:string" + minOccurs="0" /> + <xs:element name="bandwidth-down-wan1" type="xs:string" + minOccurs="0" /> + <xs:element name="bandwidth-up-wan2" type="xs:string" + minOccurs="0" /> + <xs:element name="bandwidth-down-wan2" type="xs:string" + minOccurs="0" /> + <xs:element name="vhn-portal-url" type="xs:string" + minOccurs="0" /> + <xs:element name="operational-status" type="xs:string" + minOccurs="0" /> + <xs:element name="service-instance-location-id" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:metadata" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-instances"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:service-instance" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-subscription"> + <xs:complexType> + <xs:sequence> + <xs:element name="service-type" type="xs:string" /> + <xs:element name="temp-ub-sub-account-id" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:service-instances" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-subscriptions"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:service-subscription" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="customer"> + <xs:complexType> + <xs:sequence> + <xs:element name="global-customer-id" type="xs:string" /> + <xs:element name="subscriber-name" type="xs:string" /> + <xs:element name="subscriber-type" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:service-subscriptions" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="customers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:customer" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="business"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:connectors" minOccurs="0" /> + <xs:element ref="tns:customers" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vnf-image"> + <xs:complexType> + <xs:sequence> + <xs:element name="uuid" type="xs:string" /> + <xs:element name="application" type="xs:string" /> + <xs:element name="application-vendor" type="xs:string" /> + <xs:element name="application-version" type="xs:string" + minOccurs="0" /> + <xs:element name="selflink" type="xs:string" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vnf-images"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vnf-image" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service"> + <xs:complexType> + <xs:sequence> + <xs:element name="service-id" type="xs:string" /> + <xs:element name="service-description" type="xs:string" /> + <xs:element name="service-selflink" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="service-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="services"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:service" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-capability"> + <xs:complexType> + <xs:sequence> + <xs:element name="service-type" type="xs:string" /> + <xs:element name="vnf-type" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-capabilities"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:service-capability" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="element-choice-set"> + <xs:complexType> + <xs:sequence> + <xs:element name="element-choice-set-uuid" type="xs:string" /> + <xs:element name="element-choice-set-name" type="xs:string" /> + <xs:element name="cardinality" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:model-elements" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="element-choice-sets"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:element-choice-set" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="constrained-element-set"> + <xs:complexType> + <xs:sequence> + <xs:element name="constrained-element-set-uuid" type="xs:string" /> + <xs:element name="constraint-type" type="xs:string" /> + <xs:element name="check-type" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:element-choice-sets" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="constrained-element-sets"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:constrained-element-set" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="model-constraint"> + <xs:complexType> + <xs:sequence> + <xs:element name="model-constraint-uuid" type="xs:string" /> + <xs:element name="constrained-element-set-uuid-to-replace" + type="xs:string" /> + <xs:element ref="tns:constrained-element-sets" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="model-constraints"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:model-constraint" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="model-element"> + <xs:complexType> + <xs:sequence> + <xs:element name="model-element-uuid" type="xs:string" /> + <xs:element name="new-data-del-flag" type="xs:string" /> + <xs:element name="cardinality" type="xs:string" /> + <xs:element name="linkage-points" minOccurs="0"> + <xs:complexType> + <xs:sequence> + <xs:element name="linkage-point" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:model-elements" minOccurs="0" /> + <xs:element ref="tns:model-constraints" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="model-elements"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:model-element" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="model"> + <xs:complexType> + <xs:sequence> + <xs:element name="model-name-version-id" type="xs:string" /> + <xs:element name="model-type" type="xs:string" /> + <xs:element name="model-name" type="xs:string" /> + <xs:element name="model-id" type="xs:string" /> + <xs:element name="model-version" type="xs:string" /> + <xs:element name="model-description" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:model-elements" minOccurs="0" /> + <xs:element ref="tns:metadata" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="models"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:model" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="related-lookup"> + <xs:complexType> + <xs:sequence> + <xs:element name="related-lookup-uuid" type="xs:string" /> + <xs:element name="source-node-type" type="xs:string" /> + <xs:element name="source-node-property" type="xs:string" /> + <xs:element name="target-node-type" type="xs:string" /> + <xs:element name="target-node-property" type="xs:string" /> + <xs:element name="property-collect-list" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="related-lookups"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:related-lookup" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="property-constraint"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-constraint-uuid" type="xs:string" /> + <xs:element name="constraint-type" type="xs:string" /> + <xs:element name="property-name" type="xs:string" /> + <xs:element name="property-value" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="property-constraints"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:property-constraint" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="named-query-element"> + <xs:complexType> + <xs:sequence> + <xs:element name="named-query-element-uuid" type="xs:string" /> + <xs:element name="property-collect-list" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="property-limit-desc" type="xs:string" + minOccurs="0" /> + <xs:element name="do-not-output" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:named-query-elements" minOccurs="0" /> + <xs:element ref="tns:related-lookups" minOccurs="0" /> + <xs:element ref="tns:property-constraints" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="named-query-elements"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:named-query-element" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="named-query"> + <xs:complexType> + <xs:sequence> + <xs:element name="named-query-uuid" type="xs:string" /> + <xs:element name="named-query-name" type="xs:string" /> + <xs:element name="named-query-version" type="xs:string" /> + <xs:element name="required-input-params" minOccurs="0"> + <xs:complexType> + <xs:sequence> + <xs:element name="required-input-param" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="description" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:named-query-elements" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="named-queries"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:named-query" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="service-design-and-creation"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vnf-images" minOccurs="0" /> + <xs:element ref="tns:services" minOccurs="0" /> + <xs:element ref="tns:service-capabilities" minOccurs="0" /> + <xs:element ref="tns:models" minOccurs="0" /> + <xs:element ref="tns:named-queries" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="logical-link"> + <xs:complexType> + <xs:sequence> + <xs:element name="link-name" type="xs:string" /> + <xs:element name="link-type" type="xs:string" /> + <xs:element name="speed-value" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-units" type="xs:string" + minOccurs="0" /> + <xs:element name="ip-version" type="xs:string" minOccurs="0" /> + <xs:element name="routing-protocol" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="operational-status" type="xs:string" + minOccurs="0" /> + <xs:element name="link-role" type="xs:string" minOccurs="0" /> + <xs:element name="link-name2" type="xs:string" minOccurs="0" /> + <xs:element name="link-id" type="xs:string" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="logical-links"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:logical-link" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="class-of-service"> + <xs:complexType> + <xs:sequence> + <xs:element name="cos" type="xs:string" /> + <xs:element name="probe-id" type="xs:string" minOccurs="0" /> + <xs:element name="probe-type" type="xs:string" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="classes-of-service"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:class-of-service" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="site-pair"> + <xs:complexType> + <xs:sequence> + <xs:element name="site-pair-id" type="xs:string" /> + <xs:element name="source-ip" type="xs:string" minOccurs="0" /> + <xs:element name="destination-ip" type="xs:string" + minOccurs="0" /> + <xs:element name="ip-version" type="xs:string" minOccurs="0" /> + <xs:element name="destination-hostname" type="xs:string" + minOccurs="0" /> + <xs:element name="destination-equip-type" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:classes-of-service" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="site-pairs"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:site-pair" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="routing-instance"> + <xs:complexType> + <xs:sequence> + <xs:element name="routing-instance-id" type="xs:string" /> + <xs:element name="rpm-owner" type="xs:string" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:site-pairs" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="routing-instances"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:routing-instance" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="site-pair-set"> + <xs:complexType> + <xs:sequence> + <xs:element name="site-pair-set-id" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:routing-instances" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="site-pair-sets"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:site-pair-set" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vpn-binding"> + <xs:complexType> + <xs:sequence> + <xs:element name="vpn-id" type="xs:string" /> + <xs:element name="vpn-name" type="xs:string" /> + <xs:element name="global-route-target" type="xs:string" /> + <xs:element name="vpn-platform" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vpn-bindings"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vpn-binding" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vpls-pe"> + <xs:complexType> + <xs:sequence> + <xs:element name="equipment-name" type="xs:string" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-address" type="xs:string" + minOccurs="0" /> + <xs:element name="equipment-role" type="xs:string" + minOccurs="0" /> + <xs:element name="vlan-id-outer" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:p-interfaces" minOccurs="0" /> + <xs:element ref="tns:lag-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vpls-pes"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vpls-pe" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="multicast-configuration"> + <xs:complexType> + <xs:sequence> + <xs:element name="multicast-configuration-id" type="xs:string" /> + <xs:element name="multicast-protocol" type="xs:string" /> + <xs:element name="rp-type" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="multicast-configurations"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:multicast-configuration" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="cvlan-tag-entry"> + <xs:complexType> + <xs:sequence> + <xs:element name="cvlan-tag" type="xs:unsignedInt" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="cvlan-tags"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:cvlan-tag-entry" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="port-group"> + <xs:complexType> + <xs:sequence> + <xs:element name="interface-id" type="xs:string" /> + <xs:element name="neutron-network-id" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-network-name" type="xs:string" + minOccurs="0" /> + <xs:element name="interface-role" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="port-group-id" type="xs:string" + minOccurs="0" /> + <xs:element name="port-group-name" type="xs:string" + minOccurs="0" /> + <xs:element name="switch-name" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="mso-catalog-key" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:cvlan-tags" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="port-groups"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:port-group" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vce"> + <xs:complexType> + <xs:sequence> + <xs:element name="vnf-id" type="xs:string" /> + <xs:element name="vnf-name" type="xs:string" /> + <xs:element name="vnf-name2" type="xs:string" minOccurs="0" /> + <xs:element name="vnf-type" type="xs:string" /> + <xs:element name="service-id" type="xs:string" minOccurs="0" /> + <xs:element name="regional-resource-zone" type="xs:string" + minOccurs="0" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="operational-state" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key" type="xs:string" + minOccurs="0" /> + <xs:element name="equipment-role" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="mso-catalog-key" type="xs:string" + minOccurs="0" /> + <xs:element name="vpe-id" type="xs:string" minOccurs="0" /> + <xs:element name="v6-vce-wan-address" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-address" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-loopback0-address" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:port-groups" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vces"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vce" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vpe"> + <xs:complexType> + <xs:sequence> + <xs:element name="vnf-id" type="xs:string" /> + <xs:element name="vnf-name" type="xs:string" /> + <xs:element name="vnf-name2" type="xs:string" minOccurs="0" /> + <xs:element name="vnf-type" type="xs:string" /> + <xs:element name="service-id" type="xs:string" minOccurs="0" /> + <xs:element name="regional-resource-zone" type="xs:string" + minOccurs="0" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="operational-state" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key" type="xs:string" + minOccurs="0" /> + <xs:element name="equipment-role" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="mso-catalog-key" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-address" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-gateway-address-prefix-length" + type="xs:int" minOccurs="0" /> + <xs:element name="ipv4-oam-gateway-address" type="xs:string" + minOccurs="0" /> + <xs:element name="v4-loopback0-ip-address" type="xs:string" + minOccurs="0" /> + <xs:element name="vlan-id-outer" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="as-number" type="xs:string" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="summary-status" type="xs:string" + minOccurs="0" /> + <xs:element name="encrypted-access-flag" type="xs:boolean" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l-interfaces" minOccurs="0" /> + <xs:element ref="tns:lag-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vpes"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vpe" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vnfc"> + <xs:complexType> + <xs:sequence> + <xs:element name="vnfc-name" type="xs:string" /> + <xs:element name="vnfc-function-code" type="xs:string" /> + <xs:element name="vnfc-type" type="xs:string" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="ipaddress-v4-oam-vip" type="xs:string" + minOccurs="0" /> + <xs:element name="in-maint" type="xs:boolean" /> + <xs:element name="is-closed-loop-disabled" type="xs:boolean" /> + <xs:element name="group-notation" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vnfcs"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vnfc" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="subnet"> + <xs:complexType> + <xs:sequence> + <xs:element name="subnet-id" type="xs:string" /> + <xs:element name="subnet-name" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-subnet-id" type="xs:string" + minOccurs="0" /> + <xs:element name="gateway-address" type="xs:string" + minOccurs="0" /> + <xs:element name="network-start-address" type="xs:string" + minOccurs="0" /> + <xs:element name="cidr-mask" type="xs:string" minOccurs="0" /> + <xs:element name="ip-version" type="xs:string" minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="dhcp-enabled" type="xs:boolean" /> + <xs:element name="dhcp-start" type="xs:string" minOccurs="0" /> + <xs:element name="dhcp-end" type="xs:string" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="subnets"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:subnet" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="ctag-assignment"> + <xs:complexType> + <xs:sequence> + <xs:element name="vlan-id-inner" type="xs:unsignedInt" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="ctag-assignments"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:ctag-assignment" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="segmentation-assignment"> + <xs:complexType> + <xs:sequence> + <xs:element name="segmentation-id" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="segmentation-assignments"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:segmentation-assignment" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="l3-network"> + <xs:complexType> + <xs:sequence> + <xs:element name="network-id" type="xs:string" /> + <xs:element name="network-name" type="xs:string" /> + <xs:element name="network-type" type="xs:string" + minOccurs="0" /> + <xs:element name="network-role" type="xs:string" + minOccurs="0" /> + <xs:element name="network-technology" type="xs:string" + minOccurs="0" /> + <xs:element name="neutron-network-id" type="xs:string" + minOccurs="0" /> + <xs:element name="is-bound-to-vpn" type="xs:boolean" /> + <xs:element name="service-id" type="xs:string" minOccurs="0" /> + <xs:element name="network-role-instance" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="mso-catalog-key" type="xs:string" + minOccurs="0" /> + <xs:element name="contrail-network-fqdn" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="physical-network-name" type="xs:string" + minOccurs="0" /> + <xs:element name="is-provider-network" type="xs:boolean" /> + <xs:element name="is-shared-network" type="xs:boolean" /> + <xs:element name="is-external-network" type="xs:boolean" /> + <xs:element ref="tns:subnets" minOccurs="0" /> + <xs:element ref="tns:ctag-assignments" minOccurs="0" /> + <xs:element ref="tns:segmentation-assignments" minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="l3-networks"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:l3-network" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="network-policy"> + <xs:complexType> + <xs:sequence> + <xs:element name="network-policy-id" type="xs:string" /> + <xs:element name="network-policy-fqdn" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="network-policies"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:network-policy" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vf-module"> + <xs:complexType> + <xs:sequence> + <xs:element name="vf-module-id" type="xs:string" /> + <xs:element name="vf-module-name" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="is-base-vf-module" type="xs:boolean" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="contrail-service-instance-fqdn" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vf-modules"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vf-module" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="generic-vnf"> + <xs:complexType> + <xs:sequence> + <xs:element name="vnf-id" type="xs:string" /> + <xs:element name="vnf-name" type="xs:string" /> + <xs:element name="vnf-name2" type="xs:string" minOccurs="0" /> + <xs:element name="vnf-type" type="xs:string" /> + <xs:element name="service-id" type="xs:string" minOccurs="0" /> + <xs:element name="regional-resource-zone" type="xs:string" + minOccurs="0" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="operational-state" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key" type="xs:string" + minOccurs="0" /> + <xs:element name="equipment-role" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="mso-catalog-key" type="xs:string" + minOccurs="0" /> + <xs:element name="management-option" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-address" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-loopback0-address" type="xs:string" + minOccurs="0" /> + <xs:element name="nm-lan-v6-address" type="xs:string" + minOccurs="0" /> + <xs:element name="management-v6-address" type="xs:string" + minOccurs="0" /> + <xs:element name="vcpu" type="xs:unsignedInt" minOccurs="0" /> + <xs:element name="vcpu-units" type="xs:string" minOccurs="0" /> + <xs:element name="vmemory" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="vmemory-units" type="xs:string" + minOccurs="0" /> + <xs:element name="vdisk" type="xs:unsignedInt" minOccurs="0" /> + <xs:element name="vdisk-units" type="xs:string" + minOccurs="0" /> + <xs:element name="in-maint" type="xs:boolean" /> + <xs:element name="is-closed-loop-disabled" type="xs:boolean" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="summary-status" type="xs:string" + minOccurs="0" /> + <xs:element name="encrypted-access-flag" type="xs:boolean" + minOccurs="0" /> + <xs:element name="entitlement-assignment-group-uuid" + type="xs:string" minOccurs="0" /> + <xs:element name="entitlement-resource-uuid" type="xs:string" + minOccurs="0" /> + <xs:element name="license-assignment-group-uuid" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key-uuid" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="persona-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-id" type="xs:string" + minOccurs="0" /> + <xs:element name="widget-model-version" type="xs:string" + minOccurs="0" /> + <xs:element name="as-number" type="xs:string" minOccurs="0" /> + <xs:element name="regional-resource-subzone" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l-interfaces" minOccurs="0" /> + <xs:element ref="tns:lag-interfaces" minOccurs="0" /> + <xs:element ref="tns:vf-modules" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="generic-vnfs"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:generic-vnf" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="lag-link"> + <xs:complexType> + <xs:sequence> + <xs:element name="link-name" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="lag-links"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:lag-link" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="newvce"> + <xs:complexType> + <xs:sequence> + <xs:element name="vnf-id2" type="xs:string" /> + <xs:element name="vnf-name" type="xs:string" /> + <xs:element name="vnf-name2" type="xs:string" minOccurs="0" /> + <xs:element name="vnf-type" type="xs:string" /> + <xs:element name="prov-status" type="xs:string" + minOccurs="0" /> + <xs:element name="operational-state" type="xs:string" + minOccurs="0" /> + <xs:element name="license-key" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-oam-address" type="xs:string" + minOccurs="0" /> + <xs:element name="equipment-role" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element name="ipv4-loopback0-address" type="xs:string" + minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="heat-stack-id" type="xs:string" + minOccurs="0" /> + <xs:element name="mso-catalog-key" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:l-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="newvces"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:newvce" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="pnf"> + <xs:complexType> + <xs:sequence> + <xs:element name="pnf-name" type="xs:string" /> + <xs:element name="pnf-name2" type="xs:string" minOccurs="0" /> + <xs:element name="pnf-name2-source" type="xs:string" + minOccurs="0" /> + <xs:element name="pnf-id" type="xs:string" minOccurs="0" /> + <xs:element name="equip-type" type="xs:string" minOccurs="0" /> + <xs:element name="equip-vendor" type="xs:string" + minOccurs="0" /> + <xs:element name="equip-model" type="xs:string" + minOccurs="0" /> + <xs:element name="management-option" type="xs:string" + minOccurs="0" /> + <xs:element name="ipaddress-v4-oam" type="xs:string" + minOccurs="0" /> + <xs:element name="sw-version" type="xs:string" minOccurs="0" /> + <xs:element name="orchestration-status" type="xs:string" + minOccurs="0" /> + <xs:element name="in-maint" type="xs:boolean" /> + <xs:element name="frame-id" type="xs:string" minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:p-interfaces" minOccurs="0" /> + <xs:element ref="tns:lag-interfaces" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="pnfs"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:pnf" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="physical-link"> + <xs:complexType> + <xs:sequence> + <xs:element name="link-name" type="xs:string" /> + <xs:element name="speed-value" type="xs:string" + minOccurs="0" /> + <xs:element name="speed-units" type="xs:string" + minOccurs="0" /> + <xs:element name="circuit-id" type="xs:string" minOccurs="0" /> + <xs:element name="dual-mode" type="xs:string" minOccurs="0" /> + <xs:element name="management-option" type="xs:string" + minOccurs="0" /> + <xs:element name="service-provider-name" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="physical-links"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:physical-link" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vig-server"> + <xs:complexType> + <xs:sequence> + <xs:element name="vig-address-type" type="xs:string" /> + <xs:element name="ipaddress-v4-vig" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="ipaddress-v6-vig" type="xs:string" + minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vig-servers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:vig-server" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="ipsec-configuration"> + <xs:complexType> + <xs:sequence> + <xs:element name="ipsec-configuration-id" type="xs:string" /> + <xs:element name="requested-vig-address-type" type="xs:string" + minOccurs="0" /> + <xs:element name="requested-encryption-strength" type="xs:string" + minOccurs="0" /> + <xs:element name="requested-dmz-type" type="xs:string" + minOccurs="0" /> + <xs:element name="shared-dmz-network-address" type="xs:string" + minOccurs="0" /> + <xs:element name="requested-customer-name" type="xs:string" + minOccurs="0" /> + <xs:element name="ike-version" type="xs:string" + minOccurs="0" /> + <xs:element name="ikev1-authentication" type="xs:string" + minOccurs="0" /> + <xs:element name="ikev1-encryption" type="xs:string" + minOccurs="0" /> + <xs:element name="ikev1-dh-group" type="xs:string" + minOccurs="0" /> + <xs:element name="ikev1-am-group-id" type="xs:string" + minOccurs="0" /> + <xs:element name="ikev1-am-password" type="xs:string" + minOccurs="0" /> + <xs:element name="ikev1-sa-lifetime" type="xs:string" + minOccurs="0" /> + <xs:element name="ipsec-authentication" type="xs:string" + minOccurs="0" /> + <xs:element name="ipsec-encryption" type="xs:string" + minOccurs="0" /> + <xs:element name="ipsec-sa-lifetime" type="xs:string" + minOccurs="0" /> + <xs:element name="ipsec-pfs" type="xs:string" minOccurs="0" /> + <xs:element name="xauth-userid" type="xs:string" + minOccurs="0" /> + <xs:element name="xauth-user-password" type="xs:string" + minOccurs="0" /> + <xs:element name="dpd-interval" type="xs:string" + minOccurs="0" /> + <xs:element name="dpd-frequency" type="xs:string" + minOccurs="0" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + <xs:element ref="tns:vig-servers" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="ipsec-configurations"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:ipsec-configuration" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="route-table-reference"> + <xs:complexType> + <xs:sequence> + <xs:element name="route-table-reference-id" type="xs:string" /> + <xs:element name="route-table-reference-fqdn" type="xs:string" /> + <xs:element name="resource-version" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:relationship-list" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="route-table-references"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:route-table-reference" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="network"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:logical-links" minOccurs="0" /> + <xs:element ref="tns:site-pair-sets" minOccurs="0" /> + <xs:element ref="tns:vpn-bindings" minOccurs="0" /> + <xs:element ref="tns:vpls-pes" minOccurs="0" /> + <xs:element ref="tns:multicast-configurations" minOccurs="0" /> + <xs:element ref="tns:vces" minOccurs="0" /> + <xs:element ref="tns:vpes" minOccurs="0" /> + <xs:element ref="tns:vnfcs" minOccurs="0" /> + <xs:element ref="tns:l3-networks" minOccurs="0" /> + <xs:element ref="tns:network-policies" minOccurs="0" /> + <xs:element ref="tns:generic-vnfs" minOccurs="0" /> + <xs:element ref="tns:lag-links" minOccurs="0" /> + <xs:element ref="tns:newvces" minOccurs="0" /> + <xs:element ref="tns:pnfs" minOccurs="0" /> + <xs:element ref="tns:physical-links" minOccurs="0" /> + <xs:element ref="tns:ipsec-configurations" minOccurs="0" /> + <xs:element ref="tns:route-table-references" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="reserved-prop-names"> + <xs:complexType> + <xs:sequence> + <xs:element name="last-mod-source-of-truth" type="xs:string" + minOccurs="0" /> + <xs:element name="aai-node-type" type="xs:string" + minOccurs="0" /> + <xs:element name="aai-created-ts" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="aai-unique-key" type="xs:string" + minOccurs="0" /> + <xs:element name="aai-last-mod-ts" type="xs:unsignedInt" + minOccurs="0" /> + <xs:element name="source-of-truth" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="edge-prop-names"> + <xs:complexType> + <xs:sequence> + <xs:element name="edgeLabel" type="xs:string" minOccurs="0" /> + <xs:element name="direction" type="xs:string" minOccurs="0" /> + <xs:element name="multiplicityRule" type="xs:string" + minOccurs="0" /> + <xs:element name="isParent" type="xs:boolean" minOccurs="0" /> + <xs:element name="usesResource" type="xs:boolean" + minOccurs="0" /> + <xs:element name="hasDelTarget" type="xs:boolean" + minOccurs="0" /> + <xs:element name="SVC-INFRA" type="xs:string" minOccurs="0" /> + <xs:element name="SVC-INFRA-REV" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="aai-internal"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:reserved-prop-names" minOccurs="0" + maxOccurs="unbounded" /> + <xs:element ref="tns:edge-prop-names" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="inventory"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:search" minOccurs="0" /> + <xs:element ref="tns:actions" minOccurs="0" /> + <xs:element ref="tns:cloud-infrastructure" minOccurs="0" /> + <xs:element ref="tns:license-management" minOccurs="0" /> + <xs:element ref="tns:business" minOccurs="0" /> + <xs:element ref="tns:service-design-and-creation" + minOccurs="0" /> + <xs:element ref="tns:network" minOccurs="0" /> + <xs:element ref="tns:aai-internal" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="notification-event-header"> + <xs:complexType> + <xs:sequence> + <xs:element name="id" type="xs:string" minOccurs="0" /> + <xs:element name="timestamp" type="xs:string" minOccurs="0" /> + <xs:element name="source-name" type="xs:string" + minOccurs="0" /> + <xs:element name="domain" type="xs:string" minOccurs="0" /> + <xs:element name="sequence-number" type="xs:string" + minOccurs="0" /> + <xs:element name="severity" type="xs:string" minOccurs="0" /> + <xs:element name="event-type" type="xs:string" minOccurs="0" /> + <xs:element name="version" type="xs:string" minOccurs="0" /> + <xs:element name="action" type="xs:string" minOccurs="0" /> + <xs:element name="entity-type" type="xs:string" + minOccurs="0" /> + <xs:element name="top-entity-type" type="xs:string" + minOccurs="0" /> + <xs:element name="entity-link" type="xs:string" + minOccurs="0" /> + <xs:element name="status" type="xs:string" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="notification-event"> + <xs:complexType> + <xs:sequence> + <xs:element name="cambria.partition" type="xs:string" + minOccurs="0" /> + <xs:element ref="tns:notification-event-header" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="query-parameters"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:named-query" minOccurs="0" /> + <xs:element ref="tns:model" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="instance-filter"> + <xs:complexType> + <xs:sequence /> + </xs:complexType> + </xs:element> + <xs:element name="instance-filters"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:instance-filter" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="model-and-named-query-search"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:query-parameters" minOccurs="0" /> + <xs:element ref="tns:instance-filters" minOccurs="0" /> + <xs:element name="top-node-type" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="properties"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-name" type="xs:string" + minOccurs="0" /> + <xs:element name="property-value" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="extra-properties"> + <xs:complexType> + <xs:sequence /> + </xs:complexType> + </xs:element> + <xs:element name="inventory-response-item"> + <xs:complexType> + <xs:sequence> + <xs:element name="model-name" type="xs:string" minOccurs="0" /> + <xs:element ref="tns:extra-properties" minOccurs="0" /> + <xs:element ref="tns:inventory-response-items" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="inventory-response-items"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:inventory-response-item" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="response-list"> + <xs:complexType> + <xs:sequence> + <xs:element ref="tns:inventory-response-items" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="extra-property"> + <xs:complexType> + <xs:sequence> + <xs:element name="property-name" type="xs:string" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="vnf"> + <xs:complexType> + <xs:sequence> + <xs:element name="vnf-id" type="xs:string" /> + </xs:sequence> + </xs:complexType> + </xs:element> +</xs:schema> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============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========================================================= + --> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="vnf-catalog"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="part-number-list" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="part-number" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="vnf-type" minOccurs="0" maxOccurs="1" + type="xsd:normalizedString" /> + <xsd:element name="vendor-info" minOccurs="0" + maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="vendor-name" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="vendor-part-number" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="vendor-model" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="vcpu" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="vcpu-default" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + <xsd:element name="vcpu-min" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + <xsd:element name="vcpu-max" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="vmemory" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="vmemory-default" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + <xsd:element name="vmemory-units" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="vmemory-min" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + <xsd:element name="vmemory-max" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="vdisk" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="vdisk-default" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + <xsd:element name="vdisk-units" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="vdisk-min" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + <xsd:element name="vdisk-max" minOccurs="0" + maxOccurs="1" type="xsd:int" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="software-version-list" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="software-version" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="software-version-state" + minOccurs="0" maxOccurs="1" type="xsd:int" /> + <xsd:element name="software-filetype" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="file-md5-value" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="software-filename" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="vnf-features-list" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="vnf-feature" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="license-list" minOccurs="0" + maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="license-assignment-group" + minOccurs="0" maxOccurs="1" type="xsd:normalizedString" /> + <xsd:element name="license-required" minOccurs="0" + maxOccurs="1" type="xsd:normalizedString" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> +</xsd:schema> 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 @@ +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:mvc="http://www.springframework.org/schema/mvc" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> + +</beans>
\ 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 @@ +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:mvc="http://www.springframework.org/schema/mvc" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> + + <bean id="modelLoader" class="org.openecomp.modelloader.service.ModelLoaderService" init-method="start"/> + + +</beans>
\ 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> + <display-name>model-loader</display-name> + + <listener> + <listener-class> + org.springframework.web.context.ContextLoaderListener + </listener-class> + </listener> + + <servlet> + <servlet-name>rest</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> + <servlet-mapping> + <servlet-name>rest</servlet-name> + <url-pattern>/</url-pattern> + </servlet-mapping> +</web-app>
\ No newline at end of file |