summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorserena.spinoso <serena.spinoso@polito.it>2018-04-26 14:19:16 +0200
committerserena.spinoso <serena.spinoso@polito.it>2018-04-26 14:39:01 +0200
commitfcda9807cfa6a89d691877126b406c5d3909d9b9 (patch)
tree46fcec15887a0e0722217c26606e1859c8c10ff6
parent320ca9e335797f2081f253df60a860e72b6cc9fb (diff)
Support TOSCA in verigraph (gRPC service)
JIRA: PARSER-179 Add TOSCA service description in gRPC server. Add a TOSCA-based client to use the new functionality. Add a JUnit class for testing gRPC service with TOSCA descriptor Change-Id: Id3217a674f076714cd48e3b7e4236e7445d89cd2 Signed-off-by: serena.spinoso <serena.spinoso@polito.it>
-rw-r--r--verigraph/build.xml126
-rw-r--r--verigraph/gRPC-build.xml74
-rwxr-xr-xverigraph/pom.xml16
-rw-r--r--verigraph/schema/README.rst4
-rw-r--r--verigraph/schema/tosca/TOSCA-v1.0.xsd790
-rw-r--r--verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd280
-rw-r--r--verigraph/schema/tosca/ToscaVerigraphDefinitions.xml77
-rw-r--r--verigraph/schema/tosca/yamlToscaDefinitions.yaml157
-rw-r--r--verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java299
-rw-r--r--verigraph/src/it/polito/verigraph/grpc/server/GrpcUtils.java29
-rw-r--r--verigraph/src/it/polito/verigraph/grpc/server/Service.java169
-rw-r--r--verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java425
-rw-r--r--verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java101
-rw-r--r--verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java150
-rw-r--r--verigraph/src/main/proto/verigraph.proto113
15 files changed, 2743 insertions, 67 deletions
diff --git a/verigraph/build.xml b/verigraph/build.xml
index dae4678..ba576a7 100644
--- a/verigraph/build.xml
+++ b/verigraph/build.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017 Politecnico di Torino and others.
+ Copyright (c) 2017/18 Politecnico di Torino and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Apache License, Version 2.0
@@ -14,6 +14,9 @@
<property name="root.location" location="." />
<!-- The location to be used for class files -->
+ <property name="docker-grpc.dir" value="${root.location}/docker/gRPC" />
+ <property name="docker-rest.dir" value="${root.location}/docker/REST" />
+ <property name="cli.dir" value="${root.location}/VerigraphCLI" />
<property name="src.dir" location="${root.location}/src" />
<property name="gen.dir" location="${root.location}/gen-src" />
<property name="war.dir" location="${root.location}/war" />
@@ -23,6 +26,9 @@
<property name="lib.dir" location="${root.location}/lib" />
<property name="schemadir" location="${root.location}/schema" />
<property name="schemafile" value="xml_components.xsd" />
+ <property name="toscaschemadir" location="${root.location}/schema/tosca" />
+ <property name="toscaschemafile" value="TOSCA-v1.0.xsd" />
+ <property name="toscaverigraphschemafile" value="ToscaTypes_XMLconfig.xsd" />
<property name="testfile" value="test.py" />
<property name="target" value="1.8" />
<property name="source" value="1.8" />
@@ -86,22 +92,38 @@
<delete file="${lib.dir}/z3-4.5.0-x86-win.zip" />
</target>
-
- <target name="-chk-bindings">
- <uptodate property="generate-bindings.notRequired" targetfile="${src.dir}/.flagfile">
- <srcfiles dir="${schemadir}" includes="${schemafile}" />
+
+ <target name="chk-bindings">
+ <uptodate property="generate-bindings.notRequired" targetfile="${gen.dir}/.flagfile">
+ <srcresources>
+ <fileset dir="${schemadir}" includes="${schemafile}" />
+ <fileset dir="${toscaschemadir}" includes="${toscaschemafile}" />
+ <fileset dir="${toscaschemadir}" includes="${toscaverigraphschemafile}" />
+ </srcresources>
</uptodate>
</target>
-
- <target name="generate-bindings" unless="generate-bindings.notRequired" depends="init" description="Create the value classes">
+ <target name="generate-bindings" unless="generate-bindings.notRequired" depends="init, chk-bindings" description="Create the value classes">
<exec executable="xjc" failonerror="true">
<arg line="-d ${gen.dir} -p it.polito.neo4j.jaxb ${schemadir}/${schemafile}" />
</exec>
- <touch file="${src.dir}/.flagfile" />
+ <exec executable="xjc" failonerror="true">
+ <arg line="-d ${gen.dir} -p it.polito.tosca.jaxb ${toscaschemadir}/${toscaschemafile}" />
+ </exec>
+ <mkdir dir="${root.location}/temp-gen" />
+ <exec executable="xjc" failonerror="true">
+ <arg line="-d ${root.location}/temp-gen -p it.polito.tosca.jaxb ${toscaschemadir}/${toscaverigraphschemafile}" />
+ </exec>
+
+ <copy toDir="${gen.dir}/it/polito/tosca/jaxb" overwrite="true">
+ <file name="${root.location}/temp-gen/it/polito/tosca/jaxb/Configuration.java" />
+ </copy>
+ <delete dir="${root.location}/temp-gen" />
+
+ <touch file="${gen.dir}/.flagfile" />
</target>
-
+
<!-- The target for compiling the Verigraph application -->
<target name="build-service" depends="init, generate-bindings, mvn-init">
<echo>Building verigraph (if needed)...</echo>
@@ -166,12 +188,10 @@
</sequential>
</macrodef>
-
<target name="war-exploded" depends="build-service">
<war-exploded />
</target>
-
<target name="generate-war" depends="war-exploded">
<war destfile="${gen-war.dir}/${serviceName}.war" basedir="${gen-tomcat-service.dir}">
<exclude name="protoc-dependencies/" />
@@ -181,7 +201,80 @@
</war>
</target>
-
+ <target name="docker-rest-build" depends="generate-war">
+ <delete file="${docker-rest.dir}/verigraph.war" />
+
+ <copy file="${gen-war.dir}/verigraph.war" toDir="${docker-rest.dir}" />
+ </target>
+
+ <target name="docker-grpc-build" depends="build-service">
+ <delete dir="${docker-grpc.dir}/service_lib" />
+ <mkdir dir="${docker-grpc.dir}/service_lib" />
+
+ <copy toDir="${docker-grpc.dir}/service_lib" flatten="true" overwrite="true">
+ <fileset refid="runtime.fileset" />
+ </copy>
+ <copy file="${lib.dir}/com.microsoft.z3.jar" todir="${docker-grpc.dir}/service_lib" />
+
+ <delete file="${docker-grpc.dir}/server.properties" />
+ <delete dir="${docker-grpc.dir}/jsonschema" />
+ <copy file="${root.location}/server.properties" todir="${docker-grpc.dir}" />
+ <copydir src="${root.location}/jsonschema" dest="${docker-grpc.dir}/jsonschema" />
+
+ <path id="jars.path">
+ <fileset dir="${docker-grpc.dir}">
+ <include name="service_lib/*.jar" />
+ </fileset>
+ </path>
+
+ <pathconvert property="jars.mf" pathsep=" ">
+ <path refid="jars.path" />
+ <flattenmapper />
+ <map from="" to="service_lib/" />
+ </pathconvert>
+
+ <delete file="${docker-grpc.dir}/service.jar"/>
+ <jar destfile="${docker-grpc.dir}/service.jar">
+ <manifest>
+ <attribute name="Main-Class" value="it.polito.verigraph.grpc.server.Service"/>
+ <attribute name="Class-Path" value="${jars.mf}"/>
+ </manifest>
+ <fileset dir="${root.location}/build"/>
+ </jar>
+ </target>
+
+
+ <target name="build-cli-jar" depends="build-service">
+ <delete dir="${cli.dir}" />
+ <mkdir dir="${cli.dir}" />
+
+ <copy toDir="${cli.dir}/service_lib" flatten="true" overwrite="true">
+ <fileset refid="runtime.fileset" />
+ </copy>
+ <copy file="${src.dir}/it/polito/verigraph/tosca/README_CLI.txt" todir="${cli.dir}" />
+
+ <path id="jars.path">
+ <fileset dir="${cli.dir}">
+ <include name="service_lib/*.jar" />
+ </fileset>
+ </path>
+
+ <pathconvert property="jars.mf" pathsep=" ">
+ <path refid="jars.path" />
+ <flattenmapper />
+ <map from="" to="service_lib/" />
+ </pathconvert>
+
+ <delete file="${cli.dir}/VerigraphCLI.jar"/>
+ <jar destfile="${cli.dir}/VerigraphCLI.jar">
+ <manifest>
+ <attribute name="Main-Class" value="it.polito.verigraph.tosca.ToscaCLI"/>
+ <attribute name="Class-Path" value="${jars.mf}"/>
+ </manifest>
+ <fileset dir="${root.location}/build"/>
+ </jar>
+ </target>
+
<!-- launch test python test -->
<target name="run-test">
<exec dir="${test.dir}" executable="python">
@@ -191,8 +284,6 @@
</exec>
</target>
-
-
<!-- target for cleaning -->
<target name="clean">
<delete dir="${build.dir}" />
@@ -200,7 +291,12 @@
<delete dir="${gen-tomcat-service.dir}" />
<delete dir="${war.dir}" />
<delete dir="${lib.dir}" />
+ <delete dir="${docker-grpc.dir}/service_lib" />
+ <delete dir="${docker-grpc.dir}/jsonschema" />
+ <delete file="${docker-grpc.dir}/server.properties" />
+ <delete file="${docker-grpc.dir}/service.jar" />
+ <delete file="${docker-rest.dir}/verigraph.war" />
+ <delete dir="${cli.dir}" />
</target>
-
</project> \ No newline at end of file
diff --git a/verigraph/gRPC-build.xml b/verigraph/gRPC-build.xml
index 7ff5549..50483c8 100644
--- a/verigraph/gRPC-build.xml
+++ b/verigraph/gRPC-build.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017 Politecnico di Torino and others.
-
All rights reserved. This program and the accompanying materials
are made available under the terms of the Apache License, Version 2.0
which accompanies this distribution, and is available at
@@ -31,6 +30,8 @@
<property name="test2.class" value="it.polito.verigraph.grpc.test.GrpcTest" />
<property name="test3.class" value="it.polito.verigraph.grpc.test.MultiThreadTest" />
<property name="test4.class" value="it.polito.verigraph.grpc.test.ReachabilityTest" />
+ <!-- Tosca grpc test class -->
+ <property name="testToscaGrpc.class" value="it.polito.verigraph.grpc.tosca.test.GrpcToscaTest" />
<!-- The name to be given to the final zip -->
<property name="sol.zip" value="grpc.zip" />
<!-- Java compiler settings -->
@@ -43,7 +44,7 @@
<path id="test.classpath">
<pathelement path="${build.dir}" />
<fileset dir="${grpc.location}/lib">
- <include name="com.microsoft.z3.jar" />
+ <include name="com.microsoft.z3.jar" />
</fileset>
<fileset refid="mvn-dependencies" />
</path>
@@ -65,7 +66,7 @@
</artifact:dependencies>-->
<path id="build.classpath">
- <fileset refid="mvn-dependencies" />
+ <fileset refid="mvn-dependencies" />
</path>
<!-- target name="init">
@@ -77,7 +78,7 @@
<!--target name="gRPC-build" depends="init" description="Build the sources"-->
<target name="gRPC-build" description="Build the sources">
<echo>Building gRPC (if needed)...</echo>
- <javac
+ <javac
debug="${debug}"
debuglevel="${debuglevel}"
source="${source}"
@@ -85,18 +86,18 @@
destdir="${build.dir}"
classpathref="build.classpath"
includeantruntime="false">
- <src path="${generated.dir}" />
- <src path="${src.dir}" />
- <src path="${grpc.location}/gen-src"/>
- <compilerarg value="-Xlint:unchecked"/>
- <classpath>
- <pathelement path="${grpc.location}/lib/com.microsoft.z3.jar"/>
- </classpath>
- <include name="$it/polito/**/**/*.java"/>
- <!-- classpath>
+ <src path="${generated.dir}" />
+ <src path="${src.dir}" />
+ <src path="${grpc.location}/gen-src"/>
+ <compilerarg value="-Xlint:unchecked"/>
+ <classpath>
+ <pathelement path="${grpc.location}/lib/com.microsoft.z3.jar"/>
+ </classpath>
+ <include name="$it/polito/**/**/*.java"/>
+ <!-- classpath>
<pathelement path="${other_lib.dir}/qjutils.jar"/>
</classpath-->
- </javac>
+ </javac>
<echo>Done.</echo>
</target>
@@ -104,20 +105,21 @@
<!-- The target for running the gRPC application -->
<target name="gRPC-run" depends="gRPC-build" description="Run gRPC">
<parallel>
- <sequential>
- <java classname="it.polito.verigraph.grpc.Service" failonerror="true" classpathref="build.classpath" fork="yes">
- <classpath>
- <pathelement path="${build.dir}"/>
- </classpath>
- </java>
- </sequential>
- <sequential>
- <sleep milliseconds="500"/>
- <java classname="it.polito.verigraph.grpc.Client" failonerror="true" classpathref="build.classpath" fork="yes">
- <classpath>
- <pathelement path="${build.dir}"/>
- </classpath>
- </java>
+ <sequential>
+ <java classname="it.polito.verigraph.grpc.Service" failonerror="true" classpathref="build.classpath" fork="yes">
+ <classpath>
+ <pathelement path="${build.dir}"/>
+ <path refid="test.classpath" />
+ </classpath>
+ </java>
+ </sequential>
+ <sequential>
+ <sleep milliseconds="500"/>
+ <java classname="it.polito.verigraph.grpc.Client" failonerror="true" classpathref="build.classpath" fork="yes">
+ <classpath>
+ <pathelement path="${build.dir}"/>
+ </classpath>
+ </java>
</sequential>
</parallel>
</target>
@@ -136,6 +138,7 @@
<java classname="it.polito.verigraph.grpc.server.Service" failonerror="true" classpathref="build.classpath" fork="yes">
<classpath>
<pathelement path="${build.dir}"/>
+ <path refid="test.classpath" />
</classpath>
</java>
</target>
@@ -151,6 +154,19 @@
</antcall>
</target>
+ <!-- Run Tosca Grpc Tests -->
+ <target name="gRPC-tosca-run-tests" description="Run tests for Tosca implementation of gRPC">
+ <echo>Running grpc tests...</echo>
+ <junit printsummary="yes" dir="." fork="yes" haltonfailure="no" showoutput="yes" filtertrace="true" timeout="120000">
+ <jvmarg value="-Djava.awt.headless=true" />
+ <formatter type="brief" usefile="false" />
+ <test haltonfailure="no" failureproperty="test_failed" name="${testToscaGrpc.class}" />
+ <classpath>
+ <path refid="test.classpath" />
+ </classpath>
+ </junit>
+ <fail if="test_failed" message="*** JUnit tests for gRPC Tosca completed: some Tests FAILED ***" />
+ </target>
<!-- Target runFuncTest.real -->
<target name="runFuncTest.real" depends="gRPC-build">
@@ -213,4 +229,4 @@
<!-- target name="clean">
<delete dir="${build.dir}" />
</target-->
-</project> \ No newline at end of file
+</project>
diff --git a/verigraph/pom.xml b/verigraph/pom.xml
index cfa21e9..9684667 100755
--- a/verigraph/pom.xml
+++ b/verigraph/pom.xml
@@ -37,8 +37,8 @@
<version>3.0</version>
<inherited>true</inherited>
<configuration>
- <source>1.7</source>
- <target>1.7</target>
+ <source>1.8</source>
+ <target>1.8</target>
</configuration>
</plugin>
<plugin>
@@ -218,6 +218,16 @@
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-yaml</artifactId>
+ <version>2.9.2</version>
+ </dependency>
+ <!-- Trying to make jaxb work -->
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>org.eclipse.persistence.core</artifactId>
+ <version>2.6.0</version>
+ </dependency>
</dependencies>
-
</project> \ No newline at end of file
diff --git a/verigraph/schema/README.rst b/verigraph/schema/README.rst
new file mode 100644
index 0000000..c3e7a22
--- /dev/null
+++ b/verigraph/schema/README.rst
@@ -0,0 +1,4 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+The XML Schema files in this folder are used by VeriGraph to
+automatically generate Java XML Bindings (JAXB)
diff --git a/verigraph/schema/tosca/TOSCA-v1.0.xsd b/verigraph/schema/tosca/TOSCA-v1.0.xsd
new file mode 100644
index 0000000..ebfcaa6
--- /dev/null
+++ b/verigraph/schema/tosca/TOSCA-v1.0.xsd
@@ -0,0 +1,790 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Topology and Orchestration Specification for Cloud Applications Version 1.0
+ OASIS Standard
+ 25 November 2013
+ Copyright (c) OASIS Open 2013. All rights reserved.
+ Source: http://docs.oasis-open.org/tosca/TOSCA/v1.0/os/schemas/
+-->
+<xs:schema targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns="http://docs.oasis-open.org/tosca/ns/2011/12" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <xs:element name="documentation" type="tDocumentation"/>
+ <xs:complexType name="tDocumentation" mixed="true">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="source" type="xs:anyURI"/>
+ <xs:attribute ref="xml:lang"/>
+ </xs:complexType>
+ <xs:complexType name="tExtensibleElements">
+ <xs:sequence>
+ <xs:element ref="documentation" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:complexType name="tImport">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="namespace" type="xs:anyURI"/>
+ <xs:attribute name="location" type="xs:anyURI"/>
+ <xs:attribute name="importType" type="importedURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="Definitions">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="tDefinitions"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="tDefinitions">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Extensions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Extension" type="tExtension" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Import" type="tImport" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Types" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="ServiceTemplate" type="tServiceTemplate"/>
+ <xs:element name="NodeType" type="tNodeType"/>
+ <xs:element name="NodeTypeImplementation" type="tNodeTypeImplementation"/>
+ <xs:element name="RelationshipType" type="tRelationshipType"/>
+ <xs:element name="RelationshipTypeImplementation" type="tRelationshipTypeImplementation"/>
+ <xs:element name="RequirementType" type="tRequirementType"/>
+ <xs:element name="CapabilityType" type="tCapabilityType"/>
+ <xs:element name="ArtifactType" type="tArtifactType"/>
+ <xs:element name="ArtifactTemplate" type="tArtifactTemplate"/>
+ <xs:element name="PolicyType" type="tPolicyType"/>
+ <xs:element name="PolicyTemplate" type="tPolicyTemplate"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tServiceTemplate">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="BoundaryDefinitions" type="tBoundaryDefinitions" minOccurs="0"/>
+ <xs:element name="TopologyTemplate" type="tTopologyTemplate"/>
+ <xs:element name="Plans" type="tPlans" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI"/>
+ <xs:attribute name="substitutableNodeType" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tTags">
+ <xs:sequence>
+ <xs:element name="Tag" type="tTag" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tTag">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tBoundaryDefinitions">
+ <xs:sequence>
+ <xs:element name="Properties" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other"/>
+ <xs:element name="PropertyMappings" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyMapping" type="tPropertyMapping" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PropertyConstraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyConstraint" type="tPropertyConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Requirements" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Requirement" type="tRequirementRef" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Capabilities" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Capability" type="tCapabilityRef" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Policies" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Policy" type="tPolicy" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Interfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tExportedInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPropertyMapping">
+ <xs:attribute name="serviceTemplatePropertyRef" type="xs:string" use="required"/>
+ <xs:attribute name="targetObjectRef" type="xs:IDREF" use="required"/>
+ <xs:attribute name="targetPropertyRef" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tRequirementRef">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityRef">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tEntityType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="DerivedFrom" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PropertiesDefinition" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="element" type="xs:QName"/>
+ <xs:attribute name="type" type="xs:QName"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="abstract" type="tBoolean" default="no"/>
+ <xs:attribute name="final" type="tBoolean" default="no"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tEntityTemplate" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Properties" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PropertyConstraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyConstraint" type="tPropertyConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="type" type="xs:QName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:sequence>
+ <xs:element name="Requirements" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Requirement" type="tRequirement" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Capabilities" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Capability" type="tCapability" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Policies" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Policy" type="tPolicy" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="DeploymentArtifacts" type="tDeploymentArtifacts" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="minInstances" type="xs:int" use="optional" default="1"/>
+ <xs:attribute name="maxInstances" use="optional" default="1">
+ <xs:simpleType>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:pattern value="([1-9]+[0-9]*)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tTopologyTemplate">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="NodeTemplate" type="tNodeTemplate"/>
+ <xs:element name="RelationshipTemplate" type="tRelationshipTemplate"/>
+ </xs:choice>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:sequence>
+ <xs:element name="InstanceStates" type="tTopologyElementInstanceStates" minOccurs="0"/>
+ <xs:element name="SourceInterfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TargetInterfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidSource" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidTarget" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipTypeImplementation">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="DerivedFrom" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="relationshipTypeImplementationRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RequiredContainerFeatures" type="tRequiredContainerFeatures" minOccurs="0"/>
+ <xs:element name="ImplementationArtifacts" type="tImplementationArtifacts" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ <xs:attribute name="relationshipType" type="xs:QName" use="required"/>
+ <xs:attribute name="abstract" type="tBoolean" use="optional" default="no"/>
+ <xs:attribute name="final" type="tBoolean" use="optional" default="no"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:sequence>
+ <xs:element name="SourceElement">
+ <xs:complexType>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TargetElement">
+ <xs:complexType>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RelationshipConstraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="RelationshipConstraint" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="constraintType" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:sequence>
+ <xs:element name="RequirementDefinitions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="RequirementDefinition" type="tRequirementDefinition" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="CapabilityDefinitions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="CapabilityDefinition" type="tCapabilityDefinition" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="InstanceStates" type="tTopologyElementInstanceStates" minOccurs="0"/>
+ <xs:element name="Interfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeTypeImplementation">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="DerivedFrom" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="nodeTypeImplementationRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RequiredContainerFeatures" type="tRequiredContainerFeatures" minOccurs="0"/>
+ <xs:element name="ImplementationArtifacts" type="tImplementationArtifacts" minOccurs="0"/>
+ <xs:element name="DeploymentArtifacts" type="tDeploymentArtifacts" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ <xs:attribute name="nodeType" type="xs:QName" use="required"/>
+ <xs:attribute name="abstract" type="tBoolean" use="optional" default="no"/>
+ <xs:attribute name="final" type="tBoolean" use="optional" default="no"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirementType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:attribute name="requiredCapabilityType" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirementDefinition">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Constraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Constraint" type="tConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="requirementType" type="xs:QName" use="required"/>
+ <xs:attribute name="lowerBound" type="xs:int" use="optional" default="1"/>
+ <xs:attribute name="upperBound" use="optional" default="1">
+ <xs:simpleType>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:pattern value="([1-9]+[0-9]*)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirement">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType"/>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityDefinition">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Constraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Constraint" type="tConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="capabilityType" type="xs:QName" use="required"/>
+ <xs:attribute name="lowerBound" type="xs:int" use="optional" default="1"/>
+ <xs:attribute name="upperBound" use="optional" default="1">
+ <xs:simpleType>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:pattern value="([1-9]+[0-9]*)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapability">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tArtifactType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType"/>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tArtifactTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:sequence>
+ <xs:element name="ArtifactReferences" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ArtifactReference" type="tArtifactReference" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tDeploymentArtifacts">
+ <xs:sequence>
+ <xs:element name="DeploymentArtifact" type="tDeploymentArtifact" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tDeploymentArtifact">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="artifactType" type="xs:QName" use="required"/>
+ <xs:attribute name="artifactRef" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tImplementationArtifacts">
+ <xs:sequence>
+ <xs:element name="ImplementationArtifact" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="tImplementationArtifact"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tImplementationArtifact">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="interfaceName" type="xs:anyURI" use="optional"/>
+ <xs:attribute name="operationName" type="xs:NCName" use="optional"/>
+ <xs:attribute name="artifactType" type="xs:QName" use="required"/>
+ <xs:attribute name="artifactRef" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPlans">
+ <xs:sequence>
+ <xs:element name="Plan" type="tPlan" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="tPlan">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Precondition" type="tCondition" minOccurs="0"/>
+ <xs:element name="InputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="InputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="OutputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="OutputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:choice>
+ <xs:element name="PlanModel">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PlanModelReference">
+ <xs:complexType>
+ <xs:attribute name="reference" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="planType" type="xs:anyURI" use="required"/>
+ <xs:attribute name="planLanguage" type="xs:anyURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPolicyType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:sequence>
+ <xs:element name="AppliesTo" type="tAppliesTo" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="policyLanguage" type="xs:anyURI" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPolicyTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tAppliesTo">
+ <xs:sequence>
+ <xs:element name="NodeTypeReference" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPolicy">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="policyType" type="xs:QName" use="required"/>
+ <xs:attribute name="policyRef" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tConstraint">
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="constraintType" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tPropertyConstraint">
+ <xs:complexContent>
+ <xs:extension base="tConstraint">
+ <xs:attribute name="property" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExtensions">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Extension" type="tExtension" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExtension">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="namespace" type="xs:anyURI" use="required"/>
+ <xs:attribute name="mustUnderstand" type="tBoolean" use="optional" default="yes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tParameter">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="required" type="tBoolean" use="optional" default="yes"/>
+ </xs:complexType>
+ <xs:complexType name="tInterface">
+ <xs:sequence>
+ <xs:element name="Operation" type="tOperation" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tExportedInterface">
+ <xs:sequence>
+ <xs:element name="Operation" type="tExportedOperation" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tOperation">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="InputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="InputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="OutputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="OutputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExportedOperation">
+ <xs:choice>
+ <xs:element name="NodeOperation">
+ <xs:complexType>
+ <xs:attribute name="nodeRef" type="xs:IDREF" use="required"/>
+ <xs:attribute name="interfaceName" type="xs:anyURI" use="required"/>
+ <xs:attribute name="operationName" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RelationshipOperation">
+ <xs:complexType>
+ <xs:attribute name="relationshipRef" type="xs:IDREF" use="required"/>
+ <xs:attribute name="interfaceName" type="xs:anyURI" use="required"/>
+ <xs:attribute name="operationName" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Plan">
+ <xs:complexType>
+ <xs:attribute name="planRef" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tCondition">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="expressionLanguage" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tTopologyElementInstanceStates">
+ <xs:sequence>
+ <xs:element name="InstanceState" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="state" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tArtifactReference">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Include">
+ <xs:complexType>
+ <xs:attribute name="pattern" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Exclude">
+ <xs:complexType>
+ <xs:attribute name="pattern" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="reference" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tRequiredContainerFeatures">
+ <xs:sequence>
+ <xs:element name="RequiredContainerFeature" type="tRequiredContainerFeature" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tRequiredContainerFeature">
+ <xs:attribute name="feature" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:simpleType name="tBoolean">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="importedURI">
+ <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+</xs:schema>
diff --git a/verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd b/verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd
new file mode 100644
index 0000000..98751b4
--- /dev/null
+++ b/verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2018 Politecnico di Torino and others.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Apache License, Version 2.0
+ which accompanies this distribution, and is available at
+ http://www.apache.org/licenses/LICENSE-2.0
+-->
+
+
+<xsd:schema xmlns="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition">
+
+ <!-- Generic Configuration type, contains a single configuration element -->
+ <xsd:element name="Configuration">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element name="antispamConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="source" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="cacheConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="resource" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="dpiConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="notAllowed" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="endhostConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="body" type="xsd:string" />
+ <xsd:attribute name="sequence" type="xsd:integer" />
+ <xsd:attribute name="protocol">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="HTTP_REQUEST" />
+ <xsd:enumeration value="HTTP_RESPONSE" />
+ <xsd:enumeration value="POP3_REQUEST" />
+ <xsd:enumeration value="POP3_RESPONSE" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="email_from" type="xsd:string" />
+ <xsd:attribute name="url" type="xsd:string" />
+ <xsd:attribute name="options" type="xsd:string" />
+ <xsd:attribute name="destination" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="endpointConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="fieldmodifierConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="firewallConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="elements" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="source" type="xsd:string" />
+ <xsd:element name="destination" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mailclientConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="mailserver" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mailserverConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="natConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="source" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="vpnaccessConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="vpnexit" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="vpnexitConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="vpnaccess" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="webclientConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="nameWebServer" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="webserverConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ <xsd:attribute name="confID" type="xsd:string" />
+ <xsd:attribute name="confDescr" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- <xsd:element name="firewallConfiguration">
+ <xsd:complexType >
+ <xsd:sequence>
+ <xsd:element ref="elements" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="elements">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="source" type="xsd:string" />
+ <xsd:element name="destination" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="endhostConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="body" type="xsd:string" />
+ <xsd:attribute name="sequence" type="xsd:integer" />
+ <xsd:attribute name="protocol" type="protocolTypes" />
+ <xsd:attribute name="email_from" type="xsd:string" />
+ <xsd:attribute name="url" type="xsd:string" />
+ <xsd:attribute name="options" type="xsd:string" />
+ <xsd:attribute name="destination" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="endpointConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"
+ nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="antispamConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="source" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="cacheConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="resource" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="dpiConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="notAllowed" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mailclientConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="mailserver" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mailserverConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"
+ nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="natConfiguration">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <xsd:element name="source" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="vpnaccessConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="vpnexit" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="vpnexitConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="vpnaccess" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="webclientConfiguration">
+ <xsd:complexType>
+ <xsd:attribute name="nameWebServer" type="xsd:string"
+ use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="webserverConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"
+ nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="fieldmodifierConfiguration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"
+ nillable="true" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:simpleType name="functionalTypes">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="FIREWALL" />
+ <xsd:enumeration value="ENDHOST" />
+ <xsd:enumeration value="ENDPOINT" />
+ <xsd:enumeration value="ANTISPAM" />
+ <xsd:enumeration value="CACHE" />
+ <xsd:enumeration value="DPI" />
+ <xsd:enumeration value="MAILCLIENT" />
+ <xsd:enumeration value="MAILSERVER" />
+ <xsd:enumeration value="NAT" />
+ <xsd:enumeration value="VPNACCESS" />
+ <xsd:enumeration value="VPNEXIT" />
+ <xsd:enumeration value="WEBCLIENT" />
+ <xsd:enumeration value="WEBSERVER" />
+ <xsd:enumeration value="FIELDMODIFIER" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="protocolTypes">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="HTTP_REQUEST" />
+ <xsd:enumeration value="HTTP_RESPONSE" />
+ <xsd:enumeration value="POP3_REQUEST" />
+ <xsd:enumeration value="POP3_RESPONSE" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ -->
+
+</xsd:schema> \ No newline at end of file
diff --git a/verigraph/schema/tosca/ToscaVerigraphDefinitions.xml b/verigraph/schema/tosca/ToscaVerigraphDefinitions.xml
new file mode 100644
index 0000000..4f49037
--- /dev/null
+++ b/verigraph/schema/tosca/ToscaVerigraphDefinitions.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2018 Politecnico di Torino and others.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Apache License, Version 2.0
+ which accompanies this distribution, and is available at
+ http://www.apache.org/licenses/LICENSE-2.0
+-->
+
+<Definitions id="Verigraph_Definitions" name="Verigraph Type Definition"
+ xmlns="http://docs.oasis-open.org/tosca/ns/2011/12"
+ targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition">
+
+ <import importType="http://www.w3.org/2001/XMLSchema"
+ namespace="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition"
+ location="./ToscaTypes_XMLconfig.xsd" />
+
+ <NodeType name="AntispamType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="CacheType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="DpiType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="EndhostType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="EndpointType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="FieldModifierType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="FirewallType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="MailclientType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="MailserverType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="NatType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="VpnAccessType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="VpnExitType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="WebclientType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <NodeType name="WebserverType">
+ <PropertiesDefinition element="Configuration" />
+ </NodeType>
+
+ <RelationshipType name="linkedTo" />
+
+</Definitions> \ No newline at end of file
diff --git a/verigraph/schema/tosca/yamlToscaDefinitions.yaml b/verigraph/schema/tosca/yamlToscaDefinitions.yaml
new file mode 100644
index 0000000..e72a5da
--- /dev/null
+++ b/verigraph/schema/tosca/yamlToscaDefinitions.yaml
@@ -0,0 +1,157 @@
+##############################################################################
+# Copyright (c) 2018 Politecnico di Torino and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+#Tosca definitions for Verigraph extension in Tosca Yaml simple profile
+
+tosca_definitions_version: http://docs.oasis-open.org/tosca/ns/simple/yaml/1.0
+
+description: node type definitions exetending tosca types for support to Verigraph verification system
+
+node_types:
+ verigraph.types.Antispam:
+ derived_from: tosca.nodes.Root
+ description: verigraph Antispam node
+ properties:
+ sources:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.Cache:
+ derived_from: tosca.nodes.Root
+ description: verigraph Cache node
+ properties:
+ resources:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.Dpi:
+ derived_from: tosca.nodes.Root
+ description: verigraph Dpi node
+ properties:
+ notAllowedList:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.Endhost:
+ derived_from: tosca.nodes.Root
+ description: verigraph endhost node
+ attributes:
+ body:
+ type: string
+ sequence:
+ type: integer
+ protocol:
+ type: string
+ constraints:
+ - valid_values: [ HTTP_REQUEST, HTTP_RESPONSE, POP3_REQUEST, POP3_RESOPONSE ]
+ email_from:
+ type: string
+ url:
+ type: string
+ options:
+ type: string
+ destination:
+ type: string
+
+ verigraph.types.Endpoint:
+ derived_from: tosca.nodes.Root
+ description: verigraph Endpoint node
+ properties:
+ names:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.FieldModifier:
+ derived_from: tosca.nodes.Root
+ description: verigraph Field Modifier node
+ properties:
+ names:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.Firewall:
+ derived_from: tosca.nodes.Root
+ description: verigraph Firewall node
+ properties:
+ elements:
+ type: map
+ entry_schema:
+ description: "source : destination" firewall mapping
+ type: string
+
+ verigraph.types.MailClient:
+ derived_from: tosca.nodes.Root
+ description: verigraph Mail Client node
+ attributes:
+ mailserver:
+ type: string
+
+ verigraph.types.MailServer:
+ derived_from: tosca.nodes.Root
+ descrtiption: verigraph Mail Server node
+ properties:
+ names:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.Nat:
+ derived_from: tosca.nodes.Root
+ descrtiption: verigraph Nat node
+ properties:
+ sources:
+ type: list
+ entry_schema:
+ type: string
+
+ verigraph.types.VpnAccess:
+ deriver_from: tosca.nodes.Root
+ descrtiption: verigraph Vpn Access node
+ attributes:
+ vpnexit:
+ type: string
+
+ verigraph.types.VpnExit:
+ derived_from: tosca.nodes.Root
+ descrtiption: verigraph Vpn Exit node
+ attributes:
+ vpnaccess:
+ type: string
+
+ verigraph.types.WebClient:
+ derived_from: tosca.nodes.Root
+ descrtiption: verigraph web Client node
+ attributes:
+ nameWebServer:
+ type: string
+
+ verigraph.types.WebServer:
+ derived_from: tosca.nodes.Root
+ descrtiption: verigraph web Server node
+ properties:
+ names:
+ type: list
+ entry_schema:
+ type: string
+
+relationship_types:
+ verigraph.relationshipType.generic:
+ derived_from: tosca.relationships.Root
+ properties:
+ name:
+ type: string
+ source_id:
+ type: string
+ target_id:
+ type: string
diff --git a/verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java b/verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java
new file mode 100644
index 0000000..dbf8442
--- /dev/null
+++ b/verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Politecnico di Torino and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Apache License, Version 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *******************************************************************************/
+package it.polito.verigraph.grpc.client;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.StatusRuntimeException;
+import it.polito.verigraph.grpc.GetRequest;
+import it.polito.verigraph.grpc.GraphGrpc;
+import it.polito.verigraph.grpc.NewGraph;
+import it.polito.verigraph.grpc.NewTopologyTemplate;
+import it.polito.verigraph.grpc.NodeTemplateGrpc;
+import it.polito.verigraph.grpc.RequestID;
+import it.polito.verigraph.grpc.Status;
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;
+import it.polito.verigraph.grpc.ToscaPolicy;
+import it.polito.verigraph.grpc.ToscaRequestID;
+import it.polito.verigraph.grpc.ToscaTestGrpc;
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;
+import it.polito.verigraph.grpc.VerigraphGrpc;
+
+public class ToscaClient {
+
+ private final ManagedChannel channel;
+ private final VerigraphGrpc.VerigraphBlockingStub blockingStub;
+
+ public ToscaClient(String host, int port) {
+ this(ManagedChannelBuilder.forAddress(host, port).usePlaintext(true));
+ }
+
+ /** Construct client for accessing toscaVerigraph server using the existing channel. */
+ public ToscaClient(ManagedChannelBuilder<?> channelBuilder) {
+ channel = channelBuilder.build();
+ blockingStub = VerigraphGrpc.newBlockingStub(channel);
+ }
+
+ /** Close the channel */
+ public void shutdown() throws InterruptedException {
+ channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
+ }
+
+ /** Obtain a list of the available TopologyTemplates*/
+ public List<TopologyTemplateGrpc> getTopologyTemplates(){
+ List<TopologyTemplateGrpc> templates = new ArrayList<TopologyTemplateGrpc>();
+ GetRequest request = GetRequest.newBuilder().build();
+ boolean response_ok = true;
+
+ /*Iterates on received topology templates, prints on log file in case of errors*/
+ Iterator<TopologyTemplateGrpc> receivedTemplates;
+ try {
+ receivedTemplates = blockingStub.getTopologyTemplates(request);
+ System.out.println("++ Receiving TopologyTemplates...");
+ while(receivedTemplates.hasNext()) {
+ TopologyTemplateGrpc received = receivedTemplates.next();
+ if(received.getErrorMessage().equals("")) {
+ System.out.println("++ Correctly received TopologyTemplate --> id:" + received.getId());
+ templates.add(received);
+ } else
+ System.out.println("-- Received a TopologyTemplate with error: " + received.getErrorMessage());
+ }
+ } catch (StatusRuntimeException ex) {
+ System.out.println("-- RPC failed: " + ex.getMessage());
+ response_ok = false;
+ }
+ if(response_ok) {
+ System.out.println("++ All TopologyTemplates correctly received.");
+ return templates;
+ } else {
+ return null; //Function returns null in case of error to differentiate from empty list case.
+ }
+ }
+
+
+ /** Obtain a TopologyTemplate by ID */
+ public TopologyTemplateGrpc getTopologyTemplate(String id) {
+ ToscaRequestID request = ToscaRequestID.newBuilder().setIdTopologyTemplate(id).build();
+ TopologyTemplateGrpc response = TopologyTemplateGrpc.newBuilder().build();
+ try {
+ System.out.println("++ Receiving TopologyTemplate...");
+ response = blockingStub.getTopologyTemplate(request);
+ if(response.getErrorMessage().equals("")){
+ System.out.println("++ Received TopologyTemplate --> id:" + response.getId());
+ return response;
+ } else {
+ System.out.println("-- Error: " + response.getErrorMessage());
+ return response;
+ }
+ } catch (StatusRuntimeException ex) {
+ System.out.println("-- RPC failed: " + ex.getStatus());
+ return TopologyTemplateGrpc.newBuilder().setErrorMessage(ex.getStatus().getDescription()).build();
+ }
+ }
+
+
+ /** Creates a new TopologyTemplate, takes in input a TopologyTemplateGrpc */
+ public NewTopologyTemplate createTopologyTemplate(TopologyTemplateGrpc topol) {
+ try {
+ //Sending new Topology and analyzing response
+ System.out.println("++ Sending the new TopologyTemplate...");
+ NewTopologyTemplate response = blockingStub.createTopologyTemplate(topol);
+ if(response.getSuccess())
+ System.out.println("++ TopologyTemplate successfully created with id: "+ response.getTopologyTemplate().getId());
+ else
+ System.out.println("-- TopologyTemplate creation failed: " + response.getErrorMessage());
+ return response;
+
+ } catch (StatusRuntimeException ex) {
+ System.out.println("-- RPC failed: " + ex.getStatus());
+ return NewTopologyTemplate.newBuilder().setSuccess(false).setErrorMessage(ex.getStatus().getDescription()).build();
+ //getDescription may be empty
+ }
+ }
+
+
+ /** Update a TopologyTemplate, takes in input a TopologyTemplateGrpc and the Topology's ID to be updated*/
+ public NewTopologyTemplate updateTopologyTemplate(TopologyTemplateGrpc topol, String id) {
+ //Checking if the inserted string is an object
+ try {
+ Long.valueOf(id);
+ } catch (NumberFormatException ex) {
+ System.out.println("-- The ID must a number according to Verigraph implementation.");
+ return NewTopologyTemplate.newBuilder().setSuccess(false)
+ .setErrorMessage("The ID must a number according to Verigraph implementation.").build();
+ }
+
+ //Update the topology ID
+ TopologyTemplateGrpc.Builder updTopol = TopologyTemplateGrpc.newBuilder();
+ try {
+ updTopol.setId(id)
+ .addAllNodeTemplate(topol.getNodeTemplateList())
+ .addAllRelationshipTemplate(topol.getRelationshipTemplateList());
+ } catch (Exception ex) {
+ System.out.println("-- Error: Incorrect fields implementation.");
+ return NewTopologyTemplate.newBuilder().setSuccess(false).setErrorMessage("Error: Incorrect fields implementation.").build();
+ }
+
+ //Sending updated Topology and analyzing response
+ try {
+
+ System.out.println("++ Sending the updated TopologyTemplate...");
+ NewTopologyTemplate response = blockingStub.updateTopologyTemplate(updTopol.build());
+ if(response.getSuccess())
+ System.out.println("++ TopologyTemplate successfully updated.");
+ else
+ System.out.println("-- TopologyTemplate not updated: " + response.getErrorMessage());
+ return response;
+
+ } catch (StatusRuntimeException ex) {
+ System.out.println("-- RPC failed: " + ex.getStatus());
+ return NewTopologyTemplate.newBuilder().setSuccess(false).setErrorMessage(ex.getStatus().getDescription()).build();
+ }
+ }
+
+
+ /** Delete a TopologyTemplate by ID */
+ public Status deleteTopologyTemplate(String id) {
+ try {
+ Long.valueOf(id);
+ } catch (NumberFormatException ex) {
+ System.out.println("-- The ID must a number according to Verigraph implementation.");
+ return Status.newBuilder().setSuccess(false)
+ .setErrorMessage("The ID must a number according to Verigraph implementation.").build();
+ }
+ ToscaRequestID request = ToscaRequestID.newBuilder().setIdTopologyTemplate(id).build();
+ try {
+ System.out.println("++ Sending delete request...");
+ Status response = blockingStub.deleteTopologyTemplate(request);
+ if(response.getSuccess())
+ System.out.println("++ TopologyTemplate successfully deleted.");
+ else
+ System.out.println("-- Error deleting TopologyTemplate : " + response.getErrorMessage());
+ return response;
+
+ } catch (StatusRuntimeException ex) {
+ System.out.println("-- RPC failed: " + ex.getStatus());
+ return Status.newBuilder().setSuccess(false).setErrorMessage(ex.getStatus().getDescription()).build();
+ }
+ }
+
+
+ /** VerifyPolicy */
+ public ToscaVerificationGrpc verifyPolicy(ToscaPolicy policy){
+ ToscaVerificationGrpc response;
+ try {
+ System.out.println("++ Sending ToscaPolicy...");
+ response = blockingStub.verifyToscaPolicy(policy);
+ if(!response.getErrorMessage().equals("")){
+ System.out.println("-- Error in operation: " + response.getErrorMessage());
+ }
+ else {
+ System.out.println("++ Result: " + response.getResult());
+ System.out.println("++ Comment: " + response.getComment());
+
+ for(ToscaTestGrpc test : response.getTestList()){
+ System.out.println("++ Traversed nodes:");
+ for(NodeTemplateGrpc node : test.getNodeTemplateList()){
+ System.out.println("\t Node "+node.getName());
+ }
+ }
+ }
+ return response;
+ } catch (StatusRuntimeException e) {
+ System.out.println("-- RPC failed: " + e.getStatus());
+ return ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+ .setErrorMessage(e.getStackTrace().toString()).build();
+ }
+ }
+
+
+ //Methods added for backward compatibility with JSON grpc, only create and update methods need to be redefined
+ //The reason is that the tosca Grpc converter requires a coherent numbering of IDs while the previous
+ //implementations exploits names to identify nodes and can considers IDs as not strictly required attributes.
+
+ public NewGraph createGraph(GraphGrpc gr) {
+ NewGraph response;
+ try {
+ response = blockingStub.createGraph(gr);
+ if(response.getSuccess())
+ System.out.println("++ TopologyTemplate successfully created with id: "+ response.getGraph().getId());
+ else
+ System.out.println("-- TopologyTemplate creation failed: " + response.getErrorMessage());
+ return response;
+ } catch (StatusRuntimeException e) {
+ System.err.println("-- RPC failed: " + e.getStatus());
+ return NewGraph.newBuilder().setSuccess(false).setErrorMessage(e.getStatus().getDescription()).build();
+ }
+
+ }
+
+ public NewGraph updateGraph(long idGraph, GraphGrpc newGraph) {
+
+ GraphGrpc gr = GraphGrpc.newBuilder(newGraph).setId(idGraph).build();
+ NewGraph response;
+ try {
+ response = blockingStub.updateGraph(gr);
+ if(response.getSuccess())
+ System.out.println("++ TopologyTemplate successfully created with id: "+ response.getGraph().getId());
+ else
+ System.out.println("-- TopologyTemplate creation failed: " + response.getErrorMessage());
+ return response;
+ } catch (StatusRuntimeException e) {
+ System.err.println("-- RPC failed: " + e.getStatus());
+ return NewGraph.newBuilder().setSuccess(false).setErrorMessage(e.getStatus().getDescription()).build();
+ }
+ }
+
+ public GraphGrpc getGraph(long idGraph) {
+
+ RequestID request = RequestID.newBuilder().setIdGraph(idGraph).build() ;
+ try {
+ System.out.println("++ Receiving TopologyTemplate...");
+ GraphGrpc graph = blockingStub.getGraph(request);
+ System.out.println("++ Received TopologyTemplate --> id:" + graph.getId());
+ if(!graph.getErrorMessage().equals("")){
+ System.out.println("-- Error : " + graph.getErrorMessage());
+ return graph;
+ }
+ return graph;
+ } catch (StatusRuntimeException ex) {
+ System.err.println("-- RPC failed: " + ex.getStatus());
+ return null;
+ }
+ }
+
+
+ public List<GraphGrpc> getGraphs() {
+ List<GraphGrpc> graphsReceived = new ArrayList<GraphGrpc>();
+ GetRequest request = GetRequest.newBuilder().build();
+ Iterator<GraphGrpc> graphs;
+ try {
+ graphs = blockingStub.getGraphs(request);
+ System.out.println("++ Receiving TopologyTemplates...");
+ while (graphs.hasNext()) {
+ GraphGrpc graph = graphs.next();
+ if(graph.getErrorMessage().equals("")){
+ System.out.println("++ Correctly received graph --> id:" + graph.getId());
+ graphsReceived.add(graph);
+ }else{
+ System.out.println("-- Received a graph with error : " + graph.getErrorMessage());
+ }
+ }
+ } catch (StatusRuntimeException ex) {
+ System.err.println("-- RPC failed : " + ex.getStatus());
+ return null;
+ }
+ return graphsReceived;
+ }
+}
diff --git a/verigraph/src/it/polito/verigraph/grpc/server/GrpcUtils.java b/verigraph/src/it/polito/verigraph/grpc/server/GrpcUtils.java
index 43859db..96c52a5 100644
--- a/verigraph/src/it/polito/verigraph/grpc/server/GrpcUtils.java
+++ b/verigraph/src/it/polito/verigraph/grpc/server/GrpcUtils.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 Politecnico di Torino and others.
+ * Copyright (c) 2017/18 Politecnico di Torino and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License, Version 2.0
@@ -12,16 +12,18 @@ import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Splitter;
+
import it.polito.verigraph.grpc.ConfigurationGrpc;
import it.polito.verigraph.grpc.GraphGrpc;
import it.polito.verigraph.grpc.NeighbourGrpc;
import it.polito.verigraph.grpc.NodeGrpc;
+import it.polito.verigraph.grpc.NodeGrpc.FunctionalType;
import it.polito.verigraph.grpc.TestGrpc;
import it.polito.verigraph.grpc.VerificationGrpc;
-import it.polito.verigraph.grpc.NodeGrpc.FunctionalType;
import it.polito.verigraph.model.Configuration;
import it.polito.verigraph.model.Graph;
import it.polito.verigraph.model.Neighbour;
@@ -29,6 +31,7 @@ import it.polito.verigraph.model.Node;
import it.polito.verigraph.model.Test;
import it.polito.verigraph.model.Verification;
+
public class GrpcUtils {
private static final Logger logger = Logger.getLogger(GrpcUtils.class.getName());
@@ -43,6 +46,7 @@ public class GrpcUtils {
//id is not present
Neighbour ne = new Neighbour();
ne.setName(request.getName());
+ ne.setId(request.getId());
return ne;
}
@@ -86,13 +90,17 @@ public class GrpcUtils {
}
public static Node deriveNode(NodeGrpc request) {
- //id is not present
+ //id is not present
Node node = new Node();
node.setName(request.getName());
node.setFunctional_type(request.getFunctionalType().toString());
Configuration conf = deriveConfiguration(request.getConfiguration());
node.setConfiguration(conf);
+ //Modification for Tosca CLI
+ Long id = request.getId();
+ if( id != null) node.setId(request.getId());
+
Map<Long,Neighbour> neighours = node.getNeighbours();
long i = 1;
for(NeighbourGrpc neighbour:request.getNeighbourList()){
@@ -106,7 +114,7 @@ public class GrpcUtils {
public static GraphGrpc obtainGraph(Graph graph){
GraphGrpc.Builder gr = GraphGrpc.newBuilder();
gr.setId(graph.getId());
- for(Node node:graph.getNodes().values()){
+ for(Node node : graph.getNodes().values()){
NodeGrpc ng = obtainNode(node);
gr.addNode(ng);
}
@@ -116,14 +124,16 @@ public class GrpcUtils {
public static Graph deriveGraph(GraphGrpc request) {
//id is not present
Graph graph = new Graph();
-
+ //Modification for Tosca CLI
+ Long id = request.getId();
+ if( id != null) graph.setId(request.getId());
+
long i=1;
Map<Long, Node> nodes= graph.getNodes();
for(NodeGrpc node:request.getNodeList()){
Node ng = deriveNode(node);
- nodes.put(i++, ng);
+ nodes.put(i++, ng);
}
-
return graph;
}
@@ -142,12 +152,13 @@ public class GrpcUtils {
return ver.build();
}
- /**Intended for string that begins with "?"
- * */
+
+ /** Intended for string that begins with "?" */
public static Map<String,String> getParamGivenString(String str){
String string = str.substring(1);
final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator("=").
split(string);
return map;
}
+
}
diff --git a/verigraph/src/it/polito/verigraph/grpc/server/Service.java b/verigraph/src/it/polito/verigraph/grpc/server/Service.java
index 1839b7e..c6b69b0 100644
--- a/verigraph/src/it/polito/verigraph/grpc/server/Service.java
+++ b/verigraph/src/it/polito/verigraph/grpc/server/Service.java
@@ -15,9 +15,13 @@ import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
+
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
+import it.polito.verigraph.exception.BadRequestException;
+import it.polito.verigraph.exception.DataNotFoundException;
+import it.polito.verigraph.exception.ForbiddenException;
import it.polito.verigraph.grpc.ConfigurationGrpc;
import it.polito.verigraph.grpc.GetRequest;
import it.polito.verigraph.grpc.GraphGrpc;
@@ -25,15 +29,17 @@ import it.polito.verigraph.grpc.NeighbourGrpc;
import it.polito.verigraph.grpc.NewGraph;
import it.polito.verigraph.grpc.NewNeighbour;
import it.polito.verigraph.grpc.NewNode;
+import it.polito.verigraph.grpc.NewTopologyTemplate;
import it.polito.verigraph.grpc.NodeGrpc;
import it.polito.verigraph.grpc.Policy;
import it.polito.verigraph.grpc.RequestID;
import it.polito.verigraph.grpc.Status;
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;
+import it.polito.verigraph.grpc.ToscaPolicy;
+import it.polito.verigraph.grpc.ToscaRequestID;
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;
import it.polito.verigraph.grpc.VerificationGrpc;
import it.polito.verigraph.grpc.VerigraphGrpc;
-import it.polito.verigraph.exception.BadRequestException;
-import it.polito.verigraph.exception.DataNotFoundException;
-import it.polito.verigraph.exception.ForbiddenException;
import it.polito.verigraph.model.Configuration;
import it.polito.verigraph.model.Graph;
import it.polito.verigraph.model.Neighbour;
@@ -44,6 +50,8 @@ import it.polito.verigraph.service.GraphService;
import it.polito.verigraph.service.NeighbourService;
import it.polito.verigraph.service.NodeService;
import it.polito.verigraph.service.VerificationService;
+import it.polito.verigraph.tosca.converter.grpc.GraphToGrpc;
+import it.polito.verigraph.tosca.converter.grpc.GrpcToGraph;
public class Service {
/** Port on which the server should run. */
@@ -107,7 +115,7 @@ public class Service {
}
}
- /**Here start method of my implementation*/
+ /** Here start methods */
private class VerigraphImpl extends VerigraphGrpc.VerigraphImplBase{
/** Here start methods of GraphResource*/
@@ -307,8 +315,7 @@ public class Service {
@Override
public void updateNode(NodeGrpc request, StreamObserver<NewNode> responseObserver) {
- NewNode.Builder response = NewNode.newBuilder();
- try{
+ NewNode.Builder response = NewNode.newBuilder(); try{
Node node = GrpcUtils.deriveNode(request);
node.setId(request.getId());
Node newNode = nodeService.updateNode(request.getIdGraph(), node);
@@ -340,7 +347,8 @@ public class Service {
}
Node node = nodeService.getNode(request.getIdGraph(), request.getIdNode());
if (node == null){
- throw new BadRequestException("Node with id " + request.getIdNode() + " not found in graph with id " + request.getIdGraph());
+ throw new BadRequestException("Node with id " + request.getIdNode() +
+ " not found in graph with id " + request.getIdGraph());
}
Configuration nodeConfiguration = GrpcUtils.deriveConfiguration(request);
Node nodeCopy = new Node();
@@ -386,8 +394,7 @@ public class Service {
NeighbourGrpc nr = NeighbourGrpc.newBuilder().setErrorMessage(internalError).build();
responseObserver.onNext(nr);
logger.log(Level.WARNING, ex.getMessage());
- }
- responseObserver.onCompleted();
+ } responseObserver.onCompleted();
}
@Override
@@ -462,5 +469,149 @@ public class Service {
responseObserver.onNext(response.build());
responseObserver.onCompleted();
}
+
+ /** Here start methods of TOSCA gRPC server */ @Override
+ public void getTopologyTemplates (GetRequest request, StreamObserver<TopologyTemplateGrpc> responseObserver) {
+ boolean not_correct = false;
+ try {
+ for(Graph item : graphService.getAllGraphs()) {
+ TopologyTemplateGrpc topol = GraphToGrpc.obtainTopologyTemplate(item);
+ responseObserver.onNext(topol);
+ }
+ } catch(Exception ex){
+ logger.log(Level.WARNING, ex.getMessage());
+ not_correct = true;
+ }
+ if(not_correct)
+ responseObserver.onNext(TopologyTemplateGrpc.newBuilder()
+ .setErrorMessage("Internal Server Error while retrieving TopologyTemplate").build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getTopologyTemplate (ToscaRequestID request, StreamObserver<TopologyTemplateGrpc> responseObserver) {
+ try {
+ Long graphID = Long.valueOf(request.getIdTopologyTemplate());
+ //this method will throw a NumberFormatException in case the ID is not representable as a long
+ Graph graph = graphService.getGraph(graphID);
+ TopologyTemplateGrpc topol = GraphToGrpc.obtainTopologyTemplate(graph);
+ responseObserver.onNext(topol);
+ } catch(ForbiddenException | DataNotFoundException ex) {
+ TopologyTemplateGrpc topolError = TopologyTemplateGrpc.newBuilder().setErrorMessage(ex.getMessage()).build();
+ responseObserver.onNext(topolError);
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(NumberFormatException ex) {
+ TopologyTemplateGrpc topolError = TopologyTemplateGrpc.newBuilder()
+ .setErrorMessage("The TopologyTemplate ID must be a long value.").build();
+ responseObserver.onNext(topolError);
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(Exception ex) {
+ TopologyTemplateGrpc topolError = TopologyTemplateGrpc.newBuilder().setErrorMessage(internalError).build();
+ responseObserver.onNext(topolError);
+ logger.log(Level.WARNING, ex.getMessage());
+ }
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void createTopologyTemplate (TopologyTemplateGrpc request, StreamObserver<NewTopologyTemplate> responseObserver) {
+ NewTopologyTemplate.Builder response = NewTopologyTemplate.newBuilder();
+ try{
+ Graph graph = GrpcToGraph.deriveGraph(request);
+ Graph newGraph = graphService.addGraph(graph);
+ response.setSuccess(true).setTopologyTemplate(GraphToGrpc.obtainTopologyTemplate(newGraph));
+ } catch(BadRequestException ex) {
+ ex.printStackTrace();
+ response.setSuccess(false).setErrorMessage("Provided invalid request to the service.");
+ logger.log(Level.WARNING, ex.getClass().toString());
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ response.setSuccess(false).setErrorMessage(internalError);
+ logger.log(Level.WARNING, ex.getClass().toString());
+ logger.log(Level.WARNING, ex.getMessage());
+ }
+ responseObserver.onNext(response.build());
+ responseObserver.onCompleted();
+ }
+
+
+ @Override
+ public void updateTopologyTemplate (TopologyTemplateGrpc request, StreamObserver<NewTopologyTemplate> responseObserver) {
+ NewTopologyTemplate.Builder response = NewTopologyTemplate.newBuilder();
+ try{
+ Graph graph = GrpcToGraph.deriveGraph(request);
+ Graph newGraph = graphService.updateGraph(graph);
+ response.setSuccess(true).setTopologyTemplate(GraphToGrpc.obtainTopologyTemplate(newGraph));
+ } catch(ForbiddenException | DataNotFoundException | BadRequestException ex){
+ response.setSuccess(false).setErrorMessage(ex.getMessage());
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(Exception ex){
+ response.setSuccess(false).setErrorMessage(internalError);
+ logger.log(Level.WARNING, ex.getMessage());
+ }
+ responseObserver.onNext(response.build());
+ responseObserver.onCompleted();
+ }
+
+
+ @Override
+ public void deleteTopologyTemplate (ToscaRequestID request, StreamObserver<Status> responseObserver) {
+ Status.Builder response = Status.newBuilder();
+ Long graphID = null;
+ try{
+ graphID = Long.valueOf(request.getIdTopologyTemplate());
+ //this method will throw a NumberFormatException in case the ID is not representable as a long
+ graphService.removeGraph(graphID);
+ response.setSuccess(true);
+ } catch(ForbiddenException | DataNotFoundException ex) {
+ response.setSuccess(false).setErrorMessage(ex.getMessage());
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(NumberFormatException ex) {
+ response.setSuccess(false).setErrorMessage("The TopologyTemplate ID must be a long value.");
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(Exception ex) {
+ response.setSuccess(false).setErrorMessage(internalError);
+ logger.log(Level.WARNING, ex.getMessage());
+ }
+ responseObserver.onNext(response.build());
+ responseObserver.onCompleted();
+ }
+
+
+ @Override
+ public void verifyToscaPolicy(ToscaPolicy request, StreamObserver<ToscaVerificationGrpc> responseObserver) {
+ try{
+ //Convert request
+ VerificationBean verify = new VerificationBean();
+ verify.setDestination(request.getDestination());
+ verify.setSource(request.getSource());
+ verify.setType(request.getType().toString());
+ verify.setMiddlebox(request.getMiddlebox());
+
+ //Convert Response
+ Long graphID = Long.valueOf(request.getIdTopologyTemplate());
+ //this method will throw a NumberFormatException in case the ID is not representable as a long
+ Verification ver = verificationService.verify(graphID, verify);
+ responseObserver.onNext(GraphToGrpc.obtainToscaVerification(ver));
+ } catch(ForbiddenException | DataNotFoundException | BadRequestException ex) {
+ ToscaVerificationGrpc verError = ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+ .setErrorMessage(ex.getMessage()).build();
+ responseObserver.onNext(verError);
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(NumberFormatException ex) {
+ ToscaVerificationGrpc verError = ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+ .setErrorMessage("The TopologyTemplate ID must be a long value.").build();
+ responseObserver.onNext(verError);
+ logger.log(Level.WARNING, ex.getMessage());
+ } catch(Exception ex) {
+ ToscaVerificationGrpc verError = ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+ .setErrorMessage(internalError).build();
+ responseObserver.onNext(verError);
+ logger.log(Level.WARNING, ex.getMessage());
+ } responseObserver.onCompleted();
+ }
+
+
}
}
diff --git a/verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java b/verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java
new file mode 100644
index 0000000..5771406
--- /dev/null
+++ b/verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Politecnico di Torino and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Apache License, Version 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *******************************************************************************/
+package it.polito.verigraph.grpc.tosca.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.runners.MethodSorters;
+
+import it.polito.verigraph.grpc.NewTopologyTemplate;
+import it.polito.verigraph.grpc.NodeTemplateGrpc;
+import it.polito.verigraph.grpc.NodeTemplateGrpc.Type;
+import it.polito.verigraph.grpc.RelationshipTemplateGrpc;
+import it.polito.verigraph.grpc.Status;
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;
+import it.polito.verigraph.grpc.ToscaConfigurationGrpc;
+import it.polito.verigraph.grpc.ToscaPolicy;
+import it.polito.verigraph.grpc.ToscaPolicy.PolicyType;
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;
+import it.polito.verigraph.grpc.client.ToscaClient;
+import it.polito.verigraph.grpc.server.Service;
+
+@RunWith(JUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class GrpcToscaTest {
+ private Service server;
+ private ToscaClient client;
+ private TopologyTemplateGrpc testTemplate, simpleTestTemplate;
+
+ public GrpcToscaTest() {
+ this.generateTestTemplate();
+ }
+
+ @Before
+ public void setUpBeforeClass() throws Exception {
+ client = new ToscaClient("localhost" , 50051);
+ server = new Service(50051);
+ server.start();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ server.stop();
+ client.shutdown();
+ }
+
+
+ @Test
+ public void test0Creation() {
+ System.out.println("\nTest A: Graph Creation.");
+
+ NewTopologyTemplate response = client.createTopologyTemplate(testTemplate);
+ assertNotNull("Returned a NULL graph", response);
+ assertEquals(response.getSuccess(), true);
+ assertEquals("Error report: " + response.getErrorMessage(), "", response.getErrorMessage());
+
+ Status resp = client.deleteTopologyTemplate(response.getTopologyTemplate().getId());
+ assertEquals("Error while deleting testTemplate.", true, resp.getSuccess());
+
+ System.out.println("Test A completed\n");
+
+ return;
+ }
+
+
+ @Test
+ public void test1Reading() {
+ System.out.println("\nTest B: Graph Reading.");
+
+ //Creating a test graph on remote repository
+ System.out.println("Phase B.1 -- Creating a test graph.");
+ NewTopologyTemplate response = client.createTopologyTemplate(simpleTestTemplate);
+ assertNotNull("Returned a NULL graph", response);
+ assertEquals(true, response.getSuccess());
+ assertEquals("Error report: " + response.getErrorMessage(), "", response.getErrorMessage());
+
+ //Reading remote graph.
+ System.out.println("Phase B.2 -- Reading remote graph.");
+ TopologyTemplateGrpc retrieved = client.getTopologyTemplate(response.getTopologyTemplate().getId());
+ assertNotNull("Retrieved a NULL graph", retrieved);
+ assertEquals(retrieved.getId(), response.getTopologyTemplate().getId());
+
+ //Nodes checking
+ System.out.println("Phase B.3 -- Checking graph's nodes.");
+ assertEquals(retrieved.getNodeTemplateCount(), 3);
+ assertEquals("Node1 name error", response.getTopologyTemplate().getNodeTemplateList().get(0).getName(),
+ retrieved.getNodeTemplateList().get(0).getName());
+ assertEquals("Node2 name error", response.getTopologyTemplate().getNodeTemplateList().get(1).getName(),
+ retrieved.getNodeTemplateList().get(1).getName());
+ assertEquals("Node3 name error", response.getTopologyTemplate().getNodeTemplateList().get(2).getName(),
+ retrieved.getNodeTemplateList().get(2).getName());
+
+ //Relationships checking
+ System.out.println("Phase B.4 -- Checking graph's relationships.");
+ assertEquals(retrieved.getRelationshipTemplateCount(), 4);
+ String source1=null, target1=null;
+ String source2=null, target2=null;
+ String source3=null, target3=null;
+ String source4=null, target4=null;
+ for (NodeTemplateGrpc node : retrieved.getNodeTemplateList()){
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(0).getIdSourceNodeTemplate()))
+ source1=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(0).getIdTargetNodeTemplate()))
+ target1=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(1).getIdSourceNodeTemplate()))
+ source2=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(1).getIdTargetNodeTemplate()))
+ target2=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(2).getIdSourceNodeTemplate()))
+ source3=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(2).getIdTargetNodeTemplate()))
+ target3=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(3).getIdSourceNodeTemplate()))
+ source4=node.getName();
+ if(node.getId().equals(retrieved.getRelationshipTemplateList().get(3).getIdTargetNodeTemplate()))
+ target4=node.getName();
+ }
+
+ assertEquals("Relat1 name error", retrieved.getRelationshipTemplateList().get(0).getName(), source1+"to"+target1);
+ assertEquals("Relat2 name error", retrieved.getRelationshipTemplateList().get(1).getName(), source2+"to"+target2);
+ assertEquals("Relat3 name error", retrieved.getRelationshipTemplateList().get(2).getName(), source3+"to"+target3);
+ assertEquals("Relat4 name error", retrieved.getRelationshipTemplateList().get(3).getName(), source4+"to"+target4);
+
+ System.out.println("Phase B.5 -- Deleting graph.");
+ Status resp = client.deleteTopologyTemplate(response.getTopologyTemplate().getId());
+ assertEquals("Error while deleting simpleTestTemplate", true, resp.getSuccess());
+
+
+ System.out.println("Test B completed.\n");
+ return;
+ }
+
+ @Test
+ public void test2Update() {
+ System.out.println("\nTest C: Update.");
+
+ //Creating a test graph on remote repository
+ System.out.println("Phase C.1 -- Creating a test graph.");
+ NewTopologyTemplate response = client.createTopologyTemplate(simpleTestTemplate);
+ assertNotNull("Returned a NULL graph", response);
+ assertEquals(true, response.getSuccess());
+ assertEquals("Error report: " + response.getErrorMessage(), "", response.getErrorMessage());
+
+ //Reading remote graph.
+ System.out.println("Phase C.2 -- Reading remote graph.");
+ TopologyTemplateGrpc retrieved = client.getTopologyTemplate(response.getTopologyTemplate().getId());
+ assertNotNull("Retrieved a NULL graph", retrieved);
+ assertEquals(retrieved.getId(), response.getTopologyTemplate().getId());
+
+ //Updating a TopologyTemplateGrpc
+ System.out.println("Phase C.3 -- Updating a test graph.");
+ TopologyTemplateGrpc.Builder templ = TopologyTemplateGrpc.newBuilder();
+ List<NodeTemplateGrpc> nodes = new ArrayList<NodeTemplateGrpc>();
+ List<RelationshipTemplateGrpc> relats = new ArrayList<RelationshipTemplateGrpc>();
+
+ ToscaConfigurationGrpc node1conf = ToscaConfigurationGrpc.newBuilder().setDescription("node1configuration")
+ .setId("15").setConfiguration("[]").build();
+ NodeTemplateGrpc node1 = NodeTemplateGrpc.newBuilder().setConfiguration(node1conf).setId("999")
+ .setName("webserver1").setType(Type.webserver).build();
+ nodes.add(node1);
+
+ ToscaConfigurationGrpc node2conf = ToscaConfigurationGrpc.newBuilder().setDescription("node2configuration")
+ .setId("16").setConfiguration("[{\r\n\"protocol\":\"HTTP_REQUEST\",\r\n \"url\":\"www.facebook.com\"\r\n }]").build();
+ NodeTemplateGrpc node2 = NodeTemplateGrpc.newBuilder().setConfiguration(node2conf).setId("888")
+ .setName("host2").setType(Type.endhost).build();
+ nodes.add(node2);
+
+ RelationshipTemplateGrpc rel0 = RelationshipTemplateGrpc.newBuilder().setId("1001")
+ .setIdSourceNodeTemplate("999").setIdTargetNodeTemplate("888").setName("webserver1tohost2").build();
+ relats.add(rel0);
+
+ RelationshipTemplateGrpc rel1 = RelationshipTemplateGrpc.newBuilder().setId("1002")
+ .setIdSourceNodeTemplate("888").setIdTargetNodeTemplate("999").setName("host2towebserver1").build();
+ relats.add(rel1);
+
+ TopologyTemplateGrpc newTestTemplate = templ.addAllNodeTemplate(nodes).addAllRelationshipTemplate(relats).setId("9").build();
+ NewTopologyTemplate updated = client.updateTopologyTemplate(newTestTemplate, response.getTopologyTemplate().getId());
+ assertNotNull("Returned a NULL graph", updated);
+ assertEquals(true, updated.getSuccess());
+ assertEquals("Error report: " + updated.getErrorMessage(), "", updated.getErrorMessage());
+
+ //Reading remote graph.
+ System.out.println("Phase C.4 -- Reading remote graph.");
+ TopologyTemplateGrpc retrieved2 = client.getTopologyTemplate(response.getTopologyTemplate().getId());
+ assertNotNull("Retrieved a NULL graph", retrieved2);
+ assertEquals(retrieved2.getId(), response.getTopologyTemplate().getId());
+
+ //Nodes checking
+ System.out.println("Phase C.5 -- Checking updated graph's nodes.");
+ assertEquals(retrieved2.getNodeTemplateCount(), 2);
+ assertEquals("Node1 name error", updated.getTopologyTemplate().getNodeTemplateList().get(0).getName(),
+ retrieved2.getNodeTemplateList().get(0).getName());
+ assertEquals("Node2 name error", updated.getTopologyTemplate().getNodeTemplateList().get(1).getName(),
+ retrieved2.getNodeTemplateList().get(1).getName());
+
+ //Relationships checking
+ System.out.println("Phase C.6 -- Checking updated graph's relationships.");
+ assertEquals(retrieved2.getRelationshipTemplateCount(), 2);
+ String source1=null, target1=null;
+ String source2=null, target2=null;
+ for (NodeTemplateGrpc node : retrieved2.getNodeTemplateList()){
+ if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(0).getIdSourceNodeTemplate()))
+ source1=node.getName();
+ if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(0).getIdTargetNodeTemplate()))
+ target1=node.getName();
+ if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(1).getIdSourceNodeTemplate()))
+ source2=node.getName();
+ if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(1).getIdTargetNodeTemplate()))
+ target2=node.getName();
+ }
+
+ assertEquals("Relat1 name error", retrieved2.getRelationshipTemplateList().get(0).getName(), source1+"to"+target1);
+ assertEquals("Relat2 name error", retrieved2.getRelationshipTemplateList().get(1).getName(), source2+"to"+target2);
+
+ System.out.println("Phase C.6 -- Deleting graph.");
+ Status resp = client.deleteTopologyTemplate(updated.getTopologyTemplate().getId());
+ assertEquals("Error while deleting simpleTestTemplate", true, resp.getSuccess());
+
+ System.out.println("Test C completed.\n");
+ return;
+ }
+
+
+ @Test
+ public void test3Verification() {
+ System.out.println("\nTest D: Verification.");
+ NewTopologyTemplate response = client.createTopologyTemplate(testTemplate);
+ if(response == null | response.getSuccess() != true) {
+ fail("Test failed, unable to load the graph.");
+ return;
+ }
+
+ //The Id of the graph on which we are going to perform tests
+ String testTemplateId = response.getTopologyTemplate().getId();
+
+ //REACHABILITY test
+ System.out.println("Phase 1.1 - Reachability SAT.");
+ ToscaPolicy policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)
+ .setType(PolicyType.reachability).setSource("host2").setDestination("host1").build();
+ ToscaVerificationGrpc result = client.verifyPolicy(policy);
+ assertNotNull("There was no response", result);
+ assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "SAT", result.getResult());
+ assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());
+
+ result = null;
+ System.out.println("Phase 1.2 - Reachability UNSAT.");
+ policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)
+ .setType(PolicyType.reachability).setSource("host1").setDestination("antispamNode1").build();
+ result = client.verifyPolicy(policy);
+ assertNotNull("There was no response", result);
+ assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "UNSAT", result.getResult());
+ assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());
+
+ //ISOLATION test
+ result = null;
+ System.out.println("Phase 2.1 - Isolation SAT.");
+ policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)
+ .setType(PolicyType.isolation).setSource("host2").setDestination("host1").setMiddlebox("webserver1").build();
+ result = client.verifyPolicy(policy);
+ assertNotNull("There was no response", result);
+ assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "SAT", result.getResult());
+ assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());
+
+ System.out.println("Phase 2.2 - Isolation UNSAT.");
+ policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)
+ .setType(PolicyType.isolation).setSource("host2").setDestination("host1").setMiddlebox("fw").build();
+ result = client.verifyPolicy(policy);
+ assertNotNull("There was no response", result);
+ assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "UNSAT", result.getResult());
+ assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());
+
+ //TRAVERSAL test
+ result = null;
+ System.out.println("Phase 3.1 - Traversal SAT.");
+ policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)
+ .setType(PolicyType.traversal).setSource("host2").setDestination("host1").setMiddlebox("fw").build();
+ result = client.verifyPolicy(policy);
+ assertNotNull("There was no response", result);
+ assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "SAT", result.getResult());
+ assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());
+
+ System.out.println("Phase 3.2 - Traversal UNSAT.");
+ policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)
+ .setType(PolicyType.traversal).setSource("host2").setDestination("webserver1").setMiddlebox("fw").build();
+ result = client.verifyPolicy(policy);
+ assertNotNull("There was no response", result);
+ assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "UNSAT", result.getResult());
+ assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());
+
+ Status resp = client.deleteTopologyTemplate(testTemplateId);
+ assertEquals("Error while deleting testTemplate", true, resp.getSuccess());
+
+ System.out.println("Test D completed.\n");
+ return;
+ }
+
+
+ @Test
+ public void test4Deletion() {
+ System.out.println("\nTest E: Deletion");
+ NewTopologyTemplate templ = client.createTopologyTemplate(testTemplate);
+
+ if(templ.getSuccess() != true) {
+ fail("Unable to create the graph.");
+ return;
+ }else {
+ Status resp = client.deleteTopologyTemplate(templ.getTopologyTemplate().getId());
+ assertEquals("Error while deleting testTemplate", true, resp.getSuccess());
+ }
+
+ System.out.println("Test E completed.\n");
+ return;
+ }
+
+
+ //Generates a correct instance of a TopologyTemplateGrpc to be used in tests
+ public void generateTestTemplate() {
+ TopologyTemplateGrpc.Builder templ = TopologyTemplateGrpc.newBuilder();
+ List<NodeTemplateGrpc> nodes = new ArrayList<NodeTemplateGrpc>();
+ List<RelationshipTemplateGrpc> relats = new ArrayList<RelationshipTemplateGrpc>();
+
+ //Definition of nodes
+ ToscaConfigurationGrpc node0conf = ToscaConfigurationGrpc.newBuilder().setDescription("node0configuration")
+ .setId("100").setConfiguration("[{\r\n\"webserver1\":\"host2\"\r\n}]").build();
+ NodeTemplateGrpc node0 = NodeTemplateGrpc.newBuilder().setConfiguration(node0conf).setId("100")
+ .setName("fw").setType(Type.firewall).build();
+ nodes.add(node0);
+
+ ToscaConfigurationGrpc node1conf = ToscaConfigurationGrpc.newBuilder().setDescription("node1configuration")
+ .setId("101").setConfiguration("[]").build();
+ NodeTemplateGrpc node1 = NodeTemplateGrpc.newBuilder().setConfiguration(node1conf).setId("101")
+ .setName("webserver1").setType(Type.webserver).build();
+ nodes.add(node1);
+
+ ToscaConfigurationGrpc node2conf = ToscaConfigurationGrpc.newBuilder().setDescription("node2configuration")
+ .setId("102").setConfiguration("[{\r\n\"protocol\":\"HTTP_REQUEST\",\r\n \"url\":\"www.facebook.com\"\r\n }]").build();
+ NodeTemplateGrpc node2 = NodeTemplateGrpc.newBuilder().setConfiguration(node2conf).setId("102")
+ .setName("host2").setType(Type.endhost).build();
+ nodes.add(node2);
+
+ ToscaConfigurationGrpc node3conf = ToscaConfigurationGrpc.newBuilder().setDescription("node3configuration")
+ .setId("103").setConfiguration("[ {\r\n\"protocol\":\"HTTP_REQUEST\",\r\n\"url\":\"www.google.com\",\r\n\"destination\":\"server1\"\r\n}]").build();
+ NodeTemplateGrpc node3 = NodeTemplateGrpc.newBuilder().setConfiguration(node3conf).setId("103")
+ .setName("host1").setType(Type.endhost).build();
+ nodes.add(node3);
+
+ ToscaConfigurationGrpc node4conf = ToscaConfigurationGrpc.newBuilder().setDescription("node4configuration")
+ .setId("104").setConfiguration("[\"host1\",\"host2\"]").build();
+ NodeTemplateGrpc node4 = NodeTemplateGrpc.newBuilder().setConfiguration(node4conf).setId("104")
+ .setName("antispamNode1").setType(Type.antispam).build();
+ nodes.add(node4);
+
+ //Building relationships
+ RelationshipTemplateGrpc rel0 = RelationshipTemplateGrpc.newBuilder().setId("1001")
+ .setIdSourceNodeTemplate("100").setIdTargetNodeTemplate("101").setName("fwToServ1").build();
+ relats.add(rel0);
+
+ RelationshipTemplateGrpc rel1 = RelationshipTemplateGrpc.newBuilder().setId("1002")
+ .setIdSourceNodeTemplate("101").setIdTargetNodeTemplate("100").setName("serv1ToFw").build();
+ relats.add(rel1);
+
+ RelationshipTemplateGrpc rel2 = RelationshipTemplateGrpc.newBuilder().setId("1003")
+ .setIdSourceNodeTemplate("100").setIdTargetNodeTemplate("103").setName("fwToHost1").build();
+ relats.add(rel2);
+
+ RelationshipTemplateGrpc rel3 = RelationshipTemplateGrpc.newBuilder().setId("1004")
+ .setIdSourceNodeTemplate("100").setIdTargetNodeTemplate("102").setName("fwToHost2").build();
+ relats.add(rel3);
+
+ RelationshipTemplateGrpc rel4 = RelationshipTemplateGrpc.newBuilder().setId("1005")
+ .setIdSourceNodeTemplate("102").setIdTargetNodeTemplate("100").setName("Host2Tofw").build();
+ relats.add(rel4);
+
+ RelationshipTemplateGrpc rel5 = RelationshipTemplateGrpc.newBuilder().setId("1006")
+ .setIdSourceNodeTemplate("103").setIdTargetNodeTemplate("100").setName("Host1Tofw").build();
+ relats.add(rel5);
+
+ this.testTemplate = templ.addAllNodeTemplate(nodes).addAllRelationshipTemplate(relats).setId("0").build();
+
+ TopologyTemplateGrpc.Builder templ2 = TopologyTemplateGrpc.newBuilder();
+ List<NodeTemplateGrpc> nodes2 = new ArrayList<NodeTemplateGrpc>();
+ List<RelationshipTemplateGrpc> relats2 = new ArrayList<RelationshipTemplateGrpc>();
+ nodes2.add(node0);
+ nodes2.add(node1);
+ nodes2.add(node2);
+ relats2.add(rel0);
+ relats2.add(rel1);
+ relats2.add(rel3);
+ relats2.add(rel4);
+
+ this.simpleTestTemplate = templ2.addAllNodeTemplate(nodes2).addAllRelationshipTemplate(relats2).setId("1").build();
+
+ }
+
+ /*class NodeTemplateGrpcComparator implements Comparator<NodeTemplateGrpc> {
+ public int compare(NodeTemplateGrpc n0, NodeTemplateGrpc n1) {
+ return n0.getName().compareTo(n1.getName());
+ }
+ }
+
+ class RelationshipTemplateGrpcComparator implements Comparator<RelationshipTemplateGrpc> {
+ public int compare(RelationshipTemplateGrpc n0, RelationshipTemplateGrpc n1) {
+ int source = n0.getIdSourceNodeTemplate().compareTo(n1.getIdSourceNodeTemplate());
+ int target = n0.getIdTargetNodeTemplate().compareTo(n1.getIdTargetNodeTemplate());
+ return source + target;
+ }
+ }*/
+
+}
diff --git a/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java b/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java
new file mode 100644
index 0000000..fb52c7b
--- /dev/null
+++ b/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Politecnico di Torino and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Apache License, Version 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *******************************************************************************/
+package it.polito.verigraph.tosca.converter.grpc;
+
+import java.util.Map;
+
+import it.polito.verigraph.grpc.NodeTemplateGrpc;
+import it.polito.verigraph.grpc.RelationshipTemplateGrpc;
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;
+import it.polito.verigraph.grpc.ToscaConfigurationGrpc;
+import it.polito.verigraph.grpc.ToscaTestGrpc;
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;
+import it.polito.verigraph.model.Configuration;
+import it.polito.verigraph.model.Graph;
+import it.polito.verigraph.model.Neighbour;
+import it.polito.verigraph.model.Node;
+import it.polito.verigraph.model.Test;
+import it.polito.verigraph.model.Verification;
+
+public class GraphToGrpc {
+
+ /** Mapping method --> from model Graph to grpc TopologyTemplate */
+ public static TopologyTemplateGrpc obtainTopologyTemplate(Graph graph) {
+ TopologyTemplateGrpc.Builder topol = TopologyTemplateGrpc.newBuilder();
+ topol.setId(String.valueOf(graph.getId()));
+
+ //NodeTemplate
+ for(Node node : graph.getNodes().values()) {
+ NodeTemplateGrpc nt = obtainNodeTemplate(node);
+ topol.addNodeTemplate(nt);
+ //RelationshipTemplate
+ Map<Long,Neighbour> neighMap = node.getNeighbours();
+ for (Map.Entry<Long, Neighbour> myentry : neighMap.entrySet()) {
+ Neighbour neigh = myentry.getValue();
+ RelationshipTemplateGrpc relat = obtainRelationshipTemplate(neigh, node);
+ topol.addRelationshipTemplate(relat);
+ }
+ }
+ return topol.build();
+ }
+
+
+ /** Mapping method --> from model Node to grpc NodeTemplate */
+ private static NodeTemplateGrpc obtainNodeTemplate(Node node){
+ NodeTemplateGrpc.Builder nodegrpc = NodeTemplateGrpc.newBuilder();
+
+ nodegrpc.setId(String.valueOf(node.getId()));
+ nodegrpc.setName(node.getName());
+ nodegrpc.setType(NodeTemplateGrpc.Type.valueOf(node.getFunctional_type().toLowerCase()));
+
+ ToscaConfigurationGrpc config = obtainToscaConfiguration(node.getConfiguration());
+ nodegrpc.setConfiguration(config);
+
+ return nodegrpc.build();
+ }
+
+
+ /** Mapping method --> from model Neighbour to grpc RelationshipTemplate */
+ private static RelationshipTemplateGrpc obtainRelationshipTemplate(Neighbour neigh, Node sourceNode) {
+ RelationshipTemplateGrpc.Builder relat = RelationshipTemplateGrpc.newBuilder();
+ relat.setId(String.valueOf(sourceNode.getId()));
+ //Neighbour does not have a neighbourID! RelationshipTemplate does, so it is set to sourceNodeID
+ relat.setIdSourceNodeTemplate(String.valueOf(sourceNode.getId()));
+ relat.setIdTargetNodeTemplate(String.valueOf(neigh.getId()));
+ relat.setName(sourceNode.getName()+"to"+neigh.getName());
+ return relat.build();
+ }
+
+
+ /** Mapping method --> from model Configuration to grpc ToscaConfigurationGrpc */
+ private static ToscaConfigurationGrpc obtainToscaConfiguration(Configuration conf) {
+ return ToscaConfigurationGrpc.newBuilder()
+ .setId(conf.getId())
+ .setDescription(conf.getDescription())
+ .setConfiguration(conf.getConfiguration().toString())
+ .build();
+ }
+
+ /** Mapping method --> from model Verification to grpc ToscaVerificationGrpc */
+ public static ToscaVerificationGrpc obtainToscaVerification(Verification verify){
+ ToscaVerificationGrpc.Builder ver = ToscaVerificationGrpc.newBuilder();
+ ver.setComment(verify.getComment());
+ ver.setResult(verify.getResult());
+ for(Test test:verify.getTests()){
+ ToscaTestGrpc.Builder tst = ToscaTestGrpc.newBuilder().setResult(test.getResult());
+ for(Node node:test.getPath()){
+ NodeTemplateGrpc nodetempl = obtainNodeTemplate(node);
+ tst.addNodeTemplate(nodetempl);
+ }
+ ver.addTest(tst);
+ }
+ return ver.build();
+ }
+
+}
diff --git a/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java b/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java
new file mode 100644
index 0000000..76906b3
--- /dev/null
+++ b/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Politecnico di Torino and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Apache License, Version 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *******************************************************************************/
+package it.polito.verigraph.tosca.converter.grpc;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import it.polito.verigraph.exception.BadRequestException;
+import it.polito.verigraph.grpc.NodeTemplateGrpc;
+import it.polito.verigraph.grpc.RelationshipTemplateGrpc;
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;
+import it.polito.verigraph.grpc.ToscaConfigurationGrpc;
+import it.polito.verigraph.model.Configuration;
+import it.polito.verigraph.model.Graph;
+import it.polito.verigraph.model.Neighbour;
+import it.polito.verigraph.model.Node;
+
+public class GrpcToGraph {
+
+ /** Mapping method --> from grpc TopologyTemplateGrpc to model Graph */
+ public static Graph deriveGraph(TopologyTemplateGrpc request) throws BadRequestException, JsonProcessingException, IOException {
+ Graph graph = new Graph();
+ Map<Long, Node> nodes = new HashMap<>();
+
+ try {
+ //Create a list of Node without Neighbour
+ for(NodeTemplateGrpc nodetempl : request.getNodeTemplateList()){
+ Node node = deriveNode(nodetempl);
+ //It necessary to check uniqueness here otherwise a .put with the same key will overwrite the old node
+ if(nodes.containsKey(node.getId()))
+ throw new BadRequestException("The NodeTemplate ID must be unique.");
+ else
+ nodes.put(node.getId(), node);
+ }
+
+ //Add Neighbour to the Node of the list
+ List<RelationshipTemplateGrpc> relatList = request.getRelationshipTemplateList();
+ nodes = deriveNeighboursNode(nodes, relatList);
+
+ //Add Node and ID to the graph
+ graph.setNodes(nodes);
+ try {
+ graph.setId(Long.valueOf(request.getId()));
+ } catch(NumberFormatException ex) {
+ throw new BadRequestException("If you want to store your TopologyTemplate on this server,"
+ + "the TopologyTemplate ID must be a number.");
+ }
+
+ return graph;
+
+ } catch (NullPointerException e) {
+ throw new BadRequestException("The TopologyTemplate received has invalid fields.");
+ }
+
+ }
+
+
+ /** Mapping method --> from grpc NodeTemplate to model Node (with no Neighbour) */
+ private static Node deriveNode(NodeTemplateGrpc nodegrpc) throws BadRequestException, JsonProcessingException, IOException {
+ Node node = new Node();
+ try {
+ try {
+ node.setId(Long.valueOf(nodegrpc.getId()));
+ } catch(NumberFormatException ex) {
+ throw new BadRequestException("The NodeTemplate ID must be a number.");
+ }
+
+ node.setName(nodegrpc.getName());
+ Configuration conf = deriveConfiguration(nodegrpc.getConfiguration());
+ node.setConfiguration(conf);
+ node.setFunctional_type(nodegrpc.getType().toString());
+
+ } catch(NullPointerException ex) {
+ throw new BadRequestException("A NodeTemplate has wrong fields representation.");
+ }
+
+ return node;
+ }
+
+
+
+ /** Mapping method --> from a list of model Node to a list of model Node with their Neighbour */
+ private static Map<Long,Node> deriveNeighboursNode(Map<Long,Node> nodes, List<RelationshipTemplateGrpc> relatList)
+ throws BadRequestException{
+ Map<Long,Node> updNodes = nodes; //new list to be filled with updated Node (update = Node + its Neighbour)
+ for(RelationshipTemplateGrpc relat : relatList) {
+ try {
+ //Retrieve the target Node name and generate a new Neighbour
+ String neighName = updNodes.get(Long.valueOf(relat.getIdTargetNodeTemplate())).getName();
+ Neighbour neigh = new Neighbour();
+ neigh.setName(neighName);
+ neigh.setId(Long.valueOf(relat.getId()));
+
+ //Retrieve the Neighbour map of the source Node and add the Neighbour
+ Node source = updNodes.get(Long.valueOf(relat.getIdSourceNodeTemplate()));
+ Map<Long,Neighbour> sourceNodeNeighMap = source.getNeighbours();
+ if(sourceNodeNeighMap.containsKey(neigh.getId()))
+ throw new BadRequestException("The RelationshipTemplate ID must be unique.");
+ else
+ sourceNodeNeighMap.put(neigh.getId(), neigh);
+ source.setNeighbours(sourceNodeNeighMap);
+
+ //Update the Node list
+ updNodes.put(Long.valueOf(relat.getIdSourceNodeTemplate()), source);
+ } catch(NullPointerException | NumberFormatException ex) {
+ throw new BadRequestException("A RelationshipTemplate has wrong fields representation.");
+ }
+ }
+ return updNodes;
+ }
+
+ /** Mapping method --> from ToscaConfiguration to model Configuration */
+ private static Configuration deriveConfiguration(ToscaConfigurationGrpc request)
+ throws BadRequestException, JsonProcessingException, IOException {
+ Configuration conf = new Configuration();
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode rootNode = null;
+
+ try {
+ conf.setId(request.getId());
+ } catch (NullPointerException e) {}
+
+ try {
+ conf.setDescription(request.getDescription());
+ } catch (NullPointerException e) {}
+
+ try {
+ if ("".equals(request.getConfiguration()))
+ rootNode=mapper.readTree("[]");
+ else
+ rootNode = mapper.readTree(request.getConfiguration());
+ } catch (NullPointerException e) {
+ rootNode=mapper.readTree("[]");
+ }
+ conf.setConfiguration(rootNode);
+ return conf;
+ }
+}
diff --git a/verigraph/src/main/proto/verigraph.proto b/verigraph/src/main/proto/verigraph.proto
index feb8ff0..e8e9ccc 100644
--- a/verigraph/src/main/proto/verigraph.proto
+++ b/verigraph/src/main/proto/verigraph.proto
@@ -1,3 +1,13 @@
+/* This Protocol Buffer has been updated for supporting TOSCA-based objects.
+ * The only granularity for executing CRUD operations is at the TopologyTemplate level.
+ *
+ * The names of the objects are assigned according to the TOSCA standard, and can be
+ * mapped as follows in the Verigraph domain:
+ * TopologyTemplate -> Graph
+ * NodeTemplate -> Node
+ * RelationshipTemplate -> Neighbour (partial)
+*/
+
syntax = "proto3";
package verigraph;
@@ -6,7 +16,7 @@ option java_multiple_files = true;
option java_package = "it.polito.verigraph.grpc";
option java_outer_classname = "VerigraphProto";
-// The service definition.
+/** gRPC */
service Verigraph {
// Obtains a list of graphs
rpc GetGraphs (GetRequest) returns (stream GraphGrpc) {}
@@ -45,8 +55,24 @@ service Verigraph {
rpc DeleteNeighbour (RequestID) returns (Status) {}
// Updates a neighbour
rpc UpdateNeighbour (NeighbourGrpc) returns (NewNeighbour) {}
+
+ /** TOSCA gRPC */
+ // Obtain a list of topology templates
+ rpc GetTopologyTemplates (GetRequest) returns (stream TopologyTemplateGrpc) {}
+ // Obtain a topology template
+ rpc GetTopologyTemplate (ToscaRequestID) returns (TopologyTemplateGrpc) {}
+ // Create a TopologyTemplate
+ rpc CreateTopologyTemplate (TopologyTemplateGrpc) returns (NewTopologyTemplate) {}
+ // Delete a TopologyTemplate
+ rpc DeleteTopologyTemplate (ToscaRequestID) returns (Status) {}
+ // Update a TopologyTemplate
+ rpc UpdateTopologyTemplate (TopologyTemplateGrpc) returns (NewTopologyTemplate) {}
+ // Verify a ToscaPolicy
+ rpc VerifyToscaPolicy (ToscaPolicy) returns (ToscaVerificationGrpc) {}
}
+
+/** Messages */
message GetRequest {
}
@@ -151,4 +177,87 @@ string errorMessage = 5;
message Status{
bool success = 1;
string errorMessage = 2;
-} \ No newline at end of file
+}
+
+/** TOSCA Messages */
+message ToscaRequestID {
+ string idTopologyTemplate = 1;
+}
+
+message TopologyTemplateGrpc{
+ string id = 1;
+ string name = 2;
+ repeated NodeTemplateGrpc nodeTemplate = 3;
+ repeated RelationshipTemplateGrpc relationshipTemplate = 4;
+ string errorMessage = 5;
+}
+
+message NewTopologyTemplate{
+ bool success = 1;
+ TopologyTemplateGrpc topologyTemplate = 2;
+ string errorMessage = 3;
+}
+
+message NodeTemplateGrpc{
+ string id = 1;
+ string name = 2;
+ enum Type {
+ antispam = 0;
+ cache = 1;
+ dpi = 2;
+ endhost = 3;
+ endpoint = 4;
+ fieldmodifier = 5;
+ firewall = 6;
+ mailclient = 7;
+ mailserver = 8;
+ nat = 9;
+ vpnaccess = 10;
+ vpnexit = 11;
+ webclient = 12;
+ webserver = 13;
+ }
+ Type type = 3;
+ ToscaConfigurationGrpc configuration = 4;
+ string errorMessage = 5;
+}
+
+message RelationshipTemplateGrpc{
+ string idSourceNodeTemplate = 1;
+ string idTargetNodeTemplate = 2;
+ string id = 3;
+ string name = 4;
+ string errorMessage = 5;
+}
+
+message ToscaPolicy{
+ string idTopologyTemplate = 1;
+ string source = 2;
+ string destination = 3;
+ enum PolicyType {
+ reachability = 0;
+ isolation = 1;
+ traversal = 2;
+ }
+ PolicyType type = 4;
+ string middlebox = 5;
+}
+
+message ToscaConfigurationGrpc{
+ string id = 1;
+ string description = 2;
+ string configuration = 3;
+}
+
+message ToscaTestGrpc {
+ repeated NodeTemplateGrpc nodeTemplate = 1;
+ string result = 2;
+}
+
+message ToscaVerificationGrpc{
+ bool successOfOperation = 1;
+ string result = 2;
+ string comment = 3;
+ repeated ToscaTestGrpc test = 4;
+ string errorMessage = 5;
+}