summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatej Perina <matej.perina@pantheon.tech>2019-04-03 09:09:00 +0200
committerSamuel Kontris <samuel.kontris@pantheon.tech>2019-08-16 19:28:22 +0200
commit85041dd8795b84a48d0b48dd746bfbcb230c8794 (patch)
treebae77a0c1a537f9a966f10e2deb63150df40574d
parent06877cb9a30c4ea3e7e95c230f214a78fb4db9e1 (diff)
Proposal to remove OSGi dependencies from the CCSDK project
Dependencies on the OSGi frameworks and libraries are removed by integrating the CCSDK project with the lighty.io. It's a toolkit that allows to use ODL services (in this case core services and the Restconf) without the dependency on the Karaf framework and the Blueprint DI. In this change are created the lighty.io modules which initialize and expose same services as the Blueprint DI in the blueprint.xml files. More info about the lighty.io - https://lighty.io Change-Id: I38171e83b018a18bfd8eaec95d4dc2fa2e3f5b36 Signed-off-by: Matej Perina <matej.perina@pantheon.tech> Signed-off-by: Samuel Kontris <samuel.kontris@pantheon.tech>
-rwxr-xr-xdblib/lighty/pom.xml51
-rw-r--r--dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProviderLighty.java174
-rw-r--r--dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManagerLighty.java977
-rw-r--r--dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/lighty/DblibModule.java56
-rwxr-xr-xdblib/pom.xml1
-rwxr-xr-xlighty/ccsdk-core-lighty/pom.xml38
-rw-r--r--lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/CcsdkCoreLightyModule.java148
-rw-r--r--lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/common/CcsdkLightyUtils.java78
-rwxr-xr-xlighty/ccsdk-lighty-dependency-versions/pom.xml50
-rw-r--r--lighty/pom.xml14
-rwxr-xr-xpom.xml1
-rwxr-xr-xsli/lighty/pom.xml47
-rw-r--r--sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/lighty/SliModule.java77
-rw-r--r--sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicAdaptorFactoryLighty.java53
-rw-r--r--sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolverLighty.java51
-rw-r--r--sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImplLighty.java172
-rwxr-xr-xsli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImplLighty.java110
-rwxr-xr-xsli/pom.xml1
-rwxr-xr-xsliPluginUtils/lighty/pom.xml48
-rw-r--r--sliPluginUtils/lighty/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/lighty/SliPluginUtilsModule.java51
-rwxr-xr-xsliPluginUtils/pom.xml1
-rwxr-xr-xsliapi/lighty/pom.xml48
-rw-r--r--sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/lighty/SliApiModule.java64
-rw-r--r--sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/sliapiProviderLighty.java606
-rwxr-xr-xsliapi/pom.xml1
25 files changed, 2918 insertions, 0 deletions
diff --git a/dblib/lighty/pom.xml b/dblib/lighty/pom.xml
new file mode 100755
index 000000000..e1ba85f90
--- /dev/null
+++ b/dblib/lighty/pom.xml
@@ -0,0 +1,51 @@
+<?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.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-lighty</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>ccsdk-sli-core :: dblib :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-lighty-dependency-versions</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.lighty.core</groupId>
+ <artifactId>lighty-controller</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-encrypt-service</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProviderLighty.java b/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProviderLighty.java
new file mode 100644
index 000000000..82579d7ec
--- /dev/null
+++ b/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProviderLighty.java
@@ -0,0 +1,174 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.onap.ccsdk.sli.core.dblib;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * THIS CLASS IS A COPY OF {@link DBLIBResourceProvider} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class DBLIBResourceProviderLighty {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DBLIBResourceProviderLighty.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String DBLIB_PROP_FILE_NAME = "dblib.properties";
+
+ private static final String DBLIB_PROPERTY_NAME = "org.onap.ccsdk.sli.jdbc.password";
+ private final AAAEncryptionService aaaEncryptionService;
+
+ /**
+ * A prioritized list of strategies for resolving dblib properties files.
+ */
+ private Vector<PropertiesFileResolver> dblibPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties files.
+ */
+ public DBLIBResourceProviderLighty(AAAEncryptionService aaaEncryptionService) {
+ this.aaaEncryptionService = aaaEncryptionService;
+
+ dblibPropertiesFileResolvers.add(new SdncConfigEnvVarFileResolver(
+ "Using property file (1) from environment variable"
+ ));
+ dblibPropertiesFileResolvers.add(new CoreDefaultFileResolver(
+ "Using property file (2) from default directory"
+ ));
+ dblibPropertiesFileResolvers.add(new KarafRootFileResolver(
+ "Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try(FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+
+ if(properties.containsKey(DBLIB_PROPERTY_NAME)) {
+ String sensitive = properties.getProperty(DBLIB_PROPERTY_NAME);
+ if(sensitive != null && sensitive.startsWith("ENC:")) {
+ try {
+ sensitive = sensitive.substring(4);
+ String postsense = decrypt(sensitive);
+ properties.setProperty(DBLIB_PROPERTY_NAME, postsense);
+ } catch(Exception exc) {
+ LOG.error("Failed to translate property", exc);
+ }
+ }
+ }
+
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new DblibConfigurationException("Failed to load properties for file: "
+ + propertiesFile.toString(), e));
+ }
+ }
+ }
+
+ /**
+ *
+ * @param value
+ * @return decrypted string if successful or the original value if unsuccessful
+ */
+ private String decrypt(String value) {
+ return aaaEncryptionService.decrypt(value);
+ }
+
+ /**
+ * Extract db config properties.
+ *
+ * @return the db config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the <code>Logger</code>.
+ *
+ * @param message Some user friendly message
+ * @param fileOptional The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if(fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be found.
+ *
+ * @param message An appropriate fatal error message
+ * @param dblibConfigurationException An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message,
+ final DblibConfigurationException dblibConfigurationException) {
+
+ LOG.error("{}", message, dblibConfigurationException);
+ }
+
+ /**
+ * Determines the dblib properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final DBLIBResourceProviderLighty dblibResourceProvider) {
+
+ for (final PropertiesFileResolver dblibPropertiesFileResolver : dblibPropertiesFileResolvers) {
+ final Optional<File> fileOptional = dblibPropertiesFileResolver.resolveFile(DBLIB_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(dblibPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ reportFailure("Missing configuration properties resource(3)",
+ new DblibConfigurationException("Missing configuration properties resource(3): "
+ + DBLIB_PROP_FILE_NAME));
+ return null;
+ }
+}
diff --git a/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManagerLighty.java b/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManagerLighty.java
new file mode 100644
index 000000000..9b474a5eb
--- /dev/null
+++ b/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManagerLighty.java
@@ -0,0 +1,977 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.onap.ccsdk.sli.core.dblib;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.SQLDataException;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLIntegrityConstraintViolationException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLSyntaxErrorException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Observable;
+import java.util.Properties;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.stream.Collectors;
+import javax.sql.DataSource;
+import javax.sql.rowset.CachedRowSet;
+import org.apache.tomcat.jdbc.pool.PoolExhaustedException;
+import org.onap.ccsdk.sli.core.dblib.config.DbConfigPool;
+import org.onap.ccsdk.sli.core.dblib.config.JDBCConfiguration;
+import org.onap.ccsdk.sli.core.dblib.config.TerminatingConfiguration;
+import org.onap.ccsdk.sli.core.dblib.factory.DBConfigFactory;
+import org.onap.ccsdk.sli.core.dblib.pm.PollingWorker;
+import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * THIS CLASS IS A COPY OF {@link DBResourceManager} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class DBResourceManagerLighty implements DataSource, DataAccessor, DBResourceObserver, DbLibService {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DBResourceManagerLighty.class);
+ private static final String DATABASE_URL = "org.onap.ccsdk.sli.jdbc.url";
+
+ transient boolean terminating = false;
+ transient protected long retryInterval = 10000L;
+ transient boolean recoveryMode = true;
+
+ SortedSet<CachedDataSource> dsQueue = new ConcurrentSkipListSet<>(new DataSourceComparator());
+ 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;
+ private static final String LOGGER_ALARM_MSG="Generated alarm: DBResourceManager.getData - No active DB connection pools are available.";
+ private static final String EXCEPTION_MSG= "No active DB connection pools are available in RequestDataNoRecovery call.";
+
+ public DBResourceManagerLighty(final DBLIBResourceProviderLighty configuration) {
+ this(configuration.getProperties());
+ }
+
+ public DBResourceManagerLighty(final Properties properties) {
+ this.configProps = processSystemVariables(properties);
+
+ // TODO : hack to force classloader to cache mariadb driver. This shouldnt be necessary,
+ // but for some reason it is (without this, dblib throws ClassNotFound on mariadb driver
+ // and fails to load).
+ LOGGER.info("Creating dummy instance of org.mariadb.jdbc.Driver");
+ Driver dvr = new org.mariadb.jdbc.Driver();
+ dvr = null;
+
+ // get retry interval value
+ retryInterval = getLongFromProperties(configProps, "org.onap.dblib.connection.retry", 10000L);
+
+ // get recovery mode flag
+ recoveryMode = getBooleanFromProperties(configProps, "org.onap.dblib.connection.recovery", true);
+ if(!recoveryMode)
+ {
+ recoveryMode = false;
+ LOGGER.info("Recovery Mode disabled");
+ }
+ // get time out value for thread cleanup
+ terminationTimeOut = getLongFromProperties(configProps, "org.onap.dblib.termination.timeout", 300000L);
+ // get properties for monitoring
+ monitorDbResponse = getBooleanFromProperties(configProps, "org.onap.dblib.connection.monitor", false);
+ monitoringInterval = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.interval", 1000L);
+ monitoringInitialDelay = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.startdelay", 5000L);
+ expectedCompletionTime = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.expectedcompletiontime", 5000L);
+ unprocessedFailoverThreshold = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.unprocessedfailoverthreshold", 3L);
+
+ // initialize performance monitor
+ PollingWorker.createInistance(configProps);
+
+ // initialize recovery thread
+ worker = new RecoveryMgr();
+ worker.setName("DBResourcemanagerWatchThread");
+ worker.setDaemon(true);
+ worker.start();
+
+ try {
+ this.config(configProps);
+ } catch (final Exception e) {
+ // TODO: config throws <code>Exception</code> which is poor practice. Eliminate this in a separate patch.
+ LOGGER.error("Fatal Exception encountered while configuring DBResourceManager", e);
+ }
+ }
+
+ public static Properties processSystemVariables(Properties properties) {
+ Map<Object, Object> hmap = new Properties();
+ hmap.putAll(properties);
+
+ Map<Object, Object> result = hmap.entrySet().stream()
+ .filter(map -> map.getValue().toString().startsWith("${"))
+ .filter(map -> map.getValue().toString().endsWith("}"))
+ .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
+
+ result.forEach((name, propEntries) -> {
+ hmap.put(name, replace(propEntries.toString()));
+ });
+
+ if(hmap.containsKey(DATABASE_URL) && hmap.get(DATABASE_URL).toString().contains("${")) {
+ String url = hmap.get(DATABASE_URL).toString();
+ String[] innerChunks = url.split("\\$\\{");
+ for(String chunk : innerChunks) {
+ if(chunk.contains("}")) {
+ String subChunk = chunk.substring(0, chunk.indexOf("}"));
+ String varValue = System.getenv(subChunk);
+ url = url.replace("${"+subChunk+"}", varValue);
+ }
+ }
+ hmap.put(DATABASE_URL, url);
+ }
+ return Properties.class.cast(hmap);
+ }
+
+
+ private static String replace(String value) {
+ String globalVariable = value.substring(2, value.length() -1);
+ String varValue = System.getenv(globalVariable);
+ return (varValue != null) ? varValue : value;
+ }
+
+
+ private void config(Properties configProps) throws Exception {
+ final ConcurrentLinkedQueue<CachedDataSource> semaphore = new ConcurrentLinkedQueue<>();
+ final DbConfigPool dbConfig = DBConfigFactory.createConfig(configProps);
+
+ long startTime = System.currentTimeMillis();
+
+ try {
+ JDBCConfiguration[] config = dbConfig.getJDBCbSourceArray();
+ CachedDataSource[] cachedDS = new CachedDataSource[config.length];
+ 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 < config.length; i++) {
+ cachedDS[i] = CachedDataSourceFactory.createDataSource(config[i]);
+ if(cachedDS[i] == null)
+ continue;
+ semaphore.add(cachedDS[i]);
+ cachedDS[i].setInterval(monitoringInterval);
+ cachedDS[i].setInitialDelay(monitoringInitialDelay);
+ cachedDS[i].setExpectedCompletionTime(expectedCompletionTime);
+ cachedDS[i].setUnprocessedFailoverThreshold(unprocessedFailoverThreshold);
+ cachedDS[i].addObserver(DBResourceManagerLighty.this);
+ }
+
+ DataSourceTester[] tester = new DataSourceTester[config.length];
+
+ for(int i=0; i<tester.length; i++){
+ tester[i] = new DataSourceTester(cachedDS[i], DBResourceManagerLighty.this, semaphore);
+ tester[i].start();
+ }
+
+ // the timeout param is set is seconds.
+ long timeout = ((dbConfig.getTimeout() <= 0) ? 60L : dbConfig.getTimeout());
+ LOGGER.debug("Timeout set to {} seconds", timeout);
+ timeout *= 1000;
+
+
+ synchronized (semaphore) {
+ semaphore.wait(timeout);
+ }
+ } catch(Exception exc){
+ LOGGER.warn("DBResourceManager.initWorker", exc);
+ } finally {
+ startTime = System.currentTimeMillis() - startTime;
+ LOGGER.info("Completed wait with {} active datasource(s) in {} ms", dsQueue.size(), startTime);
+ }
+ }
+
+
+ private final class DataSourceComparator implements Comparator<CachedDataSource> {
+ @Override
+ public int compare(CachedDataSource left, CachedDataSource right) {
+ if(LOGGER.isTraceEnabled())
+ LOGGER.trace("----------SORTING-------- () : ()", left.getDbConnectionName(), right.getDbConnectionName());
+ try {
+ if(left == right) {
+ return 0;
+ }
+ if(left == null){
+ return 1;
+ }
+ if(right == null){
+ return -1;
+ }
+
+ boolean leftMaster = !left.isSlave();
+ if(leftMaster) {
+ if(left.getIndex() <= right.getIndex())
+ return -1;
+ else {
+ boolean rightMaster = !right.isSlave();
+ if(rightMaster) {
+ if(left.getIndex() <= right.getIndex())
+ return -1;
+// if(left.getIndex() > right.getIndex())
+ else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ }
+ if(!right.isSlave())
+ return 1;
+
+ if(left.getIndex() <= right.getIndex())
+ return -1;
+ if(left.getIndex() > right.getIndex())
+ return 1;
+
+
+ } catch (Throwable e) {
+ LOGGER.warn("", e);
+ }
+ return -1;
+ }
+ }
+
+ class DataSourceTester extends Thread {
+
+ private final CachedDataSource ds;
+ private final DBResourceManagerLighty manager;
+ private final ConcurrentLinkedQueue<CachedDataSource> semaphoreQ;
+
+ public DataSourceTester(CachedDataSource ds, DBResourceManagerLighty manager, ConcurrentLinkedQueue<CachedDataSource> semaphore) {
+ this.ds = ds;
+ this.manager = manager;
+ this.semaphoreQ = semaphore;
+ }
+
+ @Override
+ public void run() {
+ manager.setDataSource(ds);
+ boolean slave = true;
+ if(ds != null) {
+ try {
+ slave = ds.isSlave();
+ } catch (Exception exc) {
+ LOGGER.warn("", exc);
+ }
+ }
+ if(!slave) {
+ LOGGER.info("Adding MASTER {} to active queue", ds.getDbConnectionName());
+ try {
+ synchronized (semaphoreQ) {
+ semaphoreQ.notifyAll();
+ }
+ } catch(Exception exc) {
+ LOGGER.warn("", exc);
+ }
+ }
+ try {
+ synchronized (semaphoreQ) {
+ semaphoreQ.remove(ds);
+ }
+ if(semaphoreQ.isEmpty()) {
+ synchronized (semaphoreQ) {
+ semaphoreQ.notifyAll();
+ }
+ }
+ } catch(Exception exc) {
+ LOGGER.warn("", exc);
+ }
+ if(ds != null)
+ LOGGER.info("Thread DataSourceTester terminated {} for {}", this.getName(), ds.getDbConnectionName());
+ }
+
+ }
+
+
+ private long getLongFromProperties(Properties props, String property, long defaultValue)
+ {
+ String value = null;
+ long tmpLongValue = defaultValue;
+ try {
+ value = 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 = 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;
+
+ }
+
+
+ @Override
+ 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.first())
+ {
+ if(recoveryMode && dsQueue.size() > 1){
+ handleGetConnectionException(dataSource, new Exception(data.toString()));
+ }
+ }
+ }
+ }
+ }
+
+ public void testForceRecovery()
+ {
+ CachedDataSource active = this.dsQueue.first();
+ handleGetConnectionException(active, new Exception("test"));
+ }
+
+ class RecoveryMgr extends Thread {
+
+ @Override
+ 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.onap.ccsdk.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<>();
+ 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;
+
+ // test if there are any connection pools available
+ if(this.dsQueue.isEmpty()){
+ LOGGER.error(LOGGER_ALARM_MSG);
+ throw new DBLibException("No active DB connection pools are available in RequestDataWithRecovery call.");
+ }
+
+ // loop through available data sources to retrieve data.
+ for(int i=0; i< 2; i++)
+ {
+ CachedDataSource active = this.dsQueue.first();
+
+ long time = System.currentTimeMillis();
+ try {
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+
+ return active.getData(statement, arguments);
+ } catch(SQLDataException | SQLSyntaxErrorException | SQLIntegrityConstraintViolationException exc){
+ throw exc;
+ } catch(Throwable exc){
+ if(exc instanceof SQLException) {
+ SQLException sqlExc = (SQLException)exc;
+ int code = sqlExc.getErrorCode();
+ String state = sqlExc.getSQLState();
+ LOGGER.debug("SQLException code: {} state: {}", code, state);
+ if("07001".equals(sqlExc.getSQLState())) {
+ throw sqlExc;
+ }
+ }
+ lastException = exc;
+ LOGGER.error("Generated alarm: {}", active.getDbConnectionName(), exc);
+ handleGetConnectionException(active, exc);
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = System.currentTimeMillis() - time;
+ LOGGER.debug("getData processing time : {} {} miliseconds.", active.getDbConnectionName(), time);
+ }
+ }
+ }
+ 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(LOGGER_ALARM_MSG);
+ throw new DBLibException(EXCEPTION_MSG);
+ }
+ CachedDataSource active = this.dsQueue.first();
+ long time = System.currentTimeMillis();
+ try {
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+ return active.getData(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)
+ 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 : {} {} miliseconds.", active.getDbConnectionName(), time);
+ }
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.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<>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+
+ return writeDataNoRecovery(statement, newList, preferredDS);
+ }
+
+ synchronized CachedDataSource findMaster() throws SQLException {
+ final CachedDataSource[] clone = this.dsQueue.toArray(new CachedDataSource[0]);
+
+ for(final CachedDataSource dss : clone) {
+ if(!dss.isSlave()) {
+ final CachedDataSource first = this.dsQueue.first();
+ if(first != dss) {
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("----------REODRERING--------");
+ dsQueue.clear();
+ if(!dsQueue.addAll(Arrays.asList(clone))) {
+ LOGGER.error("Failed adding datasources");
+ }
+ }
+ return dss;
+ }
+ }
+ LOGGER.warn("MASTER not found.");
+ return null;
+ }
+
+
+ private boolean writeDataNoRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException {
+ if(dsQueue.isEmpty()){
+ LOGGER.error(LOGGER_ALARM_MSG);
+ throw new DBLibException(EXCEPTION_MSG);
+ }
+
+ boolean initialRequest = true;
+ boolean retryAllowed = true;
+ CachedDataSource active = this.dsQueue.first();
+ long time = System.currentTimeMillis();
+ while(initialRequest) {
+ initialRequest = false;
+ try {
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ 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());
+ this.findMaster();
+ 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 : {} {} miliseconds.", active.getDbConnectionName(), time);
+ }
+ }
+ }
+ return true;
+ }
+
+ public void setDataSource(CachedDataSource dataSource) {
+ if(this.dsQueue.contains(dataSource))
+ return;
+ if(this.broken.contains(dataSource))
+ return;
+
+ if(dataSource.testConnection(true)){
+ this.dsQueue.add(dataSource);
+ } else {
+ this.broken.add(dataSource);
+ }
+ }
+
+ @Override
+ 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.first();
+
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ LOGGER.debug("Forcing reorder on: {}", dsQueue.toString());
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+ 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(SQLNonTransientConnectionException exc){
+ throw new NoAvailableConnectionsException(exc);
+ } catch(Exception exc){
+ lastException = 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;
+ }
+ }
+ } 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) {
+
+ throw (SQLException)lastException.getCause();
+ }
+ throw exception;
+ }
+ }
+
+ @Override
+ 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.first();
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+ 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(final 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.first().getDbConnectionName() + "> became active");
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+ }
+
+ public void cleanUp() {
+ for(Iterator<CachedDataSource> it=dsQueue.iterator();it.hasNext();){
+ CachedDataSource cds = it.next();
+ it.remove();
+ cds.cleanUp();
+ }
+
+ try {
+ this.terminating = true;
+ if(broken != null)
+ {
+ try {
+ broken.add( new TerminatingCachedDataSource(new TerminatingConfiguration()));
+ } 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);
+ }
+ }
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return this.dsQueue.first().getLogWriter();
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return this.dsQueue.first().getLoginTimeout();
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ this.dsQueue.first().setLogWriter(out);
+ }
+
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException {
+ this.dsQueue.first().setLoginTimeout(seconds);
+ }
+
+ public void displayState(){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("POOLS : Active = "+dsQueue.size() + ";\t Broken = "+broken.size());
+ CachedDataSource current = dsQueue.first();
+ if(current != null) {
+ LOGGER.debug("POOL : Active name = \'"+current.getDbConnectionName()+ "\'");
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.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<>();
+ 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(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.first() == 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(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.first() == list.get(i))
+ buffer.append("active");
+ else
+ buffer.append("standby");
+ }
+
+ buffer.append("\n");
+
+ }
+ }
+ return buffer.toString();
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return null;
+ }
+
+ /**
+ * @return the monitorDbResponse
+ */
+ @Override
+ public final boolean isMonitorDbResponse() {
+ return recoveryMode && monitorDbResponse;
+ }
+
+ public void test(){
+ CachedDataSource obj = dsQueue.first();
+ Exception ption = new Exception();
+ try {
+ for(int i=0; i<5; i++)
+ {
+ handleGetConnectionException(obj, ption);
+ }
+ } catch(Throwable exc){
+ LOGGER.warn("", exc);
+ }
+ }
+
+ @Override
+ public java.util.logging.Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ return null;
+ }
+
+ class RemindTask extends TimerTask {
+ @Override
+ public void run() {
+ CachedDataSource ds = dsQueue.first();
+ if(ds != null)
+ ds.getPoolInfo(false);
+ }
+ }
+
+ public int poolSize() {
+ return dsQueue.size();
+ }
+}
diff --git a/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/lighty/DblibModule.java b/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/lighty/DblibModule.java
new file mode 100644
index 000000000..bce166dff
--- /dev/null
+++ b/dblib/lighty/src/main/java/org/onap/ccsdk/sli/core/dblib/lighty/DblibModule.java
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START==========================================
+ * Copyright (c) 2019 PANTHEON.tech s.r.o.
+ * ===================================================================
+ * 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.onap.ccsdk.sli.core.dblib.lighty;
+
+import io.lighty.core.controller.api.AbstractLightyModule;
+import org.onap.ccsdk.sli.core.dblib.DBLIBResourceProviderLighty;
+import org.onap.ccsdk.sli.core.dblib.DBResourceManagerLighty;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
+
+/**
+ * The implementation of the {@link io.lighty.core.controller.api.LightyModule} that manages and provides services from
+ * the dblib artifact.
+ */
+public class DblibModule extends AbstractLightyModule {
+
+ private final AAAEncryptionService aaaEncryptionService;
+
+ private DBLIBResourceProviderLighty dbLibResourceProvider;
+ private DBResourceManagerLighty dbResourceManager;
+
+ public DblibModule(AAAEncryptionService aaaEncryptionService) {
+ this.aaaEncryptionService = aaaEncryptionService;
+ }
+
+ @Override
+ protected boolean initProcedure() {
+ this.dbLibResourceProvider = new DBLIBResourceProviderLighty(aaaEncryptionService);
+ this.dbResourceManager = new DBResourceManagerLighty(this.dbLibResourceProvider);
+ return true;
+ }
+
+ @Override
+ protected boolean stopProcedure() {
+ return true;
+ }
+
+ public DbLibService getDbLibService() {
+ return dbResourceManager;
+ }
+}
diff --git a/dblib/pom.xml b/dblib/pom.xml
index 258a4307a..d5a986e6c 100755
--- a/dblib/pom.xml
+++ b/dblib/pom.xml
@@ -24,5 +24,6 @@
<module>provider</module>
<module>features</module>
<module>installer</module>
+ <module>lighty</module>
</modules>
</project>
diff --git a/lighty/ccsdk-core-lighty/pom.xml b/lighty/ccsdk-core-lighty/pom.xml
new file mode 100755
index 000000000..24c03cc2b
--- /dev/null
+++ b/lighty/ccsdk-core-lighty/pom.xml
@@ -0,0 +1,38 @@
+<?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>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-core-lighty</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-lighty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-lighty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-lighty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtil-lighty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/CcsdkCoreLightyModule.java b/lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/CcsdkCoreLightyModule.java
new file mode 100644
index 000000000..578d18240
--- /dev/null
+++ b/lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/CcsdkCoreLightyModule.java
@@ -0,0 +1,148 @@
+/*
+ * ============LICENSE_START==========================================
+ * Copyright (c) 2019 PANTHEON.tech s.r.o.
+ * ===================================================================
+ * 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.onap.ccsdk.sli.core.lighty;
+
+import io.lighty.core.controller.api.AbstractLightyModule;
+import org.onap.ccsdk.sli.core.dblib.lighty.DblibModule;
+import org.onap.ccsdk.sli.core.lighty.common.CcsdkLightyUtils;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.ccsdk.sli.core.sli.lighty.SliModule;
+import org.onap.ccsdk.sli.core.sliapi.lighty.SliApiModule;
+import org.onap.ccsdk.sli.core.slipluginutils.lighty.SliPluginUtilsModule;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The implementation of the {@link io.lighty.core.controller.api.LightyModule} that groups all other LightyModules
+ * from the ccsdk-sli-core repository so they can be all treated as one component (for example started/stopped at once).
+ * For more information about the lighty.io visit the website https://lighty.io.
+ */
+public class CcsdkCoreLightyModule extends AbstractLightyModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CcsdkCoreLightyModule.class);
+
+ private final DataBroker dataBroker;
+ private final NotificationPublishService notificationPublishService;
+ private final RpcProviderRegistry rpcProviderRegistry;
+ private final AAAEncryptionService aaaEncryptionService;
+ private final SvcLogicResource svcLogicResource;
+ private final SvcLogicRecorder svcLogicRecorder;
+ private final SvcLogicJavaPlugin svcLogicJavaPlugin;
+ private final SvcLogicAdaptor svcLogicAdaptor;
+
+ private DblibModule dblibModule;
+ private SliModule sliModule;
+ private SliApiModule sliApiModule;
+ private SliPluginUtilsModule sliPluginUtilsModule;
+
+ // FIXME cyclic dependency - implementation of SvcLogicResource is located in adaptors and CcsdkAdaptorsLightyModule
+ // is depencent on DbLibService from core
+ public CcsdkCoreLightyModule(DataBroker dataBroker, NotificationPublishService notificationPublishService,
+ RpcProviderRegistry rpcProviderRegistry, AAAEncryptionService aaaEncryptionService,
+ SvcLogicResource svcLogicResource, SvcLogicRecorder svcLogicRecorder, SvcLogicJavaPlugin svcLogicJavaPlugin,
+ SvcLogicAdaptor svcLogicAdaptor) {
+ this.dataBroker = dataBroker;
+ this.notificationPublishService = notificationPublishService;
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ this.aaaEncryptionService = aaaEncryptionService;
+ this.svcLogicResource = svcLogicResource;
+ this.svcLogicRecorder = svcLogicRecorder;
+ this.svcLogicJavaPlugin = svcLogicJavaPlugin;
+ this.svcLogicAdaptor = svcLogicAdaptor;
+ }
+
+ protected boolean initProcedure() {
+ LOG.debug("Initializing CCSDK Core Lighty module...");
+
+ this.dblibModule = new DblibModule(aaaEncryptionService);
+ if (!CcsdkLightyUtils.startLightyModule(dblibModule)) {
+ return false;
+ }
+
+ this.sliModule = new SliModule(dblibModule.getDbLibService(), svcLogicResource, svcLogicRecorder,
+ svcLogicJavaPlugin, svcLogicAdaptor);
+ if (!CcsdkLightyUtils.startLightyModule(sliModule)) {
+ return false;
+ }
+
+ this.sliApiModule = new SliApiModule(dataBroker, notificationPublishService, rpcProviderRegistry, sliModule.getSvcLogicServiceImpl());
+ if (!CcsdkLightyUtils.startLightyModule(sliApiModule)) {
+ return false;
+ }
+
+ this.sliPluginUtilsModule = new SliPluginUtilsModule();
+ if (!CcsdkLightyUtils.startLightyModule(sliPluginUtilsModule)) {
+ return false;
+ }
+
+ LOG.debug("CCSDK Core Lighty module was initialized successfully");
+ return true;
+ }
+
+ protected boolean stopProcedure() {
+ LOG.debug("Stopping CCSDK Core Lighty module...");
+
+ boolean stopSuccessful = true;
+
+ if (!CcsdkLightyUtils.stopLightyModule(sliPluginUtilsModule)) {
+ stopSuccessful = false;
+ }
+
+ if (!CcsdkLightyUtils.stopLightyModule(sliApiModule)) {
+ stopSuccessful = false;
+ }
+
+ if (!CcsdkLightyUtils.stopLightyModule(sliModule)) {
+ stopSuccessful = false;
+ }
+
+ if (!CcsdkLightyUtils.stopLightyModule(dblibModule)) {
+ stopSuccessful = false;
+ }
+
+ if (stopSuccessful) {
+ LOG.debug("CCSDK Core Lighty module was stopped successfully");
+ } else {
+ LOG.error("CCSDK Core Lighty module was not stopped successfully!");
+ }
+ return stopSuccessful;
+ }
+
+ public DblibModule getDblibModule() {
+ return dblibModule;
+ }
+
+ public SliModule getSliModule() {
+ return sliModule;
+ }
+
+ public SliApiModule getSliApiModule() {
+ return sliApiModule;
+ }
+
+ public SliPluginUtilsModule getSliPluginUtilsModule() {
+ return sliPluginUtilsModule;
+ }
+}
diff --git a/lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/common/CcsdkLightyUtils.java b/lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/common/CcsdkLightyUtils.java
new file mode 100644
index 000000000..bfbcb135b
--- /dev/null
+++ b/lighty/ccsdk-core-lighty/src/main/java/org/onap/ccsdk/sli/core/lighty/common/CcsdkLightyUtils.java
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START==========================================
+ * Copyright (c) 2019 PANTHEON.tech s.r.o.
+ * ===================================================================
+ * 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.onap.ccsdk.sli.core.lighty.common;
+
+import io.lighty.core.controller.api.LightyModule;
+import java.util.concurrent.ExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utils class containing methods to start/stop LightyModules easier.
+ */
+public class CcsdkLightyUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CcsdkLightyUtils.class);
+
+ private CcsdkLightyUtils() {
+ throw new IllegalStateException("This class should not be instantiated!");
+ }
+
+ /**
+ * Starts provided LightyModule
+ * @param lightyModule LightyModule to start
+ * @return true if start was successful; false otherwise
+ */
+ public static boolean startLightyModule(LightyModule lightyModule) {
+ LOG.debug("Starting Lighty module: {} ...", lightyModule.getClass());
+ try {
+ if (lightyModule.start().get()) {
+ LOG.debug("Lighty module: {} was started successfully", lightyModule.getClass());
+ return true;
+ } else {
+ LOG.error("Unable to start Lighty Module: {}!", lightyModule.getClass());
+ return false;
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Exception thrown while initializing Lighty Module: {}!", lightyModule.getClass(), e);
+ return false;
+ }
+ }
+
+ /**
+ * Stops provided LightyModule
+ * @param lightyModule LightyModule to stop
+ * @return true if stop was successful; false otherwise
+ */
+ public static boolean stopLightyModule(LightyModule lightyModule) {
+ LOG.debug("Stopping Lighty Module: {}...", lightyModule.getClass());
+ try {
+ if (lightyModule.shutdown().get()) {
+ LOG.debug("Lighty Module: {} was stopped successfully", lightyModule.getClass());
+ return true;
+ } else {
+ LOG.error("Unable to stop Lighty Module: {}!", lightyModule.getClass());
+ return false;
+ }
+ } catch (Exception e) {
+ LOG.error("Exception thrown while shutting down {} in CCSDK Core Lighty module!", lightyModule.getClass(),
+ e);
+ return false;
+ }
+ }
+}
diff --git a/lighty/ccsdk-lighty-dependency-versions/pom.xml b/lighty/ccsdk-lighty-dependency-versions/pom.xml
new file mode 100755
index 000000000..e30a7e610
--- /dev/null
+++ b/lighty/ccsdk-lighty-dependency-versions/pom.xml
@@ -0,0 +1,50 @@
+<?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>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-lighty-dependency-versions</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <lighty.version>10.1.0</lighty.version>
+ <odl.aaa.version>0.9.0</odl.aaa.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>io.lighty.core</groupId>
+ <artifactId>lighty-controller</artifactId>
+ <version>${lighty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.lighty.modules</groupId>
+ <artifactId>lighty-restconf-nb-community</artifactId>
+ <version>${lighty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.lighty.modules</groupId>
+ <artifactId>lighty-netconf-sb</artifactId>
+ <version>${lighty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.lighty.resources</groupId>
+ <artifactId>singlenode-configuration</artifactId>
+ <version>${lighty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-artifacts</artifactId>
+ <version>${odl.aaa.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-encrypt-service</artifactId>
+ <version>${odl.aaa.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+</project>
diff --git a/lighty/pom.xml b/lighty/pom.xml
new file mode 100644
index 000000000..cd94259cb
--- /dev/null
+++ b/lighty/pom.xml
@@ -0,0 +1,14 @@
+<?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>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-core-lighty-aggregator</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>ccsdk-core-lighty</module>
+ <module>ccsdk-lighty-dependency-versions</module>
+ </modules>
+</project>
diff --git a/pom.xml b/pom.xml
index 711f3faea..bb3bc635e 100755
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
<module>sliapi</module>
<module>features</module>
<module>artifacts</module>
+ <module>lighty</module>
</modules>
<scm>
diff --git a/sli/lighty/pom.xml b/sli/lighty/pom.xml
new file mode 100755
index 000000000..c38ad286a
--- /dev/null
+++ b/sli/lighty/pom.xml
@@ -0,0 +1,47 @@
+<?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.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-lighty</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-lighty-dependency-versions</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.lighty.core</groupId>
+ <artifactId>lighty-controller</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/lighty/SliModule.java b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/lighty/SliModule.java
new file mode 100644
index 000000000..d48469320
--- /dev/null
+++ b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/lighty/SliModule.java
@@ -0,0 +1,77 @@
+/*
+ * ============LICENSE_START==========================================
+ * Copyright (c) 2019 PANTHEON.tech s.r.o.
+ * ===================================================================
+ * 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.onap.ccsdk.sli.core.sli.lighty;
+
+import io.lighty.core.controller.api.AbstractLightyModule;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicClassResolverLighty;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicPropertiesProviderImpl;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicService;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicServiceImplLighty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The implementation of the {@link io.lighty.core.controller.api.LightyModule} that manages and provides services from
+ * the sli-provider artifact.
+ */
+public class SliModule extends AbstractLightyModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SliModule.class);
+
+ private final DbLibService dbLibService;
+ private final SvcLogicResource svcLogicResource;
+ private final SvcLogicRecorder svcLogicRecorder;
+ private final SvcLogicJavaPlugin svcLogicJavaPlugin;
+ private final SvcLogicAdaptor svcLogicAdaptor;
+
+ private SvcLogicPropertiesProviderImpl svcLogicPropertiesImpl;
+ private SvcLogicServiceImplLighty svcLogicImpl;
+ private SvcLogicClassResolverLighty svcLogicClassResolver;
+
+ public SliModule(DbLibService dbLibService, SvcLogicResource svcLogicResource, SvcLogicRecorder svcLogicRecorder,
+ SvcLogicJavaPlugin svcLogicJavaPlugin, SvcLogicAdaptor svcLogicAdaptor) {
+ this.dbLibService = dbLibService;
+ this.svcLogicResource = svcLogicResource;
+ this.svcLogicRecorder = svcLogicRecorder;
+ this.svcLogicJavaPlugin = svcLogicJavaPlugin;
+ this.svcLogicAdaptor = svcLogicAdaptor;
+ }
+
+ @Override
+ protected boolean initProcedure() {
+ this.svcLogicPropertiesImpl = new SvcLogicPropertiesProviderImpl();
+ this.svcLogicClassResolver = new SvcLogicClassResolverLighty(svcLogicResource, svcLogicRecorder,
+ svcLogicJavaPlugin, svcLogicAdaptor);
+ this.svcLogicImpl = new SvcLogicServiceImplLighty(this.svcLogicPropertiesImpl, dbLibService,
+ svcLogicClassResolver);
+ return true;
+ }
+
+ @Override
+ protected boolean stopProcedure() {
+ return true;
+ }
+
+ public SvcLogicService getSvcLogicServiceImpl() {
+ return this.svcLogicImpl;
+ }
+}
diff --git a/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicAdaptorFactoryLighty.java b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicAdaptorFactoryLighty.java
new file mode 100644
index 000000000..d60e43117
--- /dev/null
+++ b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicAdaptorFactoryLighty.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * 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.onap.ccsdk.sli.core.sli.provider;
+
+import java.util.HashMap;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * THIS CLASS IS A COPY OF {@link SvcLogicAdaptorFactory} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class SvcLogicAdaptorFactoryLighty {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicAdaptorFactoryLighty.class);
+
+ private static HashMap<String, SvcLogicAdaptor> adaptorMap = new HashMap<>();
+
+ 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);
+ }
+ }
+
+}
diff --git a/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolverLighty.java b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolverLighty.java
new file mode 100644
index 000000000..7b730a8e0
--- /dev/null
+++ b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolverLighty.java
@@ -0,0 +1,51 @@
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * THIS CLASS IS A COPY OF {@link SvcLogicClassResolver} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class SvcLogicClassResolverLighty implements SvcLogicResolver {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicClassResolverLighty.class);
+
+ private final SvcLogicResource svcLogicResource;
+ private final SvcLogicRecorder svcLogicRecorder;
+ private final SvcLogicJavaPlugin svcLogicJavaPlugin;
+ private final SvcLogicAdaptor svcLogicAdaptor;
+
+ public SvcLogicClassResolverLighty(SvcLogicResource svcLogicResource, SvcLogicRecorder svcLogicRecorder,
+ SvcLogicJavaPlugin svcLogicJavaPlugin, SvcLogicAdaptor svcLogicAdaptor) {
+ this.svcLogicResource = svcLogicResource;
+ this.svcLogicRecorder = svcLogicRecorder;
+ this.svcLogicJavaPlugin = svcLogicJavaPlugin;
+ this.svcLogicAdaptor = svcLogicAdaptor;
+ }
+
+ @Override
+ public SvcLogicResource getSvcLogicResource(String resourceName) {
+ return svcLogicResource;
+ }
+
+ @Override
+ public SvcLogicRecorder getSvcLogicRecorder(String recorderName) {
+ return svcLogicRecorder;
+ }
+
+ @Override
+ public SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName) {
+ return svcLogicJavaPlugin;
+ }
+
+ @Override
+ public SvcLogicAdaptor getSvcLogicAdaptor(String adaptorName) {
+ return svcLogicAdaptor;
+ }
+
+}
diff --git a/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImplLighty.java b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImplLighty.java
new file mode 100644
index 000000000..dfc5855fd
--- /dev/null
+++ b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImplLighty.java
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.onap.ccsdk.sli.core.sli.provider;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * THIS CLASS IS A COPY OF {@link SvcLogicPropertiesProviderImpl} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class SvcLogicPropertiesProviderImplLighty implements SvcLogicPropertiesProvider {
+
+ private static final Logger log = LoggerFactory.getLogger(SvcLogicPropertiesProviderImplLighty.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String SVCLOGIC_PROP_FILE_NAME = "svclogic.properties";
+
+ /**
+ * A prioritized list of strategies for resolving dblib properties files.
+ */
+ private Vector<PropertiesFileResolver> sliPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public SvcLogicPropertiesProviderImplLighty() {
+ sliPropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ sliPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+ sliPropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ log.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+ e));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + SVCLOGIC_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ log.error("IO Exception",e);
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + SVCLOGIC_PROP_FILE_NAME));
+ }
+ }
+
+ /**
+ * Extract svclogic config properties.
+ *
+ * @return the svclogic config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the
+ * <code>Logger</code>.
+ *
+ * @param message
+ * Some user friendly message
+ * @param fileOptional
+ * The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ log.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be
+ * found.
+ *
+ * @param message
+ * An appropriate fatal error message
+ * @param configurationException
+ * An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message, final ConfigurationException configurationException) {
+
+ log.error("{}", message, configurationException);
+ }
+
+ /**
+ * Determines the dblib properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final SvcLogicPropertiesProviderImplLighty resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : sliPropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SVCLOGIC_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImplLighty.java b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImplLighty.java
new file mode 100755
index 000000000..b9740c583
--- /dev/null
+++ b/sli/lighty/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImplLighty.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.onap.ccsdk.sli.core.sli.provider;
+
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicDblibStore;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStoreFactory;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicResolver;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicServiceImplBase;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+/**
+ * THIS CLASS IS A COPY OF {@link SvcLogicServiceImpl} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class SvcLogicServiceImplLighty extends SvcLogicServiceImplBase implements SvcLogicService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicServiceImplLighty.class);
+
+ public SvcLogicServiceImplLighty(SvcLogicPropertiesProvider resourceProvider, DbLibService dbSvc,
+ SvcLogicResolver resolver) {
+ super(null);
+ this.resolver = resolver;
+ properties = resourceProvider.getProperties();
+ this.store = new SvcLogicDblibStore(dbSvc);
+ }
+
+ @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 {
+ 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(CURRENT_GRAPH, graph.toString());
+ ctx.setAttribute("X-ECOMP-RequestID", MDC.get("X-ECOMP-RequestID"));
+ ctx.setDomDataBroker(domDataBroker);
+ execute(graph, ctx);
+ return (ctx.toProperties());
+ }
+
+ @Override
+ public SvcLogicStore getStore() throws SvcLogicException {
+ // Create and initialize SvcLogicStore object - used to access
+ // saved service logic.
+ if (store != null) {
+ return store;
+ }
+
+ try {
+ store = SvcLogicStoreFactory.getSvcLogicStore(properties);
+ } catch (Exception e) {
+ throw new ConfigurationException("Could not get service logic store", e);
+
+ }
+
+ try {
+ store.init(properties);
+ } catch (SvcLogicException e) {
+ throw new ConfigurationException("Could not get service logic store", e);
+ }
+
+ return store;
+ }
+
+}
diff --git a/sli/pom.xml b/sli/pom.xml
index b9b60e9e3..bf21cb630 100755
--- a/sli/pom.xml
+++ b/sli/pom.xml
@@ -28,5 +28,6 @@
<module>recording</module>
<module>features</module>
<module>installer</module>
+ <module>lighty</module>
</modules>
</project>
diff --git a/sliPluginUtils/lighty/pom.xml b/sliPluginUtils/lighty/pom.xml
new file mode 100755
index 000000000..53445dafa
--- /dev/null
+++ b/sliPluginUtils/lighty/pom.xml
@@ -0,0 +1,48 @@
+<?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.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtil-lighty</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>ccsdk-sli-core :: sliPluginUtil :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-lighty-dependency-versions</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.lighty.core</groupId>
+ <artifactId>lighty-controller</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sliPluginUtils/lighty/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/lighty/SliPluginUtilsModule.java b/sliPluginUtils/lighty/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/lighty/SliPluginUtilsModule.java
new file mode 100644
index 000000000..41b63f535
--- /dev/null
+++ b/sliPluginUtils/lighty/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/lighty/SliPluginUtilsModule.java
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START==========================================
+ * Copyright (c) 2019 PANTHEON.tech s.r.o.
+ * ===================================================================
+ * 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.onap.ccsdk.sli.core.slipluginutils.lighty;
+
+import io.lighty.core.controller.api.AbstractLightyModule;
+import org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils;
+import org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils;
+
+/**
+ * The implementation of the {@link io.lighty.core.controller.api.LightyModule} that manages and provides services from
+ * the sliPluginUtils-provider artifact.
+ */
+public class SliPluginUtilsModule extends AbstractLightyModule {
+
+ private SliPluginUtils sliPluginUtils;
+ private SliStringUtils sliStringUtils;
+
+ @Override
+ protected boolean initProcedure() {
+ this.sliPluginUtils = new SliPluginUtils();
+ this.sliStringUtils = new SliStringUtils();
+ return true;
+ }
+
+ @Override
+ protected boolean stopProcedure() {
+ return true;
+ }
+
+ public SliPluginUtils getSliPluginUtils() {
+ return this.sliPluginUtils;
+ }
+
+ public SliStringUtils getSliStringUtils() {
+ return sliStringUtils;
+ }
+}
diff --git a/sliPluginUtils/pom.xml b/sliPluginUtils/pom.xml
index f9cdcec2e..48994d8ef 100755
--- a/sliPluginUtils/pom.xml
+++ b/sliPluginUtils/pom.xml
@@ -21,5 +21,6 @@
<module>provider</module>
<module>features</module>
<module>installer</module>
+ <module>lighty</module>
</modules>
</project>
diff --git a/sliapi/lighty/pom.xml b/sliapi/lighty/pom.xml
new file mode 100755
index 000000000..2812d6baf
--- /dev/null
+++ b/sliapi/lighty/pom.xml
@@ -0,0 +1,48 @@
+<?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.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-lighty</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>ccsdk-sli-core :: sliapi :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-lighty-dependency-versions</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.lighty.core</groupId>
+ <artifactId>lighty-controller</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/lighty/SliApiModule.java b/sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/lighty/SliApiModule.java
new file mode 100644
index 000000000..24d8958e1
--- /dev/null
+++ b/sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/lighty/SliApiModule.java
@@ -0,0 +1,64 @@
+/*
+ * ============LICENSE_START==========================================
+ * Copyright (c) 2019 PANTHEON.tech s.r.o.
+ * ===================================================================
+ * 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.onap.ccsdk.sli.core.sliapi.lighty;
+
+import io.lighty.core.controller.api.AbstractLightyModule;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicService;
+import org.onap.ccsdk.sli.core.sliapi.sliapiProviderLighty;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The implementation of the {@link io.lighty.core.controller.api.LightyModule} that manages and provides services from
+ * the sliapi-provider artifact.
+ */
+public class SliApiModule extends AbstractLightyModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SliApiModule.class);
+
+ private final DataBroker dataBroker;
+ private final NotificationPublishService notificationPublishService;
+ private final RpcProviderRegistry rpcRegistry;
+ private final SvcLogicService svcLogic;
+
+ private sliapiProviderLighty sliapiProvider;
+
+ public SliApiModule (DataBroker dataBroker, NotificationPublishService notificationPublishService,
+ RpcProviderRegistry rpcRegistry, SvcLogicService svcLogic) {
+ this.dataBroker = dataBroker;
+ this.notificationPublishService = notificationPublishService;
+ this.rpcRegistry = rpcRegistry;
+ this.svcLogic = svcLogic;
+ }
+
+ @Override
+ protected boolean initProcedure() {
+ LOG.debug("Initializing Lighty module {}...", this.getClass());
+ this.sliapiProvider = new sliapiProviderLighty(dataBroker, notificationPublishService, rpcRegistry, svcLogic);
+ LOG.debug("Lighty module {} initialized", this.getClass());
+ return true;
+ }
+
+ @Override
+ protected boolean stopProcedure() {
+ return true;
+ }
+
+}
diff --git a/sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/sliapiProviderLighty.java b/sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/sliapiProviderLighty.java
new file mode 100644
index 000000000..946984128
--- /dev/null
+++ b/sliapi/lighty/src/main/java/org/onap/ccsdk/sli/core/sliapi/sliapiProviderLighty.java
@@ -0,0 +1,606 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * 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.onap.ccsdk.sli.core.sliapi;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+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.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput.Mode;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.SLIAPIService;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.TestResults;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameter;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.test.results.TestResult;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.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.RpcError.ErrorType;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * THIS CLASS IS A COPY OF {@link sliapiProvider} WITH REMOVED OSGi DEPENDENCIES
+ */
+public class sliapiProviderLighty implements AutoCloseable, SLIAPIService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(sliapiProviderLighty.class);
+ private static final String appName = "slitester";
+
+ protected DataBroker dataBroker;
+ protected DOMDataBroker domDataBroker;
+ protected NotificationPublishService notificationService;
+ protected RpcProviderRegistry rpcRegistry;
+
+ private SvcLogicService svcLogic;
+
+ protected BindingAwareBroker.RpcRegistration<SLIAPIService> rpcRegistration;
+
+ private static String SLIAPI_NAMESPACE = "org:onap:ccsdk:sli:core:sliapi";
+ private static String SLIAPI_REVISION = "2016-11-10";
+ private static String SDNC_STATUS_FILE = "SDNC_STATUS_FILE";
+ private static String sdncStatusFile = null;
+
+ 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;
+ private static final String NON_NULL = "non-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 sliapiProviderLighty(DataBroker dataBroker, NotificationPublishService notificationPublishService,
+ RpcProviderRegistry rpcProviderRegistry, SvcLogicService svcLogic) {
+ this.LOG.info("Creating provider for " + appName);
+ this.dataBroker = dataBroker;
+ this.notificationService = notificationPublishService;
+ this.rpcRegistry = rpcProviderRegistry;
+ this.svcLogic = svcLogic;
+ initialize();
+ }
+
+ public void initialize() {
+ LOG.info("Initializing provider for " + appName);
+ // initialization code goes here.
+ rpcRegistration = rpcRegistry.addRpcImplementation(SLIAPIService.class, this);
+
+ sdncStatusFile = System.getenv(SDNC_STATUS_FILE);
+ LOG.info("SDNC STATUS FILE = " + sdncStatusFile);
+ 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(NotificationPublishService 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 ListenableFuture<RpcResult<ExecuteGraphOutput>> executeGraph(ExecuteGraphInput input) {
+ RpcResult<ExecuteGraphOutput> rpcResult = null;
+
+ 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));
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<HealthcheckOutput>> healthcheck(HealthcheckInput healthcheckInput) {
+
+ RpcResult<HealthcheckOutput> rpcResult = null;
+
+ 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));
+ }
+
+ public ListenableFuture<RpcResult<VlbcheckOutput>> vlbcheck(VlbcheckInput vlbInput) {
+
+ RpcResult<VlbcheckOutput> rpcResult = null;
+
+ VlbcheckOutputBuilder respBuilder = new VlbcheckOutputBuilder();
+
+ String calledModule = "sli";
+ String calledRpc = "vlbcheck";
+ String modeStr = "sync";
+
+ if (svcLogic == null) {
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Could not locate OSGi SvcLogicService service");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>failed().withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ boolean dgExists = true;
+ try {
+ if (!svcLogic.hasGraph(calledModule, calledRpc, null, modeStr)) {
+ dgExists = false;
+ }
+ } catch (Exception e) {
+ LOG.warn(
+ "Caught exception looking for directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr,
+ e);
+
+ dgExists = false;
+ }
+
+ if (dgExists) {
+ 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.<VlbcheckOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ } else {
+ // check the state based on the config file
+
+ boolean suspended = false;
+ BufferedReader br = null;
+ String line = "";
+
+ if (sdncStatusFile != null) {
+ try {
+ br = new BufferedReader(new FileReader(sdncStatusFile));
+ while ((line = br.readLine()) != null) {
+ if ("ODL_STATE=SUSPENDED".equals(line)) {
+ suspended = true;
+ LOG.debug("vlbcheck: server is suspended");
+ }
+ }
+ br.close();
+ } catch (FileNotFoundException e) {
+ LOG.trace("Caught File not found exception " + sdncStatusFile + "\n", e);
+ } catch (Exception e) {
+ LOG.trace("Failed to read status file " + sdncStatusFile + "\n", e);
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ LOG.warn("Failed to close status file " + sdncStatusFile + "\n", e);
+ }
+ }
+ }
+ }
+
+ if (suspended) {
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>failed()
+ .withError(ErrorType.APPLICATION, "resource-denied", "Server Suspended").build();
+ } else {
+ respBuilder.setResponseMessage("server is normal");
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>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.key());
+ InstanceIdentifier<TestResult> path = testResultIdBuilder.build();
+ 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<>();
+ 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/pom.xml b/sliapi/pom.xml
index c9541ac22..62651d065 100755
--- a/sliapi/pom.xml
+++ b/sliapi/pom.xml
@@ -21,6 +21,7 @@
<module>features</module>
<module>provider</module>
<module>installer</module>
+ <module>lighty</module>
</modules>
<properties>