Package sos.scheduler.job

Source Code of sos.scheduler.job.JobSchedulerSSHJob$PsEfLine

/********************************************************* begin of preamble
**
** Copyright (C) 2003-2010 Software- und Organisations-Service GmbH.
** All rights reserved.
**
** This file may be used under the terms of either the
**
**   GNU General Public License version 2.0 (GPL)
**
**   as published by the Free Software Foundation
**   http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
**   LICENSE.GPL included in the packaging of this file.
**
** or the
** 
**   Agreement for Purchase and Licensing
**
**   as offered by Software- und Organisations-Service GmbH
**   in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package sos.scheduler.job;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;

import sos.configuration.SOSConfiguration;
import sos.scheduler.managed.JobSchedulerManagedObject;
import sos.spooler.Order;
import sos.spooler.Variable_set;
import sos.util.SOSSchedulerLogger;

import com.trilead.ssh2.Session;
import com.trilead.ssh2.StreamGobbler;


/**
* @author andreas.pueschel@sos-berlin.com
* @author ghassan.beydoun@sos-berlin.com
* $Id: JobSchedulerSSHJob.java 3178 2008-01-04 13:49:31Z al $
* see job documentation in the package jobdoc for details
*/

public class JobSchedulerSSHJob extends JobSchedulerSSHBaseJob {

  private class PsEfLine implements Comparable{

    public String             user                     = null;

    public int                pid                      ;

    public int                parentPid                ;

    public String             commandLine              = null;

    public ArrayList          children                 = new ArrayList();       

    /* (non-Javadoc)
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    public int compareTo(Object o) {
      PsEfLine other = (PsEfLine) o;
      return pid-other.pid;
    }   

  }

  /** Inputstreams for stdout and stderr **/
  protected InputStream stdout;
  protected InputStream stderr;

  /** Output from stdout and stderr **/
  protected StringBuffer stderrOutput;

  protected Variable_set params = null;

  public void initKillJob(){
    try{
      try{
        spooler.job("scheduler_ssh_kill");
      } catch(Exception e){
        spooler_log.debug1("initializing ssh kill job");
        spooler.execute_xml("<job name=\"scheduler_ssh_kill\" title=\"Kill processes launched by SSH\""+
            " order=\"no\" stop_on_error=\"no\">"+
            "<description>"+
            "<include file=\"jobs/JobSchedulerSSHJob.xml\"/>"+
            "</description>"+
            "<params>"+
            "<param name=\"is_kill_job\" value=\"true\"/>"+
            "</params>"+  
            "<script language=\"java\""+
            " java_class=\"sos.scheduler.job.JobSchedulerSSHJob\"/>"+
        "</job>");
      }
    } catch(Exception e){
      spooler_log.warn("Failed to initialize kill job: "+e);
    }
  }

  /**
   * Processing
   *
   */

