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 | 
