Class: BaseProcessingClass

Inherits:
Object
  • Object
show all
Defined in:
lib/sshotgun.rb

Overview

This is the base processing class. Your custom processing class MUST inherit from this base class.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sshotgun, hostdef) ⇒ BaseProcessingClass

Default constructor. Don’t create a constructor in your custom processing class so that this constructor will be called.



80
81
82
83
# File 'lib/sshotgun.rb', line 80

def initialize(sshotgun, hostdef)
  @sshotgun = sshotgun
  @hostdef = hostdef
end

Instance Attribute Details

#hostdefObject

The current HostDefinition object (represents the remote server for processing)



75
76
77
# File 'lib/sshotgun.rb', line 75

def hostdef
  @hostdef
end

#sshotgunObject

A SSHotgun object



72
73
74
# File 'lib/sshotgun.rb', line 72

def sshotgun
  @sshotgun
end

Instance Method Details

#copyLocalFileToRemote(localfile, remotefile, modestr = "0644") ⇒ Object

Copy a local file to remote

localfile is the local file to copy. e.g. “/home/vickp/temp/myscript.sh”

remotefile is the name of the destination remote file. e.g. “/usr/local/bin/myscript.sh”

modestr is the string containing parameters for the chmod operation. The string must be in the NNNN or ugo format. e.g. “0755” or “u=rwx,g=rw,o=r”



165
166
167
168
169
170
171
172
173
# File 'lib/sshotgun.rb', line 165

def copyLocalFileToRemote(localfile, remotefile, modestr = "0644")
  log "[" + @hostdef.hostname + "] copyLocalFileToRemote: " + localfile + " " + @hostdef.hostname + ":" + remotefile
  if @sshotgun.gatewayhost
    cmdline = "cat " + localfile + " | gzip - | ssh -A -t -x " + @sshotgun.gatewayhost + " 'ssh -A -x " + @hostdef.hostname + " \"cat | gzip -d > " + remotefile + "; chmod " + modestr + " " + remotefile + "\"'"
  else
    cmdline = "cat " + localfile + " | gzip - | ssh -A -t -x " + @hostdef.hostname + " \"cat | gzip -d > " + remotefile + "; chmod " + modestr + " " + remotefile + "\""
  end
  runLocal cmdline, false
end

#copyRemoteFileToLocal(remotefile, localfile, modestr = "0644") ⇒ Object

Copy a remote file to local

remotefile is the remote file to fetch. e.g. “/usr/local/bin/myscript.sh”

localfile is the name of the destination local file. e.g. “/home/vickp/temp/myscript.sh”

modestr is the string containing parameters for the chmod operation. The string must be in the NNNN or ugo format. e.g. “0755” or “u=rwx,g=rw,o=r”



146
147
148
149
150
151
152
153
154
# File 'lib/sshotgun.rb', line 146

def copyRemoteFileToLocal(remotefile, localfile, modestr = "0644")
  log "[" + @hostdef.hostname + "] copyRemoteFileToLocal: " + @hostdef.hostname + ":" + remotefile + " " + localfile
  if @sshotgun.gatewayhost
    cmdline = "ssh -A -t -x " + @sshotgun.gatewayhost + " 'ssh -A -x " + @hostdef.hostname + " \"cat " + remotefile + " | gzip - \"' | gzip -d - > " + localfile + "; chmod " + modestr + " " + localfile
  else
    cmdline = "ssh -A -t -x " + @hostdef.hostname + " \"cat " + remotefile + " | gzip - \" | gzip -d - > " + localfile + "; chmod " + modestr + " " + localfile
  end
  runLocal cmdline, false
end

#createRemoteFile(contentstr, remotefile, modestr = "0644") ⇒ Object

Create a remote text file from a content string.

contentstr is the content to write to the file.

remotefile is the name of the destination remote file. e.g. “/usr/local/bin/myscript.sh”

modestr is the string containing parameters for the chmod operation. The string must be in the NNNN or ugo format. e.g. “0755” or “u=rwx,g=rw,o=r”



184
185
186
187
188
189
190
191
192
# File 'lib/sshotgun.rb', line 184

def createRemoteFile(contentstr, remotefile, modestr = "0644")
  log "[" + @hostdef.hostname + "] createRemoteFile: " + @hostdef.hostname + ":" + remotefile
  if @sshotgun.gatewayhost
    cmdline = "echo \"" + contentstr + "\" | gzip - | ssh -A -t -x " + @sshotgun.gatewayhost + " 'ssh -A -x " + @hostdef.hostname + " \"cat | gzip -d > " + remotefile + "; chmod " + modestr + " " + remotefile + "\"'"
  else
    cmdline = "echo \"" + contentstr + "\" | gzip - | ssh -A -t -x " + @hostdef.hostname + " \"cat | gzip -d > " + remotefile + "; chmod " + modestr + " " + remotefile + "\""
  end
  runLocal cmdline, false
end

#doProcessingObject

You must override the doProcessing method in your own custom processing class



87
88
89
# File 'lib/sshotgun.rb', line 87

def doProcessing
  log "[" + @hostdef.hostname + "] info: " + "The doProcessing method must be created in your custom processing class"
