SaltStack adaptor API creation

Issue-ID: CCSDK-319
Change-Id: Iaa96550a3b246a53cd8db6431fdc649dc8032feb
Signed-off-by: Ganesh Chandrasekaran <ganesh.c@samsung.com>
diff --git a/saltstack-adapter/saltstack-adapter-provider/.gitignore b/saltstack-adapter/saltstack-adapter-provider/.gitignore
new file mode 100644
index 0000000..255b540
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/.gitignore
@@ -0,0 +1,25 @@
+# ============LICENSE_START==========================================
+# ONAP : APPC
+# ===================================================================
+# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the License);
+# you may not use this software 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.
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END============================================
+/bin/
+/target/
+/target-ide/
+/.settings/
diff --git a/saltstack-adapter/saltstack-adapter-provider/pom.xml b/saltstack-adapter/saltstack-adapter-provider/pom.xml
new file mode 100644
index 0000000..f4e0450
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ============LICENSE_START======================================================= 
+	ONAP : APPC ================================================================================ 
+	Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. 
+	================================================================================ 
+	Copyright (C) 2017 Amdocs ============================================================================= 
+	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. ECOMP is 
+	a trademark and service mark of AT&T Intellectual Property. ============LICENSE_END========================================================= -->
+<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.1.0-SNAPSHOT</version>
+		<relativePath />
+	</parent>
+
+	<groupId>org.onap.ccsdk.sli.adaptors</groupId>
+	<artifactId>saltstack-adapter-provider</artifactId>
+	<version>0.3.0-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>ccsdk-sli-adaptors :: saltstack-adapter :: ${project.artifactId}</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.att.eelf</groupId>
+			<artifactId>eelf-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-logging</groupId>
+			<artifactId>commons-logging</artifactId>
+			<version>1.2</version>
+		</dependency>
+
+		<!-- Needed to run test cases -->
+		<dependency>
+			<groupId>org.glassfish.jersey.core</groupId>
+			<artifactId>jersey-common</artifactId>
+			<version>2.9.1</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-jaxrs</artifactId>
+			<version>1.9.13</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.onap.ccsdk.sli.core</groupId>
+			<artifactId>sli-common</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.onap.ccsdk.sli.core</groupId>
+			<artifactId>sli-provider</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.core</artifactId>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>jcl-over-slf4j</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.json</groupId>
+			<artifactId>json</artifactId>
+		</dependency>
+
+
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+		</dependency>
+
+
+	</dependencies>
+
+
+</project>
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java
new file mode 100644
index 0000000..2f70a79
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack;
+
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+/**
+ * This interface defines the operations that the Saltstack adapter exposes.
+ *
+ */
+public interface SaltstackAdapter extends SvcLogicJavaPlugin {
+    /**
+     * Returns the symbolic name of the adapter
+     *
+     * @return The adapter name
+     */
+    String getAdapterName();
+
+    /* Method to post a single command request for execution on SaltState server
+     *  The response from Saltstack comes in json format and it is automatically put
+     *  to context for DGs access, with a certain prefix*/
+    void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+    /* When SLS file is created/available then this Method can be used to post
+     *  the file to saltstack server and execute the SLS file on SaltState server
+     *  The response from Saltstack comes in json format and it is automatically put
+     *  to context for DGs access, with a certain prefix*/
+    void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+    /* Method to get log of a saltState execution request
+     *  The response from Saltstack comes in json format and it is automatically put
+     *  to context for DGs access, with a certain prefix*/
+    void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+    /**
+     * Set the command execution timeout
+     * @param timeout time in milliseconds
+     */
+    void setExecTimeout(long timeout);
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java
new file mode 100755
index 0000000..3731ef7
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java
@@ -0,0 +1,28 @@
+/*-
+ * ============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.adaptors.saltstack;
+
+import java.util.Properties;
+
+public interface SaltstackAdapterPropertiesProvider {
+
+    public Properties getProperties();
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
new file mode 100644
index 0000000..7702dc8
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
@@ -0,0 +1,124 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.impl;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * Returns a custom SSH client
+ * - based on options
+ * - can create one with ssl using an X509 certificate that does NOT have a known CA
+ * - create one which trusts ALL SSL certificates
+ * - return default sshclient (which only trusts known CAs from default cacerts file for process) this is the default
+ * option
+ **/
+//TODO: This class is to be altered completely based on the SALTSTACK server communication.
+public class ConnectionBuilder {
+
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
+
+
+    /**
+     * Constructor that initializes an ssh client based on certificate
+     **/
+    public ConnectionBuilder(String userName, String userPasswd) throws KeyStoreException, CertificateException, IOException,
+            KeyManagementException, NoSuchAlgorithmException, SvcLogicException {
+
+
+    }
+
+    /**
+     * Constructor which trusts all certificates in a specific java keystore file (assumes a JKS
+     * file)
+     **/
+    public ConnectionBuilder(String certFile) throws KeyStoreException, IOException,
+            KeyManagementException, NoSuchAlgorithmException, CertificateException {
+
+    }
+
+    /**
+     * Connect to SSH server.
+     */
+    public SaltstackResult connect(String agentUrl, String payload) {
+
+        SaltstackResult result = new SaltstackResult();
+        try {
+            //TODO: to implement SSH connected client to Saltstack Server
+        } catch (Exception io) {
+            logger.error("Caught Exception", io);
+            result.setStatusCode(SaltstackResultCodes.IO_EXCEPTION.getValue());
+            result.setStatusMessage(io.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * Disconnect from SSH server.
+     */
+    public SaltstackResult disConnect(){
+
+        SaltstackResult result = new SaltstackResult();
+        try {
+            //TODO: to implement SSH connected client to Saltstack Server
+        } catch (Exception io) {
+            logger.error("Caught Exception", io);
+            result.setStatusCode(SaltstackResultCodes.IO_EXCEPTION.getValue());
+            result.setStatusMessage(io.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * Exec remote command over SSH. Return command execution status.
+     * Command output is written to out or err stream.
+     *
+     * @param cmd command to execute
+     * @param out content of sysout will go to this stream
+     * @param err content of syserr will go to this stream
+     * @return command execution status
+     */
+    public SaltstackResult execute(String cmd) {
+
+        SaltstackResult result = new SaltstackResult();
+
+        try {
+            //TODO: to implement SSH command execute
+        } catch (Exception io) {
+            result.setStatusCode(SaltstackResultCodes.IO_EXCEPTION.getValue());
+            result.setStatusMessage(io.getMessage());
+            logger.error("Caught IOException", io);
+        }
+        return result;
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java
new file mode 100644
index 0000000..6ff5e57
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java
@@ -0,0 +1,246 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.impl;
+
+import java.util.Map;
+import java.util.Properties;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackMessageParser;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackServerEmulator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * This class implements the {@link SaltstackAdapter} interface. This interface defines the behaviors
+ * that our service provides.
+ */
+public class SaltstackAdapterImpl implements SaltstackAdapter {
+
+    private static final long EXEC_TIMEOUT = 120000;
+    private long timeout = EXEC_TIMEOUT;
+
+    /**
+     * The constant used to define the service name in the mapped diagnostic context
+     */
+    @SuppressWarnings("nls")
+    public static final String MDC_SERVICE = "service";
+
+    /**
+     * The constant for the status code for a failed outcome
+     */
+    @SuppressWarnings("nls")
+    public static final String OUTCOME_FAILURE = "failure";
+
+    /**
+     * The constant for the status code for a successful outcome
+     */
+    @SuppressWarnings("nls")
+    public static final String OUTCOME_SUCCESS = "success";
+
+    /**
+     * Adapter Name
+     */
+    private static final String ADAPTER_NAME = "Saltstack Adapter";
+    private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
+
+    private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.result.code";
+    private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.message";
+    private static final String RESULTS_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.results";
+    private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.Id";
+    private static final String LOG_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.log";
+
+    private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.saltstack.clientType";
+    private static final String SS_SERVER_USERNAME = "org.onap.appc.adapter.saltstack.userName";
+    private static final String SS_SERVER_PASSWORD = "org.onap.appc.adapter.saltstack.userPasswd";
+    private static final String SS_SERVER_SSH_KEY = "org.onap.appc.adapter.saltstack.sshKey";
+
+
+    /**
+     * The logger to be used
+     */
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackAdapterImpl.class);
+
+
+    /**
+     * Connection object
+     **/
+    private ConnectionBuilder sshClient;
+
+    /**
+     * Saltstack API Message Handlers
+     **/
+    private SaltstackMessageParser messageProcessor;
+
+    /**
+     * indicator whether in test mode
+     **/
+    private boolean testMode = false;
+
+    /**
+     * server emulator object to be used if in test mode
+     **/
+    private SaltstackServerEmulator testServer;
+
+    /**
+     * This default constructor is used as a work around because the activator wasn't getting called
+     */
+    public SaltstackAdapterImpl() {
+        initialize(new SaltstackAdapterPropertiesProviderImpl());
+    }
+    public SaltstackAdapterImpl(SaltstackAdapterPropertiesProvider propProvider) {
+        initialize(propProvider);
+    }
+
+    /**
+     * Used for jUnit test and testing interface
+     */
+    public SaltstackAdapterImpl(boolean mode) {
+        testMode = mode;
+        testServer = new SaltstackServerEmulator();
+        messageProcessor = new SaltstackMessageParser();
+    }
+
+    /**
+     * Returns the symbolic name of the adapter
+     *
+     * @return The adapter name
+     * @see org.onap.appc.adapter.rest.SaltstackAdapter#getAdapterName()
+     */
+    @Override
+    public String getAdapterName() {
+        return ADAPTER_NAME;
+    }
+
+    @Override
+    public void setExecTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+    /**
+     * @param rc Method posts info to Context memory in case of an error and throws a
+     *        SvcLogicException causing SLI to register this as a failure
+     */
+    @SuppressWarnings("static-method")
+    private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
+
+        svcLogic.setStatus(OUTCOME_FAILURE);
+        svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+        svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+
+        throw new SvcLogicException("Saltstack Adapter Error = " + message);
+    }
+
+    /**
+     * initialize the Saltstack adapter based on default and over-ride configuration data
+     */
+    private void initialize(SaltstackAdapterPropertiesProvider propProvider) {
+
+
+        Properties props = propProvider.getProperties();
+
+        // Create the message processor instance
+        messageProcessor = new SaltstackMessageParser();
+
+        // Create the ssh client instance
+        // type of client is extracted from the property file parameter
+        // org.onap.appc.adapter.saltstack.clientType
+        // It can be :
+        // 1. BASIC. SSH Connection using username and password
+        // 2. SSH_CERT (trust only those whose certificates have been stored in the SSH KEY file)
+        // 3. DEFAULT SSH Connection without any authentication
+
+        try {
+            String clientType = props.getProperty(CLIENT_TYPE_PROPERTY_NAME);
+            logger.info("Saltstack ssh client type set to " + clientType);
+
+            if ("BASIC".equals(clientType)) {
+                logger.info("Creating ssh client connection");
+                // set path to keystore file
+                String trustStoreFile = props.getProperty(SS_SERVER_USERNAME);
+                String key = props.getProperty(SS_SERVER_PASSWORD);
+                //TODO: Connect to SSH Saltstack server (using username and password) and return client to execute command
+                sshClient = null;
+            } else if ("SSH_CERT".equals(clientType)) {
+                // set path to keystore file
+                String key = props.getProperty(SS_SERVER_SSH_KEY);
+                logger.info("Creating ssh client with ssh KEY from " + key);
+                //TODO: Connect to SSH Saltstack server (using SSH Key) and return client to execute command
+                sshClient = null;
+            } else {
+                logger.info("Creating ssh client without any Auth");
+                //TODO: Connect to SSH Saltstack server without any Auth
+                sshClient = null;
+            }
+        } catch (Exception e) {
+            logger.error("Error Initializing Saltstack Adapter due to Unknown Exception", e);
+        }
+
+        logger.info("Initialized Saltstack Adapter");
+    }
+
+    // Public Method to post single command request to execute saltState. Posts the following back
+    // to Svc context memory
+    //  org.onap.appc.adapter.saltstack.req.code : 100 if successful
+    //  org.onap.appc.adapter.saltstack.req.messge : any message
+    //  org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+    @Override
+    public void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        //TODO: to implement
+    }
+
+    /**
+     * Public Method to post SLS file request to execute saltState. Posts the following back
+     * to Svc context memory
+     *
+     * org.onap.appc.adapter.saltstack.req.code : 100 if successful
+     * org.onap.appc.adapter.saltstack.req.messge : any message
+     * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+     */
+    @Override
+    public void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        //TODO: to implement
+
+    }
+
+    /**
+     * Public method to get logs from saltState execution for a specific request Posts the following back
+     * to Svc context memory
+     *
+     * It blocks till the Saltstack Server responds or the session times out very similar to
+     * reqExecResult logs are returned in the DG context variable org.onap.appc.adapter.saltstack.log
+     */
+    @Override
+    public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        //TODO: to implement
+
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java
new file mode 100755
index 0000000..2430885
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java
@@ -0,0 +1,191 @@
+/*-
+ * ============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.adaptors.saltstack.impl;
+
+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.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+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;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the
+ * <code>SqlResource</code> Service. The priority for properties file
+ * resolution is as follows:
+ *
+ * <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>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterPropertiesProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SaltstackAdapterPropertiesProviderImpl.class);
+
+    /**
+     * The name of the properties file for database configuration
+     */
+    private static final String SALTSTACKADAPTER_PROP_FILE_NAME = "saltstack-adapter.properties";
+
+    /**
+     * A prioritized list of strategies for resolving sql-resource properties files.
+     */
+    private Vector<PropertiesFileResolver> saltstackAdapterPropertiesFileResolvers = 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 SaltstackAdapterPropertiesProviderImpl() {
+        saltstackAdapterPropertiesFileResolvers
+                .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+        saltstackAdapterPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+        saltstackAdapterPropertiesFileResolvers.add(
+                new JREFileResolver("Using property file (3) from JRE argument", SaltstackAdapterPropertiesProviderImpl.class));
+        saltstackAdapterPropertiesFileResolvers.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("/" + SALTSTACKADAPTER_PROP_FILE_NAME);
+            if (propStr != null) {
+                properties = new Properties();
+                try {
+                    properties.load(propStr);
+                    propStr.close();
+                } catch (IOException e) {
+                    properties = null;
+                }
+            }
+
+        }
+
+        if (properties == null) {
+            reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+                    "Missing configuration properties resource(3): " + SALTSTACKADAPTER_PROP_FILE_NAME));
+
+            LOG.info("Defaulting org.onap.appc.adapter.saltstack.clientType to NONE");
+
+            properties = new Properties();
+            properties.setProperty("org.onap.appc.adapter.saltstack.clientType", "NONE");
+        }
+    }
+
+    /**
+     * 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 sql-resource 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>sql-resource.properties</code></li>
+     * <li>A <code>sql-resource.properties</code> file located in the karaf root
+     * directory</li>
+     * </ol>
+     */
+    File determinePropertiesFile(final SaltstackAdapterPropertiesProviderImpl resourceProvider) {
+
+        for (final PropertiesFileResolver sliPropertiesFileResolver : saltstackAdapterPropertiesFileResolvers) {
+            final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SALTSTACKADAPTER_PROP_FILE_NAME);
+            if (fileOptional.isPresent()) {
+                return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
new file mode 100644
index 0000000..5a548f8
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
@@ -0,0 +1,312 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+/**
+ * This module implements the APP-C/Saltstack Server interface
+ * based on the REST API specifications
+ */
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.google.common.base.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class that validates and constructs requests sent/received from
+ * Saltstack Server
+ */
+//TODO: This class is to be altered completely based on the SALTSTACK server communicaiton.
+public class SaltstackMessageParser {
+
+    private static final String STATUS_MESSAGE_KEY = "StatusMessage";
+    private static final String STATUS_CODE_KEY = "StatusCode";
+
+    private static final String SALTSTATE_NAME_KEY = "SaltStateName";
+    private static final String AGENT_URL_KEY = "AgentUrl";
+    private static final String PASS_KEY = "Password";
+    private static final String USER_KEY = "User";
+    private static final String ID_KEY = "Id";
+
+    private static final String LOCAL_PARAMETERS_OPT_KEY = "LocalParameters";
+    private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+    private static final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+    private static final String NODE_LIST_OPT_KEY = "NodeList";
+    private static final String TIMEOUT_OPT_KEY = "Timeout";
+    private static final String VERSION_OPT_KEY = "Version";
+    private static final String ACTION_OPT_KEY = "Action";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SaltstackMessageParser.class);
+
+    /**
+     * Accepts a map of strings and
+     * a) validates if all parameters are appropriate (else, throws an exception) and
+     * b) if correct returns a JSON object with appropriate key-value pairs to send to the server.
+     *
+     * Mandatory parameters, that must be in the supplied information to the Saltstack Adapter
+     * 1. URL to connect to
+     * 2. credentials for URL (assume username password for now)
+     * 3. SaltState name
+     *
+     */
+    public JSONObject reqMessage(Map<String, String> params) throws SvcLogicException {
+        final String[] mandatoryTestParams = {AGENT_URL_KEY, SALTSTATE_NAME_KEY, USER_KEY, PASS_KEY};
+        final String[] optionalTestParams = {ENV_PARAMETERS_OPT_KEY, NODE_LIST_OPT_KEY, LOCAL_PARAMETERS_OPT_KEY,
+                TIMEOUT_OPT_KEY, VERSION_OPT_KEY, FILE_PARAMETERS_OPT_KEY, ACTION_OPT_KEY};
+
+        JSONObject jsonPayload = new JSONObject();
+
+        for (String key : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, key);
+            jsonPayload.put(key, params.get(key));
+        }
+
+        parseOptionalParams(params, optionalTestParams, jsonPayload);
+
+        // Generate a unique uuid for the test
+        String reqId = UUID.randomUUID().toString();
+        jsonPayload.put(ID_KEY, reqId);
+
+        return jsonPayload;
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for a result. If so, it returns
+     * the appropriate url, else an empty string.
+     */
+    public String reqUriResult(Map<String, String> params) throws SvcLogicException {
+
+        final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+
+        for (String key : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, key);
+        }
+        return params.get(AGENT_URL_KEY) + "?Id=" + params.get(ID_KEY) + "&Type=GetResult";
+    }
+
+    /**
+     * Method that validates that the Map has enough information
+     * to query Saltstack server for logs. If so, it populates the appropriate
+     * returns the appropriate url, else an empty string.
+     */
+    public String reqUriLog(Map<String, String> params) throws SvcLogicException {
+
+        final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+
+        for (String mandatoryParam : mandatoryTestParams) {
+            throwIfMissingMandatoryParam(params, mandatoryParam);
+        }
+        return params.get(AGENT_URL_KEY) + "?Id=" + params.get(ID_KEY) + "&Type=GetLog";
+    }
+
+    /**
+     * This method parses response from the Saltstack Server when we do a post
+     * and returns an SaltstackResult object.
+     */
+    public SaltstackResult parsePostResponse(String input) throws SvcLogicException {
+        SaltstackResult saltstackResult;
+        try {
+            JSONObject postResponse = new JSONObject(input);
+
+            int code = postResponse.getInt(STATUS_CODE_KEY);
+            String msg = postResponse.getString(STATUS_MESSAGE_KEY);
+
+            int initResponseValue = SaltstackResultCodes.INITRESPONSE.getValue();
+            boolean validCode = SaltstackResultCodes.CODE.checkValidCode(initResponseValue, code);
+            if (!validCode) {
+                throw new SvcLogicException("Invalid InitResponse code  = " + code + " received. MUST be one of "
+                        + SaltstackResultCodes.CODE.getValidCodes(initResponseValue));
+            }
+
+            saltstackResult = new SaltstackResult(code, msg);
+
+        } catch (JSONException e) {
+            saltstackResult = new SaltstackResult(600, "Error parsing response = " + input + ". Error = " + e.getMessage());
+        }
+        return saltstackResult;
+    }
+
+    /**
+     * This method parses response from an Saltstack server when we do a GET for a result
+     * and returns an SaltstackResult object.
+     **/
+    public SaltstackResult parseGetResponse(String input) throws SvcLogicException {
+
+        SaltstackResult saltstackResult = new SaltstackResult();
+
+        try {
+            JSONObject postResponse = new JSONObject(input);
+            saltstackResult = parseGetResponseNested(saltstackResult, postResponse);
+        } catch (JSONException e) {
+            saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_PAYLOAD.getValue(),
+                    "Error parsing response = " + input + ". Error = " + e.getMessage(), "");
+        }
+        return saltstackResult;
+    }
+
+    private SaltstackResult parseGetResponseNested(SaltstackResult saltstackResult, JSONObject postRsp) throws SvcLogicException  {
+
+        int codeStatus = postRsp.getInt(STATUS_CODE_KEY);
+        String messageStatus = postRsp.getString(STATUS_MESSAGE_KEY);
+        int finalCode = SaltstackResultCodes.FINAL_SUCCESS.getValue();
+
+        boolean valCode =
+                SaltstackResultCodes.CODE.checkValidCode(SaltstackResultCodes.FINALRESPONSE.getValue(), codeStatus);
+
+        if (!valCode) {
+            throw new SvcLogicException("Invalid FinalResponse code  = " + codeStatus + " received. MUST be one of "
+                    + SaltstackResultCodes.CODE.getValidCodes(SaltstackResultCodes.FINALRESPONSE.getValue()));
+        }
+
+        saltstackResult.setStatusCode(codeStatus);
+        saltstackResult.setStatusMessage(messageStatus);
+        LOGGER.info("Received response with code = {}, Message = {}", codeStatus, messageStatus);
+
+        if (!postRsp.isNull("Results")) {
+
+            // Results are available. process them
+            // Results is a dictionary of the form
+            // {host :{status:s, group:g, message:m, hostname:h}, ...}
+            LOGGER.info("Processing results in response");
+            JSONObject results = postRsp.getJSONObject("Results");
+            LOGGER.info("Get JSON dictionary from Results ..");
+            Iterator<String> hosts = results.keys();
+            LOGGER.info("Iterating through hosts");
+
+            while (hosts.hasNext()) {
+                String host = hosts.next();
+                LOGGER.info("Processing host = {}", host);
+
+                try {
+                    JSONObject hostResponse = results.getJSONObject(host);
+                    int subCode = hostResponse.getInt(STATUS_CODE_KEY);
+                    String message = hostResponse.getString(STATUS_MESSAGE_KEY);
+
+                    LOGGER.info("Code = {}, Message = {}", subCode, message);
+
+                    if (subCode != 200 || !message.equals("SUCCESS")) {
+                        finalCode = SaltstackResultCodes.REQ_FAILURE.getValue();
+                    }
+                } catch (JSONException e) {
+                    saltstackResult.setStatusCode(SaltstackResultCodes.INVALID_RESPONSE.getValue());
+                    saltstackResult.setStatusMessage(String.format(
+                            "Error processing response message = %s from host %s", results.getString(host), host));
+                    break;
+                }
+            }
+
+            saltstackResult.setStatusCode(finalCode);
+
+            // We return entire Results object as message
+            saltstackResult.setResults(results.toString());
+
+        } else {
+            saltstackResult.setStatusCode(SaltstackResultCodes.INVALID_RESPONSE.getValue());
+            saltstackResult.setStatusMessage("Results not found in GET for response");
+        }
+        return saltstackResult;
+    }
+
+    private void parseOptionalParams(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload) {
+
+        Set<String> optionalParamsSet = new HashSet<>();
+        Collections.addAll(optionalParamsSet, optionalTestParams);
+
+        //@formatter:off
+        params.entrySet()
+            .stream()
+            .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+            .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+             .forEach(entry -> parseOptionalParam(entry, jsonPayload));
+        //@formatter:on
+    }
+
+    private void parseOptionalParam(Map.Entry<String, String> params, JSONObject jsonPayload) {
+        String key = params.getKey();
+        String payload = params.getValue();
+
+        switch (key) {
+            case TIMEOUT_OPT_KEY:
+                int timeout = Integer.parseInt(payload);
+                if (timeout < 0) {
+                    throw new NumberFormatException(" : specified negative integer for timeout = " + payload);
+                }
+                jsonPayload.put(key, payload);
+                break;
+
+            case VERSION_OPT_KEY:
+                jsonPayload.put(key, payload);
+                break;
+
+            case LOCAL_PARAMETERS_OPT_KEY:
+            case ENV_PARAMETERS_OPT_KEY:
+                JSONObject paramsJson = new JSONObject(payload);
+                jsonPayload.put(key, paramsJson);
+                break;
+
+            case NODE_LIST_OPT_KEY:
+                JSONArray paramsArray = new JSONArray(payload);
+                jsonPayload.put(key, paramsArray);
+                break;
+
+            case FILE_PARAMETERS_OPT_KEY:
+                jsonPayload.put(key, getFilePayload(payload));
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Return payload with escaped newlines
+     */
+    private JSONObject getFilePayload(String payload) {
+        String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+        return new JSONObject(formattedPayload);
+    }
+
+    private void throwIfMissingMandatoryParam(Map<String, String> params, String key) throws SvcLogicException {
+        if (!params.containsKey(key)) {
+            throw new SvcLogicException(String.format(
+                    "Saltstack: Mandatory SaltstackAdapter key %s not found in parameters provided by calling agent !",
+                    key));
+        }
+        if (Strings.isNullOrEmpty(params.get(key))) {
+            throw new SvcLogicException(String.format(
+                    "Saltstack: Mandatory SaltstackAdapter key %s not found in parameters provided by calling agent !",
+                    key));
+        }
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
new file mode 100644
index 0000000..f1fb40d
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+/**
+ *  Simple class to store code and message returned by POST/GET to an Saltstack Server
+ */
+public class SaltstackResult {
+
+    private static final String EMPTY_VALUE = "UNKNOWN";
+
+    private int statusCode;
+    private String statusMessage;
+    private String results;
+
+    public SaltstackResult() {
+        this(-1, EMPTY_VALUE, EMPTY_VALUE);
+    }
+
+    public SaltstackResult(int code, String message) {
+        this(code, message, EMPTY_VALUE);
+    }
+
+    public SaltstackResult(int code, String message, String result) {
+        statusCode = code;
+        statusMessage = message;
+        results = result;
+    }
+
+    public void setStatusCode(int code) {
+        this.statusCode = code;
+    }
+
+    public void setStatusMessage(String message) {
+        this.statusMessage = message;
+    }
+
+    public void setResults(String results) {
+        this.results = results;
+    }
+
+    void set(int code, String message, String results) {
+        this.statusCode = code;
+        this.statusMessage = message;
+        this.results = results;
+    }
+
+    public int getStatusCode() {
+        return this.statusCode;
+    }
+
+    public String getStatusMessage() {
+        return this.statusMessage;
+    }
+
+    public String getResults() {
+        return this.results;
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
new file mode 100644
index 0000000..e520dda
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * enum of the various codes that APP-C uses to resolve different
+ * status of response from Saltstack Server
+ **/
+
+public enum SaltstackResultCodes {
+
+    // @formatter:off
+    SUCCESS(400),
+    KEYSTORE_EXCEPTION(622),
+    CERTIFICATE_ERROR(610),
+    IO_EXCEPTION(611),
+    HOST_UNKNOWN(625),
+    USER_UNAUTHORIZED(613),
+    UNKNOWN_EXCEPTION(699),
+    SSL_EXCEPTION(697),
+    INVALID_PAYLOAD(698),
+    INVALID_RESPONSE(601),
+    PENDING(100),
+    REJECTED(101),
+    FINAL_SUCCESS(200),
+    REQ_FAILURE(401),
+    MESSAGE(1),
+    CODE(0),
+    INITRESPONSE(0),
+    FINALRESPONSE(1);
+    // @formatter:on
+
+    private final Set<Integer> initCodes = new HashSet<>(Arrays.asList(100, 101));
+    private final Set<Integer> finalCodes = new HashSet<>(Arrays.asList(200, 500));
+    private final ArrayList<Set<Integer>> codeSets = new ArrayList<>(Arrays.asList(initCodes, finalCodes));
+    private final Set<String> messageSet = new HashSet<>(Arrays.asList("PENDING", "FINISHED", "TERMINATED"));
+    private final int value;
+
+    SaltstackResultCodes(int value) {
+        this.value = value;
+    };
+
+    public int getValue() {
+        return value;
+    }
+
+    public boolean checkValidCode(int type, int code) {
+        return codeSets.get(type).contains(code);
+    }
+
+    public String getValidCodes(int type) {
+        StringBuilder sb = new StringBuilder("[ ");
+        codeSets.get(type).stream().forEach(s -> sb.append(s).append(","));
+        return sb.append("]").toString();
+    }
+
+    public boolean checkValidMessage(String message) {
+        return messageSet.contains(message);
+    }
+
+    public String getValidMessages() {
+        StringBuilder sb = new StringBuilder("[ ");
+        messageSet.stream().forEach(s -> sb.append(s).append(","));
+        return sb.append("]").toString();
+    }
+}
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
new file mode 100644
index 0000000..d324752
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+
+
+/*
+ * Class to emulate responses from the Saltstack Server that is compliant with the APP-C Saltstack Server
+ * Interface. Used for jUnit tests to verify code is working. In tests it can be used
+ * as a replacement for methods from ConnectionBuilder class
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+public class SaltstackServerEmulator {
+
+    private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class);
+
+    private static final String SALTSTATE_NAME = "SaltStateName";
+    private static final String STATUS_CODE = "StatusCode";
+    private static final String STATUS_MESSAGE = "StatusMessage";
+
+    private String saltStateName = "test_saltState.yaml";
+
+    /**
+     * Method that emulates the response from an Saltstack Server
+     * when presented with a request to execute a saltState
+     * Returns an saltstack object result. The response code is always the ssh code 200 (i.e connection successful)
+     * payload is json string as would be sent back by Saltstack Server
+     **/
+    //TODO: This class is to be altered completely based on the SALTSTACK server communicaiton.
+    public SaltstackResult Connect(String agentUrl, String payload) {
+        SaltstackResult result = new SaltstackResult();
+
+        try {
+            // Request must be a JSON object
+
+            JSONObject message = new JSONObject(payload);
+            if (message.isNull("Id")) {
+                rejectRequest(result, "Must provide a valid Id");
+            } else if (message.isNull(SALTSTATE_NAME)) {
+                rejectRequest(result, "Must provide a saltState Name");
+            } else if (!message.getString(SALTSTATE_NAME).equals(saltStateName)) {
+                rejectRequest(result, "SaltState " + message.getString(SALTSTATE_NAME) + "  not found in catalog");
+            } else {
+                acceptRequest(result);
+            }
+        } catch (JSONException e) {
+            logger.error("JSONException caught", e);
+            rejectRequest(result, e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * Method to emulate response from an Saltstack
+     * Server when presented with a GET request
+     * Returns an ansibl object result. The response code is always the ssh code 200 (i.e connection successful)
+     * payload is json string as would be sent back by Saltstack Server
+     *
+     **/
+    public SaltstackResult Execute(String agentUrl) {
+
+        Pattern pattern = Pattern.compile(".*?\\?Id=(.*?)&Type.*");
+        Matcher matcher = pattern.matcher(agentUrl);
+        String id = StringUtils.EMPTY;
+        String vmAddress = "192.168.1.10";
+
+        if (matcher.find()) {
+            id = matcher.group(1);
+        }
+
+        SaltstackResult getResult = new SaltstackResult();
+
+        JSONObject response = new JSONObject();
+        response.put(STATUS_CODE, 200);
+        response.put(STATUS_MESSAGE, "FINISHED");
+
+        JSONObject results = new JSONObject();
+
+        JSONObject vmResults = new JSONObject();
+        vmResults.put(STATUS_CODE, 200);
+        vmResults.put(STATUS_MESSAGE, "SUCCESS");
+        vmResults.put("Id", id);
+        results.put(vmAddress, vmResults);
+
+        response.put("Results", results);
+
+        getResult.setStatusCode(200);
+        getResult.setStatusMessage(response.toString());
+
+        return getResult;
+    }
+
+    private void rejectRequest(SaltstackResult result, String Message) {
+        result.setStatusCode(200);
+        JSONObject response = new JSONObject();
+        response.put(STATUS_CODE, SaltstackResultCodes.REJECTED.getValue());
+        response.put(STATUS_MESSAGE, Message);
+        result.setStatusMessage(response.toString());
+    }
+
+    private void acceptRequest(SaltstackResult result) {
+        result.setStatusCode(200);
+        JSONObject response = new JSONObject();
+        response.put(STATUS_CODE, SaltstackResultCodes.PENDING.getValue());
+        response.put(STATUS_MESSAGE, "PENDING");
+        result.setStatusMessage(response.toString());
+    }
+}
\ No newline at end of file
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/resources/ansible-adapter.properties b/saltstack-adapter/saltstack-adapter-provider/src/main/resources/ansible-adapter.properties
new file mode 100644
index 0000000..ccaea20
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/resources/ansible-adapter.properties
@@ -0,0 +1,48 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Copyright (C) 2017 Amdocs
+# =============================================================================
+# 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.
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Default properties for the APP-C TestService Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=${user.home},/opt/opendaylight/current/properties
+
+appc.application.name=APPC
+
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org.onap/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_saltstack_adapter
+
+
+# Default truststore path and password
+org.onap.appc.adapter.saltstack.trustStore=/opt/opendaylight/tls-client/mykeystore.js
+org.onap.appc.adapter.saltstack.trustStore.trustPasswd=changeit
+org.onap.appc.adapter.saltstack.clientType=TRUST_ALL
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml b/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml
new file mode 100755
index 0000000..df5c46d
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  openECOMP : SDN-C
+  ================================================================================
+  Copyright (C) 2017 - 2018 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=========================================================
+  -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+           odl:use-default-for-reference-types="true">
+
+    <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterPropertiesProviderImpl" />
+
+    <bean id="saltstackAdapterInstance" class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterImpl">
+        <argument ref="propProvider"/>
+    </bean>
+
+    <service ref="saltstackAdapterInstance">
+        <interfaces>
+            <value>org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter</value>
+        </interfaces>
+    </service>
+
+</blueprint>
diff --git a/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/appc/default.properties b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/appc/default.properties
new file mode 100644
index 0000000..2f8fb45
--- /dev/null
+++ b/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/appc/default.properties
@@ -0,0 +1,111 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Copyright (C) 2017 Amdocs
+# =============================================================================
+# 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.
+# 
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Default properties for the APP-C Provider Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded 
+# to supply configuration options 
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},.
+
+appc.application.name=APPC
+
+#
+# Define the message resource bundle name to be loaded 
+org.onap.appc.resources=org/onap/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_provider_adapter
+#
+# Set up the logging environment
+#
+org.onap.appc.logging.file=org/onap/appc/logback.xml
+org.onap.appc.logging.path=${user.home};etc;../etc
+org.onap.appc.logger=org.onap.appc
+org.onap.appc.security.logger=org.onap.appc.security
+#
+# The minimum and maximum provider/tenant context pool sizes.  Min=1 means that as soon 
+# as the provider/tenant is referenced a Context is opened and added to the pool.  Max=0 
+# means that the upper bound on the pool is unbounded. 
+org.onap.appc.provider.min.pool=1
+org.onap.appc.provider.max.pool=0
+
+#
+# The following properties are used to configure the retry logic for connection to the 
+# IaaS provider(s).  The retry delay property is the amount of time, in seconds, the
+# application waits between retry attempts.  The retry limit is the number of retries
+# that are allowed before the request is failed.
+org.onap.appc.provider.retry.delay = 30
+org.onap.appc.provider.retry.limit = 10
+
+#
+# The trusted hosts list for SSL access when a certificate is not provided.
+#
+provider.trusted.hosts=*
+#
+# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc).
+# If the server does not change state to a valid state within the alloted time, the operation 
+# fails.
+org.onap.appc.server.state.change.timeout=300
+#
+# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider 
+# to refresh the status of a resource we are waiting on.
+#
+org.onap.appc.openstack.poll.interval=20
+#
+# The connection information to connect to the provider we are using.  These properties 
+# are "structured" properties, in that the name is a compound name, where the nodes 
+# of the name can be ordered (1, 2, 3, ...).  All of the properties with the same ordinal
+# position are defining the same entity.  For example, provider1.type and provider1.name 
+# are defining the same provider, whereas provider2.name and provider2.type are defining
+# the values for a different provider.  Any number of providers can be defined in this 
+# way. 
+#
+
+# Don't change these 2 right now since they are hard coded in the DG
+#provider1.type=appc
+#provider1.name=appc
+
+#These you can change
+#provider1.identity=appc
+#provider1.tenant1.name=appc
+#provider1.tenant1.userid=appc
+#provider1.tenant1.password=appc
+
+# After a change to the provider make sure to recheck these values with an api call to provider1.identity/tokens
+test.expected-regions=1
+test.expected-endpoints=1
+
+#Your OpenStack IP
+#test.ip=192.168.1.2
+# Your OpenStack Platform's Keystone Port (default is 5000)
+#test.port=5000
+#test.tenantid=abcde12345fghijk6789lmnopq123rst
+#test.vmid=abc12345-1234-5678-890a-abcdefg12345
+# Port 8774 below is default port for OpenStack's Nova API Service
+#test.url=http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345
+