reqExec API implemented for saltstack
[ccsdk/sli/adaptors.git] / saltstack-adapter / saltstack-adapter-provider / src / main / java / org / onap / ccsdk / sli / adaptors / saltstack / impl / ConnectionBuilder.java
index 7702dc8..5dee9f5 100644 (file)
 
 package org.onap.ccsdk.sli.adaptors.saltstack.impl;
 
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.RandomStringUtils;
 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;
@@ -47,30 +54,142 @@ import com.att.eelf.configuration.EELFManager;
 public class ConnectionBuilder {
 
     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
+    SshConnection sshConnection;
 
+    /**
+     * Constructor that initializes an ssh client based on username and password
+     **/
+    public ConnectionBuilder(String host, String port, String userName, String userPasswd) {
+        sshConnection = new SshConnection(host, Integer.parseInt(port), userName, userPasswd);
+    }
 
     /**
-     * Constructor that initializes an ssh client based on certificate
+     * Constructor that initializes an ssh client based on ssh certificate
      **/
-    public ConnectionBuilder(String userName, String userPasswd) throws KeyStoreException, CertificateException, IOException,
-            KeyManagementException, NoSuchAlgorithmException, SvcLogicException {
+    public ConnectionBuilder(String host, String port, String certFile) {
+        sshConnection = new SshConnection(host, Integer.parseInt(port), certFile);
+    }
 
+    /**
+     * Constructor that initializes an ssh client based on ssh username password and certificate
+     **/
+    public ConnectionBuilder(String host, String port, String userName, String userPasswd,
+                             String certFile) {
 
+        sshConnection = new SshConnection(host, Integer.parseInt(port), userName, userPasswd, certFile);
     }
 
     /**
-     * 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 {
+     * 1. Connect to SSH server.
+     * 2. Exec remote command over SSH. Return command execution status.
+     * Command output is written to out or err stream.
+     *
+     * @param cmd Commands to execute
+     * @return command execution status
+     */
+    public SaltstackResult connectNExecute(String cmd) {
+        return connectNExecute(cmd,-1,-1);
+    }
+
+    /**
+     * 1. Connect to SSH server with retry enabled.
+     * 2. Exec remote command over SSH. Return command execution status.
+     * Command output is written to out or err stream.
+     *
+     * @param cmd Commands to execute
+     * @param retryDelay delay between retry to make a SSH connection.
+     * @param retryCount number of count retry to make a SSH connection.
+     * @return command execution status
+     */
+    public SaltstackResult connectNExecute(String cmd, int retryCount, int retryDelay) {
+
+        SaltstackResult result = new SaltstackResult();
+        try {
+            if (retryCount != -1) {
+                result = sshConnection.connectWithRetry(retryCount, retryDelay);
+            } else {
+                result = sshConnection.connect();
+            }
+            if (result.getStatusCode() != SaltstackResultCodes.SUCCESS.getValue()) {
+                return result;
+            }
+            String outFilePath = "/tmp/"+ RandomStringUtils.random(5,true,true);
+            String errFilePath = "/tmp/"+ RandomStringUtils.random(5,true,true);
+            OutputStream out = new FileOutputStream(outFilePath);
+            OutputStream errs = new FileOutputStream(errFilePath);
+            result = sshConnection.execCommand(cmd, out, errs);
+            sshConnection.disconnect();
+            out.close();
+            errs.close();
+            if (result.getSshExitStatus() != 0) {
+                return sortExitStatus(result.getSshExitStatus(), errFilePath, cmd);
+            }
+            if (result.getStatusCode() != SaltstackResultCodes.SUCCESS.getValue()) {
+                return result;
+            }
+            result.setStatusMessage("Success");
+            result.setOutputFileName(outFilePath);
+        } catch (Exception io) {
+            logger.error("Caught Exception", io);
+            result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
+            result.setStatusMessage(io.getMessage());
+        }
+        return result;
+    }
 
+    public SaltstackResult sortExitStatus (int exitStatus, String errFilePath, String cmd)  {
+        SaltstackResult result = new SaltstackResult();
+        String err;
+        StringWriter writer = new StringWriter();
+        try {
+            IOUtils.copy(new FileInputStream(new File(errFilePath)), writer, "UTF-8");
+            err = writer.toString();
+        } catch (Exception e){
+            err = "";
+        }
+        if (exitStatus == 255 || exitStatus == 1) {
+            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+                    + "]. Exit Code " + exitStatus + " and Error message : " +
+                    "Malformed configuration. "+ err;
+            logger.error(errMessage);
+            result.setStatusCode(SaltstackResultCodes.INVALID_COMMAND.getValue());
+            result.setStatusMessage(errMessage);
+        } else if (exitStatus == 5 || exitStatus == 65) {
+            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+                    + "]. Exit Code " + exitStatus + " and Error message : " +
+                    "Host not allowed to connect. "+ err;
+            logger.error(errMessage);
+            result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
+            result.setStatusMessage(errMessage);
+        } else if (exitStatus == 67 || exitStatus == 73) {
+            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+                    + "]. Exit Code " + exitStatus + " and Error message : " +
+                    "Key exchange failed. "+ err;
+            logger.error(errMessage);
+            result.setStatusCode(SaltstackResultCodes.CERTIFICATE_ERROR.getValue());
+            result.setStatusMessage(errMessage);
+        } else {
+            String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+                    + "]. Exit Code " + exitStatus + " and Error message : "+ err;
+            logger.error(errMessage);
+            result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
+            result.setStatusMessage(errMessage);
+        }
+        return result;
     }
 
     /**
-     * Connect to SSH server.
+     * 1. Connect to SSH server.
+     * 2. Exec remote command over SSH. Return command execution status.
+     * Command output is written to out or err stream.
+     *
+     * @param commands list of commands to execute
+     * @param payloadSLS has the SLS file location that is to be sent to server
+     * @param retryDelay delay between retry to make a SSH connection.
+     * @param retryCount number of count retry to make a SSH connection.
+     * @return command execution status
      */
-    public SaltstackResult connect(String agentUrl, String payload) {
+    public SaltstackResult connectNExecuteSLS(String commands, String payloadSLS, int retryDelay, int retryCount) {
 
         SaltstackResult result = new SaltstackResult();
         try {
@@ -104,8 +223,6 @@ public class ConnectionBuilder {
      * 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) {