diff options
Diffstat (limited to 'lib/oxidized')
| -rw-r--r-- | lib/oxidized/cli.rb | 48 | ||||
| -rw-r--r-- | lib/oxidized/config.rb | 44 | ||||
| -rw-r--r-- | lib/oxidized/config/bootstrap.rb | 33 | ||||
| -rw-r--r-- | lib/oxidized/config/core.rb | 33 | ||||
| -rw-r--r-- | lib/oxidized/config/defaults.rb | 14 | ||||
| -rw-r--r-- | lib/oxidized/core.rb | 2 | ||||
| -rw-r--r-- | lib/oxidized/input/ssh.rb | 14 | ||||
| -rw-r--r-- | lib/oxidized/input/telnet.rb | 2 | ||||
| -rw-r--r-- | lib/oxidized/node.rb | 4 | ||||
| -rw-r--r-- | lib/oxidized/nodes.rb | 2 | ||||
| -rw-r--r-- | lib/oxidized/output/file.rb | 15 | ||||
| -rw-r--r-- | lib/oxidized/output/git.rb | 23 | ||||
| -rw-r--r-- | lib/oxidized/output/output.rb | 1 | ||||
| -rw-r--r-- | lib/oxidized/source/csv.rb | 27 | ||||
| -rw-r--r-- | lib/oxidized/source/source.rb | 1 | ||||
| -rw-r--r-- | lib/oxidized/source/sql.rb | 29 | 
16 files changed, 149 insertions, 143 deletions
| diff --git a/lib/oxidized/cli.rb b/lib/oxidized/cli.rb new file mode 100644 index 0000000..720f405 --- /dev/null +++ b/lib/oxidized/cli.rb @@ -0,0 +1,48 @@ +module Oxidized +  class CLI +    require 'oxidized' +    require 'slop' +    class CLIError < OxidizedError; end +    class NoConfig < CLIError; end + +    def run +      Process.daemon unless CFG.debug +      begin +        Oxidized.new +      rescue => error +        crash error +        raise +      end +    end + +    private + +    def initialize +      if CFGS.system.empty? and CFGS.user.empty? +        CFGS.user = CFGS.default +        CFGS.save :user +        raise NoConfig, 'edit ~/.config/oxidized/config' +      end +      _args, opts = parse_opts +      CFG.debug = true if opts[:debug] +    end + +    def crash error +      open Config::Crash, 'w' do |file| +        file.puts '-' * 50 +        file.puts Time.now.utc +        file.puts error.message + ' [' + error.class.to_s + ']' +        file.puts '-' * 50 +        file.puts error.backtrace +        file.puts '-' * 50 +      end +    end + +    def parse_opts +      opts = Slop.new(:help=>true) do +        on 'd', 'debug', 'turn on debugging' +      end +      [opts.parse!, opts] +    end +  end +end diff --git a/lib/oxidized/config.rb b/lib/oxidized/config.rb new file mode 100644 index 0000000..475ae14 --- /dev/null +++ b/lib/oxidized/config.rb @@ -0,0 +1,44 @@ +module Oxidized +  require 'asetus' +  class Config +    Root      = File.join ENV['HOME'], '.config', 'oxidized' +    Crash     = File.join Root, 'crash' +    InputDir  = File.join Directory, %w(lib oxidized input) +    OutputDir = File.join Directory, %w(lib oxidized output) +    ModelDir  = File.join Directory, %w(lib oxidized model) +    SourceDir = File.join Directory, %w(lib oxidized source) +    Sleep     = 1 +  end +  class << self +    attr_accessor :mgr +  end +  CFGS = Asetus.new :name=>'oxidized', :load=>false, :key_to_s=>true +  CFGS.default.username = 'username' +  CFGS.default.password = 'password' +  CFGS.default.model    = 'junos' +  CFGS.default.interval = 3600 +  CFGS.default.log      = File.join Config::Root, 'log' +  CFGS.default.debug    = false +  CFGS.default.threads  = 30 +  CFGS.default.timeout  = 30 +  CFGS.default.prompt   = /^([\w.@-]+[#>]\s?)$/ +  CFGS.default.rest     = '0.0.0.0:8888'  # or false to disable +  CFGS.default.vars     = {}              # could be 'enable'=>'enablePW' + +  CFGS.default.input.default = 'ssh, telnet' +  CFGS.default.input.ssh.secure = false + +  CFGS.default.output.default = 'git' +  CFGS.default.source.default = 'csv' + +  CFGS.default.model_map = { +    'cisco'   => 'ios', +    'juniper' => 'junos', +  } + +  CFGS.load       # load system+user configs, merge to Config.cfg +  CFG = CFGS.cfg  # convenienence, instead of Config.cfg.password, CFG.password + +  Log.level = Logger::INFO unless CFG.debug +  Log.file  = CFG.log if CFG.log +end diff --git a/lib/oxidized/config/bootstrap.rb b/lib/oxidized/config/bootstrap.rb deleted file mode 100644 index 008d88a..0000000 --- a/lib/oxidized/config/bootstrap.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Oxidized -  require 'fileutils' -  FileUtils.mkdir_p Config::Root -  CFG.username = 'username' -  CFG.password = 'password' -  CFG.model    = 'junos' -  CFG.interval = 3600 -  CFG.log      = File.join Config::Root, 'log' -  CFG.debug    = false -  CFG.threads  = 30 -  CFG.timeout  = 30 -  CFG.prompt   = /^([\w.@-]+[#>]\s?)$/ -  CFG.rest     = '0.0.0.0:8888' -  CFG.vars     = { -    #:enable  => 'enablePW', -  } -  CFG.input   = { -    :default  => 'ssh, telnet', -    :ssh      =>  { -      :secure => false, -    } -  } -  CFG.output    = { -    :default => 'git', -  } -  CFG.source   = { -    :default => 'csv', -  } -  CFG.model_map = { -    'cisco'   => 'ios', -    'juniper' => 'junos', -  } -end diff --git a/lib/oxidized/config/core.rb b/lib/oxidized/config/core.rb deleted file mode 100644 index 59ada3a..0000000 --- a/lib/oxidized/config/core.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Oxidized -  require 'ostruct' -  require 'yaml' -  class Config < OpenStruct -    require 'oxidized/config/defaults' -    # @param file [string] configuration file location -    def initialize file=File.join(Config::Root, 'config') -      super() -      @file = file.to_s -    end -    # load config from file or bootstrap with built-ins -    def load -      if File.exists? @file -        cfg = YAML.load_file @file -        marshal_load marshal_dump.merge(cfg) -      else -        save -      end -    end -    def defaults -      require 'oxidized/config/bootstrap' -    end -    # save config to file -    def save -      File.write @file, YAML.dump(marshal_dump) -    end -  end -  CFG = Config.new -  CFG.defaults -  CFG.load -  Log.level = Logger::INFO unless CFG.debug -  Log.file = CFG.log if CFG.log -end diff --git a/lib/oxidized/config/defaults.rb b/lib/oxidized/config/defaults.rb deleted file mode 100644 index c30143f..0000000 --- a/lib/oxidized/config/defaults.rb +++ /dev/null @@ -1,14 +0,0 @@ -module Oxidized -  class Config -    Root      = File.join ENV['HOME'], '.config', 'oxidized' -    Crash     = File.join Root, 'crash' -    InputDir  = File.join Directory, %w(lib oxidized input) -    OutputDir = File.join Directory, %w(lib oxidized output) -    ModelDir  = File.join Directory, %w(lib oxidized model) -    SourceDir = File.join Directory, %w(lib oxidized source) -    Sleep     = 1 -  end -  class << self -    attr_accessor :mgr -  end -end diff --git a/lib/oxidized/core.rb b/lib/oxidized/core.rb index 14de9ab..3c728b6 100644 --- a/lib/oxidized/core.rb +++ b/lib/oxidized/core.rb @@ -1,6 +1,6 @@  module Oxidized    require 'oxidized/log' -  require 'oxidized/config/core' +  require 'oxidized/config'    require 'oxidized/worker'    require 'oxidized/nodes'    require 'oxidized/manager' diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index dae1d74..570f8a8 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -12,14 +12,14 @@ module Oxidized          Net::SSH::AuthenticationFailed,        ],      } -    include CLI +    include Input::CLI      class NoShell < OxidizedError; end      def connect node        @node       = node        @output     = ''        @node.model.cfg['ssh'].each { |cb| instance_exec(&cb) } -      secure = CFG.input[:ssh][:secure] +      secure = CFG.input.ssh.secure        @ssh = Net::SSH.start @node.ip, @node.auth[:username],                              :password => @node.auth[:password], :timeout => CFG.timeout,                              :paranoid => secure @@ -64,14 +64,14 @@ module Oxidized      def shell_open ssh        @ses = ssh.open_channel do |ch| -        ch.on_data do |ch, data| +        ch.on_data do |_ch, data|            @output << data            @output = @node.model.expects @output          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 +        ch.request_pty 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 diff --git a/lib/oxidized/input/telnet.rb b/lib/oxidized/input/telnet.rb index 4e80ceb..218b13c 100644 --- a/lib/oxidized/input/telnet.rb +++ b/lib/oxidized/input/telnet.rb @@ -3,7 +3,7 @@ module Oxidized    require 'oxidized/input/cli'    class Telnet < Input      RescueFail = {} -    include CLI +    include Input::CLI      attr_reader :telnet      def connect node diff --git a/lib/oxidized/node.rb b/lib/oxidized/node.rb index 0cb5cb3..3ac1c90 100644 --- a/lib/oxidized/node.rb +++ b/lib/oxidized/node.rb @@ -106,7 +106,7 @@ module Oxidized      end      def resolve_input opt -      inputs = (opt[:input]  or CFG.input[:default]) +      inputs = (opt[:input]  or CFG.input.default)        inputs.split(/\s*,\s*/).map do |input|          if not Oxidized.mgr.input[input]            Oxidized.mgr.add_input input or raise MethodNotFound, "#{input} not found for node #{ip}" @@ -116,7 +116,7 @@ module Oxidized      end      def resolve_output opt -      output = (opt[:output] or CFG.output[:default]) +      output = (opt[:output] or CFG.output.default)        if not Oxidized.mgr.output[output]          Oxidized.mgr.add_output output or raise MethodNotFound, "#{output} not found for node #{ip}"        end diff --git a/lib/oxidized/nodes.rb b/lib/oxidized/nodes.rb index 8dadaef..213f534 100644 --- a/lib/oxidized/nodes.rb +++ b/lib/oxidized/nodes.rb @@ -10,7 +10,7 @@ module Oxidized        with_lock do          new = []          node_want_ip = (IPAddr.new(node_want) rescue nil) if node_want -        @source = CFG.source[:default] +        @source = CFG.source.default          Oxidized.mgr.add_source @source          Oxidized.mgr.source[@source].new.load.each do |node| diff --git a/lib/oxidized/output/file.rb b/lib/oxidized/output/file.rb index ee8a9a6..f3443b4 100644 --- a/lib/oxidized/output/file.rb +++ b/lib/oxidized/output/file.rb @@ -3,20 +3,19 @@ class OxFile < Output    require 'fileutils'    def initialize -    @cfg = CFG.output[:file] +    @cfg = CFG.output.file    end    def setup -    if not @cfg -      CFG.output[:file] = { -        :directory => File.join(Config::Root, 'configs') -      } -      CFG.save +    if @cfg.empty? +      CFGS.user.output.file.directory = File.join(Config::Root, 'configs') +      CFGS.save :user +      raise NoConfig, 'no output file config, edit ~/.config/oxidized/config'      end    end    def store node, data, opt={} -    file = @cfg[:directory] +    file = @cfg.directory      if opt[:group]        file = File.join File.dirname(file), opt[:group]      end @@ -26,7 +25,7 @@ class OxFile < Output    end    def fetch node, group -    cfg_dir = @cfg[:directory] +    cfg_dir = @cfg.directory      if group # group is explicitly defined by user        IO.readlines File.join(cfg_dir, group, node)      else diff --git a/lib/oxidized/output/git.rb b/lib/oxidized/output/git.rb index b4fa4a8..ff9237b 100644 --- a/lib/oxidized/output/git.rb +++ b/lib/oxidized/output/git.rb @@ -5,25 +5,24 @@ class Git < Output    include Grit    def initialize -    @cfg = CFG.output[:git] +    @cfg = CFG.output.git    end    def setup -    if not @cfg -      CFG.output[:git] = { -        :user  => 'Oxidized', -        :email => 'o@example.com', -        :repo  => File.join(Config::Root, 'oxidized.git') -      } -      CFG.save +    if @cfg.empty? +      CFGS.user.output.git.user  = 'Oxidized' +      CFGS.user.output.git.email = 'o@example.com' +      CFGS.user.output.git.repo  =  File.join(Config::Root, 'oxidized.git') +      CFGS.save :user +      raise NoConfig, 'no output git config, edit ~/.config/oxidized/config'      end    end    def store file, data, opt={}      msg   = opt[:msg] -    user  = (opt[:user]  or @cfg[:user]) -    email = (opt[:email] or @cfg[:email]) -    repo  = @cfg[:repo] +    user  = (opt[:user]  or @cfg.user) +    email = (opt[:email] or @cfg.email) +    repo  = @cfg.repo      if opt[:group]        repo = File.join File.dirname(repo), opt[:group] + '.git'      end @@ -41,7 +40,7 @@ class Git < Output    def fetch node, group      begin -      repo = Repo.new(@cfg[:repo]) +      repo = Repo.new(@cfg.repo)        (repo.tree / node).data      rescue        'node not found' diff --git a/lib/oxidized/output/output.rb b/lib/oxidized/output/output.rb index 61cb2b5..54d616c 100644 --- a/lib/oxidized/output/output.rb +++ b/lib/oxidized/output/output.rb @@ -1,5 +1,6 @@  module Oxidized    class Output +    class NoConfig < OxidizedError; end      class << self        def inherited klass          Oxidized.mgr.loader = { :class => klass } diff --git a/lib/oxidized/source/csv.rb b/lib/oxidized/source/csv.rb index cf73fc8..9d291c7 100644 --- a/lib/oxidized/source/csv.rb +++ b/lib/oxidized/source/csv.rb @@ -1,31 +1,28 @@  module Oxidized  class CSV < Source    def initialize -    @cfg = CFG.source[:csv] +    @cfg = CFG.source.csv      super    end    def setup -    if not @cfg -      CFG.source[:csv] = { -        :file      => File.join(Config::Root, 'router.db'), -        :delimiter => /:/, -        :map       => { -          :name  => 0, -          :model => 1, -        } -      } -      CFG.save +    if @cfg.empty? +      CFGS.user.source.csv.file      = File.join(Config::Root, 'router.db') +      CFGS.user.source.csv.delimiter = /:/ +      CFGS.user.source.csv.map.name  = 0 +      CFGS.user.source.csv.map.model = 1 +      CFGS.save :user +      raise NoConfig, 'no source csv config, edit ~/.config/oxidized/config'      end    end    def load      nodes = [] -    open(@cfg[:file]).each_line do |line| -      data  = line.chomp.split @cfg[:delimiter] +    open(@cfg.file).each_line do |line| +      data  = line.chomp.split @cfg.delimiter        keys = {} -      @cfg[:map].each do |key, position| -        keys[key] = data[position] +      @cfg.map.each do |key, position| +        keys[key.to_sym] = data[position]        end        keys[:model] = map_model keys[:model] if keys.key? :model        nodes << keys diff --git a/lib/oxidized/source/source.rb b/lib/oxidized/source/source.rb index f5976a0..93c9b6f 100644 --- a/lib/oxidized/source/source.rb +++ b/lib/oxidized/source/source.rb @@ -1,5 +1,6 @@  module Oxidized    class Source +    class NoConfig < OxidizedError; end      class << self        def inherited klass          Oxidized.mgr.loader = { :class => klass } diff --git a/lib/oxidized/source/sql.rb b/lib/oxidized/source/sql.rb index 385f632..f84a7a8 100644 --- a/lib/oxidized/source/sql.rb +++ b/lib/oxidized/source/sql.rb @@ -4,34 +4,31 @@ class SQL < Source    def initialize      super -    @cfg = CFG.source[:sql] +    @cfg = CFG.source.sql    end    def setup -    if not @cfg -      CFG.source[:sql] = { -        :adapter => 'sqlite', -        :file    => File.join(Config::Root, 'sqlite.db'), -        :table   => 'devices', -        :map     => { -          :name      => 'name', -          :model     => 'rancid', -        } -      } -      CFG.save +    if @cfg.empty? +      CFGS.user.source.sql.adapter   = 'sqlite' +      CFGS.user.source.sql.file      = File.join(Config::Root, 'sqlite.db') +      CFGS.user.source.sql.table     = 'devices' +      CFGS.user.source.sql.map.name  = 'name' +      CFGS.user.source.sql.map.model = 'rancid' +      CFGS.save :user +      raise NoConfig, 'no source sql config, edit ~/.config/oxidized/config'      end    end    def load      nodes = [] -    db = case @cfg[:adapter] +    db = case @cfg.adapter      when 'sqlite'        require 'sqlite3' -      Sequel.sqlite @cfg[:file] +      Sequel.sqlite @cfg.file      end -    db[@cfg[:table].to_sym].each do |node| +    db[@cfg.table.to_sym].each do |node|        keys = {} -      @cfg[:map].each { |key, sql_column| keys[key] = node[sql_column.to_sym] } +      @cfg.map.each { |key, sql_column| keys[key.to_sym] = node[sql_column.to_sym] }        keys[:model] = map_model keys[:model] if keys.key? :model        nodes << keys      end | 