  public boolean spooler_process() {

    String sshKillPid = "";

    boolean isSSHKillJob = false;
    sos.net.sosftp.SOSFTPCommandSSH ftpCommand = null;       
    Properties schedulerParameter = null;
//    SOSString sosString = new SOSString();

    try {
      try { // to fetch parameters, order parameters have precedence to job parameters

        params = getParameters();
        String commandScript = "";
        String commandScriptFileName = "";
        schedulerParameter = getSchedulerParameterAsProperties(params)

        if (params.value("is_kill_job") != null && params.value("is_kill_job").length() > 0) {
          if (params.value("is_kill_job").equalsIgnoreCase("true") || params.value("is_kill_job").equalsIgnoreCase("yes") || params.value("is_kill_job").equals("1")) {                     
            isSSHKillJob= true;
          } else {
            isSSHKillJob= false;
          }
          spooler_log.info(".. parameter [is_kill_job]: " + isSSHKillJob);
        }

        if (isSSHKillJob){
          if (params.value("job_scheduler_ssh_kill_pid") != null && params.value("job_scheduler_ssh_kill_pid").length() > 0) {
            sshKillPid = (params.value("job_scheduler_ssh_kill_pid"));
            spooler_log.debug(".. parameter [job_scheduler_ssh_kill_pid]: " + sshKillPid);
          } else {
            spooler_log.info("Process doesn't need to be killed. Doing nothing");
            return false;
          }
          if (sshKillPid.equals("0")){
            spooler_log.info("Process doesn't need to be killed. Doing nothing");
            return false;
          }
        }

        if (params.value("command_script") != null && params.value("command_script").length() > 0) {
          commandScript= params.value("command_script");
          if (JobSchedulerManagedObject.isHex(commandScript)) {
            commandScript = new String(JobSchedulerManagedObject.fromHexString(commandScript),"US-ASCII");                     
            schedulerParameter.put("command_script", commandScript);
          }
          spooler_log.info(".. parameter [command_script]: " + commandScript);
        }

        if (params.value("command") != null && params.value("command").length() > 0) {
          String sCommand = params.value("command");
          if (JobSchedulerManagedObject.isHex(sCommand)) {
            sCommand = new String(JobSchedulerManagedObject.fromHexString(sCommand),"US-ASCII");
            schedulerParameter.put("jump_command", sCommand);
          }
          spooler_log.info(".. parameter [command]: " + sCommand);
          /**
           * \change
           * see http://www.sos-berlin.com/jira/browse/JS-672
           */
//        } else if (commandScript.length()==0 && commandScriptFileName.length()==0){
        } else if (commandScriptFileName.length()==0 && commandScriptFileName.length()==0){
          throw new Exception("no command (or command_script or command_script_file) has been specified for parameter [command]");
        }


      } catch (Exception e) {
        throw new Exception("error occurred processing parameters: " + e.getMessage());
      }

      try { // to connect, authenticate and execute commands

        if (isSSHKillJob){
          this.getBaseParameters();
          this.getBaseAuthentication();
          if (sshKillPid.length()>0){           
            remoteKill(sshKillPid);
          }
        }else{

          SOSConfiguration con =
            new SOSConfiguration(null, schedulerParameter, null, null, "sos/net/sosftp/Configuration.xml", new SOSSchedulerLogger(spooler_log));

          con.checkConfigurationItems();

          ftpCommand = new sos.net.sosftp.SOSFTPCommandSSH(con, new SOSSchedulerLogger(spooler_log));
          ftpCommand.setSchedulerJob(this);
          boolean rc = ftpCommand.transfer();
         
          //test
          /*if(sosString.parseToBoolean(con.getParameterAsProperties().get("ignore_error"))) {
            rc = true;
          }*/
         
          return (spooler_task.job().order_queue() == null) ? false : rc; 
        }

      } catch (Exception e) {
        throw new Exception("error occurred processing ssh command: " + e.getMessage());               
      } finally {
        if(ftpCommand != null)
          createOrderParameter(ftpCommand.getExitStatus());               
        if (this.getSshConnection() != null) try { this.getSshConnection().close(); this.setSshConnection(null); } catch (Exception ex) {} // gracefully ignore this error
      }
      return (spooler_task.job().order_queue() != null);

    } catch (Exception e) {
      spooler_log.error(e.getMessage());       
      return false;
    }
  }

  public static String myReplaceAll(String source, String what, String replacement) {

    String newReplacement = replacement.replaceAll("\\$", "\\\\\\$");     
    return source.replaceAll("(?m)"+what, newReplacement);
  }

  public void remoteKill(String pid) {
    try{
      HashMap pidMap = new HashMap();
      spooler_log.debug3("killing remote process...");
      this.setSshSession(this.getSshConnection().openSession());

      spooler_log.debug5("fetching children");
      this.getSshSession().execCommand("/bin/ps -ef");

      spooler_log.debug9("output to stdout for ps command: ");
      stdout = new StreamGobbler(this.getSshSession().getStdout());
      stderr = new StreamGobbler(this.getSshSession().getStderr());
      BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
      String line = stdoutReader.readLine(); //Ueberschrift
      spooler_log.debug9(line);


      while (true) {
        line = stdoutReader.readLine();           
        if (line == null) break;
        spooler_log.debug9(line);
        line = line.trim();
        String[] fields = line.split(" +", 8);
        PsEfLine pel = new PsEfLine();
        pel.user = fields[0];
        pel.pid  = Integer.parseInt(fields[1]);
        pel.parentPid = Integer.parseInt(fields[2]);
        pel.commandLine = fields[7];
        pidMap.put(new Integer(pel.pid), pel);
      }

      spooler_log.debug9("output to stderr for ps command: " );

      BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
      stderrOutput = new StringBuffer();
      while (true) {
        line = stderrReader.readLine();
        if (line == null) break;
        spooler_log.debug9(line);
        stderrOutput.append( line + "\n");
      }

      // get children of parent pid
      Iterator pelIter = pidMap.values().iterator();
      while (pelIter.hasNext()){
        PsEfLine current = (PsEfLine) pelIter.next();
        PsEfLine parent = (PsEfLine) pidMap.get(new Integer(current.parentPid));
        if (parent!=null) {
          spooler_log.debug9("Child of "+parent.pid+" is "+current.pid);
          parent.children.add(new Integer(current.pid));
        }
      }

      spooler_log.info("killing pid "+pid);
      executeCommand("kill -9 "+pid, -9);

      Integer parentPid = new Integer(pid);
      if(pidMap.containsKey(parentPid)){
        PsEfLine pel = (PsEfLine) pidMap.get(parentPid);
        if (pel.children.size()>0){
          spooler_log.debug("killing children of pid "+pid);
          killChildrenOfPid(pel, pidMap);
        }
      } else {
        spooler_log.debug("remote process pid="+pid + " not exist.");
      }
    } catch(Exception e){
      try{
        spooler_log.warn("failed to kill remote process: "+e);
      }catch(Exception ex){}
    } finally{
      getSshSession().close();
    }
  }

