diff options
Diffstat (limited to 'lib/oxidized/input/ssh.rb')
-rw-r--r-- | lib/oxidized/input/ssh.rb | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb new file mode 100644 index 0000000..45c89ba --- /dev/null +++ b/lib/oxidized/input/ssh.rb @@ -0,0 +1,78 @@ +module Oxidized + require 'net/ssh' + require 'oxidized/input/cli' + class SSH < Input + include CLI + class NoShell < StandardError; end + + def connect node + @node = node + @output = '' + @node.model.cfg['ssh'].each { |cb| instance_exec &cb } + begin + @ssh = Net::SSH.start @node.ip, @node.auth[:username], + :password => @node.auth[:password], :timeout => CFG.timeout + rescue Timeout::Error, Net::SSH::Disconnect + return false + end + @ses = open_shell @ssh unless @exec + not @ssh.closed? + end + + def cmd cmd, expect=@node.prompt + Log.debug "SSH: #{cmd} @ #{@node.name}" + if @exec + @ssh.exec! cmd + else + cmd_shell(cmd, expect).gsub(/\r\n/, "\n") + end + end + + private + + def disconnect + begin + @pre_logout.each { |command| cmd command } + @ssh.loop + @ssh.close if not @ssh.closed? + rescue Net::SSH::Disconnect + end + end + + def open_shell ssh + ses = ssh.open_channel do |ch| + ch.on_data do |ch, data| + @output << data + end + ch.request_pty do |ch, success| + raise NoShell, "Can't get PTY" unless success + ch.send_channel_request 'shell' do |ch, success| + raise NoShell, "Can't get shell" unless success + end + end + end + expect @node.prompt + ses + end + + def exec state=nil + state == nil ? @exec : (@exec=state) + end + + def cmd_shell(cmd, expect_re) + @output = '' + @ses.send_data cmd + "\n" + @ses.process + expect expect_re if expect_re + @output + end + + def expect regexp + @ssh.loop(0.1) do + sleep 0.1 + not @output.match regexp + end + end + + end +end |