end

#hasUnescapedQuotes(s) ⇒ Object

Does the string contain unescaped quotes? This is a safety measure. If there are unescaped quotes (double or single) contained in a command string, it may be interpolated differently than as is expected. For example a compound command may execute the first part on a local or gateway server and the last part on the remote server.

s is the string to check



266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/sshotgun.rb', line 266

def hasUnescapedQuotes(s)
  retval = false
  previousChar = ""
  sArray = s.split(//)
  sArray.each do |currentChar|
    #log currentChar
    if (currentChar == "\"" || currentChar == "\'") && previousChar != "\\"
      retval = true
      break
    end
    previousChar = currentChar
  end
  return retval
end

#log(s) ⇒ Object

Log a string to the console.

s is the string to log



254
255
256
# File 'lib/sshotgun.rb', line 254

def log(s)
  @sshotgun.log s
end

#run(cmd) ⇒ Object

Run a command on a remote server

cmd is a string containing the command to run on a remote server. e.g. “ls -alF”

Returns a RunStatus object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/sshotgun.rb', line 97

def run(cmd)
  log "[" + @hostdef.hostname + "] run: " + cmd
  if !hasUnescapedQuotes(cmd)
    if @sshotgun.gatewayhost
      cmdline = "ssh -A -t -x " + @sshotgun.gatewayhost + " 'ssh -A -x " +  @hostdef.hostname + " \"" + cmd + "\"'"
    else
      cmdline = "ssh -A -t -x " +  @hostdef.hostname + " \"" + cmd + "\""
    end
    runLocal cmdline, false
  else
    log "[_sshotgun_] fatal: Command string cannot contain unescaped quotes. Surround command string"
    log "[_sshotgun_] fatal: with single quotes or %q() so that Ruby does not interpolate string first."
    @sshotgun.exitCode = 1
    @sshotgun.showRunStatsAndExit
  end
end

#runLocal(cmdline, isSudo = false) ⇒ Object

Execute a command locally without launching ssh. Note that this will be executed for EACH host.

cmdline is the command line to run

isSudo is the flag to launch as a sudo command



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/sshotgun.rb', line 200

def runLocal (cmdline, isSudo=false)
  if @sshotgun.isDebug
    # display & log the actual command line sent to ssh
    log "[" + @hostdef.hostname + "] debug: raw command line to local ssh client: " + cmdline
  end
  currentThread = Thread.current
  runstatus = RunStatus.new
  retval = Open4::popen4( cmdline ) do |pid, stdin, stdout, stderr|
    # isSudo and if sudo password is defined, insert the sudo password via stdin
    if isSudo
      if @sshotgun.sudopassword
        stdin.puts @sshotgun.sudopassword
      else
        log "[" + @hostdef.hostname + "] info: sudo invoked but sudo password is blank"
      end
    end
    runstatus.stdoutstr = stdout.read.strip
    runstatus.stdoutstr.each do |line|
      log "[" + @hostdef.hostname + "] stdout: " + line
    end
    runstatus.stderrstr = stderr.read.strip
    runstatus.stderrstr.each do |line|
      log "[" + @hostdef.hostname + "] stderr: " + line
    end
  end
  runstatus.exitstatus = retval.exitstatus

  if runstatus.exitstatus != 0
    # am I supposed to stop thread?
    if @sshotgun.isStopOnNonZeroExit
      log "[" + @hostdef.hostname + "] stderr: Non-zero exit status - Stop processing for this server (" + runstatus.exitstatus.to_s + ")"
      currentThread.exit
    else
      # did not exit thread so just log that a non-zero exit occured
      log "[" + @hostdef.hostname + "] stderr: Non-zero exit status (" + runstatus.exitstatus.to_s + ")"
    end
  end

  # return runstatus to caller
  return runstatus
end

#runLocalSudo(cmdline) ⇒ Object

Execute a sudo command locally without launching ssh. Note that this will be executed for EACH host.

cmdline is the command line to run



246
247
248
# File 'lib/sshotgun.rb', line 246

def runLocalSudo (cmdline)
  runLocal(cmdline, true)
end

#runSudo(cmd) ⇒ Object

Sudo a command on a remote server

cmd is a string containing the sudo command to run on a remote server. e.g. “ls -alF”

Returns a RunStatus object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/sshotgun.rb', line 120

def runSudo(cmd)
  log "[" + @hostdef.hostname + "] runSudo: " + cmd
  if !hasUnescapedQuotes(cmd)
    if @sshotgun.gatewayhost
      cmdline = "ssh -A -t -x " + @sshotgun.gatewayhost + " 'ssh -A -x " + @hostdef.hostname + " sudo -S \"" + cmd + "\"'"
    else
      cmdline = "ssh -A -t -x " + @hostdef.hostname + " sudo -S \"" + cmd + "\""
    end
    runLocal cmdline, true
  else
    log "[_sshotgun_] fatal: Command string cannot contain unescaped quotes. Surround command string"
    log "[_sshotgun_] fatal: with single quotes or %q() so that Ruby does not interpolate string first."
    @sshotgun.exitCode = 1
    @sshotgun.showRunStatsAndExit
  end
end