  private void killChildrenOfPid(PsEfLine pel, HashMap pidMap) throws Exception{
    try{     
      if (pel.children.size() == 0) return;
      Iterator iter = pel.children.iterator();
      while(iter.hasNext()){
        Integer childPid = (Integer) iter.next();
        PsEfLine child = (PsEfLine) pidMap.get(childPid);
        spooler_log.debug("killing child pid "+child.pid);
        executeCommand("kill -9 "+child.pid, -9);
        killChildrenOfPid(child, pidMap);
      }

    } catch(Exception e){
      throw new Exception("Failed to kill children of pid "+pel.pid+": "+e,e);
    }
  }

  private void executeCommand(String command, int logLevel) throws Exception{
    Session session = getSshConnection().openSession();
    try{
      session.execCommand(command);
      spooler_log.log(logLevel,"output to stdout for remote command: " + command);
      stdout = new StreamGobbler(this.getSshSession().getStdout());
      stderr = new StreamGobbler(this.getSshSession().getStderr());
      BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));

      while (true) {
        String line = stdoutReader.readLine();
        if (line == null) break;
        spooler_log.log(logLevel, line);
      }


      spooler_log.log(logLevel, "output to stderr for remote command: " + command);

      BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
      stderrOutput = new StringBuffer();
      while (true) {
        String line = stderrReader.readLine();
        if (line == null) break;
        spooler_log.log(logLevel,line);
        stderrOutput.append( line + "\n");
      }
    }catch(Exception e){
      throw new Exception ("Error executing command \""+command+"\": "+e,e);
    }finally{
      if (session !=null) session.close();
    }   
  }

  /**
   * Parameter auslesen
   */
  private Variable_set getParameters() throws Exception {
    Order order = null;
    try {     
      Variable_set params = spooler.create_variable_set();      
      params = spooler_task.params();

      if (spooler_task.job().order_queue() != null) {
        order = spooler_task.order();
        if ( order.params() != null)
          params.merge(order.params());
      }
      return params;
    } catch (Exception e) {
      throw new Exception("error occurred reading Patameter: " + e.getMessage());
    }
  }

  /**
   * Convert parameters from sos.spooler.Variable_set in java.util.Properties.
   *
   * @param params as Variable_set
   * @return java.util.Properties
   * @throws Exception
   */
  private Properties getSchedulerParameterAsProperties(Variable_set params) throws Exception{
    Properties schedulerParams = new Properties();//hier variable_set in Properties casten
    try {
      if (params == null)
        return new Properties();

      String[] names = params.names().split(";");
      spooler_log.debug9("names " + params.names());

      for(int i = 0; i < names.length; i++) {
        String key = names[i];
        String val = params.var(names[i]);

        if(key.length() > 0) {
          key = "jump_" + key;
        }
        spooler_log.debug1("param [" + key +"=" + val + "]");
        schedulerParams.put(key, val);
      }

      //Einige Defaults hinzuf�gen
      schedulerParams.put("operation", "execute");     
      schedulerParams.put("check_params_names", "no");

      return schedulerParams;
    } catch (Exception e) {
      throw new Exception("error occurred reading Patameter: " + e.getMessage());
    }
  }

  public void setSchedulerSSHKillPid(int pid) {
    spooler_task.params().set_var("job_scheduler_ssh_kill_pid", ""+pid);
  }

  private void createOrderParameter(Integer exitstatus) throws Exception  {
    try {

      // return the number of transferred files and filenames
      if (spooler_job.order_queue() != null) {
        if (spooler_task.order() != null && spooler_task.order().params() != null) {
          spooler_task.order().params().set_var("job_scheduler_ssh_exit_code", Integer.toString(exitstatus.intValue()) );
        }
      }
    } catch (Exception e) {
      throw new Exception("error occurred creating order Parameter: " + e.getMessage());
    }

  }

}
TOP

Related Classes of sos.scheduler.job.JobSchedulerSSHJob$PsEfLine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.