diff options
213 files changed, 28390 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..f9801b8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +#####standard .git ignore entries##### + +## IDE Specific Files ## +org.eclipse.core.resources.prefs +.classpath +.project +.settings +.idea +.externalToolBuilders +.checkstyle +maven-eclipse.xml +workspace + +## Compilation Files ## +*.class +**/target +target +target-ide +MANIFEST.MF + +## Misc Ignores (OS specific etc) ## +bin/ +dist +*~ +*.ipr +*.iml +*.iws +classes +out/ +.DS_STORE +.metadata + +## antlr4 generated files ## +ExprGrammarBaseListener.java +ExprGrammarLexer.java +ExprGrammarListener.java +ExprGrammarParser.java +ExprGrammar.tokens +ExprGrammarLexer.tokens + +# BlackDuck generated file +sdnc-core_bdio.jsonld +blackDuckHubProjectName.txt +blackDuckHubProjectVersionName.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..3ea5081a --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,22 @@ +/* + * ============LICENSE_START========================================== + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + * + */ diff --git a/README.md b/README.md new file mode 100644 index 00000000..50134aea --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +This source repository contains the code for the core SDN Controller components. +To compile this code: + +1. Make sure your local Maven settings file ($HOME/.m2/settings.xml) contains references to the OpenECOMP repositories and OpenDaylight repositories. See example-settings.xml for an example. + +2. To compile, run "mvn clean install". + diff --git a/dblib/.gitignore b/dblib/.gitignore new file mode 100755 index 00000000..b73caf31 --- /dev/null +++ b/dblib/.gitignore @@ -0,0 +1,34 @@ +#####standard .git ignore entries##### + +## IDE Specific Files ## +org.eclipse.core.resources.prefs +.classpath +.project +.settings +.idea +.externalToolBuilders +maven-eclipse.xml +workspace + +## Compilation Files ## +*.class +**/target +target +target-ide +MANIFEST.MF + +## Misc Ignores (OS specific etc) ## +bin/ +dist +*~ +*.ipr +*.iml +*.iws +classes +out/ +.DS_STORE +.metadata + +## Folders which contain auto generated source code ## +yang-gen-config +yang-gen-sal diff --git a/dblib/README.md b/dblib/README.md new file mode 100755 index 00000000..98e8f0c6 --- /dev/null +++ b/dblib/README.md @@ -0,0 +1,6 @@ +DBLIB Utility +--------------------- + +DBLIB utility is designed as a high availability connection manager. +It is configured to use multiple databases, and based on the configured rules +always provide the connection to te active database. diff --git a/dblib/features/pom.xml b/dblib/features/pom.xml new file mode 100755 index 00000000..6c174b1c --- /dev/null +++ b/dblib/features/pom.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>dblib</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>dblib-features</artifactId> + <name>DBLIB Adaptor - Features</name> + + <packaging>jar</packaging> + + <dependencies> + + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <version>${odl.mdsal.features.version}</version> + <classifier>features</classifier> + <type>xml</type> + + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jdbc</artifactId> + <version>${tomcat-jdbc.version}</version> + </dependency> + + <!-- dependency for opendaylight-karaf-empty for use by testing --> + <dependency> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>opendaylight-karaf-empty</artifactId> + <version>${odl.karaf.empty.distro.version}</version> + <type>zip</type> + </dependency> + + <dependency> + <!-- Required for launching the feature tests --> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>features-test</artifactId> + <version>${odl.commons.opendaylight.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>features-yangtools</artifactId> + <version>${odl.yangtools.version}</version> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + <!-- launches the feature test, which validates that your karaf feature + can be installed inside of a karaf container. It doesn't validate that your + functionality works correctly, just that you have all of the dependent bundles + defined correctly. + <plugin> + + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.16</version> + <configuration> + <systemPropertyVariables> + <karaf.distro.groupId>org.opendaylight.odlparent</karaf.distro.groupId> + <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> + <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> + </systemPropertyVariables> + <dependenciesToScan> + <dependency>org.opendaylight.yangtools:features-test</dependency> + </dependenciesToScan> + </configuration> + </plugin> + --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/dblib/features/src/main/resources/features.xml b/dblib/features/src/main/resources/features.xml new file mode 100755 index 00000000..0c3e8fe3 --- /dev/null +++ b/dblib/features/src/main/resources/features.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<features name="sdnc-dblib-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features</repository> + + + <feature name='sdnc-dblib' description="sdnc-dblib" version='${project.version}'> + <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> + <feature version="${odl.mdsal.version}">odl-mdsal-broker</feature> + <bundle>wrap:mvn:org.apache.tomcat/tomcat-jdbc/${tomcat-jdbc.version}/$DynamicImport-Package=com.mysql.*&overwrite=merge</bundle> + <bundle>mvn:org.openecomp.sdnc.core/dblib-provider/${project.version}</bundle> + <bundle>mvn:mysql/mysql-connector-java/${mysql.connector.version}</bundle> + </feature> + +</features> diff --git a/dblib/installer/pom.xml b/dblib/installer/pom.xml new file mode 100755 index 00000000..9da6a459 --- /dev/null +++ b/dblib/installer/pom.xml @@ -0,0 +1,143 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>dblib</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>dblib-installer</artifactId> + <name>DBLIB Adaptor - Karaf Installer</name> + <packaging>pom</packaging> + + <properties> + <application.name>sdnc-dblib</application.name> + <features.boot>sdnc-dblib</features.boot> + <features.repositories>mvn:org.openecomp.sdnc.core/dblib-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencies> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-features</artifactId> + <version>${project.version}</version> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + <version>${project.version}</version> + </dependency> + + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jdbc</artifactId> + <version>${tomcat-jdbc.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${application.name}-${project.version}-installer</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeGroupIds>org.openecomp.sdnc,org.apache.tomcat</includeGroupIds> + <excludeArtifactIds>sli-common,sli-provider</excludeArtifactIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals><!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/dblib/installer/src/assembly/assemble_installer_zip.xml b/dblib/installer/src/assembly/assemble_installer_zip.xml new file mode 100755 index 00000000..a6a22a9b --- /dev/null +++ b/dblib/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,39 @@ +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml b/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100755 index 00000000..d96c9f40 --- /dev/null +++ b/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,29 @@ +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/dblib/installer/src/main/resources/scripts/install-feature.sh b/dblib/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 00000000..16b5be8c --- /dev/null +++ b/dblib/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/dblib/pom.xml b/dblib/pom.xml new file mode 100755 index 00000000..78af665a --- /dev/null +++ b/dblib/pom.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sdnc-core</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + + <modelVersion>4.0.0</modelVersion> + <packaging>pom</packaging> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib</artifactId> + + + <name>DBLIB Adaptor</name> + <description>The DBLIB adaptor allows service logic to access persistent data in a local sql database</description> + + <version>0.0.1-SNAPSHOT</version> + + <build> + <plugins> + <plugin> + + <groupId>org.codehaus.mojo</groupId> + + <artifactId>license-maven-plugin</artifactId> + + <version>1.9</version> + + <configuration> + + <licenseName>apache_v2</licenseName> + + <inceptionYear>2016</inceptionYear> + + <organizationName>AT&T</organizationName> + + <projectName>openecomp</projectName> + + <roots> + + <root>src/main/java</root> + + </roots> + + <excludes> + + <exclude>*.png</exclude> + + </excludes> + + </configuration> + + </plugin> + </plugins> + + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>${maven.compile.plugin.version}</version> + <configuration> + <source>${java.version.source}</source> + <target>${java.version.target}</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10</version> + + <executions> + <execution> + <id>aggregate</id> + <goals> + <goal>aggregate</goal> + </goals> + <phase>site</phase> + + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <version>2.1.1</version> + <executions> + <execution> + <id>bundle-sources</id> + <phase>package</phase> + <goals> + <!-- produce source artifact for main project sources --> + <goal>jar-no-fork</goal> + + <!-- produce source artifact for project test sources --> + <goal>test-jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + + </pluginManagement> + </build> + <organization> + <name>AT&T</name> + </organization> + <modules> + <module>provider</module> + <module>features</module> + <module>installer</module> + </modules> +</project> diff --git a/dblib/provider/pom.xml b/dblib/provider/pom.xml new file mode 100755 index 00000000..b5acc7e1 --- /dev/null +++ b/dblib/provider/pom.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>dblib-provider</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>bundle</packaging> + <name>DBLIB Adaptor - Provider</name> + <url>http://maven.apache.org</url> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>${equinox.osgi.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>${slf4j.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>${mysql.connector.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jdbc</artifactId> + <version>${tomcat-jdbc.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>${bundle.plugin.version}</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>org.openecomp.sdnc.sli.resource.dblib</Bundle-SymbolicName> + <Bundle-Activator>org.openecomp.sdnc.sli.resource.dblib.DBLIBResourceActivator</Bundle-Activator> + <Export-Package>org.openecomp.sdnc.sli.resource.dblib;version=${project.version}</Export-Package> + <!-- + <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.mysql.jdbc.*,javax.sql.*,org.apache.tomcat.*</Import-Package> + --> + <Import-Package>*</Import-Package> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + + </plugin> + + + </plugins> + </build> +</project> diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java new file mode 100644 index 00000000..58a0aeb1 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSource.java @@ -0,0 +1,616 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.io.Closeable; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.Blob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Observer; + +import javax.sql.DataSource; +import javax.sql.rowset.CachedRowSet; +import javax.sql.rowset.RowSetProvider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.tomcat.jdbc.pool.PoolExhaustedException; +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor; +import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitorObserver; +import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor.TestObject; +import com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException; + + +/** + * @version $Revision: 1.13 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ + +public abstract class CachedDataSource implements DataSource, SQLExecutionMonitorObserver +{ + private static Logger LOGGER = LoggerFactory.getLogger(CachedDataSource.class); + + protected static final String AS_CONF_ERROR = "AS_CONF_ERROR: "; + + protected long CONN_REQ_TIMEOUT = 30L; + protected long DATA_REQ_TIMEOUT = 100L; + + private final SQLExecutionMonitor monitor; + protected DataSource ds = null; + protected String connectionName = null; + protected boolean initialized = false; + + private long interval = 1000; + private long initialDelay = 5000; + private long expectedCompletionTime = 50L; + private boolean canTakeOffLine = true; + private long unprocessedFailoverThreshold = 3L; + + private long nextErrorReportTime = 0L; + + private String globalHostName = null; + + + public CachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException + { + configure(jdbcElem); + monitor = new SQLExecutionMonitor(this); + } + + protected abstract void configure(BaseDBConfiguration jdbcElem) throws DBConfigException; + /* (non-Javadoc) + * @see javax.sql.DataSource#getConnection() + */ + public Connection getConnection() throws SQLException + { + return ds.getConnection(); + } + + public CachedRowSet getData(String statement, ArrayList<Object> arguments) throws SQLException, Throwable + { + TestObject testObject = null; + testObject = monitor.registerRequest(); + + Connection connection = null; + try { + connection = this.getConnection(); + if(connection == null ) { + throw new SQLException("Connection invalid"); + } + if(LOGGER.isDebugEnabled()) + LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString()); + return executePreparedStatement(connection, statement, arguments, true); + } finally { + try { + if(connection != null && !connection.isClosed()) { + connection.close(); + } + } catch(Throwable exc) { + // the exception not monitored + } finally { + connection = null; + } + + monitor.deregisterReguest(testObject); + } + } + + public boolean writeData(String statement, ArrayList<Object> arguments) throws SQLException, Throwable + { + TestObject testObject = null; + testObject = monitor.registerRequest(); + + Connection connection = null; + try { + connection = this.getConnection(); + if(connection == null ) { + throw new SQLException("Connection invalid"); + } + if(LOGGER.isDebugEnabled()) + LOGGER.debug("Obtained connection <" + connectionName + ">: "+connection.toString()); + return executeUpdatePreparedStatement(connection, statement, arguments, true); + } finally { + try { + if(connection != null && !connection.isClosed()) { + connection.close(); + } + } catch(Throwable exc) { + // the exception not monitored + } finally { + connection = null; + } + + monitor.deregisterReguest(testObject); + } + } + + CachedRowSet executePreparedStatement(Connection conn, String statement, ArrayList<Object> arguments, boolean close) throws SQLException, Throwable + { + long time = System.currentTimeMillis(); + + CachedRowSet data = null; + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL Statement: "+ statement); + if(arguments != null && !arguments.isEmpty()) { + LOGGER.debug("Argunments: "+ Arrays.toString(arguments.toArray())); + } + } + + ResultSet rs = null; + try { + data = RowSetProvider.newFactory().createCachedRowSet(); + PreparedStatement ps = conn.prepareStatement(statement); + if(arguments != null) + { + for(int i = 0, max = arguments.size(); i < max; i++){ + ps.setObject(i+1, arguments.get(i)); + } + } + rs = ps.executeQuery(); + data.populate(rs); + // Point the rowset Cursor to the start + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL SUCCESS. rows returned: " + data.size()+ ", time(ms): "+ (System.currentTimeMillis() - time)); } + } catch(SQLException exc){ + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time)); + } + try { conn.rollback(); } catch(Throwable thr){} + if(arguments != null && !arguments.isEmpty()) { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc); + } else { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc); + } + throw exc; + } catch(Throwable exc){ + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time)); + } + if(arguments != null && !arguments.isEmpty()) { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc); + } else { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc); + } + throw exc; // new SQLException(exc); + } finally { + + try { + if(rs != null){ + rs.close(); + rs = null; + } + } catch(Exception exc){ + + } + try { + if(conn != null && close){ + conn.close(); + conn = null; + } + } catch(Exception exc){ + + } + } + + return data; + } + + boolean executeUpdatePreparedStatement(Connection conn, String statement, ArrayList<Object> arguments, boolean close) throws SQLException, Throwable { + long time = System.currentTimeMillis(); + + CachedRowSet data = null; + + int rs = -1; + try { + data = RowSetProvider.newFactory().createCachedRowSet(); + PreparedStatement ps = conn.prepareStatement(statement); + if(arguments != null) + { + for(int i = 0, max = arguments.size(); i < max; i++){ + if(arguments.get(i) instanceof Blob) { + ps.setBlob(i+1, (Blob)arguments.get(i)); + } else if(arguments.get(i) instanceof Timestamp) { + ps.setTimestamp(i+1, (Timestamp)arguments.get(i)); + } else if(arguments.get(i) instanceof Integer) { + ps.setInt(i+1, (Integer)arguments.get(i)); + } else if(arguments.get(i) instanceof Long) { + ps.setLong(i+1, (Long)arguments.get(i)); + } else if(arguments.get(i) instanceof Date) { + ps.setDate(i+1, (Date)arguments.get(i)); + } else { + ps.setObject(i+1, arguments.get(i)); + } + } + } + rs = ps.executeUpdate(); + // Point the rowset Cursor to the start + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL SUCCESS. rows returned: " + data.size()+ ", time(ms): "+ (System.currentTimeMillis() - time)); + } + } catch(SQLException exc){ + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time)); + } + try { conn.rollback(); } catch(Throwable thr){} + if(arguments != null && !arguments.isEmpty()) { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc); + } else { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc); + } + throw exc; + } catch(Throwable exc){ + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL FAILURE. time(ms): "+ (System.currentTimeMillis() - time)); + } + if(arguments != null && !arguments.isEmpty()) { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with arguments: "+arguments.toString(), exc); + } else { + LOGGER.error("<"+connectionName+"> Failed to execute: "+ statement + " with no arguments. ", exc); + } + throw exc; // new SQLException(exc); + } finally { + try { + if(conn != null && close){ + conn.close(); + conn = null; + } + } catch(Exception exc){ + + } + } + + return true; + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) + */ + public Connection getConnection(String username, String password) + throws SQLException + { + return ds.getConnection(username, password); + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#getLogWriter() + */ + public PrintWriter getLogWriter() throws SQLException + { + return ds.getLogWriter(); + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#getLoginTimeout() + */ + public int getLoginTimeout() throws SQLException + { + return ds.getLoginTimeout(); + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter) + */ + public void setLogWriter(PrintWriter out) throws SQLException + { + ds.setLogWriter(out); + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#setLoginTimeout(int) + */ + public void setLoginTimeout(int seconds) throws SQLException + { + ds.setLoginTimeout(seconds); + } + + + public final String getDbConnectionName(){ + return connectionName; + } + + protected final void setDbConnectionName(String name) { + this.connectionName = name; + } + + public void cleanUp(){ + if(ds != null && ds instanceof Closeable) { + try { + ((Closeable)ds).close(); + } catch (IOException e) { + LOGGER.warn(e.getMessage()); + } + } + ds = null; + monitor.deleteObservers(); + monitor.cleanup(); + } + + public boolean isInitialized() { + return initialized; + } + + protected boolean testConnection(){ + return testConnection(false); + } + + protected boolean testConnection(boolean error_level){ + Connection conn = null; + ResultSet rs = null; + Statement stmt = null; + try + { + Boolean readOnly = null; + String hostname = null; + conn = this.getConnection(); + stmt = conn.createStatement(); + rs = stmt.executeQuery("SELECT @@global.read_only, @@global.hostname"); //("SELECT 1 FROM DUAL"); //"select BANNER from SYS.V_$VERSION" + while(rs.next()) + { + readOnly = rs.getBoolean(1); + hostname = rs.getString(2); + + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("SQL DataSource <"+getDbConnectionName() + "> connected to " + hostname + ", read-only is " + readOnly + ", tested successfully "); + } + } + + } catch (Throwable exc) { + if(error_level) { + LOGGER.error("SQL DataSource <" + this.getDbConnectionName() + "> test failed. Cause : " + exc.getMessage()); + } else { + LOGGER.info("SQL DataSource <" + this.getDbConnectionName() + "> test failed. Cause : " + exc.getMessage()); + } + return false; + } finally { + if(rs != null) { + try { + rs.close(); + rs = null; + } catch (SQLException e) { + } + } + if(stmt != null) { + try { + stmt.close(); + stmt = null; + } catch (SQLException e) { + } + } + if(conn !=null){ + try { + conn.close(); + conn = null; + } catch (SQLException e) { + } + } + } + return true; + } + + public boolean isWrapperFor(Class<?> iface) throws SQLException { + return false; + } + + public <T> T unwrap(Class<T> iface) throws SQLException { + return null; + } + + @SuppressWarnings("deprecation") + public void setConnectionCachingEnabled(boolean state) + { +// if(ds != null && ds instanceof OracleDataSource) +// try { +// ((OracleDataSource)ds).setConnectionCachingEnabled(true); +// } catch (SQLException exc) { +// LOGGER.warn("", exc); +// } + } + + public void addObserver(Observer observer) { + monitor.addObserver(observer); + } + + public void deleteObserver(Observer observer) { + monitor.deleteObserver(observer); + } + + public long getInterval() { + return interval; + } + + public long getInitialDelay() { + return initialDelay; + } + + public void setInterval(long value) { + interval = value; + } + + public void setInitialDelay(long value) { + initialDelay = value; + } + + public long getExpectedCompletionTime() { + return expectedCompletionTime; + } + + public void setExpectedCompletionTime(long value) { + expectedCompletionTime = value; + } + + public long getUnprocessedFailoverThreshold() { + return unprocessedFailoverThreshold; + } + + public void setUnprocessedFailoverThreshold(long value) { + this.unprocessedFailoverThreshold = value; + } + + public boolean canTakeOffLine() { + return canTakeOffLine; + } + + public void blockImmediateOffLine() { + canTakeOffLine = false; + final Thread offLineTimer = new Thread() + { + public void run(){ + try { + Thread.sleep(30000L); + }catch(Throwable exc){ + + }finally{ + canTakeOffLine = true; + } + } + }; + offLineTimer.setDaemon(true); + offLineTimer.start(); + } + + /** + * @return the monitor + */ + final SQLExecutionMonitor getMonitor() { + return monitor; + } + + protected boolean isSlave() throws PoolExhaustedException, MySQLNonTransientConnectionException { + CachedRowSet rs = null; + boolean isSlave = true; + String hostname = "UNDETERMINED"; + try { + boolean localSlave = true; + rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList<Object>()); + while(rs.next()) { + localSlave = rs.getBoolean(1); + hostname = rs.getString(2); + } + isSlave = localSlave; + } catch(PoolExhaustedException | MySQLNonTransientConnectionException peexc){ + throw peexc; + } catch (SQLException e) { + LOGGER.error("", e); + isSlave = true; + } catch (Throwable e) { + LOGGER.error("", e); + isSlave = true; + } + if(isSlave){ + LOGGER.debug("SQL SLAVE : "+connectionName + " on server " + hostname); + } else { + LOGGER.debug("SQL MASTER : "+connectionName + " on server " + hostname); + } + return isSlave; + } + + public boolean isFabric() { + return false; + } + + protected boolean lockTable(Connection conn, String tableName) { + boolean retValue = false; + Statement lock = null; + try { + if(tableName != null) { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Executing 'LOCK TABLES " + tableName + " WRITE' on connection " + conn.toString()); + if("SVC_LOGIC".equals(tableName)) { + Exception e = new Exception(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + LOGGER.debug(sw.toString()); + } + } + lock = conn.createStatement(); + lock.execute("LOCK TABLES " + tableName + " WRITE"); + retValue = true; + } + } catch(Exception exc){ + LOGGER.error("", exc); + retValue = false; + } finally { + try { + lock.close(); + } catch(Exception exc) { + + } + } + return retValue; + } + + protected boolean unlockTable(Connection conn) { + boolean retValue = false; + Statement lock = null; + try { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Executing 'UNLOCK TABLES' on connection " + conn.toString()); + } + lock = conn.createStatement(); + retValue = lock.execute("UNLOCK TABLES"); + } catch(Exception exc){ + LOGGER.error("", exc); + retValue = false; + } finally { + try { + lock.close(); + } catch(Exception exc) { + + } + } + return retValue; + } + + public void getPoolInfo(boolean allocation) { + + } + + public long getNextErrorReportTime() { + return nextErrorReportTime; + } + + public void setNextErrorReportTime(long nextTime) { + this.nextErrorReportTime = nextTime; + } + + public void setGlobalHostName(String hostname) { + this.globalHostName = hostname; + } + + public String getGlobalHostName() { + return globalHostName; + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java new file mode 100644 index 00000000..3e51ed94 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/CachedDataSourceFactory.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + + +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.jdbc.JdbcDBCachedDataSource; +import org.openecomp.sdnc.sli.resource.dblib.jdbc.MySQLCachedDataSource; + +/** + * @version $Revision: 1.1 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ +public class CachedDataSourceFactory { + + public static CachedDataSource createDataSource(BaseDBConfiguration config) { + if(config instanceof JDBCConfiguration) + return JdbcDBCachedDataSource.createInstance(config); + + return (CachedDataSource)null; + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java new file mode 100644 index 00000000..b324e6a2 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBConfigException.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + + +/** + * @version $Revision: 1.1 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ +public class DBConfigException extends RuntimeException +{ + /** + * + */ + private static final long serialVersionUID = 4752405152537680257L; + + public DBConfigException(Exception e) + { + super(e.toString()); + } + + public DBConfigException(String msg) + { + super(msg); + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java new file mode 100644 index 00000000..150a9a82 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLIBResourceActivator.java @@ -0,0 +1,130 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.io.File; +import java.net.URL; +import java.util.Properties; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DBLIBResourceActivator implements BundleActivator { + + private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; + + private static final String DBLIB_PROP_PATH = "/dblib.properties"; + + private ServiceRegistration registration = null; + + private static final Logger LOG = LoggerFactory.getLogger(DBLIBResourceActivator.class); + + @Override + public void start(BundleContext ctx) throws Exception { + LOG.info("entering DBLIBResourceActivator.start"); + + DbLibService jdbcDataSource = null; + // Read properties + Properties props = new Properties(); + + File file = null; + URL propURL = null; + String propDir = System.getenv(SDNC_CONFIG_DIR); + if ((propDir == null) || (propDir.length() == 0)) { + propDir = "/opt/sdnc/data/properties"; + } + file = new File(propDir + DBLIB_PROP_PATH); + if(file.exists()) { + propURL = file.toURI().toURL(); + LOG.info("Using property file (1): " + file.toString()); + } else { + propURL = ctx.getBundle().getResource("dblib.properties"); + URL tmp = null; + if (propURL == null) { + file = new File(DBLIB_PROP_PATH); + tmp = this.getClass().getResource(DBLIB_PROP_PATH); +// if(!file.exists()) { + if(tmp == null) { + throw new DblibConfigurationException("Missing configuration properties resource(3) : " + DBLIB_PROP_PATH); + } else { + propURL = tmp; //file.toURI().toURL(); + LOG.info("Using property file (4): " + file.toString()); + } + } else { + LOG.info("Using property file (2): " + propURL.toString()); + } + } + + + try { + props.load(propURL.openStream()); + } catch (Exception e) { + throw new DblibConfigurationException("Could not load properties at URL " + propURL.toString(), e); + + } + + + + try { + jdbcDataSource = DBResourceManager.create(props); + } catch (Exception exc) { + throw new DblibConfigurationException("Could not get initialize database", exc); + } + + String regName = jdbcDataSource.getClass().getName(); + + LOG.info("Registering DBResourceManager service "+regName); + registration = ctx.registerService(new String[] { regName, DbLibService.class.getName(), "javax.sql.DataSource" }, jdbcDataSource, null); + } + + @Override + public void stop(BundleContext ctx) throws Exception { + LOG.info("entering DBLIBResourceActivator.stop"); + if (registration != null) + { + try { + ServiceReference sref = ctx.getServiceReference(DbLibService.class.getName()); + + if (sref == null) { + LOG.warn("Could not find service reference for DBLIB service (" + DbLibService.class.getName() + ")"); + } else { + DBResourceManager dblibSvc = (DBResourceManager) ctx.getService(sref); + if (dblibSvc == null) { + LOG.warn("Could not find service reference for DBLIB service (" + DbLibService.class.getName() + ")"); + } else { + dblibSvc.cleanUp(); + } + } + } catch(Throwable exc) { + LOG.warn("Cleanup", exc); + } + + registration.unregister(); + registration = null; + LOG.debug("Deregistering DBResourceManager service"); + } + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java new file mode 100644 index 00000000..5c1f5104 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibConnection.java @@ -0,0 +1,390 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.ArrayList; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +import javax.sql.rowset.CachedRowSet; + +import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.ProxyConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DBLibConnection implements Connection { + + private static Logger LOGGER = LoggerFactory.getLogger(DBLibConnection.class); + + private final Connection connection; + private final CachedDataSource dataSource; + private boolean locked = false; + private String tableName = null; + + public DBLibConnection(Connection con, CachedDataSource dataSource){ + this.connection = con; + this.dataSource = dataSource; + locked = false; + dataSource.getPoolInfo(true); + } + + public boolean lockTable(String tablename) { + this.tableName = tablename; + return locked = dataSource.lockTable(connection, tableName); + } + + public void resetInactivityTimer() { + Class<org.apache.tomcat.jdbc.pool.PooledConnection> iface = PooledConnection.class; + try { + PooledConnection pc = connection.unwrap(iface); + pc.setTimestamp(System.currentTimeMillis()); + } catch (SQLException e) { + LOGGER.warn("Failed resetting timeout timer", e); + } + } + + public boolean unlock() { + dataSource.unlockTable(connection); + return locked = false; + } + + public boolean writeData(String statement, ArrayList<String> arguments) throws SQLException, Throwable + { + ArrayList<Object> newList=new ArrayList<Object>(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + resetInactivityTimer(); + return dataSource.executeUpdatePreparedStatement(connection, statement, newList, false); + } + + public CachedRowSet getData(String statement, ArrayList<String> arguments) throws SQLException, Throwable + { + ArrayList<Object> newList=new ArrayList<Object>(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + resetInactivityTimer(); + return dataSource.executePreparedStatement(connection, statement, newList, false); + } + + @Override + public <T> T unwrap(Class<T> iface) throws SQLException { + return connection.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class<?> iface) throws SQLException { + return connection.isWrapperFor(iface); + } + + @Override + public Statement createStatement() throws SQLException { + return connection.createStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return connection.prepareStatement(sql); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return connection.prepareCall(sql); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + return connection.nativeSQL(sql); + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + connection.setAutoCommit(autoCommit); + } + + @Override + public boolean getAutoCommit() throws SQLException { + return connection.getAutoCommit(); + } + + @Override + public void commit() throws SQLException { + connection.commit(); + } + + @Override + public void rollback() throws SQLException { + connection.rollback(); + } + + @Override + public void close() throws SQLException { + if(this.locked) { + try { + this.unlock(); + } catch(Throwable th) { + LOGGER.error("Failed unlocking",th); + } + } + if(connection != null && !connection.isClosed()) { + connection.close(); + } + dataSource.getPoolInfo(false); + } + + @Override + public boolean isClosed() throws SQLException { + return connection.isClosed(); + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return connection.getMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + connection.setReadOnly(readOnly); + } + + @Override + public boolean isReadOnly() throws SQLException { + return connection.isReadOnly(); + } + + @Override + public void setCatalog(String catalog) throws SQLException { + connection.setCatalog(catalog); + } + + @Override + public String getCatalog() throws SQLException { + return connection.getCatalog(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + connection.setTransactionIsolation(level); + } + + @Override + public int getTransactionIsolation() throws SQLException { + return connection.getTransactionIsolation(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return connection.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + connection.clearWarnings(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return connection.createStatement(resultSetType, resultSetConcurrency); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return connection.prepareCall(sql, resultSetType, resultSetConcurrency); + } + + @Override + public Map<String, Class<?>> getTypeMap() throws SQLException { + return connection.getTypeMap(); + } + + @Override + public void setTypeMap(Map<String, Class<?>> map) throws SQLException { + connection.setTypeMap(map); + } + + @Override + public void setHoldability(int holdability) throws SQLException { + connection.setHoldability(holdability); + } + + @Override + public int getHoldability() throws SQLException { + return connection.getHoldability(); + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return connection.setSavepoint(); + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return connection.setSavepoint(name); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + connection.rollback(savepoint); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + connection.releaseSavepoint(savepoint); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return connection.prepareStatement(sql, autoGeneratedKeys); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return connection.prepareStatement(sql, columnIndexes); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return connection.prepareStatement(sql, columnNames); + } + + @Override + public Clob createClob() throws SQLException { + return connection.createClob(); + } + + @Override + public Blob createBlob() throws SQLException { + return connection.createBlob(); + } + + @Override + public NClob createNClob() throws SQLException { + return connection.createNClob(); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return connection.createSQLXML(); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return connection.isValid(timeout); + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + connection.setClientInfo(name, value); + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + connection.setClientInfo(properties); + } + + @Override + public String getClientInfo(String name) throws SQLException { + return connection.getClientInfo(name); + } + + @Override + public Properties getClientInfo() throws SQLException { + return connection.getClientInfo(); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return connection.createArrayOf(typeName, elements); + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return connection.createStruct(typeName, attributes); + } + + @Override + public void setSchema(String schema) throws SQLException { + connection.setSchema(schema); + } + + @Override + public String getSchema() throws SQLException { + return connection.getSchema(); + } + + @Override + public void abort(Executor executor) throws SQLException { + connection.abort(executor); + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + connection.setNetworkTimeout(executor, milliseconds); + } + + @Override + public int getNetworkTimeout() throws SQLException { + return connection.getNetworkTimeout(); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibException.java new file mode 100644 index 00000000..cc80741d --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBLibException.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.SQLException; + +/** + * An exception time for handling DBLIB specific error handling. + */ +public class DBLibException extends SQLException { + + /** + * + */ + private static final long serialVersionUID = -5345059355083984696L; + + public DBLibException(String message){ + super(message); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java new file mode 100644 index 00000000..5cf2953b --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceManager.java @@ -0,0 +1,862 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLDataException; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLIntegrityConstraintViolationException; +import java.sql.SQLSyntaxErrorException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Observable; +import java.util.PriorityQueue; +import java.util.Properties; +import java.util.Queue; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.sql.DataSource; +import javax.sql.rowset.CachedRowSet; + +import org.apache.tomcat.jdbc.pool.PoolExhaustedException; +import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool; +import org.openecomp.sdnc.sli.resource.dblib.factory.AbstractDBResourceManagerFactory; +import org.openecomp.sdnc.sli.resource.dblib.factory.AbstractResourceManagerFactory; +import org.openecomp.sdnc.sli.resource.dblib.factory.DBConfigFactory; +import org.openecomp.sdnc.sli.resource.dblib.pm.PollingWorker; +import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitor; +import com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * @version $Revision: 1.15 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ +public class DBResourceManager implements DataSource, DataAccessor, DBResourceObserver, DbLibService { + private static Logger LOGGER = LoggerFactory.getLogger(DBResourceManager.class); + + transient boolean terminating = false; + transient protected long retryInterval = 10000L; + transient boolean recoveryMode = true; + + protected final AtomicBoolean dsSelector = new AtomicBoolean(); + +// Queue<CachedDataSource> dsQueue = new ConcurrentLinkedQueue<CachedDataSource>(); + Queue<CachedDataSource> dsQueue = new PriorityQueue<CachedDataSource>(4, new Comparator<CachedDataSource>(){ + + @Override + public int compare(CachedDataSource left, CachedDataSource right) { + try { + if(!left.isSlave()) + return -1; + if(!right.isSlave()) + return 1; + + } catch (Throwable e) { + LOGGER.warn("", e); + } + return 0; + } + + }); + protected final Set<CachedDataSource> broken = Collections.synchronizedSet(new HashSet<CachedDataSource>()); + protected final Object monitor = new Object(); + protected final Properties configProps; + protected final Thread worker; + + protected final long terminationTimeOut; + protected final boolean monitorDbResponse; + protected final long monitoringInterval; + protected final long monitoringInitialDelay; + protected final long expectedCompletionTime; + protected final long unprocessedFailoverThreshold; + + public DBResourceManager(Properties props){ + this.configProps = props; + + // get retry interval value + retryInterval = getLongFromProperties(props, "org.openecomp.dblib.connection.retry", 10000L); + + // get recovery mode flag + recoveryMode = getBooleanFromProperties(props, "org.openecomp.dblib.connection.recovery", true); + if(!recoveryMode) + { + recoveryMode = false; + LOGGER.info("Recovery Mode disabled"); + } + // get time out value for thread cleanup + terminationTimeOut = getLongFromProperties(props, "org.openecomp.dblib.termination.timeout", 300000L); + // get properties for monitoring + monitorDbResponse = getBooleanFromProperties(props, "org.openecomp.dblib.connection.monitor", false); + monitoringInterval = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.interval", 1000L); + monitoringInitialDelay = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.startdelay", 5000L); + expectedCompletionTime = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.expectedcompletiontime", 5000L); + unprocessedFailoverThreshold = getLongFromProperties(props, "org.openecomp.dblib.connection.monitor.unprocessedfailoverthreshold", 3L); + + // initialize performance monitor + PollingWorker.createInistance(props); + + // initialize recovery thread + worker = new RecoveryMgr(); + worker.setName("DBResourcemanagerWatchThread"); + worker.setDaemon(true); + worker.start(); + } + + private void config(Properties ctx) throws Exception { + + DbConfigPool dbConfig = DBConfigFactory.createConfig(this.configProps); + + try { + AbstractResourceManagerFactory factory = AbstractDBResourceManagerFactory.getFactory(dbConfig.getType()); + if(LOGGER.isInfoEnabled()){ + LOGGER.info("Default DB config is : " + dbConfig.getType()); + LOGGER.info("Using factory : " + factory.getClass().getName()); + } + CachedDataSource[] cachedDS = factory.initDBResourceManager(dbConfig, this); + if(cachedDS == null || cachedDS.length == 0) { + LOGGER.error("Initialization of CachedDataSources failed. No instance was created."); + throw new Exception("Failed to initialize DB Library. No data source was created."); + } + + for(int i=0; i<cachedDS.length; i++){ + if(cachedDS[i] != null && cachedDS[i].isInitialized()){ + setDataSource(cachedDS[i]); + cachedDS[i].setInterval(monitoringInterval); + cachedDS[i].setInitialDelay(monitoringInitialDelay); + cachedDS[i].setExpectedCompletionTime(expectedCompletionTime); + cachedDS[i].setUnprocessedFailoverThreshold(unprocessedFailoverThreshold); + cachedDS[i].addObserver(this); + } + } + + } catch(Exception exc){ + throw exc; + } + } + + private long getLongFromProperties(Properties props, String property, long defaultValue) + { + String value = null; + long tmpLongValue = defaultValue; + try { + value = (String)props.getProperty(property); + if(value != null) + tmpLongValue = Long.parseLong(value); + + } catch(NumberFormatException exc) { + if(LOGGER.isWarnEnabled()){ + LOGGER.warn("'"+property+"'=" + value+" is invalid. It should be a numeric value"); + } + } catch(Exception exc) { + } + return tmpLongValue; + + } + + private boolean getBooleanFromProperties(Properties props, String property, boolean defaultValue) + { + boolean tmpValue = defaultValue; + String value = null; + + try { + value = (String)props.getProperty(property); + if(value != null) + tmpValue = Boolean.parseBoolean(value); + + } catch(NumberFormatException exc) { + if(LOGGER.isWarnEnabled()){ + LOGGER.warn("'"+property+"'=" + value+" is invalid. It should be a boolean value"); + } + } catch(Exception exc) { + } + return tmpValue; + + } + + + public void update(Observable observable, Object data) { + // if observable is active and there is a standby available, switch + if(observable instanceof SQLExecutionMonitor) + { + SQLExecutionMonitor monitor = (SQLExecutionMonitor)observable; + if(monitor.getParent() instanceof CachedDataSource) + { + CachedDataSource dataSource = (CachedDataSource)monitor.getParent(); + if(dataSource == dsQueue.peek()) + { + if(recoveryMode && dsQueue.size() > 1){ + handleGetConnectionException(dataSource, new Exception(data.toString())); + } + } + } + } + } + + public void testForceRecovery() + { + CachedDataSource active = (CachedDataSource) this.dsQueue.peek(); + handleGetConnectionException(active, new Exception("test")); + } + + class RecoveryMgr extends Thread { + + public void run() { + while(!terminating) + { + try { + Thread.sleep(retryInterval); + } catch (InterruptedException e1) { } + CachedDataSource brokenSource = null; + try { + if (!broken.isEmpty()) { + CachedDataSource[] sourceArray = broken.toArray(new CachedDataSource[0]); + for (int i = 0; i < sourceArray.length; i++) + { + brokenSource = sourceArray[i]; + if (brokenSource instanceof TerminatingCachedDataSource) + break; + if (resetConnectionPool(brokenSource)) { + broken.remove(brokenSource); + brokenSource.blockImmediateOffLine(); + dsQueue.add(brokenSource); + LOGGER.info("DataSource <" + + brokenSource.getDbConnectionName() + + "> recovered."); + } + brokenSource = null; + } + } + } catch (Exception exc) { + LOGGER.warn(exc.getMessage()); + if(brokenSource != null){ + try { + if(!broken.contains(brokenSource)) + broken.add(brokenSource); + brokenSource = null; + } catch (Exception e1) { } + } + } + } + LOGGER.info("DBResourceManager.RecoveryMgr <"+this.toString() +"> terminated." ); + } + + private boolean resetConnectionPool(CachedDataSource dataSource){ + try { + return dataSource.testConnection(); + } catch (Exception exc) { + LOGGER.info("DataSource <" + dataSource.getDbConnectionName() + "> resetCache failed with error: "+ exc.getMessage()); + return false; + } + } + } + + /* (non-Javadoc) + * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#getData(java.lang.String, java.util.ArrayList, java.lang.String) + */ + @Override + public CachedRowSet getData(String statement, ArrayList<String> arguments, String preferredDS) throws SQLException { + ArrayList<Object> newList=new ArrayList<Object>(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + if(recoveryMode) + return requestDataWithRecovery(statement, newList, preferredDS); + else + return requestDataNoRecovery(statement, newList, preferredDS); + } + + private CachedRowSet requestDataWithRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException { + Throwable lastException = null; + CachedDataSource active = null; + + // test if there are any connection pools available + LinkedList<CachedDataSource> sources = new LinkedList<CachedDataSource>(this.dsQueue); + if(sources.isEmpty()){ + LOGGER.error("Generated alarm: DBResourceManager.getData - No active DB connection pools are available."); + throw new DBLibException("No active DB connection pools are available in RequestDataWithRecovery call."); + } + if(preferredDS != null && !sources.peek().getDbConnectionName().equals(preferredDS)) { + Collections.reverse(sources); + } + + + // loop through available data sources to retrieve data. + while(!sources.isEmpty()) + { + active = sources.peek(); + + long time = System.currentTimeMillis(); + try { + if(!active.isFabric()) { + CachedDataSource master = findMaster(); + if(master != null) { + active = master; + master = null; + } + } + sources.remove(active); + return active.getData(statement, arguments); + } catch(SQLDataException exc){ + throw exc; + } catch(SQLSyntaxErrorException exc){ + throw exc; + } catch(SQLIntegrityConstraintViolationException exc){ + throw exc; + } catch(Throwable exc){ + lastException = exc; + String message = exc.getMessage(); + if(message == null) { + if(exc.getCause() != null) { + message = exc.getCause().getMessage(); + } + if(message == null) + message = exc.getClass().getName(); + } + LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message); + handleGetConnectionException(active, exc); + } finally { + if(LOGGER.isDebugEnabled()){ + time = (System.currentTimeMillis() - time); + LOGGER.debug("getData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + } + } + } + if(lastException instanceof SQLException){ + throw (SQLException)lastException; + } + // repackage the exception + // you are here because either you run out of available data sources + // or the last exception was not of SQLException type. + // repackage the exception + if(lastException == null) { + throw new DBLibException("The operation timed out while waiting to acquire a new connection." ); + } else { + SQLException exception = new DBLibException(lastException.getMessage()); + exception.setStackTrace(lastException.getStackTrace()); + if(lastException.getCause() instanceof SQLException) { + throw (SQLException)lastException.getCause(); + } + throw exception; + } + } + + private CachedRowSet requestDataNoRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException { + if(dsQueue.isEmpty()){ + LOGGER.error("Generated alarm: DBResourceManager.getData - No active DB connection pools are available."); + throw new DBLibException("No active DB connection pools are available in RequestDataNoRecovery call."); + } + CachedDataSource active = (CachedDataSource) this.dsQueue.peek(); + long time = System.currentTimeMillis(); + try { + if(!active.isFabric()) { + CachedDataSource master = findMaster(); + if(master != null) + active = master; + } + return active.getData(statement, arguments); +// } catch(SQLDataException exc){ +// throw exc; + } catch(Throwable exc){ + String message = exc.getMessage(); + if(message == null) + message = exc.getClass().getName(); + LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message); + if(exc instanceof SQLException) + throw (SQLException)exc; + else { + DBLibException excptn = new DBLibException(exc.getMessage()); + excptn.setStackTrace(exc.getStackTrace()); + throw excptn; + } + } finally { + if(LOGGER.isDebugEnabled()){ + time = (System.currentTimeMillis() - time); + LOGGER.debug(">> getData : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + } + } + } + + + /* (non-Javadoc) + * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#writeData(java.lang.String, java.util.ArrayList, java.lang.String) + */ + @Override + public boolean writeData(String statement, ArrayList<String> arguments, String preferredDS) throws SQLException + { + ArrayList<Object> newList=new ArrayList<Object>(); + if(arguments != null && !arguments.isEmpty()) { + newList.addAll(arguments); + } + + return writeDataNoRecovery(statement, newList, preferredDS); + } + + CachedDataSource findMaster() throws PoolExhaustedException, MySQLNonTransientConnectionException { + CachedDataSource master = null; + CachedDataSource[] dss = this.dsQueue.toArray(new CachedDataSource[0]); + for(int i=0; i<dss.length; i++) { + if(!dss[i].isSlave()) { + master = dss[i]; + if(i != 0) { + dsQueue.remove(master); + dsQueue.add(master); + } + return master; + } + } + if(master == null) { + LOGGER.warn("MASTER not found."); + } + return master; + } + + + private boolean writeDataNoRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException { + if(dsQueue.isEmpty()){ + LOGGER.error("Generated alarm: DBResourceManager.getData - No active DB connection pools are available."); + throw new DBLibException("No active DB connection pools are available in RequestDataNoRecovery call."); + } + + boolean initialRequest = true; + boolean retryAllowed = true; + CachedDataSource active = (CachedDataSource) this.dsQueue.peek(); + long time = System.currentTimeMillis(); + while(initialRequest) { + initialRequest = false; + try { + if(!active.isFabric()) { + CachedDataSource master = findMaster(); + if(master != null) { + active = master; + } + } + + return active.writeData(statement, arguments); + } catch(Throwable exc){ + String message = exc.getMessage(); + if(message == null) + message = exc.getClass().getName(); + LOGGER.error("Generated alarm: "+active.getDbConnectionName()+" - "+message); + if(exc instanceof SQLException) { + SQLException sqlExc = SQLException.class.cast(exc); + // handle read-only exception + if(sqlExc.getErrorCode() == 1290 && "HY000".equals(sqlExc.getSQLState())) { + LOGGER.warn("retrying due to: " + sqlExc.getMessage()); + dsQueue.remove(active); + dsQueue.add(active); + if(retryAllowed){ + retryAllowed = false; + initialRequest = true; + continue; + } + } + throw (SQLException)exc; + } else { + DBLibException excptn = new DBLibException(exc.getMessage()); + excptn.setStackTrace(exc.getStackTrace()); + throw excptn; + } + } finally { + if(LOGGER.isDebugEnabled()){ + time = (System.currentTimeMillis() - time); + LOGGER.debug("writeData processing time : "+ active.getDbConnectionName()+" "+time+" miliseconds."); + } + } + } + return true; + } + + private void setDataSource(CachedDataSource dataSource) { + if(dataSource.testConnection(true)){ + this.dsQueue.add(dataSource); + } else { + this.broken.add(dataSource); + } + } + + public Connection getConnection() throws SQLException { + Throwable lastException = null; + CachedDataSource active = null; + + if(dsQueue.isEmpty()){ + throw new DBLibException("No active DB connection pools are available in GetConnection call."); + } + + try { + active = dsQueue.peek(); + CachedDataSource tmpActive = findMaster(); + if(tmpActive != null) { + active = tmpActive; + } + return new DBLibConnection(active.getConnection(), active); + } catch(javax.sql.rowset.spi.SyncFactoryException exc){ + LOGGER.debug("Free memory (bytes): " + Runtime.getRuntime().freeMemory()); + LOGGER.warn("CLASSPATH issue. Allowing retry", exc); + lastException = exc; + } catch(PoolExhaustedException exc) { + throw new NoAvailableConnectionsException(exc); + } catch(MySQLNonTransientConnectionException exc){ + throw new NoAvailableConnectionsException(exc); + } catch(Exception exc){ + lastException = exc; + if(recoveryMode){ + handleGetConnectionException(active, exc); + } else { + if(exc instanceof MySQLNonTransientConnectionException) { + throw new NoAvailableConnectionsException(exc); + } if(exc instanceof SQLException) { + throw (SQLException)exc; + } else { + DBLibException excptn = new DBLibException(exc.getMessage()); + excptn.setStackTrace(exc.getStackTrace()); + throw excptn; + } + } + } catch (Throwable trwb) { + DBLibException excptn = new DBLibException(trwb.getMessage()); + excptn.setStackTrace(trwb.getStackTrace()); + throw excptn; + } finally { + if(LOGGER.isDebugEnabled()){ + displayState(); + } + } + + if(lastException instanceof SQLException){ + throw (SQLException)lastException; + } + // repackage the exception + if(lastException == null) { + throw new DBLibException("The operation timed out while waiting to acquire a new connection." ); + } else { + SQLException exception = new DBLibException(lastException.getMessage()); + exception.setStackTrace(lastException.getStackTrace()); + if(lastException.getCause() instanceof SQLException) { +// exception.setNextException((SQLException)lastException.getCause()); + throw (SQLException)lastException.getCause(); + } + throw exception; + } + } + + public Connection getConnection(String username, String password) + throws SQLException { + CachedDataSource active = null; + + if(dsQueue.isEmpty()){ + throw new DBLibException("No active DB connection pools are available in GetConnection call."); + } + + + try { + active = dsQueue.peek(); + CachedDataSource tmpActive = findMaster(); + if(tmpActive != null) { + active = tmpActive; + } + return active.getConnection(username, password); + } catch(Throwable exc){ + if(recoveryMode){ + handleGetConnectionException(active, exc); + } else { + if(exc instanceof SQLException) + throw (SQLException)exc; + else { + DBLibException excptn = new DBLibException(exc.getMessage()); + excptn.setStackTrace(exc.getStackTrace()); + throw excptn; + } + } + + } + + throw new DBLibException("No connections available in DBResourceManager in GetConnection call."); + } + + private void handleGetConnectionException(CachedDataSource source, Throwable exc) { + try { + if(!source.canTakeOffLine()) + { + LOGGER.error("Could not switch due to blocking"); + return; + } + + boolean removed = dsQueue.remove(source); + if(!broken.contains(source)) + { + if(broken.add(source)) + { + LOGGER.warn("DB Recovery: DataSource <" + source.getDbConnectionName() + "> put in the recovery mode. Reason : " + exc.getMessage()); + } else { + LOGGER.warn("Error putting DataSource <" +source.getDbConnectionName()+ "> in recovery mode."); + } + } else { + LOGGER.info("DB Recovery: DataSource <" + source.getDbConnectionName() + "> already in recovery queue"); + } + if(removed) + { + if(!dsQueue.isEmpty()) + { + LOGGER.warn("DB DataSource <" + dsQueue.peek().getDbConnectionName() + "> became active"); + } + } + } catch (Exception e) { + LOGGER.error("", e); + } + } + + public void cleanUp() { + for(Iterator<CachedDataSource> it=dsQueue.iterator();it.hasNext();){ + CachedDataSource cds = (CachedDataSource)it.next(); + it.remove(); + cds.cleanUp(); + } + + try { + this.terminating = true; + if(broken != null) + { + try { + broken.add( new TerminatingCachedDataSource(null)); + } catch(Exception exc){ + LOGGER.error("Waiting for Worker to stop", exc); + } + } + worker.join(terminationTimeOut); + LOGGER.info("DBResourceManager.RecoveryMgr <"+worker.toString() +"> termination was successful: " + worker.getState()); + } catch(Exception exc){ + LOGGER.error("Waiting for Worker thread to terminate ", exc); + } + } + + public static DBResourceManager create(Properties props) throws Exception { + DBResourceManager dbmanager = new DBResourceManager(props); + dbmanager.config(props); + return dbmanager; + } + + public PrintWriter getLogWriter() throws SQLException { + return ((CachedDataSource)this.dsQueue.peek()).getLogWriter(); + } + + public int getLoginTimeout() throws SQLException { + return ((CachedDataSource)this.dsQueue.peek()).getLoginTimeout(); + } + + public void setLogWriter(PrintWriter out) throws SQLException { + ((CachedDataSource)this.dsQueue.peek()).setLogWriter(out); + } + + public void setLoginTimeout(int seconds) throws SQLException { + ((CachedDataSource)this.dsQueue.peek()).setLoginTimeout(seconds); + } + + public void displayState(){ + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("POOLS : Active = "+dsQueue.size() + ";\t Broken = "+broken.size()); + CachedDataSource current = (CachedDataSource)dsQueue.peek(); + if(current != null) { + LOGGER.debug("POOL : Active name = \'"+current.getDbConnectionName()+ "\'"); + } + } + } + + /* (non-Javadoc) + * @see org.openecomp.sdnc.sli.resource.dblib.DbLibService#isActive() + */ + @Override + public boolean isActive() { + return this.dsQueue.size()>0; + } + + public String getActiveStatus(){ + return "Connected: " + dsQueue.size()+"\tIn-recovery: "+broken.size(); + } + + public String getDBStatus(boolean htmlFormat) { + StringBuilder buffer = new StringBuilder(); + + ArrayList<CachedDataSource> list = new ArrayList<CachedDataSource>(); + list.addAll(dsQueue); + list.addAll(broken); + if (htmlFormat) + { + buffer.append("<tr class=\"headerRow\"><th id=\"header1\">") + .append("Name:").append("</th>"); + for (int i = 0; i < list.size(); i++) { + buffer.append("<th id=\"header").append(2 + i).append("\">"); + buffer.append(((CachedDataSource) list.get(i)).getDbConnectionName()).append("</th>"); + } + buffer.append("</tr>"); + + buffer.append("<tr><td>State:</td>"); + for (int i = 0; i < list.size(); i++) { + if (broken.contains(list.get(i))) { + buffer.append("<td>in recovery</td>"); + } + if (dsQueue.contains(list.get(i))) { + if (dsQueue.peek() == list.get(i)) + buffer.append("<td>active</td>"); + else + buffer.append("<td>standby</td>"); + } + } + buffer.append("</tr>"); + + } else { + for (int i = 0; i < list.size(); i++) { + buffer.append("Name: ").append(((CachedDataSource) list.get(i)).getDbConnectionName()); + buffer.append("\tState: "); + if (broken.contains(list.get(i))) { + buffer.append("in recovery"); + } else + if (dsQueue.contains(list.get(i))) { + if (dsQueue.peek() == list.get(i)) + buffer.append("active"); + else + buffer.append("standby"); + } + + buffer.append("\n"); + + } + } + return buffer.toString(); + } + + public boolean isWrapperFor(Class<?> iface) throws SQLException { + return false; + } + + public <T> T unwrap(Class<T> iface) throws SQLException { + return null; + } + + /** + * @return the monitorDbResponse + */ + public final boolean isMonitorDbResponse() { + return recoveryMode && monitorDbResponse; + } + + public void test(){ + CachedDataSource obj = dsQueue.peek(); + Exception ption = new Exception(); + try { + for(int i=0; i<5; i++) + { + handleGetConnectionException(obj, ption); + } + } catch(Throwable exc){ + LOGGER.warn("", exc); + } + } + + public String getPreferredDSName(){ + if(isActive()){ + return getPreferredDataSourceName(dsSelector); + } + return ""; + } + + public String getPreferredDataSourceName(AtomicBoolean flipper) { + + LinkedList<CachedDataSource> snapshot = new LinkedList<CachedDataSource>(dsQueue); + if(snapshot.size() > 1){ + CachedDataSource first = snapshot.getFirst(); + CachedDataSource last = snapshot.getLast(); + + int delta = first.getMonitor().getPorcessedConnectionsCount() - last.getMonitor().getPorcessedConnectionsCount(); + if(delta < 0) { + flipper.set(false); + } else if(delta > 0) { + flipper.set(true); + } else { + // check the last value and return !last + flipper.getAndSet(!flipper.get()); + } + + if (flipper.get()) + Collections.reverse(snapshot); + } + return snapshot.peek().getDbConnectionName(); + } + + public java.util.logging.Logger getParentLogger() + throws SQLFeatureNotSupportedException { + return null; + } + + public String getMasterName() { + if(isActive()){ + return getMasterDataSourceName(dsSelector); + } + return ""; + } + + + private String getMasterDataSourceName(AtomicBoolean flipper) { + + LinkedList<CachedDataSource> snapshot = new LinkedList<CachedDataSource>(dsQueue); + if(snapshot.size() > 1){ + CachedDataSource first = snapshot.getFirst(); + CachedDataSource last = snapshot.getLast(); + + int delta = first.getMonitor().getPorcessedConnectionsCount() - last.getMonitor().getPorcessedConnectionsCount(); + if(delta < 0) { + flipper.set(false); + } else if(delta > 0) { + flipper.set(true); + } else { + // check the last value and return !last + flipper.getAndSet(!flipper.get()); + } + + if (flipper.get()) + Collections.reverse(snapshot); + } + return snapshot.peek().getDbConnectionName(); + } + + class RemindTask extends TimerTask { + public void run() { + CachedDataSource ds = dsQueue.peek(); + if(ds != null) + ds.getPoolInfo(false); + } + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceObserver.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceObserver.java new file mode 100644 index 00000000..e06779f3 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DBResourceObserver.java @@ -0,0 +1,27 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.util.Observer; + +public interface DBResourceObserver extends Observer { + public boolean isMonitorDbResponse(); +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java new file mode 100644 index 00000000..cd054a51 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataAccessor.java @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.SQLException; +import java.util.ArrayList; + +import javax.sql.rowset.CachedRowSet; + +public interface DataAccessor { + + public abstract CachedRowSet getData(String statement, ArrayList<String> arguments, String preferredDS) + throws SQLException; + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java new file mode 100644 index 00000000..37d62513 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DataSourceComparator.java @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.util.Comparator; + +public interface DataSourceComparator extends Comparator <CachedDataSource>{ + + public abstract CachedDataSource getLastUsed(); + + public abstract void setLastUsed(CachedDataSource lastUsed); + + public abstract int compare(CachedDataSource ds1, CachedDataSource ds2); + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java new file mode 100644 index 00000000..25edd1f0 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DbLibService.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.SQLException; +import java.util.ArrayList; + +import javax.sql.rowset.CachedRowSet; + +public interface DbLibService { + + /* (non-Javadoc) + * @see DataAccessor#getData(java.lang.String, java.util.ArrayList) + */ + public abstract CachedRowSet getData(String statement, + ArrayList<String> arguments, String preferredDS) + throws SQLException; + + /* (non-Javadoc) + * @see DataAccessor#writeData(java.lang.String, java.util.ArrayList) + */ + public abstract boolean writeData(String statement, + ArrayList<String> arguments, String preferredDS) + throws SQLException; + + public abstract boolean isActive(); + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java new file mode 100644 index 00000000..17700a5e --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/DblibConfigurationException.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + + +public class DblibConfigurationException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public DblibConfigurationException() + { + super(); + } + + public DblibConfigurationException(String msg) + { + super(msg); + } + + public DblibConfigurationException(String msg, Throwable t) + { + super(msg, t); + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java new file mode 100644 index 00000000..16895b4d --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/NoAvailableConnectionsException.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.SQLException; + +public class NoAvailableConnectionsException extends SQLException { + + /** + * + */ + private static final long serialVersionUID = -6259205931674413018L; + + public NoAvailableConnectionsException(Exception exc) { + super(exc); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java new file mode 100644 index 00000000..234bbed0 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/TerminatingCachedDataSource.java @@ -0,0 +1,82 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib; + +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; + +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.pm.SQLExecutionMonitorObserver; + + +public class TerminatingCachedDataSource extends CachedDataSource implements SQLExecutionMonitorObserver { + + public TerminatingCachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException { + super(jdbcElem); + } + + protected void configure(BaseDBConfiguration jdbcElem) throws DBConfigException { + // no action + } + + public long getInterval() { + return 1000; + } + + public long getInitialDelay() { + return 1000; + } + + public long getExpectedCompletionTime() { + return 50; + } + + public void setExpectedCompletionTime(long value) { + + } + + public void setInterval(long value) { + + } + + public void setInitialDelay(long value) { + + } + + public long getUnprocessedFailoverThreshold() { + return 3; + } + + public void setUnprocessedFailoverThreshold(long value) { + + } + + public int compareTo(CachedDataSource ods) + { + return 0; + } + + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java new file mode 100644 index 00000000..976b1cf2 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/BaseDBConfiguration.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.config; + +import java.util.Properties; + +public abstract class BaseDBConfiguration { + public static final String DATABASE_TYPE = "org.openecomp.sdnc.sli.dbtype"; + public static final String DATABASE_URL = "org.openecomp.sdnc.sli.jdbc.url"; + public static final String DATABASE_NAME = "org.openecomp.sdnc.sli.jdbc.database"; + public static final String CONNECTION_NAME = "org.openecomp.sdnc.sli.jdbc.connection.name"; + public static final String DATABASE_USER = "org.openecomp.sdnc.sli.jdbc.user"; + public static final String DATABASE_PSSWD = "org.openecomp.sdnc.sli.jdbc.password"; + public static final String CONNECTION_TIMEOUT="org.openecomp.sdnc.sli.jdbc.connection.timeout"; + public static final String REQUEST_TIMEOUT = "org.openecomp.sdnc.sli.jdbc.request.timeout"; + public static final String MIN_LIMIT = "org.openecomp.sdnc.sli.jdbc.limit.min"; + public static final String MAX_LIMIT = "org.openecomp.sdnc.sli.jdbc.limit.max"; + public static final String INIT_LIMIT = "org.openecomp.sdnc.sli.jdbc.limit.init"; + public static final String DATABASE_HOSTS = "org.openecomp.sdnc.sli.jdbc.hosts"; + + + protected final Properties props; + + public BaseDBConfiguration(Properties properties) { + this.props = properties; + } + + public int getConnTimeout() { + try { + String value = props.getProperty(CONNECTION_TIMEOUT); + return Integer.parseInt(value); + } catch(Exception exc) { + return -1; + } + } + + public int getRequestTimeout() { + try { + String value = props.getProperty(REQUEST_TIMEOUT); + if(value == null) + return -1; + return Integer.parseInt(value); + } catch(Exception exc) { + return -1; + } + } + + public String getDbConnectionName() { + return props.getProperty(CONNECTION_NAME); + } + + public String getDatabaseName() { + return props.getProperty(DATABASE_NAME); + } + + public String getDbUserId() { + return props.getProperty(DATABASE_USER); + } + + public String getDbPasswd() { + return props.getProperty(DATABASE_PSSWD); + } + + public int getDbMinLimit() { + String value = props.getProperty(MIN_LIMIT); + return Integer.parseInt(value); + } + + public int getDbMaxLimit() { + String value = props.getProperty(MAX_LIMIT); + return Integer.parseInt(value); + } + + public int getDbInitialLimit() { + String value = props.getProperty(INIT_LIMIT); + return Integer.parseInt(value); + } + + public String getDbUrl() { + return props.getProperty(DATABASE_URL); + } + + public String getServerGroup() { + return null; + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java new file mode 100644 index 00000000..117f9321 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/DbConfigPool.java @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.config; + +import java.util.ArrayList; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DbConfigPool { + private static Logger LOGGER = LoggerFactory.getLogger(DbConfigPool.class); + + private final String type; + + private ArrayList<BaseDBConfiguration> configurations = new ArrayList<BaseDBConfiguration>(); + + public DbConfigPool(Properties properties) { + LOGGER.debug("Initializing DbConfigType"); + type = properties.getProperty(BaseDBConfiguration.DATABASE_TYPE, "JDBC").toUpperCase(); + } + + public int getTimeout() { + // TODO Auto-generated method stub + return 0; + } + + public String getType() { + return type; + } + + public JDBCConfiguration[] getJDBCbSourceArray() { + return configurations.toArray(new JDBCConfiguration[configurations.size()]); + } + + public void addConfiguration(BaseDBConfiguration config) { + configurations.add(config); + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java new file mode 100644 index 00000000..cb6ea3e5 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/config/JDBCConfiguration.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.config; + +import java.util.Properties; + +public class JDBCConfiguration extends BaseDBConfiguration { + + public JDBCConfiguration(Properties xmlElem) { + super(xmlElem); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java new file mode 100644 index 00000000..f4291a7d --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractDBResourceManagerFactory.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.factory; + +import org.openecomp.sdnc.sli.resource.dblib.jdbc.JdbcDbResourceManagerFactory; + +/** + * @version $Revision: 1.1 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ +public class AbstractDBResourceManagerFactory { + + public static AbstractResourceManagerFactory getFactory(String type) throws FactoryNotDefinedException { + + // JDBC + return JdbcDbResourceManagerFactory.createIntstance(); + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java new file mode 100644 index 00000000..0f58a3f0 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/AbstractResourceManagerFactory.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.factory; + + +import java.sql.SQLException; +import java.util.Set; +import java.util.concurrent.Callable; + +import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource; +import org.openecomp.sdnc.sli.resource.dblib.CachedDataSourceFactory; +import org.openecomp.sdnc.sli.resource.dblib.DBConfigException; +import org.openecomp.sdnc.sli.resource.dblib.DBResourceManager; +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool; +import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @version $Revision: 1.6 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ +public abstract class AbstractResourceManagerFactory { + private static Logger LOGGER = LoggerFactory.getLogger(AbstractResourceManagerFactory.class); + + public abstract CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager) throws Exception; + public abstract CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager dbResourceManager, String sourceName) throws SQLException ; + + + public static AbstractResourceManagerFactory createIntstance() throws FactoryNotDefinedException { + throw new FactoryNotDefinedException("Factory method 'createIntstance' needs to be overriden in DBResourceManagerFactory"); + } + + public class DBInitTask implements Callable<CachedDataSource> + { + private BaseDBConfiguration config = null; + private Set<DBInitTask> activeTasks; + + public DBInitTask(JDBCConfiguration jdbcconfig, Set<DBInitTask> tasks) { + this.config = jdbcconfig; + this.activeTasks = tasks; + } + + public CachedDataSource call() throws Exception { + CachedDataSource ds = null; + try { + ds = CachedDataSourceFactory.createDataSource(config); + return ds; + } finally { + synchronized(activeTasks) { + activeTasks.remove(this); + if (activeTasks.isEmpty()) { + final Runnable closure = new Runnable() { + + public void run() { + try { + Thread.sleep(300); + } catch (Exception e) { + } + synchronized(activeTasks) { + activeTasks.notifyAll(); + } + } + }; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Completed CachedDataSource.Call and notifyAll from " + ds.getDbConnectionName()); + } + Thread worker = new Thread(closure); + worker.setDaemon(true); + worker.start(); + } else { + if (LOGGER.isDebugEnabled()) { + if (ds != null) { + LOGGER.debug("Completed CachedDataSource.Call from " + ds.getDbConnectionName()); + } + } + } + } + } + } + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java new file mode 100644 index 00000000..8aadcae6 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/DBConfigFactory.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.factory; + + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Properties; + +import org.slf4j.LoggerFactory; + +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool; +import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration; + +/** + * @version $Revision: 1.1 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki 01/17/08 Initial version + */ +public class DBConfigFactory { + + public static DbConfigPool createConfig(Properties resource) { + return getConfigparams(resource); + } + + static DbConfigPool getConfigparams(Properties properties){ + DbConfigPool xmlConfig = new DbConfigPool(properties); + ArrayList<Properties> propertySets = new ArrayList<Properties>(); + + if("JDBC".equalsIgnoreCase(xmlConfig.getType())) { + String hosts = properties.getProperty(BaseDBConfiguration.DATABASE_HOSTS); + if(hosts == null || hosts.isEmpty()) { + propertySets.add(properties); + } else { + String[] newhost = hosts.split(","); + for(int i=0; i< newhost.length; i++) { + Properties localset = new Properties(); + localset.putAll(properties); + String url = localset.getProperty(BaseDBConfiguration.DATABASE_URL); + if(url.contains("DBHOST")) + url = url.replace("DBHOST", newhost[i]); + if(url.contains("dbhost")) + url = url.replace("dbhost", newhost[i]); + localset.setProperty(BaseDBConfiguration.DATABASE_URL, url); + localset.setProperty(BaseDBConfiguration.CONNECTION_NAME, newhost[i]); + propertySets.add(localset); + } + } + } else { + propertySets.add(properties); + } + try { + Iterator<Properties> it = propertySets.iterator(); + while(it.hasNext()) { + BaseDBConfiguration config = parse(it.next()); + xmlConfig.addConfiguration(config); + } + + } catch (Exception e) { + LoggerFactory.getLogger(DBConfigFactory.class).warn("",e); + } + + return xmlConfig; + } + + public static BaseDBConfiguration parse(Properties props) throws Exception { + + String type = props.getProperty(BaseDBConfiguration.DATABASE_TYPE); + + BaseDBConfiguration config = null; + + if("JDBC".equalsIgnoreCase(type)) { + config = new JDBCConfiguration(props); + } + + return config; + + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java new file mode 100644 index 00000000..e38cd351 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/factory/FactoryNotDefinedException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.factory; + + +/** + * @version 1.3 + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki 01/16/08 Initial version + */ +public class FactoryNotDefinedException extends Exception { + + public FactoryNotDefinedException(String message) { + super(message); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java new file mode 100644 index 00000000..90c76f63 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDBCachedDataSource.java @@ -0,0 +1,249 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.jdbc; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLFeatureNotSupportedException; + +import org.apache.tomcat.jdbc.pool.DataSource; +import org.apache.tomcat.jdbc.pool.PoolProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource; +import org.openecomp.sdnc.sli.resource.dblib.DBConfigException; +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration; +import com.mysql.jdbc.Driver; + + +/** + * @version $Revision: 1.7 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ + +public class JdbcDBCachedDataSource extends CachedDataSource +{ + private String dbUserId; + private String dbPasswd; + private String dbUrl; + + private int minLimit; + private int maxLimit; + private int initialLimit; + + private static final String AS_CONF_ERROR = "AS_CONF_ERROR: "; + + private static Logger LOGGER = LoggerFactory.getLogger(JdbcDBCachedDataSource.class); + + /** + * @param jdbcElem + */ + public JdbcDBCachedDataSource(BaseDBConfiguration jdbcElem) + { + super(jdbcElem); + } + + @Override + protected void configure(BaseDBConfiguration xmlElem) throws DBConfigException + { + BaseDBConfiguration jdbcConfig = (BaseDBConfiguration)xmlElem; + if(jdbcConfig.getConnTimeout() > 0){ + this.CONN_REQ_TIMEOUT = jdbcConfig.getConnTimeout(); + } + if(jdbcConfig.getRequestTimeout() > 0){ + this.DATA_REQ_TIMEOUT = jdbcConfig.getRequestTimeout(); + } + + // set connection pool name + String dbConnectionName = jdbcConfig.getDbConnectionName(); + super.setDbConnectionName(dbConnectionName); + // Configure the JDBC connection + dbUserId = jdbcConfig.getDbUserId(); + if (dbUserId == null) + { + String errorMsg = "Invalid XML contents: JDBCConnection missing dbUserId attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + + dbPasswd = jdbcConfig.getDbPasswd(); + if (dbPasswd == null) + { + String errorMsg = "Invalid XML contents: JDBCConnection missing dbPasswd attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + /* + dbDriver = jdbcConfig.getDbDriver(); + if (dbDriver == null) + { + String errorMsg = "Invalid XML contents: JDBCConnection missing dbDriver attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new ScpTblUpdateError(errorMsg); + } + */ + + minLimit = jdbcConfig.getDbMinLimit(); +// if (minLimit == null) +// { +// String errorMsg = "Invalid XML contents: JDBC Connection missing minLimit attribute"; +// LOGGER.error(AS_CONF_ERROR + errorMsg); +// throw new DBConfigException(errorMsg); +// } + maxLimit = jdbcConfig.getDbMaxLimit(); +// if (maxLimit == null) +// { +// String errorMsg = "Invalid XML contents: JDBC Connection missing maxLimit attribute"; +// LOGGER.error(AS_CONF_ERROR + errorMsg); +// throw new DBConfigException(errorMsg); +// } + initialLimit = jdbcConfig.getDbInitialLimit(); +// if (initialLimit == null) +// { +// String errorMsg = "Invalid XML contents: JDBC Connection missing initialLimit attribute"; +// LOGGER.error(AS_CONF_ERROR + errorMsg); +// throw new DBConfigException(errorMsg); +// } + + dbUrl = jdbcConfig.getDbUrl(); + if(dbUrl == null){ + String errorMsg = "Invalid XML contents: JDBCConnection missing dbUrl attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + + try { + Driver dr = new com.mysql.jdbc.Driver(); + Class clazz = Class.forName("com.mysql.jdbc.Driver") ; + + PoolProperties p = new PoolProperties(); + p.setDriverClassName("com.mysql.jdbc.Driver"); + p.setUrl(dbUrl); + p.setUsername(dbUserId); + p.setPassword(dbPasswd); + p.setJmxEnabled(true); + p.setTestWhileIdle(false); + p.setTestOnBorrow(true); + p.setValidationQuery("SELECT 1"); + p.setTestOnReturn(false); + p.setValidationInterval(30000); + p.setTimeBetweenEvictionRunsMillis(30000); + p.setInitialSize(initialLimit); + p.setMaxActive(maxLimit); + p.setMaxIdle(maxLimit); + p.setMaxWait(10000); + p.setRemoveAbandonedTimeout(60); + p.setMinEvictableIdleTimeMillis(30000); + p.setMinIdle(minLimit); + p.setLogAbandoned(true); + p.setRemoveAbandoned(true); + p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;" + + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"); + + DataSource dataSource = new DataSource(p); + + synchronized(this) + { + this.ds = dataSource; + Connection con = null; + PreparedStatement st = null; + ResultSet rs = null; + + try { + con = dataSource.getConnection(); + st = con.prepareStatement("Select 1 FROM DUAL"); + rs = st.executeQuery(); + } catch(Exception exc) { + LOGGER.error(exc.getMessage()); + } finally { + if(rs != null) rs.close(); + if(st != null) st.close(); + if(con != null) con.close(); + } + + initialized = true; + LOGGER.info("MySQLDataSource <"+dbConnectionName+"> configured successfully. Using URL: "+dbUrl); + } + +// } catch (SQLException exc) { +// initialized = false; +// StringBuffer sb = new StringBuffer(); +// sb.append("Failed to initialize MySQLDataSource<"); +// sb.append(dbConnectionName).append(">. Reason: "); +// sb.append(exc.getMessage()); +// LOGGER.error("AS_CONF_ERROR: " + sb.toString()); +//// throw new DBConfigException(e.getMessage()); + } catch (Exception exc) { + initialized = false; + StringBuffer sb = new StringBuffer(); + sb.append("Failed to initialize MySQLCachedDataSource <"); + sb.append(dbConnectionName).append(">. Reason: "); + sb.append(exc.getMessage()); + LOGGER.error("AS_CONF_ERROR: " + sb.toString()); +// throw new DBConfigException(e.getMessage()); + } + } + + public final String getDbUrl() + { + return dbUrl; + } + + public final String getDbUserId() + { + return dbUserId; + } + + public final String getDbPasswd() + { + return dbPasswd; + } + + public static JdbcDBCachedDataSource createInstance(BaseDBConfiguration config) /*throws Exception*/ { + return new JdbcDBCachedDataSource(config); + } + + public String toString(){ + return getDbConnectionName(); + } + + public java.util.logging.Logger getParentLogger() + throws SQLFeatureNotSupportedException { + // TODO Auto-generated method stub + return null; + } + + public void cleanUp(){ + DataSource dataSource = (DataSource)ds; + dataSource.getPool().purge(); + int active = dataSource.getActive(); + int size = dataSource.getSize(); + dataSource.close(true); + super.cleanUp(); + } + +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java new file mode 100644 index 00000000..84399dfd --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/JdbcDbResourceManagerFactory.java @@ -0,0 +1,186 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.jdbc; + + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; + +import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource; +import org.openecomp.sdnc.sli.resource.dblib.CachedDataSourceFactory; +import org.openecomp.sdnc.sli.resource.dblib.DBResourceManager; +import org.openecomp.sdnc.sli.resource.dblib.DataSourceComparator; +import org.openecomp.sdnc.sli.resource.dblib.config.DbConfigPool; +import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.factory.AbstractResourceManagerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @version $Revision: 1.6 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ +public class JdbcDbResourceManagerFactory extends AbstractResourceManagerFactory { + private static Logger LOGGER = LoggerFactory.getLogger(JdbcDbResourceManagerFactory.class ); + private JdbcDbResourceManagerFactory(){ + + } + + class MyFutureTask extends FutureTask<CachedDataSource> + { + + public MyFutureTask(Callable<CachedDataSource> result) { + super(result); + } + + } + + public CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager, String sourceName) throws SQLException + { + // here create the data sources objects + JDBCConfiguration[] list = dbConfig.getJDBCbSourceArray(); + CachedDataSource[] cachedDS = new CachedDataSource[1]; + + for(int i=0, max=list.length; i<max; i++){ + if(!sourceName.equals(list[i].getDbConnectionName())) + continue; + + JDBCConfiguration config = list[i]; + CachedDataSource dataSource = CachedDataSourceFactory.createDataSource(config); + cachedDS[0] = dataSource; + } + return cachedDS; + } + + public CachedDataSource[] initDBResourceManager(DbConfigPool dbConfig, DBResourceManager manager) /* throws Exception */ { + + ExecutorService threadExecutor = Executors.newFixedThreadPool(2); + // here create the data sources objects + JDBCConfiguration[] list = dbConfig.getJDBCbSourceArray(); + + MyFutureTask[] futures = new MyFutureTask[list.length]; + final Set<DBInitTask> tasks = new HashSet<DBInitTask>(); + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Creating " + list.length + " datasources."); + } + + for(int i=0, max=list.length; i<max; i++){ + JDBCConfiguration config = list[i]; + + DBInitTask task = new DBInitTask(config, tasks); + tasks.add(task); + futures[i] = new MyFutureTask(task); + } + + try { + synchronized(tasks){ + for(int i=0, max=list.length; i<max; i++){ + if(LOGGER.isDebugEnabled()) + LOGGER.debug("Starting executor tasks."); + threadExecutor.execute(futures[i]); + } + // the timeout param is set is seconds. + long timeout = ((dbConfig.getTimeout() <= 0) ? 60L : dbConfig.getTimeout()); + LOGGER.debug("Timeout set to " +timeout+" seconds"); + timeout *= 1000; + // the timeout param is set is seconds, hence it needs to be multiplied by 1000. + tasks.wait(timeout); + if(LOGGER.isDebugEnabled()) + LOGGER.debug("initDBResourceManager wait completed."); + } + } catch(Exception exc) { + LOGGER.error("Failed to initialize JndiCachedDataSource. Reason: ", exc); + } + + if(threadExecutor != null){ + try { + threadExecutor.shutdown(); + } catch(Exception exc){} + } + + CachedDataSource[] cachedDS = new CachedDataSource[futures.length]; + + boolean initialized = false; + for(int i=0; i<futures.length; i++){ + Object obj = null; + if(futures[i].isDone()){ + try { + obj = futures[i].get(); + if(obj instanceof CachedDataSource){ + cachedDS[i] = (CachedDataSource)obj; + initialized |= cachedDS[i].isInitialized(); + if(cachedDS[i].isInitialized()) + LOGGER.info("DataSource "+list[i].getDbConnectionName()+" initialized successfully"); + else + LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed"); + } else { + if(obj == null) { + LOGGER.warn("DataSource " + i + " initialization failed. Returned object is null"); + } else { + LOGGER.warn("DataSource " + i + " initialization failed. Returned object is " + obj.getClass().getName()); + } + } + } catch (InterruptedException exc) { + LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc); + } catch (ExecutionException exc) { + LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc); + } catch (Exception exc) { + LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc); + } + } else { + try { + obj = futures[i].get(); + if(obj instanceof CachedDataSource){ + LOGGER.warn("DataSource "+((CachedDataSource)obj).getDbConnectionName()+" failed"); + } else { + if(obj == null) { + LOGGER.warn("DataSource " + i + " initialization failed. Returned object is null"); + } else { + LOGGER.warn("DataSource " + i + " initialization failed. Returned object is " + obj.getClass().getName()); + } + } + } catch (Exception exc) { + LOGGER.error("DataSource "+list[i].getDbConnectionName()+" initialization failed", exc); + } + } + } + + if(!initialized){ + new Error("Failed to initialize DB Library."); + } + return cachedDS; + } + + public static AbstractResourceManagerFactory createIntstance() { + return new JdbcDbResourceManagerFactory(); + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java new file mode 100644 index 00000000..a5482d08 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/jdbc/MySQLCachedDataSource.java @@ -0,0 +1,217 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.jdbc; + +import java.sql.SQLFeatureNotSupportedException; +import java.util.Properties; + +import org.openecomp.sdnc.sli.resource.dblib.CachedDataSource; +import org.openecomp.sdnc.sli.resource.dblib.DBConfigException; +import org.openecomp.sdnc.sli.resource.dblib.config.BaseDBConfiguration; +import org.openecomp.sdnc.sli.resource.dblib.config.JDBCConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; + + + + +/** + * @version $Revision: 1.7 $ + * Change Log + * Author Date Comments + * ============== ======== ==================================================== + * Rich Tabedzki + */ + +public class MySQLCachedDataSource extends CachedDataSource +{ + private String dbUserId; + private String dbPasswd; + private String dbUrl; + + private String minLimit; + private String maxLimit; + private String initialLimit; + + private static final String AS_CONF_ERROR = "AS_CONF_ERROR: "; + + private static Logger LOGGER = LoggerFactory.getLogger(MySQLCachedDataSource.class); + + /** + * @param jdbcElem + */ + public MySQLCachedDataSource(BaseDBConfiguration jdbcElem) + { + super(jdbcElem); + } + + @Override + protected void configure(BaseDBConfiguration xmlElem) throws DBConfigException + { + BaseDBConfiguration jdbcConfig = (BaseDBConfiguration)xmlElem; + if(jdbcConfig.getConnTimeout() > 0){ + this.CONN_REQ_TIMEOUT = jdbcConfig.getConnTimeout(); + } + if(jdbcConfig.getRequestTimeout() > 0){ + this.DATA_REQ_TIMEOUT = jdbcConfig.getRequestTimeout(); + } + + // set connection pool name + String dbConnectionName = jdbcConfig.getDbConnectionName(); + super.setDbConnectionName(dbConnectionName); + // Configure the JDBC connection + dbUserId = jdbcConfig.getDbUserId(); + if (dbUserId == null) + { + String errorMsg = "Invalid XML contents: JDBCConnection missing dbUserId attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + + dbPasswd = jdbcConfig.getDbPasswd(); + if (dbPasswd == null) + { + String errorMsg = "Invalid XML contents: JDBCConnection missing dbPasswd attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + /* + dbDriver = jdbcConfig.getDbDriver(); + if (dbDriver == null) + { + String errorMsg = "Invalid XML contents: JDBCConnection missing dbDriver attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new ScpTblUpdateError(errorMsg); + } + */ + + minLimit = Integer.toString(jdbcConfig.getDbMinLimit()); + if (minLimit == null) + { + String errorMsg = "Invalid XML contents: JDBC Connection missing minLimit attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + maxLimit = Integer.toString(jdbcConfig.getDbMaxLimit()); + if (maxLimit == null) + { + String errorMsg = "Invalid XML contents: JDBC Connection missing maxLimit attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + initialLimit = Integer.toString(jdbcConfig.getDbInitialLimit()); + if (initialLimit == null) + { + String errorMsg = "Invalid XML contents: JDBC Connection missing initialLimit attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + + dbUrl = jdbcConfig.getDbUrl(); + if(dbUrl == null){ + String errorMsg = "Invalid XML contents: JDBCConnection missing dbUrl attribute"; + LOGGER.error(AS_CONF_ERROR + errorMsg); + throw new DBConfigException(errorMsg); + } + + try { + + MysqlDataSource dataSource = new MysqlDataSource(); + dataSource.setUser(dbUserId); + dataSource.setPassword(dbPasswd); + dataSource.setURL(dbUrl); +// dataSource.setInitialSize(5); +// dataSource.setMaxTotal(60); +// dataSource.setMaxActive(100); +// dataSource.setMaxWait(10000); +// dataSource.setMaxIdle(10); + + Properties connAttr = new Properties(); + + connAttr.setProperty("MinLimit", minLimit); + connAttr.setProperty("MaxLimit", maxLimit); + connAttr.setProperty("InitialLimit", initialLimit); + connAttr.setProperty("TRANSACTION_ISOLATION","SERIALIZABLE"); + connAttr.setProperty("CONNECTION_TAG", dbConnectionName.toUpperCase()+"_CONNECTION"); + connAttr.setProperty("InactivityTimeout", "900"); + connAttr.setProperty("AbandonedConnectionTimeout", "600"); + connAttr.setProperty("PropertyCheckInterval", "60"); + connAttr.setProperty("ValidateConnection", "true"); + + + synchronized(this) + { + this.ds = dataSource; + + initialized = true; + LOGGER.info("MySQLDataSource <"+dbConnectionName+"> configured successfully. Using URL: "+dbUrl); + } + +// } catch (SQLException exc) { +// initialized = false; +// StringBuffer sb = new StringBuffer(); +// sb.append("Failed to initialize MySQLDataSource<"); +// sb.append(dbConnectionName).append(">. Reason: "); +// sb.append(exc.getMessage()); +// LOGGER.error("AS_CONF_ERROR: " + sb.toString()); +//// throw new DBConfigException(e.getMessage()); + } catch (Exception exc) { + initialized = false; + StringBuffer sb = new StringBuffer(); + sb.append("Failed to initialize MySQLCachedDataSource <"); + sb.append(dbConnectionName).append(">. Reason: "); + sb.append(exc.getMessage()); + LOGGER.error("AS_CONF_ERROR: " + sb.toString()); +// throw new DBConfigException(e.getMessage()); + } + } + + public final String getDbUrl() + { + return dbUrl; + } + + public final String getDbUserId() + { + return dbUserId; + } + + public final String getDbPasswd() + { + return dbPasswd; + } + + public static MySQLCachedDataSource createInstance(BaseDBConfiguration config) /*throws Exception*/ { + return new MySQLCachedDataSource(config); + } + + public String toString(){ + return getDbConnectionName(); + } + + public java.util.logging.Logger getParentLogger() + throws SQLFeatureNotSupportedException { + // TODO Auto-generated method stub + return null; + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java new file mode 100644 index 00000000..de87fa7e --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/PollingWorker.java @@ -0,0 +1,217 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.pm; + +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.TreeSet; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicLong; + +public class PollingWorker implements Runnable { + + private Logger LOGGER = LoggerFactory.getLogger(PollingWorker.class); + + private static PollingWorker self = null; + + private LinkedBlockingQueue tasks = new LinkedBlockingQueue(100); + private long interval = 1000L; + private Thread worker = null; + private AtomicLong[] counters = null; + private int[] bucketUnit = null; + private static boolean enabled = false; + private Timer timer = null; + + public static void post(long starttime){ + PollingWorker temp = self; + if(temp != null && enabled) { + temp.register(new TestSample(starttime)); + } + } + + public static void createInistance(Properties props){ + self = new PollingWorker(props); + } + + private PollingWorker(Properties ctxprops){ + if(ctxprops==null || ctxprops.getProperty("org.openecomp.sdnc.dblib.pm") == null){ + enabled = false; + } else { + if("true".equalsIgnoreCase((String)ctxprops.getProperty("org.openecomp.sdnc.dblib.pm"))){ + enabled = true; + } else { + enabled = false; + } + } + + interval = Long.parseLong(( ctxprops == null || ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.interval") == null) ? "60" : (String)ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.interval")); + // '0' bucket is to count exceptions + String sampling[] = ((ctxprops == null || ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.sampling")==null) ? "0,2,5,10,20,50,100" : (String)ctxprops.getProperty("org.openecomp.sdnc.dblib.pm.sampling")).split(","); + + if(enabled){ + bucketUnit = new int[sampling.length]; + for(int i=0, max = bucketUnit.length; i<max; i++){ + bucketUnit[i] = Integer.parseInt(sampling[i].trim()); + } + counters = new AtomicLong[bucketUnit.length+1]; + for(int i=0, max = counters.length; i<max; i++){ + counters[i] = new AtomicLong(); + } + worker = new Thread(this); + worker.setDaemon(true); + worker.start(); + timer = new Timer(true); + timer.schedule(new MyTimerTask(), interval*1000L, interval*1000L); + } + } + + private void register(TestSample object){ + try { + tasks.add(object); + } catch(Throwable exc) { + // if cannot add an object to the queue, do nothing + } + } + + private void deRegister(TestSample object){ + tasks.remove(object); + } + + public void run() { + for(;;){ + Set data = new TreeSet(); + tasks.drainTo(data); + for(Iterator it = data.iterator(); it.hasNext(); ){ + Object next = it.next(); + if(next instanceof TestSample){ + consume((TestSample)next); + } else { + System.out.println(next.getClass().getName()); + } + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + } + public void clearReqister(){ + AtomicLong[] tmp = new AtomicLong[counters.length]; + for(int i=0, max = tmp.length; i<max; i++){ + tmp[i] = new AtomicLong(); + } + AtomicLong[] tmp2 = counters; + synchronized(tmp2){ + counters = tmp; + } + StringBuffer sb = new StringBuffer("CPM: "); + for(int i=0, max = tmp2.length; i < max; i++){ + if(i==0 && bucketUnit[0]==0){ + sb.append("[Exc]="); + } else { + sb.append("["); + if(i==bucketUnit.length){ + sb.append("Other]="); + } else { + sb.append(bucketUnit[i]).append(" ms]="); + } + } + sb.append(tmp2[i].get()).append("\t"); + } + LOGGER.info(sb.toString()); + } + + class MyTimerTask extends TimerTask{ + + public void run() { + + clearReqister(); + } + + } + + private void consume(TestSample probe) { + AtomicLong[] tmp = counters; + synchronized(tmp){ + counters[getBucket(probe.getDuration())].incrementAndGet(); + } + } + + /* + * This method is used to find the offset of the bucket in + * counters. 'counters' array is 1 size longer than bucketUnit, + * hence by default it returns 'bucketUnit.length' + */ + private int getBucket(long difftime){ + for(int i=0; i<bucketUnit.length; i++){ + if(difftime < bucketUnit[i]){ + return i; + } + } + return bucketUnit.length; + } + + private static boolean isEnabled() { + return enabled; + } + /** + * @author Rich Tabedzki + * A helper class to pass measured parameter to the counter. + */ + static class TestSample implements Comparable{ + private long starttime; + private long endtime; + + public TestSample(long starttime) { + this.endtime = System.currentTimeMillis(); + this.starttime = starttime; + } + + public long getDuration(){ + return endtime - starttime; + } + + public int compareTo(Object o) { + if(o instanceof TestSample){ + TestSample x = (TestSample)o; + if(starttime < x.starttime) + return 1; + if(endtime < x.endtime) + return 1; + if(starttime > x.starttime) + return -1; + if(endtime > x.endtime) + return -1; + return 0; + } + return 1; + } + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java new file mode 100644 index 00000000..c58c9db7 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitor.java @@ -0,0 +1,237 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.pm; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.Observable; +import java.util.Observer; +import java.util.SortedSet; +import java.util.Timer; +import java.util.TimerTask; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; + +import org.openecomp.sdnc.sli.resource.dblib.DBResourceObserver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SQLExecutionMonitor extends Observable +{ + private static Logger LOGGER = LoggerFactory.getLogger(SQLExecutionMonitor.class); + + final static long MILISECOND = 1000000L; + final static long SECOND = 1000L*MILISECOND; + + private final Timer timer; + // collection + private final SortedSet<TestObject> innerSet; + private SQLExecutionMonitorObserver parent = null; + private final AtomicLong completionCounter; + private boolean activeState = false; + private final long interval; + private final long initialDelay; + private final long EXPECTED_TIME_TO_COMPLETE; + private final long UNPROCESSED_FAILOVER_THRESHOLD; + + private final class MonitoringTask extends TimerTask + { + + public void run() + { + try { + TestObject testObj = new TestObject(); + testObj.setStartTime(testObj.getStartTime() - EXPECTED_TIME_TO_COMPLETE); + + // take a snapshot of the current task list + TestObject[] array = innerSet.toArray(new TestObject[0]); + SortedSet<TestObject> copyCurrent = new TreeSet<TestObject>(Arrays.asList(array)); + // get the list of the tasks that are older than the specified + // interval. + SortedSet<TestObject> unprocessed = copyCurrent.headSet(testObj); + + long succesfulCount = completionCounter.get(); + int unprocessedCount = unprocessed.size(); + + if (!unprocessed.isEmpty() && unprocessedCount > UNPROCESSED_FAILOVER_THRESHOLD && succesfulCount == 0) + { + // switch the Connection Pool to passive + setChanged(); + notifyObservers("Open JDBC requests=" + unprocessedCount+" in "+SQLExecutionMonitor.this.parent.getDbConnectionName()); + } + } catch (Exception exc) { + LOGGER.error("", exc); + } finally { + completionCounter.set(0L); + } + } + } + + public static class TestObject implements Comparable<TestObject>, Serializable + { + + private static final long serialVersionUID = 1L; + private long starttime; + private long randId; + + public TestObject() + { + starttime = System.nanoTime(); + } + + public long getStartTime() + { + return starttime; + } + + public void setStartTime(long newTime) + { + starttime = newTime; + } + + public int compareTo(TestObject o) + { + if( this == o) + return 0; + if(this.starttime > o.getStartTime()) + return 1; + if(this.starttime < o.getStartTime()) + return -1; + + if(this.hashCode() > o.hashCode()) + return 1; + if(this.hashCode() < o.hashCode()) + return -1; + + return 0; + } + + public String toString() + { + return Long.toString(starttime)+"#"+ this.hashCode(); + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + + return (obj instanceof TestObject + && starttime == ((TestObject) obj).getStartTime() + && hashCode() == ((TestObject) obj).hashCode()); + } + } + + public SQLExecutionMonitor(SQLExecutionMonitorObserver parent) + { + this.parent = parent; + completionCounter = new AtomicLong(0L); + interval = parent.getInterval(); + initialDelay = parent.getInitialDelay(); + this.UNPROCESSED_FAILOVER_THRESHOLD = parent.getUnprocessedFailoverThreshold(); + this.EXPECTED_TIME_TO_COMPLETE = parent.getExpectedCompletionTime()*MILISECOND; + + innerSet = Collections.synchronizedSortedSet(new TreeSet<TestObject>()); + timer = new Timer(); + } + + public void cleanup() + { + timer.cancel(); + } + + // registerRequest + public TestObject registerRequest() + { + if(activeState) + { + TestObject test = new TestObject(); + if(innerSet.add(test)) + return test; + } + return null; + } + + // deregisterSuccessfulReguest + public boolean deregisterReguest(TestObject test) + { + if(test == null) + return false; + // remove from the collection + if(innerSet.remove(test) && activeState) + { + completionCounter.incrementAndGet(); + return true; + } + return false; + } + + public void terminate() { + timer.cancel(); + } + + /** + * @return the parent + */ + public final Object getParent() { + return parent; + } + + public void addObserver(Observer observer) + { + if(observer instanceof DBResourceObserver) + { + DBResourceObserver dbObserver = (DBResourceObserver)observer; + if(dbObserver.isMonitorDbResponse()) + { + if(countObservers() == 0) + { + TimerTask remindTask = new MonitoringTask(); + timer.schedule(remindTask, initialDelay, interval); + activeState = true; + } + } + } + super.addObserver(observer); + } + + public void deleteObserver(Observer observer) + { + super.deleteObserver(observer); + if(observer instanceof DBResourceObserver) + { + DBResourceObserver dbObserver = (DBResourceObserver)observer; + if(dbObserver.isMonitorDbResponse()) + { + if(countObservers() == 0) + { + timer.cancel(); + activeState = false; + } + } + } + } + + public final int getPorcessedConnectionsCount() { + return innerSet.size(); + } +} diff --git a/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java new file mode 100644 index 00000000..1f329750 --- /dev/null +++ b/dblib/provider/src/main/java/org/openecomp/sdnc/sli/resource/dblib/pm/SQLExecutionMonitorObserver.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * openecomp + * ================================================================================ + * Copyright (C) 2016 - 2017 AT&T + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.resource.dblib.pm; + +public interface SQLExecutionMonitorObserver { + public String getDbConnectionName(); + + public long getInterval(); + public void setInterval(long value); + + public long getInitialDelay(); + public void setInitialDelay(long value); + + public long getExpectedCompletionTime(); + public void setExpectedCompletionTime(long value); + + public long getUnprocessedFailoverThreshold(); + public void setUnprocessedFailoverThreshold(long value); +} diff --git a/dblib/provider/src/main/resources/dblib.properties b/dblib/provider/src/main/resources/dblib.properties new file mode 100755 index 00000000..ac295c78 --- /dev/null +++ b/dblib/provider/src/main/resources/dblib.properties @@ -0,0 +1,13 @@ +org.openecomp.sdnc.sli.dbtype=jdbc +org.openecomp.sdnc.sli.jdbc.hosts=sdnctldb01,sdnctldb02 +org.openecomp.sdnc.sli.jdbc.url=jdbc:mysql://DBHOST:3306/sdnctl +org.openecomp.sdnc.sli.jdbc.database=sdnctl +org.openecomp.sdnc.sli.jdbc.user={user for sdnctl} +org.openecomp.sdnc.sli.jdbc.password={password for sdnctl} +org.openecomp.sdnc.sli.jdbc.connection.name=sdnctldb01 + +org.openecomp.sdnc.sli.jdbc.connection.timeout=50 +org.openecomp.sdnc.sli.jdbc.request.timeout=100 +org.openecomp.sdnc.sli.jdbc.limit.init=10 +org.openecomp.sdnc.sli.jdbc.limit.min=10 +org.openecomp.sdnc.sli.jdbc.limit.max=20 diff --git a/example-settings.xml b/example-settings.xml new file mode 100644 index 00000000..bfd6b9f4 --- /dev/null +++ b/example-settings.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- vi: set et smarttab sw=2 tabstop=2: --> +<!-- + Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v1.0 which accompanies this distribution, + and is available at http://www.eclipse.org/legal/epl-v10.html +--> +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + + <profiles> + <profile> + <id>openecomp-release</id> + <repositories> + <repository> + <id>openecomp-release</id> + <name>openecomp-release</name> + <url>https://nexus.onap.org/content/repositories/releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>openecomp-release</id> + <name>openecomp-release</name> + <url>https://nexus.onap.org/content/repositories/releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + + <profile> + <id>openecomp-snapshots</id> + <repositories> + <repository> + <id>openecomp-snapshot</id> + <name>openecomp-snapshot</name> + <url>https://nexus.onap.org/content/repositories/snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>openecomp-snapshot</id> + <name>openecomp-snapshot</name> + <url>https://nexus.onap.org/content/repositories/snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + <profile> + <id>opendaylight-release</id> + <repositories> + <repository> + <id>opendaylight-mirror</id> + <name>opendaylight-mirror</name> + <url>https://nexus.opendaylight.org/content/repositories/public/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>opendaylight-mirror</id> + <name>opendaylight-mirror</name> + <url>https://nexus.opendaylight.org/content/repositories/public/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + + <profile> + <id>opendaylight-snapshots</id> + <repositories> + <repository> + <id>opendaylight-snapshot</id> + <name>opendaylight-snapshot</name> + <url>https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>opendaylight-snapshot</id> + <name>opendaylight-snapshot</name> + <url>https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> + + <activeProfiles> + <activeProfile>openecomp-release</activeProfile> + <activeProfile>openecomp-snapshots</activeProfile> + <activeProfile>opendaylight-release</activeProfile> + <activeProfile>opendaylight-snapshots</activeProfile> + </activeProfiles> + + <servers> + <server> + <id>nexus</id> + <username>USERNAME</username> + <password>PASSWORD</password> + </server> + <server> + <id>openecomp-release</id> + <username>USERNAME</username> + <password>PASSWORD</password> + </server> + <server> + <id>openecomp-snapshot</id> + <username>USERNAME</username> + <password>PASSWORD</password> + </server> + </servers> +</settings> diff --git a/filters/.gitignore b/filters/.gitignore new file mode 100755 index 00000000..b73caf31 --- /dev/null +++ b/filters/.gitignore @@ -0,0 +1,34 @@ +#####standard .git ignore entries##### + +## IDE Specific Files ## +org.eclipse.core.resources.prefs +.classpath +.project +.settings +.idea +.externalToolBuilders +maven-eclipse.xml +workspace + +## Compilation Files ## +*.class +**/target +target +target-ide +MANIFEST.MF + +## Misc Ignores (OS specific etc) ## +bin/ +dist +*~ +*.ipr +*.iml +*.iws +classes +out/ +.DS_STORE +.metadata + +## Folders which contain auto generated source code ## +yang-gen-config +yang-gen-sal diff --git a/filters/.sonar/checkstyle.xml b/filters/.sonar/checkstyle.xml new file mode 100755 index 00000000..3fa23153 --- /dev/null +++ b/filters/.sonar/checkstyle.xml @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd"><!-- Generated by Sonar --><module name="Checker"><module name="SuppressionCommentFilter"/><module name="TreeWalker"><module name="FileContentsHolder"/> <module name="ClassFanOutComplexity"><property name="severity" value="warning"/></module><module name="NestedForDepth"><property name="severity" value="warning"/><property name="max" value="1"/></module><module name="ClassDataAbstractionCoupling"><property name="severity" value="warning"/></module></module></module>
\ No newline at end of file diff --git a/filters/.sonar/pmd.xml b/filters/.sonar/pmd.xml new file mode 100755 index 00000000..80343b3b --- /dev/null +++ b/filters/.sonar/pmd.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+ <rule ref="rulesets/java/naming.xml/BooleanGetMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/StaticEJBFieldShouldBeFinal">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/CouplingBetweenObjects">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyMethods">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingTypeName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/DoubleCheckedLocking">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/ExcessiveImports">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/OverrideBothEqualsAndHashcode">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/ShortMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/BooleanInstantiation">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyFields">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/controversial.xml/AvoidUsingNativeCode">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/optimizations.xml/UseStringBufferForStringAppends">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/LooseCoupling">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/NonThreadSafeSingleton">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/DoNotUseThreads">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/ArrayIsStoredDirectly">
+ <priority>5</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/MethodReturnsInternalArray">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/AssignmentToNonFinalStatic">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/strictexception.xml/AvoidCatchingGenericException">
+ <priority>3</priority>
+ </rule>
+</ruleset>
+
diff --git a/filters/README b/filters/README new file mode 100755 index 00000000..9d69d638 --- /dev/null +++ b/filters/README @@ -0,0 +1,14 @@ + +/restconf filters are enabled by specifying filter chain in + /opt/opendaylight/current/etc/org.opendaylight.aaa.filterchain.cfg +and enabling bundle class loading + >bundle:dynamic-import org.openecomp.sdnc.filters-provider + +loggers: + org.openecomp.sdnc.filters.audit + org.openecomp.sdnc.filters.metric + org.openecomp.sdnc.filters.request.response + + + + diff --git a/filters/features/pom.xml b/filters/features/pom.xml new file mode 100755 index 00000000..1e3875de --- /dev/null +++ b/filters/features/pom.xml @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>filters</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>filters-features</artifactId> + <name>Filters - Features</name> + + <packaging>jar</packaging> + + <dependencies> + + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>filters-provider</artifactId> + <version>${project.version}</version> + </dependency> +<!-- + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <version>${odl.mdsal.version}</version> + <classifier>features</classifier> + <type>xml</type> + + <scope>runtime</scope> + </dependency> +--> + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + <!-- launches the feature test, which validates that your karaf feature + can be installed inside of a karaf container. It doesn't validate that your + functionality works correctly, just that you have all of the dependent bundles + defined correctly. + <plugin> + + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.16</version> + <configuration> + <systemPropertyVariables> + <karaf.distro.groupId>org.opendaylight.odlparent</karaf.distro.groupId> + <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> + <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> + </systemPropertyVariables> + <dependenciesToScan> + <dependency>org.opendaylight.yangtools:features-test</dependency> + </dependenciesToScan> + </configuration> + </plugin> + --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/filters/features/src/main/resources/features.xml b/filters/features/src/main/resources/features.xml new file mode 100644 index 00000000..1c58e649 --- /dev/null +++ b/filters/features/src/main/resources/features.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<features name="sdnc-filters-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <feature name='sdnc-filters' description="servlet filters" version='${project.version}'> + <bundle>mvn:org.openecomp.sdnc.core/filters-provider/${project.version}</bundle> + </feature> + +</features> diff --git a/filters/installer/pom.xml b/filters/installer/pom.xml new file mode 100755 index 00000000..579c0e9a --- /dev/null +++ b/filters/installer/pom.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>filters</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>filters-installer</artifactId> + <name>Filters - Karaf Installer</name> + <packaging>pom</packaging> + + <properties> + <application.name>sdnc-filters</application.name> + <features.boot>sdnc-filters</features.boot> + <features.repositories>mvn:org.openecomp.sdnc.core/filters-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencies> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>filters-features</artifactId> + <version>${project.version}</version> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>filters-provider</artifactId> + <version>${project.version}</version> + </dependency> + + + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${application.name}-${project.version}-installer</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeGroupIds>org.openecomp.sdnc</includeGroupIds> + <excludeArtifactIds>sli-common,sli-provider</excludeArtifactIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals><!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/filters/installer/src/assembly/assemble_installer_zip.xml b/filters/installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 00000000..3a5c5f65 --- /dev/null +++ b/filters/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,61 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + + <id>bin</id> + + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/filters/installer/src/assembly/assemble_mvnrepo_zip.xml b/filters/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 00000000..a9fca4d0 --- /dev/null +++ b/filters/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,49 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/filters/installer/src/main/resources/scripts/install-feature.sh b/filters/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 00000000..93236c5b --- /dev/null +++ b/filters/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/filters/pom.xml b/filters/pom.xml new file mode 100644 index 00000000..b075be98 --- /dev/null +++ b/filters/pom.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sdnc-core</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <packaging>pom</packaging> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>filters</artifactId> + + + <name>Filters</name> + <description>Servlet filter to implement ECOMP logging spec</description> + + <version>0.0.1-SNAPSHOT</version> + + + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>${maven.compile.plugin.version}</version> + <configuration> + <source>${java.version.source}</source> + <target>${java.version.target}</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10</version> + + <executions> + <execution> + <id>aggregate</id> + <goals> + <goal>aggregate</goal> + </goals> + <phase>site</phase> + + </execution> + + </executions> + </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <version>2.1.1</version> + <executions> + <execution> + <id>bundle-sources</id> + <phase>package</phase> + <goals> + <!-- produce source artifact for main project sources --> + <goal>jar-no-fork</goal> + + <!-- produce source artifact for project test sources --> + <goal>test-jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + + </pluginManagement> + </build> + <organization> + <name>OpenECOMP</name> + </organization> + <modules> + <module>provider</module> + <module>features</module> + <module>installer</module> + </modules> +</project> diff --git a/filters/provider/pom.xml b/filters/provider/pom.xml new file mode 100755 index 00000000..a7b6daec --- /dev/null +++ b/filters/provider/pom.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>filters</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>filters-provider</artifactId> + <packaging>bundle</packaging> + <name>Filters - Provider</name> + <url>http://maven.apache.org</url> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.0.1</version> + <scope>provided</scope> + </dependency> + + + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>${equinox.osgi.version}</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>${commons.codec.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + </dependency> +<!-- + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>${mysql.connector.version}</version> + </dependency> +--> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>${bundle.plugin.version}</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>org.openecomp.sdnc.filters</Bundle-SymbolicName> + <Bundle-Activator>org.openecomp.sdnc.filters.Activator</Bundle-Activator> + <Export-Package>org.openecomp.sdnc.filters</Export-Package> + <DynamicImport-Package>org.openecomp.sdnc.filters</DynamicImport-Package> + <Import-Package>javax.servlet.*,java.io.*,org.osgi.framework.*,org.slf4j.*,org.apache.commons.codec.binary.*</Import-Package> + <!-- + <Import-Package>org.openecomp.sdnc.filters.filters.*,javax.servlet.*,java.io.*,org.osgi.framework.*,org.slf4j.*</Import-Package> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency> + <Import-Package>*</Import-Package> + --> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + + </plugin> + + + </plugins> + </build> +</project> diff --git a/filters/provider/src/main/java/org/openecomp/sdnc/filters/Activator.java b/filters/provider/src/main/java/org/openecomp/sdnc/filters/Activator.java new file mode 100644 index 00000000..d21b3099 --- /dev/null +++ b/filters/provider/src/main/java/org/openecomp/sdnc/filters/Activator.java @@ -0,0 +1,63 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.filters; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class Activator implements BundleActivator { + + private ServiceRegistration registration = null; + + private static final Logger LOG = LoggerFactory.getLogger(Activator.class); + + @Override + public void start(BundleContext ctx) throws Exception { + + + + Object impl = new String(); + String regName = impl.getClass().getName(); + + if (registration == null) + { + LOG.debug("Registering Filters service "+regName); + registration = ctx.registerService(regName, impl, null); + } + + } + + @Override + public void stop(BundleContext ctx) throws Exception { + + if (registration != null) + { + registration.unregister(); + registration = null; + } + } + +} diff --git a/filters/provider/src/main/java/org/openecomp/sdnc/filters/LogFilter.java b/filters/provider/src/main/java/org/openecomp/sdnc/filters/LogFilter.java new file mode 100644 index 00000000..809cfb28 --- /dev/null +++ b/filters/provider/src/main/java/org/openecomp/sdnc/filters/LogFilter.java @@ -0,0 +1,222 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.filters; + +import java.io.IOException; +import java.util.UUID; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.codec.binary.Base64; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + + + +/** + * Logs IN request according ECOMP Logging Guidelines at https://tspace.web.att.com/viewer/app/lcfiles/ae5f7751-39da-4c6b-8a83-5836c8c815e1/content + */ +public class LogFilter implements Filter { + + //X-ECOMP is shared between audit and metric + public static final String BEGIN_TIMESTAMP = "AUDIT-BeginTimestamp"; + public static final String END_TIMESTAMP = "AUDIT-EndTimestamp"; + public static final String REQUEST_ID = "X-ECOMP-RequestID"; + public static final String SERVICE_INSTANCE = "X-ECOMP-ServiceInstanceID"; + public static final String THREAD_ID ="X-ECOMP-ThreadId"; //optional + public static final String PHYSICAL_SERVER_NAME="X-ECOMP-PhysicalServerName"; //optional + public static final String SERVICE_NAME="X-ECOMP-ServiceName"; + public static final String PARTNER_NAME="X-ECOMP-PartnerName"; + public static final String STATUS_CODE="AUDIT-StatusCode"; + public static final String RESP_CODE="AUDIT-ResponseCode"; + public static final String RESP_DESC="AUDIT-ResponseDescription"; + public static final String INSTANCE_UUID="AUDIT-InstanceUUID"; + public static final String CATEGORY="AUDIT-INFO"; + public static final String SEVERITY ="AUDIT-Severity"; //optional + public static final String SERVER_IP="AUDIT-ServerIP"; //by chef node['ip'] + public static final String ELAPSED_TIME="AUDIT-ElapsedTime"; + public static final String SERVER_HOST="AUDIT-Server";//by chef node['fqdn'] + public static final String CLIENT_IP="AUDIT-ClientIPaddress"; + public static final String CLASS="AUDIT-Classname"; //optional + public static final String UNUSED="AUDIT-Unused"; //empty + public static final String PROCESS_KEY="AUDIT-ProcessKey"; //optional + public static final String CUST_1="AUDIT-CustomField1";//optional + public static final String CUST_2="AUDIT-CustomField2"; //optional + public static final String CUST_3="AUDIT-CustomField3"; //optional + public static final String CUST_4="AUDIT-CustomField4"; //optional + public static final String DETAIL_MESSAGE="AUDIT-DetailMessage";//optional + + + private static final Logger log = LoggerFactory.getLogger(LogFilter.class); + private static final Logger AUDIT = LoggerFactory.getLogger("org.openecomp.sdnc.filters.audit"); + @Override + public void destroy() { + } + + @Override + public void doFilter(final ServletRequest request, final ServletResponse response, + final FilterChain filterChain) throws IOException, ServletException { + + long startTime = System.currentTimeMillis(); + try { + + if ( request != null && request instanceof HttpServletRequest ) { + pre((HttpServletRequest)request); + } + filterChain.doFilter(request, response); + + + } finally { + + if (request != null && request instanceof HttpServletRequest ) { + post((HttpServletRequest)request,(HttpServletResponse)response,startTime); + } + MDC.clear(); + } + + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + + + private void pre(HttpServletRequest request) { + + UUID uuid = UUID.randomUUID(); + // check if uuid is in header X-ECOMP-RequestID + + String ecompUUID = request.getHeader(REQUEST_ID); + + if (ecompUUID != null && ecompUUID.length() > 0) { + try { + uuid = UUID.fromString(ecompUUID); + log.info("UUID is ECOMP UUID " + uuid.toString()); + } catch (Exception ex){ + log.warn("Failed to convert ECOMP UUID to java.util.UUID format:" + ecompUUID,ex); + } + } + MDC.put(REQUEST_ID, uuid.toString()); + + String userName="unknown"; + + /* below returning org.opendaylight.aaa.shiro.realm.TokenAuthRealm$ODLPrincipal@745dfcfe + if ( request.getUserPrincipal() != null) { + userName = request.getUserPrincipal().getName(); + } + */ + // going directly after Authorization header + if (request.getHeader("Authorization") != null) { + String authzHeader = request.getHeader("Authorization"); + String usernameAndPassword = new String(Base64.decodeBase64(authzHeader.substring(6).getBytes())); + + int userNameIndex = usernameAndPassword.indexOf(":"); + String username = usernameAndPassword.substring(0, userNameIndex); + userName = username; + + } + + + MDC.put(PARTNER_NAME, userName); + //just to initilaze for metric logger (outbound calls) + MDC.put("X-ECOMP-TargetEntity",""); + MDC.put("X-ECOMP-TargetServiceName",""); + + MDC.put(SERVICE_NAME,request.getRequestURL().toString()); + MDC.put(SERVICE_INSTANCE,""); + + } + + + private void post(HttpServletRequest request,HttpServletResponse response,long startTime) { + + //AUDIT.info("{}|{}|{}{}",request.getRemoteHost(),request.getMethod(),request.getRequestURL().toString(),request.getQueryString()); + //AUDIT.info(request.getRemoteHost() + D + request.getMethod() + D + request.getRequestURL().toString() + D + request.getQueryString()); + //METRIC.info(request.getMethod() + D + response.getStatus() + D + request.getRequestURL().toString() + D + (System.currentTimeMillis() - startTime) + " ms"); + MDC.put(BEGIN_TIMESTAMP,asIso8601(startTime)); + MDC.put(END_TIMESTAMP,asIso8601(System.currentTimeMillis())); + //MDC.put(REQUEST_ID,"already done above"); + MDC.put(SERVICE_NAME,request.getRequestURL().toString()); + int idx = request.getPathInfo().toString().lastIndexOf(":"); + String instance = ""; + if ( idx != -1 ) { + instance = request.getPathInfo().substring(idx+1); + } + MDC.put(SERVICE_INSTANCE,instance); + MDC.put(THREAD_ID,""); + MDC.put(PHYSICAL_SERVER_NAME,""); + //MDC.put(PARTNER_NAME,"already done above"); + if ( response.getStatus() >= 400 ) { + MDC.put(STATUS_CODE,"ERROR"); + } else { + MDC.put(STATUS_CODE,"COMPLETE"); + } + + MDC.put(RESP_CODE,"" + response.getStatus()); + MDC.put(RESP_DESC,""); + MDC.put(INSTANCE_UUID,""); + MDC.put(CATEGORY,""); + MDC.put(SEVERITY,""); + //MDC.put(SERVER_IP,""); //by chef + MDC.put(ELAPSED_TIME,"" + (System.currentTimeMillis() - startTime)); + //MDC.put(SERVER_HOST,""); //by chef + MDC.put(CLIENT_IP,request.getRemoteHost()); + MDC.put(CLASS,""); + MDC.put(UNUSED,""); + MDC.put(PROCESS_KEY,""); + MDC.put(CUST_1,""); + MDC.put(CUST_2,""); + MDC.put(CUST_3,""); + MDC.put(CUST_4,""); + MDC.put(DETAIL_MESSAGE,request.getMethod()); + + AUDIT.info(""); + } + + private String asIso8601(Date date) { + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyy-MM-dd'T'hh:mm:ss:SS'+00:00'"); + df.setTimeZone(tz); + return df.format(date); + } + + private String asIso8601(long tsInMillis) { + return asIso8601(new Date(tsInMillis)); + } + + +} diff --git a/filters/provider/src/main/java/org/openecomp/sdnc/filters/RequestResponseDbLoggingFilter.java b/filters/provider/src/main/java/org/openecomp/sdnc/filters/RequestResponseDbLoggingFilter.java new file mode 100644 index 00000000..183301be --- /dev/null +++ b/filters/provider/src/main/java/org/openecomp/sdnc/filters/RequestResponseDbLoggingFilter.java @@ -0,0 +1,297 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.filters; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.util.zip.GZIPInputStream; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.openecomp.sdnc.sli.MessageWriter; + +public class RequestResponseDbLoggingFilter implements Filter { + + private static Logger log = LoggerFactory.getLogger(RequestResponseDbLoggingFilter.class); + + public static final String REQUEST_ID = "X-ECOMP-RequestID"; + + private static class ByteArrayServletStream extends ServletOutputStream { + + ByteArrayOutputStream baos; + + ByteArrayServletStream(ByteArrayOutputStream baos) { + this.baos = baos; + } + + @Override + public void write(int param) throws IOException { + baos.write(param); + } + } + + private static class ByteArrayPrintWriter { + + private ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + private PrintWriter pw = new PrintWriter(baos); + + private ServletOutputStream sos = new ByteArrayServletStream(baos); + + public PrintWriter getWriter() { + return pw; + } + + public ServletOutputStream getStream() { + return sos; + } + + byte[] toByteArray() { + return baos.toByteArray(); + } + } + + private class BufferedServletInputStream extends ServletInputStream { + + ByteArrayInputStream bais; + + public BufferedServletInputStream(ByteArrayInputStream bais) { + this.bais = bais; + } + + @Override + public int available() { + return bais.available(); + } + + @Override + public int read() { + return bais.read(); + } + + @Override + public int read(byte[] buf, int off, int len) { + return bais.read(buf, off, len); + } + + } + + private class BufferedRequestWrapper extends HttpServletRequestWrapper { + + ByteArrayInputStream bais; + + ByteArrayOutputStream baos; + + BufferedServletInputStream bsis; + + byte[] buffer; + + public BufferedRequestWrapper(HttpServletRequest req) throws IOException { + super(req); + + InputStream is = req.getInputStream(); + baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int letti; + while ((letti = is.read(buf)) > 0) { + baos.write(buf, 0, letti); + } + buffer = baos.toByteArray(); + + } + + @Override + public ServletInputStream getInputStream() { + try { + bais = new ByteArrayInputStream(buffer); + bsis = new BufferedServletInputStream(bais); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return bsis; + } + + public byte[] getBuffer() { + return buffer; + } + + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) + throws IOException, ServletException { + + if (request == null || !(request instanceof HttpServletRequest)) { + filterChain.doFilter(request, response); + return; + } + + long t1 = System.currentTimeMillis(); + + final HttpServletRequest httpRequest = (HttpServletRequest) request; + BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpRequest); + + String requestId = httpRequest.getHeader(REQUEST_ID); + if (requestId == null || requestId.trim().length() == 0) { + log.warn("Could not write request in DB: " + REQUEST_ID + " is missing in the HTTP headers."); + return; + } + + String requestHost = request.getRemoteHost(); + if (requestHost == null) + requestHost = request.getRemoteAddr(); + + String requestStr = new String(bufferedRequest.getBuffer()); + + MessageWriter.saveIncomingRequest(requestId, null, requestHost, requestStr); + + long t2 = System.currentTimeMillis(); + + log.info("Request saved in DB for request-id: " + requestId + ". TIme: " + (t2 - t1)); + + final HttpServletResponse httpResponse = (HttpServletResponse) response; + + final ByteArrayPrintWriter pw = new ByteArrayPrintWriter(); + HttpServletResponse wrappedResp = new HttpServletResponseWrapper(httpResponse) { + + @Override + public PrintWriter getWriter() { + return pw.getWriter(); + } + + @Override + public ServletOutputStream getOutputStream() { + return pw.getStream(); + } + }; + + try { + + filterChain.doFilter(bufferedRequest, wrappedResp); + + } finally { + + if (request != null && request instanceof HttpServletRequest) { + + t1 = System.currentTimeMillis(); + + byte[] bytes = pw.toByteArray(); + response.getOutputStream().write(bytes); + response.getOutputStream().flush(); + + String responseStr = null; + if ("gzip".equals(httpResponse.getHeader("Content-Encoding"))) { + responseStr = decompressGZIPByteArray(bytes); + } else { + responseStr = new String(bytes); + } + + MessageWriter.saveIncomingResponse(requestId, httpResponse.getStatus(), responseStr); + + t2 = System.currentTimeMillis(); + + log.info("Response saved in DB for request-id: " + requestId + ". TIme: " + (t2 - t1)); + } + } + + } + + @Override + public void destroy() { + } + + private String decompressGZIPByteArray(byte[] bytes) { + + BufferedReader in = null; + InputStreamReader inR = null; + ByteArrayInputStream byteS = null; + GZIPInputStream gzS = null; + StringBuilder str = new StringBuilder(); + try { + byteS = new ByteArrayInputStream(bytes); + gzS = new GZIPInputStream(byteS); + inR = new InputStreamReader(gzS); + in = new BufferedReader(inR); + + if (in != null) { + + String content; + + while ((content = in.readLine()) != null) { + str.append(content); + } + } + + } catch (Exception e) { + log.error("Failed get read GZIPInputStream", e); + } finally { + + if (byteS != null) + try { + byteS.close(); + } catch (IOException e1) { + log.error("Failed to close ByteStream", e1); + } + if (gzS != null) + try { + gzS.close(); + } catch (IOException e2) { + log.error("Failed to close GZStream", e2); + } + if (inR != null) + try { + inR.close(); + } catch (IOException e3) { + log.error("Failed to close InputReader", e3); + } + if (in != null) + try { + in.close(); + } catch (IOException e) { + log.error("Failed to close BufferedReader", e); + } + } + return str.toString(); + } +} diff --git a/filters/provider/src/main/java/org/openecomp/sdnc/filters/RequestResponseLoggingFilter.java b/filters/provider/src/main/java/org/openecomp/sdnc/filters/RequestResponseLoggingFilter.java new file mode 100644 index 00000000..b15932f0 --- /dev/null +++ b/filters/provider/src/main/java/org/openecomp/sdnc/filters/RequestResponseLoggingFilter.java @@ -0,0 +1,289 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.filters; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.zip.GZIPInputStream; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +public class RequestResponseLoggingFilter implements Filter { + + private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("org.openecomp.sdnc.filters.request.response"); + + private static class ByteArrayServletStream extends ServletOutputStream { + + ByteArrayOutputStream baos; + + ByteArrayServletStream(ByteArrayOutputStream baos) { + this.baos = baos; + } + + @Override + public void write(int param) throws IOException { + baos.write(param); + } + } + + private static class ByteArrayPrintWriter { + + private ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + private PrintWriter pw = new PrintWriter(baos); + + private ServletOutputStream sos = new ByteArrayServletStream(baos); + + public PrintWriter getWriter() { + return pw; + } + + public ServletOutputStream getStream() { + return sos; + } + + byte[] toByteArray() { + return baos.toByteArray(); + } + } + + private class BufferedServletInputStream extends ServletInputStream { + + ByteArrayInputStream bais; + + public BufferedServletInputStream(ByteArrayInputStream bais) { + this.bais = bais; + } + + @Override + public int available() { + return bais.available(); + } + + @Override + public int read() { + return bais.read(); + } + + @Override + public int read(byte[] buf, int off, int len) { + return bais.read(buf, off, len); + } + + } + + private class BufferedRequestWrapper extends HttpServletRequestWrapper { + + ByteArrayInputStream bais; + + ByteArrayOutputStream baos; + + BufferedServletInputStream bsis; + + byte[] buffer; + + public BufferedRequestWrapper(HttpServletRequest req) throws IOException { + super(req); + + InputStream is = req.getInputStream(); + baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int letti; + while ((letti = is.read(buf)) > 0) { + baos.write(buf, 0, letti); + } + buffer = baos.toByteArray(); + + } + + @Override + public ServletInputStream getInputStream() { + try { + bais = new ByteArrayInputStream(buffer); + bsis = new BufferedServletInputStream(bais); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return bsis; + } + + public byte[] getBuffer() { + return buffer; + } + + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; + BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpRequest); + + StringBuilder requestHeaders = new StringBuilder("REQUEST|"); + requestHeaders.append(httpRequest.getMethod()); + requestHeaders.append(":"); + requestHeaders.append(httpRequest.getRequestURL().toString()); + requestHeaders.append("|"); + String header; + for (Enumeration<String> e = httpRequest.getHeaderNames(); e.hasMoreElements();) { + header = e.nextElement(); + requestHeaders.append(header); + requestHeaders.append(":"); + requestHeaders.append(httpRequest.getHeader(header)); + requestHeaders.append(";"); + + } + log.info(requestHeaders.toString()); + + log.info("REQUEST BODY|" + new String(bufferedRequest.getBuffer())); + + final HttpServletResponse response = (HttpServletResponse) servletResponse; + + final ByteArrayPrintWriter pw = new ByteArrayPrintWriter(); + HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) { + @Override + public PrintWriter getWriter() { + return pw.getWriter(); + } + + @Override + public ServletOutputStream getOutputStream() { + return pw.getStream(); + } + + }; + + try { + + filterChain.doFilter(bufferedRequest, wrappedResp); + + }catch (Exception e){ + log.error("Chain Exception",e); + throw e; + } finally { + byte[] bytes = pw.toByteArray(); + response.getOutputStream().write(bytes); + response.getOutputStream().flush(); + + StringBuilder responseHeaders = new StringBuilder("RESPONSE HEADERS|"); + + for (String headerName : response.getHeaderNames()) { + responseHeaders.append(headerName); + responseHeaders.append(":"); + responseHeaders.append(response.getHeader(headerName)); + responseHeaders.append(";"); + + } + log.info(responseHeaders.toString()); + + if ("gzip".equals(response.getHeader("Content-Encoding"))) { + + log.info("UNGZIPED RESPONSE BODY|" + decompressGZIPByteArray(bytes)); + + } else { + + log.info("RESPONSE BODY|" + new String(bytes)); + } + } + } + + @Override + public void destroy() { + } + + private String decompressGZIPByteArray(byte[] bytes) { + + BufferedReader in = null; + InputStreamReader inR = null; + ByteArrayInputStream byteS = null; + GZIPInputStream gzS = null; + StringBuilder str = new StringBuilder(); + try { + byteS = new ByteArrayInputStream(bytes); + gzS = new GZIPInputStream(byteS); + inR = new InputStreamReader(gzS); + in = new BufferedReader(inR); + + if (in != null) { + + String content; + + while ((content = in.readLine()) != null) { + str.append(content); + } + } + + } catch (Exception e) { + log.error("Failed get read GZIPInputStream", e); + } finally { + + if (byteS != null) + try { + byteS.close(); + } catch (IOException e1) { + log.error("Failed to close ByteStream", e1); + } + if (gzS != null) + try { + gzS.close(); + } catch (IOException e2) { + log.error("Failed to close GZStream", e2); + } + if (inR != null) + try { + inR.close(); + } catch (IOException e3) { + log.error("Failed to close InputReader", e3); + } + if (in != null) + try { + in.close(); + } catch (IOException e) { + log.error("Failed to close BufferedReader", e); + } + } + return str.toString(); + } +} diff --git a/jenkins-settings.xml b/jenkins-settings.xml new file mode 100644 index 00000000..344994f8 --- /dev/null +++ b/jenkins-settings.xml @@ -0,0 +1,168 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- vi: set et smarttab sw=2 tabstop=2: --> +<!-- + Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v1.0 which accompanies this distribution, + and is available at http://www.eclipse.org/legal/epl-v10.html +--> +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + + <profiles> + <profile> + <id>openecomp-release</id> + <repositories> + <repository> + <id>openecomp-release</id> + <name>openecomp-release</name> + <url>https://ecomp-nexus:8443/repository/maven-releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>openecomp-release</id> + <name>openecomp-release</name> + <url>https://ecomp-nexus:8443/repository/maven-releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + + <profile> + <id>openecomp-snapshots</id> + <repositories> + <repository> + <id>openecomp-snapshot</id> + <name>openecomp-snapshot</name> + <url>https://ecomp-nexus:8443/repository/maven-snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>openecomp-snapshot</id> + <name>openecomp-snapshot</name> + <url>https://ecomp-nexus:8443/repository/maven-snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + <profile> + <id>opendaylight-release</id> + <repositories> + <repository> + <id>opendaylight-mirror</id> + <name>opendaylight-mirror</name> + <url>https://nexus.opendaylight.org/content/repositories/public/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>opendaylight-mirror</id> + <name>opendaylight-mirror</name> + <url>https://nexus.opendaylight.org/content/repositories/public/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + + <profile> + <id>opendaylight-snapshots</id> + <repositories> + <repository> + <id>opendaylight-snapshot</id> + <name>opendaylight-snapshot</name> + <url>https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>opendaylight-snapshot</id> + <name>opendaylight-snapshot</name> + <url>https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> + + <activeProfiles> + <activeProfile>openecomp-release</activeProfile> + <activeProfile>openecomp-snapshots</activeProfile> + <activeProfile>opendaylight-release</activeProfile> + <activeProfile>opendaylight-snapshots</activeProfile> + </activeProfiles> + + <servers> + <server> + <id>nexus</id> + <username>${ecomp.nexus.user}</username> + <password>${ecomp.nexus.password}</password> + </server> + <server> + <id>openecomp-release</id> + <username>${ecomp.nexus.user}</username> + <password>${ecomp.nexus.password}</password> + </server> + <server> + <id>openecomp-snapshot</id> + <username>${ecomp.nexus.user}</username> + <password>${ecomp.nexus.password}</password> + </server> + <server> + <id>sdnc-javadoc</id> + <username>${ecomp.nexus.user}</username> + <password>${ecomp.nexus.password}</password> + </server> + </servers> +</settings> diff --git a/pom.xml b/pom.xml new file mode 100755 index 00000000..bb0df7e7 --- /dev/null +++ b/pom.xml @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <packaging>pom</packaging> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sdnc-core</artifactId> + + <name>SDN-C Core Components</name> + <url>https://wiki.onap.org</url> + <description>The SDN-C core components contains the SLI, dblib and root pom</description> + + <parent> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>odlparent-boron-sr3</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <issueManagement> + <system>JIRA</system> + <url>http://jira.onap.org/</url> + </issueManagement> + + + <scm> + <connection>scm:git:ssh://git@${onap.git.host}/sdnc-code.git</connection> + <developerConnection>scm:git:ssh://${onap.git.host}:${onap.git.port}/${onap.git.project}/sdnc-core.git</developerConnection> + <url>${onap.git.protocol}://${onap.git.host}/projects/${onap.git.project}/repos/sdnc-core/browse</url> + <tag>sdnc-core-1.1.0</tag> + </scm> + + <ciManagement> + <system>Jenkins</system> + <url>https://jenkins.onap.org/</url> + </ciManagement> + + + <distributionManagement> + <site> + <id>ecomp-site</id> + <url>dav:https://${onap.nexus.host}/content/sites/site/org/onap/sdnc/core/${project.artifactId}/${project.version}</url> + </site> + </distributionManagement> + + + <profiles> + <profile> + <id>blackduck</id> + <activation> + <property> + <name>blackduck-scan</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>com.blackducksoftware.integration</groupId> + <artifactId>hub-maven-plugin</artifactId> + <version>1.4.0</version> + <inherited>false</inherited> + <configuration> + <hubProjectName>${project.name}</hubProjectName> + <outputDirectory>${project.basedir}</outputDirectory> + </configuration> + <executions> + <execution> + <id>create-bdio-file</id> + <phase>package</phase> + <goals> + <goal>createHubOutput</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + + + + </build> + + </profile> + + </profiles> + + <build> + <plugins> + <!-- license plugin --> + + <plugin> + + <groupId>org.codehaus.mojo</groupId> + + <artifactId>license-maven-plugin</artifactId> + + <version>1.10</version> + + <configuration> + + <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage> + + <processStartTag>============LICENSE_START=======================================================</processStartTag> + + <processEndTag>============LICENSE_END=========================================================</processEndTag> + + <sectionDelimiter>================================================================================</sectionDelimiter> + + <licenseName>apache_v2</licenseName> + + <inceptionYear>2017</inceptionYear> + + <organizationName>AT&T Intellectual Property. All rights + reserved.</organizationName> + + <projectName>openECOMP : SDN-C</projectName> + + <canUpdateCopyright>true</canUpdateCopyright> + + <canUpdateDescription>true</canUpdateDescription> + + <canUpdateLicense>true</canUpdateLicense> + + <emptyLineAfterHeader>true</emptyLineAfterHeader> + + </configuration> + + <executions> + + <execution> + + <id>first</id> + + <goals> + + <goal>update-file-header</goal> + + </goals> + + <phase>process-sources</phase> + + </execution> + + </executions> + + </plugin> + + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.17</version> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> + <plugin> + <groupId>org.sonatype.plugins</groupId> + <artifactId>nexus-staging-maven-plugin</artifactId> + <version>1.6.7</version> + <extensions>true</extensions> + <configuration> + <nexusUrl>https://${onap.nexus.host}</nexusUrl> + <stagingProfileId>${onap.nexus.staging.profile-id}</stagingProfileId> + <serverId>${onap.nexus.staging.server-id}</serverId> + </configuration> + </plugin> + + </plugins> + + </build> + <modules> + <module>dblib</module> + <module>sli</module> + <module>filters</module> + <module>sliPluginUtils</module> + <module>sliapi</module> + </modules> + <organization> + <name>OpenECOMP</name> + </organization> + <version>0.0.1-SNAPSHOT</version> + + +</project> diff --git a/sli/.gitignore b/sli/.gitignore new file mode 100755 index 00000000..3632ac67 --- /dev/null +++ b/sli/.gitignore @@ -0,0 +1,38 @@ +#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## antlr4 generated files ##
+ExprGrammarBaseListener.java
+ExprGrammarLexer.java
+ExprGrammarListener.java
+ExprGrammarParser.java
+ExprGrammar.tokens
+ExprGrammarLexer.tokens
diff --git a/sli/common/pom.xml b/sli/common/pom.xml new file mode 100755 index 00000000..ce98b947 --- /dev/null +++ b/sli/common/pom.xml @@ -0,0 +1,150 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sli</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sli-common</artifactId> + <packaging>bundle</packaging> + + <name>SLI - Common Classes</name> + <description>The SLI Common package includes common classes used by the various SLI subcomponents, as well as classes used by clients to interface with the service logic interpreter</description> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.antlr</groupId> + <artifactId>antlr4</artifactId> + <version>${antlr.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.7.5</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>${commons.lang3.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>yang-binding</artifactId> + <version>${odl.mdsal.yang.binding.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-common</artifactId> + <version>${odl.yangtools.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-inet-types</artifactId> + <version>${odl.ietf-inet-types.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-yang-types</artifactId> + <version>${odl.ietf-yang-types.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>sal-core-api</artifactId> + <version>${odl.mdsal.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-data-impl</artifactId> + <version>${odl.yangtools.version}</version> + </dependency> + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>${equinox.osgi.version}</version> + </dependency> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>${mysql.connector.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + <version>${sdnctl.dblib.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <configuration> + <includes>**/*.xsd</includes> + <archive> + <manifest> + <mainClass>org.openecomp.sdnc.sli.SvcLogicParser</mainClass> + <packageName>org.openecomp.sdnc.sli</packageName> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package>org.openecomp.sdnc.sli;version=${project.version}</Export-Package> + <Import-Package>*</Import-Package> + <Embed-Dependency>*;scope=compile;artifactId=commons-lang|commons-lang3</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.antlr</groupId> + <artifactId>antlr4-maven-plugin</artifactId> + <version>${antlr.version}</version> + <executions> + <execution> + <configuration> + <outputDirectory>${project.basedir}/src/main/java/</outputDirectory> + </configuration> + <id>antlr</id> + <goals> + <goal>antlr4</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> diff --git a/sli/common/src/main/antlr4/org/openecomp/sdnc/sli/ExprGrammar.g4 b/sli/common/src/main/antlr4/org/openecomp/sdnc/sli/ExprGrammar.g4 new file mode 100755 index 00000000..51f40169 --- /dev/null +++ b/sli/common/src/main/antlr4/org/openecomp/sdnc/sli/ExprGrammar.g4 @@ -0,0 +1,66 @@ +grammar ExprGrammar; + +options { + language = Java; +} + + +COMPAREOP : '==' | '!=' | '>' | '<' | '>=' | '<='; + +RELOP : 'and' | 'or'; + +ADDOP : '+' | '-'; + +MULTOP : '/' | '*'; + +NUMBER : ('0'..'9')+; + +STRING : '\'' ~[\']* '\''; + +IDENTIFIER : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*; + +// CONTEXT_VAR : '$' IDENTIFIER; + +WS: [ \n\t\r]+ -> skip; + +constant : NUMBER | STRING ; + +variableLead : ('$')? variableTerm ; + +variableTerm : IDENTIFIER ('[' expr ']')? ; + +variable : variableLead ('.' variableTerm)* ('.')?; + +// variable : CONTEXT_VAR ( '[' expr ']' )? ('.' IDENTIFIER )? ; + +atom : constant | variable; + + +expr : atom + | parenExpr + | multExpr + | addExpr + | compareExpr + | relExpr + | funcExpr; + +parenExpr : '(' expr ')'; + +term : atom | parenExpr | funcExpr; + +multExpr : term (MULTOP term)*; + +addExpr : multExpr (ADDOP multExpr)*; + +compareExpr : addExpr COMPAREOP addExpr; + +relExpr : compareExpr (RELOP expr)*; + +funcExpr : IDENTIFIER '(' expr (',' expr)* ')'; + + + + + + + diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/BreakNodeException.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/BreakNodeException.java new file mode 100644 index 00000000..3e355baa --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/BreakNodeException.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +public class BreakNodeException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public BreakNodeException() + { + super(); + } + + public BreakNodeException(String message) + { + super(message); + } + + public BreakNodeException(String message, Throwable t) + { + super(message, t); + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/ConfigurationException.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/ConfigurationException.java new file mode 100644 index 00000000..fa1308f0 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/ConfigurationException.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +public class ConfigurationException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ConfigurationException() + { + super(); + } + + public ConfigurationException(String msg) + { + super(msg); + } + + public ConfigurationException(String msg, Throwable t) + { + super(msg, t); + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/DuplicateValueException.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/DuplicateValueException.java new file mode 100644 index 00000000..beb22b0b --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/DuplicateValueException.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +public class DuplicateValueException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public DuplicateValueException() + { + super(); + } + + public DuplicateValueException(String message) + { + super(message); + } + + public DuplicateValueException(String message, Throwable t) + { + super(message, t); + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/MessageWriter.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/MessageWriter.java new file mode 100644 index 00000000..5e5b621b --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/MessageWriter.java @@ -0,0 +1,302 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.File; +import java.io.FileInputStream; +import java.sql.SQLException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Properties; + +import javax.sql.rowset.CachedRowSet; + +import org.openecomp.sdnc.sli.resource.dblib.DbLibService; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class MessageWriter { + + private static final Logger LOG = LoggerFactory.getLogger(MessageWriter.class); + + private static final String DBLIB_SERVICE = "org.openecomp.sdnc.sli.resource.dblib.DBResourceManager"; + private static final String SVCLOGIC_PROP_VAR = "SDNC_SLI_PROPERTIES"; + private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; + + private static final String INCOMING_PROPERTY_NAME = "org.openecomp.sdnc.sli.MessageWriter.writeIncomingRequests"; + private static final String OUTGOING_PROPERTY_NAME = "org.openecomp.sdnc.sli.MessageWriter.writeOutgoingRequests"; + + private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + + private static DbLibService dbLibService = null; + + private static boolean incomingEnabled = false; + private static boolean outgoingEnabled = false; + + private static boolean initialized = false; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static void init() { + if (initialized) + return; + + initialized = true; + + // Read properties + Properties props = new Properties(); + String propPath = System.getenv(SVCLOGIC_PROP_VAR); + + if (propPath == null) { + String propDir = System.getenv(SDNC_CONFIG_DIR); + if (propDir == null) { + propDir = "/opt/sdnc/data/properties"; + } + propPath = propDir + "/svclogic.properties"; + LOG.warn("Environment variable " + SVCLOGIC_PROP_VAR + " unset - defaulting to " + propPath); + } + + File propFile = new File(propPath); + + if (!propFile.exists()) { + LOG.warn("Property file does not exist: " + propPath); + } + + try { + props.load(new FileInputStream(propFile)); + } catch (Exception e) { + LOG.warn("Error loading property file: " + propPath, e); + } + + incomingEnabled = Boolean.valueOf(props.getProperty(INCOMING_PROPERTY_NAME, "false")); + outgoingEnabled = Boolean.valueOf(props.getProperty(OUTGOING_PROPERTY_NAME, "false")); + + LOG.info(INCOMING_PROPERTY_NAME + ": " + incomingEnabled); + LOG.info(OUTGOING_PROPERTY_NAME + ": " + outgoingEnabled); + + if (dbLibService != null) + return; + + BundleContext bctx = FrameworkUtil.getBundle(MessageWriter.class).getBundleContext(); + + ServiceReference sref = bctx.getServiceReference(DBLIB_SERVICE); + + if (sref == null) { + LOG.warn("Could not find service reference for DBLIB service (" + DBLIB_SERVICE + ")"); + } else { + dbLibService = (DbLibService) bctx.getService(sref); + if (dbLibService == null) { + LOG.warn("Could not find service reference for DBLIB service (" + DBLIB_SERVICE + ")"); + } + } + } + + public static void saveOutgoingRequest( + String requestId, + String serviceInstanceId, + String targetUrl, + String request) { + try { + init(); + + if (!outgoingEnabled) + return; + + if (serviceInstanceId == null || serviceInstanceId.trim().length() == 0) + serviceInstanceId = "NA"; + + int seqnum = getLastSequenceNumber("OUTGOING_MESSAGE", requestId) + 1; + String now = df.format(new Date()); + + String sql = "INSERT INTO OUTGOING_MESSAGE (\n" + + " request_id, sequence_number, service_instance_id, target_url, request, start_time)\n" + + "VALUES (?, ?, ?, ?, ?, ?)"; + + ArrayList<String> data = new ArrayList<>(); + data.add(requestId); + data.add(String.valueOf(seqnum)); + data.add(serviceInstanceId); + data.add(targetUrl); + data.add(request); + data.add(now); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save outgoing request for request-id: " + requestId, e); + } + } + + public static void saveOutgoingResponse(String requestId, int httpResponseCode, String response) { + try { + init(); + + if (!outgoingEnabled) + return; + + int seqnum = getLastSequenceNumber("OUTGOING_MESSAGE", requestId); + if (seqnum == 0) { + LOG.warn("Failed to save outgoing response for request-id: " + requestId + + ": Request record not found in OUTGOING_MESSAGE"); + return; + } + + String now = df.format(new Date()); + + String sql = "UPDATE OUTGOING_MESSAGE SET http_response_code = ?, response = ?,\n" + + " duration = timestampdiff(MICROSECOND, start_time, ?) / 1000\n" + + "WHERE request_id = ? AND sequence_number = ?"; + + ArrayList<String> data = new ArrayList<>(); + data.add(String.valueOf(httpResponseCode)); + data.add(response); + data.add(now); + data.add(requestId); + data.add(String.valueOf(seqnum)); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save outgoing response for request-id: " + requestId, e); + } + } + + public static void saveIncomingRequest( + String requestId, + String serviceInstanceId, + String requestHost, + String request) { + try { + init(); + + if (!incomingEnabled) + return; + + if (serviceInstanceId == null || serviceInstanceId.trim().length() == 0) + serviceInstanceId = "NA"; + + int seqnum = getLastSequenceNumber("INCOMING_MESSAGE", requestId) + 1; + String now = df.format(new Date()); + + String sql = "INSERT INTO INCOMING_MESSAGE (\n" + + " request_id, sequence_number, service_instance_id, request_host, request, start_time)\n" + + "VALUES (?, ?, ?, ?, ?, ?)"; + + ArrayList<String> data = new ArrayList<>(); + data.add(requestId); + data.add(String.valueOf(seqnum)); + data.add(serviceInstanceId); + data.add(requestHost); + data.add(request); + data.add(now); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save incoming request for request-id: " + requestId, e); + } + } + + public static void saveIncomingResponse(String requestId, int httpResponseCode, String response) { + try { + init(); + + if (!incomingEnabled) + return; + + int seqnum = getLastSequenceNumber("INCOMING_MESSAGE", requestId); + if (seqnum == 0) { + LOG.warn("Failed to save response for request-id: " + requestId + + ": Request record not found in INCOMING_MESSAGE"); + return; + } + + String now = df.format(new Date()); + + String sql = "UPDATE INCOMING_MESSAGE SET http_response_code = ?, response = ?,\n" + + " duration = timestampdiff(MICROSECOND, start_time, ?) / 1000\n" + + "WHERE request_id = ? AND sequence_number = ?"; + + ArrayList<String> data = new ArrayList<>(); + data.add(String.valueOf(httpResponseCode)); + data.add(response); + data.add(now); + data.add(requestId); + data.add(String.valueOf(seqnum)); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save response for request-id: " + requestId, e); + } + } + + public static String getServiceInstanceId(String requestId) throws SQLException { + init(); + + String sql = "SELECT service_instance_id FROM OUTGOING_MESSAGE WHERE request_id = '" + requestId + + "' ORDER BY sequence_number DESC"; + + CachedRowSet rs = null; + try { + rs = dbLibService.getData(sql, null, null); + if (rs.next()) { + return rs.getString("service_instance_id"); + } + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception e) { + LOG.warn("Failed to close CachedRowSet", e); + } + } + } + return null; + } + + private static int getLastSequenceNumber(String tableName, String requestId) throws SQLException { + String sql = "SELECT sequence_number FROM " + tableName + " WHERE request_id = '" + requestId + + "' ORDER BY sequence_number DESC"; + + CachedRowSet rs = null; + try { + rs = dbLibService.getData(sql, null, null); + if (rs.next()) { + return rs.getInt("sequence_number"); + } + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception e) { + LOG.warn("Failed to close CachedRowSet", e); + } + } + } + return 0; + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/MetricLogger.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/MetricLogger.java new file mode 100644 index 00000000..14b1f008 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/MetricLogger.java @@ -0,0 +1,301 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +package org.openecomp.sdnc.sli; + +import java.net.InetAddress; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +/** + * @author dt5972 + * + */ +public class MetricLogger { + + private static final Logger KARAF = LoggerFactory.getLogger(MetricLogger.class); + private static final Logger METRIC = LoggerFactory.getLogger("org.openecomp.sdnc.filters.metric"); + + public static final String BEGIN_TIMESTAMP = "X-ECOMP-BeginTimestamp"; + public static final String END_TIMESTAMP = "X-ECOMP-EndTimestamp"; + public static final String REQUEST_ID = "X-ECOMP-RequestID"; + public static final String SERVICE_INSTANCE_ID = "X-ECOMP-ServiceInstanceID"; + public static final String SERVICE_NAME = "X-ECOMP-ServiceName"; + public static final String PARTNER_NAME = "X-ECOMP-PartnerName"; + public static final String TARGET_ENTITY = "X-ECOMP-TargetEntity"; + public static final String TARGET_SERVICE_NAME = "X-ECOMP-TargetServiceName"; + public static final String STATUS_CODE = "X-ECOMP-StatusCode"; + public static final String RESPONSE_CODE = "X-ECOMP-ResponseCode"; + public static final String RESPONSE_DESCRIPTION = "X-ECOMP-ResponseDescription"; + public static final String INSTANCE_UUID = "X-ECOMP-InstanceUUID"; + public static final String CATEGORY_LOG_LEVEL = "X-ECOMP-CategoryLogLevel"; + public static final String SEVERITY = "X-ECOMP-Severity"; + public static final String SERVER_IP_ADDRESS = "X-ECOMP-ServerIpAddress"; + public static final String ELAPSED_TIME = "X-ECOMP-ElapsedTime"; + public static final String SERVER = "X-ECOMP-Server"; + public static final String CLIENT_IP = "X-ECOMP-ClientIp"; + public static final String CLASS_NAME = "X-ECOMP-ClassName"; + public static final String TARGET_VIRTUAL_ENTITY = "X-ECOMP-TargetVirtualEntity"; + + private long beginTimestamp; + private String lastMsg = null; + + public MetricLogger() { + beginTimestamp = System.currentTimeMillis(); + + try { + InetAddress localhost = InetAddress.getLocalHost(); + setServerIpAddress(localhost.getHostAddress()); + setServer(localhost.getCanonicalHostName()); + } catch (Exception e) { + KARAF.error("Could not get localhost", e); + } + + } + + + public String getBeginTimestamp() { + return MDC.get(BEGIN_TIMESTAMP); + } + + private void setBeginTimestamp(long beginTimestamp) { + this.beginTimestamp = beginTimestamp; + MDC.put(BEGIN_TIMESTAMP, MetricLogger.asIso8601(beginTimestamp)); + } + + public String getEndTimestamp() { + return MDC.get(END_TIMESTAMP); + } + + private void setEndTimestamp(long endTimestamp) { + // Set MDC with formatted time stamp + MDC.put(END_TIMESTAMP, MetricLogger.asIso8601(endTimestamp)); + + // Set elapsed time + setElapsedTime(endTimestamp - beginTimestamp); + + } + + public String getRequestID() { + return MDC.get(REQUEST_ID); + } + + + public String getServiceInstanceID() { + return MDC.get(SERVICE_INSTANCE_ID); + } + + private void setServiceInstanceID(String svcInstanceId) { + MDC.put(SERVICE_INSTANCE_ID, svcInstanceId); + } + + public String getServiceName() { + return MDC.get(SERVICE_NAME); + } + + private void setServiceName(String svcName) { + MDC.put(SERVICE_NAME, svcName); + } + + public String getPartnerName() { + return MDC.get(PARTNER_NAME); + } + + private void setPartnerName(String partnerName) { + MDC.put(PARTNER_NAME, partnerName); + } + + public String getTargetEntity() { + return MDC.get(TARGET_ENTITY); + } + + private void setTargetEntity(String targetEntity) { + MDC.put(TARGET_ENTITY, targetEntity); + } + + public String getTargetServiceName() { + return MDC.get(TARGET_SERVICE_NAME); + } + + private void setTargetServiceName(String targetServiceName) { + MDC.put(TARGET_SERVICE_NAME, targetServiceName); + } + + public String getStatusCode() { + return MDC.get(STATUS_CODE); + } + + private void setStatusCode(String statusCode) { + MDC.put(STATUS_CODE, statusCode); + } + + public String getResponseCode() { + return MDC.get(RESPONSE_CODE); + } + + private void setResponseCode(String responseCode) { + MDC.put(RESPONSE_CODE, responseCode); + } + + public String getResponseDescription() { + return MDC.get(RESPONSE_DESCRIPTION); + } + + private void setResponseDescription(String responseDesc) { + MDC.put(RESPONSE_DESCRIPTION, responseDesc); + } + + public String getInstanceUUID() { + return MDC.get(INSTANCE_UUID); + } + + private void setInstanceUUID(String instanceUUID) { + MDC.put(INSTANCE_UUID, instanceUUID); + } + + public String getCategoryLogLevel() { + return MDC.get(CATEGORY_LOG_LEVEL); + } + + private void setCategoryLogLevel(String categoryLogLevel) { + MDC.put(CATEGORY_LOG_LEVEL, categoryLogLevel); + } + + public String getSeverity() { + return MDC.get(SEVERITY); + } + + private void setSeverity(String severity) { + MDC.put(SEVERITY, severity); + } + + public String getServerIpAddress() { + return MDC.get(SERVER_IP_ADDRESS); + } + + private void setServerIpAddress(String serverIpAddress) { + MDC.put(SERVER_IP_ADDRESS, serverIpAddress); + } + + public String getElapsedTime() { + return MDC.get(ELAPSED_TIME); + } + + private void setElapsedTime(long elapsedTime) { + MDC.put(ELAPSED_TIME, ""+elapsedTime); + } + + public String getServer() { + return MDC.get(SERVER); + } + + private void setServer(String server) { + MDC.put(SERVER, server); + } + + public String getClientIp() { + return MDC.get(CLIENT_IP); + } + + private void setClientIp(String clientIp) { + MDC.put(CLIENT_IP, clientIp); + } + + public String getClassName() { + return MDC.get(CLASS_NAME); + } + + private void setClassName(String className) { + MDC.put(CLASS_NAME, className); + } + + public String getTargetVirtualEntity() { + return MDC.get(TARGET_VIRTUAL_ENTITY); + } + + private void setTargetVirtualEntity(String targetVirtualEntity) { + MDC.put(TARGET_VIRTUAL_ENTITY, targetVirtualEntity); + } + + public static String asIso8601(Date date) { + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss:SS'+00:00'"); + df.setTimeZone(tz); + return df.format(date); + } + + public static String asIso8601(long tsInMillis) { + return MetricLogger.asIso8601(new Date(tsInMillis)); + } + + public void logRequest(String svcInstanceId, String svcName, String partnerName, String targetEntity, String targetServiceName, String targetVirtualEntity, String msg) { + + setBeginTimestamp(System.currentTimeMillis()); + + if (svcInstanceId != null) { + setServiceInstanceID(svcInstanceId); + } + + if (svcName != null) { + setServiceName(svcName); + } + + if (partnerName != null) { + setPartnerName(partnerName); + } + + if (targetEntity != null) { + setTargetEntity(targetEntity); + } + + if (targetServiceName != null) { + setTargetServiceName(targetServiceName); + } + + if (targetVirtualEntity != null) { + setTargetVirtualEntity(targetVirtualEntity); + } + + this.lastMsg = msg; + + + } + + public void logResponse(String statusCode, String responseCode, String responseDescription) { + setEndTimestamp(System.currentTimeMillis()); + + setStatusCode(statusCode); + setResponseCode(responseCode); + setResponseDescription(responseDescription); + + METRIC.info(lastMsg); + + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicAdaptor.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicAdaptor.java new file mode 100644 index 00000000..b4d62ab4 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicAdaptor.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.Map; + +public interface SvcLogicAdaptor { + + public enum ConfigStatus { + SUCCESS, + ALREADY_ACTIVE, + NOT_FOUND, + NOT_READY, + FAILURE + } + + public ConfigStatus configure(String key, Map<String,String> parameters, SvcLogicContext ctx); + + public ConfigStatus activate(String key, SvcLogicContext ctx); + + public ConfigStatus deactivate(String key, SvcLogicContext ctx); + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicAtom.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicAtom.java new file mode 100644 index 00000000..9ac64893 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicAtom.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +public class SvcLogicAtom extends SvcLogicExpression { + + public enum AtomType { + NUMBER, + STRING, + IDENTIFIER, + CONTEXT_VAR + + } + + private AtomType atomType; + private String atom; + + + public SvcLogicAtom(String atomType, String atom) + { + this.atomType = AtomType.valueOf(atomType); + this.atom = atom; + + } + + public SvcLogicAtom(String atom) + { + + if (atom == null) + { + this.atomType = null; + this.atom = null; + } + else + { + if (atom.startsWith("$")) + { + this.atomType = AtomType.CONTEXT_VAR; + this.atom = atom.substring(1); + } + else + { + if (Character.isDigit(atom.charAt(0))) + { + this.atomType = AtomType.NUMBER; + this.atom = atom; + } + else if (atom.charAt(0) == '\'') + { + this.atomType = AtomType.STRING; + this.atom = atom.substring(1, atom.length()-1); + } + else + { + this.atomType = AtomType.IDENTIFIER; + this.atom = atom; + + } + + } + } + } + + public AtomType getAtomType() { + return atomType; + } + + public void setAtomType(String newType) + { + atomType = AtomType.valueOf(newType); + } + + public String getAtom() { + return atom; + } + + + + public void setAtomType(AtomType atomType) { + this.atomType = atomType; + } + + public void setAtom(String atom) { + this.atom = atom; + } + + + + public String toString() + { + StringBuffer sbuff = new StringBuffer(); + switch(getAtomType()) + { + case CONTEXT_VAR: + sbuff.append("$"); + case IDENTIFIER: + boolean needDot = false; + for (SvcLogicExpression term: this.getOperands()) + { + if (needDot) + { + sbuff.append("."); + } + sbuff.append(term.toString()); + needDot = true; + } + return(sbuff.toString()); + case STRING: + case NUMBER: + default: + return(atom); + } + } + + public String asParsedExpr() + { + // simplify debugging output for NUMBER type + if (atomType == AtomType.NUMBER) { + return atom; + } + + StringBuffer sbuff = new StringBuffer(); + + sbuff.append("(atom"); + sbuff.append("<"); + sbuff.append(atomType.toString()); + sbuff.append(">"); + + switch(atomType) + { + case IDENTIFIER: + case CONTEXT_VAR: + for (SvcLogicExpression term : getOperands()) + { + sbuff.append(" "); + sbuff.append(term.asParsedExpr()); + + } + break; + default: + sbuff.append(" "); + sbuff.append(atom); + } + + sbuff.append(")"); + return(sbuff.toString()); + } + + + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicBinaryExpression.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicBinaryExpression.java new file mode 100644 index 00000000..1d780d7e --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicBinaryExpression.java @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.LinkedList; +import java.util.List; + +public class SvcLogicBinaryExpression extends SvcLogicExpression { + + + public enum OperatorType { + addOp("+"), + subOp("-"), + multOp("*"), + divOp("/"), + equalOp("=="), + ltOp("<"), + leOp("<="), + gtOp(">"), + geOp(">="), + neOp("!="), + andOp("and"), + orOp("or"); + + private String text; + + private OperatorType(String text) + { + this.text = text; + } + + public String getText() + { + return(text); + } + + public static OperatorType fromString(String text) + { + if (text != null) + { + for (OperatorType t : OperatorType.values()) + { + if (text.equalsIgnoreCase(t.getText())) { + + return(t); + } + } + } + return(null); + } + + public String toString() + { + return(text); + } + } + private List<OperatorType> operators; + + public List<OperatorType> getOperators() { + return operators; + } + + public SvcLogicBinaryExpression() + { + operators = new LinkedList<OperatorType>(); + } + + public void addOperator(String operator) + { + operators.add(OperatorType.fromString(operator)); + } + + + public String toString() + { + + List<SvcLogicExpression>operands = getOperands(); + StringBuffer sbuff = new StringBuffer(); + + sbuff.append(operands.get(0).toString()); + for (int i = 0 ; i < operators.size(); i++) + { + sbuff.append(" "); + sbuff.append(operators.get(i)); + sbuff.append(" "); + if (i + 1 < operands.size()) { + sbuff.append(operands.get(i + 1).toString()); + } else { + // expression incomplete; operand not bound yet + sbuff.append("?"); + } + } + + return(sbuff.toString()); + + } + + public String asParsedExpr() { + + List<SvcLogicExpression> operands = getOperands(); + + if (operators.isEmpty()) { + return operands.get(0).asParsedExpr(); + } else { + StringBuffer sbuff = new StringBuffer(); + // operators in reverse order for left associativity + for (int i = operators.size() - 1; i >= 0; --i) { + sbuff.append("("); + sbuff.append(operators.get(i).getText()); + sbuff.append(" "); + } + for (int i = 0; i < operators.size() + 1; ++i) { + if (i < operands.size()) { + sbuff.append(operands.get(i).asParsedExpr()); + } else { + // expression incomplete; operand not bound yet + sbuff.append("?"); + } + if (i != 0) { + sbuff.append(")"); + } + if (i < operators.size()) { + sbuff.append(" "); + } + } + return sbuff.toString(); + } + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicContext.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicContext.java new file mode 100644 index 00000000..79082af2 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicContext.java @@ -0,0 +1,248 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + + +public class SvcLogicContext { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicContext.class); + + private HashMap<String, String> attributes; + + private DOMDataBroker domDataBroker; + + private String status = "success"; + + public SvcLogicContext() + { + this.attributes = new HashMap<String,String> (); + + } + + public SvcLogicContext(Properties props) + { + this.attributes = new HashMap<String, String> (); + + if (props.containsKey("SvcLogic.status")) + { + this.status = props.getProperty("SvcLogic.status"); + } + + for (Object nameObj : props.keySet()) + { + String propName = (String) nameObj; + attributes.put(propName, props.getProperty(propName)); + } + } + + + + public DOMDataBroker getDomDataBroker() { + return domDataBroker; + } + + public void setDomDataBroker(DOMDataBroker domDataBroker) { + this.domDataBroker = domDataBroker; + } + + public String getAttribute(String name) + { + if (attributes.containsKey(name)) + { + return(attributes.get(name)); + } + else + { + return(null); + } + } + + public void setAttribute(String name, String value) + { + if (value == null) { + if (attributes.containsKey(name)) { + attributes.remove(name); + } + } else { + attributes.put(name, value); + } + } + + public Set<String> getAttributeKeySet() + { + return(attributes.keySet()); + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public Properties toProperties() + { + Properties props = new Properties(); + + if (status != null) + { + props.setProperty("SvcLogic.status", status); + } + + for (String attrName : attributes.keySet()) + { + String attrVal = attributes.get(attrName); + if (attrVal == null) { + LOG.warn("attribute " + attrName + + "null - setting to empty string"); + props.setProperty(attrName, ""); + } else { + props.setProperty(attrName, attributes.get(attrName)); + } + } + + return(props); + } + + public void mergeDocument(String pfx, Document doc) { + String prefix = ""; + + if (pfx != null) { + prefix = pfx; + } + + Element root = doc.getDocumentElement(); + + mergeElement(prefix, root, null); + } + + public void mergeElement(String pfx, Element element, Map<String, Integer> nodeMap) { + + // In XML, cannot tell the difference between containers and lists. + // So, have to treat each element as both (ugly but necessary). + // We do this by passing a nodeMap to be used to count instance of each tag, + // which will be used to set _length and to set index + + LOG.trace("mergeElement("+pfx+","+element.getTagName()+","+nodeMap+")"); + + String curTagName = element.getTagName(); + String prefix = curTagName; + + if (pfx != null) { + prefix = pfx + "." + prefix; + } + + int myIdx = 0; + + if (nodeMap != null) { + if (nodeMap.containsKey(curTagName)) { + myIdx = nodeMap.get(curTagName).intValue(); + } + + nodeMap.put(curTagName, new Integer(myIdx+1)); + this.setAttribute(prefix+"_length", ""+(myIdx+1)); + } + + NodeList children = element.getChildNodes(); + + int numChildren = children.getLength(); + + Map<String, Integer> childMap = new HashMap<String, Integer>(); + Map<String, Integer> idxChildMap = new HashMap<String, Integer>(); + + for (int i = 0 ; i < numChildren ; i++) { + Node curNode = children.item(i); + + if (curNode instanceof Text) { + Text curText = (Text) curNode; + String curTextValue = curText.getTextContent(); + LOG.trace("Setting ctx variable "+prefix+" = "+curTextValue); + this.setAttribute(prefix, curText.getTextContent()); + + + } else if (curNode instanceof Element) { + mergeElement(prefix, (Element) curNode, childMap); + if (nodeMap != null) { + + mergeElement(prefix+"["+myIdx+"]", (Element)curNode, idxChildMap); + + } + } + } + + } + + public String resolve(String ctxVarName) { + + if (ctxVarName.indexOf('[') == -1) { + // Ctx variable contains no arrays + return (this.getAttribute(ctxVarName)); + } + + // Resolve any array references + StringBuffer sbuff = new StringBuffer(); + String[] ctxVarParts = ctxVarName.split("\\["); + sbuff.append(ctxVarParts[0]); + for (int i = 1; i < ctxVarParts.length; i++) { + if (ctxVarParts[i].startsWith("$")) { + int endBracketLoc = ctxVarParts[i].indexOf("]"); + if (endBracketLoc == -1) { + // Missing end bracket ... give up parsing + LOG.warn("Variable reference " + ctxVarName + + " seems to be missing a ']'"); + return (this.getAttribute(ctxVarName)); + } + + String idxVarName = ctxVarParts[i].substring(1, endBracketLoc); + String remainder = ctxVarParts[i].substring(endBracketLoc); + + sbuff.append("["); + sbuff.append(this.getAttribute(idxVarName)); + sbuff.append(remainder); + + } else { + // Index is not a variable reference + sbuff.append("["); + sbuff.append(ctxVarParts[i]); + } + } + + return (this.getAttribute(sbuff.toString())); + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicDblibStore.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicDblibStore.java new file mode 100644 index 00000000..d494eaab --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicDblibStore.java @@ -0,0 +1,533 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.Blob; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Properties; + +import javax.sql.rowset.CachedRowSet; + +import org.openecomp.sdnc.sli.resource.dblib.DBResourceManager; +import org.openecomp.sdnc.sli.resource.dblib.DbLibService; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicDblibStore implements SvcLogicStore { + + private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicDblibStore.class); + + private static final String DBLIB_SERVICE = + // "org.openecomp.sdnc.sli.resource.dblib.DBLibService"; + "org.openecomp.sdnc.sli.resource.dblib.DBResourceManager"; + + Properties props = null; + + public void init(Properties props) throws ConfigurationException { + + DbLibService dbSvc = getDbLibService(); + if(dbSvc == null) { + LOG.error("SvcLogic cannot acquire DBLIB_SERVICE"); + return; + } + try { + dbSvc.getData("select 1 from DUAL", new ArrayList<String>(), null); + LOG.debug("SQL test was successful"); + } catch (SQLException e) { + LOG.error("Failed SQL test", e); + } + } + + public boolean hasGraph(String module, String rpc, String version, + String mode) throws SvcLogicException { + + DbLibService dbSvc = getDbLibService(); + + boolean retval = false; + CachedRowSet results = null; + String hasVersionGraphSql = "SELECT count(*) FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + String hasActiveGraphSql = "SELECT count(*) FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; + + PreparedStatement hasGraphStmt = null; + + ArrayList<String> args = new ArrayList<String>(); + args.add(module); + args.add(rpc); + args.add(mode); + + try { + + if (version == null) { + results = dbSvc.getData(hasActiveGraphSql, args, null); + } else { + args.add(version); + results = dbSvc.getData(hasVersionGraphSql, args, null); + } + + if (results.next()) { + int cnt = results.getInt(1); + + if (cnt > 0) { + retval = true; + } + + } + } catch (Exception e) { + throw new ConfigurationException("SQL query failed", e); + } finally { + if (results != null) { + try { + + results.close(); + } catch (SQLException x) { + } + } + + } + + return (retval); + + } + + public SvcLogicGraph fetch(String module, String rpc, String version, + String mode) throws SvcLogicException { + + DbLibService dbSvc = getDbLibService(); + + Connection dbConn = null; + SvcLogicGraph retval = null; + ResultSet results = null; + + String fetchVersionGraphSql = "SELECT graph FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + String fetchActiveGraphSql = "SELECT graph FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; + + + try { + dbConn = ((DBResourceManager) dbSvc).getConnection(); + PreparedStatement fetchGraphStmt; + + ArrayList<String> args = new ArrayList<String>(); + args.add(module); + args.add(rpc); + args.add(mode); + + if (version == null) { + fetchGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql); + } else { + fetchGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql); + } + + fetchGraphStmt.setString(1, module); + fetchGraphStmt.setString(2, rpc); + fetchGraphStmt.setString(3, mode); + if (version != null) { + fetchGraphStmt.setString(4,version); + } + + results = fetchGraphStmt.executeQuery(); + + if (results.next()) { + Blob graphBlob = results.getBlob("graph"); + + ObjectInputStream gStream = new ObjectInputStream( + graphBlob.getBinaryStream()); + + Object graphObj = gStream.readObject(); + gStream.close(); + + if (graphObj instanceof SvcLogicGraph) { + retval = (SvcLogicGraph) graphObj; + } else { + throw new ConfigurationException("invalid type for graph (" + + graphObj.getClass().getName()); + + } + + } else { + return (null); + } + } catch (SQLException e) { + throw new ConfigurationException("SQL query failed", e); + } catch (Exception e) { + throw new ConfigurationException("Graph processing failed", e); + } finally { + if (results != null) { + try { + results.close(); + } catch (SQLException x) { + } + } + try { + if (dbConn != null && !dbConn.isClosed()) { + dbConn.close(); + } + } catch (Throwable exc) { + // the exception not monitored + } finally { + dbConn = null; + } + + } + + return (retval); + + } + + public void store(SvcLogicGraph graph) throws SvcLogicException { + + DbLibService dbSvc = getDbLibService(); + + String storeGraphSql = "INSERT INTO SVC_LOGIC (module, rpc, version, mode, active, graph)" + + " VALUES(?, ?, ?, ?, ?, ?)"; + + if (graph == null) { + throw new SvcLogicException("graph cannot be null"); + } + + byte[] graphBytes = null; + + ByteArrayOutputStream byteStr = null; + ObjectOutputStream goutStr = null; + + try { + byteStr = new ByteArrayOutputStream(); + goutStr = new ObjectOutputStream(byteStr); + goutStr.writeObject(graph); + + graphBytes = byteStr.toByteArray(); + + } catch (Exception e) { + throw new SvcLogicException("could not serialize graph", e); + } finally { + + if (goutStr != null) { + try { + goutStr.close(); + } catch (IOException e) { + + } + } + + if (byteStr != null) { + try { + byteStr.close(); + } catch (IOException e) { + + } + } + } + + // If object already stored in database, delete it + if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(), + graph.getMode())) { + delete(graph.getModule(), graph.getRpc(), graph.getVersion(), + graph.getMode()); + } + + Connection dbConn = null; + + try { + dbConn = ((DBResourceManager) dbSvc).getConnection(); + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + PreparedStatement storeGraphStmt = dbConn + .prepareStatement(storeGraphSql); + storeGraphStmt.setString(1, graph.getModule()); + storeGraphStmt.setString(2, graph.getRpc()); + storeGraphStmt.setString(3, graph.getVersion()); + storeGraphStmt.setString(4, graph.getMode()); + storeGraphStmt.setString(5, "N"); + storeGraphStmt.setBlob(6, new ByteArrayInputStream(graphBytes)); + + storeGraphStmt.executeUpdate(); + dbConn.commit(); + + dbConn.setAutoCommit(oldAutoCommit); + } catch (Exception e) { + throw new SvcLogicException("Could not write object to database", e); + } finally { + try { + if (dbConn != null && !dbConn.isClosed()) { + dbConn.close(); + } + } catch (Throwable exc) { + // the exception not monitored + } finally { + dbConn = null; + } + + } + } + + public void delete(String module, String rpc, String version, String mode) + throws SvcLogicException { + + DbLibService dbSvc = getDbLibService(); + + String deleteGraphSql = "DELETE FROM SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?"; + + ArrayList<String> args = new ArrayList<String>(); + + args.add(module); + args.add(rpc); + args.add(version); + args.add(mode); + + try { + dbSvc.writeData(deleteGraphSql, args, null); + } catch (Exception e) { + throw new SvcLogicException( + "Could not delete object from database", e); + } + } + + public void activate(SvcLogicGraph graph) throws SvcLogicException { + DbLibService dbSvc = getDbLibService(); + + String deactivateSql = "UPDATE SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?"; + + String activateSql = "UPDATE SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + ArrayList<String> args = new ArrayList<String>(); + + args.add(graph.getModule()); + args.add(graph.getRpc()); + args.add(graph.getMode()); + + try { + + dbSvc.writeData(deactivateSql, args, null); + + args.add(graph.getVersion()); + dbSvc.writeData(activateSql, args, null); + + } catch (Exception e) { + throw new SvcLogicException("Could not activate graph", e); + } + } + + @Override + public void registerNodeType(String nodeType) throws SvcLogicException { + + String registerNodeSql = "INSERT INTO NODE_TYPES (nodetype) VALUES(?)"; + + if (isValidNodeType(nodeType)) { + return; + } + + DbLibService dbSvc = getDbLibService(); + ArrayList<String> args = new ArrayList<String>(); + + args.add(nodeType); + + try { + dbSvc.writeData(registerNodeSql, args, null); + } catch (Exception e) { + throw new SvcLogicException("Could not add node type to database", + e); + } + + } + + @Override + public void unregisterNodeType(String nodeType) throws SvcLogicException { + + if (!isValidNodeType(nodeType)) { + return; + } + + String unregisterNodeSql = "DELETE FROM NODE_TYPES WHERE nodetype = ?"; + + DbLibService dbSvc = getDbLibService(); + ArrayList<String> args = new ArrayList<String>(); + + args.add(nodeType); + + try { + dbSvc.writeData(unregisterNodeSql, args, null); + } catch (Exception e) { + throw new SvcLogicException( + "Could not delete node type from database", e); + } + + } + + @Override + public boolean isValidNodeType(String nodeType) throws SvcLogicException { + + String validateNodeSql = "SELECT count(*) FROM NODE_TYPES WHERE nodetype = ?"; + + DbLibService dbSvc = getDbLibService(); + + ArrayList<String> args = new ArrayList<String>(); + + args.add(nodeType); + + boolean isValid = false; + + CachedRowSet results = null; + try { + results = dbSvc.getData(validateNodeSql, args, null); + if (results != null) { + if (results.next()) { + int cnt = results.getInt(1); + + if (cnt > 0) { + isValid = true; + } + } + } + } catch (Exception e) { + throw new SvcLogicException( + "Cannot select node type from database", e); + } finally { + if (results != null) { + try { + results.close(); + } catch (SQLException x) { + } + } + + } + + return (isValid); + } + + private DbLibService getDbLibService() { + + // Get DbLibService interface object. + DbLibService dblibSvc = null; + ServiceReference sref = null; + BundleContext bctx = null; + + Bundle bundle = FrameworkUtil.getBundle(SvcLogicDblibStore.class); + + if (bundle != null) { + bctx = bundle.getBundleContext(); + + if (bctx != null) { + sref = bctx.getServiceReference(DBLIB_SERVICE); + } + + if (sref == null) { + LOG.warn("Could not find service reference for DBLIB service (" + + DBLIB_SERVICE + ")"); + } else { + dblibSvc = (DbLibService) bctx.getService(sref); + if (dblibSvc == null) { + + LOG.warn("Could not find service reference for DBLIB service (" + + DBLIB_SERVICE + ")"); + } + } + } + + // initialize a stand-alone instance of dblib resource + else { + // Try to create a DbLibService object from dblib properties + if(JavaSingleton.getInstance() == null){ + Properties dblibProps = new Properties(); + + String propDir = System.getenv(SDNC_CONFIG_DIR); + if (propDir == null) { + + propDir = "/opt/sdnc/data/properties"; + } + String propPath = propDir + "/dblib.properties"; + + File propFile = new File(propPath); + + if (!propFile.exists()) { + + LOG.warn( + "Missing configuration properties file : " + + propFile); + return(null); + } + + try { + + dblibProps.load(new FileInputStream(propFile)); + } catch (Exception e) { + LOG.warn( + "Could not load properties file " + propPath, e); + return(null); + + } + + try { + dblibSvc = DBResourceManager.create(dblibProps); + JavaSingleton.setInstance(dblibSvc); + } catch (Exception e) { + LOG.warn("Caught exception trying to create DBResourceManager", e); + } + } else { + dblibSvc = JavaSingleton.getInstance(); + } + } + return (dblibSvc); + } + + + static class JavaSingleton { + /* Private constructor */ + private JavaSingleton() { + /* the body of the constructor here */ + } + + /* instance of the singleton declaration */ + private static volatile DbLibService INSTANCE ; + + /* Access point to the unique instance of the singleton */ + public static DbLibService getInstance() { + return INSTANCE; + } + + public static void setInstance(DbLibService dbresource) { + INSTANCE = dbresource; + } + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicException.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicException.java new file mode 100644 index 00000000..c087b8ad --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicException.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +public class SvcLogicException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public SvcLogicException() + { + super(); + } + + public SvcLogicException(String message) + { + super(message); + } + + public SvcLogicException(String message, Throwable t) + { + super(message, t); + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExprListener.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExprListener.java new file mode 100644 index 00000000..4fef12fb --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExprListener.java @@ -0,0 +1,316 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.LinkedList; +import java.util.List; + +import org.antlr.v4.runtime.tree.TerminalNode; +import org.openecomp.sdnc.sli.ExprGrammarParser.AddExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.AtomContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.CompareExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.ConstantContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.ExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.FuncExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.MultExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.ParenExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.RelExprContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.VariableContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.VariableLeadContext; +import org.openecomp.sdnc.sli.ExprGrammarParser.VariableTermContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicExprListener extends ExprGrammarBaseListener +{ + + + + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExprListener.class); + + private SvcLogicExpression curExpr; + private SvcLogicExpression topExpr; + private LinkedList<SvcLogicExpression> exprStack; + + public SvcLogicExprListener() + { + exprStack = new LinkedList<SvcLogicExpression>(); + } + + public SvcLogicExpression getParsedExpr() + { + return(curExpr); + } + + private void pushOperand(SvcLogicExpression operand) + { + if (curExpr == null) + { + curExpr = operand; + } + else + { + curExpr.addOperand(operand); + } + } + + private void pushExpr(SvcLogicExpression expr) + { + LOG.trace("Pushing expression ["+expr.getClass().getName()+"]"); + if (curExpr != null) + { + exprStack.push(curExpr); + } + curExpr = expr; + } + + private void popExpr() + { + if (exprStack.isEmpty()) + { + LOG.trace("Popping last expression"); + topExpr = curExpr; + } + else + { + SvcLogicExpression lastExpr = curExpr; + curExpr = exprStack.pop(); + curExpr.addOperand(lastExpr); + LOG.trace("New curExpr is ["+curExpr.getClass().getName()+"]"); + } + + } + + @Override + public void enterAtom(AtomContext ctx) { + + String atomText = ctx.getText(); + + LOG.trace("enterAtom: text = "+atomText); + + + SvcLogicAtom newAtom = new SvcLogicAtom(atomText); + + pushExpr(newAtom); + } + + + @Override + public void enterMultExpr(MultExprContext ctx) { + LOG.trace("enterMultExpr: text = "+ctx.getText()); + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + List<TerminalNode> opList = ctx.MULTOP(); + + for (TerminalNode nd : opList) + { + LOG.trace("enterMultExpr: operator - "+nd.getText()); + curBinExpr.addOperator(nd.getText()); + } + + } + + @Override + public void exitMultExpr(MultExprContext ctx) { + + LOG.trace("exitMultExpr: text = "+ctx.getText()); + + popExpr(); + + } + + @Override + public void exitAtom(AtomContext ctx) { + LOG.trace("exitAtom: text = "+ctx.getText()); + popExpr(); + } + + @Override + public void enterAddExpr(AddExprContext ctx) { + LOG.trace("enterAddExpr: text = "+ctx.getText()); + List<TerminalNode> opList = ctx.ADDOP(); + + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + + for (TerminalNode nd : opList) + { + LOG.trace("enterAddExpr: operator - "+nd.getText()); + curBinExpr.addOperator(nd.getText()); + } + + } + + @Override + public void exitAddExpr(AddExprContext ctx) { + LOG.trace("exitAddExpr: text = "+ctx.getText()); + + popExpr(); + } + + @Override + public void enterFuncExpr(FuncExprContext ctx) { + LOG.trace("enterFuncExpr: text = "+ctx.getText()); + LOG.trace("enterFuncExpr - IDENTIFIER : "+ctx.IDENTIFIER().getText()); + + for (ExprContext expr: ctx.expr()) + { + LOG.trace("enterFuncExpr - expr = "+expr.getText()); + } + + + pushExpr(new SvcLogicFunctionCall(ctx.IDENTIFIER().getText())); + } + + @Override + public void exitFuncExpr(FuncExprContext ctx) { + LOG.trace("exitFuncExpr: text = "+ctx.getText()); + + popExpr(); + } + + @Override + public void enterParenExpr(ParenExprContext ctx) { + LOG.trace("enterParenExpr: text = "+ctx.getText()); + LOG.trace("enterParenExpr: expr = "+ctx.expr().getText()); + } + + @Override + public void exitParenExpr(ParenExprContext ctx) { + LOG.trace("exitParenExpr: text = "+ctx.getText()); + } + + @Override + public void enterRelExpr(RelExprContext ctx) { + LOG.trace("enterRelExpr: text = "+ctx.getText()); + + List<TerminalNode> opList = ctx.RELOP(); + + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + + for (TerminalNode nd : opList) + { + LOG.trace("enterRelExpr: operator - "+nd.getText()); + curBinExpr.addOperator(nd.getText()); + } + + } + + @Override + public void exitRelExpr(RelExprContext ctx) { + LOG.trace("exitRelExpr: text = "+ctx.getText()); + + popExpr(); + } + + @Override + public void enterCompareExpr(CompareExprContext ctx) { + LOG.trace("enterCompareExpr: text = "+ctx.getText()); + + TerminalNode nd = ctx.COMPAREOP(); + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + LOG.trace("enterCompareExpr: operator - "+nd.getText()); + curBinExpr.addOperator(nd.getText()); + + } + + @Override + public void exitCompareExpr(CompareExprContext ctx) { + LOG.trace("exitCompareExpr : text = "+ctx.getText()); + + popExpr(); + } + + + + @Override + public void enterConstant(ConstantContext ctx) { + LOG.trace("enterConstant: text = "+ctx.getText()); + } + + @Override + public void exitConstant(ConstantContext ctx) { + LOG.trace("exitConstant: text = "+ctx.getText()); + } + + + @Override + public void enterVariable(VariableContext ctx) { + LOG.trace("enterVariable: text = "+ctx.getText()); + + + } + + @Override + public void exitVariable(VariableContext ctx) { + LOG.debug("exitVariable: text ="+ctx.getText()); + + } + + + @Override + public void enterVariableLead(VariableLeadContext ctx) { + + LOG.debug("enterVariableLead: text ="+ctx.getText()); + + + } + + @Override + public void exitVariableLead(VariableLeadContext ctx) { + + LOG.trace("exitVariableLead: text ="+ctx.getText()); + } + + @Override + public void enterVariableTerm(VariableTermContext ctx) { + LOG.trace("enterVariableTerm: text ="+ctx.getText()); + + String name = ctx.getText(); + + int subscrStart = name.indexOf("["); + if (subscrStart > -1) + { + name = name.substring(0, subscrStart); + } + SvcLogicVariableTerm vterm = new SvcLogicVariableTerm(name); + pushExpr(vterm); + } + + @Override + public void exitVariableTerm(VariableTermContext ctx) { + LOG.trace("exitVariableTerm: text="+ctx.getText()); + popExpr(); + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExprParserErrorListener.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExprParserErrorListener.java new file mode 100644 index 00000000..4c7dd22b --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExprParserErrorListener.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.misc.ParseCancellationException; + +public class SvcLogicExprParserErrorListener extends BaseErrorListener { + + private static final SvcLogicExprParserErrorListener instance = new SvcLogicExprParserErrorListener(); + + public static SvcLogicExprParserErrorListener getInstance() { + return(instance); + } + + @Override + public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, + String msg, RecognitionException e) throws ParseCancellationException { + throw new ParseCancellationException(msg); + } + + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExpression.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExpression.java new file mode 100644 index 00000000..a6af8201 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExpression.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + + +public abstract class SvcLogicExpression implements Serializable { + + private List<SvcLogicExpression> operands = new LinkedList<SvcLogicExpression>(); + + + public void addOperand(SvcLogicExpression expr) + { + operands.add(expr); + } + + public List<SvcLogicExpression> getOperands() { + return operands; + } + + public int numOperands() + { + return(operands.size()); + } + + public abstract String asParsedExpr(); + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExpressionFactory.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExpressionFactory.java new file mode 100644 index 00000000..cce8e044 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicExpressionFactory.java @@ -0,0 +1,99 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.openecomp.sdnc.sli.ExprGrammarParser.ExprContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class SvcLogicExpressionFactory { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExpressionFactory.class); + + + public static SvcLogicExpression parse(String exprStr) throws IOException + { + LOG.trace("parse("+exprStr+")"); + InputStream exprStream = new ByteArrayInputStream(exprStr.getBytes()); + CharStream input = new ANTLRInputStream(exprStream); + ExprGrammarLexer lexer = new ExprGrammarLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + ExprGrammarParser parser = new ExprGrammarParser(tokens); + + lexer.removeErrorListeners(); + lexer.addErrorListener(SvcLogicExprParserErrorListener.getInstance()); + parser.removeErrorListeners(); + parser.addErrorListener(SvcLogicExprParserErrorListener.getInstance()); + + ExprContext expression = null; + + try { + expression = parser.expr(); + } catch (Exception e) { + String errorMsg = e.getMessage(); + + LOG.error(errorMsg); + throw new SvcLogicParserException(errorMsg); + } + + + ParseTreeWalker walker = new ParseTreeWalker(); + SvcLogicExprListener listener = new SvcLogicExprListener(); + walker.walk(listener, expression); + + + return(listener.getParsedExpr()); + } + + public static void main(String argv[]) { + + + System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "debug"); + + StringBuffer sbuff = new StringBuffer(); + + for (int i = 0 ; i < argv.length ; i++) + { + if (sbuff.length() > 0) + { + sbuff.append(" "); + } + sbuff.append(argv[i]); + } + + try { + SvcLogicExpressionFactory.parse(sbuff.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicFunctionCall.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicFunctionCall.java new file mode 100644 index 00000000..a98cf6b2 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicFunctionCall.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +public class SvcLogicFunctionCall extends SvcLogicExpression { + + private String functionName; + + public SvcLogicFunctionCall(String functionName) + { + this.functionName = functionName; + } + + public String getFunctionName() { + return functionName; + } + + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + public String toString() + { + StringBuffer sbuff = new StringBuffer(); + + sbuff.append(functionName); + sbuff.append("("); + boolean needComma = false; + for (SvcLogicExpression operand: getOperands()) + { + if (needComma) + { + sbuff.append(","); + } + else + { + needComma = true; + } + sbuff.append(operand.toString()); + + } + sbuff.append(")"); + return(sbuff.toString()); + } + + public String asParsedExpr() + { + StringBuffer sbuff = new StringBuffer(); + + sbuff.append("("); + sbuff.append(functionName); + for (SvcLogicExpression operand: getOperands()) + { + sbuff.append(" "); + sbuff.append(operand.asParsedExpr()); + } + sbuff.append(")"); + return(sbuff.toString()); + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicGraph.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicGraph.java new file mode 100644 index 00000000..d3d6d950 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicGraph.java @@ -0,0 +1,184 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.PrintStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class SvcLogicGraph implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private String module = null; + private String rpc = null; + private String mode = null; + private String version = null; + + private Map<String, Serializable> attributes; + private Map<String, SvcLogicNode> namedNodes; + private SvcLogicNode rootNode; + + public SvcLogicGraph() + { + attributes = new HashMap<String, Serializable>(); + namedNodes = new HashMap<String, SvcLogicNode>(); + rootNode = null; + } + + + public String getModule() { + return module; + } + + + public void setModule(String module) { + this.module = module; + } + + + public String getRpc() { + return rpc; + } + + + public void setRpc(String rpc) { + this.rpc = rpc; + } + + + + + public String getMode() { + return mode; + } + + + public void setMode(String mode) { + this.mode = mode; + } + + + public String getVersion() { + return version; + } + + + public void setVersion(String version) { + this.version = version; + } + + + public void setRootNode(SvcLogicNode rootNode) + { + this.rootNode = rootNode; + } + + public SvcLogicNode getRootNode() + { + return(rootNode); + } + + public Serializable getAttribute(String name) + { + if (attributes.containsKey(name)) + { + return(attributes.get(name)); + } + else + { + return(null); + } + + } + + public void setAttribute(String name, Serializable value) throws DuplicateValueException + { + if (attributes.containsKey(name)) + { + throw new DuplicateValueException("Duplicate attribute "+name); + } + + attributes.put(name, value); + } + + public SvcLogicNode getNamedNode(String nodeName) + { + if (namedNodes.containsKey(nodeName)) + { + return(namedNodes.get(nodeName)); + } + else + { + return(null); + } + } + + public void setNamedNode(String nodeName, SvcLogicNode node) throws DuplicateValueException + { + if (namedNodes.containsKey(nodeName)) + { + throw new DuplicateValueException("Duplicate node name "+nodeName); + } + + namedNodes.put(nodeName, node); + } + + + + public void printAsGv(PrintStream pstr) + { + pstr.println("digraph g {"); + pstr.println("START [label=\"START\\n"+module+":"+rpc+"\"];"); + + if (rootNode != null) + { + pstr.println("START -> node"+rootNode.getNodeId()+";"); + rootNode.setVisited(false, true); + rootNode.printAsGv(pstr); + } + pstr.println("}"); + } + + public void printAsXml(PrintStream pstr) + { + pstr.println("<service-logic module='"+getModule()+"' version='"+getVersion()+"'>"); + pstr.println(" <method rpc='"+getRpc()+"' mode='"+getMode()+"'>"); + if (rootNode != null) + { + rootNode.setVisited(false, true); + rootNode.printAsXml(pstr, 2); + } + pstr.println(" </method>"); + pstr.println("</service-logic>"); + } + + @Override + public String toString() { + return "SvcLogicGraph [module=" + module + ", rpc=" + rpc + ", mode=" + mode + ", version=" + version + "]"; + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicJavaPlugin.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicJavaPlugin.java new file mode 100644 index 00000000..ac14cacc --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicJavaPlugin.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.Map; + +public interface SvcLogicJavaPlugin { + + /** + * A marker interface, used to indicate that a class exposes methods that can be + * called from an <execute> node. Such methods must have the signature: + * void methodName(Map, SvcLogicContext) + */ + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicJdbcStore.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicJdbcStore.java new file mode 100644 index 00000000..b9e7f80e --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicJdbcStore.java @@ -0,0 +1,895 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.Blob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class SvcLogicJdbcStore implements SvcLogicStore { + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicJdbcStore.class); + + private String dbUrl = null; + private String dbName = null; + private String dbUser = null; + private String dbPasswd = null; + private String dbDriver = null; + + private Connection dbConn; + private PreparedStatement hasActiveGraphStmt = null; + private PreparedStatement hasVersionGraphStmt = null; + private PreparedStatement fetchActiveGraphStmt = null; + private PreparedStatement fetchVersionGraphStmt = null; + private PreparedStatement storeGraphStmt = null; + private PreparedStatement deleteGraphStmt = null; + + private PreparedStatement deactivateStmt = null; + private PreparedStatement activateStmt = null; + + private PreparedStatement registerNodeStmt = null; + private PreparedStatement unregisterNodeStmt = null; + private PreparedStatement validateNodeStmt = null; + + private void getConnection() throws ConfigurationException + { + + Properties jdbcProps = new Properties(); + + jdbcProps.setProperty("user", dbUser); + jdbcProps.setProperty("password", dbPasswd); + + try { + Driver dvr = new com.mysql.jdbc.Driver(); + if (dvr.acceptsURL(dbUrl)) + { + LOG.debug("Driver com.mysql.jdbc.Driver accepts "+dbUrl); + } + else + { + LOG.warn("Driver com.mysql.jdbc.Driver does not accept "+dbUrl); + } + } catch (SQLException e1) { + LOG.error("Caught exception trying to load com.mysql.jdbc.Driver", e1); + + + } + + + try + { + this.dbConn = DriverManager.getConnection(dbUrl, jdbcProps); + } + catch (Exception e) + { + throw new ConfigurationException("failed to get database connection ["+dbUrl+"]", e); + } + + } + + private void createTable() throws ConfigurationException + { + + + DatabaseMetaData dbm = null; + + + try { + dbm = dbConn.getMetaData(); + } catch (SQLException e) { + + throw new ConfigurationException("could not get databse metadata", e); + } + + // See if table SVC_LOGIC exists. If not, create it. + try + { + + + ResultSet tables = dbm.getTables(null, null, "SVC_LOGIC", null); + if (tables.next()) { + // Table exists + } + else { + + String crTableCmd = "CREATE TABLE "+dbName+".SVC_LOGIC (" + + "module varchar(80) NOT NULL," + + "rpc varchar(80) NOT NULL," + + "version varchar(40) NOT NULL," + + "mode varchar(5) NOT NULL," + + "active varchar(1) NOT NULL," + + "graph BLOB," + + "CONSTRAINT P_SVC_LOGIC PRIMARY KEY(module, rpc, version, mode))"; + + Statement stmt = null; + ConfigurationException myExc = null; + try + { + stmt = dbConn.createStatement(); + stmt.executeUpdate(crTableCmd); + } + catch (SQLException e1) + { + myExc = new ConfigurationException("cannot create SVC_LOGIC table", e1); + } + finally + { + if (stmt != null) + { + stmt.close(); + } + } + + if (myExc != null) + { + throw myExc; + } + } + } + catch (Exception e) + { + throw new ConfigurationException("could not create SVC_LOGIC table", e); + } + + // See if NODE_TYPES table exists and, if not, create it + + try + { + + + ResultSet tables = dbm.getTables(null, null, "NODE_TYPES", null); + if (tables.next()) { + // Table exists + } + else { + + String crTableCmd = "CREATE TABLE "+dbName+".NODE_TYPES (" + + "nodetype varchar(80) NOT NULL," + + "CONSTRAINT P_NODE_TYPES PRIMARY KEY(nodetype))"; + + Statement stmt = null; + ConfigurationException myExc = null; + try + { + stmt = dbConn.createStatement(); + stmt.executeUpdate(crTableCmd); + } + catch (SQLException e1) + { + myExc = new ConfigurationException("cannot create SVC_LOGIC table", e1); + } + finally + { + if (stmt != null) + { + stmt.close(); + } + } + + if (myExc != null) + { + throw myExc; + } + } + } + catch (Exception e) + { + throw new ConfigurationException("could not create SVC_LOGIC table", e); + } + } + + private void prepStatements() throws ConfigurationException + { + + // Prepare statements + String hasVersionGraphSql = "SELECT count(*) FROM "+dbName+".SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + try + { + hasVersionGraphStmt = dbConn.prepareStatement(hasVersionGraphSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+hasVersionGraphSql, e); + + } + + String hasActiveGraphSql = "SELECT count(*) FROM "+dbName+".SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; + + try + { + hasActiveGraphStmt = dbConn.prepareStatement(hasActiveGraphSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+hasVersionGraphSql, e); + + } + + String fetchVersionGraphSql = "SELECT graph FROM "+dbName+".SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + try + { + fetchVersionGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+fetchVersionGraphSql, e); + + } + + String fetchActiveGraphSql = "SELECT graph FROM "+dbName+".SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; + + try + { + fetchActiveGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+fetchVersionGraphSql, e); + + } + + String storeGraphSql = "INSERT INTO "+dbName+".SVC_LOGIC (module, rpc, version, mode, active, graph)" + + " VALUES(?, ?, ?, ?, ?, ?)"; + + try + { + storeGraphStmt = dbConn.prepareStatement(storeGraphSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+storeGraphSql, e); + } + + String deleteGraphSql = "DELETE FROM "+dbName+".SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?"; + + try + { + deleteGraphStmt = dbConn.prepareStatement(deleteGraphSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+deleteGraphSql, e); + } + + String deactivateSql = "UPDATE "+dbName+".SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?"; + + try + { + deactivateStmt = dbConn.prepareStatement(deactivateSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+deactivateSql, e); + } + + String activateSql = "UPDATE "+dbName+".SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND version = ? AND mode = ?"; + + try + { + activateStmt = dbConn.prepareStatement(activateSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+activateSql, e); + } + + String registerNodeSql = "INSERT INTO "+dbName+".NODE_TYPES (nodetype) VALUES(?)"; + try + { + registerNodeStmt = dbConn.prepareStatement(registerNodeSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+registerNodeSql, e); + } + + String unregisterNodeSql = "DELETE FROM "+dbName+".NODE_TYPES WHERE nodetype = ?"; + try + { + unregisterNodeStmt = dbConn.prepareStatement(unregisterNodeSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+unregisterNodeSql, e); + } + + String validateNodeSql = "SELECT count(*) FROM "+dbName+".NODE_TYPES WHERE nodetype = ?"; + try + { + validateNodeStmt = dbConn.prepareStatement(validateNodeSql); + } + catch (Exception e) + { + throw new ConfigurationException("could not prepare statement "+validateNodeSql, e); + } + } + + private void initDbResources() throws ConfigurationException + { + if ((dbDriver != null) && (dbDriver.length() > 0)) + { + + try + { + Class.forName(dbDriver); + } + catch (Exception e) + { + throw new ConfigurationException("could not load driver class "+dbDriver, e); + } + } + getConnection(); + createTable(); + prepStatements(); + } + + + public void init(Properties props) throws ConfigurationException { + + + dbUrl = props.getProperty("org.openecomp.sdnc.sli.jdbc.url"); + if ((dbUrl == null) || (dbUrl.length() == 0)) + { + throw new ConfigurationException("property org.openecomp.sdnc.sli.jdbc.url unset"); + } + + dbName = props.getProperty("org.openecomp.sdnc.sli.jdbc.database"); + if ((dbName == null) || (dbName.length() == 0)) + { + throw new ConfigurationException("property org.openecomp.sdnc.sli.jdbc.database unset"); + } + + dbUser = props.getProperty("org.openecomp.sdnc.sli.jdbc.user"); + if ((dbUser == null) || (dbUser.length() == 0)) + { + throw new ConfigurationException("property org.openecomp.sdnc.sli.jdbc.user unset"); + } + + + dbPasswd = props.getProperty("org.openecomp.sdnc.sli.jdbc.password"); + if ((dbPasswd == null) || (dbPasswd.length() == 0)) + { + throw new ConfigurationException("property org.openecomp.sdnc.sli.jdbc.password unset"); + } + + dbDriver = props.getProperty("org.openecomp.sdnc.sli.jdbc.driver"); + + + initDbResources(); + + } + + private boolean isDbConnValid() + { + + boolean isValid = false; + + try + { + if (dbConn != null) + { + isValid = dbConn.isValid(1); + } + } + catch (SQLException e) + {} + + return(isValid); + } +public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException { + + + + + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + + + boolean retval = false; + ResultSet results = null; + + PreparedStatement hasGraphStmt = null; + if (version == null) + { + hasGraphStmt = hasActiveGraphStmt; + } + else + { + hasGraphStmt = hasVersionGraphStmt; + } + + + + try + { + hasGraphStmt.setString(1, module); + hasGraphStmt.setString(2, rpc); + hasGraphStmt.setString(3, mode); + + + if (version != null) + { + hasGraphStmt.setString(4, version); + } + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + results = hasGraphStmt.executeQuery(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + + if (results.next()) + { + int cnt = results.getInt(1); + + if (cnt > 0) + { + retval = true; + } + + } + } + catch (Exception e) + { + throw new ConfigurationException("SQL query failed", e); + } + finally + { + if (results != null) + { + try + { + + results.close(); + } + catch (SQLException x) + {} + } + + } + + + return(retval); + + + } + + public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException { + + + + + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + + + SvcLogicGraph retval = null; + ResultSet results = null; + + PreparedStatement fetchGraphStmt = null; + if (version == null) + { + fetchGraphStmt = fetchActiveGraphStmt; + } + else + { + fetchGraphStmt = fetchVersionGraphStmt; + } + try + { + fetchGraphStmt.setString(1, module); + fetchGraphStmt.setString(2, rpc); + fetchGraphStmt.setString(3, mode); + + + if (version != null) + { + fetchGraphStmt.setString(4, version); + } + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + results = fetchGraphStmt.executeQuery(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + + if (results.next()) + { + Blob graphBlob = results.getBlob("graph"); + + ObjectInputStream gStream = new ObjectInputStream(graphBlob.getBinaryStream()); + + Object graphObj = gStream.readObject(); + gStream.close(); + + if (graphObj instanceof SvcLogicGraph) + { + retval = (SvcLogicGraph) graphObj; + } + else + { + throw new ConfigurationException("invalid type for graph ("+graphObj.getClass().getName()); + + } + + } + else + { + return(null); + } + } + catch (Exception e) + { + throw new ConfigurationException("SQL query failed", e); + } + finally + { + if (results != null) + { + try + { + results.close(); + } + catch (SQLException x) + {} + } + + } + + + return(retval); + + + } + + public void store(SvcLogicGraph graph) throws SvcLogicException { + + + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + if (graph == null) + { + throw new SvcLogicException("graph cannot be null"); + } + + byte[] graphBytes = null; + + ByteArrayOutputStream byteStr = null; + ObjectOutputStream goutStr = null; + + try + { + byteStr = new ByteArrayOutputStream(); + goutStr = new ObjectOutputStream(byteStr); + goutStr.writeObject(graph); + + graphBytes = byteStr.toByteArray(); + + } + catch (Exception e) + { + throw new SvcLogicException("could not serialize graph", e); + } + finally + { + + if (goutStr != null) + { + try { + goutStr.close(); + } catch (IOException e) { + + } + } + + if (byteStr != null) + { + try { + byteStr.close(); + } catch (IOException e) { + + } + } + } + + + // If object already stored in database, delete it + if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode())) + { + delete(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode()); + } + + try + { + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + storeGraphStmt.setString(1, graph.getModule()); + storeGraphStmt.setString(2, graph.getRpc()); + storeGraphStmt.setString(3, graph.getVersion()); + storeGraphStmt.setString(4, graph.getMode()); + storeGraphStmt.setString(5, "N"); + storeGraphStmt.setBlob(6, new ByteArrayInputStream(graphBytes)); + + storeGraphStmt.executeUpdate(); + dbConn.commit(); + + dbConn.setAutoCommit(oldAutoCommit); + } + catch (Exception e) + { + throw new SvcLogicException("Could not write object to database", e); + } + } + + public void delete(String module, String rpc, String version, String mode) throws SvcLogicException + { + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + try + { + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + deleteGraphStmt.setString(1, module); + deleteGraphStmt.setString(2, rpc); + deleteGraphStmt.setString(3, version); + deleteGraphStmt.setString(4, mode); + + + deleteGraphStmt.executeUpdate(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + } + catch (Exception e) + { + throw new SvcLogicException("Could not delete object from database", e); + } + } + + public void activate(SvcLogicGraph graph) throws SvcLogicException + { + try + { + boolean oldAutoCommit = dbConn.getAutoCommit(); + + dbConn.setAutoCommit(false); + + // Deactivate any current active version + deactivateStmt.setString(1, graph.getModule()); + deactivateStmt.setString(2, graph.getRpc()); + deactivateStmt.setString(3, graph.getMode()); + deactivateStmt.executeUpdate(); + + // Activate this version + activateStmt.setString(1, graph.getModule()); + activateStmt.setString(2, graph.getRpc()); + activateStmt.setString(3, graph.getVersion()); + activateStmt.setString(4, graph.getMode()); + activateStmt.executeUpdate(); + + dbConn.commit(); + + dbConn.setAutoCommit(oldAutoCommit); + + } + catch (Exception e) + { + throw new SvcLogicException("Could not activate graph", e); + } + } + + @Override + public void registerNodeType(String nodeType) throws SvcLogicException { + + if (isValidNodeType(nodeType)) + { + return; + } + + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + try + { + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + registerNodeStmt.setString(1, nodeType); + registerNodeStmt.executeUpdate(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + } + catch (Exception e) + { + throw new SvcLogicException("Could not add node type to database", e); + } + + } + + @Override + public void unregisterNodeType(String nodeType) throws SvcLogicException { + + if (!isValidNodeType(nodeType)) + { + return; + } + + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + try + { + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + unregisterNodeStmt.setString(1, nodeType); + unregisterNodeStmt.executeUpdate(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + } + catch (Exception e) + { + throw new SvcLogicException("Could not delete node type from database", e); + } + + } + + @Override + public boolean isValidNodeType(String nodeType) throws SvcLogicException { + + boolean isValid = false; + + if (!isDbConnValid()) + { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) + { + throw new ConfigurationException("no jdbc connection"); + } + } + + ResultSet results = null; + try + { + validateNodeStmt.setString(1, nodeType); + + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + results = validateNodeStmt.executeQuery(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + + if (results != null) + { + if (results.next()) + { + int cnt = results.getInt(1); + + if (cnt > 0) + { + isValid = true; + } + } + } + + } + catch (Exception e) + { + throw new SvcLogicException("Cannot select node type from database", e); + } + finally + { + if (results != null) + { + try + { + results.close(); + } + catch (SQLException x) + {} + } + + } + + return(isValid); + } + + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicNode.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicNode.java new file mode 100644 index 00000000..6828e9ad --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicNode.java @@ -0,0 +1,456 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +package org.openecomp.sdnc.sli; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Locator; + + +public class SvcLogicNode implements Serializable { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExprListener.class); + + private static final long serialVersionUID = 2L; + + private String nodeName; + private int nodeId; + private String nodeType; + private boolean visited; + private SvcLogicGraph graph; + + + private HashMap<String, SvcLogicExpression> attributes; + private HashMap<String, SvcLogicNode> outcomes; + private HashMap<String, SvcLogicExpression> parameters; + + public SvcLogicNode(int nodeId, String nodeType, SvcLogicGraph graph) + { + this.nodeId = nodeId; + nodeName = ""; + this.nodeType = nodeType; + this.graph = graph; + attributes = new HashMap<String, SvcLogicExpression> (); + parameters = new HashMap<String, SvcLogicExpression> (); + outcomes = null; + + } + + public SvcLogicNode(int nodeId, String nodeType, String nodeName, SvcLogicGraph graph) throws DuplicateValueException + { + this.nodeId = nodeId; + this.nodeName = nodeName; + this.nodeType = nodeType; + this.graph = graph; + attributes = new HashMap<String, SvcLogicExpression> (); + parameters = new HashMap<String, SvcLogicExpression> (); + outcomes = null; + graph.setNamedNode(nodeName, this); + } + + + public int getNodeId() + { + return nodeId; + } + + public String getNodeName() + { + return(nodeName); + } + + public String getNodeType() + { + return(nodeType); + } + + public SvcLogicGraph getGraph() + { + return(graph); + } + + public int getNumOutcomes() + { + if (outcomes == null) + { + return(0); + } + else + { + return(outcomes.size()); + } + } + + public SvcLogicExpression getAttribute(String name) + { + if (attributes.containsKey(name)) + { + return(attributes.get(name)); + } + else + { + return(null); + } + + } + + public void setAttribute(String name, String value) throws SvcLogicException + { + setAttribute(name, new SvcLogicAtom("STRING", value)); + } + + public void setAttribute(String name, SvcLogicExpression value) throws SvcLogicException + { + if (attributes.containsKey(name)) + { + throw new DuplicateValueException("Duplicate attribute "+name); + } + + attributes.put(name, value); + } + + + public void mapParameter(String name, String value) throws SvcLogicException + { + + if (parameters.containsKey(name)) + { + throw new DuplicateValueException("Duplicate parameter "+name); + } + try + { + SvcLogicExpression parmValue; + if ((value == null) || (value.length() == 0)) + { + parmValue = new SvcLogicAtom("STRING", ""); + } + else if (value.trim().startsWith("`")) + { + int lastParen = value.lastIndexOf("`"); + String evalExpr = value.trim().substring(1, lastParen); + parmValue = SvcLogicExpressionFactory.parse(evalExpr); + + } + else + { + if (Character.isDigit(value.charAt(0))) + { + parmValue = new SvcLogicAtom("NUMBER", value); + } + else + { + parmValue = new SvcLogicAtom("STRING", value); + } + } + LOG.debug("Setting parameter "+name+" = "+value+" = "+parmValue.asParsedExpr()); + parameters.put(name, parmValue); + } + catch (IOException e) { + + LOG.error("Invalid parameter value expression ("+value+")"); + throw new SvcLogicException(e.getMessage()); + } + } + + public SvcLogicExpression getParameter(String name) + { + if (parameters.containsKey(name)) + { + return(parameters.get(name)); + } + else + { + return(null); + } + } + + public boolean isVisited() { + return visited; + } + + public void setVisited(boolean visited, boolean recursive) { + this.visited = visited; + + if (recursive) + { + Set<Map.Entry<String, SvcLogicNode>> outcomeSet = getOutcomeSet(); + + if (outcomeSet == null) + { + return; + } + + for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator(); iter.hasNext();) + { + Map.Entry<String, SvcLogicNode> curOutcome = iter.next(); + SvcLogicNode outNode = curOutcome.getValue(); + outNode.setVisited(visited, recursive); + } + } + } + + public void addOutcome(String outcomeValue, SvcLogicNode node) throws SvcLogicException + { + if (outcomes == null) + { + outcomes = new HashMap<String, SvcLogicNode>(); + } + + if (outcomeValue.length() == 0) { + outcomeValue = "\"\""; + } + if (outcomes.containsKey(outcomeValue)) + { + throw new DuplicateValueException("Duplicate outcome value "+outcomeValue); + } + + outcomes.put(outcomeValue, node); + } + + public Set<Map.Entry<String, SvcLogicNode>> getOutcomeSet() + { + if (outcomes == null) + { + return null; + } + + return(outcomes.entrySet()); + + } + + public Set<Map.Entry<String, SvcLogicExpression>> getParameterSet() + { + if (parameters == null) + { + return null; + } + + return(parameters.entrySet()); + + } + + public void printAsGv(PrintStream pstr) + { + + if (visited) + { + return; + } + else + { + visited = true; + } + + StringBuffer sbuff = new StringBuffer(); + + sbuff.append("node"); + sbuff.append(nodeId); + sbuff.append(" [ shape=none, margin=0, label=<<table border=\"0\" cellborder=\"1\" align=\"left\">"); + sbuff.append("<tr><td colspan=\"2\"><b>"); + sbuff.append(nodeId); + sbuff.append(" : "); + sbuff.append(nodeType); + sbuff.append("</b></td></tr><th><td><i>Attribute</i></td><td><i>Value</i></td></th>"); + + if (nodeName.length() > 0) + { + sbuff.append("<tr><td>name</td><td>"); + sbuff.append(nodeName); + sbuff.append("</td></tr>"); + } + + Set<Map.Entry<String, SvcLogicExpression>> attrSet = attributes.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = attrSet.iterator() ; iter.hasNext();) + { + Map.Entry<String, SvcLogicExpression> curAttr = iter.next(); + sbuff.append("<tr><td>"); + sbuff.append(curAttr.getKey()); + sbuff.append("</td><td>"); + sbuff.append(StringEscapeUtils.escapeHtml3(curAttr.getValue().toString())); + sbuff.append("</td></tr>"); + } + sbuff.append("</table>>];"); + + pstr.println(sbuff.toString()); + + + if (outcomes != null) + { + TreeMap<String, SvcLogicNode> sortedOutcomes = new TreeMap<String, SvcLogicNode>(outcomes); + Set<Map.Entry<String, SvcLogicNode>> outcomeSet = sortedOutcomes.entrySet(); + + for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator(); iter.hasNext();) + { + Map.Entry<String, SvcLogicNode> curOutcome = iter.next(); + String outValue = curOutcome.getKey(); + SvcLogicNode outNode = curOutcome.getValue(); + pstr.println("node"+nodeId+" -> node"+outNode.getNodeId()+" [label=\""+outValue+"\"];"); + outNode.printAsGv(pstr); + } + } + } + + public void printAsXml(PrintStream pstr, int indentLvl) + { + if (visited) + { + return; + } + // Print node tag + for (int i = 0 ; i < indentLvl ; i++) + { + pstr.print(" "); + } + pstr.print("<"); + pstr.print(this.getNodeType()); + + Set<Map.Entry<String, SvcLogicExpression>> attrSet = attributes.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = attrSet.iterator() ; iter.hasNext();) + { + Map.Entry<String, SvcLogicExpression> curAttr = iter.next(); + pstr.print(" "); + pstr.print(curAttr.getKey()); + pstr.print("='`"); + pstr.print(curAttr.getValue()); + pstr.print("'`"); + } + + if (((parameters == null) || (parameters.isEmpty())) && + ((outcomes == null) || outcomes.isEmpty())) + { + pstr.print("/>\n"); + pstr.flush(); + return; + } + else + { + pstr.print(">\n"); + } + + // Print parameters (if any) + if (parameters != null) + { + Set<Map.Entry<String, SvcLogicExpression>> paramSet = parameters.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = paramSet.iterator() ; iter.hasNext();) + { + for (int i = 0 ; i < indentLvl+1 ; i++) + { + pstr.print(" "); + } + pstr.print("<parameter"); + Map.Entry<String, SvcLogicExpression> curAttr = iter.next(); + pstr.print(" name='"); + pstr.print(curAttr.getKey()); + pstr.print("' value='`"); + pstr.print(curAttr.getValue().toString()); + pstr.print("`'/>\n"); + } + } + + // Print outcomes (if any) + if (outcomes != null) + { + Set<Map.Entry<String, SvcLogicNode>> outcomeSet = outcomes.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator() ; iter.hasNext();) + { + for (int i = 0 ; i < indentLvl+1 ; i++) + { + pstr.print(" "); + } + pstr.print("<outcome"); + Map.Entry<String, SvcLogicNode> curAttr = iter.next(); + pstr.print(" value='"); + pstr.print(curAttr.getKey()); + pstr.print("'>\n"); + SvcLogicNode outNode = curAttr.getValue(); + outNode.printAsXml(pstr, indentLvl+2); + for (int i = 0 ; i < indentLvl+1 ; i++) + { + pstr.print(" "); + } + pstr.print("</outcome>\n"); + } + } + + // Print node end tag + for (int i = 0 ; i < indentLvl ; i++) + { + pstr.print(" "); + } + pstr.print("</"); + pstr.print(this.getNodeType()); + pstr.print(">\n"); + pstr.flush(); + + } + + + public SvcLogicNode getOutcomeValue(String value) + { + + if (value.length() == 0) { + value = "\"\""; + } + if (outcomes == null) + { + return(null); + } + + if (outcomes.containsKey(value)) + { + return(outcomes.get(value)); + } + else + { + StringBuffer keyBuffer = new StringBuffer(); + keyBuffer.append("{"); + for (String key : outcomes.keySet()) { + keyBuffer.append(" ("+key+")"); + } + keyBuffer.append("}"); + LOG.info("Outcome (" + value + ") not found, keys are " + keyBuffer.toString()); + + if (outcomes.containsKey("Other")) + { + return(outcomes.get("Other")); + } + else + { + return(null); + } + } + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicParser.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicParser.java new file mode 100644 index 00000000..398c28de --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicParser.java @@ -0,0 +1,598 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.LinkedList; + +import javax.xml.XMLConstants; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * @author dt5972 + * + */ +public class SvcLogicParser { + + SvcLogicStore store = null; + static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; + static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; + static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; + static final String JAXP_DYNAMIC_VALIDATION = "http://apache.org/xml/features/validation/dynamic"; + static final String JAXP_SCHEMA_VALIDATION = "http://apache.org/xml/features/validation/schema"; + + private static final String LOAD_MESSAGE = "Getting SvcLogicGraph from database - "; + private static final String LOAD_ERROR_MESSAGE = "SvcLogicGraph not found - "; + private static final String ACTIVATION_ERROR_MESSAGE = "Could not activate SvcLogicGraph - "; + private static final String PRINT_ERROR_MESSAGE = "Could not print SvcLogicGraph - "; + private static final String SVC_LOGIC_STORE_ERROR = "Could not get service logic store"; + + private static final Logger LOGGER = LoggerFactory.getLogger(SvcLogicParser.class); + private static final String SLI_VALIDATING_PARSER = "org.openecomp.sdnc.sli.parser.validate"; + private static final String SVCLOGIC_XSD = "/svclogic.xsd"; + + private class SvcLogicHandler extends DefaultHandler { + private Locator locator = null; + private String module = null; + private String version = null; + private LinkedList<SvcLogicGraph> graphs = null; + private SvcLogicGraph curGraph = null; + private SvcLogicNode curNode = null; + private LinkedList<SvcLogicNode> nodeStack = null; + private int curNodeId = 0; + private String outcomeValue = null; + private LinkedList<String> outcomeStack = null; + private SvcLogicStore svcLogicStore = null; + + public SvcLogicHandler(LinkedList<SvcLogicGraph> graphs, SvcLogicStore store) { + this.graphs = graphs; + this.curNode = null; + this.nodeStack = new LinkedList<>(); + this.outcomeStack = new LinkedList<>(); + this.curNodeId = 1; + this.outcomeValue = null; + this.svcLogicStore = store; + + } + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + + // Handle service-logic (graph) tag + if ("service-logic".equalsIgnoreCase(qName)) { + + module = attributes.getValue("module"); + if (module == null || module.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Missing 'module' attribute from service-logic tag"); + } + + version = attributes.getValue("version"); + if (version == null || version.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Missing 'version' attribute from service-logic tag"); + } + + return; + } + + if ("method".equalsIgnoreCase(qName)) { + if (curGraph != null) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Cannot nest module tags"); + } + curGraph = new SvcLogicGraph(); + curGraph.setModule(module); + curGraph.setVersion(version); + this.curNodeId = 1; + + String attrValue = attributes.getValue("rpc"); + if (attrValue == null || attrValue.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Missing 'rpc' attribute for method tag"); + } + curGraph.setRpc(attrValue); + + attrValue = attributes.getValue("mode"); + if (attrValue == null || attrValue.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Missing 'mode' attribute for method tag"); + } + curGraph.setMode(attrValue); + + return; + + } + + // Handle outcome (edge) tag + if ("outcome".equalsIgnoreCase(qName)) { + String refValue = attributes.getValue("ref"); + + if (refValue != null) { + SvcLogicNode refNode = curGraph.getNamedNode(refValue); + + if (refNode != null) { + try { + curNode.addOutcome(attributes.getValue("value"), refNode); + } catch (SvcLogicException e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Cannot add outcome", e); + } + } else { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "ref to unknown node " + refValue); + } + return; + } + + if (outcomeValue != null) { + outcomeStack.push(outcomeValue); + } + outcomeValue = attributes.getValue("value"); + + return; + } + + // Handle parameter tag + if ("parameter".equalsIgnoreCase(qName)) { + String parmName = attributes.getValue("name"); + String parmValue = attributes.getValue("value"); + + if (parmName != null && parmName.length() > 0 && parmValue != null) { + try { + + curNode.mapParameter(parmName, parmValue); + } catch (Exception e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + " cannot set parameter " + parmName + " to " + parmValue + " [" + e.getMessage() + "]"); + } + } + + return; + } + + // Handle node tags + + String nodeName = attributes.getValue("name"); + SvcLogicNode thisNode = null; + + try { + if (!svcLogicStore.isValidNodeType(qName)) { + throw new SAXNotRecognizedException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Unknown tag " + qName); + } + } catch (Exception e) { + throw new SAXNotRecognizedException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Cannot validate node type " + qName); + } + + try { + if (nodeName != null && nodeName.length() > 0) { + thisNode = new SvcLogicNode(curNodeId++, qName, nodeName, curGraph); + } else { + thisNode = new SvcLogicNode(curNodeId++, qName, curGraph); + } + + if (curGraph.getRootNode() == null) { + curGraph.setRootNode(thisNode); + } + } catch (SvcLogicException e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + e.getMessage()); + + } + + int numAttributes = attributes.getLength(); + + for (int i = 0; i < numAttributes; i++) { + String attrName = attributes.getQName(i); + if (!"name".equalsIgnoreCase(attrName)) { + try { + + String attrValueStr = attributes.getValue(i); + SvcLogicExpression attrValue = null; + if (attrValueStr.trim().startsWith("`")) { + int lastParen = attrValueStr.lastIndexOf("`"); + String evalExpr = attrValueStr.trim().substring(1, lastParen); + attrValue = SvcLogicExpressionFactory.parse(evalExpr); + + } else { + if (Character.isDigit(attrValueStr.charAt(0))) { + attrValue = new SvcLogicAtom("NUMBER", attrValueStr); + } else { + attrValue = new SvcLogicAtom("STRING", attrValueStr); + } + } + thisNode.setAttribute(attrName, attrValue); + } catch (Exception e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + "Cannot set attribute " + attrName, e); + } + } + } + + if (curNode != null) { + try { + if ("block".equalsIgnoreCase(curNode.getNodeType()) || "for".equalsIgnoreCase(curNode.getNodeType()) || "while".equalsIgnoreCase(curNode.getNodeType())) { + curNode.addOutcome("" + (curNode.getNumOutcomes() + 1), thisNode); + } else { + if (outcomeValue == null) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + curNode.getNodeType() + " node expects outcome, instead found " + thisNode.getNodeType()); + } + curNode.addOutcome(outcomeValue, thisNode); + } + } catch (SvcLogicException e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + e.getMessage()); + } + nodeStack.push(curNode); + } + curNode = thisNode; + + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + + // Handle close of service-logic tag + if ("service-logic".equalsIgnoreCase(qName)) { + // Nothing more to do + return; + } + + // Handle close of method tag + if ("method".equalsIgnoreCase(qName)) { + graphs.add(curGraph); + curGraph = null; + return; + } + + // Handle close of outcome tag + if ("outcome".equalsIgnoreCase(qName)) { + // Finished this outcome - pop the outcome stack + if (outcomeStack.isEmpty()) { + outcomeValue = null; + } else { + outcomeValue = outcomeStack.pop(); + } + return; + } + + // Handle close of parameter tag - do nothing + if ("parameter".equalsIgnoreCase(qName)) { + return; + } + + // Handle close of a node tag + if (nodeStack.isEmpty()) { + curNode = null; + } else { + curNode = nodeStack.pop(); + } + } + + @Override + public void error(SAXParseException arg0) throws SAXException { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + arg0.getMessage()); + } + + } + + public SvcLogicParser(SvcLogicStore store) { + this.store = store; + } + + public SvcLogicParser(String propFile) { + + try { + this.store = SvcLogicStoreFactory.getSvcLogicStore(propFile); + } catch (Exception e) { + LOGGER.error(SVC_LOGIC_STORE_ERROR, e); + + } + + } + + public SvcLogicParser(InputStream propStr) { + + try { + this.store = SvcLogicStoreFactory.getSvcLogicStore(propStr); + } catch (Exception e) { + LOGGER.error(SVC_LOGIC_STORE_ERROR, e); + + } + + } + + public LinkedList<SvcLogicGraph> parse(String fileName) throws SvcLogicException { + LinkedList<SvcLogicGraph> graphs = null; + + URL xsdUrl = null; + Schema schema = null; + String validateSchema = System.getProperty(SLI_VALIDATING_PARSER, "true"); + + if (validateSchema != null || validateSchema.equalsIgnoreCase("true")) { + xsdUrl = getClass().getResource(SVCLOGIC_XSD); + + } + + if (xsdUrl != null) { + try { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + schema = schemaFactory.newSchema(xsdUrl); + } catch (Exception e) { + LOGGER.warn("Could not validate using schema " + xsdUrl.getPath(), e); + } + } else { + LOGGER.warn("Could not find resource " + SVCLOGIC_XSD); + } + + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + + if (schema != null) { + factory.setNamespaceAware(true); + factory.setSchema(schema); + } + SAXParser saxParser = factory.newSAXParser(); + + if (saxParser.isValidating()) { + LOGGER.info("Validating against schema " + xsdUrl.getPath()); + } + graphs = new LinkedList<>(); + + saxParser.parse(fileName, new SvcLogicHandler(graphs, store)); + + } catch (Exception e) { + String msg = e.getMessage(); + if (msg != null) { + LOGGER.error(msg); + throw new SvcLogicException("Compiler error: " + fileName + " @ " + msg); + } else { + LOGGER.info("Caught exception parsing " + fileName, e); + throw new SvcLogicException("Compiler error: " + fileName, e); + } + } + + return graphs; + } + + public static void main(String argv[]) { + + if (argv.length == 0) { + SvcLogicParser.usage(); + } + + if ("load".equalsIgnoreCase(argv[0])) { + if (argv.length == 3) { + String xmlfile = argv[1]; + String propfile = argv[2]; + + SvcLogicStore store = SvcLogicParser.getStore(propfile); + try { + SvcLogicParser.load(xmlfile, store); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } else { + SvcLogicParser.usage(); + } + } else if ("print".equalsIgnoreCase(argv[0])) { + String version = null; + String propfile = null; + + switch (argv.length) { + case 6: + version = argv[4]; + propfile = argv[5]; + case 5: + if (propfile == null) { + propfile = argv[4]; + } + SvcLogicStore store = SvcLogicParser.getStore(propfile); + SvcLogicParser.print(argv[1], argv[2], argv[3], version, store); + break; + default: + SvcLogicParser.usage(); + } + } else if ("get-source".equalsIgnoreCase(argv[0])) { + + switch (argv.length) { + case 6: + SvcLogicStore store = SvcLogicParser.getStore(argv[5]); + SvcLogicParser.getSource(argv[1], argv[2], argv[3], argv[4], store); + break; + default: + SvcLogicParser.usage(); + } + } else if ("activate".equalsIgnoreCase(argv[0])) { + if (argv.length == 6) { + SvcLogicStore store = SvcLogicParser.getStore(argv[5]); + SvcLogicParser.activate(argv[1], argv[2], argv[3], argv[4], store); + } else { + SvcLogicParser.usage(); + } + } else if ("validate".equalsIgnoreCase(argv[0])) { + if (argv.length == 3) { + String xmlfile = argv[1]; + String propfile = argv[2]; + + System.setProperty(SLI_VALIDATING_PARSER, "true"); + SvcLogicStore store = SvcLogicParser.getStore(propfile); + try { + SvcLogicParser.validate(xmlfile, store); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } else { + SvcLogicParser.usage(); + } + } + + System.exit(0); + } + + private static SvcLogicStore getStore(String propfile) { + + SvcLogicStore store = null; + + try { + store = SvcLogicStoreFactory.getSvcLogicStore(propfile); + } catch (Exception e) { + LOGGER.error(SVC_LOGIC_STORE_ERROR, e); + System.exit(1); + } + + return store; + + } + + public static void load(String xmlfile, SvcLogicStore store) throws SvcLogicException { + File xmlFile = new File(xmlfile); + if (!xmlFile.canRead()) { + throw new ConfigurationException("Cannot read xml file (" + xmlfile + ")"); + } + + SvcLogicParser parser = new SvcLogicParser(store); + LinkedList<SvcLogicGraph> graphs = null; + try { + graphs = parser.parse(xmlfile); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + if (graphs == null) { + throw new SvcLogicException("Could not parse " + xmlfile); + } + + for (SvcLogicGraph graph : graphs) { + + String module = graph.getModule(); + String rpc = graph.getRpc(); + String version = graph.getVersion(); + String mode = graph.getMode(); + try { + LOGGER.info("Saving SvcLogicGraph to database (module:" + module + ",rpc:" + rpc + ",version:" + version + ",mode:" + mode + ")"); + store.store(graph); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + } + + } + + public static void validate(String xmlfile, SvcLogicStore store) throws SvcLogicException { + File xmlFile = new File(xmlfile); + if (!xmlFile.canRead()) { + throw new ConfigurationException("Cannot read xml file (" + xmlfile + ")"); + } + + SvcLogicParser parser = new SvcLogicParser(store); + LinkedList<SvcLogicGraph> graphs = null; + try { + LOGGER.info("Validating " + xmlfile); + graphs = parser.parse(xmlfile); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + if (graphs == null) { + throw new SvcLogicException("Could not parse " + xmlfile); + } else { + LOGGER.info("Compilation successful for " + xmlfile); + } + + } + + private static void print(String module, String rpc, String mode, String version, SvcLogicStore store) { + String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")"; + + try { + LOGGER.info(LOAD_MESSAGE + details); + + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + if (graph == null) { + LOGGER.error(LOAD_ERROR_MESSAGE + details); + System.exit(1); + } + graph.printAsGv(System.out); + } catch (Exception e) { + LOGGER.error(PRINT_ERROR_MESSAGE + details, e); + System.exit(1); + } + + } + + private static void getSource(String module, String rpc, String mode, String version, SvcLogicStore store) { + String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")"; + + try { + LOGGER.info(LOAD_MESSAGE + details); + + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + if (graph == null) { + LOGGER.error(LOAD_ERROR_MESSAGE + details); + System.exit(1); + } + graph.printAsXml(System.out); + } catch (Exception e) { + LOGGER.error(PRINT_ERROR_MESSAGE + details, e); + System.exit(1); + } + + } + + private static void activate(String module, String rpc, String version, String mode, SvcLogicStore store) { + String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")"; + + try { + LOGGER.info(LOAD_MESSAGE + details); + + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + if (graph == null) { + LOGGER.error(LOAD_ERROR_MESSAGE + details); + System.exit(1); + } + store.activate(graph); + } catch (Exception e) { + LOGGER.error(ACTIVATION_ERROR_MESSAGE + details, e); + System.exit(1); + } + + } + + private static void usage() { + System.err.println("Usage: SvcLogicParser load <xml-file> <prop-file>"); + System.err.println(" OR SvcLogicParser print <module> <rpc> <mode> [<version>] <prop-file>"); + System.err.println(" OR SvcLogicParser get-source <module> <rpc> <mode> <version> <prop-file>"); + System.err.println(" OR SvcLogicParser activate <module> <rpc> <version> <mode>"); + System.exit(1); + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicParserException.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicParserException.java new file mode 100644 index 00000000..ac9c515e --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicParserException.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.IOException; + +public class SvcLogicParserException extends IOException { + + public SvcLogicParserException() { + super(); + } + + public SvcLogicParserException(String msg) { + super(msg); + } + + public SvcLogicParserException(Throwable t) { + super(t); + } + + public SvcLogicParserException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicRecorder.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicRecorder.java new file mode 100644 index 00000000..8a23adf1 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicRecorder.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.Map; + +public interface SvcLogicRecorder { + + void record(Map<String, String> parmMap) throws SvcLogicException; + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicResource.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicResource.java new file mode 100644 index 00000000..5fc00f87 --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicResource.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.sql.SQLException; +import java.util.Map; + +public interface SvcLogicResource { + + public enum QueryStatus { + SUCCESS, + NOT_FOUND, + FAILURE + } + + public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx) throws SvcLogicException; + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicStore.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicStore.java new file mode 100644 index 00000000..6959c86a --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicStore.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.util.Properties; + +public interface SvcLogicStore { + + public void init(Properties props) throws SvcLogicException; + public void registerNodeType(String nodeType) throws SvcLogicException; + public void unregisterNodeType(String nodeType) throws SvcLogicException; + public boolean isValidNodeType(String nodeType) throws SvcLogicException; + public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException; + public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException; + public void store(SvcLogicGraph graph) throws SvcLogicException; + public void delete(String module, String rpc, String version, String mode) throws SvcLogicException; + public void activate(SvcLogicGraph graph) throws SvcLogicException; +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicStoreFactory.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicStoreFactory.java new file mode 100644 index 00000000..8b6618be --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicStoreFactory.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicStoreFactory { + + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicStoreFactory.class); + + public static SvcLogicStore getSvcLogicStore(String propfile) + throws SvcLogicException { + File propFile = new File(propfile); + if (!propFile.canRead()) { + throw new ConfigurationException("Cannot read property file " + + propfile); + + } + + try { + return (getSvcLogicStore(new FileInputStream(propFile))); + } catch (Exception e) { + throw new ConfigurationException( + "Could load service store from properties file " + propfile, + e); + } + + } + + public static SvcLogicStore getSvcLogicStore(InputStream inStr) throws SvcLogicException + { + Properties props = new Properties(); + + try { + props.load(inStr); + } catch (Exception e) { + throw new ConfigurationException("Could not get load properties from input stream", e); + } + + return(getSvcLogicStore(props)); + } + + public static SvcLogicStore getSvcLogicStore(Properties props) + throws SvcLogicException { + String storeType = props.getProperty("org.openecomp.sdnc.sli.dbtype"); + if ((storeType == null) || (storeType.length() == 0)) { + throw new ConfigurationException( + "property org.openecomp.sdnc.sli.dbtype unset"); + + } + + SvcLogicStore retval = null; + LOG.debug(String.format("Using org.openecomp.sdnc.sli.dbtype=%s", storeType)); + + if ("jdbc".equalsIgnoreCase(storeType)) { + retval = new SvcLogicJdbcStore(); + + } else if ("dblib".equalsIgnoreCase(storeType)) { + retval = new SvcLogicDblibStore(); + } else { + throw new ConfigurationException("unsupported dbtype (" + storeType + + ")"); + + } + + + retval.init(props); + return (retval); + } + +} diff --git a/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicVariableTerm.java b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicVariableTerm.java new file mode 100644 index 00000000..9ddc3c0b --- /dev/null +++ b/sli/common/src/main/java/org/openecomp/sdnc/sli/SvcLogicVariableTerm.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +public class SvcLogicVariableTerm extends SvcLogicExpression { + + private String name = null; + + public String getName() { + return name; + } + + + public SvcLogicVariableTerm(String identifier) + { + this.name = identifier; + } + + public SvcLogicExpression getSubscript() + { + if (numOperands() > 0) + { + return(getOperands().get(0)); + } + else + { + return(null); + } + } + + + public String toString() + { + String retval = ""; + + if (numOperands() > 0) + { + retval = name + "[" + getSubscript().toString() + "]"; + } + else + { + retval = name; + } + return(retval); + } + + @Override + public String asParsedExpr() { + if (numOperands() == 0) { + return("(variable-term "+name+")"); + } + else + { + return("(variable-term "+name+" "+getSubscript().asParsedExpr()+")"); + } + } + +} diff --git a/sli/common/src/main/resources/crAseNetwork.sql b/sli/common/src/main/resources/crAseNetwork.sql new file mode 100644 index 00000000..41231176 --- /dev/null +++ b/sli/common/src/main/resources/crAseNetwork.sql @@ -0,0 +1,82 @@ +--- +-- ============LICENSE_START======================================================= +-- openECOMP : SDN-C +-- ================================================================================ +-- Copyright (C) 2017 AT&T Intellectual Property. All rights +-- reserved. +-- ================================================================================ +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- ============LICENSE_END========================================================= +--- + +CREATE TABLE sdnctl.ASE ( + ase_network_id INT NOT NULL, + topology VARCHAR(25), + CONSTRAINT P_ASE PRIMARY KEY(ase_network_id)); + +CREATE TABLE sdnctl.ASE_PORT ( + esm_name VARCHAR(25), + resource_emt_clli VARCHAR(25) NOT NULL, + resource_emt_ip_addr VARCHAR(25) NOT NULL, + port_action VARCHAR(25), + profile VARCHAR(25) , + port VARCHAR(15) NOT NULL, + state VARCHAR(25), + resource_mode VARCHAR(25), + speed INT, + resource_lldp VARCHAR(1), + resource_mtu VARCHAR(5), + resource_autoneg VARCHAR(10), + resource_twamp VARCHAR(10), + resource_description VARCHAR(80), + uni_circuit_id VARCHAR(45), + CONSTRAINT P_ASE_PORT PRIMARY KEY(resource_emt_clli, port)); + +CREATE TABLE sdnctl.ASE_EVC ( + esm_name VARCHAR(25), + emt_ip_addr VARCHAR(25) NOT NULL, + evc_action VARCHAR(25), + service_id VARCHAR(25), + serv_type VARCHAR(25), + evc_choice VARCHAR(25), + uni_port VARCHAR(25) NOT NULL, + lag_port VARCHAR(25), + mac_onoff VARCHAR(25), + ppcos VARCHAR(25), + cir VARCHAR(25), + cbs VARCHAR(25), + ebs VARCHAR(25), + sgos VARCHAR(25), + pe VARCHAR(25), + unit VARCHAR(25), + qinq VARCHAR(25), + interface VARCHAR(25), + evc_description VARCHAR(80), + bandwidth VARCHAR(10), + svlan VARCHAR(5), + cvlan VARCHAR(5), + routing_instance VARCHAR(25), + rd VARCHAR(25), + rt VARCHAR(25), + evc_limit VARCHAR(25), + label_block_size VARCHAR(25), + site VARCHAR(25), + int_mac_limit VARCHAR(5), + sgos_grade VARCHAR(25), + bum_rate VARCHAR(25), + uni_circuit_id VARCHAR(45), + leg INT, + CONSTRAINT P_ASE_EVC PRIMARY KEY(emt_ip_addr, uni_port,leg)); + + + diff --git a/sli/common/src/main/resources/svclogic.xsd b/sli/common/src/main/resources/svclogic.xsd new file mode 100755 index 00000000..f74bd5dc --- /dev/null +++ b/sli/common/src/main/resources/svclogic.xsd @@ -0,0 +1,334 @@ +<?xml version = "1.0" encoding = "UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.openecomp.org/sdnc/svclogic" xmlns="http://www.openecomp.org/sdnc/svclogic">
+
+ <xsd:simpleType name="modeType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="sync" />
+ <xsd:enumeration value="async" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:group name="node">
+ <xsd:choice>
+ <xsd:element ref="block" />
+ <xsd:element ref="is-available" />
+ <xsd:element ref="exists" />
+ <xsd:element ref="reserve" />
+ <xsd:element ref="release" />
+ <xsd:element ref="allocate" />
+ <xsd:element ref="get-resource" />
+ <xsd:element ref="configure" />
+ <xsd:element ref="return" />
+ <xsd:element ref="switch" />
+ <xsd:element ref="record" />
+ <xsd:element ref="save" />
+ <xsd:element ref="for" />
+ <xsd:element ref="set" />
+ <xsd:element ref="execute" />
+ <xsd:element ref="delete" />
+ <xsd:element ref="update" />
+ <xsd:element ref="call" />
+ <xsd:element ref="notify" />
+ <xsd:element ref="break" />
+ <xsd:element ref="while" />
+ </xsd:choice>
+ </xsd:group>
+
+ <xsd:element name="service-logic">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="method" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="module" use="required" type="xsd:string" />
+ <xsd:attribute name="version" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="method">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="rpc" use="required" type="xsd:string" />
+ <xsd:attribute name="mode" use="optional" type="modeType" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="block">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="atomic" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="is-available">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="exists">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="outcome">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="ref" use="optional" type="xsd:string" />
+ <xsd:attribute name="value" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="reserve">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="select" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="release">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="record">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="allocate">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ <xsd:attribute name="pfx" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="get-resource">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="order-by" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="configure">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="adaptor" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ <xsd:attribute name="activate" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="parameter">
+ <xsd:complexType>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="value" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="return">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="status" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="switch">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="test" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="save">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="force" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="delete">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ <!-- local-only is retired and does not do anything -->
+ <xsd:attribute name="local-only" use="optional" type="xsd:string" />
+ <!-- pfx is retired and does not do anything -->
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="for">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="atomic" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="index" use="required" type="xsd:string" />
+ <xsd:attribute name="start" use="required" type="xsd:string" />
+ <xsd:attribute name="end" use="required" type="xsd:string" />
+ <xsd:attribute name="silentFailure" use="optional" type="xsd:boolean" default="false" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="set">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="only-if-unset" use="optional"
+ type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="execute">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="method" use="required" type="xsd:string" />
+ <xsd:attribute name="emitsOutcome" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="update">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="force" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="call">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="module" use="optional" type="xsd:string" />
+ <xsd:attribute name="rpc" use="required" type="xsd:string" />
+ <xsd:attribute name="version" use="optional" type="xsd:string" />
+ <xsd:attribute name="mode" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="notify">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="optional" type="xsd:string" />
+ <xsd:attribute name="resource" use="optional" type="xsd:string" />
+ <xsd:attribute name="action" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="break">
+ <xsd:complexType />
+ </xsd:element>
+
+ <xsd:element name="while">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="test" use="required" type="xsd:string" />
+ <xsd:attribute name="do" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
diff --git a/sli/common/src/main/yang/ase-network.yang b/sli/common/src/main/yang/ase-network.yang new file mode 100755 index 00000000..ae654ae0 --- /dev/null +++ b/sli/common/src/main/yang/ase-network.yang @@ -0,0 +1,179 @@ +module ase { + namespace "att:ase"; + prefix ase; + revision "2014-06-03" { + description "Example ASE Network Module"; + } + + container ase { + config true; + leaf ase-network-id{ + type uint32; + } + leaf topology { + type string ; // check enum + } + } + + container ase-port { + config true; + // is this really a list of cpe ports one for each uni-ckt + leaf esm-name { + type string; + } + + leaf resource-emt-clli { + type string; + } + + leaf resource-emt-ip-addr{ + type string; + } + leaf port-action { + type string; + } + leaf profile { + type string; + } + leaf port { + type string; + } + leaf state { + type string; + } + leaf resource-mode { + type string; + } + leaf speed { + type string; + } + leaf resource-lldp { + type string; + } + leaf resource-mtu { + type string; + } + leaf resource-autoneg{ + type string; + } + leaf resource-twamp { + type string; + } + leaf resource-description { + type string; + } + leaf uni-circuit-id { + type string; + } + } // ase-port container + + container ase-evc { +// Port contains a list of EVC +// EVCs are either point to point or multipoint (topology) +// EVCs are connected ? what ID is used to connected them ? (network-id) ? + config true; + leaf esm-name { + type string; + } + leaf emt-ip-addr { + type string; + } + leaf evc-action { + type string; + } + leaf service-id { + type string; + } + + leaf serv-type { + type string; + } + leaf evc-choice { + type string; + } + leaf uni-port { + type string; + } + leaf lag-port { + type string; + } + leaf mac-onoff { + type string; + } + + leaf ppcos { + type string; + } + leaf cir { + type string; + } + leaf cbs { + type string; + } + leaf ebs { + type string; + } + leaf sgos { + type string; + } +// ipag Device Data + leaf pe { + type string; + } + leaf unit { + type string; + } + leaf qinq { + type string; + } + leaf interface { + type string; + } + leaf evc-description { + type string; + } + leaf bandwidth { + type string; + } + leaf svlan { + type string; + description "Service VLAN is either outer tag or only tag depending on QinQ"; + } + leaf cvlan { + type string; + description "Customer VLAN is null if not QinQ"; + } + leaf routing-instance { + type string; + } + leaf rd { + type string; + } + leaf rt { + type string; + } + leaf limit { + type string; + } + leaf label-block-size { + type string; + } + leaf site { + type string; + } + leaf int-mac-limit { + type string; + } + leaf sgos-grade { + type string; + } + leaf bum-rate { + type string; + } + leaf uni-circuit-id { + type string; + } + } // ase-evc container + +} // module ase-network + diff --git a/sli/common/src/main/yang/ase-type.yang b/sli/common/src/main/yang/ase-type.yang new file mode 100755 index 00000000..2de186e6 --- /dev/null +++ b/sli/common/src/main/yang/ase-type.yang @@ -0,0 +1,561 @@ +module ase-type { + + namespace "att:ase:type"; + prefix ase-type; + + organization "AT&T ASE"; + + revision 2014-06-09 { + description + "Initial version"; + } + + ///////////////////////////////////////////////////// + // ASE Service Model Typedefs & Groupings + ///////////////////////////////////////////////////// + + typedef query-type { + type enumeration { + enum getDevicePortDetails{ + value 0; + } + enum GetServiceDetailsRequest{ + value 1; + } + } + } + + typedef uni-action-type { + type enumeration { + enum PortPreReserveRequest{ + value 0; + } + enum PortReleaseRequest{ + value 1; + } + enum PortDeProvRequest{ + value 2; + } + enum ChangePortProvRequest{ + value 3; + } + enum PortActivateRequest{ + value 4; + } + enum ChangePortActivateRequest{ + value 5; + } + enum DisconnectPortRequest{ + value 6; + } + enum getDevicePortDetails{ + value 7; + } + } + } + + typedef evc-action-type { + type enumeration { + enum ConnectionProvRequest{ + value 0; + } + enum ChangeConnectionProvRequest{ + value 1; + } + enum ConnectionDeProvrequest{ + value 2; + } + enum ConnectionActivateRequest{ + value 3; + } + enum ChangeConnectionActivateRequest{ + value 4; + } + enum DisconnectConnectionRequest{ + value 5; + } + enum GetServiceDetailsRequest{ + value 6; + } + } + } + + typedef evc-gos-type { + type enumeration { + enum "REAL-TIME"{ + value 0; + } + enum "INTERACTIVE"{ + value 1; + } + enum "BUSINESS-CRITICAL-HIGH"{ + value 2; + } + enum "BUSINESS-CRITICAL-MEDIUM"{ + value 3; + } + enum "NON-CRITICAL-HIGH"{ + value 4; + } + enum "NON-CRITICAL-LOW"{ + value 5; + } + } + } + + typedef cir-rate-type { + type enumeration { + enum "Mbps"{ + value 0; + } + enum "Gbps"{ + value 1; + } + } + } + + typedef ase-yes-no-type { + type enumeration { + enum "Y"{ + value 0; + } + enum "N"{ + value 1; + } + } + } + + typedef provisioning-indicator { + type enumeration { + enum "Y"{ + value 0; + } + enum "N"{ + value 1; + } + } + } + + typedef media-type { + type enumeration { + enum "SFP-1GE-SX"{ + value 0; + } + enum "SFP-1GE-LX"{ + value 1; + } + enum "SFP-1GE"{ + value 2; + } + enum "Ethernet-10_100_1000M"{ + value 3; + } + } + } + + typedef media-speed-type { + type enumeration { + enum "100"{ + value 0; + } + enum "1000"{ + value 1; + } + enum "10000"{ + value 2; + } + } + } + + typedef cos-category-type { + type enumeration { + enum "GOS"{ + value 0; + } + enum "PPCOS"{ + value 1; + } + } + } + + typedef uni-gos-type { + type enumeration { + enum "INTERACTIVE"{ + value 0; + } + enum "BUSINESS-CRITICAL-HIGH"{ + value 1; + } + enum "BUSINESS-CRITICAL-MEDIUM"{ + value 2; + } + enum "NON-CRITICAL-HIGH"{ + value 3; + } + } + } + + typedef uni-cir-value-type { + type enumeration { + enum "2"{ + value 0; + } + enum "4"{ + value 1; + } + enum "5"{ + value 2; + } + enum "8"{ + value 3; + } + enum "10"{ + value 4; + } + enum "20"{ + value 5; + } + enum "30"{ + value 6; + } + enum "40"{ + value 7; + } + enum "50"{ + value 8; + } + enum "60"{ + value 9; + } + enum "70"{ + value 10; + } + enum "80"{ + value 11; + } + enum "90"{ + value 12; + } + enum "100"{ + value 13; + } + enum "125"{ + value 14; + } + enum "150"{ + value 15; + } + enum "175"{ + value 16; + } + enum "200"{ + value 17; + } + enum "225"{ + value 18; + } + enum "250"{ + value 19; + } + } + } + + typedef uni-mac-limit-type { + description "MAC address limit for UNI port"; + type enumeration { + enum "Y"{ + value 0; + } + enum "N"{ + value 1; + } + } + } + + typedef port-tagging-type { + type enumeration { + enum "port-based"{ + value 0; + } + enum "vlan-based"{ + value 1; + } + } + } + + typedef port-status { + type enumeration { + enum "Available"{ + value 0; + } + enum "Reserved"{ + value 1; + } + enum "Active" { + value 2; + } + } + } + + grouping uni-common-request-hdr { + leaf request-id { + type string; + mandatory true; + } + leaf source { + description "The source system requesting action or info"; + type string; + mandatory true; + } + leaf request-action { + description "action indicator for this service instance"; + type uni-action-type; + } + leaf undo-indicator { + type provisioning-indicator; + } + leaf notification-url { + description "When this field exists, NCS will return an " + + "acknowledgement that the request is legal " + + "Once the activate is finished (or fails) NCS" + + "will utilize the URL to indicate the status"; + type string; + } + } + + grouping uni-common-return-hdr { + leaf request-action { + description "action indicator for this service instance"; + type uni-action-type; + } + leaf request-id { + description "Identifier for the request from NGO"; + type string; + + } + } + + grouping uni-common-error-format { + leaf error-code { + description "Error code"; + type int32; + } + leaf error-message { + description "Error text describing the API error occurance"; + type string; + } + } + + grouping query-common-hdr { + leaf request-id { + description "Identifier for the request from NGO"; + type string; + } + leaf request-type { + description "action indicator for this service instance"; + type query-type; + } + } + + grouping query-error-format { + leaf error-code { + description "Error code"; + type int32; + } + leaf error-message { + description "Error text describing the API error occurance"; + type string; + } + } + + grouping evc-common-request-hdr { + leaf request-id { + description "Identifier for the request from NGO"; + type string; + } + leaf source { + description "The source system requesting action or info"; + type string; + mandatory true; + } + leaf uni-order-number { + type string; + } + leaf request-action { + description "action indicator for this service instance"; + type evc-action-type; + mandatory true; + } + leaf undo-indicator { + type provisioning-indicator; + } + leaf notification-url { + description "When this field exists, NCS will return an " + + "acknowledgement that the request is legal " + + "Once the activate is finished (or fails) NCS" + + "will utilize the URL to indicate the status"; + type string; + } + leaf evc-name { + type string; + mandatory true; + } + } + + grouping evc-common-error-format { + leaf error-code { + description "Error code"; + type int32; + } + leaf error-message { + description "Error text describing the API error occurance"; + type string; + } + } + + ///////////////////////////////////////// + // UNI-PORTS table contains all circuits + ///////////////////////////////////////// + container uni-ports { + description + "UNI port container"; + list uni-port { + key "uni-circuit-id"; + leaf uni-circuit-id { + type string; + mandatory true; + } + leaf subscriber-name { + type string; + mandatory true; + } + leaf uni-order-number { + type string; + mandatory true; + } + leaf edge-device-clli { + description "Edge device (e.g. EMT) on which port " + + " reservation is needed"; + type string; + mandatory true; + } + leaf uni-location-city { + type string; + mandatory true; + } + leaf uni-location-state { + type string; + mandatory true; + } + leaf media-type { + type media-type; + mandatory true; + } + leaf media-speed { + type media-speed-type; + mandatory true; + } + leaf uni-cir-value { + description "Integer value for the CIR"; + type uni-cir-value-type; + mandatory true; + } + leaf uni-cir-units { + description "Units for the CIR"; + type cir-rate-type; + mandatory true; + } + leaf cos-category { + description "CoS Type"; + type cos-category-type; + mandatory true; + } + leaf gos-profile { + description "GoS tpye"; + type uni-gos-type; + mandatory true; + } + leaf aditional-mac-allowed { + type uni-mac-limit-type; + } + leaf port-tagging { + type port-tagging-type; + mandatory true; + } + leaf port-status { + type port-status; + } + leaf name-value-pair { + type string; + } + } + } + + /////////////////////////////////////////// + // EVCS table contains all evc associations + /////////////////////////////////////////// + container evcs { + list evc { + key "evc-name"; + leaf evc-name { + type string; + mandatory true; + } + leaf topology { + type enumeration { + enum "MultiPoint"{ + value 0; + } + enum "PointToPoint"{ + value 1; + } + } + } + list evc-leg { + key evc-access-name; + leaf evc-access-name { + type string; + } + leaf subscriber-name { + type string; + } + leaf cvlan { + type uint16 { + range "2..4090"; + } + } + leaf connection-cir-value { + type uni-cir-value-type; + } + leaf connection-cir-units-string { + type cir-rate-type; + } + leaf connection-gos-profile { + type evc-gos-type; + } + leaf connection-additional-mac-allowed { + type uni-mac-limit-type; + } + leaf connection-emc-indicator { + type enumeration { + enum "Y"{ + value 0; + } + enum "N"{ + value 1; + } + } + } + leaf connection-emc-speed-value { + type uni-cir-value-type; + } + leaf connection-emc-speed-units-string { + type cir-rate-type; + } + } + leaf name-value-pair { + type string; + } + } + } +} diff --git a/sli/common/src/main/yang/ase.yang b/sli/common/src/main/yang/ase.yang new file mode 100755 index 00000000..0b36a561 --- /dev/null +++ b/sli/common/src/main/yang/ase.yang @@ -0,0 +1,558 @@ +module ase { + + namespace "att:ase"; + prefix ase; + + import ase-type {prefix ase-type; revision-date "2014-06-09";} + + organization "AT&T ASE"; + + description + "This submodule contains a collection of YANG definitions for + defining the ASE service model(s) for UNI and EVC"; + + revision 2014-03-27 { + description + "Additional detail for UNI and EVC API"; + } + revision 2014-03-18 { + description + "Initial version"; + } + + + ///////////////////////////////////////////////////// + // ASE Query Actions + ///////////////////////////////////////////////////// + + //// + // Port Reserve Request + //// + rpc ase-port-reserve { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + leaf edge-device-clli { + description "Edge device (e.g. EMT) on which port " + + " reservation is needed"; + type string; + mandatory true; + } + leaf uni-cir-value { + description "Integer value for the CIR"; + type ase-type:uni-cir-value-type; + mandatory true; + } + leaf uni-cir-units { + description "Units for the CIR"; + type ase-type:cir-rate-type; + mandatory true; + } + } + output { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + } + leaf uni-port-id { + description "Allocated UNI port id"; + type string; + } + + uses ase-type:uni-common-error-format; + } + } + + //// + // Release Port Request + //// + rpc ase-release-port-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + } + output { + uses ase-type:uni-common-return-hdr; + uses ase-type:uni-common-error-format; + } + } + + //// + // Port Provisioning Request + //// + rpc ase-port-prov-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + leaf subscriber-name { + type string; + mandatory true; + } + leaf uni-order-number { + type string; + mandatory true; + } + leaf edge-device-clli { + description "Edge device (e.g. EMT) on which port " + + " reservation is needed"; + type string; + mandatory true; + } + leaf uni-location-city { + type string; + mandatory true; + } + leaf uni-location-state { + type string; + mandatory true; + } + leaf media-type { + type ase-type:media-type; + mandatory true; + } + leaf media-speed { + type ase-type:media-speed-type; + mandatory true; + } + leaf uni-cir-value { + description "Integer value for the CIR"; + type ase-type:uni-cir-value-type; + mandatory true; + } + leaf uni-cir-units { + description "Units for the CIR"; + type ase-type:cir-rate-type; + mandatory true; + } + leaf cos-category { + description "CoS Type"; + type ase-type:cos-category-type; + mandatory true; + } + leaf gos-profile { + description "GoS tpye"; + type ase-type:uni-gos-type; + mandatory true; + } + leaf aditional-mac-allowed { + type ase-type:uni-mac-limit-type; + } + leaf port-tagging { + type ase-type:port-tagging-type; + mandatory true; + } + leaf name-value-pair { + type string; + } + } + output { + uses ase-type:uni-common-return-hdr; + uses ase-type:uni-common-error-format; + } + } + + //// + // Deprovisioning Port Request + //// + rpc ase-deprov-port-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + } + output { + uses ase-type:uni-common-error-format; + } + } + + //// + // Change Port Provisioning Request + //// + rpc ase-change-port-prov-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + leaf subscriber-name { + type string; + } + leaf media-speed { + type ase-type:media-speed-type; + } + leaf uni-cir-value { + description "Integer value for the CIR"; + type ase-type:uni-cir-value-type; + } + leaf uni-cir-units { + description "Units for the CIR"; + type ase-type:cir-rate-type; + } + leaf cos-catagory { + type ase-type:cos-category-type; + } + leaf gos-profile { + type ase-type:uni-gos-type; + } + leaf additional-mac-allowed { + type ase-type:uni-mac-limit-type; + } + leaf port-tagging { + type ase-type:port-tagging-type; + mandatory true; + } + leaf name-value-pair { + type string; + } + } + output { + uses ase-type:uni-common-error-format; + } + } + + //// + // Port Activate Request + //// + rpc ase-port-activate-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + } + output { + uses ase-type:uni-common-error-format; + } + } + + //// + // Port Change Activation Request + //// + rpc ase-change-port-activation-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + } + output { + uses ase-type:uni-common-error-format; + } + } + + //// + // Port Disconnect Request + //// + rpc ase-port-disconnect-request { + input { + uses ase-type:uni-common-request-hdr; + + leaf uni-circuit-id { + type string; + mandatory true; + } + } + output { + uses ase-type:uni-common-error-format; + } + } + + ///////////////////////////////////////////////////// + // EVC API + ///////////////////////////////////////////////////// + + //// + // EVC Provision Request + //// + rpc ase-evc-activation { + input { + uses ase-type:evc-common-request-hdr; + leaf topology { + type enumeration { + enum "MultiPoint"{ + value 0; + } + enum "PointToPoint"{ + value 1; + } + } + } + list evc-leg { + key evc-access-name; + leaf evc-access-name { + type string; + } + leaf subscriber-name { + type string; + } + leaf cvlan { + type uint16 { + range "2..4090"; + } + } + leaf connection-cir-value { + type ase-type:uni-cir-value-type; + } + leaf connection-cir-units-string { + type ase-type:cir-rate-type; + } + leaf connection-gos-profile { + type ase-type:evc-gos-type; + } + leaf connection-additional-mac-allowed { + type ase-type:uni-mac-limit-type; + } + leaf connection-emc-indicator { + type enumeration { + enum "Y"{ + value 0; + } + enum "N"{ + value 1; + } + } + } + leaf connection-emc-speed-value { + type ase-type:uni-cir-value-type; + } + leaf connection-emc-speed-units-string { + type ase-type:cir-rate-type; + } + } + leaf name-value-pair { + type string; + } + } + output { + uses ase-type:evc-common-error-format; + } + } + + //// + // EVC Change Activation Request + //// + rpc ase-evc-change-activation { + input { + uses ase-type:evc-common-request-hdr; + leaf topology { + type enumeration { + enum "MultiPoint"{ + value 0; + } + enum "PointToPoint"{ + value 1; + } + } + } + list evc-leg { + key evc-access-name; + leaf evc-access-name { + type string; + } + leaf connection-cir-value { + type ase-type:uni-cir-value-type; + } + leaf connection-cir-units-string { + type ase-type:cir-rate-type; + } + leaf connection-gos-profile { + type ase-type:evc-gos-type; + } + leaf connection-additional-mac-allowed { + type ase-type:uni-mac-limit-type; + } + + } + leaf name-value-pair { + type string; + } + + } + output { + uses ase-type:evc-common-error-format; + } + } + + //// + // EVC Disconnet Connection Request + //// + rpc ase-evc-disconnect-request { + input { + uses ase-type:evc-common-request-hdr; + leaf topology { + type enumeration { + enum "MultiPoint"{ + value 0; + } + enum "PointToPoint"{ + value 1; + } + } + } + list evc-leg { + key evc-access-name; + leaf evc-access-name { + type string; + } + } + leaf name-value-pair { + type string; + } + + } + output { + uses ase-type:evc-common-error-format; + } + } + + ///////////////////////////////////////////////////// + // ASE Query Actions + ///////////////////////////////////////////////////// + + rpc find-available-ports { + description "Return a count of available ports"; + input { + uses ase-type:query-common-hdr; + leaf edge-device-clli { + type string; + mandatory true; + } + + leaf port-role { + type enumeration { + enum "NETWORK"{ + value 0; + } + enum "ACCESS"{ + value 1; + } + enum "SDN-ACCESS"{ + value 2; + } + } + mandatory true; + } + leaf port-assigned { + type string; + } + } + output { + uses ase-type:query-common-hdr; + container statuss { + leaf edge-device-clli { + type string; + } + container max-cir { + leaf cir-value { + type uint16; + } + leaf cir-type { + type ase-type:cir-rate-type; + } + } + leaf if-count { + type uint16; + } + } + uses ase-type:query-error-format; + } + } + + rpc find-evcs-in-uni { + description "Return EVC instances for a specified UNI"; + input { + uses ase-type:query-common-hdr; + + leaf uni-circuit-id { + type string; //leafref + } + leaf edge-device-clli { + description "Edge device (e.g. EMT) on which port " + + " reservation is needed"; + type string; + } + } + output { + uses ase-type:query-common-hdr; + + leaf uni-leg-name { + description "NGO-proivded named"; + type string; + } + uses ase-type:query-error-format; + } + } + + rpc find-service-details { + description "Return EVC instances for a specified UNI"; + input { + uses ase-type:query-common-hdr; + leaf uni-circuit-id { + type string; //leafref + } + leaf source { + type string; + mandatory true; + } + leaf service-name { + type string; + mandatory true; + } + leaf service-type { + type string; + mandatory true; + } + } + output { + uses ase-type:query-common-hdr; + + leaf service-name { + type string; + mandatory true; + } + leaf service-type { + type string; + mandatory true; + } + leaf service-state { + type enumeration { + enum "Active"{ + value 0; + } + enum "NotActive"{ + value 1; + } + } + } + leaf has-pending-change { + type ase-type:ase-yes-no-type; + } + leaf allowed-connection-count { + type int16; + } + uses ase-type:query-error-format; + } + } +} //module diff --git a/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicContextTest.java b/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicContextTest.java new file mode 100644 index 00000000..6e6656e8 --- /dev/null +++ b/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicContextTest.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Enumeration; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; + +import junit.framework.TestCase; + +public class SvcLogicContextTest extends TestCase { + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicContext.class); + + public void testMerge() { + + try { + InputStream testStr = getClass().getResourceAsStream("/mergetest.xml"); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + + Document theDocument = db.parse(testStr); + SvcLogicContext ctx = new SvcLogicContext(); + ctx.mergeDocument("test-merge", theDocument); + Properties props = ctx.toProperties(); + LOG.info("SvcLogicContext contains the following : "); + for (Enumeration e = props.propertyNames(); e.hasMoreElements() ; ) { + String propName = (String) e.nextElement(); + LOG.info(propName+" = "+props.getProperty(propName)); + + } + } catch (Exception e) { + LOG.error("Caught exception trying to merge", e); + fail("Caught exception trying to merge"); + } + + } + +} diff --git a/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicExpressionParserTest.java b/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicExpressionParserTest.java new file mode 100644 index 00000000..d6503b60 --- /dev/null +++ b/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicExpressionParserTest.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.openecomp.sdnc.sli.SvcLogicExprListener; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicExpressionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import junit.framework.TestCase; + +public class SvcLogicExpressionParserTest extends TestCase { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExprListener.class); + + public void testParse() { + try + { + InputStream testStr = getClass().getResourceAsStream("/expression.tests"); + BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr)); + + String testExpr = null; + while ((testExpr = testsReader.readLine()) != null) { + + SvcLogicExpression parsedExpr = SvcLogicExpressionFactory.parse(testExpr); + if (parsedExpr == null) + { + fail("parse("+testExpr+") returned null"); + } + else + { + LOG.info("test expression = ["+testExpr+"] ; parsed expression = ["+parsedExpr.asParsedExpr()+"]"); + + } + } + } + catch (Exception e) + { + e.printStackTrace(); + fail("Caught exception processing test cases"); + } + } + +} diff --git a/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicParserTest.java b/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicParserTest.java new file mode 100644 index 00000000..e8ff2fee --- /dev/null +++ b/sli/common/src/test/java/org/openecomp/sdnc/sli/SvcLogicParserTest.java @@ -0,0 +1,163 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +package org.openecomp.sdnc.sli; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.LinkedList; + +import org.openecomp.sdnc.sli.SvcLogicParser; +import org.openecomp.sdnc.sli.SvcLogicParserException; +import org.openecomp.sdnc.sli.SvcLogicStore; +import org.openecomp.sdnc.sli.SvcLogicStoreFactory; + +import junit.framework.TestCase; + +/** + * @author dt5972 + * + */ +public class SvcLogicParserTest extends TestCase { + + /** + * Test method for {@link org.openecomp.sdnc.sli.SvcLogicParser#parse(java.lang.String)}. + */ + + + public void testParse() { + + + try + { + + URL propUrl = getClass().getResource("/svclogic.properties"); + + InputStream propStr = getClass().getResourceAsStream("/svclogic.properties"); + + SvcLogicStore store = SvcLogicStoreFactory.getSvcLogicStore(propStr); + + assertNotNull(store); + + store.registerNodeType("switch"); + store.registerNodeType("block"); + store.registerNodeType("get-resource"); + store.registerNodeType("reserve"); + store.registerNodeType("is-available"); + store.registerNodeType("exists"); + store.registerNodeType("configure"); + store.registerNodeType("return"); + store.registerNodeType("record"); + store.registerNodeType("allocate"); + store.registerNodeType("release"); + store.registerNodeType("for"); + store.registerNodeType("set"); + + + InputStream testStr = getClass().getResourceAsStream("/parser-good.tests"); + BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr)); + String testCaseFile = null; + while ((testCaseFile = testsReader.readLine()) != null) { + + testCaseFile = testCaseFile.trim(); + + if (testCaseFile.length() > 0) + { + if (!testCaseFile.startsWith("/")) + { + testCaseFile = "/"+testCaseFile; + } + URL testCaseUrl = getClass().getResource(testCaseFile); + if (testCaseUrl == null) + { + fail("Could not resolve test case file "+testCaseFile); + } + + try { + SvcLogicParser.validate(testCaseUrl.getPath(), store); + } catch (Exception e) { + fail("Validation failure ["+e.getMessage()+"]"); + + } + + + + + + } + } + + testStr = getClass().getResourceAsStream("/parser-bad.tests"); + testsReader = new BufferedReader(new InputStreamReader(testStr)); + testCaseFile = null; + while ((testCaseFile = testsReader.readLine()) != null) { + + testCaseFile = testCaseFile.trim(); + + if (testCaseFile.length() > 0) + { + if (!testCaseFile.startsWith("/")) + { + testCaseFile = "/"+testCaseFile; + } + URL testCaseUrl = getClass().getResource(testCaseFile); + if (testCaseUrl == null) + { + fail("Could not resolve test case file "+testCaseFile); + } + + boolean valid = true; + try { + SvcLogicParser.load(testCaseUrl.getPath(), store); + } catch (Exception e) { + System.out.println(e.getMessage()); + valid = false; + } + + if (valid) { + fail("Expected compiler error on "+testCaseFile+", but got success"); + } + + + } + } + } + catch (SvcLogicParserException e) + { + fail("Parser error : "+e.getMessage()); + } + catch (Exception e) + { + e.printStackTrace(); + fail("Caught exception processing test cases"); + } + + + } + + + +} diff --git a/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml b/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml new file mode 100644 index 00000000..097078a8 --- /dev/null +++ b/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<service-logic xmlns="http://www.openecomp.org/sdnc/svclogic" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openecomp.org/sdnc/svclogic ./svclogic.xsd" + module="ase" version="1.0.0"> + + + <method rpc="ase-evc-activation" mode="sync"> + <configure adaptor="org.openecomp.sdnc.sli.adaptor.emt.EmtAdaptor" + key="$evc-name" activate="true"> + <parameter name="circuit.name" value="$evc-name" /> + <parameter name="topology" value="$topology" /> + <parameter name="leg1.uniCircuitId" value="$evc-leg[0].evc-access-name" /> + <parameter name="leg2.uniCircuitId" value="$evc-leg[1].evc-access-name" /> + <outcome value="success"> + <return status="success" /> + </outcome> + <outcome value="already-active"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="`Circuit already active`" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Activation failure" /> + </return> + </outcome> + </configure> + </method> + + <method rpc="ase-evc-disconnect-request" mode="sync"> + <configure adaptor="org.openecomp.sdnc.sli.adaptor.emt.EmtAdaptor" + key="$evc-name" activate="false"> + <outcome value="success"> + <return status="success" /> + </outcome> + + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="De-activation failure" /> + </return> + </outcome> + </configure> + </method> + + +</service-logic> diff --git a/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml b/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml new file mode 100644 index 00000000..08084420 --- /dev/null +++ b/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml @@ -0,0 +1,263 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<service-logic xmlns="http://www.openecomp.org/sdnc/svclogic" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openecomp.org/sdnc/svclogic ./svclogic.xsd" + module="ase" version="1.0.0"> + + <!-- Reserve a port. Returns uni-circuit-id of reserved ase-port --> + <method rpc="ase-port-reserve" mode="sync"> + <switch test="$uni-cir-units"> + <outcome value="Mbps"> + <reserve plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value" + pfx="asePort"> + + + <outcome value="success"> + <block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="RESERVED"/> + <parameter name="field3" value="$asePort.uni_circuit_id"/> + </record> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </block> + + </outcome> + + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" value="No ports found that match criteria" /> + </return> + </outcome> + + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" + value="Error encountered trying to reserve port" /> + </return> + </outcome> + + </reserve> + </outcome> + <outcome value="Gbps"> + <reserve plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= 1000 * $uni-cir-value" + pfx="asePort"> + + + <outcome value="success"> + <block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="RESERVED"/> + <parameter name="field3" value="$asePort.uni_circuit_id"/> + </record> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </block> + </outcome> + + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" value="No ports found that match criteria" /> + </return> + </outcome> + <outcome value=""> + <return status="failure"> + <parameter name="error-code" value="1012" /> + <parameter name="error-message" + value="Error encountered trying to reserve port" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" + value="Error encountered trying to reserve port" /> + </return> + </outcome> + </reserve> + </outcome> + </switch> + </method> + + <!-- One step provisioning/activation command. Allocates a local resource, + then configures it on device --> + <method rpc="ase-port-activate-request" mode="sync"> + + <allocate plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-port" key="uni-circuit-id == $uni-circuit-id" pfx="asePort"> + + <outcome value="success"> + <configure adaptor="org.openecomp.sdnc.sli.adaptor.emt.EmtAdaptor" + key="$uni-circuit-id" activate="true"> + <parameter name="circuit.id" value="$uni-circuit-id" /> + <parameter name="subscriber.name" value="$subscriber-name" /> + <parameter name="emt.clli" value="$edge-device-clli" /> + <parameter name="port.tagging" value="$port-tagging" /> + <parameter name="port.mediaSpeed" value="$media-speed" /> + <parameter name="location.state" value="$uni-location-state" /> + <parameter name="location.city" value="$uni-location-city" /> + <parameter name="cosCategory" value="$cos-category" /> + <parameter name="gosProfile" value="$gos-profile" /> + <parameter name="lldp" value="$asePort.resource-lldp" /> + <parameter name="mtu" value="$asePort.resource-mtu" /> + <outcome value="success"> + <block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="ACTIVE"/> + <parameter name="field3" value="$uni-circuit-id"/> + </record> + <return status="success"> + <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" /> + </return> + </block> + + </outcome> + <outcome value="already-active"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Port already active" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Activation failure" /> + </return> + </outcome> + </configure> + </outcome> + + <outcome value="not-found"> + + <return status="failure"> + <parameter name="error-code" value="1220" /> + <parameter name="error-message" value="Circuit not found" /> + </return> + + </outcome> + + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1230" /> + <parameter name="error-message" value="Error occurred trying to find circuit" /> + </return> + </outcome> + </allocate> + </method> + + + + <!-- Change provisioning w/o activation --> + <method rpc="ase-change-port-prov-request" mode="sync"> + <allocate plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-port" key="uni-circuit-id == $uni-circuit-id" pfx="asePort"> + + <outcome value="success"> + <return status="success"> + <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" /> + </return> + </outcome> + + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1220" /> + <parameter name="error-message" value="Circuit not found" /> + </return> + </outcome> + + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1230" /> + <parameter name="error-message" value="Error occurred trying to find circuit" /> + </return> + </outcome> + </allocate> + </method> + + + + + <!-- Release port --> + + <method rpc="ase-release-port-request" mode="sync"> + <exists plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-evc" key="uni-circuit-id == $uni-circuit-id"> + + <outcome value="true"> + <return status="failure"> + <parameter name="error-code" value="1130" /> + <parameter name="error-message" + value="Cannot release port - used in existing EVC" /> + </return> + </outcome> + <outcome value="false"> + <release plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-port" key="uni-circuit-id == $uni-circuit-id"> + <outcome value="success"> + <block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="RELEASED"/> + <parameter name="field3" value="$uni-circuit-id"/> + </record> + <return status="success"/> + </block> + </outcome> + + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1110" /> + <parameter name="error-message" value="No port found for this uni-circuit-id" /> + </return> + </outcome> + + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1130" /> + <parameter name="error-message" + value="Error encountered trying to release port" /> + </return> + </outcome> + </release> + </outcome> + </exists> + </method> + +</service-logic> + diff --git a/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml b/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml new file mode 100644 index 00000000..5a835b7b --- /dev/null +++ b/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<service-logic xmlns="http://www.openecomp.org/sdnc/svclogic" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openecomp.org/sdnc/svclogic ./svclogic.xsd" + module="ase" version="1.0.1"> + + <!-- Updated release port logic : deactivate the released port on the EMT --> + <method rpc="ase-release-port-request" mode="sync"> + <exists plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-evc" key="uni-circuit-id == $uni-circuit-id"> + + <outcome value="true"> + <return status="failure"> + <parameter name="error-code" value="1130" /> + <parameter name="error-message" + value="Cannot release port - used in existing EVC" /> + </return> + </outcome> + <outcome value="false"> + <release plugin="org.openecomp.sdnc.sli.resource.sample.SampleResource" + resource="ase-port" key="uni-circuit-id == $uni-circuit-id"> + <outcome value="success"> + <configure adaptor="org.openecomp.sdnc.sli.adaptor.emt.EmtAdaptor" + key="$uni-circuit-id" activate="false"> + + <outcome value="success"> + <block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__" /> + <parameter name="field2" value="RELEASED" /> + <parameter name="field3" value="$uni-circuit-id" /> + </record> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </block> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1130" /> + <parameter name="error-message" + value="Error encountered trying to de-activate port" /> + </return> + </outcome> + </configure> + </outcome> + + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1110" /> + <parameter name="error-message" value="No port found for this uni-circuit-id" /> + </return> + </outcome> + + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1130" /> + <parameter name="error-message" + value="Error encountered trying to release port" /> + </return> + </outcome> + </release> + </outcome> + </exists> + </method> + +</service-logic> + diff --git a/sli/common/src/test/resources/bad_neutron_logic_v11.xml b/sli/common/src/test/resources/bad_neutron_logic_v11.xml new file mode 100644 index 00000000..4e1e8d9b --- /dev/null +++ b/sli/common/src/test/resources/bad_neutron_logic_v11.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<service-logic xmlns="http://www.openecomp.org/sdnc/svclogic" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openecomp.org/sdnc/svclogic ./svclogic.xsd" + module="neutron" version="1.0.0"> + + <method rpc="canCreateNetwork" mode="sync"> + <switch test="true"> + <return status="success"> + <parameter name="error-code" value="200" /> + </return> + </switch> + </method> + + <method rpc="networkCreated" mode="sync"> + <switch test="`(length($network.segment[0].provider-physical-network) >= 5) and (substr($network.segment[0].provider-physical-network,0,5) == 'dvspg')`"> + <outcome value="true"> + <block> + <set> + <parameter name="vlanlist" value="`$network.segment[0].provider-segmentation-id`"/> + </set> + <for index="i" start="1" end="`$network.num-segments`"> + <set> + <parameter name="vlanlist" value="`$vlanlist+','+$network.segment[$i].provider-segmentation-id`"/> + </set> + </for> + + <switch test="true"> + <return status="success"/> + </switch> + </block> + </outcome> + <outcome value="Other"> + <return status="success"> + <parameter name="error-code" value="200"/> + </return> + </outcome> + </switch> + </method> + +</service-logic> diff --git a/sli/common/src/test/resources/expression.tests b/sli/common/src/test/resources/expression.tests new file mode 100755 index 00000000..c352e9b0 --- /dev/null +++ b/sli/common/src/test/resources/expression.tests @@ -0,0 +1,19 @@ +$uni-circuit-id +$asePort +length($uni-circuit-id) > 0 +$asePort.uni-circuit-id +$uni-cir-units * 1000 * 100 / 100 +$uni-cir-units / 1000 +$uni-cir-units - 100 +$uni-cir-units + 100 +(value * 3 - $arg1 > 0) and (length($uni-circuit-id) == 0) +'pg-'+$network.name +$network.segment[0].provider-physical-network +length($network_segment[0].provider-physical-network) >= 5 +substr($network_segment[0].provider-physical-network,0,5) == 'dvspg' +length($network_segment[0].provider-physical-network) >= 5 and substr($network_segment[0].provider-physical-network,0,5) == 'dvspg' +(length($network_segment[0].provider-physical-network) >= 5) and (substr($network_segment[0].provider-physical-network,0,5) == 'dvspg') +4-2-2 +1+1 +1 +1+2*3-4 diff --git a/sli/common/src/test/resources/mergetest.xml b/sli/common/src/test/resources/mergetest.xml new file mode 100644 index 00000000..12e083c7 --- /dev/null +++ b/sli/common/src/test/resources/mergetest.xml @@ -0,0 +1,54 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<multicast-parameters xmlns="org.openecomp.sdnc:test"> + <vpn-v4-multicast-enabled>Y</vpn-v4-multicast-enabled> + <v4-multicast> + <v4-pim-ssm-default-range>Y</v4-pim-ssm-default-range> + <v4-data-mdt>11.11.11.11</v4-data-mdt> + <v4-data-mdt-wildcard-mask>2.2.2.2</v4-data-mdt-wildcard-mask> + <max-routes-limit>100</max-routes-limit> + <v4-default-mdt>1.1.1.1</v4-default-mdt> + <v4-pim-sm-static-override>N</v4-pim-sm-static-override> + <v4-pim-ssm-groups> + <v4-pim-ssm-group-address>4.4.4.4</v4-pim-ssm-group-address> + </v4-pim-ssm-groups> + <v4-pim-ssm-groups> + <v4-pim-ssm-group-address>3.3.3.3</v4-pim-ssm-group-address> + </v4-pim-ssm-groups> + <v4-static-rp-triplet> + <rp-address>8.8.8.8</rp-address> + <c-groups> + <c-group-address-prefix>10.10.10.10</c-group-address-prefix> + </c-groups> + <c-groups> + <c-group-address-prefix>9.9.9.9</c-group-address-prefix> + </c-groups> + </v4-static-rp-triplet> + <v4-static-rp-triplet> + <rp-address>7.7.7.7</rp-address> + <c-groups> + <c-group-address-prefix>6.6.6.6</c-group-address-prefix> + </c-groups> + <c-groups> + <c-group-address-prefix>5.5.5.5</c-group-address-prefix> + </c-groups> + </v4-static-rp-triplet> + </v4-multicast> +</multicast-parameters> diff --git a/sli/common/src/test/resources/neutron_logic_v10.xml b/sli/common/src/test/resources/neutron_logic_v10.xml new file mode 100644 index 00000000..9cd33127 --- /dev/null +++ b/sli/common/src/test/resources/neutron_logic_v10.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<service-logic xmlns="http://www.openecomp.org/sdnc/svclogic" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openecomp.org/sdnc/svclogic ./svclogic.xsd" + module="neutron" version="1.0.0"> + + <method rpc="canCreateNetwork" mode="sync"> + <return status="success"> + <parameter name="error-code" value="200" /> + </return> + </method> + + <method rpc="networkCreated" mode="sync"> + <switch test="`(length($network.segment[0].provider-physical-network) >= 5) and (substr($network.segment[0].provider-physical-network,0,5) == 'dvspg')`"> + <outcome value="true"> + <block> + <set> + <parameter name="vlanlist" value="`$network.segment[0].provider-segmentation-id`"/> + </set> + <for index="i" start="1" end="`$network.num-segments`"> + <set> + <parameter name="vlanlist" value="`$vlanlist+','+$network.segment[$i].provider-segmentation-id`"/> + </set> + </for> + + </block> + </outcome> + <outcome value="Other"> + <return status="success"> + <parameter name="error-code" value="200"/> + </return> + </outcome> + </switch> + </method> + +</service-logic> diff --git a/sli/common/src/test/resources/nonsense.xml b/sli/common/src/test/resources/nonsense.xml new file mode 100644 index 00000000..61220825 --- /dev/null +++ b/sli/common/src/test/resources/nonsense.xml @@ -0,0 +1,24 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<non> +<sense>Hello world</sense> +</non> diff --git a/sli/common/src/test/resources/parser-bad.tests b/sli/common/src/test/resources/parser-bad.tests new file mode 100755 index 00000000..82913afc --- /dev/null +++ b/sli/common/src/test/resources/parser-bad.tests @@ -0,0 +1,3 @@ +bad_neutron_logic_v11.xml +EvcActivateSvcLogic_v100.xml +nonsense.xml
\ No newline at end of file diff --git a/sli/common/src/test/resources/parser-good.tests b/sli/common/src/test/resources/parser-good.tests new file mode 100755 index 00000000..06543126 --- /dev/null +++ b/sli/common/src/test/resources/parser-good.tests @@ -0,0 +1,2 @@ +ReleasePortSvcLogic_v101.xml +neutron_logic_v10.xml diff --git a/sli/common/src/test/resources/simplelogger.properties b/sli/common/src/test/resources/simplelogger.properties new file mode 100644 index 00000000..6f70984c --- /dev/null +++ b/sli/common/src/test/resources/simplelogger.properties @@ -0,0 +1,24 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.slf4j.simpleLogger.defaultLogLevel=info +org.slf4j.simplelogger.log.org.openecomp.sdnc.sli.SvcLogicContext=debug +org.slf4j.simplelogger.log.SvcLogicContext=debug diff --git a/sli/common/src/test/resources/svclogic.properties b/sli/common/src/test/resources/svclogic.properties new file mode 100644 index 00000000..fa33146e --- /dev/null +++ b/sli/common/src/test/resources/svclogic.properties @@ -0,0 +1,26 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.openecomp.sdnc.sli.dbtype = jdbc +org.openecomp.sdnc.sli.jdbc.url = jdbc:mysql://localhost:3306/sdnctl +org.openecomp.sdnc.sli.jdbc.database = sdnctl +org.openecomp.sdnc.sli.jdbc.user = sdnctl +org.openecomp.sdnc.sli.jdbc.password = gamma diff --git a/sli/common/src/test/resources/svclogic.sh b/sli/common/src/test/resources/svclogic.sh new file mode 100644 index 00000000..09f0637d --- /dev/null +++ b/sli/common/src/test/resources/svclogic.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +MYSQL_JDBC_DRIVER=${MYSQL_JDBC_DRIVER:-/home/ubuntu/mysql-connector-java-5.1.38.1.jar} +SLI_COMMON_TARGETDIR=${SLI_COMMON_TARGETDIR:-/home/ubuntu/opendaylight/plugins} +#SLI_COMMON_TARGETDIR=${SLI_COMMON_TARGETDIR:-/home/ubuntu/git/sdnctl/sli/common/target} +SLI_VERSION=${SLI_VERSION:-1.1.0-SNAPSHOT} +SLI_COMMON_JAR=${SLI_COMMON_JAR:=${SLI_COMMON_TARGETDIR}/sli-common-${SLI_VERSION}.jar} + +echo SLI_COMMON_JAR is $SLI_COMMON_JAR + +java -cp ${CLASSPATH}:${MYSQL_JDBC_DRIVER}:${SLI_COMMON_JAR} org.openecomp.sdnc.sli.SvcLogicParser $* diff --git a/sli/common/src/test/resources/svclogic.xsd b/sli/common/src/test/resources/svclogic.xsd new file mode 100755 index 00000000..07430891 --- /dev/null +++ b/sli/common/src/test/resources/svclogic.xsd @@ -0,0 +1,323 @@ +<?xml version = "1.0" encoding = "UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.openecomp.org/sdnc/svclogic" xmlns="http://www.openecomp.org/sdnc/svclogic">
+
+ <xsd:simpleType name="modeType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="sync" />
+ <xsd:enumeration value="async" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:group name="node">
+ <xsd:choice>
+ <xsd:element ref="block" />
+ <xsd:element ref="is-available" />
+ <xsd:element ref="exists" />
+ <xsd:element ref="reserve" />
+ <xsd:element ref="release" />
+ <xsd:element ref="allocate" />
+ <xsd:element ref="get-resource" />
+ <xsd:element ref="configure" />
+ <xsd:element ref="return" />
+ <xsd:element ref="switch" />
+ <xsd:element ref="record" />
+ <xsd:element ref="save" />
+ <xsd:element ref="for" />
+ <xsd:element ref="set" />
+ <xsd:element ref="execute" />
+ <xsd:element ref="delete" />
+ <xsd:element ref="update" />
+ <xsd:element ref="call" />
+ <xsd:element ref="notify" />
+ <xsd:element ref="break" />
+ </xsd:choice>
+ </xsd:group>
+
+ <xsd:element name="service-logic">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="method" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="module" use="required" type="xsd:string" />
+ <xsd:attribute name="version" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="method">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="rpc" use="required" type="xsd:string" />
+ <xsd:attribute name="mode" use="optional" type="modeType" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="block">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="atomic" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="is-available">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="exists">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="outcome">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="ref" use="optional" type="xsd:string" />
+ <xsd:attribute name="value" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="reserve">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="select" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="release">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="record">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="allocate">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ <xsd:attribute name="pfx" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="get-resource">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="order-by" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="configure">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="adaptor" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ <xsd:attribute name="activate" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="parameter">
+ <xsd:complexType>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="value" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="return">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="status" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="switch">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="test" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="save">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="force" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="delete">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ <!-- local-only is retired and does not do anything -->
+ <xsd:attribute name="local-only" use="optional" type="xsd:string" />
+ <!-- pfx is retired and does not do anything -->
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="for">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="atomic" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="index" use="required" type="xsd:string" />
+ <xsd:attribute name="start" use="required" type="xsd:string" />
+ <xsd:attribute name="end" use="required" type="xsd:string" />
+ <xsd:attribute name="silentFailure" use="optional" type="xsd:boolean" default="false" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="set">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="only-if-unset" use="optional"
+ type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="execute">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="method" use="required" type="xsd:string" />
+ <xsd:attribute name="emitsOutcome" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="update">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="force" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="call">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="module" use="optional" type="xsd:string" />
+ <xsd:attribute name="rpc" use="required" type="xsd:string" />
+ <xsd:attribute name="version" use="optional" type="xsd:string" />
+ <xsd:attribute name="mode" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="notify">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="optional" type="xsd:string" />
+ <xsd:attribute name="resource" use="optional" type="xsd:string" />
+ <xsd:attribute name="action" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="break">
+ <xsd:complexType />
+ </xsd:element>
+
+</xsd:schema>
diff --git a/sli/features/pom.xml b/sli/features/pom.xml new file mode 100755 index 00000000..2556a579 --- /dev/null +++ b/sli/features/pom.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sli</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sli-features</artifactId> + <name>SLI - Features</name> + + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + </dependency> + + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-recording</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <version>${odl.mdsal.features.version}</version> + <classifier>features</classifier> + <type>xml</type> + + <scope>runtime</scope> + </dependency> + + + <!-- dependency for opendaylight-karaf-empty for use by testing + <dependency> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>opendaylight-karaf-empty</artifactId> + <version>${odl.karaf.empty.version}</version> + <type>zip</type> + </dependency> + --> + + + <dependency> + <!-- Required for launching the feature tests --> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>features-test</artifactId> + <version>${odl.commons.opendaylight.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>features-yangtools</artifactId> + <version>${odl.yangtools.version}</version> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + + <!-- Comment out feature test, since it fails in Jenkins due to env issues + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.16</version> + <configuration> + <systemPropertyVariables> + <karaf.distro.groupId>org.opendaylight.odlparent</karaf.distro.groupId> + <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> + <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> + </systemPropertyVariables> + <dependenciesToScan> + <dependency>org.opendaylight.yangtools:features-test</dependency> + </dependenciesToScan> + </configuration> + </plugin> + --> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/sli/features/src/main/resources/features.xml b/sli/features/src/main/resources/features.xml new file mode 100644 index 00000000..e1ce255a --- /dev/null +++ b/sli/features/src/main/resources/features.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<features name="sdnc-sli-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features</repository> + + + <feature name='sdnc-sli' description="sdnc-sli" version='${project.version}'> + + <feature version="${odl.mdsal.version}">odl-mdsal-broker</feature> + <bundle>mvn:org.openecomp.sdnc.core/sli-common/${project.version}</bundle> + <bundle>mvn:org.openecomp.sdnc.core/sli-provider/${project.version}</bundle> + <bundle>mvn:org.openecomp.sdnc.core/sli-recording/${project.version}</bundle> + <feature>sdnc-dblib</feature> + <bundle>mvn:mysql/mysql-connector-java/${mysql.connector.version}</bundle> + </feature> + +</features> diff --git a/sli/installer/pom.xml b/sli/installer/pom.xml new file mode 100755 index 00000000..d43769e2 --- /dev/null +++ b/sli/installer/pom.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sli</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sli-installer</artifactId> + <name>SLI - Karaf Installer</name> + <packaging>pom</packaging> + + <properties> + <application.name>sdnc-sli</application.name> + <features.boot>sdnc-sli</features.boot> + <features.repositories>mvn:org.openecomp.sdnc.core/sli-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencies> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-features</artifactId> + <version>${project.version}</version> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-recording</artifactId> + <version>${project.version}</version> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${application.name}-${project.version}-installer</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeGroupIds>org.openecomp.sdnc</includeGroupIds> + <excludeArtifactIds>dblib-provider</excludeArtifactIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals><!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/sli/installer/src/assembly/assemble_installer_zip.xml b/sli/installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 00000000..85e2e1e8 --- /dev/null +++ b/sli/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,59 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/sli/installer/src/assembly/assemble_mvnrepo_zip.xml b/sli/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 00000000..38e6d47b --- /dev/null +++ b/sli/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,49 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/sli/installer/src/main/resources/scripts/install-feature.sh b/sli/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 00000000..93236c5b --- /dev/null +++ b/sli/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/sli/pom.xml b/sli/pom.xml new file mode 100755 index 00000000..53a8b629 --- /dev/null +++ b/sli/pom.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sdnc-core</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <packaging>pom</packaging> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli</artifactId> + + <dependencyManagement> + + <dependencies> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-recording</artifactId> + <version>${project.version}</version> + </dependency> + + </dependencies> + + </dependencyManagement> + + + <name>Service Logic Interpreter</name> + <description>The Service Logic Interpreter (SLI) allows service planners to design the flow of logic within the SDN controller in an XML format, without a need for custom Java code. </description> + + <modules> + <module>common</module> + <module>provider</module> + <module>recording</module> + <module>features</module> + <module>installer</module> + </modules> + <organization> + <name>openECOMP</name> + </organization> + <version>0.0.1-SNAPSHOT</version> + + +</project> diff --git a/sli/provider/pom.xml b/sli/provider/pom.xml new file mode 100755 index 00000000..f73d0071 --- /dev/null +++ b/sli/provider/pom.xml @@ -0,0 +1,96 @@ +<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sli-provider</artifactId> + <packaging>bundle</packaging> + <name>SLI - Provider</name> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>${equinox.osgi.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>${commons.lang.version}</version> + <scope>compile</scope> + </dependency> + + + <!-- + <dependency> + <groupId>org.antlr</groupId> + <artifactId>antlr4</artifactId> + <version>${antlr.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + --> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>${bundle.plugin.version}</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator>org.openecomp.sdnc.sli.provider.SvcLogicActivator</Bundle-Activator> + <Export-Package>org.openecomp.sdnc.sli.provider;version=${project.version}</Export-Package> + + <DynamicImport-Package>*</DynamicImport-Package> + <!-- + <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.vim25.*,org.apache.xerces.*,com.mysql.jdbc.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*</Import-Package> + --> + + <Import-Package>org.openecomp.sdnc.sli;version="${project.version}",*</Import-Package> + <!-- + <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|jcl-over-slf4j|xml-apis|mysql-connector-java</Embed-Dependency> + --> + <Embed-Dependency>*;scope=compile;artifactId=commons-lang|commons-lang3</Embed-Dependency> + + <Embed-Transitive>true</Embed-Transitive> + </instructions> + + + </configuration> + + </plugin> + </plugins> + </build> + <description>SLI Provider is the OSGi bundle that exposes the service logic interpreter as a service.</description> +</project> diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/BlockNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/BlockNodeExecutor.java new file mode 100644 index 00000000..f83154d9 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/BlockNodeExecutor.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BlockNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(BlockNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, SvcLogicContext ctx) + throws SvcLogicException { + + SvcLogicExpression atomicExpr = node.getAttribute("atomic"); + String atomicStr = SvcLogicExpressionResolver.evaluate(atomicExpr, node, ctx); + boolean isAtomic = "true".equalsIgnoreCase(atomicStr); + + // Initialize status to success so that at least one outcome will execute + ctx.setStatus("success"); + + int numOutcomes = node.getNumOutcomes(); + + for (int i = 0; i < numOutcomes; i++) { + if ("failure".equals(ctx.getStatus()) && isAtomic) { + LOG.info("Block - stopped executing nodes due to failure status"); + return(null); + } + + SvcLogicNode nextNode = node.getOutcomeValue("" + (i + 1)); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Block - executing outcome " + (i + 1)); + } + while (nextNode != null) + { + nextNode = svc.executeNode(nextNode, ctx); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Block - done: no outcome " + (i + 1)); + } + } + } + + return (null); + } + + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/BreakNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/BreakNodeExecutor.java new file mode 100644 index 00000000..0f8719c8 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/BreakNodeExecutor.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.BreakNodeException; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BreakNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory.getLogger(BreakNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException { + String message = "BreakNodeExecutor encountered break with nodeId " + node.getNodeId(); + LOG.debug(message); + throw new BreakNodeException(message); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/CallNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/CallNodeExecutor.java new file mode 100644 index 00000000..7b79c19f --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/CallNodeExecutor.java @@ -0,0 +1,165 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicGraph; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CallNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(CallNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, SvcLogicContext ctx) + throws SvcLogicException { + + String outValue = "not-found"; + + SvcLogicGraph myGraph = node.getGraph(); + + if (myGraph == null) + { + LOG.debug("execute: getGraph returned null"); + } + else + { + LOG.debug("execute: got SvcLogicGraph"); + } + + SvcLogicExpression moduleExpr = null; + + String module = null; + + moduleExpr = node.getAttribute("module"); + if (moduleExpr != null) + { + module = SvcLogicExpressionResolver.evaluate(moduleExpr, node, ctx); + } + + if ((module == null) || (module.length() == 0)) + { + if (myGraph != null) + { + module = myGraph.getModule(); + LOG.debug("myGraph.getModule() returned "+module); + } + } + + SvcLogicExpression rpcExpr = null; + String rpc = null; + rpcExpr = node.getAttribute("rpc"); + if (rpcExpr != null) + { + rpc = SvcLogicExpressionResolver.evaluate(rpcExpr, node, ctx); + } + + if ((rpc == null) || (rpc.length() == 0)) + { + if (myGraph != null) + { + rpc = myGraph.getRpc(); + LOG.debug("myGraph.getRpc() returned "+rpc); + } + } + + String mode = null; + + moduleExpr = node.getAttribute("mode"); + if (moduleExpr != null) + { + mode = SvcLogicExpressionResolver.evaluate(moduleExpr, node, ctx); + } + + if ((mode == null) || (mode.length() == 0)) + { + if (myGraph != null) + { + mode = myGraph.getMode(); + + LOG.debug("myGraph.getMode() returned "+mode); + } + } + + String version = null; + + moduleExpr = node.getAttribute("version"); + if (moduleExpr != null) + { + version = SvcLogicExpressionResolver.evaluate(moduleExpr, node, ctx); + } + + String parentGraph = ctx.getAttribute("currentGraph"); + ctx.setAttribute("parentGraph", parentGraph); + + SvcLogicStore store = getStore(); + + if (store != null) { + SvcLogicGraph calledGraph = store.fetch(module, rpc, version, mode); + LOG.debug("Parent " + parentGraph + " is calling child " + calledGraph.toString()); + ctx.setAttribute("currentGraph", calledGraph.toString()); + if (calledGraph != null) { + svc.execute(calledGraph, ctx); + + outValue = ctx.getStatus(); + } else { + LOG.error("Could not find service logic for [" + module + "," + rpc + "," + version + "," + mode + "]"); + } + } + else + { + LOG.debug("Could not get SvcLogicStore reference"); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + ctx.setAttribute("currentGraph", parentGraph); + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no " + outValue + " or Other branch found"); + } + } + ctx.setAttribute("currentGraph", parentGraph); + ctx.setAttribute("parentGraph", null); + + return (nextNode); + + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ConfigureNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ConfigureNodeExecutor.java new file mode 100644 index 00000000..a3f2874f --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ConfigureNodeExecutor.java @@ -0,0 +1,248 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicAdaptor; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConfigureNodeExecutor extends SvcLogicNodeExecutor { + private static final Logger LOG = LoggerFactory + .getLogger(ConfigureNodeExecutor.class); + + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String adaptorName = SvcLogicExpressionResolver.evaluate( + node.getAttribute("adaptor"), node, ctx); + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("configure node encountered - looking for adaptor " + + adaptorName); + } + + SvcLogicAdaptor adaptor = getAdaptor(adaptorName); + + if (adaptor != null) { + String activate = SvcLogicExpressionResolver.evaluate( + node.getAttribute("activate"), node, ctx); + String key = SvcLogicExpressionResolver.evaluate( + node.getAttribute("key"), node, ctx); + + Map<String, String> parmMap = new HashMap<String, String>(); + + Set<Map.Entry<String, SvcLogicExpression>> parmSet = node + .getParameterSet(); + boolean hasParms = false; + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parmSet + .iterator(); iter.hasNext();) { + hasParms = true; + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + SvcLogicExpression curExpr = curEnt.getValue(); + String curExprValue = SvcLogicExpressionResolver.evaluate(curExpr, node, ctx); + + LOG.debug("Parameter "+curName+" = "+curExpr.asParsedExpr()+" resolves to "+curExprValue); + + parmMap.put(curName,curExprValue); + } + + if (hasParms) { + SvcLogicAdaptor.ConfigStatus confStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + + try { + confStatus = adaptor.configure(key, parmMap, ctx); + } catch (Exception e) { + LOG.warn("Caught exception from "+adaptorName+".configure", e); + confStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + } + + switch (confStatus) { + case SUCCESS: + outValue = "success"; + if ((activate != null) && (activate.length() > 0)) { + if ("true".equalsIgnoreCase(activate)) { + SvcLogicAdaptor.ConfigStatus activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + + try { + activateStatus = adaptor.activate(key, ctx); + } catch (Exception e) { + + LOG.warn("Caught exception from "+adaptorName+".activate", e); + activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + } + switch (activateStatus) { + case SUCCESS: + break; + case ALREADY_ACTIVE: + outValue = "already-active"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case NOT_READY: + outValue = "not-ready"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } else if ("false".equalsIgnoreCase(activate)) { + SvcLogicAdaptor.ConfigStatus deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + + try { + deactivateStatus = adaptor.deactivate(key, ctx); + } catch (Exception e) { + + LOG.warn("Caught exception from "+adaptorName+".deactivate", e); + deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + } + switch (deactivateStatus) { + case SUCCESS: + break; + case ALREADY_ACTIVE: + outValue = "already-active"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case NOT_READY: + outValue = "not-ready"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } + } + break; + case ALREADY_ACTIVE: + outValue = "already-active"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case NOT_READY: + outValue = "not-ready"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } else { + if ((activate != null) && (activate.length() > 0)) { + if ("true".equalsIgnoreCase(activate)) { + SvcLogicAdaptor.ConfigStatus activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + try { + activateStatus = adaptor.activate(key, ctx); + } catch (Exception e) { + LOG.warn("Caught exception from "+adaptorName+".activate", e); + activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + } + switch (activateStatus) { + case SUCCESS: + outValue = "success"; + break; + case ALREADY_ACTIVE: + outValue = "already-active"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case NOT_READY: + outValue = "not-ready"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } else if ("false".equalsIgnoreCase(activate)) { + SvcLogicAdaptor.ConfigStatus deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + + try { + deactivateStatus = adaptor.deactivate(key, ctx); + } catch (Exception e) { + LOG.warn("Caught exception from "+adaptorName+".deactivate", e); + deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE; + } + switch (deactivateStatus) { + case SUCCESS: + outValue = "success"; + break; + case ALREADY_ACTIVE: + outValue = "already-active"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case NOT_READY: + outValue = "not-ready"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } + } else { + LOG.warn("Nothing to configure - no parameters passed, and activate attribute is not set"); + outValue = "success"; + } + } + } else { + if (LOG.isWarnEnabled()) { + LOG.warn("Adaptor for " + adaptorName + " not found"); + } + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no " + outValue + " or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/DeleteNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/DeleteNodeExecutor.java new file mode 100644 index 00000000..081cbcfa --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/DeleteNodeExecutor.java @@ -0,0 +1,101 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeleteNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(DeleteNodeExecutor.class); + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("delete node encountered - looking for resource class " + + plugin); + } + + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + if (resourcePlugin != null) { + + try { + + switch (resourcePlugin.delete(resourceType, key, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ExecuteNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ExecuteNodeExecutor.java new file mode 100644 index 00000000..7ae4d0db --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ExecuteNodeExecutor.java @@ -0,0 +1,161 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExecuteNodeExecutor extends SvcLogicNodeExecutor { + private static final Logger LOG = LoggerFactory + .getLogger(ExecuteNodeExecutor.class); + + private static final String pluginErrorMessage = "Could not execute plugin. SvcLogic status will be set to failure."; + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String pluginName = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("execute node encountered - looking for plugin " + + pluginName); + } + + SvcLogicJavaPlugin plugin = getSvcLogicJavaPlugin(pluginName); + + if (plugin == null) { + outValue = "not-found"; + } else { + + String methodName = evaluate(node.getAttribute("method"), node, ctx); + + Class pluginClass = plugin.getClass(); + + Method pluginMethod = null; + + try { + pluginMethod = pluginClass.getMethod(methodName, Map.class, SvcLogicContext.class); + } catch (NoSuchMethodException e) { + LOG.error(pluginErrorMessage, e); + } + + if (pluginMethod == null) { + outValue = "unsupported-method"; + } else { + try { + + Map<String, String> parmMap = new HashMap<String, String>(); + + Set<Map.Entry<String, SvcLogicExpression>> parmSet = node + .getParameterSet(); + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parmSet + .iterator(); iter.hasNext();) { + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + SvcLogicExpression curExpr = curEnt.getValue(); + String curExprValue = SvcLogicExpressionResolver.evaluate(curExpr, node, ctx); + + LOG.debug("Parameter "+curName+" = "+curExpr.asParsedExpr()+" resolves to "+curExprValue); + + parmMap.put(curName,curExprValue); + } + + Object o = pluginMethod.invoke(plugin, parmMap, ctx); + String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx); + + outValue = mapOutcome(o, emitsOutcome); + + } catch (InvocationTargetException e) { + if(e.getCause() != null){ + LOG.error(pluginErrorMessage, e.getCause()); + }else{ + LOG.error(pluginErrorMessage, e); + } + outValue = "failure"; + ctx.setStatus("failure"); + } catch (IllegalAccessException e) { + LOG.error(pluginErrorMessage, e); + outValue = "failure"; + ctx.setStatus("failure"); + } catch (IllegalArgumentException e) { + LOG.error(pluginErrorMessage, e); + outValue = "failure"; + ctx.setStatus("failure"); + } + } + + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no " + outValue + " or Other branch found"); + } + } + return (nextNode); + } + + protected String evaluate(SvcLogicExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException { + return SvcLogicExpressionResolver.evaluate(node.getAttribute("method"), node, ctx); + } + + public String mapOutcome(Object o, String emitsOutcome) { + if (emitsOutcome != null) { + Boolean nodeEmitsOutcome = Boolean.valueOf(emitsOutcome); + if (nodeEmitsOutcome) { + return (String) o; + } else { + return "success"; + } + + } else { + return "success"; + } + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ExistsNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ExistsNodeExecutor.java new file mode 100644 index 00000000..688a86e5 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ExistsNodeExecutor.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExistsNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(ExistsNodeExecutor.class); + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + String pfx = SvcLogicExpressionResolver.evaluate( + node.getAttribute("pfx"), node, ctx); + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("exists node encountered - looking for resource class " + + plugin); + } + + + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + + if (resourcePlugin != null) { + + try { + + switch (resourcePlugin.exists(resourceType, key, pfx, ctx)) { + case SUCCESS: + outValue = "true"; + break; + case NOT_FOUND: + outValue = "false"; + break; + case FAILURE: + default: + outValue = "false"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ForNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ForNodeExecutor.java new file mode 100644 index 00000000..e9fdc55e --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ForNodeExecutor.java @@ -0,0 +1,109 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.BreakNodeException; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ForNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(ForNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + SvcLogicExpression atomicExpr = node.getAttribute("atomic"); + String atomicStr = SvcLogicExpressionResolver.evaluate(atomicExpr, node, ctx); + boolean isAtomic = !("false".equalsIgnoreCase(atomicStr)); + + int numOutcomes = node.getNumOutcomes(); + String idxVar = SvcLogicExpressionResolver.evaluate( + node.getAttribute("index"), node, ctx); + String startVal = SvcLogicExpressionResolver.evaluate( + node.getAttribute("start"), node, ctx); + String endVal = SvcLogicExpressionResolver.evaluate( + node.getAttribute("end"), node, ctx); + + LOG.debug("Executing "+ (isAtomic ? "atomic" : "non-atomic") + " for loop - for (int " + idxVar + " = " + startVal + + "; " + idxVar + " < " + endVal + "; " + idxVar + "++)"); + + int startIdx = 0; + int endIdx = 0; + + try { + startIdx = Integer.parseInt(startVal); + endIdx = Integer.parseInt(endVal); + } catch (NumberFormatException e) { + SvcLogicExpression silentFailureExpr = node.getAttribute("silentFailure"); + String silentFailure = SvcLogicExpressionResolver.evaluate(silentFailureExpr, node, ctx); + boolean isSilentFailure = Boolean.parseBoolean(silentFailure); + String message = "Invalid index values [" + startVal + "," + endVal + "]"; + if(!isSilentFailure){ + throw new SvcLogicException(message); + }else{ + LOG.debug(message + ". Not exiting because silentFailure was set to true."); + return(null); + } + } + + try { + for (int ctr = startIdx; ctr < endIdx; ctr++) { + + ctx.setAttribute(idxVar, "" + ctr); + + for (int i = 0; i < numOutcomes; i++) { + + if ("failure".equals(ctx.getStatus()) && isAtomic) { + LOG.info("For - stopped executing nodes due to failure status"); + return(null); + } + + SvcLogicNode nextNode = node.getOutcomeValue("" + (i + 1)); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("For - executing outcome " + (i + 1)); + } + SvcLogicNode innerNextNode = nextNode; + while (innerNextNode != null) { + innerNextNode = svc.executeNode(innerNextNode, ctx); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("For - done: no outcome " + (i + 1)); + } + } + } + } + } catch (BreakNodeException br) { + LOG.debug("ForNodeExecutor caught break"); + } + return (null); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/GetResourceNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/GetResourceNodeExecutor.java new file mode 100644 index 00000000..d431a18a --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/GetResourceNodeExecutor.java @@ -0,0 +1,134 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GetResourceNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(GetResourceNodeExecutor.class); + + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + String pfx = SvcLogicExpressionResolver.evaluate( + node.getAttribute("pfx"), node, ctx); + + String localOnlyStr = SvcLogicExpressionResolver.evaluate( + node.getAttribute("local-only"), node, ctx); + + // Note: for get-resource, only refresh from A&AI if the DG explicitly set + // local-only to false. Otherwise, just read from local database. + boolean localOnly = true; + + if ("false".equalsIgnoreCase(localOnlyStr)) { + localOnly = false; + } + + SvcLogicExpression selectExpr = node.getAttribute("select"); + String select = null; + + if (selectExpr != null) { + select = SvcLogicExpressionResolver.evaluateAsKey(selectExpr, node, + ctx); + } + + SvcLogicExpression orderByExpr = node.getAttribute("order-by"); + String orderBy = null; + + if (orderByExpr != null) { + orderBy = SvcLogicExpressionResolver.evaluateAsKey(orderByExpr, node, + ctx); + } + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug(node.getNodeType() + + " node encountered - looking for resource class " + + plugin); + } + + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + + if (resourcePlugin != null) { + + try { + switch (resourcePlugin.query(resourceType, localOnly, select, key, + pfx, orderBy, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/IsAvailableNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/IsAvailableNodeExecutor.java new file mode 100644 index 00000000..0df73682 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/IsAvailableNodeExecutor.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IsAvailableNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(IsAvailableNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + String pfx = SvcLogicExpressionResolver.evaluate( + node.getAttribute("pfx"), node, ctx); + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("is-available node encountered - looking for resource class " + + plugin); + } + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + + + if (resourcePlugin != null) { + try { + switch (resourcePlugin.isAvailable(resourceType, key, pfx, ctx)) { + case SUCCESS: + outValue = "true"; + break; + case NOT_FOUND: + outValue = "false"; + break; + case FAILURE: + default: + outValue = "false"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/MdsalHelper.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/MdsalHelper.java new file mode 100644 index 00000000..4c5ee068 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/MdsalHelper.java @@ -0,0 +1,1186 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MdsalHelper { + + private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class); + private static Properties yangMappingProperties = new Properties(); + + @Deprecated + public static void setProperties(Properties input) { + setYangMappingProperties(input); + } + + public static void setYangMappingProperties(Properties properties) { + for (Object propNameObj : properties.keySet()) { + String propName = (String) propNameObj; + MdsalHelper.yangMappingProperties.setProperty(propName, properties.getProperty(propName)); + } + } + + public static void loadProperties(String propertiesFile) { + File file = new File(propertiesFile); + Properties properties = new Properties(); + InputStream input = null; + if (file.isFile() && file.canRead()) { + try { + input = new FileInputStream(file); + properties.load(input); + MdsalHelper.setYangMappingProperties(properties); + LOG.info("Loaded properties from " + propertiesFile); + } catch (Exception e) { + LOG.error("Failed to load properties " + propertiesFile + "\n", e); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + LOG.error("Failed to close properties file " + propertiesFile + "\n", e); + } + } + } + }else{ + LOG.error("Failed to load the properties file " + propertiesFile + "\n"); + LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n"); + } + } + + public static Properties toProperties(Properties props, Object fromObj) { + Class fromClass = null; + + if (fromObj != null) { + fromClass = fromObj.getClass(); + } + return (toProperties(props, "", fromObj, fromClass)); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj) { + Class fromClass = null; + + if (fromObj != null) { + fromClass = fromObj.getClass(); + } + + return (toProperties(props, pfx, fromObj, fromClass)); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) { + + if (fromObj == null) { + return (props); + } + + String simpleName = fromClass.getSimpleName(); + + LOG.trace("Extracting properties from " + fromClass.getName() + " class"); + if (fromObj instanceof List) { + + // Class is a List. List should contain yang-generated classes. + LOG.trace(fromClass.getName() + " is a List"); + + List fromList = (List) fromObj; + + for (int i = 0; i < fromList.size(); i++) { + toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass); + } + props.setProperty(pfx + "_length", "" + fromList.size()); + + } else if (isYangGenerated(fromClass)) { + // Class is yang generated. + LOG.trace(fromClass.getName() + " is a Yang-generated class"); + + String propNamePfx = null; + + // If called from a list (so prefix ends in ']'), don't + // add class name again + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx; + } else { + propNamePfx = toLowerHyphen(fromClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // save from + + int numGetters = 0; + String lastGetterName = null; + String propVal = null; + + for (Method m : fromClass.getMethods()) { + if (isGetter(m)) { + + numGetters++; + lastGetterName = m.getName(); + + Class returnType = m.getReturnType(); + String fieldName; + if (m.getName().startsWith("get")) { + fieldName = toLowerHyphen(m.getName().substring(3)); + } else { + + fieldName = toLowerHyphen(m.getName().substring(2)); + } + + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + + // Is the return type a yang generated class? + if (isYangGenerated(returnType)) { + // Is it an enum? + if (returnType.isEnum()) { + // Return type is a typedef. Save its value. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + Object retValue = m.invoke(fromObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + String propName = propNamePfx + "." + fieldName; + propVal = retValue.toString(); + props.setProperty(propName, mapEnumeratedValue(fieldName, propVal)); + } + } catch (Exception e) { + LOG.error("Caught exception trying to convert Yang-generated enum returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } else if (isIpv4Address(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv4Address retValue = (Ipv4Address) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + propVal = retValue.getValue().toString(); + LOG.debug("Setting property " + propName + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } else if (isIpv6Address(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv6Address retValue = (Ipv6Address) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + propVal = retValue.getValue().toString(); + LOG.debug("Setting property " + propName + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } else if (isIpAddress(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + IpAddress retValue = (IpAddress) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + propVal = new String(retValue.getValue()); + LOG.debug("Setting property " + propName + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } else if (isIpPrefix(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + IpPrefix retValue = (IpPrefix) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + propVal = new String(retValue.getValue()); + LOG.debug("Setting property " + propName + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retValue = m.invoke(fromObj); + + if (retValue instanceof byte[]) { + LOG.trace(m.getName() + " returns a byte[]"); + retValue = new String((byte[]) retValue, "UTF-8"); + LOG.trace("Converted byte array " + propNamePfx + "." + fieldName + "to string " + retValue); + } + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + toProperties(props, propNamePfx + "." + fieldName, retValue, returnType); + } + } catch (Exception e) { + + if (m.getName().equals("getKey")) { + LOG.trace("Caught " + e.getClass().getName() + " exception trying to convert results from getKey() - ignoring"); + } else { + LOG.error("Caught exception trying to convert Yang-generated class returned by" + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } + } else if (returnType.equals(Class.class)) { + + LOG.trace(m.getName() + " returns a Class object - not interested"); + + } else if (List.class.isAssignableFrom(returnType)) { + + // This getter method returns a list. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retList = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + // Figure out what type of elements are stored in + // this array. + Type paramType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0]; + toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType); + } catch (Exception e) { + LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + + } else { + + // Method returns something that is not a List and not + // yang-generated. + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object propValObj = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (propValObj != null) { + if (propValObj instanceof byte[]) { + LOG.trace(m.getName() + " returns a byte[]"); + propVal = new String((byte[]) propValObj, "UTF-8"); + LOG.trace("Converted byte array " + propNamePfx + "." + fieldName + "to string " + propVal); + + } else { + propVal = propValObj.toString(); + } + LOG.debug("Setting property " + propName + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + if (m.getName().equals("getKey")) { + LOG.trace("Caught " + e.getClass().getName() + " exception trying to convert results from getKey() - ignoring"); + } else { + LOG.error("Caught exception trying to convert value returned by" + fromClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } + + } + } + + // End of method loop. If there was only one getter, named + // "getValue", then + // set value identified by "prefix" to that one value. + if ((numGetters == 1) && ("getValue".equals(lastGetterName))) { + LOG.trace("getValueFIX : " + propNamePfx + " only has getValue() getter - setting " + propNamePfx + " = " + propVal); + props.setProperty(propNamePfx, propVal); + } else { + LOG.trace("getValueFIX : " + propNamePfx + " has " + numGetters + " getter(s), last one found was " + lastGetterName); + + } + + } else { + // Class is not yang generated and not a list + // It must be an element of a leaf list - set "prefix" to value + String fromVal = null; + if (fromObj instanceof byte[]) { + try { + fromVal = new String((byte[]) fromObj, "UTF-8"); + LOG.trace("Converted byte array " + pfx + "to string " + fromVal); + } catch (Exception e) { + LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e); + fromVal = fromObj.toString(); + } + + } else { + fromVal = fromObj.toString(); + } + LOG.debug("Setting property " + pfx + " to " + fromVal); + props.setProperty(pfx, fromVal); + } + + return (props); + } + + public static Object toBuilder(Properties props, Object toObj) { + + return (toBuilder(props, "", toObj)); + } + + public static List toList(Properties props, String pfx, List toObj, Class elemType) { + + int maxIdx = -1; + boolean foundValue = false; + + LOG.trace("Saving properties to List<" + elemType.getName() + "> from " + pfx); + + if (props.contains(pfx + "_length")) { + try { + int listLength = Integer.parseInt(props.getProperty(pfx + "_length")); + + if (listLength > 0) { + maxIdx = listLength - 1; + } + } catch (Exception e) { + // Ignore exception + } + } + + if (maxIdx == -1) { + // Figure out array size + for (Object pNameObj : props.keySet()) { + String key = (String) pNameObj; + + if (key.startsWith(pfx + "[")) { + String idxStr = key.substring(pfx.length() + 1); + int endloc = idxStr.indexOf("]"); + if (endloc != -1) { + idxStr = idxStr.substring(0, endloc); + } + + try { + int curIdx = Integer.parseInt(idxStr); + if (curIdx > maxIdx) { + maxIdx = curIdx; + } + } catch (Exception e) { + LOG.error("Illegal subscript in property " + key); + } + + } + } + } + + LOG.trace(pfx + " has max index of " + maxIdx); + for (int i = 0; i <= maxIdx; i++) { + + String curBase = pfx + "[" + i + "]"; + + if (isYangGenerated(elemType)) { + String builderName = elemType.getName() + "Builder"; + try { + Class builderClass = Class.forName(builderName); + Object builderObj = builderClass.newInstance(); + Method buildMethod = builderClass.getMethod("build"); + builderObj = toBuilder(props, curBase, builderObj, true); + if (builderObj != null) { + LOG.trace("Calling " + builderObj.getClass().getName() + "." + buildMethod.getName() + "()"); + Object builtObj = buildMethod.invoke(builderObj); + toObj.add(builtObj); + foundValue = true; + } + + } catch (ClassNotFoundException e) { + LOG.warn("Could not find builder class " + builderName, e); + } catch (Exception e) { + LOG.error("Caught exception trying to populate list from " + pfx); + } + } else { + // Must be a leaf list + String curValue = props.getProperty(curBase, ""); + + toObj.add(curValue); + + if ((curValue != null) && (curValue.length() > 0)) { + foundValue = true; + } + } + + } + + if (foundValue) { + return (toObj); + } else { + return (null); + } + + } + + public static Object toBuilder(Properties props, String pfx, Object toObj) { + return (toBuilder(props, pfx, toObj, false)); + } + + public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) { + Class toClass = toObj.getClass(); + boolean foundValue = false; + + LOG.trace("Saving properties to " + toClass.getName() + " class from " + pfx); + + Ipv4Address addr; + + if (isYangGenerated(toClass)) { + // Class is yang generated. + LOG.trace(toClass.getName() + " is a Yang-generated class"); + + String propNamePfx = null; + if (preservePfx) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length()); + } + } + + if (toObj instanceof Identifier) { + LOG.trace(toClass.getName() + " is a Key - skipping"); + return (toObj); + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + if (isSetter(m)) { + Class paramTypes[] = m.getParameterTypes(); + Class paramClass = paramTypes[0]; + + String fieldName = toLowerHyphen(m.getName().substring(3)); + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + + String paramValue = props.getProperty(propName); + if (paramValue == null) { + LOG.trace(propName + " is unset"); + } else { + LOG.trace(propName + " = " + paramValue); + } + + // Is the return type a yang generated class? + if (isYangGenerated(paramClass)) { + // Is it an enum? + if (paramClass.isEnum()) { + + LOG.trace(m.getName() + " expects an Enum"); + // Param type is a typedef. + if ((paramValue != null) && (paramValue.length() > 0)) { + Object paramObj = null; + + try { + paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue)); + } catch (Exception e) { + LOG.error("Caught exception trying to convert field " + propName + " to enum " + paramClass.getName(), e); + } + + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")"); + m.invoke(toObj, paramObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to create Yang-generated enum expected by" + toClass.getName() + "." + m.getName() + "() from Properties entry", e); + } + } + } else { + + String simpleName = paramClass.getSimpleName(); + + if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName)) { + + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue); + + if ("Ipv4Address".equals(simpleName)) { + m.invoke(toObj, ipAddr.getIpv4Address()); + } else if ("Ipv6Address".equals(simpleName)) { + m.invoke(toObj, ipAddr.getIpv6Address()); + + } else { + m.invoke(toObj, ipAddr); + } + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + "(" + paramValue + ")", e); + + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")"); + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to call " + toClass.getName() + "." + m.getName() + "() with Properties entry", e); + } + } + } else if ("IpPrefix".equals(simpleName)) { + if ((paramValue != null) && (paramValue.length() > 0)) { + try { + IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue); + m.invoke(toObj, ipPrefix); + foundValue = true; + } catch (Exception e) { + LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + "(" + paramValue + ")", e); + } + } + } else { + // setter expects a yang-generated class. Need + // to + // create a builder to set it. + + String builderName = paramClass.getName() + "Builder"; + Class builderClass = null; + Object builderObj = null; + Object paramObj = null; + + Object constObj = null; + + LOG.trace(m.getName() + " expects a yang-generated class - looking for builder " + builderName); + try { + builderClass = Class.forName(builderName); + builderObj = builderClass.newInstance(); + paramObj = toBuilder(props, propNamePfx, builderObj); + } catch (ClassNotFoundException e) { + + if (paramValue == null) { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(null)"); + m.invoke(toObj, new Object[] { null }); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e1) { + LOG.error("Caught exception trying to cally" + toClass.getName() + "." + m.getName() + "() with Properties entry", e1); + } + } else { + try { + // See if I can find a constructor I + // can + // use + Constructor[] constructors = paramClass.getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (String.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (Long.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(Long.parseLong(paramValue)); + } + } + } + + } + + if (constObj == null) { + + // Last chance - see if + // parameter class has a static + // method + // getDefaultInstance(String) + try { + Method gm = paramClass.getMethod("getDefaultInstance", String.class); + + int gmodifier = gm.getModifiers(); + if (Modifier.isStatic(gmodifier)) { + // Invoke static + // getDefaultInstance(String) + paramObj = gm.invoke(null, paramValue); + } + + } catch (Exception gme) { + // Ignore exceptions + } + } + + } catch (Exception e1) { + LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1); + } + + if (constObj == null) { + LOG.warn("Could not find builder class " + builderName + " and could not find a String or Long constructor or static getDefaultInstance(String) - trying just to set passing paramValue"); + + } + } + } catch (Exception e) { + LOG.error("Caught exception trying to create builder " + builderName, e); + } + + if (paramObj != null) { + + try { + + Method buildMethod = builderClass.getMethod("build"); + LOG.trace("Calling " + paramObj.getClass().getName() + "." + buildMethod.getName() + "()"); + Object builtObj = buildMethod.invoke(paramObj); + + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "()"); + m.invoke(toObj, builtObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to set Yang-generated class expected by" + toClass.getName() + "." + m.getName() + "() from Properties entry", e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + if (constObj != null) { + + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + constObj.toString() + ")"); + m.invoke(toObj, constObj); + } else { + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")"); + m.invoke(toObj, paramValue); + + } + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(paramClass)) { + + LOG.trace("Parameter class " + paramClass.getName() + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type paramType = m.getGenericParameterTypes()[0]; + Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0]; + Object paramObj = new LinkedList(); + try { + paramObj = toList(props, propName, (List) paramObj, (Class) elementType); + } catch (Exception e) { + LOG.error("Caught exception trying to create list expected as argument to " + toClass.getName() + "." + m.getName()); + } + + if (paramObj != null) { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")"); + m.invoke(toObj, paramObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to convert List returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } else { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + LOG.trace("Parameter class " + paramClass.getName() + " is not a yang-generated class or a List"); + + if ((paramValue != null) && (paramValue.length() > 0)) { + + Object constObj = null; + + try { + // See if I can find a constructor I can use + Constructor[] constructors = paramClass.getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (String.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) && (cParms.length == 1)) { + if (Long.class.isAssignableFrom(cParms[0])) { + constObj = c.newInstance(Long.parseLong(paramValue)); + } + } + } + + } + + if (constObj != null) { + try { + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + constObj + ")"); + m.invoke(toObj, constObj); + foundValue = true; + } catch (Exception e2) { + LOG.error("Caught exception trying to call " + m.getName(), e2); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")"); + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error("Caught exception trying to convert value returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e); + } + } + } catch (Exception e1) { + LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1); + } + + } + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + if (foundValue) { + return (toObj); + } else { + return (null); + } + } + + public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) { + boolean foundValue = false; + + LOG.trace("Analyzing " + toClass.getName() + " class : pfx " + pfx); + + if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) { + // Class is yang generated. + LOG.trace(toClass.getName() + " is a Yang-generated class"); + + if (toClass.getName().endsWith("Key")) { + if (Identifier.class.isAssignableFrom(toClass)) { + LOG.trace(Identifier.class.getName() + " is assignable from " + toClass.getName()); + } else { + + LOG.trace(Identifier.class.getName() + " is NOT assignable from " + toClass.getName()); + } + } + + String propNamePfx = null; + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + LOG.trace("Is " + m.getName() + " method a getter?"); + if (isGetter(m)) { + LOG.trace(m.getName() + " is a getter"); + Class returnClass = m.getReturnType(); + + String fieldName = toLowerHyphen(m.getName().substring(3)); + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + + // Is the return type a yang generated class? + if (isYangGenerated(returnClass)) { + // Is it an enum? + if (returnClass.isEnum()) { + + LOG.trace(m.getName() + " is an Enum"); + pstr.print("\n\n * " + propName); + + } else { + + String simpleName = returnClass.getSimpleName(); + + if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName) || "IpPrefix".equals(simpleName)) { + LOG.trace(m.getName() + " is an " + simpleName); + pstr.print("\n\n * " + propName); + } else { + printPropertyList(pstr, propNamePfx, returnClass); + } + + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(returnClass)) { + + LOG.trace("Parameter class " + returnClass.getName() + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type returnType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0]; + Class elementClass = (Class) elementType; + LOG.trace("Calling printPropertyList on list type (" + elementClass.getName() + "), pfx is (" + pfx + "), toClass is (" + toClass.getName() + ")"); + printPropertyList(pstr, propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]", elementClass); + + } else if (!returnClass.equals(Class.class)) { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + LOG.trace("Parameter class " + returnClass.getName() + " is not a yang-generated class or a List"); + + pstr.print("\n\n * " + propName); + + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + } + + public static boolean isYangGenerated(Class c) { + if (c == null) { + return (false); + } else { + return (c.getName().startsWith("org.opendaylight.yang.gen.")); + } + } + + public static boolean isIpPrefix(Class c) { + + if (c == null) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("IpPrefix".equals(simpleName)); + } + + public static boolean isIpv4Address(Class c) { + + if (c == null) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Ipv4Address".equals(simpleName)); + } + + public static boolean isIpv6Address(Class c) { + + if (c == null) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Ipv6Address".equals(simpleName)); + } + + public static boolean isIpAddress(Class c) { + + if (c == null) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("IpAddress".equals(simpleName)); + } + + public static String toLowerHyphen(String inStr) { + if (inStr == null) { + return (null); + } + + String str = inStr.substring(0, 1).toLowerCase(); + if (inStr.length() > 1) { + str = str + inStr.substring(1); + } + + String regex = "(([a-z0-9])([A-Z]))"; + String replacement = "$2-$3"; + + String retval = str.replaceAll(regex, replacement).toLowerCase(); + + LOG.trace("Converting " + inStr + " => " + str + " => " + retval); + return (retval); + } + + //This is called when mapping the yang value back to a valid java enumeration + public static String toJavaEnum(String inStr) { + if (inStr == null) { + return (null); + } else if (inStr.length() == 0) { + return (inStr); + } + + //This will strip out all periods, which cannot be in a java enum + inStr = inStr.replaceAll("\\.", ""); + + String[] terms = inStr.split("-"); + StringBuffer sbuff = new StringBuffer(); + + //appends an _ if the string starts with a digit to make it a valid java enum + if (Character.isDigit(inStr.charAt(0))) { + sbuff.append('_'); + } + //If the string contains hyphens it will convert the string to upperCamelCase without hyphens + for (String term : terms) { + sbuff.append(term.substring(0, 1).toUpperCase()); + if (term.length() > 1) { + sbuff.append(term.substring(1)); + } + } + return (sbuff.toString()); + + } + + public static boolean isGetter(Method m) { + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) { + if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) { + if (!"getClass".equals(m.getName())) { + return (true); + } + } + + if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) { + return (true); + } + + if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) { + return (true); + } + } + + return (false); + } + + public static boolean isSetter(Method m) { + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) { + if (m.getName().matches("^set[A-Z].*")) { + Class[] paramTypes = m.getParameterTypes(); + if (paramTypes[0].isAssignableFrom(Identifier.class) || Identifier.class.isAssignableFrom(paramTypes[0])) { + return (false); + } else { + return (true); + } + } + + } + + return (false); + } + + public static String getFullPropertiesPath(String propertiesFileName) { + return "/opt/bvc/controller/configuration/" + propertiesFileName; + } + + //This is called when mapping a valid java enumeration back to the yang model value + public static String mapEnumeratedValue(String propertyName, String propertyValue) { + LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue); + String mappingKey = "yang." + propertyName + "." + propertyValue; + if (yangMappingProperties.containsKey(mappingKey)) { + return (yangMappingProperties.getProperty(mappingKey)); + } else { + LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value."); + return propertyValue; + } + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/NotifyNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/NotifyNodeExecutor.java new file mode 100644 index 00000000..706014a3 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/NotifyNodeExecutor.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NotifyNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(NotifyNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String action = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("action"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("release node encountered - looking for resource class " + + plugin); + } + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + if (resourcePlugin != null) { + + try { + + switch (resourcePlugin.notify(resourceType, action, key, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/RecordNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/RecordNodeExecutor.java new file mode 100644 index 00000000..8ba14d27 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/RecordNodeExecutor.java @@ -0,0 +1,119 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicRecorder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RecordNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(RecordNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String outValue = "failure"; + + if (LOG.isTraceEnabled()) { + LOG.trace(node.getNodeType() + + " node encountered - looking for recorder class " + + plugin); + } + + Map<String, String> parmMap = new HashMap<String, String>(); + + Set<Map.Entry<String, SvcLogicExpression>> parmSet = node + .getParameterSet(); + boolean hasParms = false; + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parmSet + .iterator(); iter.hasNext();) { + hasParms = true; + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + SvcLogicExpression curExpr = curEnt.getValue(); + String curExprValue = SvcLogicExpressionResolver.evaluate(curExpr, + node, ctx); + + if (LOG.isTraceEnabled()) { + LOG.trace("executeRecordNode : parameter " + curName + " = " + + curExpr + " => " + curExprValue); + } + parmMap.put(curName, curExprValue); + } + + + SvcLogicRecorder recorder = getSvcLogicRecorder(plugin); + + if (recorder != null) { + + try { + recorder.record(parmMap); + } catch (SvcLogicException e) { + LOG.error("Caught exception from recorder plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicRecorder object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isTraceEnabled()) { + LOG.trace("no failure or Other branch found"); + } + } + return (nextNode); + } + + + + + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReleaseNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReleaseNodeExecutor.java new file mode 100644 index 00000000..0d8416cd --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReleaseNodeExecutor.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReleaseNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(ReleaseNodeExecutor.class); + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("release node encountered - looking for resource class " + + plugin); + } + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + if (resourcePlugin != null) { + + try { + + switch (resourcePlugin.release(resourceType, key, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReserveNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReserveNodeExecutor.java new file mode 100644 index 00000000..f0bbda88 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReserveNodeExecutor.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReserveNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(ReserveNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"),node,ctx); + + + SvcLogicExpression selectExpr = node.getAttribute("select"); + String select = null; + + if (selectExpr != null) + { + select = SvcLogicExpressionResolver.evaluateAsKey(selectExpr, node, ctx); + } + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("reserve node encountered - looking for resource class " + + plugin); + } + + + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + + if (resourcePlugin != null) { + + try { + switch (resourcePlugin.reserve(resourceType, select, key, pfx, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReturnNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReturnNodeExecutor.java new file mode 100644 index 00000000..5cca4712 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/ReturnNodeExecutor.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReturnNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(ReturnNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String status = SvcLogicExpressionResolver.evaluate( + node.getAttribute("status"), node, ctx); + + if (status != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Returning status " + status); + } + ctx.setStatus(status); + } else { + if (LOG.isWarnEnabled()) { + LOG.warn("Return node has no status attribute set"); + } + } + + Set<Map.Entry<String, SvcLogicExpression>> parameterSet = node + .getParameterSet(); + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parameterSet + .iterator(); iter.hasNext();) { + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + String curValue = SvcLogicExpressionResolver.evaluate( + curEnt.getValue(), node, ctx); + + if (LOG.isDebugEnabled()) { + LOG.debug("Setting context attribute " + curName + " to " + + curValue); + } + ctx.setAttribute(curName, curValue); + } + return null; + } + + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SaveNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SaveNodeExecutor.java new file mode 100644 index 00000000..57eac7f7 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SaveNodeExecutor.java @@ -0,0 +1,142 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SaveNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(SaveNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + String forceStr = SvcLogicExpressionResolver.evaluate( + node.getAttribute("force"), node, ctx); + String localOnlyStr = SvcLogicExpressionResolver.evaluate( + node.getAttribute("local-only"), node, ctx); + String pfx = SvcLogicExpressionResolver.evaluate( + node.getAttribute("pfx"), node, ctx); + + boolean force = "true".equalsIgnoreCase(forceStr); + boolean localOnly = "true".equalsIgnoreCase(localOnlyStr); + + Map<String, String> parmMap = new HashMap<String, String>(); + + Set<Map.Entry<String, SvcLogicExpression>> parmSet = node + .getParameterSet(); + boolean hasParms = false; + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parmSet + .iterator(); iter.hasNext();) { + hasParms = true; + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + SvcLogicExpression curExpr = curEnt.getValue(); + if (curExpr != null) { + String curExprValue = SvcLogicExpressionResolver.evaluate( + curExpr, node, ctx); + + LOG.debug("Parameter " + curName + " = " + + curExpr.asParsedExpr() + " resolves to " + + curExprValue); + + parmMap.put(curName, curExprValue); + } + } + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("save node encountered - looking for resource class " + + plugin); + } + + + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + + if (resourcePlugin != null) { + + try { + switch (resourcePlugin.save(resourceType, force, localOnly, key, + parmMap, pfx, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SetNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SetNodeExecutor.java new file mode 100644 index 00000000..013997ed --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SetNodeExecutor.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicExpressionFactory; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SetNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(SetNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String ifunsetStr = SvcLogicExpressionResolver.evaluate( + node.getAttribute("only-if-unset"), node, ctx); + + boolean ifunset = "true".equalsIgnoreCase(ifunsetStr); + + Set<Map.Entry<String, SvcLogicExpression>> parameterSet = node + .getParameterSet(); + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parameterSet + .iterator(); iter.hasNext();) { + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + String lhsVarName = curName; + + // Resolve LHS of assignment (could contain index variables) + try { + SvcLogicExpression lhsExpr = SvcLogicExpressionFactory.parse(curName); + lhsVarName = SvcLogicExpressionResolver.resolveVariableName(lhsExpr, node, ctx); + } catch (Exception e) { + LOG.warn("Caught exception trying to resolve variable name ("+curName+")", e); + } + + + boolean setValue = true; + + if (curName.endsWith(".")) { + + // Copy subtree - value should be a variable name + SvcLogicExpression curValue = curEnt.getValue(); + + if (curValue != null) { + String rhsRoot = curValue.toString(); + + if ((rhsRoot != null) && (rhsRoot.length() > 0)) { + if (rhsRoot.endsWith(".")) { + rhsRoot = rhsRoot + .substring(0, rhsRoot.length() - 1); + } + + + // SDNGC-2321 : rhsRoot is variable name, possibly with subscript(s) to be resolved + try { + SvcLogicExpression rhsExpr = SvcLogicExpressionFactory.parse(rhsRoot); + rhsRoot = SvcLogicExpressionResolver.resolveVariableName(rhsExpr, node, ctx); + } catch (Exception e) { + LOG.warn("Caught exception trying to resolve variable name ("+rhsRoot+")", e); + } + + // See if the parameters are reversed (copying service-data to input) .. this + // was done as a workaround to earlier issue + if (curName.endsWith("-input.") && rhsRoot.startsWith("service-data")) { + LOG.warn("Arguments appear to be reversed .. will copy input to service-data instead"); + lhsVarName = rhsRoot + "."; + rhsRoot = curName.substring(0, curName.length()-1); + } + + rhsRoot = rhsRoot + "."; + String lhsPrefix = lhsVarName; + + if (lhsPrefix.endsWith(".")) { + lhsPrefix = lhsPrefix.substring(0, + lhsPrefix.length()-1); + } + int lhsPfxLength = lhsPrefix.length(); + HashMap<String, String> parmsToAdd = new HashMap<String,String>(); + + for (String sourceVarName : ctx.getAttributeKeySet()) { + + if (sourceVarName.startsWith(rhsRoot)) { + + String targetVar = lhsPrefix + + "." + + sourceVarName + .substring(rhsRoot.length()); + + LOG.debug("Copying " + sourceVarName + + " value to " + targetVar); + + parmsToAdd.put(targetVar, + ctx.getAttribute(sourceVarName)); + } + } + + for (String newParmName : parmsToAdd.keySet()) { + ctx.setAttribute(newParmName, parmsToAdd.get(newParmName)); + } + + } else { + // If RHS is empty, unset attributes in LHS + String lhsPrefix = lhsVarName.substring(0, + lhsVarName.length() - 1); + int lhsPfxLength = lhsPrefix.length(); + + LinkedList<String> parmsToRemove = new LinkedList<String> (); + + for (String curCtxVarname : ctx.getAttributeKeySet()) { + + if (curCtxVarname.startsWith(lhsPrefix)) { + LOG.debug("Unsetting " + curCtxVarname); + parmsToRemove.add(curCtxVarname); + } + } + + for (String parmName : parmsToRemove) { + ctx.setAttribute(parmName, null); + } + + } + } + + } else { + + if (ifunset) { + String ctxValue = ctx.getAttribute(lhsVarName); + + if ((ctxValue != null) && (ctxValue.length() > 0)) { + setValue = false; + LOG.debug("Attribute " + + lhsVarName + + " already set and only-if-unset is true, so not overriding"); + } + } + + if (setValue) { + String curValue = SvcLogicExpressionResolver.evaluate( + curEnt.getValue(), node, ctx); + + if (LOG.isDebugEnabled()) { + LOG.trace("Parameter value " + + curEnt.getValue().asParsedExpr() + + " resolves to " + curValue); + LOG.debug("Setting context attribute " + lhsVarName + + " to " + curValue); + } + ctx.setAttribute(lhsVarName, curValue); + } + } + } + + return null; + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicActivator.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicActivator.java new file mode 100644 index 00000000..ae42e2c7 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicActivator.java @@ -0,0 +1,225 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.io.File; +import java.io.FileInputStream; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.Map; +import java.util.Properties; + +import org.openecomp.sdnc.sli.ConfigurationException; +import org.openecomp.sdnc.sli.SvcLogicAdaptor; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicStore; +import org.openecomp.sdnc.sli.SvcLogicStoreFactory; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mysql.jdbc.Driver; + +public class SvcLogicActivator implements BundleActivator { + + private static final String SVCLOGIC_PROP_VAR = "SDNC_SLI_PROPERTIES"; + private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; + + private static final Map<String, SvcLogicNodeExecutor> BUILTIN_NODES = new HashMap<String, SvcLogicNodeExecutor>() { + { + put("block", new BlockNodeExecutor()); + put("call", new CallNodeExecutor()); + put("configure", new ConfigureNodeExecutor()); + put("delete", new DeleteNodeExecutor()); + put("execute", new ExecuteNodeExecutor()); + put("exists", new ExistsNodeExecutor()); + put("for", new ForNodeExecutor()); + put("get-resource", new GetResourceNodeExecutor()); + put("is-available", new IsAvailableNodeExecutor()); + put("notify", new NotifyNodeExecutor()); + put("record", new RecordNodeExecutor()); + put("release", new ReleaseNodeExecutor()); + put("reserve", new ReserveNodeExecutor()); + put("return", new ReturnNodeExecutor()); + put("save", new SaveNodeExecutor()); + put("set", new SetNodeExecutor()); + put("switch", new SwitchNodeExecutor()); + put("update", new UpdateNodeExecutor()); + put("break", new BreakNodeExecutor()); + + } + }; + + private static LinkedList<ServiceRegistration> registrations = new LinkedList<ServiceRegistration>(); + + private static HashMap<String, SvcLogicAdaptor> adaptorMap = null; + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicActivator.class); + + private static Properties props = null; + + private static BundleContext bundleCtx = null; + + private static SvcLogicService svcLogicServiceImpl = null; + + @Override + public void start(BundleContext ctx) throws Exception { + + LOG.info("Activating SLI"); + + bundleCtx = ctx; + + // Read properties + props = new Properties(); + String propPath = System.getenv(SVCLOGIC_PROP_VAR); + + if (propPath == null) { + String propDir = System.getenv(SDNC_CONFIG_DIR); + if (propDir == null) { + + propDir = "/opt/sdnc/data/properties"; + } + propPath = propDir + "/svclogic.properties"; + LOG.warn("Environment variable "+SVCLOGIC_PROP_VAR+" unset - defaulting to "+propPath); + } + + File propFile = new File(propPath); + + if (!propFile.exists()) { + + throw new ConfigurationException( + "Missing configuration properties file : " + + propFile); + } + try { + + props.load(new FileInputStream(propFile)); + } catch (Exception e) { + throw new ConfigurationException( + "Could not load properties file " + propPath, e); + + } + + + if (registrations == null) { + + registrations = new LinkedList<ServiceRegistration>(); + } + + // Advertise SvcLogicService + svcLogicServiceImpl = new SvcLogicServiceImpl(); + + LOG.info("SLI: Registering service " + SvcLogicService.NAME + + " in bundle " + ctx.getBundle().getSymbolicName()); + ServiceRegistration reg = ctx.registerService(SvcLogicService.NAME, + svcLogicServiceImpl, null); + registrations.add(reg); + + // Initialize SvcLogicStore + try { + SvcLogicStore store = getStore(); + registerNodeTypes(store); + } catch (ConfigurationException e) { + LOG.warn("Could not initialize SvcLogicScore", e); + } + + LOG.info("SLI - done registering services"); + } + + @Override + public void stop(BundleContext ctx) throws Exception { + + if (registrations != null) { + for (ServiceRegistration reg : registrations) { + ServiceReference regRef = reg.getReference(); + /* Don't bother to remove node types from table + String nodeType = (String) regRef.getProperty("nodeType"); + if (nodeType != null) { + LOG.info("SLI - unregistering node type " + nodeType); + store.unregisterNodeType(nodeType); + } + */ + reg.unregister(); + } + registrations = null; + } + } + + public static SvcLogicStore getStore() throws SvcLogicException { + // Create and initialize SvcLogicStore object - used to access + // saved service logic. + + SvcLogicStore store = null; + + try { + Driver dvr = new Driver(); + store = SvcLogicStoreFactory.getSvcLogicStore(props); + } catch (Exception e) { + throw new ConfigurationException( + "Could not get service logic store", e); + + } + + try { + store.init(props); + } catch (Exception e) { + throw new ConfigurationException( + "Could not get service logic store", e); + } + + return(store); + } + + private static void registerNodeTypes(SvcLogicStore store) throws SvcLogicException { + + if (store == null) { + return; + } + // Advertise built-in node executors + LOG.info("SLI : Registering built-in node executors"); + Hashtable propTable = new Hashtable(); + + for (String nodeType : BUILTIN_NODES.keySet()) { + LOG.info("SLI - registering node type " + nodeType); + propTable.clear(); + propTable.put("nodeType", nodeType); + + ServiceRegistration reg = bundleCtx.registerService(SvcLogicNodeExecutor.class.getName(), + BUILTIN_NODES.get(nodeType), propTable); + registrations.add(reg); + + store.registerNodeType(nodeType); + + LOG.info("SLI - registering node executor"); + + ((SvcLogicServiceImpl)svcLogicServiceImpl).registerExecutor(nodeType, BUILTIN_NODES.get(nodeType)); + + } + + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicAdaptorFactory.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicAdaptorFactory.java new file mode 100644 index 00000000..aa8c005a --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicAdaptorFactory.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; + +import org.openecomp.sdnc.sli.SvcLogicAdaptor; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicAdaptorFactory { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicAdaptorFactory.class); + + private static HashMap<String, SvcLogicAdaptor> adaptorMap = new HashMap<String, SvcLogicAdaptor>(); + + public static void registerAdaptor(SvcLogicAdaptor adaptor) { + String name = adaptor.getClass().getName(); + LOG.info("Registering adaptor " + name); + adaptorMap.put(name, adaptor); + + } + + public static void unregisterAdaptor(String name) { + if (adaptorMap.containsKey(name)) { + LOG.info("Unregistering " + name); + adaptorMap.remove(name); + } + } + + public static SvcLogicAdaptor getInstance(String name) { + if (adaptorMap.containsKey(name)) { + return (adaptorMap.get(name)); + } else { + BundleContext bctx = null; + try + { + bctx = FrameworkUtil.getBundle(SvcLogicAdaptorFactory.class) + .getBundleContext(); + } + catch (Exception e) + { + LOG.debug("Caught exception trying to locate device adaptor "+name, e); + return(null); + } + + ServiceReference sref = bctx.getServiceReference(name); + + if (sref != null) { + SvcLogicAdaptor adaptor = (SvcLogicAdaptor) bctx + .getService(sref); + + if (adaptor != null) { + registerAdaptor(adaptor); + + return (adaptor); + } + return (null); + } + } + return(null); + } +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicExpressionResolver.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicExpressionResolver.java new file mode 100644 index 00000000..5c17c799 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicExpressionResolver.java @@ -0,0 +1,605 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdnc.sli.SvcLogicAtom; +import org.openecomp.sdnc.sli.SvcLogicAtom.AtomType; +import org.openecomp.sdnc.sli.SvcLogicBinaryExpression; +import org.openecomp.sdnc.sli.SvcLogicBinaryExpression.OperatorType; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicFunctionCall; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicVariableTerm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicExpressionResolver { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExpressionResolver.class); + + public static String evaluate(SvcLogicExpression expr, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + if (expr == null) { + return (null); + } + + + + if (expr instanceof SvcLogicAtom) { + SvcLogicAtom atom = (SvcLogicAtom) expr; + + AtomType atomType = atom.getAtomType(); + switch (atomType) { + case NUMBER: + case STRING: + return (atom.toString()); + case CONTEXT_VAR: + case IDENTIFIER: + + String varName = resolveVariableName(atom, node, ctx); + + if (atomType == AtomType.CONTEXT_VAR) + { + LOG.trace("Evaluating context variable $"+varName); + + String varValue = ctx.getAttribute(varName); + + if (varValue == null) { + LOG.trace("Context variable $"+varName+" unset - treating as empty string"); + varValue = ""; + } + + return (varValue); + } + SvcLogicExpression parm = node.getParameter(varName); + if (parm != null) { + LOG.trace("Evaluating value of parameter "+varName+": "+parm.asParsedExpr()); + + return (evaluate(parm, node, ctx)); + } + else + { + return(varName); + } + default: + return(null); + } + + } else if (expr instanceof SvcLogicBinaryExpression) { + SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr; + List<OperatorType> operators = binExpr.getOperators(); + if (operators.isEmpty()) + { + List<SvcLogicExpression> operands = binExpr.getOperands(); + if (operands.size() == 1) + { + LOG.trace("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand"); + return(evaluate(operands.get(0), node, ctx)); + } + else + { + if (operands.isEmpty()) + { + LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null"); + } + else + { + LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null"); + } + return(null); + } + } + switch (operators.get(0)) { + case addOp: + case subOp: + case multOp: + case divOp: + return(evalArithExpression(binExpr, node, ctx)); + case equalOp: + case neOp: + case ltOp: + case leOp: + case gtOp: + case geOp: + return (evalCompareExpression(binExpr, node, ctx)); + case andOp: + case orOp: + return(evalLogicExpression(binExpr, node, ctx)); + + default: + return(null); + } + } + else if (expr instanceof SvcLogicFunctionCall) + { + return(evalFunctionCall((SvcLogicFunctionCall)expr, node, ctx)); + } + else + { + throw new SvcLogicException("Unrecognized expression type ["+expr+"]"); + } + } + + private static String evalArithExpression(SvcLogicBinaryExpression binExpr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException { + List<SvcLogicExpression> operands = binExpr.getOperands(); + List<OperatorType> operators = binExpr.getOperators(); + if (operands.size() != (operators.size()+1)) + { + throw new SvcLogicException("Invalid expression ("+binExpr+")"); + } + String retval = evaluate(operands.get(0), node, ctx); + String retsval = retval; + long retlval = 0; + boolean valueIsLong = false; + + int i = 1; + try + { + + if ((retval.length() > 0) && StringUtils.isNumeric(retval)) + { + retlval = Long.parseLong(retval); + valueIsLong = true; + } + for (OperatorType operator: operators) + { + String curOperandValue = evaluate(operands.get(i++), node, ctx); + switch(operator) { + case addOp: + retsval = retsval + curOperandValue; + if (valueIsLong) + { + if ((curOperandValue.length() > 0) && StringUtils.isNumeric(curOperandValue) ) + { + retlval = retlval + Long.parseLong(curOperandValue); + } + else + { + valueIsLong = false; + } + } + break; + case subOp: + retlval = retlval - Long.parseLong(curOperandValue); + break; + case multOp: + retlval = retlval * Long.parseLong(curOperandValue); + break; + case divOp: + retlval = retlval / Long.parseLong(curOperandValue); + break; + } + + } + } + catch (NumberFormatException e1) + { + throw new SvcLogicException("Illegal value in arithmetic expression", e1); + } + + if (valueIsLong) + { + return("" + retlval); + } + else + { + return(retsval); + } + + } + + + + private static String evalCompareExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + + List<OperatorType> operators = expr.getOperators(); + List<SvcLogicExpression> operands = expr.getOperands(); + + if ((operators.size() != 1) || (operands.size() != 2)) + { + throw new SvcLogicException ("Invalid comparison expression : "+expr); + } + + OperatorType operator = operators.get(0); + String op1Value = evaluate(operands.get(0), node, ctx); + String op2Value = evaluate(operands.get(1), node, ctx); + + if ((StringUtils.isNotEmpty(op1Value) && StringUtils.isNumeric(op1Value) && StringUtils.isNotEmpty(op2Value) && StringUtils.isNumeric(op2Value))) + { + try + { + double op1dbl = Double.parseDouble(op1Value); + double op2dbl = Double.parseDouble(op2Value); + + switch(operator) + { + case equalOp: + return(Boolean.toString(op1dbl == op2dbl)); + case neOp: + return(Boolean.toString(op1dbl != op2dbl)); + case ltOp: + return(Boolean.toString(op1dbl < op2dbl)); + case leOp: + return(Boolean.toString(op1dbl <= op2dbl)); + case gtOp: + return(Boolean.toString(op1dbl > op2dbl)); + case geOp: + return(Boolean.toString(op1dbl >= op2dbl)); + default: + return(null); + } + } + catch (NumberFormatException e) + { + throw new SvcLogicException("Caught exception trying to compare numeric values", e); + } + } + else + { + + int compResult = 0; + + if (op1Value == null) { + compResult = -1; + } else if (op2Value == null ) { + compResult = 1; + } else { + compResult = op1Value.compareToIgnoreCase(op2Value); + } + + switch(operator) + { + case equalOp: + return(Boolean.toString(compResult == 0)); + case neOp: + return(Boolean.toString(compResult != 0)); + case ltOp: + return(Boolean.toString(compResult < 0)); + case leOp: + return(Boolean.toString(compResult <= 0)); + case gtOp: + return(Boolean.toString(compResult > 0)); + case geOp: + return(Boolean.toString(compResult >= 0)); + default: + return(null); + } + } + + } + + private static String evalLogicExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + boolean retval; + + List<SvcLogicExpression> operands = expr.getOperands(); + List<OperatorType> operators = expr.getOperators(); + + if (operands.size() != (operators.size()+1)) + { + throw new SvcLogicException("Invalid expression ("+expr+")"); + } + + try + { + retval = Boolean.parseBoolean(evaluate(operands.get(0), node, ctx)); + int i = 1; + for (OperatorType operator : operators) + { + if (operator == OperatorType.andOp) + { + retval = retval && Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx)); + } + else + { + + retval = retval || Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx)); + } + + } + } + catch (Exception e) + { + throw new SvcLogicException("Invalid expression ("+expr+")"); + } + + + return(Boolean.toString(retval)); + } + + private static String evalFunctionCall(SvcLogicFunctionCall func, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + String funcName = func.getFunctionName(); + List<SvcLogicExpression> operands = func.getOperands(); + + if ("length".equalsIgnoreCase(funcName)) + { + + if (operands.size() == 1) + { + String opValue = evaluate(operands.get(0), node, ctx); + return(""+opValue.length()); + } + else + { + throw new SvcLogicException("Invalid call to length() function"); + } + } + else if ("substr".equalsIgnoreCase(funcName)) + { + if (operands.size() == 3) + { + String op1Value = evaluate(operands.get(0), node, ctx); + String op2Value = evaluate(operands.get(1), node, ctx); + String op3Value = evaluate(operands.get(2), node, ctx); + + if (!StringUtils.isNumeric(op2Value) || !StringUtils.isNumeric(op3Value)) + { + throw new SvcLogicException("Invalid arguments to substr() function"); + } + + try + { + return(op1Value.substring(Integer.parseInt(op2Value), Integer.parseInt(op3Value))); + } + catch (Exception e) + { + throw new SvcLogicException("Caught exception trying to take substring", e); + } + } + else + { + + throw new SvcLogicException("Invalid call to substr() function"); + } + + } + else if ("toUpperCase".equalsIgnoreCase(funcName)) + { + if (operands.size() == 1) + { + String opValue = evaluate(operands.get(0), node, ctx); + if (opValue != null) { + return(opValue.toUpperCase()); + } else { + return(""); + } + } + else + { + throw new SvcLogicException("Invalid call to toUpperCase() function"); + } + } + else if ("toLowerCase".equalsIgnoreCase(funcName)) + { + if (operands.size() == 1) + { + String opValue = evaluate(operands.get(0), node, ctx); + if (opValue != null) { + return(opValue.toLowerCase()); + } else { + return(""); + } + } + else + { + throw new SvcLogicException("Invalid call to toLowerCase() function"); + } + } + else if ("convertBase".equalsIgnoreCase(funcName)) { + int fromBase = 10; + int toBase = 10; + String srcString = ""; + + if (operands.size() == 2) + { + fromBase = 10; + srcString = evaluate(operands.get(0), node, ctx); + toBase = Integer.parseInt(evaluate(operands.get(1), node, ctx)); + } else if (operands.size() == 3) { + + srcString = evaluate(operands.get(0), node, ctx); + fromBase = Integer.parseInt(evaluate(operands.get(1), node, ctx)); + toBase = Integer.parseInt(evaluate(operands.get(2), node, ctx)); + } else { + throw new SvcLogicException("Invalid call to convertBase() function"); + } + + long srcValue = Long.parseLong(srcString, fromBase); + return(Long.toString(srcValue, toBase)); + } + else + { + throw new SvcLogicException("Unrecognized function ("+funcName+")"); + } + + } + + public static String evaluateAsKey(SvcLogicExpression expr, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + if (expr == null) { + return (null); + } + + + + if (expr instanceof SvcLogicAtom) { + SvcLogicAtom atom = (SvcLogicAtom) expr; + + AtomType atomType = atom.getAtomType(); + StringBuffer varNameBuff = new StringBuffer(); + switch (atomType) { + case NUMBER: + return (atom.toString()); + case STRING: + return("'"+atom.toString()+"'"); + case CONTEXT_VAR: + case IDENTIFIER: + boolean needDot = false; + for (SvcLogicExpression term : atom.getOperands()) + { + if (needDot) + { + varNameBuff.append("."); + } + if (term instanceof SvcLogicVariableTerm) + { + SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term; + varNameBuff.append(vterm.getName()); + if (vterm.numOperands() > 0) + { + varNameBuff.append("["); + varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx)); + varNameBuff.append("]"); + + } + } + else + { + varNameBuff.append(term.toString()); + } + needDot = true; + } + + String varName = varNameBuff.toString(); + LOG.debug("Evaluating context variable $"+varName); + String ctxValue = ctx.getAttribute(varName); + if (ctxValue == null) + { + return(null); + } + if (StringUtils.isNumeric(ctxValue)) + { + return(ctxValue); + } + else + { + return("'"+ctxValue+"'"); + } + + default: + return(null); + } + + } else if (expr instanceof SvcLogicBinaryExpression) { + SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr; + List<OperatorType> operators = binExpr.getOperators(); + List<SvcLogicExpression> operands = binExpr.getOperands(); + if (operators.isEmpty()) + { + if (operands.size() == 1) + { + LOG.debug("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand"); + return(evaluateAsKey(operands.get(0), node, ctx)); + } + else + { + if (operands.isEmpty()) + { + LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null"); + } + else + { + LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null"); + } + return(null); + } + } + StringBuffer sbuff = new StringBuffer(); + sbuff.append(evaluateAsKey(operands.get(0), node, ctx)); + int i = 1; + for (OperatorType operator : operators) + { + sbuff.append(" "); + sbuff.append(operator.toString()); + sbuff.append(" "); + sbuff.append(evaluateAsKey(operands.get(i++), node,ctx)); + } + return(sbuff.toString()); + } + else if (expr instanceof SvcLogicFunctionCall) + { + StringBuffer sbuff = new StringBuffer(); + SvcLogicFunctionCall funcCall = (SvcLogicFunctionCall) expr; + sbuff.append(funcCall.getFunctionName()); + sbuff.append("("); + boolean needComma = false; + for (SvcLogicExpression operand : funcCall.getOperands()) + { + if (needComma) + { + sbuff.append(","); + } + else + { + needComma = true; + } + sbuff.append(evaluateAsKey(operand, node, ctx)); + } + sbuff.append(")"); + return(sbuff.toString()); + } + else + { + throw new SvcLogicException("Unrecognized expression type ["+expr+"]"); + } + } + + public static String resolveVariableName(SvcLogicExpression atom, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + StringBuffer varNameBuff = new StringBuffer(); + + boolean needDot = false; + for (SvcLogicExpression term : atom.getOperands()) + { + if (needDot) + { + varNameBuff.append("."); + } + if (term instanceof SvcLogicVariableTerm) + { + SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term; + varNameBuff.append(vterm.getName()); + if (vterm.numOperands() > 0) + { + varNameBuff.append("["); + varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx)); + varNameBuff.append("]"); + } + } + else + { + varNameBuff.append(term.toString()); + } + needDot = true; + } + return(varNameBuff.toString()); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicNodeExecutor.java new file mode 100644 index 00000000..0c8166ae --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicNodeExecutor.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicAdaptor; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicRecorder; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.openecomp.sdnc.sli.SvcLogicStore; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class SvcLogicNodeExecutor { + + public abstract SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException; + + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicNodeExecutor.class); + + protected String evaluateNodeTest(SvcLogicNode node, SvcLogicContext ctx) + throws SvcLogicException { + if (node == null) { + return null; + } + + return (SvcLogicExpressionResolver.evaluate(node.getAttribute("test"), + node, ctx)); + + } + + protected SvcLogicStore getStore() throws SvcLogicException { + return SvcLogicActivator.getStore(); + } + + protected SvcLogicAdaptor getAdaptor(String adaptorName) { + return SvcLogicAdaptorFactory.getInstance(adaptorName); + } + + protected SvcLogicResource getSvcLogicResource(String plugin) { + BundleContext bctx = FrameworkUtil.getBundle(this.getClass()) + .getBundleContext(); + + ServiceReference sref = bctx.getServiceReference(plugin); + if (sref != null) { + SvcLogicResource resourcePlugin = (SvcLogicResource) bctx + .getService(sref); + return resourcePlugin; + } + else { + LOG.warn("Could not find service reference object for plugin " + plugin); + return null; + } + } + + protected SvcLogicRecorder getSvcLogicRecorder(String plugin) { + BundleContext bctx = FrameworkUtil.getBundle(this.getClass()) + .getBundleContext(); + + ServiceReference sref = bctx.getServiceReference(plugin); + if (sref != null) { + SvcLogicRecorder resourcePlugin = (SvcLogicRecorder) bctx + .getService(sref); + return resourcePlugin; + } + else { + return null; + } + } + + protected SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName){ + BundleContext bctx = FrameworkUtil.getBundle(this.getClass()) + .getBundleContext(); + + ServiceReference sref = bctx.getServiceReference(pluginName); + + if (sref == null) { + LOG.warn("Could not find service reference object for plugin " + pluginName); + return null; + } else { + SvcLogicJavaPlugin plugin = (SvcLogicJavaPlugin) bctx + .getService(sref); + return plugin; + } + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicService.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicService.java new file mode 100644 index 00000000..f30b3fc0 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicService.java @@ -0,0 +1,76 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.Properties; + +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.openecomp.sdnc.sli.SvcLogicException; + +public interface SvcLogicService { + + public static final String NAME = "org.openecomp.sdnc.sli.provider.SvcLogicService"; + + // public SvcLogicContext execute(SvcLogicGraph graph, SvcLogicContext ctx) throws SvcLogicException; + /** + * Check for existence of a directed graph + * @param module - module name + * @param rpc - rpc name + * @param version - version. If null, looks for active version + * @param mode - mode (sync/async) + * @return true if directed graph found, false otherwise + * @throws SvcLogicException + */ + public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException; + + /** + * Execute a directed graph + * + * @param module - module name + * @param rpc - rpc name + * @param version - version. If null, use active version + * @param mode - mode (sync/async) + * @param parms - parameters, used to set SvcLogicContext attributes + * @return final values of attributes from SvcLogicContext, as Properties + * @throws SvcLogicException + * + * + * @deprecated use execute(String module, String rpc, String version, String mode, DOMDataBroker dataBroker) instead + */ + @Deprecated + public Properties execute(String module, String rpc, String version, String mode, Properties parms) throws SvcLogicException; + + /** + * Execute a directed graph + * + * @param module - module name + * @param rpc - rpc name + * @param version - version. If null, use active version + * @param mode - mode (sync/async) + * @param parms - parameters, used to set SvcLogicContext attributes + * @param domDataBroker - DOMDataBroker object + * @return final values of attributes from SvcLogicContext, as Properties + * @throws SvcLogicException + */ + public Properties execute(String module, String rpc, String version, String mode, Properties parms, DOMDataBroker domDataBroker) throws SvcLogicException; + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicServiceImpl.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicServiceImpl.java new file mode 100644 index 00000000..ba929bae --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SvcLogicServiceImpl.java @@ -0,0 +1,273 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; +import java.util.Properties; + +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.openecomp.sdnc.sli.MetricLogger; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicGraph; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicStore; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +public class SvcLogicServiceImpl implements SvcLogicService { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicServiceImpl.class); + + private HashMap<String, SvcLogicNodeExecutor> nodeExecutors = null; + + private BundleContext bctx = null; + + private void registerExecutors() { + + LOG.info("Entered register executors"); + if (bctx == null) { + bctx = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); + } + + if (nodeExecutors == null) { + nodeExecutors = new HashMap<String, SvcLogicNodeExecutor>(); + } + + LOG.info("Opening service tracker"); + ServiceTracker tracker = new ServiceTracker(bctx, + SvcLogicNodeExecutor.class.getName(), null); + + tracker.open(); + + ServiceListener listener = new ServiceListener() { + + public void serviceChanged(ServiceEvent ev) { + ServiceReference sr = ev.getServiceReference(); + switch (ev.getType()) { + case ServiceEvent.REGISTERED: { + registerExecutor(sr); + } + break; + case ServiceEvent.UNREGISTERING: { + unregisterExecutor(sr); + } + break; + } + } + }; + + LOG.info("Adding service listener"); + String filter = "(objectclass=" + SvcLogicNodeExecutor.class.getName() + + ")"; + try { + bctx.addServiceListener(listener, filter); + ServiceReference[] srl = bctx.getServiceReferences( + SvcLogicNodeExecutor.class.getName(), null); + for (int i = 0; srl != null && i < srl.length; i++) { + listener.serviceChanged(new ServiceEvent( + ServiceEvent.REGISTERED, srl[i])); + } + } catch (InvalidSyntaxException e) { + e.printStackTrace(); + } + LOG.info("Done registerExecutors"); + } + + public void registerExecutor(ServiceReference sr) { + + String nodeName = (String) sr.getProperty("nodeType"); + if (nodeName != null) { + + SvcLogicNodeExecutor executor = null; + + try { + executor = (SvcLogicNodeExecutor) bctx.getService(sr); + } catch (Exception e) { + LOG.error("Cannot get service executor for " + nodeName); + return; + } + + registerExecutor(nodeName, executor); + + } + } + + public void registerExecutor(String nodeName, SvcLogicNodeExecutor executor) + { + if (nodeExecutors == null) { + nodeExecutors = new HashMap<String, SvcLogicNodeExecutor>(); + } + LOG.info("SLI - registering executor for node type "+nodeName); + nodeExecutors.put(nodeName, executor); + } + + public void unregisterExecutor(ServiceReference sr) { + String nodeName = (String) sr.getProperty("nodeType"); + + if (nodeName != null) { + + unregisterExecutor(nodeName); + + } + + } + + public void unregisterExecutor(String nodeName) + { + + LOG.info("SLI - unregistering executor for node type "+nodeName); + nodeExecutors.remove(nodeName); + } + + + + + public SvcLogicContext execute(SvcLogicGraph graph, SvcLogicContext ctx) + throws SvcLogicException { + + if (nodeExecutors == null) { + registerExecutors(); + } + + // Set service name in MDC to reference current working directed graph + MDC.put(MetricLogger.SERVICE_NAME, graph.getModule()+":"+graph.getRpc()+"/v"+graph.getVersion()); + + SvcLogicNode curNode = graph.getRootNode(); + LOG.info("About to execute graph " + graph.toString()); + + + + while (curNode != null) { + LOG.info("About to execute node # "+curNode.getNodeId()+" ("+curNode.getNodeType()+")"); + + SvcLogicNode nextNode = executeNode(curNode, ctx); + curNode = nextNode; + } + + return (ctx); + } + + + public SvcLogicNode executeNode(SvcLogicNode node, SvcLogicContext ctx) + throws SvcLogicException { + if (node == null) { + return (null); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Executing node " + node.getNodeId()); + } + + SvcLogicNodeExecutor executor = nodeExecutors.get(node.getNodeType()); + + if (executor != null) { + LOG.debug("Executing node executor for node type "+node.getNodeType()+" - "+executor.getClass().getName()); + return (executor.execute(this, node, ctx)); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug(node.getNodeType() + " node not implemented"); + } + SvcLogicNode nextNode = node.getOutcomeValue("failure"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute failure branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no failure or Other branch found"); + } + } + return (nextNode); + } + + } + + @Override + public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException + { + SvcLogicStore store = SvcLogicActivator.getStore(); + + return (store.hasGraph(module, rpc, version, mode)); + } + + @Override + public Properties execute(String module, String rpc, String version, String mode, Properties props) + throws SvcLogicException { + return(execute(module, rpc, version, mode, props, null)); + } + + + @Override + public Properties execute(String module, String rpc, String version, String mode, + Properties props, DOMDataBroker domDataBroker) throws SvcLogicException { + + + // See if there is a service logic defined + // + SvcLogicStore store = SvcLogicActivator.getStore(); + + LOG.info("Fetching service logic from data store"); + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + + + + if (graph == null) + { + Properties retProps = new Properties(); + retProps.setProperty("error-code", "401"); + retProps.setProperty("error-message", "No service logic found for ["+module+","+rpc+","+version+","+mode+"]"); + return(retProps); + + } + + SvcLogicContext ctx = new SvcLogicContext(props); + ctx.setAttribute("currentGraph", graph.toString()); + ctx.setAttribute("X-ECOMP-RequestID", MDC.get("X-ECOMP-RequestID")); + ctx.setDomDataBroker(domDataBroker); + + execute(graph, ctx); + + return(ctx.toProperties()); + } + + + + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SwitchNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SwitchNodeExecutor.java new file mode 100644 index 00000000..e8ae7c89 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/SwitchNodeExecutor.java @@ -0,0 +1,63 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SwitchNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(SwitchNodeExecutor.class); + + @Override + + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + + String testResult = evaluateNodeTest(node, ctx); + + if (LOG.isDebugEnabled()) { + LOG.debug("Executing switch node"); + + + LOG.debug("test expression (" + node.getAttribute("test") + + ") evaluates to " + testResult); + } + + SvcLogicNode nextNode = node.getOutcomeValue(testResult); + + if (LOG.isDebugEnabled()) { + if (nextNode != null) { + LOG.debug("Next node to execute is node " + nextNode.getNodeId()); + } else { + LOG.debug("No next node found"); + } + } + return (nextNode); + + } +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/UpdateNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/UpdateNodeExecutor.java new file mode 100644 index 00000000..9eeab65a --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/UpdateNodeExecutor.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UpdateNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory + .getLogger(UpdateNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + + String plugin = SvcLogicExpressionResolver.evaluate( + node.getAttribute("plugin"), node, ctx); + String resourceType = SvcLogicExpressionResolver.evaluate( + node.getAttribute("resource"), node, ctx); + String key = SvcLogicExpressionResolver.evaluateAsKey( + node.getAttribute("key"), node, ctx); + String pfx = SvcLogicExpressionResolver.evaluate( + node.getAttribute("pfx"), node, ctx); + + + Map<String, String> parmMap = new HashMap<String, String>(); + + Set<Map.Entry<String, SvcLogicExpression>> parmSet = node + .getParameterSet(); + boolean hasParms = false; + + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parmSet + .iterator(); iter.hasNext();) { + hasParms = true; + Map.Entry<String, SvcLogicExpression> curEnt = iter.next(); + String curName = curEnt.getKey(); + SvcLogicExpression curExpr = curEnt.getValue(); + if (curExpr != null) { + String curExprValue = SvcLogicExpressionResolver.evaluate( + curExpr, node, ctx); + + LOG.debug("Parameter " + curName + " = " + + curExpr.asParsedExpr() + " resolves to " + + curExprValue); + + parmMap.put(curName, curExprValue); + } + } + + String outValue = "failure"; + + if (LOG.isDebugEnabled()) { + LOG.debug("save node encountered - looking for resource class " + + plugin); + } + + + SvcLogicResource resourcePlugin = getSvcLogicResource(plugin); + + + if (resourcePlugin != null) { + + try { + switch (resourcePlugin.update(resourceType, key, + parmMap, pfx, ctx)) { + case SUCCESS: + outValue = "success"; + break; + case NOT_FOUND: + outValue = "not-found"; + break; + case FAILURE: + default: + outValue = "failure"; + } + } catch (SvcLogicException e) { + LOG.error("Caught exception from resource plugin", e); + outValue = "failure"; + } + } else { + LOG.warn("Could not find SvcLogicResource object for plugin " + + plugin); + } + + SvcLogicNode nextNode = node.getOutcomeValue(outValue); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute " + outValue + " branch"); + } + return (nextNode); + } + + nextNode = node.getOutcomeValue("Other"); + if (nextNode != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("about to execute Other branch"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no "+outValue+" or Other branch found"); + } + } + return (nextNode); + } + +} diff --git a/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/WhileNodeExecutor.java b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/WhileNodeExecutor.java new file mode 100644 index 00000000..5bbab323 --- /dev/null +++ b/sli/provider/src/main/java/org/openecomp/sdnc/sli/provider/WhileNodeExecutor.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.BreakNodeException; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WhileNodeExecutor extends SvcLogicNodeExecutor { + + private static final Logger LOG = LoggerFactory.getLogger(WhileNodeExecutor.class); + + @Override + public SvcLogicNode execute(SvcLogicServiceImpl svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException { + + String testResult = evaluateNodeTest(node, ctx); + SvcLogicExpression silentFailureExpr = node.getAttribute("do"); + String doWhile = SvcLogicExpressionResolver.evaluate(silentFailureExpr, node, ctx); + if ("true".equals(doWhile)) { + LOG.debug("While loop will execute once regardless of expression because do is set to true"); + } + + try { + while ("true".equals(testResult) || "true".equals(doWhile)) { + if (!"true".equals(doWhile)) { + LOG.debug("Test expression (" + node.getAttribute("test") + ") evaluates to true, executing loop."); + } + int numOutcomes = node.getNumOutcomes() + 1; + for (int i = 0; i < numOutcomes; i++) { + SvcLogicNode nextNode = node.getOutcomeValue("" + (i + 1)); + if (nextNode != null) { + while (nextNode != null) { + nextNode = svc.executeNode(nextNode, ctx); + } + } else { + if ("true".equals(doWhile)) { + LOG.debug("Do executed, will only execute again if test expression is true."); + doWhile = "false"; + } + testResult = evaluateNodeTest(node, ctx); + LOG.debug("test expression (" + node.getAttribute("test") + ") evaluates to " + testResult); + } + } + } + LOG.debug("testResult was " + testResult + " which is not equal to true, exiting while loop."); + } catch (BreakNodeException e) { + LOG.debug("WhileNodeExecutor caught break"); + } + return (null); + } + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/BadPlugin.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/BadPlugin.java new file mode 100644 index 00000000..d1ab4cfd --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/BadPlugin.java @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.Map; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; + + +public class BadPlugin implements SvcLogicJavaPlugin { + public String selectLunch(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + String day = parameters.get("day"); + if (day == null || day.length() < 1) { + throw new SvcLogicException("What day is it?"); + } + switch (day) { + case ("monday"): { + return "pizza"; + } + case ("tuesday"): { + return "soup"; + } + case ("wednesday"): { + return "salad"; + } + case ("thursday"): { + return "sushi"; + } + case ("friday"): { + return "bbq"; + } + } + throw new SvcLogicException("Lunch cannot be served"); + } +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/ExecuteNodeExecutorTest.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/ExecuteNodeExecutorTest.java new file mode 100644 index 00000000..3d43ee11 --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/ExecuteNodeExecutorTest.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.Map.Entry; + +import org.openecomp.sdnc.sli.DuplicateValueException; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicGraph; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.openecomp.sdnc.sli.SvcLogicNode; + +import junit.framework.TestCase; + +public class ExecuteNodeExecutorTest extends TestCase { + public class MockExecuteNodeExecutor extends ExecuteNodeExecutor { + + protected SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName) { + return (SvcLogicJavaPlugin) new LunchSelectorPlugin(); + } + + protected String evaluate(SvcLogicExpression expr, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + return "selectLunch"; + } + } + + public void testBadPlugin() throws DuplicateValueException, SvcLogicException { + LunchSelectorPlugin p = new LunchSelectorPlugin(); + MockExecuteNodeExecutor execute = new MockExecuteNodeExecutor(); + SvcLogicNode node = new SvcLogicNode(0, "", "", new SvcLogicGraph()); + node.setAttribute("method", "selectLunch"); + execute.execute(new SvcLogicServiceImpl(), new SvcLogicNode(0, "", "", new SvcLogicGraph()), new SvcLogicContext()); + } + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/LunchSelectorPlugin.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/LunchSelectorPlugin.java new file mode 100644 index 00000000..b9156bcd --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/LunchSelectorPlugin.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.Map; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; + + + +public class LunchSelectorPlugin implements SvcLogicJavaPlugin { + public class UnknownLunchDayException extends Exception{ + + public UnknownLunchDayException(String string) { + super(string); + } + + } + class Sandwhich { + String meat; + String cheese; + + public Sandwhich(String meat, String cheese) { + this.meat = meat; + this.cheese = cheese; + } + } + + public String selectLunch(Map<String, String> parameters, SvcLogicContext ctx) throws Exception { + String day = parameters.get("day"); + if (day == null || day.length() < 1) { + throw new UnknownLunchDayException("What day is it?"); + } + switch (day) { + case ("monday"): { + return "pizza"; + } + case ("tuesday"): { + return "soup"; + } + case ("wednesday"): { + return "salad"; + } + case ("thursday"): { + return "sushi"; + } + case ("friday"): { + return "bbq"; + } + } + throw new SvcLogicException("Lunch cannot be served"); + } + + public Sandwhich makeLunch(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + return new Sandwhich("ham", "american"); + } +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/MdsalHelperTest.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/MdsalHelperTest.java new file mode 100644 index 00000000..a4e41bba --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/MdsalHelperTest.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import junit.framework.TestCase; + +public class MdsalHelperTest extends TestCase { + + public static final String pathToSdnPropertiesFile = "./src/test/resources/l3sdn.properties"; + + public void testSdnProperties() { + MdsalHelperTesterUtil.loadProperties(pathToSdnPropertiesFile); + assertEquals("synccomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "Synccomplete")); + assertEquals("asynccomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "asynccomplete")); + assertEquals("notifycomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "notifycomplete")); + assertEquals("service-configuration-operation", MdsalHelperTesterUtil.mapEnumeratedValue("rpc-name", + "ServiceConfigurationOperation")); + } + + public void testNegativeSdnProperties() { + assertNotSame("synccomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "Synccomplete")); + } + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/MdsalHelperTesterUtil.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/MdsalHelperTesterUtil.java new file mode 100644 index 00000000..01e333f6 --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/MdsalHelperTesterUtil.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import org.openecomp.sdnc.sli.provider.MdsalHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MdsalHelperTesterUtil extends MdsalHelper { + + private static final Logger LOG = LoggerFactory.getLogger(MdsalHelperTesterUtil.class); + + //Normally static init of classes goes here for some weird classloader thing + static { + String str = "Hello World!"; + } + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/PluginTest.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/PluginTest.java new file mode 100644 index 00000000..035cd3e7 --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/PluginTest.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicGraph; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.openecomp.sdnc.sli.SvcLogicNode; + +import junit.framework.TestCase; + +public class PluginTest extends TestCase { + + // The existing plugins work just like a VoidDummyPlugin + // They will return null simply because they are all void + // The attribute emitsOutcome will not be present, the expected outcome is success when no exception is thrown by the plugin + public void testOldPlugin() throws Exception { + ExecuteNodeExecutor executor = new ExecuteNodeExecutor(); + SvcLogicJavaPlugin plugin = new VoidDummyPlugin(); + + Class pluginClass = plugin.getClass(); + Method pluginMethod = pluginClass.getMethod("dummy", Map.class, SvcLogicContext.class); + Map<String, String> parmMap = new HashMap<String, String>(); + SvcLogicContext ctx = new SvcLogicContext(); + Object o = pluginMethod.invoke(plugin, parmMap, ctx); + + SvcLogicGraph graph = new SvcLogicGraph(); + SvcLogicNode node = new SvcLogicNode(1, "return", graph); + String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx); + String outValue = executor.mapOutcome(o, emitsOutcome); + assertEquals("success",outValue); + } + + //Newer plugins can set the attribute emitsOutcome to true, if so they should return a string + //The string represents the outcome value + public void testNewPlugin() throws Exception { + ExecuteNodeExecutor executor = new ExecuteNodeExecutor(); + SvcLogicJavaPlugin plugin = new LunchSelectorPlugin(); + + Class pluginClass = plugin.getClass(); + Method pluginMethod = pluginClass.getMethod("selectLunch", Map.class, SvcLogicContext.class); + + Map<String, String> parmMap = new HashMap<String, String>(); + SvcLogicContext ctx = new SvcLogicContext(); + + parmMap.put("day", "monday"); + Object o = pluginMethod.invoke(plugin, parmMap, ctx); + SvcLogicGraph graph = new SvcLogicGraph(); + SvcLogicNode node = new SvcLogicNode(1, "return", graph); + node.setAttribute("emitsOutcome", "true"); + String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx); + String outValue = executor.mapOutcome(o, emitsOutcome); + assertEquals("pizza", outValue); + + parmMap.put("day", "tuesday"); + outValue = (String) pluginMethod.invoke(plugin, parmMap, ctx); + o = pluginMethod.invoke(plugin, parmMap, ctx); + outValue = executor.mapOutcome(o, emitsOutcome); + assertEquals("soup",outValue); + + } + + //APPC had some legacy plugins returning objects which should not be treated as outcomes + //The attribute emitsOutcome will not be set + //The outcome should be success as it has always been + public void testObjPlugin() throws Exception{ + ExecuteNodeExecutor executor = new ExecuteNodeExecutor(); + SvcLogicJavaPlugin plugin = new LunchSelectorPlugin(); + + Class pluginClass = plugin.getClass(); + Method pluginMethod = pluginClass.getMethod("makeLunch", Map.class, SvcLogicContext.class); + + Map<String, String> parmMap = new HashMap<String, String>(); + SvcLogicContext ctx = new SvcLogicContext(); + Object o = pluginMethod.invoke(plugin, parmMap, ctx); + SvcLogicGraph graph = new SvcLogicGraph(); + SvcLogicNode node = new SvcLogicNode(1, "return", graph); + String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx); + String outValue = executor.mapOutcome(o, emitsOutcome); + assertEquals("success",outValue); + } + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/SvcLogicExpressionResolverTest.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/SvcLogicExpressionResolverTest.java new file mode 100644 index 00000000..61815488 --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/SvcLogicExpressionResolverTest.java @@ -0,0 +1,123 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicExprListener; +import org.openecomp.sdnc.sli.SvcLogicExpression; +import org.openecomp.sdnc.sli.SvcLogicExpressionFactory; +import org.openecomp.sdnc.sli.SvcLogicGraph; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.provider.SvcLogicExpressionResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class SvcLogicExpressionResolverTest extends TestCase { + + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExpressionResolver.class); + + public void testEvaluate() + { + InputStream testStr = getClass().getResourceAsStream("/expression.tests"); + BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr)); + + try + { + SvcLogicContext ctx = new SvcLogicContext(); + SvcLogicGraph graph = new SvcLogicGraph(); + SvcLogicNode node = new SvcLogicNode(1, "return", graph); + graph.setRootNode(node); + + String line = null; + int lineNo = 0; + while ((line = testsReader.readLine()) != null) { + ++lineNo; + if (line.startsWith("#")) + { + String testExpr = line.trim().substring(1).trim(); + String[] nameValue = testExpr.split("="); + String name = nameValue[0].trim(); + String value = nameValue[1].trim(); + + if (name.startsWith("$")) + { + LOG.info("Setting context attribute "+name+" = "+value); + ctx.setAttribute(name.substring(1), value); + } + else + { + + LOG.info("Setting node attribute "+name+" = "+value); + node.setAttribute(name, value); + + } + } + else + { + // if the line contains #, what comes before is the expression to evaluate, and what comes after + // is the expected value + String[] substrings = line.split("#"); + String expectedValue = substrings.length > 1 ? substrings[1].trim() : null; + String testExpr = substrings[0].trim(); + + LOG.info("Parsing expression "+testExpr); + SvcLogicExpression expr = SvcLogicExpressionFactory.parse(testExpr); + if (expr == null) + { + fail("Unable to parse expression "+testExpr); + } + else + { + LOG.info("Evaluating parsed expression "+expr.asParsedExpr()); + String exprValue = SvcLogicExpressionResolver.evaluate(expr, node, ctx); + if (exprValue == null) + { + fail("Unable to evaluate expression "+testExpr); + } + else + { + LOG.info("Expression " + testExpr + " evaluates to " + exprValue); + if (expectedValue != null) { + Assert.assertEquals("Line " + lineNo + ": " + testExpr, expectedValue, exprValue); + } + } + } + } + } + } + catch (Exception e) + { + LOG.error("Caught exception", e); + fail("Caught exception"); + } + } + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/SvcLogicGraphExecutorTest.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/SvcLogicGraphExecutorTest.java new file mode 100644 index 00000000..2e8b35e1 --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/SvcLogicGraphExecutorTest.java @@ -0,0 +1,212 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Properties; + +import org.openecomp.sdnc.sli.MetricLogger; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicGraph; +import org.openecomp.sdnc.sli.SvcLogicNode; +import org.openecomp.sdnc.sli.SvcLogicParser; +import org.openecomp.sdnc.sli.SvcLogicStore; +import org.openecomp.sdnc.sli.SvcLogicStoreFactory; +import org.openecomp.sdnc.sli.provider.BlockNodeExecutor; +import org.openecomp.sdnc.sli.provider.CallNodeExecutor; +import org.openecomp.sdnc.sli.provider.ConfigureNodeExecutor; +import org.openecomp.sdnc.sli.provider.DeleteNodeExecutor; +import org.openecomp.sdnc.sli.provider.ExecuteNodeExecutor; +import org.openecomp.sdnc.sli.provider.ExistsNodeExecutor; +import org.openecomp.sdnc.sli.provider.ForNodeExecutor; +import org.openecomp.sdnc.sli.provider.GetResourceNodeExecutor; +import org.openecomp.sdnc.sli.provider.IsAvailableNodeExecutor; +import org.openecomp.sdnc.sli.provider.NotifyNodeExecutor; +import org.openecomp.sdnc.sli.provider.RecordNodeExecutor; +import org.openecomp.sdnc.sli.provider.ReleaseNodeExecutor; +import org.openecomp.sdnc.sli.provider.ReserveNodeExecutor; +import org.openecomp.sdnc.sli.provider.ReturnNodeExecutor; +import org.openecomp.sdnc.sli.provider.SaveNodeExecutor; +import org.openecomp.sdnc.sli.provider.SetNodeExecutor; +import org.openecomp.sdnc.sli.provider.SvcLogicNodeExecutor; +import org.openecomp.sdnc.sli.provider.SvcLogicServiceImpl; +import org.openecomp.sdnc.sli.provider.SwitchNodeExecutor; +import org.openecomp.sdnc.sli.provider.UpdateNodeExecutor; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import junit.framework.TestCase; + +public class SvcLogicGraphExecutorTest extends TestCase { + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicGraph.class); + + private static final Map<String, SvcLogicNodeExecutor> BUILTIN_NODES = new HashMap<String, SvcLogicNodeExecutor>() { + { + put("block", new BlockNodeExecutor()); + put("call", new CallNodeExecutor()); + put("configure", new ConfigureNodeExecutor()); + put("delete", new DeleteNodeExecutor()); + put("execute", new ExecuteNodeExecutor()); + put("exists", new ExistsNodeExecutor()); + put("for", new ForNodeExecutor()); + put("get-resource", new GetResourceNodeExecutor()); + put("is-available", new IsAvailableNodeExecutor()); + put("notify", new NotifyNodeExecutor()); + put("record", new RecordNodeExecutor()); + put("release", new ReleaseNodeExecutor()); + put("reserve", new ReserveNodeExecutor()); + put("return", new ReturnNodeExecutor()); + put("save", new SaveNodeExecutor()); + put("set", new SetNodeExecutor()); + put("switch", new SwitchNodeExecutor()); + put("update", new UpdateNodeExecutor()); + + } + }; + + public void testExecute() { + + try { + InputStream testStr = getClass().getResourceAsStream("/executor.tests"); + BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr)); + + InputStream propStr = getClass().getResourceAsStream("/svclogic.properties"); + + SvcLogicStore store = SvcLogicStoreFactory.getSvcLogicStore(propStr); + + assertNotNull(store); + + store.registerNodeType("switch"); + store.registerNodeType("block"); + store.registerNodeType("get-resource"); + store.registerNodeType("reserve"); + store.registerNodeType("is-available"); + store.registerNodeType("exists"); + store.registerNodeType("configure"); + store.registerNodeType("return"); + store.registerNodeType("record"); + store.registerNodeType("allocate"); + store.registerNodeType("release"); + store.registerNodeType("for"); + store.registerNodeType("set"); + SvcLogicParser parser = new SvcLogicParser(store); + + // Loop through executor tests + + SvcLogicServiceImpl svc = new SvcLogicServiceImpl(); + + for (String nodeType : BUILTIN_NODES.keySet()) { + + LOG.info("SLI - registering node executor for node type "+nodeType); + + svc.registerExecutor(nodeType, BUILTIN_NODES.get(nodeType)); + + } + String testCaseLine = null; + while ((testCaseLine = testsReader.readLine()) != null) { + + String[] testCaseFields = testCaseLine.split(":"); + String testCaseFile = testCaseFields[0]; + String testCaseMethod = testCaseFields[1]; + String testCaseParameters = null; + + if (testCaseFields.length > 2) { + testCaseParameters = testCaseFields[2]; + } + + SvcLogicContext ctx = new SvcLogicContext(); + if (testCaseParameters != null) { + String[] testCaseParameterSettings = testCaseParameters.split(","); + + for (int i = 0 ; i < testCaseParameterSettings.length ; i++) { + String[] nameValue = testCaseParameterSettings[i].split("="); + if (nameValue != null) { + String name = nameValue[0]; + String value = ""; + if (nameValue.length > 1) { + value = nameValue[1]; + } + + ctx.setAttribute(name, value); + } + } + } + + testCaseFile = testCaseFile.trim(); + + if (testCaseFile.length() > 0) { + if (!testCaseFile.startsWith("/")) { + testCaseFile = "/"+testCaseFile; + } + URL testCaseUrl = getClass().getResource(testCaseFile); + if (testCaseUrl == null) { + fail("Could not resolve test case file "+testCaseFile); + } + + LinkedList<SvcLogicGraph> graphs = parser.parse(testCaseUrl.getPath()); + + + assertNotNull(graphs); + + for (SvcLogicGraph graph: graphs) { + if (graph.getRpc().equals(testCaseMethod)) { + Properties props = ctx.toProperties(); + LOG.info("SvcLogicContext before executing "+testCaseMethod+":"); + for (Enumeration e1 = props.propertyNames(); e1.hasMoreElements() ; ) { + String propName = (String) e1.nextElement(); + LOG.info(propName+" = "+props.getProperty(propName)); + } + + svc.execute(graph, ctx); + + props = ctx.toProperties(); + LOG.info("SvcLogicContext after executing "+testCaseMethod+":"); + for (Enumeration e2 = props.propertyNames(); e2.hasMoreElements() ; ) { + String propName = (String) e2.nextElement(); + LOG.info(propName+" = "+props.getProperty(propName)); + } + } + } + + } + + + } + + + } catch (Exception e) { + LOG.error("Caught exception executing directed graphs", e); + fail("Exception executing graphs"); + } + } + + +} diff --git a/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/VoidDummyPlugin.java b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/VoidDummyPlugin.java new file mode 100644 index 00000000..6c8214ab --- /dev/null +++ b/sli/provider/src/test/java/org/openecomp/sdnc/sli/provider/VoidDummyPlugin.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.provider; + +import java.util.Map; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; + + + +public class VoidDummyPlugin implements SvcLogicJavaPlugin { + + public void dummy(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + return; + } + +} diff --git a/sli/provider/src/test/resources/executor.tests b/sli/provider/src/test/resources/executor.tests new file mode 100755 index 00000000..e7547e63 --- /dev/null +++ b/sli/provider/src/test/resources/executor.tests @@ -0,0 +1,2 @@ +l3sdn_logic_v10.xml:switchTester:test-value="" +l3sdn_logic_v10.xml:switchTester:test-value="hi"
\ No newline at end of file diff --git a/sli/provider/src/test/resources/expression.tests b/sli/provider/src/test/resources/expression.tests new file mode 100755 index 00000000..848a0e7a --- /dev/null +++ b/sli/provider/src/test/resources/expression.tests @@ -0,0 +1,24 @@ +# $uni-circuit-id = abc123 +# $uni-cir-units = 10 +# value = 1 +# $arg1 = 2 +# $network.name = vCE0001.in +# $network.segment[0].provider-segmentation-id = 1212 +# $network.segment[1].provider-segmentation-id = 1213 +# $availability-zone = mtsnj-esx-az01 +length($uni-circuit-id) > 0 # true +$uni-cir-units * 1000 * 100 / 100 # 10000 +$uni-cir-units / 1000 # 0 +$uni-cir-units - 100 # -90 +$uni-cir-units + 100 # 110 +(value * 3 - $arg1 > 0) and (length($uni-circuit-id) == 0) # true +'pg-'+$network.name # pg-vCE0001.in +$network.segment[0].provider-segmentation-id # 1212 +toUpperCase($network.name) # VCE0001.IN +toLowerCase($network.name) # vce0001.in +toUpperCase(substr($availability-zone, 0, 5)) # MTSNJ +convertBase(1234, 10) # 1234 +convertBase(10, 16, 10) # 16 +convertBase(ZZ, 36, 10) # 1295 +convertBase(10, 10, 36) # a +(0 - 1) * $arg1 # -1 diff --git a/sli/provider/src/test/resources/l3sdn_logic_v10.xml b/sli/provider/src/test/resources/l3sdn_logic_v10.xml new file mode 100644 index 00000000..d81b8b78 --- /dev/null +++ b/sli/provider/src/test/resources/l3sdn_logic_v10.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<service-logic xmlns="http://www.openecomp.org/sdnc/svclogic" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openecomp.org/sdnc/svclogic ./svclogic.xsd" + module="neutron" version="1.0.0"> + + <method rpc="canCreateNetwork" mode="sync"> + <return status="success"> + <parameter name="error-code" value="200" /> + </return> + </method> + + <method rpc="switchTester" mode="sync"> + + <switch test="`$test-value`"> + <outcome value=""> + <return status="success"> + <parameter name="visited-outcome" value="empty string" /> + </return> + </outcome> + <outcome value="Other"> + <return status="success"> + <parameter name="visited-outcome" value="Other" /> + </return> + </outcome> + </switch> + + + </method> + + <method rpc="networkCreated" mode="sync"> + <switch test="length($network.segment[0].provider-physical-network) >= 5 and substr($network.segment[0].provider-physical-network,0,5) == 'dvspg'"> + <outcome value="true"> + <block> + <set> + <parameter name="$vlanlist" value="$network.segment[0].provider-segmentation-id"/> + </set> + <for index="i" start="1" end="$network.num-segments"> + <set> + <parameter name="$vlanlist" value="eval($vlanlist+','+$network.segment[i].provider-segmentation-id)"/> + </set> + </for> + + </block> + </outcome> + <outcome value="Other"> + <return status="success"> + <parameter name="error-code" value="200"/> + </return> + </outcome> + </switch> + </method> + +</service-logic> diff --git a/sli/provider/src/test/resources/simplelogger.properties b/sli/provider/src/test/resources/simplelogger.properties new file mode 100644 index 00000000..3581395a --- /dev/null +++ b/sli/provider/src/test/resources/simplelogger.properties @@ -0,0 +1,22 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.slf4j.simpleLogger.defaultLogLevel=info diff --git a/sli/provider/src/test/resources/svclogic.properties b/sli/provider/src/test/resources/svclogic.properties new file mode 100644 index 00000000..fa33146e --- /dev/null +++ b/sli/provider/src/test/resources/svclogic.properties @@ -0,0 +1,26 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.openecomp.sdnc.sli.dbtype = jdbc +org.openecomp.sdnc.sli.jdbc.url = jdbc:mysql://localhost:3306/sdnctl +org.openecomp.sdnc.sli.jdbc.database = sdnctl +org.openecomp.sdnc.sli.jdbc.user = sdnctl +org.openecomp.sdnc.sli.jdbc.password = gamma diff --git a/sli/recording/pom.xml b/sli/recording/pom.xml new file mode 100755 index 00000000..4fb4a797 --- /dev/null +++ b/sli/recording/pom.xml @@ -0,0 +1,77 @@ +<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sli-recording</artifactId> + <packaging>bundle</packaging> + <name>SLI - Recording</name> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>${equinox.osgi.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${slf4j.version}</version> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>compile</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>${bundle.plugin.version}</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator>org.openecomp.sdnc.sli.recording.RecordingActivator</Bundle-Activator> + <Export-Package>org.openecomp.sdnc.sli.recording;version=${project.version}</Export-Package> + <Import-Package>*</Import-Package> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + + + </configuration> + + </plugin> + + + </plugins> + </build> + <description>SLI Recording is an OSGi bundle that implements recording service for the service logic record node.</description> +</project> diff --git a/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/FileRecorder.java b/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/FileRecorder.java new file mode 100644 index 00000000..dc857b25 --- /dev/null +++ b/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/FileRecorder.java @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.recording; + +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.TimeZone; + +import org.openecomp.sdnc.sli.ConfigurationException; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicRecorder; + + +public class FileRecorder implements SvcLogicRecorder { + + @Override + public void record(Map<String, String> parmMap) throws SvcLogicException { + + String fileName = parmMap.get("file"); + if (fileName == null) + { + throw new ConfigurationException("No file parameter specified"); + } + + String record = parmMap.get("record"); + if (record == null) + { + String delimiter = parmMap.get("delimiter"); + if (delimiter == null) + { + delimiter = "|"; + } + + int idx = 1; + boolean moreFields = true; + while (moreFields) + { + String curField = parmMap.get("field"+idx++); + if (curField == null) + { + moreFields = false; + } + else + { + if (record == null) + { + record = delimiter; + } + record = record + curField + delimiter; + } + } + } + + if (record == null) + { + throw new ConfigurationException("No record/fields passed in record node"); + } + + File recordFile = new File(fileName); + PrintWriter recPrinter = null; + Date now = new Date(); + + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat dateFmt = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss:SS'+00:00'"); + dateFmt.setTimeZone(tz); + if (record.indexOf("__TIMESTAMP__") != -1) + { + record = record.replaceFirst("__TIMESTAMP__", dateFmt.format(now)); + } + + try + { + + recPrinter = new PrintWriter(new FileWriter(recordFile, true)); + recPrinter.println(record); + } + catch (Exception e) + { + throw new SvcLogicException("Cannot write record to file", e); + } + finally + { + if (recPrinter != null) + { + recPrinter.close(); + } + } + + + } + +} + diff --git a/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/RecordingActivator.java b/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/RecordingActivator.java new file mode 100644 index 00000000..d6e016af --- /dev/null +++ b/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/RecordingActivator.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.recording; + +import java.util.LinkedList; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class RecordingActivator implements BundleActivator { + + private LinkedList<ServiceRegistration> registrations = new LinkedList<ServiceRegistration>(); + + private static final Logger LOG = LoggerFactory + .getLogger(RecordingActivator.class); + + @Override + public void start(BundleContext ctx) throws Exception { + + if (registrations == null) + { + registrations = new LinkedList<ServiceRegistration>(); + } + + + FileRecorder fileRecorder = new FileRecorder(); + String regName = fileRecorder.getClass().getName(); + LOG.debug("Registering FileRecorder service "+regName); + ServiceRegistration reg =ctx.registerService(regName, fileRecorder, null); + registrations.add(reg); + + Slf4jRecorder slf4jRecorder = new Slf4jRecorder(); + regName = slf4jRecorder.getClass().getName(); + LOG.debug("Registering Slf4jRecorder service "+regName); + reg =ctx.registerService(regName, slf4jRecorder, null); + registrations.add(reg); + + } + + @Override + public void stop(BundleContext arg0) throws Exception { + if (registrations != null) { + for (ServiceRegistration reg : registrations) { + ServiceReference regRef = reg.getReference(); + reg.unregister(); + } + registrations = null; + } + } + +} diff --git a/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/Slf4jRecorder.java b/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/Slf4jRecorder.java new file mode 100644 index 00000000..5aad6f25 --- /dev/null +++ b/sli/recording/src/main/java/org/openecomp/sdnc/sli/recording/Slf4jRecorder.java @@ -0,0 +1,130 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.recording; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.TimeZone; + +import org.openecomp.sdnc.sli.ConfigurationException; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicRecorder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Slf4jRecorder implements SvcLogicRecorder { + + + public enum Level { + ERROR, + WARN, + INFO, + DEBUG, + TRACE + } + + @Override + public void record(Map<String, String> parmMap) throws SvcLogicException { + String loggerName = parmMap.get("logger"); + if (loggerName == null) { + loggerName = "Log4jRecorder"; + } + + String lvl = parmMap.get("level"); + if (lvl == null) { + lvl = "INFO"; + } + + Level level = Level.INFO; + + try { + level = Level.valueOf(lvl.toUpperCase()); + } catch (Exception e) {} + + + + String record = parmMap.get("record"); + if (record == null) + { + String delimiter = parmMap.get("delimiter"); + if (delimiter == null) + { + delimiter = "|"; + } + + int idx = 1; + boolean moreFields = true; + while (moreFields) + { + String curField = parmMap.get("field"+idx++); + if (curField == null) + { + moreFields = false; + } + else + { + if (record == null) + { + record = delimiter; + } + record = record + curField + delimiter; + } + } + } + + if (record == null) + { + throw new ConfigurationException("No record/fields passed in record node"); + } + + Logger logger = LoggerFactory.getLogger(loggerName); + + Date now = new Date(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat dateFmt = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss:SS'+00:00'"); + dateFmt.setTimeZone(tz); + if (record.indexOf("__TIMESTAMP__") != -1) + { + record = record.replaceFirst("__TIMESTAMP__", dateFmt.format(now)); + } + + switch (level) { + case ERROR: + logger.error(record); + break; + case WARN: + logger.warn(record); + break; + case INFO: + logger.info(record); + break; + case DEBUG: + logger.debug(record); + break; + case TRACE: + logger.trace(record); + } + } + +} diff --git a/sli/recording/src/main/resources/svclogic.properties b/sli/recording/src/main/resources/svclogic.properties new file mode 100644 index 00000000..0cf3b419 --- /dev/null +++ b/sli/recording/src/main/resources/svclogic.properties @@ -0,0 +1,26 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.openecomp.sdnc.sli.dbtype = jdbc +org.openecomp.sdnc.sli.jdbc.url = jdbc:mysql://dbhost:3306/sdnctl +org.openecomp.sdnc.sli.jdbc.database = sdnctl +org.openecomp.sdnc.sli.jdbc.user = sdnctl +org.openecomp.sdnc.sli.jdbc.password = gamma diff --git a/sliPluginUtils/.gitignore b/sliPluginUtils/.gitignore new file mode 100755 index 00000000..b73caf31 --- /dev/null +++ b/sliPluginUtils/.gitignore @@ -0,0 +1,34 @@ +#####standard .git ignore entries##### + +## IDE Specific Files ## +org.eclipse.core.resources.prefs +.classpath +.project +.settings +.idea +.externalToolBuilders +maven-eclipse.xml +workspace + +## Compilation Files ## +*.class +**/target +target +target-ide +MANIFEST.MF + +## Misc Ignores (OS specific etc) ## +bin/ +dist +*~ +*.ipr +*.iml +*.iws +classes +out/ +.DS_STORE +.metadata + +## Folders which contain auto generated source code ## +yang-gen-config +yang-gen-sal diff --git a/sliPluginUtils/.sonar/checkstyle.xml b/sliPluginUtils/.sonar/checkstyle.xml new file mode 100755 index 00000000..3fa23153 --- /dev/null +++ b/sliPluginUtils/.sonar/checkstyle.xml @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd"><!-- Generated by Sonar --><module name="Checker"><module name="SuppressionCommentFilter"/><module name="TreeWalker"><module name="FileContentsHolder"/> <module name="ClassFanOutComplexity"><property name="severity" value="warning"/></module><module name="NestedForDepth"><property name="severity" value="warning"/><property name="max" value="1"/></module><module name="ClassDataAbstractionCoupling"><property name="severity" value="warning"/></module></module></module>
\ No newline at end of file diff --git a/sliPluginUtils/.sonar/pmd.xml b/sliPluginUtils/.sonar/pmd.xml new file mode 100755 index 00000000..80343b3b --- /dev/null +++ b/sliPluginUtils/.sonar/pmd.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+ <rule ref="rulesets/java/naming.xml/BooleanGetMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/StaticEJBFieldShouldBeFinal">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/CouplingBetweenObjects">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyMethods">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingTypeName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/DoubleCheckedLocking">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/ExcessiveImports">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/OverrideBothEqualsAndHashcode">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/ShortMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/BooleanInstantiation">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyFields">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/controversial.xml/AvoidUsingNativeCode">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/optimizations.xml/UseStringBufferForStringAppends">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/LooseCoupling">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/NonThreadSafeSingleton">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/DoNotUseThreads">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/ArrayIsStoredDirectly">
+ <priority>5</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/MethodReturnsInternalArray">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/AssignmentToNonFinalStatic">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/strictexception.xml/AvoidCatchingGenericException">
+ <priority>3</priority>
+ </rule>
+</ruleset>
+
diff --git a/sliPluginUtils/features/pom.xml b/sliPluginUtils/features/pom.xml new file mode 100755 index 00000000..9d189177 --- /dev/null +++ b/sliPluginUtils/features/pom.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <artifactId>sliPluginUtils-features</artifactId> + <packaging>jar</packaging> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>sliPluginUtils</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <name>SliPluginUtils Plugin - Features</name> + + <dependencies> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliPluginUtils-provider</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <version>${odl.mdsal.features.version}</version> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + <!-- dependency for opendaylight-karaf-empty for use by testing --> + <dependency> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>opendaylight-karaf-empty</artifactId> + <version>${odl.karaf.empty.distro.version}</version> + <type>zip</type> + </dependency> + <dependency> + <!-- Required for launching the feature tests --> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>features-test</artifactId> + <version>${odl.commons.opendaylight.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>features-yangtools</artifactId> + <version>${odl.yangtools.version}</version> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + + <!-- launches the feature test, which validates that your karaf feature + can be installed inside of a karaf container. It doesn't validate that your + functionality works correctly, just that you have all of the dependent bundles + defined correctly. + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.16</version> + <configuration> + <systemPropertyVariables> + <karaf.distro.groupId>org.opendaylight.odlparent</karaf.distro.groupId> + <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> + <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> + </systemPropertyVariables> + <dependenciesToScan> + <dependency>org.opendaylight.yangtools:features-test</dependency> + </dependenciesToScan> + </configuration> + </plugin> + --> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/sliPluginUtils/features/src/main/resources/features.xml b/sliPluginUtils/features/src/main/resources/features.xml new file mode 100644 index 00000000..c7dca2e5 --- /dev/null +++ b/sliPluginUtils/features/src/main/resources/features.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<features name="sdnc-sliPluginUtils-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features</repository> + + + <feature name='sdnc-sliPluginUtils' description="sdnc-sliPluginUtils" version='${project.version}'> + <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> + <feature version="${odl.mdsal.version}">odl-mdsal-broker</feature> + <feature>sdnc-sli</feature> + <bundle>mvn:org.openecomp.sdnc.core/sliPluginUtils-provider/${project.version}</bundle> + <bundle>mvn:mysql/mysql-connector-java/${mysql.connector.version}</bundle> + </feature> + +</features> diff --git a/sliPluginUtils/installer/pom.xml b/sliPluginUtils/installer/pom.xml new file mode 100755 index 00000000..6520867b --- /dev/null +++ b/sliPluginUtils/installer/pom.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sliPluginUtils</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sliPluginUtils-installer</artifactId> + <name>SLI Plugin Utilities - Karaf Installer</name> + <packaging>pom</packaging> + + <properties> + <application.name>sdnc-sliPluginUtils</application.name> + <features.boot>sdnc-sliPluginUtils</features.boot> + <features.repositories>mvn:org.openecomp.sdnc.core/sliPluginUtils-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencies> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliPluginUtils-features</artifactId> + <version>${project.version}</version> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliPluginUtils-provider</artifactId> + <version>${project.version}</version> + </dependency> + + + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${application.name}-${project.version}-installer</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeGroupIds>org.openecomp.sdnc</includeGroupIds> + <excludeArtifactIds>sli-common,sli-provider,dblib-provider</excludeArtifactIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals><!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml b/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 00000000..85e2e1e8 --- /dev/null +++ b/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,59 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml b/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 00000000..bf7805f7 --- /dev/null +++ b/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,49 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh b/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 00000000..93236c5b --- /dev/null +++ b/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/sliPluginUtils/pom.xml b/sliPluginUtils/pom.xml new file mode 100755 index 00000000..a14b41ff --- /dev/null +++ b/sliPluginUtils/pom.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliPluginUtils</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>pom</packaging> + <modelVersion>4.0.0</modelVersion> + + + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sdnc-core</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <name>Service Logic Interface Plugin Utilities</name> + <description>A package of static utility functions to be used when developing SLI plugins</description> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>SliPluginUtils-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>SliPluginUtils-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </dependencyManagement> + + <modules> + <module>provider</module> + <module>features</module> + <module>installer</module> + </modules> +</project> diff --git a/sliPluginUtils/provider/pom.xml b/sliPluginUtils/provider/pom.xml new file mode 100755 index 00000000..cad7a0bc --- /dev/null +++ b/sliPluginUtils/provider/pom.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <artifactId>sliPluginUtils-provider</artifactId> + <packaging>bundle</packaging> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliPluginUtils</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <name>SliPluginUtils Plugin - Provider</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>${equinox.osgi.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.1</version> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + <version>1.3</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>${bundle.plugin.version}</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>org.openecomp.sdnc.sli.SliPluginUtils</Bundle-SymbolicName> + <Bundle-Activator>org.openecomp.sdnc.sli.SliPluginUtils.SliPluginUtilsActivator</Bundle-Activator> + <Export-Package>org.openecomp.sdnc.sli.SliPluginUtils</Export-Package> + <Import-Package>org.openecomp.sdnc.*,org.osgi.framework.*,org.slf4j.*,java.net.*</Import-Package> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|mysql-connector-java|slf4j-api|jcl-over-slf4j</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + </plugin> + + </plugins> + + </build> +</project> diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/DME2.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/DME2.java new file mode 100644 index 00000000..39612716 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/DME2.java @@ -0,0 +1,111 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import java.util.Map; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +/** + * A SvcLogicJavaPlugin that generates DME2 proxy urls using parameters from context memory. + */ +public class DME2 implements SvcLogicJavaPlugin { + String aafUserName; + String aafPassword; + String envContext; + String routeOffer; + String[] proxyUrls; + Integer index; + String commonServiceVersion; + String partner; + + private static final Logger LOG = LoggerFactory.getLogger(DME2.class); + + public void setPartner(String partner) { + if (partner != null && partner.length() > 0) { + this.partner = partner; + } + } + + public DME2(String aafUserName, String aafPassword, String envContext, String routeOffer, String[] proxyUrls, String commonServiceVersion) { + this.aafUserName = aafUserName; + this.aafPassword = aafPassword; + this.envContext = envContext; + this.routeOffer = routeOffer; + this.proxyUrls = proxyUrls; + this.index = 0; + this.commonServiceVersion = commonServiceVersion; + } + + // constructs a URL to contact the proxy which contacts a DME2 service + public String constructUrl(String service, String version, String subContext) { + StringBuilder sb = new StringBuilder(); + + // The hostname is assigned in a round robin fashion + sb.append(acquireHostName()); + sb.append("/service=" + service); + + //If the directedGraph passes an explicit version use that, if not use the commonServiceVersion found in the properties file + if (version == null) { + version = this.commonServiceVersion; + } + sb.append("/version=" + version); + + sb.append("/envContext=" + this.envContext); + if (this.routeOffer != null && this.routeOffer.length() > 0) { + sb.append("/routeOffer=" + this.routeOffer); + } + if (subContext != null && subContext.length() > 0) { + sb.append("/subContext=" + subContext); + } + sb.append("?dme2.password=" + this.aafPassword); + sb.append("&dme2.username=" + this.aafUserName); + if (this.partner != null) { + sb.append("&dme2.partner=" + this.partner); + } + sb.append("&dme2.allowhttpcode=true"); + return (sb.toString()); + } + + public synchronized String acquireHostName() { + String retVal = proxyUrls[index]; + index++; + if (index == this.proxyUrls.length) { + index = 0; + } + return retVal; + } + + // Node entry point + public void constructUrl(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[] { "service", "outputPath" }, LOG); + String completeProxyUrl = constructUrl(parameters.get("service"), parameters.get("version"), parameters.get("subContext")); + ctx.setAttribute(parameters.get("outputPath"), completeProxyUrl); + } + +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils.java new file mode 100644 index 00000000..c73315f4 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils.java @@ -0,0 +1,754 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A utility class used to streamline the interface between Java plugins, + * the Service Logic Context, and Directed Graphs. + * @version 7.0.1 + * @see org.openecomp.sdnc.sli.SvcLogicContext + */ +public class SliPluginUtils implements SvcLogicJavaPlugin { + public enum LogLevel { + TRACE, DEBUG, INFO, WARN, ERROR; + } + + private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils.class); + + + // ========== CONSTRUCTORS ========== + + public SliPluginUtils() {} + + public SliPluginUtils( Properties props ) {} + + + + // ========== CONTEXT MEMORY FUNCTIONS ========== + + /** + * Removes 1 or more elements from a list in context memory. + * <p> + * Values are removed based on either the index in the list, a key-value + * pair, or a list of key-value pairs that all must match in the element. + * @param parameters + * @param ctx Reference to context memory + * @throws SvcLogicException All exceptions are wrapped in + * SvcLogicException for compatibility with SLI. + * @since 7.0.1 + */ + public void ctxListRemove( Map<String,String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + try{ + LOG.debug( "ENTERING Execute Node \"ctxListRemove\"" ); + + // Validate, Log, & read parameters + checkParameters(parameters, new String[]{"list_pfx"}, LOG); + logExecuteNodeParameters(parameters, LOG, LogLevel.DEBUG); + String list_pfx = parameters.get("list_pfx"); + String param_index = parameters.get("index"); + String param_key = parameters.get("key"); + String param_value = parameters.get("value"); + String param_keys_length = parameters.get("keys_length"); + + // Initialize context memory list mimic + SvcLogicContextList list; + + // Process based on input parameters: + // index: remove object at specific index + // key & value: remove all objects with key-value pair + // keys_length: remove all objects that match all key-value pairs + // in list + if( param_index != null ) { + // Parse index + LOG.trace("executing remove by index logic"); + int index; + try { + index = Integer.parseInt(param_index); + } + catch( NumberFormatException e ) { + throw new IllegalArgumentException("\"index\" parameter is not a number. index = " + param_index, e); + } + + // Extract list from context memory & remove object @ index + LOG.trace("extracting list from context memory"); + list = SvcLogicContextList.extract(ctx, list_pfx); + LOG.trace("removing elements from list"); + list.remove(index); + } + else if( param_value != null ) { + if( param_key == null ) { param_key = ""; } + + // Extract list from context memory & remove objects with + // key-value pair + LOG.trace("executing remove by key-value pair logic"); + LOG.trace("extracting list from context memory"); + list = SvcLogicContextList.extract(ctx, list_pfx); + LOG.trace("removing elements from list"); + list.remove( param_key, param_value ); + } + else if( param_keys_length != null ) { + // Parse keys_length + LOG.trace("executing remove by key-value pair list logic"); + int keys_length; + try { + keys_length = Integer.parseInt(param_keys_length); + } + catch( NumberFormatException e ) { + throw new IllegalArgumentException("\"keys_length\" parameters is not a number. keys_length = " + param_keys_length, e); + } + + // Obtain key-value pairs to check from parameters + LOG.trace("reading keys parameter list"); + HashMap<String,String> keys_values = new HashMap<String,String>(); + for( int i = 0; i < keys_length; i++ ) { + keys_values.put(parameters.get("keys[" + i + "].key"), parameters.get("keys[" + i + "].value")); + } + + // Extract list from context memory & remove objects with all + // key-value pairs matching + LOG.trace("extracting list from context memory"); + list = SvcLogicContextList.extract(ctx, list_pfx); + LOG.trace("removing elements from list"); + list.remove(keys_values); + } + else { + throw new IllegalArgumentException("Required parameters missing. Requires one of: index, key & value, or keys_length array"); + } + + // Remove index from list + LOG.trace("writing list back into context memory"); + list.writeToContext(ctx); + } + catch( Exception e ) { + throw new SvcLogicException( "An error occurred in the ctxListRemove Execute node", e ); + } + finally { + LOG.debug( "EXITING Execute Node \"ctxListRemove\"" ); + } + } + + /** + * ctxSortList + * @param parameters - the set of required parameters must contain list and delimiter. + * @param ctx Reference to context memory + * @throws SvcLogicException if a required parameter is missing an exception is thrown + */ + public void ctxSortList( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + checkParameters(parameters, new String[]{"list","delimiter"}, LOG); + ArrayList<SortableCtxListElement> list = new ArrayList<SortableCtxListElement>(); + + String[] sort_fields = null; + if( parameters.containsKey("sort-fields") ) { + sort_fields = parameters.get("sort-fields").split(parameters.get("delimiter"), 0); + } + + String ctx_list_str = parameters.get("list"); + int listSz = getArrayLength(ctx, ctx_list_str); + + + + for( int i = 0; i < listSz; i++ ) { + list.add( new SortableCtxListElement(ctx, ctx_list_str + '[' + i + ']', sort_fields) ); + } + Collections.sort(list); + + ctxBulkErase(ctx, ctx_list_str); + int i = 0; + for( SortableCtxListElement list_element : list ) { + for( Map.Entry<String,String> entry : list_element.child_elements.entrySet() ) { + if( sort_fields == null ) { + ctx.setAttribute(ctx_list_str + '[' + i + ']', entry.getValue()); + } + else { + ctx.setAttribute(ctx_list_str + '[' + i + "]." + entry.getKey(), entry.getValue()); + } + } + i++; + } + // Reset list length (removed by ctxBulkErase above) + ctx.setAttribute(ctx_list_str+"_length", ""+listSz); + } + + /** + * generates a UUID and writes it to context memory + * @param parameters - ctx-destination is a required parameter + * @param ctx Reference to context memory + * @throws SvcLogicException thrown if a UUID cannot be generated or if ctx-destination is missing or null + */ + public void generateUUID( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + checkParameters(parameters, new String[]{"ctx-destination"}, LOG); + ctx.setAttribute(parameters.get("ctx-destination"), UUID.randomUUID().toString() ); + } + + /** + * Provides substring functionality to Directed Graphs. + * <p> + * Calls either String.substring(String beginIndex) or + * String.substring(String beginInded, String endIndex) if the end-index + * is present or not. + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>string</td><td>Mandatory</td><td>String to perform substring on</td></tr> + * <tr><td>result</td><td>Mandatory</td><td>Key in context memory to populate the resulting string in</td></tr> + * <tr><td>begin-index</td><td>Mandatory</td><td>Beginning index to pass to Java substring function</td></tr> + * <tr><td>end-index</td><td>Optional</td><td>Ending index to pass to Java substring function. If not included, String.substring(begin) will be called.</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 8.0.1 + * @see SliPluginUtils#substring(Map, SvcLogicContext) + */ + @Deprecated + public void substring( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + try { + checkParameters( parameters, new String[]{"string","begin-index","result"}, LOG ); + final String string = parameters.get("string"); + final String result = parameters.get("result"); + final String begin = parameters.get("begin-index"); + final String end = parameters.get("end-index"); + + if( StringUtils.isEmpty(end) ) { + ctx.setAttribute( result, string.substring(Integer.parseInt(begin)) ); + } + else { + ctx.setAttribute( result, string.substring(Integer.parseInt(begin), Integer.parseInt(end)) ); + } + } + catch( Exception e ) { + throw new SvcLogicException( "An error occurred while the Directed Graph was performing a substring", e ); + } + } + + + + // ========== PUBLIC STATIC UTILITY FUNCTIONS ========== + + /** + * Throws an exception and writes an error to the log file if a required + * parameters is not found in the parametersMap. + * <p> + * Use at the beginning of functions that can be called by Directed Graphs + * and can take parameters to verify that all parameters have been provided + * by the Directed Graph. + * @param parametersMap parameters Map passed to this node + * @param requiredParams Array of parameters required by the calling function + * @param log Reference to Logger to log to + * @throws SvcLogicException if a String in the requiredParams array is + * not a key in parametersMap. + * @since 1.0 + */ + public static final void checkParameters(Map<String, String> parametersMap, String[] requiredParams, Logger log) throws SvcLogicException { + if( requiredParams == null || requiredParams.length < 1){ + log.debug("required parameters was empty, exiting early."); + return; + } + if (parametersMap == null || parametersMap.keySet().size() < 1){ + String errorMessage = "This method requires the parameters [" + StringUtils.join(requiredParams,",") + "], but no parameters were passed in."; + log.error(errorMessage); + throw new SvcLogicException(errorMessage); + } + + for (String param : requiredParams) { + if (!parametersMap.containsKey(param)) { + String errorMessage = "Required parameter \"" + param + "\" was not found in parameter list."; + log.error(errorMessage); + log.error("Total list of required parameters is [" + StringUtils.join(requiredParams, ",") + "]."); + throw new SvcLogicException(errorMessage); + } + } + } + + /** + * Removes all key-value pairs with keys that begin with pfx + * @param ctx Reference to context memory + * @param pfx Prefix of key-value pairs to remove + * @since 1.0 + */ + public static final void ctxBulkErase( SvcLogicContext ctx, String pfx ) { + ArrayList<String> Keys = new ArrayList<String>( ctx.getAttributeKeySet() ); + for( String key : Keys ) { + if( key.startsWith( pfx ) ) { + ctx.setAttribute( pfx + key.substring(pfx.length()) , null); + } + } + } + + /** + * Copies all context memory key-value pairs that start with src_pfx to + * the keys that start with dest_pfx + suffix, where suffix is the result + * of {@code key.substring(src_pfx.length())}. + * <p> + * Does NOT guarantee removal of all keys at the destination before + * copying, but will overwrite any destination keys that have a + * corresponding source key. Use {@link #ctxBulkErase(SvcLogicContext, String) ctxBulkErase} + * before copy to erase destination root before copying from source. + * @param ctx Reference to context memory. + * @param src_pfx Prefix of the keys to copy values from. + * @param dest_pfx Prefix of the keys to copy values to. + * @since 1.0 + */ + public static final void ctxBulkCopy( SvcLogicContext ctx, String src_pfx, String dest_pfx ) { + // Remove trailing period from dest_pfx + if( dest_pfx.charAt(dest_pfx.length()-1) == '.' ) { + dest_pfx = dest_pfx.substring(0,dest_pfx.length()-1); + } + + // For each context key that begins with src_pfx, set the value of the + // key dest_pfx + the suffix of the key to the key's value + ArrayList<String> Keys = new ArrayList<String>(ctx.getAttributeKeySet()); + for( String key : Keys ) { + if( key.startsWith(src_pfx) ) { + // Get suffix (no leading period) + String suffix = key.substring(src_pfx.length()); + if( suffix.charAt(0) == '.') { + suffix = suffix.substring(1); + } + + // Set destination's value to key's value + ctx.setAttribute(dest_pfx + '.' + suffix, ctx.getAttribute(key)); + } + } + } + + /** + * Creates and returns a {@code Map<String, String>} that is a subset of + * context memory where all keys begin with the prefix. + * @param ctx Reference to context memory. + * @param prefix Returned map's keys should all begin with this value. + * @return A {@code Map<String, String>} containing all the key-value pairs + * in ctx whose key begins with prefix. + */ + public static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) { + Map<String, String> prefixMap = new HashMap<String, String>(); + + for( String key : ctx.getAttributeKeySet() ) { + if( key.startsWith(prefix) ) { + prefixMap.put( key, ctx.getAttribute(key) ); + } + } + + return prefixMap; + } + + /** + * Returns true if key's value in context memory is "" or if it doesn't + * exist in context memory. + * @param ctx Reference to context memory. + * @param key Key to search for. + * @return true if key's value in context memory is "" or if it doesn't + * exist in context memory. + * @since 1.0 + */ + public static final boolean ctxKeyEmpty( SvcLogicContext ctx, String key ) { + String value = ctx.getAttribute(key); + return value == null || value.isEmpty(); + } + + /** + * Adds all key-value pairs in the entries Map to context memory. + * @param ctx Reference to context memory. Value's {@code toString()} + * function is used to add it. + * @param entries {@code Map<String, ?>} of key-value pairs to add to + * context memory. Value's {@code toString()} function is used to add it. + * @return Reference to context memory to be used for function chaining. + */ + public static final SvcLogicContext ctxPutAll( SvcLogicContext ctx, Map<String, ?> entries ) { + for( Map.Entry<String, ?> entry : entries.entrySet() ) { + ctxSetAttribute( ctx, entry.getKey(), entry.getValue() ); + //ctx.setAttribute(entry.getKey(), entry.getValue().toString()); + } + + return ctx; + } + + /** + * Sets a key in context memory to the output of object's toString(). The + * key is deleted from context memory if object is null. + * @param ctx Reference to context memory. + * @param key Key to set. + * @param object Object whose toString() will be the value set + */ + public static final void ctxSetAttribute( SvcLogicContext ctx, String key, Object object ) { + if( object == null ) { + ctx.setAttribute(key, null); + } + else { + ctx.setAttribute(key, object.toString()); + } + } + + /** + * Sets a key in context memory to the output of object's toString(). + * <p> + * The key is deleted from context memory if object is null. The key and + * value set in context memory are logged to the Logger at the provided + * logLevel level. + * @param <O> Any Java object + * @param ctx Reference to context memory. + * @param key Key to set. + * @param obj Object whose toString() will be the value set + * @param LOG Logger to log to + * @param logLevel level to log at in Logger + */ + public static final <O extends Object> void ctxSetAttribute( SvcLogicContext ctx, String key, O obj, Logger LOG, LogLevel logLevel ) { + String value = Objects.toString( obj, null ); + ctx.setAttribute( key, value ); + if( logLevelIsEnabled(LOG, logLevel ) ) { + if( value == null ) { + logMessageAtLevel( LOG, logLevel, "Deleting " + key ); + } + else { + logMessageAtLevel( LOG, logLevel, "Setting " + key + " = " + value ); + } + } + } + + /** + * Utility function used to get an array's length from context memory. + * Will return 0 if key doesn't exist in context memory or isn't numeric. + * <p> + * Use to obtain a context memory array length without having to worry + * about throwing a NumberFormatException. + * @param ctx Reference to context memory + * @param key Key in context memory whose value is the array's length. If + * the key doesn't end in "_length", then "_length is appended. + * @param log Reference to Logger to log to + * @return The array length or 0 if the key is not found in context memory. + * @since 1.0 + */ + public static final int getArrayLength( SvcLogicContext ctx, String key ) { + return getArrayLength(ctx, key, null, null, null); + } + + /** + * Utility function used to get an array's length from context memory. + * Will return 0 if key doesn't exist in context memory or isn't numeric + * and print the provided log message to the configured log file. + * <p> + * Use to obtain a context memory array length without having to worry + * about throwing a NumberFormatException. + * @param ctx Reference to context memory. + * @param key Key in context memory whose value is the array's length. If + * the key doesn't end in "_length", then "_length is appended. + * @param log Reference to Logger to log to. Doesn't log if null. + * @param logLevel Logging level to log the message at if the context + * memory key isn't found. Doesn't log if null. + * @param log_message Message to log if the context memory key isn't found. + * Doesn't log if null. + * @return The array length or 0 if the key is not found in context memory. + * @since 1.0 + */ + public static final int getArrayLength( SvcLogicContext ctx, String key, Logger log, LogLevel logLevel, String log_message ) { + String ctxKey = ( key.endsWith("_length") ) ? key : key + "_length"; + try { + return Integer.parseInt(ctx.getAttribute(ctxKey)); + } + catch( NumberFormatException e ) { + if( log != null && logLevel != null && log_message != null ) { + switch( logLevel ) { + case TRACE: + log.trace(log_message); + case DEBUG: + log.debug(log_message); + break; + case INFO: + log.info(log_message); + break; + case WARN: + log.warn(log_message); + break; + case ERROR: + log.error(log_message); + break; + } + } + } + + return 0; + } + + /** + * Prints sorted context memory key-value pairs to the log file at the log + * level. Returns immediately if the log level isn't enabled. + * <p> + * O(n log(n)) time where n = size of context memory + * @param ctx Reference to context memory + * @param log Reference to Logger to log to + * @param logLevel Logging level to log the context memory key-value pairs + * at. + * @since 1.0 + */ + public static final void logContextMemory( SvcLogicContext ctx, Logger log, LogLevel logLevel ) { + logLevelIsEnabled( log, logLevel ); + + // Print sorted context memory key-value pairs to the log + ArrayList<String> keys = new ArrayList<String>(ctx.getAttributeKeySet()); + Collections.sort(keys); + for( String key : keys ) { + logMessageAtLevel( log, logLevel, key + " = " + ctx.getAttribute(key) ); + } + } + + + + // ========== PRIVATE FUNCTIONS ========== + + // TODO: javadoc + /** + * + * @param parameters + * @param log + * @param loglevel + * @since 7.0.1 + */ + public static final void logExecuteNodeParameters( Map<String,String> parameters, Logger log, LogLevel loglevel ) { + logLevelIsEnabled( log, loglevel ); + + for( Map.Entry<String,String> param : parameters.entrySet() ) { + logMessageAtLevel( log, loglevel, "PARAM: " + param.getKey() + " = " + param.getValue() ); + } + } + + // TODO: javadoc + /** + * Returns true if the loglevel is enabled. Otherwise, returns false. + * @param log Reference to logger + * @param loglevel Log level to check if enabled + * @return True if the loglevel is enabled. Otherwise, false + * @since 7.0.1 + */ + private static final boolean logLevelIsEnabled( Logger log, LogLevel loglevel ) { + // Return immediately if logging level isn't enabled + switch( loglevel ) { + case TRACE: + if( log.isTraceEnabled() ) { return true; } + return false; + case DEBUG: + if( log.isDebugEnabled() ) { return true; } + return false; + case INFO: + if( log.isInfoEnabled() ) { return true; } + return false; + case WARN: + if( log.isWarnEnabled() ) { return true; } + return false; + case ERROR: + if( log.isErrorEnabled() ) { return true; } + return false; + default: + throw new IllegalArgumentException("Unknown LogLevel: " + loglevel.toString()); + } + } + + // TODO: javadoc + /** + * + * @param log + * @param loglevel + * @param msg + * @since 7.0.1 + */ + private static final void logMessageAtLevel( Logger log, LogLevel loglevel, String msg ) { + switch( loglevel ) { + case TRACE: + log.trace(msg); + return; + case DEBUG: + log.debug(msg); + return; + case INFO: + log.info(msg); + return; + case WARN: + log.warn(msg); + return; + case ERROR: + log.error(msg); + return; + } + } + + + + // ========== LOCAL CLASSES ========== + + private class SortableCtxListElement implements Comparable<SortableCtxListElement> { + HashMap<String,String> child_elements = new HashMap<String,String>(); + String[] sort_fields; + + public SortableCtxListElement( SvcLogicContext ctx, String root, String[] sort_fields ) { + this.sort_fields = sort_fields; + + for( String key : ctx.getAttributeKeySet() ) { + if( key.startsWith(root) ) { + if( key.length() == root.length() ) { + child_elements.put("", ctx.getAttribute(key)); + break; + } + else { + child_elements.put(key.substring(root.length()+1), ctx.getAttribute(key)); + } + } + } + } + + @Override + public int compareTo(SortableCtxListElement arg0) { + if( sort_fields == null ) { + return this.child_elements.get("").compareTo(arg0.child_elements.get("")); + } + + for( String field : this.sort_fields ) { + int result = this.child_elements.get(field).compareTo(arg0.child_elements.get(field)); + if( result != 0 ) { + return result; + } + } + + return 0; + } + } + + /** + * Creates a file that contains the content of context memory. + * @param parameters - must contain the parameter filename + * @param ctx Reference to context memory + * @throws SvcLogicException thrown if file cannot be created or if parameters are missing + */ + public static void printContext(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + if (parameters == null || parameters.isEmpty()) { + throw new SvcLogicException("no parameters passed"); + } + + checkParameters(parameters, new String[]{"filename"}, LOG); + + String fileName = parameters.get("filename"); + + + try (FileOutputStream fstr = new FileOutputStream(new File(fileName)); + PrintStream pstr = new PrintStream(fstr, true);) + { + pstr.println("#######################################"); + for (String attr : ctx.getAttributeKeySet()) { + pstr.println(attr + " = " + ctx.getAttribute(attr)); + } + } catch (Exception e) { + throw new SvcLogicException("Cannot write context to file " + fileName, e); + } + + + } + + /** + * Checks context memory for a set of required parameters + * Every parameter aside from prefix will be treated as mandatory + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>prefix</td><td>Optional</td><td>the prefix will be added to each parameter</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void requiredParameters(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + if (parameters == null || parameters.keySet().size() < 1) { + String errorMessage = "requiredParameters should not be called if the parameters hashmap is null or empty!"; + LOG.error(errorMessage); + throw new SvcLogicException(errorMessage); + } + String prefixValue = null; + String prefix = "prefix"; + if(parameters.containsKey(prefix)){ + prefixValue = parameters.get(prefix); + parameters.remove(prefix); + } + checkParameters(prefixValue, ctx.getAttributeKeySet(), parameters.keySet(), LOG); + } + + private static void checkParameters(String prefixValue, Set<String> ctx, Set<String> parameters, Logger log) throws SvcLogicException { + for (String param : parameters) { + if (prefixValue != null) { + param = prefixValue + param; + } + if (!ctx.contains(param)) { + String errorMessage = "This method requires the parameters [" + StringUtils.join(parameters, ",") + + "], but " + param + " was not passed in."; + log.error(errorMessage); + throw new SvcLogicException(errorMessage); + } + } + } + + /** + * is in a different DG invocation just before/after we call NCS and set the state to InProgress + */ + /** + * setTime write the current date time to a string located at outputPath + * @param parameters - requires outputPath to not be null + * @param ctx Reference to context memory + * @throws SvcLogicException if a required parameter is missing an exception is thrown + */ + public static void setTime(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException + { + checkParameters(parameters, new String[] { "outputPath" }, LOG); + + // Set the DateFormat + // "2015-03-16T12:18:35.138Z" + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + // Parse the date + String ctxVariable = parameters.get("outputPath"); + try { + String dateTime = format.format(new Date()); + ctx.setAttribute(ctxVariable, dateTime); + } catch (Exception ex) { + throw new SvcLogicException("problem with setTime", ex); + } + } +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtilsActivator.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtilsActivator.java new file mode 100644 index 00000000..e0568ab7 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtilsActivator.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SliPluginUtilsActivator implements BundleActivator { + @SuppressWarnings("rawtypes") private List<ServiceRegistration> registrations = new LinkedList<ServiceRegistration>(); + + private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtilsActivator.class); + private static final String SDNC_ROOT_DIR = "SDNC_CONFIG_DIR"; + private static final String DME2_PROPERTIES_FILE_NAME = "dme2.properties"; + + @Override + public void start(BundleContext ctx) throws Exception { + SliPluginUtils plugin = new SliPluginUtils(new Properties()); + LOG.info("Registering service " + plugin.getClass().getName()); + registrations.add(ctx.registerService(plugin.getClass().getName(), plugin, null)); + + SliStringUtils sliStringUtils_Plugin = new SliStringUtils(); + LOG.info("Registering service " + sliStringUtils_Plugin.getClass().getName()); + registrations.add(ctx.registerService(sliStringUtils_Plugin.getClass().getName(), sliStringUtils_Plugin, null)); + + try { + String path = System.getenv(SDNC_ROOT_DIR) + File.separator + DME2_PROPERTIES_FILE_NAME; + DME2 dmePlugin = initDme2(path); + if (dmePlugin != null) { + LOG.info("Registering service " + dmePlugin.getClass().getName()); + registrations.add(ctx.registerService(dmePlugin.getClass().getName(), dmePlugin, null)); + } + } catch (Exception e) { + LOG.error("DME2 plugin could not be started", e); + } + } + + public DME2 initDme2(String pathToDmeProperties) { + Properties dme2properties = new Properties(); + String loadPropertiesErrorMessage = "Couldn't load DME2 properties at path " + pathToDmeProperties; + File dme2propertiesFile = new File(pathToDmeProperties); + + try { + dme2properties.load(new FileReader(dme2propertiesFile)); + String proxyUrlProperty = dme2properties.getProperty("proxyUrl"); + String[] proxyUrls = proxyUrlProperty.split(","); + DME2 dmePlugin = new DME2(dme2properties.getProperty("aafUserName"), dme2properties.getProperty("aafPassword"), dme2properties.getProperty("envContext"), dme2properties.getProperty("routeOffer"), proxyUrls, dme2properties.getProperty("commonServiceVersion")); + dmePlugin.setPartner(dme2properties.getProperty("partner")); + return dmePlugin; + } catch (FileNotFoundException e) { + LOG.error(loadPropertiesErrorMessage); + } catch (IOException e) { + LOG.error(loadPropertiesErrorMessage); + } + LOG.error("Couldn't create DME2 plugin"); + return null; + } + + @Override + public void stop(BundleContext ctx) throws Exception { + for (@SuppressWarnings("rawtypes") ServiceRegistration registration : registrations) { + registration.unregister(); + registration = null; + } + } +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliStringUtils.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliStringUtils.java new file mode 100644 index 00000000..43af6f59 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SliStringUtils.java @@ -0,0 +1,396 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A SvcLogicJavaPlugin that exposes java.lang.String functions to DirectedGraph + */ +public class SliStringUtils implements SvcLogicJavaPlugin { + private static final Logger LOG = LoggerFactory.getLogger(SliStringUtils.class); + + public SliStringUtils() {} + + /** + * Provides split functionality to Directed Graphs. + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>original_string</td><td>Mandatory</td><td>String to perform split on</td></tr> + * <tr><td>regex</td><td>Mandatory</td><td>the delimiting regular expression</td></tr> + * <tr><td>limit</td><td>Optional</td><td>result threshold. See String.split method for further description. Defaults to 0</td></tr> + * <tr><td>ctx_memory_result_key</td><td>Mandatory</td><td>Key in context memory to populate the resulting array of strings under</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + * @see String#split(String, int) + */ + public void split( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + final String original_string = parameters.get("original_string"); + LOG.trace("original_string = " + original_string); + final String regex = parameters.get("regex"); + LOG.trace("regex = " + regex); + final String limit_str = parameters.get("limit"); + LOG.trace("limit_str = " + limit_str); + final String ctx_memory_result_key = parameters.get("ctx_memory_result_key"); + LOG.trace("ctx_memory_result_key = " + ctx_memory_result_key); + + try { + // Validation that parameters are not null + SliPluginUtils.checkParameters( parameters, new String[]{"original_string","regex","ctx_memory_result_key"}, LOG ); + + // Read limit from context memory. Default to 0 if null/empty + int limit = 0; + if( StringUtils.isNotEmpty(limit_str) ) { + try { + limit = Integer.parseInt(limit_str); + } + catch( NumberFormatException e ) { + throw new IllegalArgumentException( "The limit parameter of the SliStringUtils.split() function must be a number, empty string, or null", e ); + } + } + + // Call String.split(regex,limit) on string passed in + String[] split_string = original_string.split(regex, limit); + + // Populate context memory with results + for( int i = 0; i < split_string.length; i++ ) { + SliPluginUtils.ctxSetAttribute(ctx, ctx_memory_result_key + '[' + i + ']', split_string[i], LOG, SliPluginUtils.LogLevel.DEBUG); + } + SliPluginUtils.ctxSetAttribute(ctx, ctx_memory_result_key + "_length", new Integer(split_string.length), LOG, SliPluginUtils.LogLevel.DEBUG); + } + catch( Exception e ) { + // Have error message print parameters + throw new SvcLogicException( "An error occurred during SliStringUtils.split() where original_string = " + quotedOrNULL(regex) + + " regex = " + quotedOrNULL(regex) + + " limit = " + quotedOrNULL(regex) + + " ctx_memory_result_key = " + quotedOrNULL(regex), e ); + } + } + + private static String quotedOrNULL( String str ) { + return (str == null) ? "NULL" : '"' + str + '"'; + } + + /** + * exposes equalsIgnoreCase to directed graph + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * emits a true or false outcome + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static String equalsIgnoreCase(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","target"}, LOG); + if(parameters.get("source").equalsIgnoreCase(parameters.get("target"))){ + return "true"; + } + return "false"; + } + + /** + * exposes toUpperCase to directed graph + * writes an upperCase version of source to outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void toUpper(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","outputPath"}, LOG); + ctx.setAttribute(parameters.get("outputPath"), parameters.get("source").toUpperCase()); + } + + /** + * exposes toLowerCase to directed graph + * writes a lowerCase version of source to outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void toLower(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","outputPath"}, LOG); + ctx.setAttribute(parameters.get("outputPath"), parameters.get("source").toLowerCase()); + } + + /** + * exposes contains to directed graph to test if one string contains another + * tests if the source contains the target + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * emits a true or false outcome + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static String contains(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","target"}, LOG); + if(parameters.get("source").contains(parameters.get("target"))){ + return "true"; + } + return "false"; + } + + /** + * exposes endsWith to directed graph to test if one string endsWith another string + * tests if the source ends with the target + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * emits a true or false outcome + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static String endsWith(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","target"}, LOG); + if(parameters.get("source").endsWith(parameters.get("target"))){ + return "true"; + } + return "false"; + } + + /** + * exposes startsWith to directed graph to test if one string endsWith another string + * tests if the source ends with the target + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * emits a true or false outcome + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static String startsWith(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","target"}, LOG); + if(parameters.get("source").startsWith(parameters.get("target"))){ + return "true"; + } + return "false"; + } + + /** + * exposes trim to directed graph + * writes a trimmed version of the string to the outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void trim(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","outputPath"}, LOG); + ctx.setAttribute(parameters.get("outputPath"), parameters.get("source").trim()); + } + + /** + * exposes String.length() to directed graph + * writes the length of source to outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void getLength(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","outputPath"}, LOG); + ctx.setAttribute(parameters.get("outputPath"), String.valueOf(parameters.get("source").length())); + } + + /** + * exposes replace to directed graph + * writes the length of source to outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>target</td><td>Mandatory</td><td>The sequence of char values to be replaced</td></tr> + * <tr><td>replacement</td><td>Mandatory</td><td>The replacement sequence of char values</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void replace(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[]{"source","outputPath","target","replacement"}, LOG); + ctx.setAttribute(parameters.get("outputPath"), (parameters.get("source").replace(parameters.get("target"), parameters.get("replacement")))); + } + + /** + * Provides substring functionality to Directed Graphs. + * <p> + * Calls either String.substring(String beginIndex) or + * String.substring(String beginInded, String endIndex) if the end-index + * is present or not. + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>string</td><td>Mandatory</td><td>String to perform substring on</td></tr> + * <tr><td>result</td><td>Mandatory</td><td>Key in context memory to populate the resulting string in</td></tr> + * <tr><td>begin-index</td><td>Mandatory</td><td>Beginning index to pass to Java substring function</td></tr> + * <tr><td>end-index</td><td>Optional</td><td>Ending index to pass to Java substring function. If not included, String.substring(begin) will be called.</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public void substring( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + try { + SliPluginUtils.checkParameters( parameters, new String[]{"string","begin-index","result"}, LOG ); + final String string = parameters.get("string"); + final String result = parameters.get("result"); + final String begin = parameters.get("begin-index"); + final String end = parameters.get("end-index"); + if( StringUtils.isEmpty(end) ) { + ctx.setAttribute( result, string.substring(Integer.parseInt(begin)) ); + } + else { + ctx.setAttribute( result, string.substring(Integer.parseInt(begin), Integer.parseInt(end)) ); + } + } + catch( Exception e ) { + throw new SvcLogicException( "An error occurred while the Directed Graph was performing a substring", e ); + } + } + + /** + * Provides concat functionality to Directed Graphs. + * <p> + * Will concat target to source and write the result to outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>target</td><td>Mandatory</td><td>The sequence of char values to be replaced</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + * @since 11.0.2 + */ + public static void concat( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException { + SliPluginUtils.checkParameters( parameters, new String[]{"source","target","outputPath"}, LOG ); + String result = parameters.get("source").concat(parameters.get("target")); + ctx.setAttribute(parameters.get("outputPath"), result); + } + + /** + * Provides url encoding functionality to Directed Graphs. + * <p> + * Will url encode the source and write the result to outputPath + * @param parameters HashMap<String,String> of parameters passed by the DG to this function + * <table border="1"> + * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead> + * <tbody> + * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr> + * <tr><td>encoding</td><td>Optional</td><td>the name of a supported character encoding, defaulted to UTF-8 if not supplied</td></tr> + * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr> + * </tbody> + * </table> + * @param ctx Reference to context memory + * @throws SvcLogicException + */ + public static void urlEncode(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException { + SliPluginUtils.checkParameters(parameters, new String[] { "source", "outputPath" }, LOG); + String encoding = parameters.get("encoding"); + if (encoding == null) { + encoding = "UTF-8"; + } + try { + String result = URLEncoder.encode(parameters.get("source"), encoding); + ctx.setAttribute(parameters.get("outputPath"), result); + } catch (UnsupportedEncodingException e) { + throw new SvcLogicException("Url encode failed.", e); + } + } + +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextList.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextList.java new file mode 100644 index 00000000..89a4a98f --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextList.java @@ -0,0 +1,210 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.ListIterator; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.openecomp.sdnc.sli.SvcLogicContext; + +/** + * A utility class used to manage list manipulation in the context memory. + * @see org.openecomp.sdnc.sli.SvcLogicContext + */ +public class SvcLogicContextList { + /** + * Internal flag indicating if list should be deleted from context memory + * when it is copied into the SvcLogicContextList object. + */ + private enum OperType { + COPY, EXTRACT + } + + // TODO: javadoc + protected final String prefix; + // TODO: javadoc + protected final ArrayList<HashMap<String,String>> list; + + + // TODO: javadoc + public SvcLogicContextList( SvcLogicContext ctx, String list_prefix ) { + this(ctx, list_prefix, OperType.COPY); + } + + // TODO: javadoc + private SvcLogicContextList( SvcLogicContext ctx, String list_prefix, OperType operation ) { + this.prefix = list_prefix; + + // Initialize list + int capacity = getCtxListLength(ctx, prefix); + this.list = new ArrayList<HashMap<String, String>>(capacity); + for( int i = 0; i < capacity; i++ ) { + this.list.add(i, new HashMap<String,String>()); + } + + // Populate "elements" in list + String prefix_bracket = this.prefix + '['; + for (String key : new HashSet<String>(ctx.getAttributeKeySet())) { + if( key.startsWith(prefix_bracket) ) { + // Extract the index of the list + int index = getCtxListIndex(key, this.prefix, capacity); + + // Store the + String suffix = key.substring((prefix_bracket + index + ']').length()); + suffix = suffix.isEmpty() ? suffix : suffix.substring(1); + this.list.get(index).put( suffix, ctx.getAttribute(key)); + + // If flag to extract set, remove data from context memory as + // it is read into this list + if( operation == OperType.EXTRACT ) { + ctx.setAttribute(key, null); + } + } + } + + // If flag to extract set, remove list _length value from cxt mem + if( operation == OperType.EXTRACT ) { + ctx.setAttribute(this.prefix + "_length", null); + } + } + + // TODO: javadoc + public static SvcLogicContextList extract( SvcLogicContext ctx, String list_prefix ) { + return new SvcLogicContextList(ctx, list_prefix, OperType.EXTRACT); + } + + + // ========== PUBLIC FUNCTIONS ========== + + // TODO: javadoc + public HashMap<String,String> get( int index ) { + return this.list.get(index); + } + + // TODO: javadoc + public HashMap<String,String> remove( int index ) { + return this.list.remove(index); + } + + // TODO: javadoc + public void remove( String value ) { + remove( "", value ); + } + + // TODO: javadoc + public void remove( String key, String value ) { + if( value == null ) { + throw new IllegalArgumentException("value cannot be null"); + } + + ListIterator<HashMap<String,String>> itr = this.list.listIterator(); + while( itr.hasNext() ) { + if( value.equals(itr.next().get(key)) ) { + itr.remove(); + } + } + } + + // TODO javadoc + public void remove( Map<String,String> primary_key ) { + ListIterator<HashMap<String,String>> itr = this.list.listIterator(); + while( itr.hasNext() ) { + boolean found = true; + HashMap<String,String> list_element = itr.next(); + for( Map.Entry<String,String> key : primary_key.entrySet() ) { + if( !key.getValue().equals(list_element.get(key.getKey())) ) { + found = false; + break; + } + } + + if( found ) { + itr.remove(); + } + } + } + + // TODO: javadoc + public int size() { + return list.size(); + } + + // TODO: javadoc + public void writeToContext( SvcLogicContext ctx ) { + ctx.setAttribute( prefix + "_length", Integer.toString(this.list.size()) ); + + for( int i = 0; i < this.list.size(); i++ ) { + for( Map.Entry<String,String> entry : this.list.get(i).entrySet() ) { + if( entry.getKey().equals("") ) { + ctx.setAttribute(prefix + '[' + i + ']', entry.getValue()); + } else { + ctx.setAttribute(prefix + '[' + i + "]." + entry.getKey(), entry.getValue()); + } + } + } + } + + + + // ========== PRIVATE STATIC FUNCTIONS ========== + + // TODO: javadoc + private static int getCtxListIndex( String key, String prefix, int list_size ) { + int index = getCtxListIndex( key, prefix ); + if( index >= list_size ) { + throw new IllegalArgumentException("Context memory list \"" + prefix + "[]\" contains an index >= the size of the list", new ArrayIndexOutOfBoundsException("index \"" + index + "\" is outside the bounds of the context memory list \"" + prefix + "[]. List Length = " + list_size)); + } else if (index < 0) { + throw new IllegalArgumentException("Context memory list \"" + prefix + "[]\" contains a negative index", new NegativeArraySizeException("index \"" + index + "\" of context memory list is negative")); + } + + return index; + } + + // TODO: javadoc + private static int getCtxListIndex( String key, String prefix ) { + String ctx_index_str = StringUtils.substringBetween(key.substring(prefix.length()), "[", "]"); + try { + return Integer.parseInt( ctx_index_str ); + } catch (NumberFormatException e) { + throw new IllegalStateException("Could not parse index value \"" + ctx_index_str + "\" in context memory key \"" + key + "\"", e); + } + } + + // TODO: javadoc + private static int getCtxListLength( SvcLogicContext ctx, String prefix ) { + String _length_key = prefix + "_length"; + String _length_val_str = ctx.getAttribute(_length_key); + try { + return Integer.parseInt(_length_val_str); + } catch (NumberFormatException e) { + if( _length_val_str == null ) { + throw new IllegalStateException( "Could not find list length \"" + _length_key + "\" in context memory." ); + } else { + throw new IllegalStateException( "Could not parse index value \"" + _length_val_str + "\" of context memory list length \"" + _length_key + "\"" , e ); + } + } + } +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextObject.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextObject.java new file mode 100644 index 00000000..d79522f0 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextObject.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import org.openecomp.sdnc.sli.SvcLogicContext; + +public interface SvcLogicContextObject { + public void writeToContext( SvcLogicContext ctx, String root ); +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/commondatastructures/YesNo.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/commondatastructures/YesNo.java new file mode 100644 index 00000000..4d2fb4c2 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/commondatastructures/YesNo.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +package org.openecomp.sdnc.sli.SliPluginUtils.commondatastructures; + +/** + * An enum found in many Yang models. It is commonly used as a + * substitute for boolean. + */ +public enum YesNo { + N, Y; + + /** + * Method overload for {@link #valueOf(String)} for the char primative + */ + public static YesNo valueOf( final char name ) { + return YesNo.valueOf( Character.toString(name) ); + } + + /** + * Method overload for {@link #valueOf(String)} for the Character object + */ + public static YesNo valueOf( final Character name ) { + if( name == null ) { + return null; + } + + return YesNo.valueOf( name.toString() ); + } +} diff --git a/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/commondatastructures/package-info.java b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/commondatastructures/package-info.java new file mode 100644 index 00000000..4a81d9a3 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/openecomp/sdnc/sli/SliPluginUtils/commondatastructures/package-info.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +/** + * + */ +package org.openecomp.sdnc.sli.SliPluginUtils.commondatastructures; diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/CheckParametersTest.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/CheckParametersTest.java new file mode 100644 index 00000000..318e4643 --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/CheckParametersTest.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckParametersTest { + + @Test + public void nullRequiredParameters() throws Exception { + Map<String, String> parametersMap = new HashMap<String, String>(); + String[] requiredParams = null; + Logger Log = LoggerFactory.getLogger(SliPluginUtils.class); + SliPluginUtils.checkParameters(parametersMap, requiredParams, Log); + } + + @Test(expected = SvcLogicException.class) + public void emptyParametersMap() throws Exception { + Map<String, String> parametersMap = new HashMap<String, String>(); + String[] requiredParams = new String[] { "param1", "param2", "param3" }; + Logger Log = LoggerFactory.getLogger(SliPluginUtils.class); + SliPluginUtils.checkParameters(parametersMap, requiredParams, Log); + } + + @Test(expected = SvcLogicException.class) + public void paramNotFound() throws Exception { + Map<String, String> parametersMap = new HashMap<String, String>(); + parametersMap.put("tst", "me"); + String[] requiredParams = new String[] { "param1", "parm2", "param3" }; + Logger Log = LoggerFactory.getLogger(SliPluginUtils.class); + SliPluginUtils.checkParameters(parametersMap, requiredParams, Log); + } + + @Test + public void testSunnyRequiredParameters() throws Exception { + SvcLogicContext ctx = new SvcLogicContext(); + ctx.setAttribute("param1", "hello"); + ctx.setAttribute("param2", "world"); + ctx.setAttribute("param3", "!"); + + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("param1", "dog"); + parameters.put("param2", "cat"); + parameters.put("param3", "fish"); + + SliPluginUtils.requiredParameters(parameters, ctx); + } + + @Test + public void testSunnyRequiredParametersWithPrefix() throws Exception { + String prefixValue = "my.unique.path."; + SvcLogicContext ctx = new SvcLogicContext(); + ctx.setAttribute(prefixValue + "param1", "hello"); + ctx.setAttribute(prefixValue + "param2", "world"); + ctx.setAttribute(prefixValue + "param3", "!"); + + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("prefix", prefixValue); + parameters.put("param1", "dog"); + parameters.put("param2", "cat"); + parameters.put("param3", "fish"); + + SliPluginUtils.requiredParameters(parameters, ctx); + } + + @Test(expected = SvcLogicException.class) + public void testRainyMissingRequiredParameters() throws Exception { + SvcLogicContext ctx = new SvcLogicContext(); + ctx.setAttribute("param1", "hello"); + ctx.setAttribute("param3", "!"); + + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("param1", null); + parameters.put("param2", null); + parameters.put("param3", null); + + SliPluginUtils.requiredParameters(parameters, ctx); + } + + @Test(expected = SvcLogicException.class) + public void testEmptyRequiredParameters() throws Exception { + SvcLogicContext ctx = new SvcLogicContext(); + ctx.setAttribute("param1", "hello"); + ctx.setAttribute("param3", "!"); + + Map<String, String> parameters = new HashMap<String, String>(); + + SliPluginUtils.requiredParameters(parameters, ctx); + } +} diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/Dme2Test.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/Dme2Test.java new file mode 100644 index 00000000..d66b0114 --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/Dme2Test.java @@ -0,0 +1,109 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.openecomp.sdnc.sli.SliPluginUtils.DME2; +import org.openecomp.sdnc.sli.SliPluginUtils.SliPluginUtilsActivator; + +public class Dme2Test { + + @Test + public void createInstarUrl() { + String instarUrl = "http://localhost:25055/service=sample.com/services/eim/v1/rest/version=1702.0/envContext=TEST/routeOffer=DEFAULT/subContext=/enterpriseConnection/getEnterpriseConnectionDetails/v1?dme2.password=fake&dme2.username=user@sample.com"; + DME2 dme = new DME2("user@sample.com", "fake", "TEST", "DEFAULT", new String[] { "http://localhost:25055" }, "common"); + String constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(instarUrl, constructedUrl); + } + + @Test + public void createInstarUrlNoSubContext() { + String instarUrl = "http://localhost:25055/service=sample.com/services/eim/v1/rest/version=1702.0/envContext=TEST/routeOffer=DEFAULT?dme2.password=fake&dme2.username=user@sample.com"; + DME2 dme = new DME2("user@sample.com", "fake", "TEST", "DEFAULT", new String[] { "http://localhost:25055" }, "common"); + Map<String, String> parameters = new HashMap<String, String>(); + String constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", parameters.get(null)); + assertEquals(instarUrl, constructedUrl); + } + + @Test + public void testRoundRobin() { + String[] proxyHostNames = new String[] { "http://one:25055", "http://two:25055", "http://three:25055" }; + String urlSuffix = "/service=sample.com/services/eim/v1/rest/version=1702.0/envContext=TEST/routeOffer=DEFAULT/subContext=/enterpriseConnection/getEnterpriseConnectionDetails/v1?dme2.password=fake&dme2.username=user@sample.com"; + DME2 dme = new DME2("user@sample.com", "fake", "TEST", "DEFAULT", proxyHostNames, "common"); + String constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[0] + urlSuffix, constructedUrl); + constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[1] + urlSuffix, constructedUrl); + constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[2] + urlSuffix, constructedUrl); + constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[0] + urlSuffix, constructedUrl); + constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[1] + urlSuffix, constructedUrl); + constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[2] + urlSuffix, constructedUrl); + constructedUrl = dme.constructUrl("sample.com/services/eim/v1/rest", "1702.0", "/enterpriseConnection/getEnterpriseConnectionDetails/v1"); + assertEquals(proxyHostNames[0] + urlSuffix, constructedUrl); + } + + @Test + public void createDme2EndtoEnd() { + SliPluginUtilsActivator activator = new SliPluginUtilsActivator(); + DME2 dme2 = activator.initDme2("src/test/resources/dme2.e2e.properties"); + assertEquals("user@sample.com", dme2.aafUserName); + assertEquals("fake", dme2.aafPassword); + assertEquals("UAT", dme2.envContext); + assertEquals("UAT", dme2.routeOffer); + Assert.assertArrayEquals("http://sample.com:25055,http://sample.com:25055".split(","), dme2.proxyUrls); + assertEquals("1702.0", dme2.commonServiceVersion); + assertEquals(null, dme2.partner); + + String constructedUrl = dme2.constructUrl("sample.com/restservices/instar/v1/assetSearch", null, "/mySubContext"); + assertNotNull(constructedUrl); + System.out.println(constructedUrl); + } + + @Test + public void createDme2Prod() { + SliPluginUtilsActivator activator = new SliPluginUtilsActivator(); + DME2 dme2 = activator.initDme2("src/test/resources/dme2.prod.properties"); + assertEquals("user@sample.com", dme2.aafUserName); + assertEquals("fake", dme2.aafPassword); + assertEquals("PROD", dme2.envContext); + assertEquals("", dme2.routeOffer); + Assert.assertArrayEquals("http://sample.com:25055,http://sample.com:25055".split(","), dme2.proxyUrls); + assertEquals("1.0", dme2.commonServiceVersion); + assertEquals("LPP_PROD", dme2.partner); + + String constructedUrl = dme2.constructUrl("sample.com/restservices/instar/v1/assetSearch", null, "/mySubContext"); + assertNotNull(constructedUrl); + System.out.println(constructedUrl); + } + +} diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_StaticFunctionsTest.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_StaticFunctionsTest.java new file mode 100644 index 00000000..e69d0867 --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_StaticFunctionsTest.java @@ -0,0 +1,250 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SliPluginUtils_StaticFunctionsTest { + private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils_StaticFunctionsTest.class); + SliPluginUtils utils = new SliPluginUtils(); + private SvcLogicContext ctx; + private HashMap<String, String> parameters; + + @Before + public void setUp() throws Exception { + this.ctx = new SvcLogicContext(); + parameters = new HashMap<String, String>(); + } + + // TODO: javadoc + @Test + public final void testCtxGetBeginsWith() { + ctx.setAttribute("service-data.oper-status.order-status", "InProgress"); + ctx.setAttribute("service-data.service-information.service-instance-id", "my-instance"); + ctx.setAttribute("service-data.service-information.service-type", "my-service"); + + Map<String, String> entries = SliPluginUtils.ctxGetBeginsWith(ctx, "service-data.service-information"); + + assertEquals("my-instance", entries.get("service-data.service-information.service-instance-id")); + assertEquals("my-service", entries.get("service-data.service-information.service-type")); + assertFalse(entries.containsKey("service-data.oper-status.order-status")); + } + + // TODO: javadoc + @Test + public final void testCtxListRemove_index() throws SvcLogicException { + LOG.trace("=== testCtxListRemove_index ==="); + ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2"); + ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2"); + ctx.setAttribute("service-data.vnf-l3_length", "3"); + + parameters.put("index", "1"); + parameters.put("list_pfx", "service-data.vnf-l3"); + + utils.ctxListRemove(parameters, ctx); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + assertEquals("2", ctx.getAttribute("service-data.vnf-l3_length")); + assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].vnf-host-name")); + assertEquals("device-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].device-host-name")); + assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].vnf-host-name")); + assertEquals("device-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].device-host-name")); + } + + // TODO: javadoc + @Test + public final void textCtxListRemove_keyValue() throws SvcLogicException { + LOG.trace("=== textCtxListRemove_keyValue ==="); + ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2"); + ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2"); + // 2nd entry + ctx.setAttribute("service-data.vnf-l3[3].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[3].device-host-name", "device-host-name_1"); + ctx.setAttribute("service-data.vnf-l3_length", "4"); + + parameters.put("list_pfx", "service-data.vnf-l3"); + parameters.put("key", "vnf-host-name"); + parameters.put("value", "vnf-host-name_1"); + + utils.ctxListRemove(parameters, ctx); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + assertEquals("2", ctx.getAttribute("service-data.vnf-l3_length")); + assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].vnf-host-name")); + assertEquals("device-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].device-host-name")); + assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].vnf-host-name")); + assertEquals("device-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].device-host-name")); + } + + // TODO: javadoc + @Test + public final void textCtxListRemove_keyValue_nullkey() throws SvcLogicException { + LOG.trace("=== textCtxListRemove_keyValue_nullkey ==="); + ctx.setAttribute("service-data.vnf-l3[0]", "vnf-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[1]", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[2]", "vnf-host-name_2"); + ctx.setAttribute("service-data.vnf-l3_length", "3"); + + parameters.put("list_pfx", "service-data.vnf-l3"); + parameters.put("value", "vnf-host-name_1"); + + utils.ctxListRemove(parameters, ctx); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + assertEquals("2", ctx.getAttribute("service-data.vnf-l3_length")); + assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0]")); + assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1]")); + } + + // TODO: javadoc + @Test + public final void textCtxListRemove_keyValueList() throws SvcLogicException { + LOG.trace("=== textCtxListRemove_keyValueList ==="); + ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2"); + ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2"); + // 2nd entry + ctx.setAttribute("service-data.vnf-l3[3].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[3].device-host-name", "device-host-name_1"); + // entries with only 1 of 2 key-value pairs matching + ctx.setAttribute("service-data.vnf-l3[4].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[4].device-host-name", "device-host-name_4"); + ctx.setAttribute("service-data.vnf-l3[5].vnf-host-name", "vnf-host-name_5"); + ctx.setAttribute("service-data.vnf-l3[5].device-host-name", "device-host-name_1"); + ctx.setAttribute("service-data.vnf-l3_length", "6"); + + parameters.put("list_pfx", "service-data.vnf-l3"); + parameters.put("keys_length", "2"); + parameters.put("keys[0].key", "vnf-host-name"); + parameters.put("keys[0].value", "vnf-host-name_1"); + parameters.put("keys[1].key", "device-host-name"); + parameters.put("keys[1].value", "device-host-name_1"); + + utils.ctxListRemove(parameters, ctx); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + assertEquals("4", ctx.getAttribute("service-data.vnf-l3_length")); + assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].vnf-host-name")); + assertEquals("device-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].device-host-name")); + assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].vnf-host-name")); + assertEquals("device-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].device-host-name")); + assertEquals("vnf-host-name_1", ctx.getAttribute("service-data.vnf-l3[2].vnf-host-name")); + assertEquals("device-host-name_4", ctx.getAttribute("service-data.vnf-l3[2].device-host-name")); + assertEquals("vnf-host-name_5", ctx.getAttribute("service-data.vnf-l3[3].vnf-host-name")); + assertEquals("device-host-name_1", ctx.getAttribute("service-data.vnf-l3[3].device-host-name")); + } + + // TODO: javadoc + @Test(expected = SvcLogicException.class) + public final void testCtxListRemove_nullListLength() throws SvcLogicException { + LOG.trace("=== testCtxListRemove_nullListLength ==="); + ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0"); + ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1"); + ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2"); + ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2"); + + parameters.put("index", "1"); + parameters.put("list_pfx", "service-data.vnf-l3"); + + utils.ctxListRemove(parameters, ctx); + } + + // TODO: javadoc + @Test + public final void testCtxPutAll() { + HashMap<String, Object> entries = new HashMap<String, Object>(); + entries.put("service-data.oper-status.order-status", "InProgress"); + entries.put("service-data.service-information.service-instance-id", "my-instance"); + entries.put("service-data.request-information.order-number", 1234); + entries.put("service-data.request-information.request-id", null); + + SliPluginUtils.ctxPutAll(ctx, entries); + + assertEquals("InProgress", ctx.getAttribute("service-data.oper-status.order-status")); + assertEquals("my-instance", ctx.getAttribute("service-data.service-information.service-instance-id")); + assertEquals("1234", ctx.getAttribute("service-data.request-information.order-number")); + assertFalse(ctx.getAttributeKeySet().contains("service-data.request-information.request-id")); + } + + // TODO: javadoc + @Test + public final void testCtxSetAttribute_LOG() { + LOG.debug("=== testCtxSetAttribute_LOG ==="); + Integer i = new Integer(3); + SliPluginUtils.ctxSetAttribute(ctx, "test", i, LOG, SliPluginUtils.LogLevel.TRACE); + } + + /*@Test + public void printContext() throws SvcLogicException, IOException { + String filePath = "/src/test/resources/printContext.txt"; + parameters.put("filename", filePath); + File f = new File(filePath); + assert (f.exists()); + assert (!f.isDirectory()); + ctx.setAttribute("hello", "world"); + ctx.setAttribute("name", "value"); + + SliPluginUtils.printContext(parameters, ctx); + BufferedReader br = new BufferedReader(new FileReader(f)); + String line = br.readLine(); + assertEquals("#######################################", line); + line = br.readLine(); + assertEquals("hello = world", line); + line = br.readLine(); + assertEquals("name = value", line); + br.close(); + Files.delete(Paths.get(filePath)); + }*/ + + @Test + public void setTime() throws SvcLogicException { + String outputPath = "output"; + parameters.put("outputPath", outputPath); + SliPluginUtils.setTime(parameters, ctx); + assertNotNull(ctx.getAttribute(outputPath)); + } +} diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_ctxSortList.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_ctxSortList.java new file mode 100644 index 00000000..b1cae54a --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_ctxSortList.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Random; + +import org.junit.Before; +import org.junit.Test; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("unused") +public class SliPluginUtils_ctxSortList { + private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils_ctxSortList.class); + SliPluginUtils utils = new SliPluginUtils(); + SvcLogicContext ctx; + HashMap<String,String> parameters; + Random rand = new Random(); + + @Before + public void setUp() throws Exception { + this.ctx = new SvcLogicContext(); + this.parameters = new HashMap<String,String>(); + } + + @Test + public final void list_of_containers() throws SvcLogicException { + this.parameters.put("list", "input.list"); + this.parameters.put("sort-fields", "sort-key"); + this.parameters.put("delimiter",","); + + ctx.setAttribute("input.list_length", "10"); + for( int i = 0; i < 10; i++ ) { + this.ctx.setAttribute("input.list[" + i + "].sort-key", Integer.toString( rand.nextInt(10) )); + this.ctx.setAttribute("input.list[" + i + "].value", Integer.toString( rand.nextInt(10) )); + } + + LOG.trace("BEFORE SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + utils.ctxSortList(this.parameters, this.ctx); + + LOG.trace("AFTER SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + for( int i = 0; i < 9; i++ ) { + assertTrue(this.ctx.getAttribute("input.list[" + i + "].sort-key").compareTo(this.ctx.getAttribute("input.list[" + (i+1) + "].sort-key")) < 1 ); + } + } + + @Test public final void list_of_elements() throws SvcLogicException { + this.parameters.put("list", "input.list"); + this.parameters.put("delimiter",","); + + this.ctx.setAttribute("input.list_length", "10"); + for( int i = 0; i < 10; i++ ) { + this.ctx.setAttribute("input.list[" + i + ']', Integer.toString( rand.nextInt(10) )); + } + + LOG.trace("BEFORE SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + utils.ctxSortList(this.parameters, this.ctx); + + LOG.trace("AFTER SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + for( int i = 0; i < 9; i++ ) { + assertTrue(this.ctx.getAttribute("input.list[" + i + ']').compareTo(this.ctx.getAttribute("input.list[" + (i+1) + ']')) < 1 ); + } + } +} diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_ctxSortListTest.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_ctxSortListTest.java new file mode 100644 index 00000000..e2fcb33d --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliPluginUtils_ctxSortListTest.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Random; + +import org.junit.Before; +import org.junit.Test; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("unused") +public class SliPluginUtils_ctxSortListTest { + private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils_ctxSortListTest.class); + SliPluginUtils utils = new SliPluginUtils(); + SvcLogicContext ctx; + HashMap<String, String> parameters; + Random rand = new Random(); + + @Before + public void setUp() throws Exception { + this.ctx = new SvcLogicContext(); + this.parameters = new HashMap<String, String>(); + } + + @Test + public final void list_of_containers() throws SvcLogicException { + this.parameters.put("list", "input.list"); + this.parameters.put("sort-fields", "sort-key"); + this.parameters.put("delimiter", ","); + + ctx.setAttribute("input.list_length", "10"); + for (int i = 0; i < 10; i++) { + this.ctx.setAttribute("input.list[" + i + "].sort-key", Integer.toString(rand.nextInt(10))); + this.ctx.setAttribute("input.list[" + i + "].value", Integer.toString(rand.nextInt(10))); + } + + LOG.trace("BEFORE SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + utils.ctxSortList(this.parameters, this.ctx); + + LOG.trace("AFTER SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + for (int i = 0; i < 9; i++) { + assertTrue(this.ctx.getAttribute("input.list[" + i + "].sort-key").compareTo(this.ctx.getAttribute("input.list[" + (i + 1) + "].sort-key")) < 1); + } + } + + @Test + public final void list_of_elements() throws SvcLogicException { + this.parameters.put("list", "input.list"); + this.parameters.put("delimiter", ","); + + this.ctx.setAttribute("input.list_length", "10"); + for (int i = 0; i < 10; i++) { + this.ctx.setAttribute("input.list[" + i + ']', Integer.toString(rand.nextInt(10))); + } + + LOG.trace("BEFORE SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + utils.ctxSortList(this.parameters, this.ctx); + + LOG.trace("AFTER SORT:"); + SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE); + + for (int i = 0; i < 9; i++) { + assertTrue(this.ctx.getAttribute("input.list[" + i + ']').compareTo(this.ctx.getAttribute("input.list[" + (i + 1) + ']')) < 1); + } + } +} diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliStringUtilsTest.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliStringUtilsTest.java new file mode 100644 index 00000000..d57cefa0 --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SliStringUtilsTest.java @@ -0,0 +1,244 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +package org.openecomp.sdnc.sli.SliPluginUtils; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; + +/** + * @author km991u + * + */ +public class SliStringUtilsTest { + private SvcLogicContext ctx; + private HashMap<String, String> param; + private SliStringUtils stringUtils = new SliStringUtils(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + this.ctx = new SvcLogicContext(); + param = new HashMap<String, String>(); + } + + /** + * @throws SvcLogicException + * @see SliStringUtils#split(Map, SvcLogicContext) + */ + @Test + public final void testSplit() throws SvcLogicException { + param.put("original_string", "one ## two ## three"); + param.put("regex", " ## "); + param.put("ctx_memory_result_key", "result"); + + stringUtils.split(param, ctx); + + assertThat(ctx.getAttribute("result[0]"), equalTo("one")); + assertThat(ctx.getAttribute("result[1]"), equalTo("two")); + assertThat(ctx.getAttribute("result[2]"), equalTo("three")); + assertThat(ctx.getAttribute("result_length"), equalTo("3")); + } + + /** + * @throws SvcLogicException + * @see SliStringUtils#split(Map, SvcLogicContext) + */ + @Test + public final void testSplit_limit() throws SvcLogicException { + param.put("original_string", "one ## two ## three"); + param.put("regex", " ## "); + param.put("limit", "2"); + param.put("ctx_memory_result_key", "result"); + + stringUtils.split(param, ctx); + + assertThat(ctx.getAttribute("result[0]"), equalTo("one")); + assertThat(ctx.getAttribute("result[1]"), equalTo("two ## three")); + assertThat(ctx.getAttribute("result_length"), equalTo("2")); + } + + @Test + public void equalsIgnoreCaseTrue() throws SvcLogicException { + String sourceString = "HeLlOwORLD"; + String targetSTring = "HELLOWORLD"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("true", SliStringUtils.equalsIgnoreCase(param, ctx)); + } + + @Test + public void equalsIgnoreCaseFalse() throws SvcLogicException { + String sourceString = "HeLlOwORLD"; + String targetSTring = "goodbyeWORLD"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("false", SliStringUtils.equalsIgnoreCase(param, ctx)); + } + + @Test + public void toUpper() throws SvcLogicException { + String sourceString = "HeLlOwORLD"; + param.put("source", sourceString); + String path = "my.unique.path."; + param.put("outputPath", path); + SliStringUtils.toUpper(param, ctx); + assertEquals(sourceString.toUpperCase(), ctx.getAttribute(path)); + } + + @Test + public void toLower() throws SvcLogicException { + String sourceString = "HeLlOwORLD"; + param.put("source", sourceString); + String path = "my.unique.path."; + param.put("outputPath", path); + SliStringUtils.toLower(param, ctx); + assertEquals(sourceString.toLowerCase(), ctx.getAttribute(path)); + } + + @Test + public void containsTrue() throws SvcLogicException { + String sourceString = "Pizza"; + String targetSTring = "izza"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("true", SliStringUtils.contains(param, ctx)); + } + + @Test + public void containsFalse() throws SvcLogicException { + String sourceString = "Pizza"; + String targetSTring = "muffin"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("false", SliStringUtils.contains(param, ctx)); + } + + @Test + public void endsWithTrue() throws SvcLogicException { + String sourceString = "Pizza"; + String targetSTring = "za"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("true", SliStringUtils.endsWith(param, ctx)); + } + + @Test + public void endsWithFalse() throws SvcLogicException { + String sourceString = "Pizza"; + String targetSTring = "muffin"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("false", SliStringUtils.endsWith(param, ctx)); + } + + @Test + public void trim() throws SvcLogicException { + String sourceString = " H E L L O W O R L D"; + String outputPath = "muffin"; + param.put("source", sourceString); + param.put("outputPath", outputPath); + SliStringUtils.trim(param, ctx); + assertEquals(sourceString.trim(), ctx.getAttribute(outputPath)); + } + + @Test + public void getLength() throws SvcLogicException { + String sourceString = "SomeRandomString"; + String outputPath = "muffin"; + param.put("source", sourceString); + param.put("outputPath", outputPath); + SliStringUtils.getLength(param, ctx); + assertEquals(String.valueOf(sourceString.length()), ctx.getAttribute(outputPath)); + } + + @Test + public void startsWithFalse() throws SvcLogicException { + String sourceString = "Java"; + String targetSTring = "DG"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("false", SliStringUtils.startsWith(param, ctx)); + } + + @Test + public void startsWithTrue() throws SvcLogicException { + String sourceString = "Java"; + String targetSTring = "Ja"; + param.put("source", sourceString); + param.put("target", targetSTring); + assertEquals("true", SliStringUtils.startsWith(param, ctx)); + } + + @Test + public void replace() throws SvcLogicException { + String sourceString = "cat Hello World cat"; + String old = "cat"; + String neww = "dog"; + String outputPath = "out"; + + param.put("source", sourceString); + param.put("target", old); + param.put("replacement", neww); + param.put("outputPath", outputPath); + SliStringUtils.replace(param, ctx); + assertEquals(sourceString.replace(old, neww), ctx.getAttribute(outputPath)); + } + + @Test + public void concat() throws SvcLogicException { + String sourceString = "cat"; + String targetString = "dog"; + String outputPath = "out"; + + param.put("source", sourceString); + param.put("target", targetString); + param.put("outputPath", outputPath); + SliStringUtils.concat(param, ctx); + assertEquals(sourceString + targetString, ctx.getAttribute(outputPath)); + } + + @Test + public void urlEncode() throws SvcLogicException { + String sourceString = "102/GE100/SNJSCAMCJP8/SNJSCAMCJT4"; + String outputPath = "out"; + + param.put("source", sourceString); + param.put("outputPath", outputPath); + SliStringUtils.urlEncode(param, ctx); + assertEquals("102%2FGE100%2FSNJSCAMCJP8%2FSNJSCAMCJT4", ctx.getAttribute(outputPath)); + } + +} diff --git a/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextListTest.java b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextListTest.java new file mode 100644 index 00000000..5d7bb249 --- /dev/null +++ b/sliPluginUtils/provider/src/test/java/org/openecomp/sdnc/sli/SliPluginUtils/SvcLogicContextListTest.java @@ -0,0 +1,307 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sli.SliPluginUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.HashMap; + +import org.junit.Before; +import org.junit.Test; +import org.openecomp.sdnc.sli.SvcLogicContext; + +public class SvcLogicContextListTest { + //private static final Logger LOG = LoggerFactory.getLogger(SvcLogicContextTest.class); + private SvcLogicContext ctx; + + @Before + public void setUp() throws Exception { + this.ctx = new SvcLogicContext(); + } + + // TODO: javadoc + @Test + public final void testSvcLogicContextList_SingleValueList() { + ctx.setAttribute("list[0]", "0"); + ctx.setAttribute("list[1]", "1"); + ctx.setAttribute("list[2]", "2"); + ctx.setAttribute("list[3]", "3"); + ctx.setAttribute("list[4]", "4"); + ctx.setAttribute("list_length", "5"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + + // Check that size of list is 5 + assertEquals(5, list.size()); + + // Check that each HashMap has it's list value in the empty string key + // and has no other values + assertEquals(1, list.get(0).size()); + assertEquals("0", list.get(0).get("")); + assertEquals(1, list.get(1).size()); + assertEquals("1", list.get(1).get("")); + assertEquals(1, list.get(2).size()); + assertEquals("2", list.get(2).get("")); + assertEquals(1, list.get(3).size()); + assertEquals("3", list.get(3).get("")); + assertEquals(1, list.get(4).size()); + assertEquals("4", list.get(4).get("")); + } + + // TODO: javadoc + @Test + public final void testSvcLogicContextList_ObjectList() { + ctx.setAttribute("list[0].ipv4", "1.1.1.0"); + ctx.setAttribute("list[0].ipv6", "2001::0"); + ctx.setAttribute("list[1].ipv4", "1.1.1.1"); + ctx.setAttribute("list[1].ipv6", "2001::1"); + ctx.setAttribute("list[2].ipv4", "1.1.1.2"); + ctx.setAttribute("list[2].ipv6", "2001::2"); + ctx.setAttribute("list[3].ipv4", "1.1.1.3"); + ctx.setAttribute("list[3].ipv6", "2001::3"); + ctx.setAttribute("list[4].ipv4", "1.1.1.4"); + ctx.setAttribute("list[4].ipv6", "2001::4"); + ctx.setAttribute("list_length", "5"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + + // Check that size of list is 5 + assertEquals(5, list.size()); + + assertEquals(2, list.get(0).size()); + assertEquals("1.1.1.0", list.get(0).get("ipv4")); + assertEquals("2001::0", list.get(0).get("ipv6")); + assertEquals(2, list.get(1).size()); + assertEquals("1.1.1.1", list.get(1).get("ipv4")); + assertEquals("2001::1", list.get(1).get("ipv6")); + assertEquals(2, list.get(2).size()); + assertEquals("1.1.1.2", list.get(2).get("ipv4")); + assertEquals("2001::2", list.get(2).get("ipv6")); + assertEquals(2, list.get(3).size()); + assertEquals("1.1.1.3", list.get(3).get("ipv4")); + assertEquals("2001::3", list.get(3).get("ipv6")); + assertEquals(2, list.get(4).size()); + assertEquals("1.1.1.4", list.get(4).get("ipv4")); + assertEquals("2001::4", list.get(4).get("ipv6")); + } + + // TODO: javadoc + @Test + public final void testExtract() { + ctx.setAttribute("list[0]", "0"); + ctx.setAttribute("list[1]", "1"); + ctx.setAttribute("list[2]", "2"); + ctx.setAttribute("list[3]", "3"); + ctx.setAttribute("list[4]", "4"); + ctx.setAttribute("list_length", "5"); + ctx.setAttribute("Other", "other"); + + SvcLogicContextList list = SvcLogicContextList.extract(ctx, "list"); + + // Check that size of list is 5 + assertEquals(5, list.size()); + + // Check that all list values exist in list object + assertEquals(1, list.get(0).size()); + assertEquals("0", list.get(0).get("")); + assertEquals(1, list.get(1).size()); + assertEquals("1", list.get(1).get("")); + assertEquals(1, list.get(2).size()); + assertEquals("2", list.get(2).get("")); + assertEquals(1, list.get(3).size()); + assertEquals("3", list.get(3).get("")); + assertEquals(1, list.get(4).size()); + assertEquals("4", list.get(4).get("")); + + // Check that all list values no longer exist in ctx + assertNull(ctx.getAttribute("list[0]")); + assertNull(ctx.getAttribute("list[1]")); + assertNull(ctx.getAttribute("list[2]")); + assertNull(ctx.getAttribute("list[3]")); + assertNull(ctx.getAttribute("list[4]")); + assertNull(ctx.getAttribute("list_length")); + + // Check that non-list values still exist in ctx + assertEquals("other", ctx.getAttribute("Other")); + } + + // TODO: javadoc + @Test + public final void testRemove_int() { + ctx.setAttribute("list[0]", "0"); + ctx.setAttribute("list[1]", "1"); + ctx.setAttribute("list[2]", "2"); + ctx.setAttribute("list[3]", "3"); + ctx.setAttribute("list[4]", "4"); + ctx.setAttribute("list_length", "5"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + list.remove(2); + + // Check that size of list is 4 (1 less than original) + assertEquals(4, list.size()); + + // Check that value was remove from list + assertEquals(1, list.get(0).size()); + assertEquals("0", list.get(0).get("")); + assertEquals(1, list.get(1).size()); + assertEquals("1", list.get(1).get("")); + assertEquals(1, list.get(2).size()); + assertEquals("3", list.get(2).get("")); + assertEquals(1, list.get(3).size()); + assertEquals("4", list.get(3).get("")); + } + + // TODO: javadoc + @Test + public final void testRemove_StringString() { + ctx.setAttribute("list[0].ipv4", "1.1.1.0"); + ctx.setAttribute("list[0].ipv6", "2001::0"); + ctx.setAttribute("list[1].ipv4", "1.1.1.1"); + ctx.setAttribute("list[1].ipv6", "2001::1"); + ctx.setAttribute("list[2].ipv4", "1.1.1.2"); + ctx.setAttribute("list[2].ipv6", "2001::2"); + ctx.setAttribute("list[3].ipv4", "1.1.1.3"); + ctx.setAttribute("list[3].ipv6", "2001::3"); + ctx.setAttribute("list[4].ipv4", "1.1.1.4"); + ctx.setAttribute("list[4].ipv6", "2001::4"); + ctx.setAttribute("list[5].ipv4", "1.1.1.2"); + ctx.setAttribute("list[5].ipv6", "2001::2"); + ctx.setAttribute("list_length", "6"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + list.remove("ipv4", "1.1.1.2"); + + // Check that size of list is 4 (2 less than original) + assertEquals(4, list.size()); + + // Check that all elements with values ending in 2 were removed + assertEquals("1.1.1.0", list.get(0).get("ipv4")); + assertEquals("2001::0", list.get(0).get("ipv6")); + assertEquals("1.1.1.1", list.get(1).get("ipv4")); + assertEquals("2001::1", list.get(1).get("ipv6")); + assertEquals("1.1.1.3", list.get(2).get("ipv4")); + assertEquals("2001::3", list.get(2).get("ipv6")); + assertEquals("1.1.1.4", list.get(3).get("ipv4")); + assertEquals("2001::4", list.get(3).get("ipv6")); + } + + // TODO: javadoc + @Test + public final void testRemove_StringString_ValueList() { + ctx.setAttribute("list[0]", "5"); + ctx.setAttribute("list[1]", "6"); + ctx.setAttribute("list[2]", "7"); + ctx.setAttribute("list[3]", "8"); + ctx.setAttribute("list[4]", "9"); + ctx.setAttribute("list_length", "5"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + list.remove("", "6"); + + // Check that size of list is 4 (1 less than original) + assertEquals(4, list.size()); + + // Check that value was remove from list + assertEquals(1, list.get(0).size()); + assertEquals("5", list.get(0).get("")); + assertEquals(1, list.get(1).size()); + assertEquals("7", list.get(1).get("")); + assertEquals(1, list.get(2).size()); + assertEquals("8", list.get(2).get("")); + assertEquals(1, list.get(3).size()); + assertEquals("9", list.get(3).get("")); + } + + // TODO: javadoc + @Test + public final void testRemove_Map() { + ctx.setAttribute("list[0].ipv4", "1.1.1.0"); + ctx.setAttribute("list[0].ipv6", "2001::0"); + ctx.setAttribute("list[1].ipv4", "1.1.1.1"); + ctx.setAttribute("list[1].ipv6", "2001::1"); + ctx.setAttribute("list[2].ipv4", "1.1.1.2"); + ctx.setAttribute("list[2].ipv6", "2001::2"); + ctx.setAttribute("list[3].ipv4", "1.1.1.3"); + ctx.setAttribute("list[3].ipv6", "2001::3"); + ctx.setAttribute("list[4].ipv4", "1.1.1.4"); + ctx.setAttribute("list[4].ipv6", "2001::4"); + ctx.setAttribute("list[5].ipv4", "1.1.1.2"); + ctx.setAttribute("list[5].ipv6", "2001::2"); + ctx.setAttribute("list_length", "6"); + + HashMap<String,String> remove_key = new HashMap<String,String>(); + remove_key.put("ipv4", "1.1.1.2"); + remove_key.put("ipv6", "2001::2"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + list.remove(remove_key); + + // Check that size of list is 4 (2 less than original) + assertEquals(4, list.size()); + + // Check that all elements with values ending in 2 were removed + assertEquals("1.1.1.0", list.get(0).get("ipv4")); + assertEquals("2001::0", list.get(0).get("ipv6")); + assertEquals("1.1.1.1", list.get(1).get("ipv4")); + assertEquals("2001::1", list.get(1).get("ipv6")); + assertEquals("1.1.1.3", list.get(2).get("ipv4")); + assertEquals("2001::3", list.get(2).get("ipv6")); + assertEquals("1.1.1.4", list.get(3).get("ipv4")); + assertEquals("2001::4", list.get(3).get("ipv6")); + } + + // TODO: javadoc + @Test + public final void testWriteToContext() { + ctx.setAttribute("list[0]", "0"); + ctx.setAttribute("list[1]", "1"); + ctx.setAttribute("list[2]", "2"); + ctx.setAttribute("list[3]", "3"); + ctx.setAttribute("list[4]", "4"); + ctx.setAttribute("list_length", "5"); + ctx.setAttribute("Other", "other"); + + SvcLogicContextList list = new SvcLogicContextList( ctx, "list" ); + + // Erase context memory + ctx = new SvcLogicContext(); + + // Write list back into context memory + list.writeToContext(ctx); + + // Check that size of list is 5 + assertEquals(5, list.size()); + + // Check that all list values exist in list object + assertEquals("0", ctx.getAttribute("list[0]")); + assertEquals("1", ctx.getAttribute("list[1]")); + assertEquals("2", ctx.getAttribute("list[2]")); + assertEquals("3", ctx.getAttribute("list[3]")); + assertEquals("4", ctx.getAttribute("list[4]")); + assertEquals("5", ctx.getAttribute("list_length")); + + // Check that old list values aren't in new list + assertNull(ctx.getAttribute("Other")); + } +} diff --git a/sliapi/.gitignore b/sliapi/.gitignore new file mode 100755 index 00000000..b73caf31 --- /dev/null +++ b/sliapi/.gitignore @@ -0,0 +1,34 @@ +#####standard .git ignore entries##### + +## IDE Specific Files ## +org.eclipse.core.resources.prefs +.classpath +.project +.settings +.idea +.externalToolBuilders +maven-eclipse.xml +workspace + +## Compilation Files ## +*.class +**/target +target +target-ide +MANIFEST.MF + +## Misc Ignores (OS specific etc) ## +bin/ +dist +*~ +*.ipr +*.iml +*.iws +classes +out/ +.DS_STORE +.metadata + +## Folders which contain auto generated source code ## +yang-gen-config +yang-gen-sal diff --git a/sliapi/README.txt b/sliapi/README.txt new file mode 100755 index 00000000..f9f4a2ab --- /dev/null +++ b/sliapi/README.txt @@ -0,0 +1,35 @@ +====================== +Introduction +====================== +You have generated an MD-SAL module using the Brocade Archetype. + +* You should be able to successfully run 'mvn clean install' on this project. +* This will produce a .zip file under the karaf.extension directory which you can deploy using +Brocade's extension deployment mechanism. + +====================== +Next Steps: +====================== +* run a 'mvn clean install' if you haven't already. This will generate some code from the yang models. +* Modify the model yang file under the model project. +* Follow the comments in the generated provider class to wire your new provider into the generated +code. +* Modify the generated provider model to respond to and handle the yang model. Depending on what +you added to your model you may need to inherit additional interfaces or make other changes to +the provider model. + +====================== +Generated Bundles: +====================== +* model + - Provides the yang model for your application. This is your primary northbound interface. +* provider + - Provides a template implementation for a provider to respond to your yang model. +* features + - Defines a karaf feature. If you add dependencies on third-party bundles then you will need to + modify the features.xml to list out the dependencies. +* karaf.extension + - Bundles all of the jars and third party dependencies (minus ODL dependencies) into a single + .zip file with the necessary configuration files to work correctly with the Brocade extension + mechanism. + diff --git a/sliapi/features/pom.xml b/sliapi/features/pom.xml new file mode 100755 index 00000000..fcc08eb7 --- /dev/null +++ b/sliapi/features/pom.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sliapi</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sliapi-features</artifactId> + + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-model</artifactId> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-provider</artifactId> + <classifier>config</classifier> + <type>xml</type> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-provider</artifactId> + </dependency> + + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <version>${odl.mdsal.features.version}</version> + <classifier>features</classifier> + <type>xml</type> + + <scope>runtime</scope> + </dependency> + + + + <!-- dependency for opendaylight-karaf-empty for use by testing --> + <dependency> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>opendaylight-karaf-empty</artifactId> + <version>${odl.karaf.empty.distro.version}</version> + <type>zip</type> + </dependency> + + + <dependency> + <!-- Required for launching the feature tests--> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>features-test</artifactId> + <scope>test</scope> + <version>${odl.commons.opendaylight.version}</version> + </dependency> + + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>features-yangtools</artifactId> + <version>${odl.yangtools.version}</version> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + <!-- launches the feature test, which validates that your karaf feature can + be installed inside of a karaf container. It doesn't validate that your + functionality works correctly, just that you have all of the dependent + bundles defined correctly. + <plugin> + + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.16</version> + <configuration> + <systemPropertyVariables> + <karaf.distro.groupId>org.opendaylight.odlparent</karaf.distro.groupId> + <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> + <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> + </systemPropertyVariables> + <dependenciesToScan> + <dependency>org.opendaylight.yangtools:features-test</dependency> + </dependenciesToScan> + </configuration> + </plugin> + --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/sliapi/features/src/main/resources/features.xml b/sliapi/features/src/main/resources/features.xml new file mode 100644 index 00000000..630b1115 --- /dev/null +++ b/sliapi/features/src/main/resources/features.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<features name="sdnc-sliapi-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features</repository> + + <feature name='sdnc-sliapi' description="sdnc-sliapi" version='${project.version}'> + <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> + <feature version="${odl.mdsal.version}">odl-mdsal-broker</feature> + <feature version="${sdnctl.sli.version}">sdnc-sli</feature> + <bundle>mvn:org.openecomp.sdnc.core/sliapi-model/${project.version}</bundle> + <bundle>mvn:org.openecomp.sdnc.core/sliapi-provider/${project.version}</bundle> + <configfile finalname="etc/opendaylight/karaf/200-sliapiprovider.xml">mvn:org.openecomp.sdnc.core/sliapi-provider/${project.version}/xml/config</configfile> + </feature> + +</features> diff --git a/sliapi/installer/pom.xml b/sliapi/installer/pom.xml new file mode 100755 index 00000000..a0204f3b --- /dev/null +++ b/sliapi/installer/pom.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sliapi</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sliapi-installer</artifactId> + <packaging>pom</packaging> + + <properties> + <application.name>sdnc-sliapi</application.name> + <features.boot>sdnc-sliapi</features.boot> + <features.repositories>mvn:org.openecomp.sdnc.core/sliapi-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencies> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-features</artifactId> + <version>${project.version}</version> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-provider</artifactId> + <version>${project.version}</version> + </dependency> + + + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${application.name}-${project.version}-installer</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <includeGroupIds>org.openecomp.sdnc.core</includeGroupIds> + <excludeArtifactIds>sli-common,sli-provider,dblib-provider</excludeArtifactIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals><!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/sliapi/installer/src/assembly/assemble_installer_zip.xml b/sliapi/installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 00000000..85e2e1e8 --- /dev/null +++ b/sliapi/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,59 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml b/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 00000000..18700a1b --- /dev/null +++ b/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,55 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + + <files> + <file> + <source>../provider/src/main/resources/initial/${feature-name}-provider.xml</source> + <destName>./etc/opendaylight/karaf/200-${feature-name}provider.xml</destName> + </file> + + </files> + +</assembly> diff --git a/sliapi/installer/src/main/resources/scripts/install-feature.sh b/sliapi/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 00000000..93236c5b --- /dev/null +++ b/sliapi/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/sliapi/model/pom.xml b/sliapi/model/pom.xml new file mode 100755 index 00000000..be8c8b3c --- /dev/null +++ b/sliapi/model/pom.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sliapi</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sliapi-model</artifactId> + <packaging>bundle</packaging> + + <build> + + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>*</Import-Package> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-maven-plugin</artifactId> + <version>${odl.yangtools.yang.maven.plugin.version}</version> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>maven-sal-api-gen-plugin</artifactId> + <version>${odl.sal.api.gen.plugin.version}</version> + <type>jar</type> + </dependency> + </dependencies> + <executions> + <execution> + <goals> + <goal>generate-sources</goal> + </goals> + <configuration> + <yangFilesRootDir>${yang.file.directory}</yangFilesRootDir> + <codeGenerators> + <generator> + <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass> + <outputBaseDir>${salGeneratorPath}</outputBaseDir> + </generator> + </codeGenerators> + <inspectDependencies>true</inspectDependencies> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>yang-binding</artifactId> + <version>${odl.mdsal.yang.binding.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-common</artifactId> + <version>${odl.yangtools.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-inet-types</artifactId> + <version>${odl.ietf-inet-types.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-yang-types</artifactId> + <version>${odl.ietf-yang-types.version}</version> + </dependency> + </dependencies> +</project> diff --git a/sliapi/model/src/main/yang/sliapi.yang b/sliapi/model/src/main/yang/sliapi.yang new file mode 100755 index 00000000..047fd690 --- /dev/null +++ b/sliapi/model/src/main/yang/sliapi.yang @@ -0,0 +1,111 @@ +module SLI-API { + + yang-version 1; + + namespace "org:openecomp:sdnc:sliapi"; + + prefix sample; + + import ietf-inet-types { prefix "inet"; revision-date 2010-09-24; } + + organization "openECOMP"; + + contact + "Dan Timoney"; + + description + "Defines API to service logic interpreter"; + + revision "2016-11-10" { + description + "REST API to Service Logic Interpreter"; + } + + grouping parameter-setting { + description + "Parameter setting"; + + leaf parameter-name { + type string; + description "Parameter name"; + } + + leaf int-value { + type int32; + } + leaf string-value { + type string; + } + leaf boolean-value { + type boolean; + } + } + + grouping response-fields { + leaf response-code { + type string; + } + leaf ack-final-indicator { + type string; + } + leaf response-message { + type string; + } + leaf context-memory-json { + type string; + } + } + + container test-results { + description "Test results"; + + list test-result { + key "test-identifier"; + + leaf test-identifier { + type string; + } + + leaf-list results { + type string; + } + } + } + + rpc execute-graph { + description " Method to add a new parameter."; + input { + + leaf module-name { + type string; + } + + leaf rpc-name { + type string; + } + + leaf mode { + type enumeration { + enum sync; + enum async; + } + } + + list sli-parameter { + key "parameter-name"; + uses parameter-setting; + } + } + + output { + uses response-fields; + } + } + + rpc healthcheck { + output { + uses response-fields; + } + } + +} diff --git a/sliapi/pom.xml b/sliapi/pom.xml new file mode 100755 index 00000000..06ee5e0e --- /dev/null +++ b/sliapi/pom.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + + <parent> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sdnc-core</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <packaging>pom</packaging> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <properties> + <feature-name>sliapi</feature-name> + </properties> + + <dependencyManagement> + + <dependencies> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-model</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-provider</artifactId> + <version>${project.version}</version> + <classifier>config</classifier> + <type>xml</type> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + + </dependencyManagement> + + <modules> + <module>model</module> + <module>features</module> + <module>provider</module> + <module>installer</module> + </modules> +</project> diff --git a/sliapi/provider/pom.xml b/sliapi/provider/pom.xml new file mode 100755 index 00000000..b4a6ff0f --- /dev/null +++ b/sliapi/provider/pom.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>sliapi</artifactId> + <groupId>org.openecomp.sdnc.core</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <artifactId>sliapi-provider</artifactId> + <packaging>bundle</packaging> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package>org.opendaylight.controller.config.yang.config.sliapi.impl</Export-Package> + <Import-Package>*</Import-Package> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-maven-plugin</artifactId> + <version>${odl.yangtools.yang.maven.plugin.version}</version> + <executions> + <execution> + <id>config</id> + <goals> + <goal>generate-sources</goal> + </goals> + <configuration> + <codeGenerators> + <generator> + <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass> + <outputBaseDir>${jmxGeneratorPath}</outputBaseDir> + <additionalConfiguration> + <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1> + </additionalConfiguration> + </generator> + <generator> + <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass> + <outputBaseDir>${salGeneratorPath}</outputBaseDir> + </generator> + </codeGenerators> + <inspectDependencies>true</inspectDependencies> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>maven-sal-api-gen-plugin</artifactId> + <version>${odl.sal.api.gen.plugin.version}</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>yang-jmx-generator-plugin</artifactId> + <version>${odl.yang.jmx.generator.version}</version> + </dependency> + </dependencies> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/initial/sliapi-provider.xml</file> + <type>xml</type> + <classifier>config</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sliapi-model</artifactId> + </dependency> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>config-api</artifactId> + <version>${odl.controller.config.api.version}</version> + </dependency> + + + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>sal-binding-config</artifactId> + <version>${odl.mdsal.version}</version> + </dependency> + + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>sal-binding-api</artifactId> + <version>${odl.mdsal.version}</version> + </dependency> + + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>sal-common-util</artifactId> + <version>${odl.mdsal.version}</version> + </dependency> + + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>sal-core-api</artifactId> + <version>${odl.mdsal.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-data-impl</artifactId> + <version>${odl.yangtools.version}</version> + </dependency> + </dependencies> +</project> diff --git a/sliapi/provider/src/main/java/org/opendaylight/yang/gen/v1/org/openecomp/sdnc/sliapi/provider/impl/rev140523/SliapiProviderModule.java b/sliapi/provider/src/main/java/org/opendaylight/yang/gen/v1/org/openecomp/sdnc/sliapi/provider/impl/rev140523/SliapiProviderModule.java new file mode 100644 index 00000000..e05103cd --- /dev/null +++ b/sliapi/provider/src/main/java/org/opendaylight/yang/gen/v1/org/openecomp/sdnc/sliapi/provider/impl/rev140523/SliapiProviderModule.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.provider.impl.rev140523; + +import org.openecomp.sdnc.sliapi.sliapiProvider; + +public class SliapiProviderModule extends org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.provider.impl.rev140523.AbstractSliapiProviderModule { + public SliapiProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public SliapiProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.provider.impl.rev140523.SliapiProviderModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + + final sliapiProvider provider = new sliapiProvider(); + provider.setDataBroker( getDataBrokerDependency() ); + provider.setNotificationService( getNotificationServiceDependency() ); + provider.setRpcRegistry( getRpcRegistryDependency() ); + provider.initialize(); + return new AutoCloseable() { + + @Override + public void close() throws Exception { + //TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE BROKER/NOTIFICATION + //SERVIE/RPC REGISTRY + provider.close(); + } + }; + } + +} diff --git a/sliapi/provider/src/main/java/org/opendaylight/yang/gen/v1/org/openecomp/sdnc/sliapi/provider/impl/rev140523/SliapiProviderModuleFactory.java b/sliapi/provider/src/main/java/org/opendaylight/yang/gen/v1/org/openecomp/sdnc/sliapi/provider/impl/rev140523/SliapiProviderModuleFactory.java new file mode 100644 index 00000000..fbd20365 --- /dev/null +++ b/sliapi/provider/src/main/java/org/opendaylight/yang/gen/v1/org/openecomp/sdnc/sliapi/provider/impl/rev140523/SliapiProviderModuleFactory.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +/* +* Generated file +* +* Generated from: yang module name: slitester-provider-impl yang module local name: sliapi-provider-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Oct 21 10:42:49 EDT 2016 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.provider.impl.rev140523; +public class SliapiProviderModuleFactory extends org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.provider.impl.rev140523.AbstractSliapiProviderModuleFactory { + +} diff --git a/sliapi/provider/src/main/java/org/openecomp/sdnc/sliapi/SliapiHelper.java b/sliapi/provider/src/main/java/org/openecomp/sdnc/sliapi/SliapiHelper.java new file mode 100644 index 00000000..4ad4f016 --- /dev/null +++ b/sliapi/provider/src/main/java/org/openecomp/sdnc/sliapi/SliapiHelper.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sliapi; + +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.ExecuteGraphInputBuilder; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.execute.graph.input.SliParameterBuilder; +import org.openecomp.sdnc.sli.provider.MdsalHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SliapiHelper extends MdsalHelper { + + private static final Logger LOG = LoggerFactory.getLogger(SliapiHelper.class); + + static { + ExecuteGraphInputBuilder b1 = new ExecuteGraphInputBuilder(); + SliParameterBuilder b2 = new SliParameterBuilder(); + + } + +} diff --git a/sliapi/provider/src/main/java/org/openecomp/sdnc/sliapi/sliapiProvider.java b/sliapi/provider/src/main/java/org/openecomp/sdnc/sliapi/sliapiProvider.java new file mode 100644 index 00000000..705277c6 --- /dev/null +++ b/sliapi/provider/src/main/java/org/openecomp/sdnc/sliapi/sliapiProvider.java @@ -0,0 +1,557 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdnc.sliapi; + +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.Properties; +import java.util.concurrent.Future; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.ExecuteGraphInput; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.ExecuteGraphInput.Mode; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.ExecuteGraphInputBuilder; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.ExecuteGraphOutput; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.ExecuteGraphOutputBuilder; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.HealthcheckOutput; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.HealthcheckOutputBuilder; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.SLIAPIService; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.TestResults; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.execute.graph.input.SliParameter; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.test.results.TestResult; +import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.sliapi.rev161110.test.results.TestResultBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; +import org.openecomp.sdnc.sli.provider.SvcLogicService; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; + + +/** + * Defines a base implementation for your provider. This class extends from a helper class + * which provides storage for the most commonly used components of the MD-SAL. Additionally the + * base class provides some basic logging and initialization / clean up methods. + * + * To use this, copy and paste (overwrite) the following method into the TestApplicationProviderModule + * class which is auto generated under src/main/java in this project + * (created only once during first compilation): + * + * <pre> + + @Override + public java.lang.AutoCloseable createInstance() { + + final sliapiProvider provider = new sliapiProvider(); + provider.setDataBroker( getDataBrokerDependency() ); + provider.setNotificationService( getNotificationServiceDependency() ); + provider.setRpcRegistry( getRpcRegistryDependency() ); + provider.initialize(); + return new AutoCloseable() { + + @Override + public void close() throws Exception { + //TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE BROKER/NOTIFICATION + //SERVIE/RPC REGISTRY + provider.close(); + } + }; + } + + + </pre> + */ +public class sliapiProvider implements AutoCloseable, SLIAPIService{ + + private final Logger LOG = LoggerFactory.getLogger( sliapiProvider.class ); + private final String appName = "slitester"; + + protected DataBroker dataBroker; + protected DOMDataBroker domDataBroker; + protected NotificationProviderService notificationService; + protected RpcProviderRegistry rpcRegistry; + + protected BindingAwareBroker.RpcRegistration<SLIAPIService> rpcRegistration; + + private static String SLIAPI_NAMESPACE = "org:openecomp:sdnc:sliapi"; + private static String SLIAPI_REVISION = "2016-11-10"; + + private static QName TEST_RESULTS_QNAME = null; + private static QName TEST_RESULT_QNAME = null; + private static QName TEST_ID_QNAME = null; + private static QName RESULTS_QNAME = null; + + static { + + TEST_RESULTS_QNAME = QName.create(SLIAPI_NAMESPACE, SLIAPI_REVISION, "test-results"); + TEST_RESULT_QNAME = QName.create(TEST_RESULTS_QNAME, "test-result"); + TEST_ID_QNAME = QName.create(TEST_RESULT_QNAME, "test-identifier"); + RESULTS_QNAME = QName.create(TEST_RESULT_QNAME, "results"); + } + + + public sliapiProvider() { + this.LOG.info( "Creating provider for " + appName ); + } + + public void initialize(){ + LOG.info( "Initializing provider for " + appName ); + //initialization code goes here. + + rpcRegistration = rpcRegistry.addRpcImplementation(SLIAPIService.class, this); + LOG.info( "Initialization complete for " + appName ); + } + + protected void initializeChild() { + //Override if you have custom initialization intelligence + } + + @Override + public void close() throws Exception { + LOG.info( "Closing provider for " + appName ); + //closing code goes here + + rpcRegistration.close(); + LOG.info( "Successfully closed provider for " + appName ); + } + + public void setDataBroker(DataBroker dataBroker) { + this.dataBroker = dataBroker; + if (dataBroker instanceof AbstractForwardedDataBroker) { + domDataBroker = ((AbstractForwardedDataBroker) dataBroker).getDelegate(); + } + if( LOG.isDebugEnabled() ){ + LOG.debug( "DataBroker set to " + (dataBroker==null?"null":"non-null") + "." ); + } + } + + public void setNotificationService( + NotificationProviderService notificationService) { + this.notificationService = notificationService; + if( LOG.isDebugEnabled() ){ + LOG.debug( "Notification Service set to " + (notificationService==null?"null":"non-null") + "." ); + } + } + + public void setRpcRegistry(RpcProviderRegistry rpcRegistry) { + this.rpcRegistry = rpcRegistry; + if( LOG.isDebugEnabled() ){ + LOG.debug( "RpcRegistry set to " + (rpcRegistry==null?"null":"non-null") + "." ); + } + } + + @Override + public Future<RpcResult<ExecuteGraphOutput>> executeGraph(ExecuteGraphInput input) { + RpcResult<ExecuteGraphOutput> rpcResult = null; + + SvcLogicService svcLogic = getSvcLogicService(); + ExecuteGraphOutputBuilder respBuilder = new ExecuteGraphOutputBuilder(); + + String calledModule = input.getModuleName(); + String calledRpc = input.getRpcName(); + Mode calledMode = input.getMode(); + String modeStr = "sync"; + + if (calledMode == Mode.Async) { + modeStr = "async"; + } + + if (svcLogic == null) { + respBuilder.setResponseCode("500"); + respBuilder.setResponseMessage("Could not locate OSGi SvcLogicService service"); + respBuilder.setAckFinalIndicator("Y"); + + rpcResult = RpcResultBuilder.<ExecuteGraphOutput> status(true).withResult(respBuilder.build()).build(); + return(Futures.immediateFuture(rpcResult)); + } + + + try { + if (!svcLogic.hasGraph(calledModule, calledRpc, null, modeStr)) { + respBuilder.setResponseCode("404"); + respBuilder.setResponseMessage("Directed graph for "+calledModule+"/"+calledRpc+"/"+modeStr+" not found"); + respBuilder.setAckFinalIndicator("Y"); + + rpcResult = RpcResultBuilder.<ExecuteGraphOutput> status(true).withResult(respBuilder.build()).build(); + return(Futures.immediateFuture(rpcResult)); + } + } catch (Exception e) { + LOG.error("Caught exception looking for directed graph for "+calledModule+"/"+calledRpc+"/"+modeStr, e); + + respBuilder.setResponseCode("500"); + respBuilder.setResponseMessage("Internal error : could not determine if target graph exists"); + respBuilder.setAckFinalIndicator("Y"); + + rpcResult = RpcResultBuilder.<ExecuteGraphOutput> status(true).withResult(respBuilder.build()).build(); + return(Futures.immediateFuture(rpcResult)); + } + + // Load properties + Properties parms = new Properties(); + + // Pass properties using names from sli-parameters + for (SliParameter sliParm : input.getSliParameter()) { + + String propValue = ""; + + Boolean boolval = sliParm.isBooleanValue(); + + if (boolval != null) { + propValue = boolval.toString(); + } else { + Integer intval = sliParm.getIntValue(); + if (intval != null) { + propValue = intval.toString(); + } else { + propValue = sliParm.getStringValue(); + if (propValue == null) { + propValue = ""; + } + } + } + parms.setProperty(sliParm.getParameterName(), propValue); + } + + // Also, pass "meta" properties (i.e. pass SliParameter objects themselves) + ExecuteGraphInputBuilder inputBuilder = new ExecuteGraphInputBuilder(input); + + SliapiHelper.toProperties(parms, "input", inputBuilder); + + try { + LOG.info("Calling directed graph for "+calledModule+"/"+calledRpc+"/"+modeStr); + + if (LOG.isTraceEnabled()) { + StringBuffer argList = new StringBuffer(); + argList.append("Parameters : {"); + Enumeration e = parms.propertyNames(); + while (e.hasMoreElements()) { + String propName = (String) e.nextElement(); + argList.append(" ("+propName+","+parms.getProperty(propName)+") "); + } + argList.append("}"); + LOG.trace(argList.toString()); + argList = null; + } + + + + Properties respProps = svcLogic.execute(calledModule, calledRpc, + null, modeStr, parms, domDataBroker); + + StringBuilder sb = new StringBuilder("{"); + + for (Object key : respProps.keySet()) { + String keyValue = (String) key; + if (keyValue != null && !"".equals(keyValue) && !keyValue.contains("input.sli-parameter")) { + sb.append("\"").append(keyValue).append("\": \"").append(respProps.getProperty(keyValue)).append("\","); + } + } + + sb.setLength(sb.length() - 1); + sb.append("}"); + + respBuilder.setResponseCode(respProps.getProperty("error-code", "0")); + respBuilder.setResponseMessage(respProps.getProperty("error-message", ""));// TODO change response-text to response-message to match other BVC APIs + respBuilder.setAckFinalIndicator(respProps.getProperty("ack-final", "Y")); + respBuilder.setContextMemoryJson(sb.toString()); + + TestResultBuilder testResultBuilder = new TestResultBuilder(); + + SliapiHelper.toBuilder(respProps, testResultBuilder); + + String testIdentifier = testResultBuilder.getTestIdentifier(); + + if ((testIdentifier != null) && (testIdentifier.length() > 0)) { + + // Add test results to config tree + LOG.debug("Saving test results for test id "+testIdentifier); + + DomSaveTestResult(testResultBuilder.build(), true, LogicalDatastoreType.CONFIGURATION); + + } + + } catch (Exception e) { + LOG.error("Caught exception executing directed graph for" + + calledModule + ":" + calledRpc + "," + modeStr + ">", e); + + respBuilder.setResponseCode("500"); + respBuilder + .setResponseMessage("Internal error : caught exception executing directed graph " + + calledModule + + "/" + + calledRpc + + "/" + + modeStr); + respBuilder.setAckFinalIndicator("Y"); + + } + + rpcResult = RpcResultBuilder.<ExecuteGraphOutput> status(true) + .withResult(respBuilder.build()).build(); + return (Futures.immediateFuture(rpcResult)); + } + + + private SvcLogicService getSvcLogicService() { + BundleContext bctx = FrameworkUtil.getBundle(SvcLogicService.class).getBundleContext(); + + SvcLogicService svcLogic = null; + + // Get SvcLogicService reference + ServiceReference sref = bctx.getServiceReference(SvcLogicService.NAME); + if (sref != null) + { + svcLogic = (SvcLogicService) bctx.getService(sref); + + } + else + { + LOG.warn("Cannot find service reference for "+SvcLogicService.NAME); + + } + + return(svcLogic); + } + + @Override + public Future<RpcResult<HealthcheckOutput>> healthcheck() { + + RpcResult<HealthcheckOutput> rpcResult = null; + SvcLogicService svcLogic = getSvcLogicService(); + + HealthcheckOutputBuilder respBuilder = new HealthcheckOutputBuilder(); + + String calledModule = "sli"; + String calledRpc = "healthcheck"; + String modeStr = "sync"; + + if (svcLogic == null) { + respBuilder.setResponseCode("500"); + respBuilder.setResponseMessage("Could not locate OSGi SvcLogicService service"); + respBuilder.setAckFinalIndicator("Y"); + + rpcResult = RpcResultBuilder.<HealthcheckOutput> failed().withResult(respBuilder.build()).build(); + return(Futures.immediateFuture(rpcResult)); + } + + try { + if (!svcLogic.hasGraph(calledModule, calledRpc, null, modeStr)) { + respBuilder.setResponseCode("404"); + respBuilder.setResponseMessage("Directed graph for "+calledModule+"/"+calledRpc+"/"+modeStr+" not found"); + + respBuilder.setAckFinalIndicator("Y"); + + rpcResult = RpcResultBuilder.<HealthcheckOutput> status(true).withResult(respBuilder.build()).build(); + return(Futures.immediateFuture(rpcResult)); + } + } catch (Exception e) { + LOG.error("Caught exception looking for directed graph for "+calledModule+"/"+calledRpc+"/"+modeStr, e); + + respBuilder.setResponseCode("500"); + respBuilder.setResponseMessage("Internal error : could not determine if target graph exists"); + respBuilder.setAckFinalIndicator("Y"); + + rpcResult = RpcResultBuilder.<HealthcheckOutput> failed().withResult(respBuilder.build()).build(); + return(Futures.immediateFuture(rpcResult)); + } + + try { + LOG.info("Calling directed graph for "+calledModule+"/"+calledRpc+"/"+modeStr); + + Properties parms = new Properties(); + + Properties respProps = svcLogic.execute(calledModule, calledRpc, + null, modeStr, parms); + + respBuilder.setResponseCode(respProps.getProperty("error-code", "0")); + respBuilder.setResponseMessage(respProps.getProperty("error-message", "")); + respBuilder.setAckFinalIndicator(respProps.getProperty("ack-final", "Y")); + + } catch (Exception e) { + LOG.error("Caught exception executing directed graph for" + + calledModule + ":" + calledRpc + "," + modeStr + ">", e); + + respBuilder.setResponseCode("500"); + respBuilder + .setResponseMessage("Internal error : caught exception executing directed graph " + + calledModule + + "/" + + calledRpc + + "/" + + modeStr); + respBuilder.setAckFinalIndicator("Y"); + + } + + rpcResult = RpcResultBuilder.<HealthcheckOutput> status(true) + .withResult(respBuilder.build()).build(); + return (Futures.immediateFuture(rpcResult)); + } + + private void DomSaveTestResult(final TestResult entry, boolean merge, LogicalDatastoreType storeType) { + + + if (domDataBroker == null) { + LOG.error("domDataBroker unset - cannot save test result using DOMDataBroker"); + return; + } + + MapEntryNode resultNode = null; + + try { + resultNode = toMapEntryNode(entry); + } catch (Exception e) { + LOG.error("Caught exception trying to create map entry node", e); + } + + if (resultNode == null) { + LOG.error("Could not convert entry to MapEntryNode"); + return; + } + + + YangInstanceIdentifier testResultsPid = YangInstanceIdentifier.builder().node(TEST_RESULTS_QNAME).node(QName.create(TEST_RESULTS_QNAME, "test-result")).build(); + YangInstanceIdentifier testResultPid = testResultsPid.node(new NodeIdentifierWithPredicates(TEST_RESULT_QNAME, resultNode.getIdentifier().getKeyValues())); + + + + int tries = 2; + while(true) { + try { + DOMDataWriteTransaction wtx = domDataBroker.newWriteOnlyTransaction(); + if (merge) { + LOG.info("Merging test identifier "+entry.getTestIdentifier()); + wtx.merge(storeType, testResultPid, resultNode); + } else { + LOG.info("Putting test identifier "+entry.getTestIdentifier()); + wtx.put(storeType, testResultPid, resultNode); + } + wtx.submit().checkedGet(); + LOG.trace("Update DataStore succeeded"); + break; + } catch (final TransactionCommitFailedException e) { + if(e instanceof OptimisticLockFailedException) { + if(--tries <= 0) { + LOG.trace("Got OptimisticLockFailedException on last try - failing "); + throw new IllegalStateException(e); + } + LOG.trace("Got OptimisticLockFailedException - trying again "); + } else { + LOG.trace("Update DataStore failed"); + throw new IllegalStateException(e); + } + } + } + + } + + private void SaveTestResult(final TestResult entry, boolean merge, LogicalDatastoreType storeType) throws IllegalStateException + { + // Each entry will be identifiable by a unique key, we have to create that identifier + InstanceIdentifier.InstanceIdentifierBuilder<TestResult> testResultIdBuilder = + InstanceIdentifier.<TestResults>builder(TestResults.class) + .child(TestResult.class, entry.getKey()); + InstanceIdentifier<TestResult> path = testResultIdBuilder.toInstance(); + int tries = 2; + while(true) { + try { + WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); + if (merge) { + tx.merge(storeType, path, entry); + } else { + tx.put(storeType, path, entry); + } + tx.submit().checkedGet(); + LOG.trace("Update DataStore succeeded"); + break; + } catch (final TransactionCommitFailedException e) { + if(e instanceof OptimisticLockFailedException) { + if(--tries <= 0) { + LOG.trace("Got OptimisticLockFailedException on last try - failing "); + throw new IllegalStateException(e); + } + LOG.trace("Got OptimisticLockFailedException - trying again "); + } else { + LOG.trace("Update DataStore failed"); + throw new IllegalStateException(e); + } + } + } + } + + private MapEntryNode toMapEntryNode(TestResult testResult) { + + + YangInstanceIdentifier testResultId = YangInstanceIdentifier.builder().node(TEST_RESULTS_QNAME).node(TEST_RESULT_QNAME).build(); + + // Construct results list + LinkedList<LeafSetEntryNode<Object>> entryList = new LinkedList<LeafSetEntryNode<Object>>(); + for (String result : testResult.getResults()) { + LeafSetEntryNode<Object> leafSetEntryNode = ImmutableLeafSetEntryNodeBuilder.create() + .withNodeIdentifier(new NodeWithValue(RESULTS_QNAME, result)) + .withValue(result) + .build(); + entryList.add(leafSetEntryNode); + } + // Construct results LeafSetNode + LeafSetNode<?> resultsNode = ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(RESULTS_QNAME)).withValue(entryList).build(); + + + + // Construct test result ContainerNode with 2 children - test-identifier leaf and results leaf-set + MapEntryNode testResultNode = ImmutableNodes.mapEntryBuilder() + .withNodeIdentifier(new NodeIdentifierWithPredicates(TEST_RESULT_QNAME, TEST_ID_QNAME, testResult.getTestIdentifier())) + .withChild(ImmutableNodes.leafNode(TEST_ID_QNAME, testResult.getTestIdentifier())) + .withChild(resultsNode) + .build(); + + return(testResultNode); + + } + +} diff --git a/sliapi/provider/src/main/resources/initial/sliapi-provider.xml b/sliapi/provider/src/main/resources/initial/sliapi-provider.xml new file mode 100644 index 00000000..fd2ccbee --- /dev/null +++ b/sliapi/provider/src/main/resources/initial/sliapi-provider.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- vi: set et smarttab sw=4 tabstop=4: --> +<snapshot> + <configuration> + <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> + <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config"> + <module> + + <!-- This xmlns:prefix should match the namespace in the *-provider-impl.yang file + The prefix: inside type should match the prefix of the yang file. --> + <type xmlns:prefix="org:openecomp:sdnc:sliapi:provider:impl"> + prefix:sliapi-provider-impl + </type> + <name>sliapi-provider-impl</name> + + <!-- The following sections contain bindings to services defined in the + *-provider-impl yang file. For example the rpc-registry is required + because we have a dependency (or augmentation) named "rpc-registry" + and which binds to the md-sa-binding-registry. If you remove those + dependencies from the yang file then you can remove them from here. --> + <rpc-registry> + <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type> + <name>binding-rpc-broker</name> + </rpc-registry> + + <data-broker> + <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type> + <name>binding-data-broker</name> + </data-broker> + + <notification-service> + <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding"> + binding:binding-notification-service + </type> + <name>binding-notification-broker</name> + </notification-service> + </module> + + </modules> + </data> + + </configuration> + + <!-- Required capabilities are basically a listing of all modules that need to be imported before + our service can be resolved. Capabilities for dependencies defined above are implied which is + why we do not have define a required capability for the data broker, for example. --> + <required-capabilities> + <capability>org:openecomp:sdnc:sliapi:provider:impl?module=sliapi-provider-impl&revision=2014-05-23</capability> + </required-capabilities> + +</snapshot> diff --git a/sliapi/provider/src/main/yang/sliapi-provider-impl.yang b/sliapi/provider/src/main/yang/sliapi-provider-impl.yang new file mode 100755 index 00000000..b32ff6c3 --- /dev/null +++ b/sliapi/provider/src/main/yang/sliapi-provider-impl.yang @@ -0,0 +1,61 @@ +module sliapi-provider-impl { + + yang-version 1; + namespace "org:openecomp:sdnc:sliapi:provider:impl"; + prefix "sliapi-provider-impl"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; } + + description + "This module contains the base YANG definitions for + sliapi-provider impl implementation."; + + revision "2014-05-23" { + description + "Initial revision."; + } + + // This is the definition of the service implementation as a module identity. + identity sliapi-provider-impl { + base config:module-type; + + // Specifies the prefix for generated java classes. + config:java-name-prefix sliapiProvider; + } + + // Augments the 'configuration' choice node under modules/module. + // We consume the three main services, RPCs, DataStore, and Notifications + augment "/config:modules/config:module/config:configuration" { + case sliapi-provider-impl { + when "/config:modules/config:module/config:type = 'sliapi-provider-impl'"; + + container rpc-registry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-rpc-registry; + } + } + } + + container notification-service { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-notification-service; + } + } + } + + container data-broker { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity mdsal:binding-async-data-broker; + } + } + } + } + } +} diff --git a/src/site/apt/nodes.apt b/src/site/apt/nodes.apt new file mode 100644 index 00000000..b8ce9879 --- /dev/null +++ b/src/site/apt/nodes.apt @@ -0,0 +1,953 @@ +~~~ +~~ ============LICENSE_START======================================================= +~~ openECOMP : SDN-C +~~ ================================================================================ +~~ Copyright (C) 2017 AT&T Intellectual Property. All rights +~~ reserved. +~~ ================================================================================ +~~ Licensed under the Apache License, Version 2.0 (the "License"); +~~ you may not use this file except in compliance with the License. +~~ You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, software +~~ distributed under the License is distributed on an "AS IS" BASIS, +~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +~~ See the License for the specific language governing permissions and +~~ limitations under the License. +~~ ============LICENSE_END========================================================= +~~~ + + --- + Service Logic Interpreter + --- + Dan Timoney + --- + 2014-11-12 + --- + +Supported node types + + The following built-in node types are currently supported: + + * Flow Control + + * {{{Block node}<<block>>}} + + * {{{Call node}<<call>>}} + + * {{{For node}<<for>>}} + + * {{{Return node}<<return>>}} + + * {{{Set node}<<set>>}} + + * {{{Switch node}<<switch>>}} + + * Device Management + + * {{{Configure node}<<configure>>}} + + * Java Plugin Support + + * {{{Execute node}<<execute>>}} + + * Recording + + * {{{Record node}<<record>>}} + + * Resource Management + + * {{{Delete node}<<delete>>}} + + * {{{Exists node}<<exists>>}} + + * {{{Get-resource node}<<get-resource>>}} + + * {{{Is-available node}<<is-available>>}} + + * {{{Notify node}<<notify>>}} + + * {{{Release node}<<release>>}} + + * {{{Reserve node}<<reserve>>}} + + * {{{Save node}<<save>>}} + + * {{{Update node}<<update>>}} + + +* Flow Control + +** Block node + +*** Description + + A <<block>> node is used to executes a set of nodes. + +*** Attributes + +*--------------*--------------------------------------------+ +| <<atomic>> | if <true>, then if a node returns failure, subsequent nodes will not be executed and nodes already executed will be backed out. +*--------------*--------------------------------------------+ + +*** Parameters + + None + +*** Outcomes + + None + +*** Example + ++-----------------+ +<block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="RESERVED"/> + <parameter name="field3" value="$asePort.uni_circuit_id"/> + </record> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> +</block> ++-----------------+ + + + +**Call node + +*** Description + + A <<call>> node is used to call another graph + +*** Attributes + +*--------------*-------+ +| <<module>> | Module of directed graph to call. If unset, defaults to that of calling graph +*--------------*-------+ +| <<rpc>> | rpc of directed graph to call. +*--------------*-------+ +| <<version>> | version of graph to call, If unset, uses active version. +*--------------*-------+ +| <<mode>> | mode (sync/async) of graph to call. If unset, defaults to that of calling graph. +*--------------*-------+ + + + +*** Parameters + + Not applicable + +*** Outcomes + +*----------*---------+ +| <<success>> | Sub graph returned success +*----------*---------+ +| <<not-found>> | Graph not found +*----------*---------+ +| <<failure>> | Subgraph returned success +*----------*---------+ + . + +*** Example + ++-------------------+ +<call rpc="svc-topology-reserve" mode="sync" /> ++-------------------+ + +**For node + +*** Description + + A <<for>> node provides a fixed iteration looping mechanism, similar to the Java for loop + +*** Attributes + +*--------------*-------+ +| <<index>> | index variable +*--------------*-------+ +| <<start>> | initial value +*--------------*-------+ +| <<end>> | maximum value +*--------------*-------+ + + +*** Parameters + + Not applicable. + +*** Outcomes + + Not applicable. The <<status>> node has no outcomes. + +*** Example + ++-------------------+ +<for index="i" start="0" end="`$service-data.universal-cpe-ft.l2-switch-interfaces_length`"> + <record plugin="org.openecomp.sdnc.sli.recording.Slf4jRecorder"> + <parameter name="logger" value="message-log"/> + <parameter name="level" value="info"/> + <parameter name="field1" value="`'current l2-switch-interface name is ' + $service-data.universal-cpe-ft.l2-switch-interfaces[$i].name`"/> + </record> +</for> ++-------------------+ + +**Return node + +*** Description + + A <<return>> node is used to return a status to the invoking MD-SAL application + +*** Attributes + +*--------------*-------+ +| <<status>> | Status value to return (<success> or <failure>) +*--------------*-------+ + + +*** Parameters + + The following optional parameters may be passed to convey more + detailed status information. + +*------------*-----------+ +| <<error-code>> | A brief, usually numeric, code indicating the error condition +*------------*-----------+ +| <<error-message>> | A more detailed error message +*------------*-----------+ + +*** Outcomes + + Not applicable. The <<status>> node has no outcomes. + +*** Example + ++-------------------+ +<return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Activation failure" /> +</return> ++-------------------+ + +**Set node + +*** Description + + A <<set>> node is used to set one or more values in the execution context + +*** Attributes + +*--------------*-------+ +| <<only-if-unset>> | If true the set node will only execute if the current value of the target is null +*--------------*-------+ + +*** Parameters + + Values to be set are passed as parameters + +*** Outcomes + + Not applicable. The <<set>> node has no outcomes. + +*** Example + ++-------------------+ +<set> + <parameter name="vlan" value="$network.provider-segmentation-id" /> +</set> ++-------------------+ + +**Switch node + +*** Description + + A <<switch>> node is used to make a decision based on its <<test>> attribute. + +*** Attributes + +*--------------*-------+ +| <<test>> | Condition to test +*--------------*-------+ + + +*** Parameters + + None + + +*** Outcomes + + Depends on the <<test>> condition + +*** Example + ++-------------------+ +<switch test="$uni-cir-units"> + <outcome value="Mbps"> + <reserve plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value" + pfx="asePort"> + + <outcome value="success"> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" value="No ports found that match criteria" /> + </return> + </outcome> + </reserve> + </outcome> + <outcome value="Gbps"> + <reserve plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value*1000" + pfx="asePort"> + + <outcome value="success"> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" value="No ports found that match criteria" /> + </return> + </outcome> + </reserve> + </outcome> +</switch> ++-------------------+ + +* Device Management + +**Configure node + +*** Description + + A <<configure>> node is used to configure a device. + +*** Attributes + +*--------------*-------+ +| <<adaptor>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<activate>> | Activate device/interface, for devices that support a separate activation step. +*--------------*-------+ +| <<key>> | SQL-like string specifying criteria for item to configure +*--------------*-------+ + +*** Parameters + + Specific to device adaptor. + +*** Outcomes + +*-----------*-------+ +| <<success>> | Device successfully configured +*-----------*-------+ +| <<not-found>> | Element to be configured does not exist. +*-----------*--------+ +| <<not-ready>> | Element is not in a state where it can be configured/activated +*-----------*-------+ +| <<already-active>> | Attempt to activate element that is already active +*-----------*-------+ +| <<failure>> | Configure failed for some other reason +*-----------*-------+ + +*** Example + ++-------------------+ +<configure adaptor="org.openecomp.sdnc.sli.adaptor.emt.EmtAdaptor" + key="$uni-circuit-id" activate="true"> + <parameter name="circuit.id" value="$uni-circuit-id" /> + <parameter name="subscriber.name" value="$subscriber-name" /> + <parameter name="emt.clli" value="$edge-device-clli" /> + <parameter name="port.tagging" value="$port-tagging" /> + <parameter name="port.mediaSpeed" value="$media-speed" /> + <parameter name="location.state" value="$uni-location-state" /> + <parameter name="location.city" value="$uni-location-city" /> + <parameter name="cosCategory" value="$cos-category" /> + <parameter name="gosProfile" value="$gos-profile" /> + <parameter name="lldp" value="$asePort.resource-lldp" /> + <parameter name="mtu" value="$asePort.resource-mtu" /> + <outcome value="success"> + <block> + <record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="ACTIVE"/> + <parameter name="field3" value="$uni-circuit-id"/> + </record> + <return status="success"> + <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" /> + </return> + </block> + </outcome> + <outcome value="already-active"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Port already active" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Activation failure" /> + </return> + </outcome> +</configure> ++-------------------+ + +* Java Plugin Support + +**Execute node + +*** Description + + An <<execute>> node is used to execute Java code supplied as a plugin + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of plugin to be used +*--------------*-------+ +| <<method>> | Name of method in the plugin class to execute. Method must return void, and take 2 arguments: a Map (for parameters) and a SvcLogicContext (to allow plugin read/write access to context memory) +*--------------*-------+ + +*** Parameters + + Specific to plugin / method + +*** Outcomes + +*-----------*-------+ +| <<success>> | Device successfully configured +*-----------*-------+ +| <<not-found>> | Plugin class could not be loaded +*-----------*--------+ +| <<unsupported-method>> | Named method taking (Map, SvcLogicContext) could not be found +*-----------*-------+ +| <<failure>> | Configure failed for some other reason +*-----------*-------+ + +*** Example + ++-------------------+ +<execute plugin="org.openecomp.sdnc.sli.plugin.HelloWorld" + method="log"> + <parameter name="message" value="Hello, world!" /> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Could not locate plugin" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Internal error" /> + </return> + </outcome> +</execute> ++-------------------+ + +* Recording + +** Record node + +*** Description + + A <<record>> node is used to record an event. For example, this might be used + to log provisioning events. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class to handle recording. +*--------------*-------+ + + +*** Parameters + + Parameters will depend on the plugin being used. For the FileRecorder class, + the parameters are as follows + +*------------*-----------+ +| <<file>> | The file to which the record should be written +*------------*-----------+ +| <<field1>> | First field to write. There will be <<field>> parameters for each field to write, from <<field1>> through <<fieldN>>. A special value __TIMESTAMP__ may be assigned to a field to insert the current timestamp +*------------*-----------+ + + +*** Outcomes + +*----------*---------+ +| <<success>> | Record successfully written +*----------*---------+ +| <<failure>> | Record could not be successfully written +*----------*---------+ + +*** Example + ++-------------------+ +<record plugin="org.openecomp.sdnc.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="ACTIVE"/> + <parameter name="field3" value="$uni-circuit-id"/> +</record> ++-------------------+ + +* Resource Management + +** Delete node + +*** Description + + A <<delete>> node is used to delete a resource from the local resource inventory. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to delete +*--------------*-------+ +| <<key>> | SQL-like string specifying key to delete +*--------------*-------+ + +*** Parameters + + None + +*** Outcomes + +*-----------*-------+ +| <<success>> | Resource specified deleted successfully. +*-----------*-------+ +| <failure>> | Resource specified was not deleted +*-----------*-------+ + +*** Example + ++-------------------+ +<delete plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="true"> + <return status="success"/> + </outcome> + <outcome value="false"> + <return status="failure"/> + </outcome> +</delete> ++-------------------+ + + +** Exists node + +*** Description + + An <<exists>> node is used to determine whether a particular + instance of a resource exists. For example, this might be + used to test whether a particular switch CLLI is provisioned. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to check +*--------------*-------+ +| <<key>> | SQL-like string specifying key to check for +*--------------*-------+ + +*** Parameters + + None + +*** Outcomes + +*-----------*-------+ +| <<true>> | Resource specified exists. +*-----------*-------+ +| <<false>> | Resource specified is unknown +*-----------*-------+ + +*** Example + ++-------------------+ +<exists plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="true"> + <return status="success"/> + </outcome> + <outcome value="false"> + <return status="failure"/> + </outcome> +</exists> ++-------------------+ + +** Get-resource node + +*** Description + + A <<get-resource>> node is used to retrieve information about a + particular resource and make it available to other nodes in the + service logic tree. For example, this might be used to + retrieve information about a particular uni-port. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to retrieve +*--------------*-------+ +| <<key>> | SQL-like string specifying criteria for retrieval +*--------------*-------+ +| <<pfx>> | Prefix to add to context variable names set for data retrieved +*--------------*-------+ +| <<select>> | String to specify, if key matches multiple entries, which entry should take precedence +*--------------*-------+ +| <<order-by>> | Prefix to add to context variable names set for data retrieved +*--------------*-------+ + +*** Parameters + + None + + +*** Outcomes + +*-----------*-------+ +| <<success>> | Resource successfully retrieved +*-----------*-------+ +| <<not-found>> | Resource referenced does not exist +*-----------*-------+ +| <<failure>> | Resource retrieve failed for some other reason +*-----------*-------+ + +*** Example + ++-------------------+ +<get-resource plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id" + pfx="current-port"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"/> + </outcome> + <outcome value="failure"> + <return status="failure"/> + </outcome> +</get-resource> ++-------------------+ + +** Is-available node + +*** Description + + An <<is-available>> node is used to determine whether a particular + type of resource is available. For example, this might be used to + test whether any ports are available for assignment on a particular switch. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to check +*--------------*-------+ +| <<key>> | SQL-like string specifying key to check for +*--------------*-------+ +| <<pfx>> | Prefix to add to context variable names set for data retrieved +*--------------*-------+ + +*** Parameters + + None + +*** Outcomes + +*-----------*-------+ +| <<true>> | Resource requested is available +*-----------*-------+ +| <<false>> | Resource requested is not available +*-----------*-------+ + +*** Example + ++-------------------+ +<is-available plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value"> + <outcome value="true"> + <return status="success"/> + </outcome> + <outcome value="false"> + <return status="failure"/> + </outcome> +</is-available> ++-------------------+ + +** Notify node + +*** Description + + A <<notify>> node is used to inform an external application (e.g. A&AI) that a resource was + updated. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Identifies resource that was updated +*--------------*-------+ +| <<action>> | Action that triggered notification to be sent (ADD/UPDATE/DELETE) +*--------------*-------+ + +*** Parameters + + None + +*** Outcomes + +*-----------*-------+ +| <<success>> | Notification was successful +*-----------*-------+ +| <<failure>> | Notification failed is not available +*-----------*-------+ + +*** Example + ++-------------------+ +<notify plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + action="ADD"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="Other"> + <return status="failure"/> + </outcome> +</notify> ++-------------------+ + +** Release node + +*** Description + + A <<release>> node is used to mark a resource as no longer in use, and thus + available for assignment. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to release +*--------------*-------+ +| <<key>> | SQL-like string specifying key to check of resource to release +*--------------*-------+ + +*** Parameters + + None + +*** Outcomes + +*-----------*-------+ +| <<success>> | Resource successfully released +*-----------*-------+ +| <<not-found>> | Resource referenced does not exist +*-----------*-------+ +| <<failure>> | Resource release failed for some other reason +*-----------*-------+ + +*** Example + ++-------------------+ +<release plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"/> + </outcome> + <outcome value="failure"> + <return status="failure"/> + </outcome> +</release> ++-------------------+ + + +** Reserve node + +*** Description + + A <<reserve>> node is used to reserve a particular + type of resource.. For example, this might be used to + reserve a port on a particular switch. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to reserve +*--------------*-------+ +| <<key>> | SQL-like string specifying criteria for reservation +*--------------*-------+ +| <<select>> | String to specify, if <<key>> matches multiple entries, which entry should take precedence +*--------------*-------+ + +*** Parameters + + None + +*** Outcomes + +*-----------*-------+ +| <<success>> | Resource requested was successfully reserved +*-----------*-------+ +| <<failure>> | Resource requested was not successfully reserved +*-----------*-------+ + +*** Example + ++-------------------+ +<reserve plugin="org.openecomp.sdnc.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value" + select="min(speed)"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="failure"> + <return status="failure"/> + </outcome> +</reserve> ++-------------------+ + +** Save node + +*** Description + + A <<save>> node is used to save information about a + particular resource to persistent storage. For example, this might be used to + save information about a particular uni-port. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to save +*--------------*-------+ +| <<key>> | SQL-like string specifying criteria for retrieval +*--------------*-------+ +| <<force>> | If "true", save resource even if this resource is already stored in persistent storage +*--------------*-------+ +| <<pfx>> | Prefix to be prepended to variable names, when attributes are set in SvcLogicContext +*--------------*-------+ + +*** Parameters + + Values to save (columns) are specified as parameters, with each name + corresponding to a column name and each value corresponding to the + value to set. + +*** Outcomes + +*-----------*-------+ +| <<success>> | Resource successfully saved +*-----------*-------+ +| <<failure>> | Resource save failed +*-----------*-------+ + +*** Example + ++-------------------+ +<save plugin="`$sample-resource-plugin`" resource="vnf" + key="vnf-name = $requests.vnf.vnf-name" force="true" + pfx="requests.vnf"> + <parameter name="vnf-name" + value="`$requests.cust-country-code + $requests.cust-id + $requests.cust-city + $requests.cust-state + '001VCE'`" /> + <parameter name="vnf-type" value="vce" /> + <parameter name="orchestration-status" value="pending-create" /> + <parameter name="heat-stack-id" value="`$requests.heat-stack-id`" /> + <parameter name="mso-catalog-key" value="`$requests.mso-catalog-key`" /> + <parameter name="oam-ipv4-address" value="`$vce-ipv4-oam-addr.ipv4-addr`" /> +</save> ++-------------------+ + +** Update node + +*** Description + + An <<update>> node is used to update information about a + particular resource to persistent storage. + +*** Attributes + +*--------------*-------+ +| <<plugin>> | Fully qualified Java class of resource adaptor to be used +*--------------*-------+ +| <<resource>> | Type of resource to update +*--------------*-------+ +| <<key>> | SQL-like string specifying criteria for retrieval +*--------------*-------+ +| <<pfx>> | Prefix to be prepended to variable names, when attributes are set in SvcLogicContext +*--------------*-------+ + +*** Parameters + + Values to save (columns) are specified as parameters, with each name + corresponding to a column name and each value corresponding to the + value to set. + +*** Outcomes + +*-----------*-------+ +| <<success>> | Resource successfully saved +*-----------*-------+ +| <<failure>> | Resource save failed +*-----------*-------+ + +*** Example + ++-------------------+ +<update plugin="`$sample-resource-plugin`" resource="vnf" + key="vnf-name = $requests.vnf.vnf-name" + pfx="requests.vnf"> + <parameter name="vnf-name" + value="`$requests.cust-country-code + $requests.cust-id + $requests.cust-city + $requests.cust-state + '001VCE'`" /> + <parameter name="vnf-type" value="vce" /> + <parameter name="orchestration-status" value="pending-create" /> + <parameter name="heat-stack-id" value="`$requests.heat-stack-id`" /> + <parameter name="mso-catalog-key" value="`$requests.mso-catalog-key`" /> + <parameter name="oam-ipv4-address" value="`$vce-ipv4-oam-addr.ipv4-addr`" /> +</update> ++-------------------+ + diff --git a/src/site/site.xml b/src/site/site.xml new file mode 100644 index 00000000..7da1eb9f --- /dev/null +++ b/src/site/site.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project> + <body> + <links> + <item name="Built-in Nodes" href="nodes.html" /> + </links> + <menu ref="modules"/> + + <menu ref="reports"/> + + </body> +</project> diff --git a/version.properties b/version.properties new file mode 100644 index 00000000..f78b4bdf --- /dev/null +++ b/version.properties @@ -0,0 +1,15 @@ +########################################################### +# Versioning variables +# Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... ) +# because they are used in Jenkins, whose plug-in doesn't support + + +release_name=1 +sprint_number=1 +feature_revision=2 + +base_version=${release_name}.${sprint_number}.${feature_revision} + +release_version=${base_version} +snapshot_version=${base_version}-SNAPSHOT + |