diff options
-rw-r--r-- | CHANGELOG.md | 15 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | Rakefile | 7 | ||||
-rw-r--r-- | extra/oxidized.supervisord | 10 | ||||
-rw-r--r-- | extra/oxidized.upstart | 18 | ||||
-rw-r--r-- | extra/syslog.rb | 17 | ||||
-rw-r--r-- | lib/oxidized/input/input.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/input/ssh.rb | 6 | ||||
-rw-r--r-- | lib/oxidized/input/telnet.rb | 6 | ||||
-rw-r--r-- | lib/oxidized/model/asa.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/eos.rb | 8 | ||||
-rw-r--r-- | lib/oxidized/model/junos.rb | 2 | ||||
-rw-r--r-- | lib/oxidized/model/powerconnect.rb | 27 | ||||
-rw-r--r-- | lib/oxidized/model/routeros.rb | 17 | ||||
-rw-r--r-- | lib/oxidized/output/file.rb | 1 | ||||
-rw-r--r-- | lib/oxidized/output/git.rb | 1 | ||||
-rw-r--r-- | oxidized.gemspec | 2 |
17 files changed, 126 insertions, 20 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1481a0b..0ed1b85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,28 @@ +# 0.5.0 +- FEATURE: Mikrotik RouterOS model (by @emjemj) +- FEATURE: add support for Cisco VSS (by @MrRJ45) +- BUGFIX: general fixes to powerconnect model (by @MrRJ45) +- BUGFIX: fix initial commit issues with rugged (by @MrRJ45) +- BUGFIX: pager error for old dell powerconnect switches (by @emjemj) +- BUGFIX: logout error for old dell powerconnect switches (by @emjemj) + +# 0.4.1 +- BUGFIX: handle missing output file (by @brandt) +- BUGFIX: fix passwordless enable on Arista EOS model (by @brandt) + # 0.4.0 - FEATURE: allow setting IP address in addition to name in source (SQL/CSV) - FEATURE: approximate how long it takes to get node from larger view than 1 - FEATURE: unconditionally start new job if too long has passed since previous start - FEATURE: add enable to Arista EOS model - FEATURE: add rugged dependency in gemspec +- FEATURE: log prompt detection failures - BUGFIX: xos while using telnet (by @fhibler) - BUGFIX: ironware logout on some models (by @fhibler) - BUGFIX: allow node to be removed while it is being collected - BUGFIX: if model returns non string value, return empty string +- BUGFIX: better prompt for Arista EOS model (by @rodecker) +- BUGFIX: improved configuration handling for Arista EOS model (by @rodecker) # 0.3.0 - FEATURE: *FIXME* bunch of stuff I did for richih, docs needed @@ -1,6 +1,8 @@ # Oxidized -Oxidized is a network device configration backup tool. Its a RANCID replacment! +[![Gem Version](https://badge.fury.io/rb/oxidized.svg)](http://badge.fury.io/rb/oxidized) + +Oxidized is a network device configuration backup tool. It's a RANCID replacment! * automatically adds/removes threads to meet configured retrieval interval * restful API to move node immediately to head-of-queue (GET/POST /node/next/[NODE]) @@ -62,6 +64,7 @@ Oxidized is a network device configration backup tool. Its a RANCID replacment! * Huawei VRP * Juniper JunOS * Juniper ScreenOS (Netscreen) + * Mikrotik RouterOS * Ubiquiti AirOS @@ -40,7 +40,12 @@ task :clean do FileUtils.rm_rf 'gems' end +desc 'Tag the release' +task :tag do + system "git tag #{gemspec.version}" +end + desc 'Push to rubygems' -task :push do +task :push => :tag do system "gem push gems/#{file}" end diff --git a/extra/oxidized.supervisord b/extra/oxidized.supervisord new file mode 100644 index 0000000..3bef7fa --- /dev/null +++ b/extra/oxidized.supervisord @@ -0,0 +1,10 @@ +# by @MrRJ45 at issues #45 + +[program:oxidized] +command=/usr/local/bin/oxidized +autostart=true +autorestart=true +user=oxidized +stderr_logfile=/var/log/oxidized.err.log +stdout_logfile=/var/log/oxidized.out.log +environment=HOME='/home/oxidized/' diff --git a/extra/oxidized.upstart b/extra/oxidized.upstart new file mode 100644 index 0000000..26a0f83 --- /dev/null +++ b/extra/oxidized.upstart @@ -0,0 +1,18 @@ +# by @andrewpwade in issue #45 + +start on started networking + +respawn + +setuid oxidized +setgid oxidized + +chdir /home/oxidized + +env HOME=/home/oxidized + +pre-start script + test -x /usr/local/bin/oxidized || { stop; exit 0; } +end script + +exec /usr/local/bin/oxidized diff --git a/extra/syslog.rb b/extra/syslog.rb index 7671d22..2af83a0 100644 --- a/extra/syslog.rb +++ b/extra/syslog.rb @@ -1,20 +1,22 @@ #!/usr/bin/env ruby # IOS: -# logging discriminator CFG mnemonics includes CONFIG_I +# logging discriminator CFG mnemonics includes CONFIG_I # logging host SERVER discriminator CFG # JunOS: # set system syslog host SERVER interactive-commands notice # set system syslog host SERVER match "^mgd\[[0-9]+\]: UI_COMMIT: .*" +# Ports < 1024 need extra privileges, use a port higher than this by passing the first argument a number +# To use the default port for syslog (514) you shouldnt pass an argument, but you will need to allow this with: # sudo setcap 'cap_net_bind_service=+ep' /usr/bin/ruby # exit if fork ## TODO: proper daemonize require 'socket' require 'resolv' -require './rest_client' +require_relative 'rest_client' module Oxidized class SyslogMonitor @@ -25,12 +27,13 @@ module Oxidized PORT = 514 FILE = 'messages' MSG = { - :ios => '%SYS-5-CONFIG_I:', + :ios => /%SYS-(SW[0-9]+-)?5-CONFIG_I:/, :junos => 'UI_COMMIT:', } class << self def udp port=PORT, listen=0 + port ||= PORT io = UDPSocket.new io.bind listen, port new io, :udp @@ -42,7 +45,7 @@ module Oxidized end end - private + private def initialize io, mode=:udp @mode = mode @@ -72,7 +75,7 @@ module Oxidized def handle_log log, ip log = log.to_s.split ' ' - if i = log.index(MSG[:ios]) + if i = log.find_index { |e| e.match( MSG[:ios] ) } ios ip, log, i elsif i = log.index(MSG[:junos]) jnpr ip, log, i @@ -86,7 +89,7 @@ module Oxidized if @mode == :udp log, ip = log.recvfrom_nonblock 2000 ip = ip.last - else + else begin log = log.read_nonblock 2000 rescue EOFError @@ -106,5 +109,5 @@ module Oxidized end end -Oxidized::SyslogMonitor.udp +Oxidized::SyslogMonitor.udp ARGV[0] #Oxidized::SyslogMonitor.file '/var/log/poop' diff --git a/lib/oxidized/input/input.rb b/lib/oxidized/input/input.rb index a7fb16d..da8ff5d 100644 --- a/lib/oxidized/input/input.rb +++ b/lib/oxidized/input/input.rb @@ -1,4 +1,5 @@ module Oxidized + class PromptUndetect < OxidizedError; end class Input include Oxidized::Config::Vars @@ -8,6 +9,7 @@ module Oxidized ], :warn => [ IOError, + PromptUndetect, Timeout::Error, Errno::ECONNRESET, Errno::EHOSTUNREACH, diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index 62a31eb..ec33d37 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -26,7 +26,11 @@ module Oxidized :paranoid => secure unless @exec shell_open @ssh - @username ? shell_login : expect(@node.prompt) + begin + @username ? shell_login : expect(@node.prompt) + rescue Timeout::Error + raise PromptUndetect, [ @output, 'not matching configured prompt', @node.prompt ].join(' ') + end end connected? end diff --git a/lib/oxidized/input/telnet.rb b/lib/oxidized/input/telnet.rb index 62f361e..13fccf7 100644 --- a/lib/oxidized/input/telnet.rb +++ b/lib/oxidized/input/telnet.rb @@ -20,7 +20,11 @@ module Oxidized @telnet.puts @node.auth[:username] expect password @telnet.puts @node.auth[:password] - expect @node.prompt + begin + expect @node.prompt + rescue Timeout::Error + raise PromptUndetect, [ 'unable to detect prompt:', @node.prompt ].join(' ') + end end def connected? diff --git a/lib/oxidized/model/asa.rb b/lib/oxidized/model/asa.rb index 8335b1d..d257e9e 100644 --- a/lib/oxidized/model/asa.rb +++ b/lib/oxidized/model/asa.rb @@ -23,7 +23,7 @@ class ASA < Oxidized::Model comment cfg end - cmd 'show running-config' do |cfg| + cmd 'more system:running-config' do |cfg| cfg = cfg.each_line.to_a[3..-1].join cfg.gsub! /^: [^\n]*\n/, '' cfg diff --git a/lib/oxidized/model/eos.rb b/lib/oxidized/model/eos.rb index 58bb5a9..84ef8cb 100644 --- a/lib/oxidized/model/eos.rb +++ b/lib/oxidized/model/eos.rb @@ -29,8 +29,11 @@ class EOS < Oxidized::Model if vars :enable post_login do send "enable\n" - expect /[pP]assword:\s?$/ - send vars(:enable) + "\n" + # Interpret enable: true as meaning we won't be prompted for a password + unless vars(:enable).is_a? TrueClass + expect /[pP]assword:\s?$/ + send vars(:enable) + "\n" + end expect /^.+[#>]\s?$/ end post_login 'terminal length 0' @@ -39,4 +42,3 @@ class EOS < Oxidized::Model end end - diff --git a/lib/oxidized/model/junos.rb b/lib/oxidized/model/junos.rb index 70f0956..e43d71a 100644 --- a/lib/oxidized/model/junos.rb +++ b/lib/oxidized/model/junos.rb @@ -9,7 +9,7 @@ class JunOS < Oxidized::Model cmd :all do |cfg| # we don't need screen-scraping in ssh due to exec cfg = cfg.lines.to_a[1..-2].join if telnet - cfg + cfg.lines.map { |line| line.rstrip }.join "\n" end cmd :secret do |cfg| diff --git a/lib/oxidized/model/powerconnect.rb b/lib/oxidized/model/powerconnect.rb index a1fe229..531ad0b 100644 --- a/lib/oxidized/model/powerconnect.rb +++ b/lib/oxidized/model/powerconnect.rb @@ -19,9 +19,8 @@ class PowerConnect < Oxidized::Model end cmd 'show system' do |cfg| - cfg = cfg.split("\n").select { |line| not line[/Up\sTime/] } - cfg = cfg[0..-28]<<" " - comment cfg.join("\n") + @model = $1 if cfg.match /Power[C|c]onnect (\d{4})[P|F]?/ + clean cfg end cmd 'show running-config' @@ -39,9 +38,31 @@ class PowerConnect < Oxidized::Model end end + post_login "terminal datadump" post_login "terminal length 0" pre_logout "logout" + pre_logout "exit" end + def clean cfg + out = [] + skip_block = false + cfg.each_line do |line| + if line.match /Up\sTime|Temperature|Power Supplies/i + # For 34xx, 54xx, 55xx, and 8024F we should skip this block (terminated by a blank line) + skip_block = true if @model =~ /^(34|35)(24|48)$|^(54|55)(24|48)$|^8024$/ + end + # If we have lines to skip do this until we reach and empty line + if skip_block + skip_block = false if /\S/ !~ line + next + end + out << line.strip + end + out = comment out.join "\n" + out << "\n" + end + + end diff --git a/lib/oxidized/model/routeros.rb b/lib/oxidized/model/routeros.rb new file mode 100644 index 0000000..bd588b7 --- /dev/null +++ b/lib/oxidized/model/routeros.rb @@ -0,0 +1,17 @@ +class RouterOS < Oxidized::Model + prompt /^\[\w+@\S+\]\s?>\s?$/ + comment "# " + + cmd '/system routerboard print' do |cfg| + comment cfg + end + + cmd '/export' do |cfg| + cfg = cfg.split("\n").select { |line| not line[/^\#\s\w{3}\/\d{2}\/\d{4}.*$/] } + cfg.join("\n") + "\n" + end + + cfg :ssh do + exec true + end +end diff --git a/lib/oxidized/output/file.rb b/lib/oxidized/output/file.rb index 03c878a..38c9917 100644 --- a/lib/oxidized/output/file.rb +++ b/lib/oxidized/output/file.rb @@ -33,6 +33,7 @@ class OxidizedFile < Output IO.readlines File.join(cfg_dir, node) else path = Dir.glob File.join(cfg_dir, '**', node) # fetch node in all groups + return nil if path[0].nil? open(path[0], 'r').readlines end end diff --git a/lib/oxidized/output/git.rb b/lib/oxidized/output/git.rb index d5eb8e7..e9256e8 100644 --- a/lib/oxidized/output/git.rb +++ b/lib/oxidized/output/git.rb @@ -99,6 +99,7 @@ class Git < Output :parents => repo.empty? ? [] : [repo.head.target].compact, :update_ref => 'HEAD', ) + index.write end end end diff --git a/oxidized.gemspec b/oxidized.gemspec index 94b7668..49343e6 100644 --- a/oxidized.gemspec +++ b/oxidized.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'oxidized' - s.version = '0.4.0' + s.version = '0.5.0' s.licenses = %w( Apache-2.0 ) s.platform = Gem::Platform::RUBY s.authors = [ 'Saku Ytti', 'Samer Abdel-Hafez' ] |