diff options
author | Saku Ytti <saku@ytti.fi> | 2013-04-17 17:48:50 +0300 |
---|---|---|
committer | Saku Ytti <saku@ytti.fi> | 2013-04-17 17:48:50 +0300 |
commit | 9d217025fac3e335c308f02e7377e14ccfdc0e66 (patch) | |
tree | b90d4d04947fe26a9e592e12d8c4352142380c03 /lib/oxidized/input |
Initial commit
Silly for shit-and-giggles attempt at rancid
Diffstat (limited to 'lib/oxidized/input')
-rw-r--r-- | lib/oxidized/input/cli.rb | 26 | ||||
-rw-r--r-- | lib/oxidized/input/input.rb | 9 | ||||
-rw-r--r-- | lib/oxidized/input/ssh.rb | 78 | ||||
-rw-r--r-- | lib/oxidized/input/telnet.rb | 51 |
4 files changed, 164 insertions, 0 deletions
diff --git a/lib/oxidized/input/cli.rb b/lib/oxidized/input/cli.rb new file mode 100644 index 0000000..30a66f4 --- /dev/null +++ b/lib/oxidized/input/cli.rb @@ -0,0 +1,26 @@ +module Oxidized + class Input + module CLI + + def initialize + @post_login = [] + @pre_logout = [] + end + + def get + @post_login.each { |command| cmd command } + d = @node.model.cmds + disconnect + d + end + + def post_login _post_login + @post_login << _post_login unless @exec + end + + def pre_logout _pre_logout + @pre_logout << _pre_logout unless @exec + end + end + end +end diff --git a/lib/oxidized/input/input.rb b/lib/oxidized/input/input.rb new file mode 100644 index 0000000..e028ce4 --- /dev/null +++ b/lib/oxidized/input/input.rb @@ -0,0 +1,9 @@ +module Oxidized + class Input + class << self + def inherited klass + Oxidized.mgr.loader = { :class => klass } + end + end + end +end 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 diff --git a/lib/oxidized/input/telnet.rb b/lib/oxidized/input/telnet.rb new file mode 100644 index 0000000..6dae2d6 --- /dev/null +++ b/lib/oxidized/input/telnet.rb @@ -0,0 +1,51 @@ +module Oxidized + require 'net/telnet' + require 'oxidized/input/cli' + class Telnet < Input + include CLI + attr_reader :telnet + + def connect node + @node = node + @timeout = CFG.timeout + @node.model.cfg['telnet'].each { |cb| instance_exec &cb } + begin + @telnet = Net::Telnet.new 'Host' => @node.ip, 'Waittime' => @timeout + expect username + @telnet.puts @node.auth[:username] + expect password + @telnet.puts @node.auth[:password] + expect @node.prompt + rescue Errno::ECONNREFUSED, Net::OpenTimeout, Net::ReadTimeout + return false + end + end + + def cmd cmd, expect=@node.prompt + Log.debug "Telnet: #{cmd} @#{@node.name}" + args = { 'String' => cmd } + args.merge!({ 'Match' => expect, 'Timeout' => @timeout }) if expect + @telnet.cmd args + end + + private + + def expect re + @telnet.waitfor 'Match' => re, 'Timeout' => @timeout + end + + def disconnect + @pre_logout.each { |command| cmd(command, nil) } + @telnet.close + end + + def username re=/^(Username|login)/ + @username or @username = re + end + + def password re=/^Password/ + @password or @password = re + end + + end +end |