Class: Oxidized::SSH

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ SSH

Returns a new instance of SSH.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/oxidized/ssh.rb', line 13

def initialize(options)
  @ip = options[:ip]
  @username = options[:username]
  @password = options[:password]
  @verbose = options[:verbose]
  @debug = options[:debug]
  @prompt = options[:prompt]
  @exec = options[:exec]
  @pty_options = options[:pty_options] ||= { term: "vt100" }
  @port = options[:port] ||= 22
  @output = String.new
  @logger = options[:logger] ||= Logger.new(STDOUT)
  @expectation_handler = options[:expectation_handler]
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



9
10
11
# File 'lib/oxidized/ssh.rb', line 9

def connection
  @connection
end

#debugObject (readonly)

Returns the value of attribute debug.



10
11
12
# File 'lib/oxidized/ssh.rb', line 10

def debug
  @debug
end

#exec(params, expectation) ⇒ Object (readonly)

Returns the value of attribute exec.



10
11
12
# File 'lib/oxidized/ssh.rb', line 10

def exec
  @exec
end

#ipObject (readonly)

Returns the value of attribute ip.



9
10
11
# File 'lib/oxidized/ssh.rb', line 9

def ip
  @ip
end

#outputObject (readonly)

Returns the value of attribute output.



11
12
13
# File 'lib/oxidized/ssh.rb', line 11

def output
  @output
end

#passwordObject (readonly)

Returns the value of attribute password.



9
10
11
# File 'lib/oxidized/ssh.rb', line 9

def password
  @password
end

#portObject (readonly)

Returns the value of attribute port.



11
12
13
# File 'lib/oxidized/ssh.rb', line 11

def port
  @port
end

#promptObject (readonly)

Returns the value of attribute prompt.



10
11
12
# File 'lib/oxidized/ssh.rb', line 10

def prompt
  @prompt
end

#pty_optionsObject (readonly)

Returns the value of attribute pty_options.



10
11
12
# File 'lib/oxidized/ssh.rb', line 10

def pty_options
  @pty_options
end

#sessionObject (readonly)

Returns the value of attribute session.



11
12
13
# File 'lib/oxidized/ssh.rb', line 11

def session
  @session
end

#usernameObject (readonly)

Returns the value of attribute username.



9
10
11
# File 'lib/oxidized/ssh.rb', line 9

def username
  @username
end

Instance Method Details

#check_for_connectionObject



43
44
45
# File 'lib/oxidized/ssh.rb', line 43

def check_for_connection
  prep_connection unless @session
end

#collect_output(params, expectation) ⇒ Object



57
58
59
60
# File 'lib/oxidized/ssh.rb', line 57

def collect_output(params, expectation)
  send_data((params + "\n"), expectation)
  return @output
end

#create_sessionObject



95
96
97
98
99
# File 'lib/oxidized/ssh.rb', line 95

def create_session
  @session = @connection.open_channel do |channel|
    setup_channels(channel)
  end
end

#disconnectObject



139
140
141
142
143
144
# File 'lib/oxidized/ssh.rb', line 139

def disconnect
  Timeout::timeout(5) { @connection.loop }
  rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError
  ensure
  (@connection.close rescue true) unless @connection.closed?
end

#exec!(params, expect = @prompt) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/oxidized/ssh.rb', line 35

def exec!(params, expect = @prompt)
  check_for_connection
  exec(params, expect)
  sanitize_output_buffer("\n", /\r\n/)
  sanitize_output_buffer('', params)
  @output
end

#expect(*regexps) ⇒ Object



75
76
77
78
79
80
81
82
83
84
# File 'lib/oxidized/ssh.rb', line 75

def expect *regexps
  regexps = [regexps].flatten
  @logger.debug "expecting #{regexps.inspect} at #{@ip}" if @debug
  @connection.loop(0.1) do
    sleep 0.1
    match = regexps.find { |regexp| @output.match regexp }
    return match if match
    true
  end
end

#expectation_list_handler(data) ⇒ Object



114
115
116
117
118
119
# File 'lib/oxidized/ssh.rb', line 114

def expectation_list_handler(data)
  @expectation_handler.each_slice(2) do |handler, meth|
    handler.method(meth.to_sym).call(self, data)
  end
  @output
end

#prep_connectionObject



86
87
88
89
# File 'lib/oxidized/ssh.rb', line 86

def prep_connection
  return true if @exec
  start_channel_requests
end

#request_channels(ch) ⇒ Object



121
122
123
124
125
126
127
128
# File 'lib/oxidized/ssh.rb', line 121

def request_channels(ch)
  ch.request_pty @pty_options do |_ch, success_pty|
    raise NoShell, "Can't get PTY" unless success_pty
    ch.send_channel_request 'shell' do |_ch, success_shell|
      raise NoShell, "Can't get shell" unless success_shell
    end
  end
end

#reset_output_bufferObject



130
131
132
# File 'lib/oxidized/ssh.rb', line 130

def reset_output_buffer
  @output = ''
end

#sanitize_output_buffer(sub, *regexs) ⇒ Object



134
135
136
137
# File 'lib/oxidized/ssh.rb', line 134

def sanitize_output_buffer sub, *regexs
  @logger.debug "sanitizing #{regexs.join("|")} with #{sub}" if @debug
  @output.gsub!(/#{regexs.join("|")}/, sub)
end

#send(params) ⇒ Object



71
72
73
# File 'lib/oxidized/ssh.rb', line 71

def send(params)
  @session.send_data params
end

#send_data(params, expectation) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/oxidized/ssh.rb', line 62

def send_data(params, expectation)
  expect expectation
  reset_output_buffer
  send(params)
  @session.process
  expect expectation
  @output
end

#set_data_hook(ch) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/oxidized/ssh.rb', line 106

def set_data_hook(ch)
  ch.on_data do |_ch, data|
    @logger.debug "received #{data}" if @debug
    @output << data
    @output = expectation_list_handler(@output) if @expectation_handler
  end
end

#setup_channels(ch) ⇒ Object



101
102
103
104
# File 'lib/oxidized/ssh.rb', line 101

def setup_channels(ch)
  set_data_hook(ch)
  request_channels(ch)
end

#startObject



28
29
30
31
32
33
# File 'lib/oxidized/ssh.rb', line 28

def start
  raise "MissingSSHLibrary" if !defined? Net::SSH
  @connection = Net::SSH.start(@ip, @username, password: @password, verbose: @verbose, port: @port)
  return yield self if block_given?
  return (@connection and not @connection.closed?)
end

#start_channel_requestsObject



91
92
93
# File 'lib/oxidized/ssh.rb', line 91

def start_channel_requests
  create_session
end