diff options
42 files changed, 403 insertions, 67 deletions
diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..ebf14b4 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.1.8 diff --git a/CHANGELOG.md b/CHANGELOG.md index b59e03d..cea6fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +# 0.14.3 +- BUGFIX: fix git when using multiple groups without single_repo + +# 0.14.2 +- BUGFIX: git expand path for all groups +- BUGFIX: git get_version, teletubbies do it again +- BUGFIX: comware, acos, procurve models + +# 0.14.1 +- BUGFIX: git get_version when groups and single_repo are used + +# 0.14.0 +- FEATURE: support supermicro swithes (by @funzoneq) +- FEATURE: support catos switches +- BUGFIX: git+groups+singlerepo (by @PANZERBARON) +- BUGFIX: asa, tmos, ironware, ios-xr +- BUGFIX: mandate net-ssh 3.0.x, don't accept 3.1 (numerous issues) + +# 0.13.1 +- BUGFIX: file permissions (Sigh...) + +# 0.13.0 +- FEATURE: http post for configs (by @jgroom33) +- FEATURE: support ericsson redbacks (by @roedie) +- FEATURE: support motorola wireless controllers (by @roadie) +- FEATURE: support citrix netscaler (by @roadie) +- FEATURE: support datacom devices (by @danilopopeye) +- FEATURE: support netonix devices +- FEATURE: support specifying ssh cipher and kex (by @roadie) +- FEATURE: rename proxy to ssh_proxy (by @roadie) +- FEATURE: support ssh keys on ssh_proxy (by @awix) +- BUGFIX: various (by @danilopopeye) +- BUGFIX: Node#repo with groups (by @danilopopeye) +- BUGFIX: githubrepohoook (by @danilopopeye) +- BUGFIX: fortios, airos, junos, xos, edgeswitch, nos, tmos, procurve, ipos models + # 0.12.2 - BUGFIX: more MRV model fixes (by @natm) @@ -12,7 +48,7 @@ - FEATURE: EdgeSwitch support (by @doogieconsulting) - BUGFIX: rename input debug log files - BUGFIX: powerconnect model fixes (by @Madpilot0) -- BUGFIX: fortigate model fixes (by @ElvinEfendi) +- BUGFIX: fortigate model fixes (by @ElvinEfendi) - BUGFIX: various (by @mikebryant) - BUGFIX: write SSH debug to file without buffering - BUGFIX: fix IOS XR prompt handling @@ -13,3 +13,6 @@ RUN apt-get -y autoremove ADD extra/oxidized.runit /etc/service/oxidized/run ADD extra/auto-reload-config.runit /etc/service/auto-reload-config/run + +VOLUME ["/root/.config/oxidized"] +EXPOSE 8888/tcp diff --git a/Gemfile.lock b/Gemfile.lock index 6be5978..1188627 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,9 @@ PATH remote: . specs: - oxidized (0.12.2) + oxidized (0.14.3) asetus (~> 0.1) - net-ssh (~> 3.0, >= 3.0.2) + net-ssh (>= 3.0.0, < 3.1) rugged (~> 0.21, >= 0.21.4) slop (~> 3.5) @@ -23,7 +23,7 @@ GEM method_source (~> 0.8.1) slop (~> 3.4) rake (10.4.2) - rugged (0.23.3) + rugged (0.24.0) slop (3.6.0) PLATFORMS @@ -38,4 +38,4 @@ DEPENDENCIES rake (~> 10.0) BUNDLED WITH - 1.11.2 + 1.12.4 @@ -67,6 +67,7 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen * Cisco * AireOS * ASA + * CatOS * IOS * IOSXR * NXOS @@ -100,22 +101,30 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen * Juniper * JunOS * ScreenOS (Netscreen) + * Mellanox + * MLNX-OS * Mikrotik * RouterOS * Motorola * RFS * MRV * MasterOS + * Netonix + * WISP Switch (As Netonix) * Opengear * Opengear * Palo Alto * PANOS + * Quanta + * Quanta / VxWorks 6.6 (1.1.0.8) * Supermicro * Supermicro * Ubiquiti * AirOS * Edgeos * EdgeSwitch + * Watchguard + * Fireware OS * Zyxel * ZyNOS @@ -125,7 +134,7 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen Install all required packages and gems. ```shell -apt-get install ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake +apt-get install ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake libssh2-1-dev gem install oxidized gem install oxidized-script oxidized-web # if you don't install oxidized-web, make sure you remove "rest" from your config ``` @@ -289,6 +298,30 @@ vars: enable: S3cre7 ``` +### Removing secrets + +To strip out secrets from configurations before storing them, Oxidized needs the the remove_secrets flag. You can globally enable this by adding the following snippet to the global sections of the configuration file. + +``` +vars: + remove_secret: true +``` + +Device models can contain substitution filters to remove potentially sensitive data from configs. + +As a partial example from ios.rb: + +``` + cmd :secret do |cfg| + cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>' + (...) + cfg + end +``` +The above strips out snmp community strings from your saved configs. + +**NOTE:** Removing secrets reduces the usefulness as a full configuration backup, but it may make sharing configs easier. + ### Source: CSV One line per device, colon seperated. @@ -401,9 +434,23 @@ output: git: user: Oxidized email: o@example.com - repo: - first: "/var/lib/oxidized/first.git" - second: "/var/lib/oxidized/second.git" + repo: "/var/lib/oxidized/git-repos/default.git" +``` + +Oxidized will create a repository for each group in the same directory as the `default.git`. For +example: + +``` csv +host1:ios:first +host2:nxos:second +``` + +This will generate the following repositories: + +``` bash +$ ls /var/lib/oxidized/git-repos + +default.git first.git second.git ``` If you would like to use groups and a single repository, you can force this with the `single_repo` config. @@ -510,6 +557,7 @@ vars: enable: S3cr3tx groups: {} rest: 127.0.0.1:8888 +pid: ~/.config/oxidized/oxidized.pid input: default: ssh, telnet debug: false diff --git a/extra/nagios_check_failing_nodes.rb b/extra/nagios_check_failing_nodes.rb index abb34ba..abb34ba 100644..100755 --- a/extra/nagios_check_failing_nodes.rb +++ b/extra/nagios_check_failing_nodes.rb diff --git a/extra/oxidized.init b/extra/oxidized.init index 197c5b1..197c5b1 100644..100755 --- a/extra/oxidized.init +++ b/extra/oxidized.init diff --git a/extra/syslog.rb b/extra/syslog.rb index e364cf9..e364cf9 100644..100755 --- a/extra/syslog.rb +++ b/extra/syslog.rb diff --git a/lib/oxidized/cli.rb b/lib/oxidized/cli.rb index 0594dcb..9a09d41 100644 --- a/lib/oxidized/cli.rb +++ b/lib/oxidized/cli.rb @@ -24,7 +24,7 @@ module Oxidized Config.load(@opts) Oxidized.setup_logger - @pidfile = File.join(Oxidized::Config::Root, 'pid') + @pidfile = File.expand_path(Oxidized.config.pid) end def crash error diff --git a/lib/oxidized/config.rb b/lib/oxidized/config.rb index 7884625..1797be6 100644 --- a/lib/oxidized/config.rb +++ b/lib/oxidized/config.rb @@ -30,6 +30,7 @@ module Oxidized asetus.default.rest = '127.0.0.1:8888' # or false to disable asetus.default.vars = {} # could be 'enable'=>'enablePW' asetus.default.groups = {} # group level configuration + asetus.default.pid = File.join(Oxidized::Config::Root, 'pid') asetus.default.input.default = 'ssh, telnet' asetus.default.input.debug = false # or String for session log file diff --git a/lib/oxidized/core.rb b/lib/oxidized/core.rb index d57c5cb..e007c9d 100644 --- a/lib/oxidized/core.rb +++ b/lib/oxidized/core.rb @@ -31,6 +31,7 @@ module Oxidized private def run + Oxidized.logger.debug "lib/oxidized/core.rb: Starting the worker..." while true @worker.work sleep Config::Sleep diff --git a/lib/oxidized/input/cli.rb b/lib/oxidized/input/cli.rb index 731b459..fc7f426 100644 --- a/lib/oxidized/input/cli.rb +++ b/lib/oxidized/input/cli.rb @@ -17,10 +17,15 @@ module Oxidized end def connect_cli - @post_login.each { |command, block| block ? block.call : (cmd command) } + Oxidized.logger.debug "lib/oxidized/input/cli.rb: Running post_login commands at #{node.name}" + @post_login.each do |command, block| + Oxidized.logger.debug "lib/oxidized/input/cli.rb: Running post_login command: #{command.inspect}, block: #{block.inspect} at #{node.name}" + block ? block.call : (cmd command) + end end def disconnect_cli + Oxidized.logger.debug "lib/oxidized/input/cli.rb Running pre_logout commands at #{node.name}" @pre_logout.each { |command, block| block ? block.call : (cmd command, nil) } end diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index fef20d6..db39a7e 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -37,6 +37,7 @@ module Oxidized ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex) ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption) + Oxidized.logger.debug "lib/oxidized/input/ssh.rb: Connecting to #{@node.name}" @ssh = Net::SSH.start(@node.ip, @node.auth[:username], ssh_opts) unless @exec shell_open @ssh @@ -54,7 +55,7 @@ module Oxidized end def cmd cmd, expect=node.prompt - Oxidized.logger.debug "SSH: #{cmd} @ #{node.name}" + Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd} @ #{node.name} with expect: #{expect.inspect}" if @exec @ssh.exec! cmd else @@ -123,6 +124,7 @@ module Oxidized end def expect regexp + Oxidized.logger.debug "lib/oxidized/input/ssh.rb: expecting #{regexp.inspect} at #{node.name}" Timeout::timeout(Oxidized.config.timeout) do @ssh.loop(0.1) do sleep 0.1 @@ -130,6 +132,5 @@ module Oxidized end end end - end end diff --git a/lib/oxidized/job.rb b/lib/oxidized/job.rb index 0a4a24b..924cd44 100644 --- a/lib/oxidized/job.rb +++ b/lib/oxidized/job.rb @@ -5,9 +5,11 @@ module Oxidized @node = node @start = Time.now.utc super do + Oxidized.logger.debug "lib/oxidized/job.rb: Starting fetching process for #{@node.name} at #{Time.now.utc}" @status, @config = @node.run @end = Time.now.utc @time = @end - @start + Oxidized.logger.debug "lib/oxidized/job.rb: Config fetched for #{@node.name} at #{@end}" end end end diff --git a/lib/oxidized/jobs.rb b/lib/oxidized/jobs.rb index 2c656f6..c566778 100644 --- a/lib/oxidized/jobs.rb +++ b/lib/oxidized/jobs.rb @@ -6,7 +6,9 @@ module Oxidized def initialize max, interval, nodes @max = max - @interval = interval + # Set interval to 1 if interval is 0 (=disabled) so we don't break + # the 'ceil' function + @interval = interval == 0 ? 1 : interval @nodes = nodes @last = Time.now.utc @durations = Array.new @nodes.size, AVERAGE_DURATION diff --git a/lib/oxidized/model/acos.rb b/lib/oxidized/model/acos.rb index 75fbacf..bb9846e 100644 --- a/lib/oxidized/model/acos.rb +++ b/lib/oxidized/model/acos.rb @@ -1,5 +1,5 @@ class ACOS < Oxidized::Model - # A10 ACOS model for AX and Thunder series + # A10 ACOS model for AX and Thunder series comment '! ' @@ -7,6 +7,14 @@ class ACOS < Oxidized::Model prompt /^([-\w.\/:?\[\]\(\)]+[#>]\s?)$/ cmd 'show version' do |cfg| + cfg.gsub! /\s(Last configuration saved at).*/, ' \\1 <removed>' + cfg.gsub! /\s(Memory).*/, ' \\1 <removed>' + cfg.gsub! /\s(Current time is).*/, ' \\1 <removed>' + cfg.gsub! /\s(The system has been up).*/, ' \\1 <removed>' + comment cfg + end + + cmd 'show bootimage' do |cfg| comment cfg end @@ -14,13 +22,22 @@ class ACOS < Oxidized::Model comment cfg end - cmd 'show running-config all-partitions' + cmd 'show running-config all-partitions' do |cfg| + cfg.gsub! /(Current configuration).*/, '\\1 <removed>' + cfg.gsub! /(Configuration last updated at).*/, '\\1 <removed>' + cfg.gsub! /(Configuration last saved at).*/, '\\1 <removed>' + cfg.gsub! /(Configuration last synchronized at).*/, '\\1 <removed>' + end + + cmd 'show aflex all-partitions' do |cfg| + comment cfg + end cmd 'show aflex all-partitions' do |cfg| @partitions_aflex = cfg.lines.each_with_object({}) do |l,h| h[$1] = [] if l.match /partition: (.+)/ # only consider scripts that have passed syntax check - h[h.keys.last] << $1 if l.match /^([\w-]+) +Check/ + h[h.keys.last] << $1 if l.match /^([\w-]+) +Check/ end '' end @@ -52,18 +69,18 @@ class ACOS < Oxidized::Model username /login:/ password /^Password:/ end - + cfg :telnet, :ssh do # preferred way to handle additional passwords - if vars :enable - post_login do - send "enable\n" - send vars(:enable) + "\n" - end + post_login do + pw = vars(:enable) + pw ||= "" + send "enable\r\n" + cmd pw end post_login 'terminal length 0' post_login 'terminal width 0' - pre_logout "exit\nexit\ny" + pre_logout "exit\nexit\nY\r\n" end end diff --git a/lib/oxidized/model/asa.rb b/lib/oxidized/model/asa.rb index 547afd7..1e45a91 100644 --- a/lib/oxidized/model/asa.rb +++ b/lib/oxidized/model/asa.rb @@ -18,7 +18,7 @@ class ASA < Oxidized::Model cmd 'show version' do |cfg| # avoid commits due to uptime / ixo-router01 up 2 mins 28 secs / ixo-router01 up 1 days 2 hours - cfg = cfg.each_line.select { |line| not line.match /\s+up\s+\d+\s+/ } + cfg = cfg.each_line.select { |line| not line.match /(\s+up\s+\d+\s+)|(.*days.*)/ } cfg = cfg.join comment cfg end @@ -30,6 +30,21 @@ class ASA < Oxidized::Model cmd 'more system:running-config' do |cfg| cfg = cfg.each_line.to_a[3..-1].join cfg.gsub! /^: [^\n]*\n/, '' + # backup any xml referenced in the configuration. + anyconnect_profiles = cfg.scan(Regexp.new('(\sdisk0:/.+\.xml)')).flatten + anyconnect_profiles.each do |profile| + cfg << (comment profile + "\n" ) + cmd ("more" + profile) do |xml| + cfg << (comment xml) + end + end + # if DAP is enabled, also backup dap.xml + if cfg.rindex(/dynamic-access-policy-record\s(?!DfltAccessPolicy)/) + cfg << (comment "disk0:/dap.xml\n") + cmd "more disk0:/dap.xml" do |xml| + cfg << (comment xml) + end + end cfg end @@ -37,7 +52,7 @@ class ASA < Oxidized::Model if vars :enable post_login do send "enable\n" - send vars(:enable) + "\n" + cmd vars(:enable) end end post_login 'terminal pager 0' diff --git a/lib/oxidized/model/catos.rb b/lib/oxidized/model/catos.rb new file mode 100644 index 0000000..874ebbc --- /dev/null +++ b/lib/oxidized/model/catos.rb @@ -0,0 +1,36 @@ +class Catos < Oxidized::Model + + prompt /^[\w.@-]+> \(enable\) $/ + comment '# ' + + cmd :all do |cfg| + cfg.each_line.to_a[1..-2].join + end + + cmd 'show system' do |cfg| + cfg = cfg.gsub /(\s+)\d+,\d+:\d+:\d+(\s+)/, '\1X\2' + comment cfg + end + + cmd 'show version' do |cfg| + cfg = cfg.gsub /\d+(K)/, 'X\1' + cfg = cfg.gsub /^(Uptime is ).*/, '\1X' + comment cfg + end + + cmd 'show conf all' do |cfg| + cfg = cfg.sub /^(#time: ).*/, '\1X' + cfg.each_line.drop_while { |line| not line.match /^begin/ }.join + end + + cfg :telnet do + username /^Username: / + password /^Password:/ + end + + cfg :ssh, :telnet do + post_login 'set length 0' + pre_logout 'exit' + end + +end diff --git a/lib/oxidized/model/comware.rb b/lib/oxidized/model/comware.rb index 9b36e8b..27b70ae 100644 --- a/lib/oxidized/model/comware.rb +++ b/lib/oxidized/model/comware.rb @@ -13,6 +13,8 @@ class Comware < Oxidized::Model cmd :all do |cfg| #cfg.gsub! /^.*\e\[42D/, '' # example how to handle pager + #skip rogue ^M + cfg = cfg.gsub /\r/, '' cfg.each_line.to_a[1..-2].join end diff --git a/lib/oxidized/model/edgeswitch.rb b/lib/oxidized/model/edgeswitch.rb index cb921b8..7c82639 100644 --- a/lib/oxidized/model/edgeswitch.rb +++ b/lib/oxidized/model/edgeswitch.rb @@ -16,9 +16,17 @@ class EdgeSwitch < Oxidized::Model end cfg :telnet, :ssh do - post_login 'enable' - post_login 'terminal length 0' + post_login do + if vars :enable + send "enable\n" + cmd vars(:enable) + else + cmd 'enable' + end + cmd 'terminal length 0' + end pre_logout 'quit' + pre_logout 'n' end end diff --git a/lib/oxidized/model/firewareos.rb b/lib/oxidized/model/firewareos.rb new file mode 100644 index 0000000..f2bef4c --- /dev/null +++ b/lib/oxidized/model/firewareos.rb @@ -0,0 +1,24 @@ +class FirewareOS < Oxidized::Model + + prompt /^\[?\w*\]?\w*<?\w*>?#\s*$/ + comment '-- ' + + cmd :all do |cfg| + cfg.each_line.to_a[1..-2].join + end + + cmd 'show sysinfo' do |cfg| + # avoid commits due to uptime + cfg = cfg.each_line.select { |line| not line.match /(.*time.*)|(.*memory.*)|(.*cpu.*)/ } + cfg = cfg.join + comment cfg + end + + cmd 'export config to console' + + cfg :ssh do + pre_logout 'exit' + end + +end + diff --git a/lib/oxidized/model/iosxr.rb b/lib/oxidized/model/iosxr.rb index a622b66..bf01140 100644 --- a/lib/oxidized/model/iosxr.rb +++ b/lib/oxidized/model/iosxr.rb @@ -30,7 +30,7 @@ class IOSXR < Oxidized::Model cfg :telnet do username /^Username:/ - password /^Password:/ + password /^\r?Password:/ end cfg :telnet, :ssh do diff --git a/lib/oxidized/model/ironware.rb b/lib/oxidized/model/ironware.rb index 55b6e57..1e8c30e 100644 --- a/lib/oxidized/model/ironware.rb +++ b/lib/oxidized/model/ironware.rb @@ -23,6 +23,7 @@ class IronWare < Oxidized::Model cmd 'show version' do |cfg| cfg.gsub! /(^((.*)[Ss]ystem uptime(.*))$)/, '' #remove unwanted line system uptime + cfg.gsub! /(^((.*)[Tt]he system started at(.*))$)/, '' cfg.gsub! /[Uu]p\s?[Tt]ime is .*/,'' comment cfg diff --git a/lib/oxidized/model/mlnxos.rb b/lib/oxidized/model/mlnxos.rb new file mode 100644 index 0000000..9542c88 --- /dev/null +++ b/lib/oxidized/model/mlnxos.rb @@ -0,0 +1,43 @@ +class MLNXOS < Oxidized::Model + + prompt /([\w.@()-\[:\s\]]+[#>]\s)$/ + comment '## ' + + # Pager Handling + expect /.+lines\s\d+\-\d+([\s]|\/\d+\s\(END\)\s).+$/ do |data, re| + send ' ' + data.sub re, '' + end + + cmd :all do |cfg| + cfg.gsub! /\[\?1h=\r/, '' # Pager Handling + cfg.gsub! /\r\[K/,'' # Pager Handling + cfg.gsub! /\s/, '' # Linebreak Handling + cfg = cfg.lines.to_a[2..-3].join + end + + cmd :secret do |cfg| + cfg.gsub! /(snmp-server community).*/, ' <snmp-server community configuration removed>' + cfg.gsub! /username (\S+) password (\d+) (\S+).*/, '<secret hidden>' + cfg + end + + cmd 'show version' do |cfg| + comment cfg + end + + cmd 'show inventory' do |cfg| + comment cfg + end + + cmd 'enable' + + cmd 'show running-config' do |cfg| + cfg + end + + cfg :ssh do + password /^Password:\s*/ + pre_logout 'exit' + end +end diff --git a/lib/oxidized/model/model.rb b/lib/oxidized/model/model.rb index 9185d43..4a15a45 100644 --- a/lib/oxidized/model/model.rb +++ b/lib/oxidized/model/model.rb @@ -35,6 +35,7 @@ module Oxidized else @cmd[:cmd] << [_cmd, block] end + Oxidized.logger.debug "lib/oxidized/model/model.rb Added #{_cmd} to the commands list" end def cmds @cmd @@ -79,6 +80,7 @@ module Oxidized attr_accessor :input, :node def cmd string, &block + Oxidized.logger.debug "lib/oxidized/model/model.rb Executing #{string}" out = @input.cmd(string) return false unless out self.class.cmds[:all].each do |all_block| @@ -127,6 +129,7 @@ module Oxidized end def get + Oxidized.logger.debug 'lib/oxidized/model/model.rb Collecting commands\' outputs' outputs = Outputs.new procs = self.class.procs self.class.cmds[:cmd].each do |command, block| diff --git a/lib/oxidized/model/mtrlrfs.rb b/lib/oxidized/model/mtrlrfs.rb index 84bcfe1..8baa4e9 100644 --- a/lib/oxidized/model/mtrlrfs.rb +++ b/lib/oxidized/model/mtrlrfs.rb @@ -1,4 +1,4 @@ -class mtrlrfs < Oxidized::Model +class Mtrlrfs < Oxidized::Model # Motorola RFS/Extreme WM diff --git a/lib/oxidized/model/netonix.rb b/lib/oxidized/model/netonix.rb new file mode 100644 index 0000000..4624f83 --- /dev/null +++ b/lib/oxidized/model/netonix.rb @@ -0,0 +1,15 @@ +class Netonix < Oxidized::Model + prompt /^[\w\s.@_\/:-]+#/ + + cmd :all do |cfg| + cfg.each_line.to_a[1..-2].join + end + + cmd 'cat config.json;echo' + + cfg :ssh do + post_login 'cmdline' + pre_logout 'exit' + pre_logout 'exit' + end +end diff --git a/lib/oxidized/model/nos.rb b/lib/oxidized/model/nos.rb index bd2cb0f..ec7c818 100644 --- a/lib/oxidized/model/nos.rb +++ b/lib/oxidized/model/nos.rb @@ -22,14 +22,14 @@ class NOS < Oxidized::Model end cmd 'show chassis' do |cfg| - comment cfg.each_line.reject { |line| line.match /Time/ }.join + comment cfg.each_line.reject { |line| line.match /Time/ or line.match /Update/ }.join end cfg 'show system' do |cfg| comment cfg.each_line.reject { |line| line.match /Time/ or line.match /speed/ } end - cmd 'show running-config' + cmd 'show running-config | nomore' cfg :telnet do username /^.* login: / diff --git a/lib/oxidized/model/panos.rb b/lib/oxidized/model/panos.rb index 35624b7..68d80c3 100644 --- a/lib/oxidized/model/panos.rb +++ b/lib/oxidized/model/panos.rb @@ -11,7 +11,14 @@ class PanOS < Oxidized::Model end cmd 'show system info' do |cfg| - cfg.gsub! /^(up)?time:\ .*\n/, '' + cfg.gsub! /^(up)?time:\ .*$/, '' + cfg.gsub! /^app-.*?:\ .*$/, '' + cfg.gsub! /^av-.*?:\ .*$/, '' + cfg.gsub! /^threat-.*?:\ .*$/, '' + cfg.gsub! /^wildfire-.*?:\ .*$/, '' + cfg.gsub! /^wf-private.*?:\ .*$/, '' + cfg.gsub! /^url-filtering.*?:\ .*$/, '' + cfg.gsub! /^global-.*?:\ .*$/, '' comment cfg end diff --git a/lib/oxidized/model/procurve.rb b/lib/oxidized/model/procurve.rb index e667f48..0dc6f8f 100644 --- a/lib/oxidized/model/procurve.rb +++ b/lib/oxidized/model/procurve.rb @@ -2,7 +2,7 @@ class Procurve < Oxidized::Model # some models start lines with \r # previous command is repeated followed by "\eE", which sometimes ends up on last line - prompt /^\r?([\w -]+\eE)?([\w-]+# )$/ + prompt /^\r?([\w -]+\eE)?([\w.-]+# )$/ comment '! ' @@ -40,7 +40,8 @@ class Procurve < Oxidized::Model # not supported on all models cmd 'show system information' do |cfg| - cfg = cfg.split("\n")[0..-8].join("\n") + cfg = cfg.each_line.select { |line| not line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/ } + cfg = cfg.join comment cfg end diff --git a/lib/oxidized/model/quantaos.rb b/lib/oxidized/model/quantaos.rb new file mode 100644 index 0000000..274440d --- /dev/null +++ b/lib/oxidized/model/quantaos.rb @@ -0,0 +1,35 @@ +class QuantaOS < Oxidized::Model + + prompt /^\((\w|\S)+\) (>|#)$/ + comment '! ' + + cmd 'show run' do |cfg| + cfg.each_line.select do |line| + not line.match /^!.*$/ and + not line.match /^\((\w|\S)+\) (>|#)$/ and + not line.match /^show run$/ + end.join + end + + cfg :telnet do + username /^Username:/ + password /^Password:/ + end + + cfg :telnet, :ssh do + post_login do + send "enable\n" + if vars :enable + cmd vars(:enable) + else + cmd "" + end + end + post_login 'terminal length 0' + pre_logout do + send "quit\n" + send "n\n" + end + end + +end diff --git a/lib/oxidized/model/tmos.rb b/lib/oxidized/model/tmos.rb index abaec9f..390046d 100644 --- a/lib/oxidized/model/tmos.rb +++ b/lib/oxidized/model/tmos.rb @@ -3,18 +3,20 @@ class TMOS < Oxidized::Model comment '# ' cmd :secret do |cfg| - cfg.gsub!(/password (\S+)/, 'password <secret removed>') - cfg.gsub!(/passphrase (\S+)/, 'passphrase <secret removed>') - cfg.gsub!(/community (\S+)/, 'community <secret removed>') - cfg.gsub!(/community-name (\S+)/, 'community-name <secret removed>') + cfg.gsub!(/^([\s\t]*)secret \S+/, '\1secret <secret removed>') + cfg.gsub!(/^([\s\t]*\S*)password \S+/, '\1password <secret removed>') + cfg.gsub!(/^([\s\t]*\S*)passphrase \S+/, '\1passphrase <secret removed>') + cfg.gsub!(/community \S+/, 'community <secret removed>') + cfg.gsub!(/community-name \S+/, 'community-name <secret removed>') + cfg.gsub!(/^([\s\t]*\S*)encrypted \S+$/, '\1encrypted <secret removed>') cfg end - cmd('tmsh show sys version') { |cfg| comment cfg } + cmd('tmsh -q show sys version') { |cfg| comment cfg } - cmd('tmsh show sys software') { |cfg| comment cfg } + cmd('tmsh -q show sys software') { |cfg| comment cfg } - cmd 'tmsh show sys hardware field-fmt' do |cfg| + cmd 'tmsh -q show sys hardware field-fmt' do |cfg| cfg.gsub!(/fan-speed (\S+)/, '') cfg.gsub!(/temperature (\S+)/, '') comment cfg diff --git a/lib/oxidized/node.rb b/lib/oxidized/node.rb index 35bcad9..cc1e406 100644 --- a/lib/oxidized/node.rb +++ b/lib/oxidized/node.rb @@ -38,9 +38,11 @@ module Oxidized next unless @model.cfg[cfg_name] and not @model.cfg[cfg_name].empty? @model.input = input = input.new if config=run_input(input) + Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} ran for #{name} successfully" status = :success break else + Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} failed for #{name}" status = :no_connection end end @@ -165,6 +167,7 @@ module Oxidized def resolve_model opt model = (opt[:model] or Oxidized.config.model) if not Oxidized.mgr.model[model] + Oxidized.logger.debug "lib/oxidized/node.rb: Loading model #{model.inspect}" Oxidized.mgr.add_model model or raise ModelNotFound, "#{model} not found for node #{ip}" end Oxidized.mgr.model[model].new diff --git a/lib/oxidized/nodes.rb b/lib/oxidized/nodes.rb index 61d2d44..cd67007 100644 --- a/lib/oxidized/nodes.rb +++ b/lib/oxidized/nodes.rb @@ -11,6 +11,7 @@ module Oxidized new = [] @source = Oxidized.config.source.default Oxidized.mgr.add_source @source + Oxidized.logger.info "lib/oxidized/nodes.rb: Loading nodes" Oxidized.mgr.source[@source].new.load.each do |node| # we want to load specific node(s), not all of them next unless node_want? node_want, node @@ -24,7 +25,7 @@ module Oxidized end end size == 0 ? replace(new) : update_nodes(new) - Oxidized.logger.info "Loaded #{size} nodes" + Oxidized.logger.info "lib/oxidized/nodes.rb: Loaded #{size} nodes" end end diff --git a/lib/oxidized/output/git.rb b/lib/oxidized/output/git.rb index 8b605f6..8d9dae1 100644 --- a/lib/oxidized/output/git.rb +++ b/lib/oxidized/output/git.rb @@ -21,7 +21,14 @@ class Git < Output Oxidized.asetus.save :user raise NoConfig, 'no output git config, edit ~/.config/oxidized/config' end - @cfg.repo = File.expand_path @cfg.repo + + if @cfg.repo.respond_to?(:each) + @cfg.repo.each do |group, repo| + @cfg.repo["#{group}="] = File.expand_path repo + end + else + @cfg.repo = File.expand_path @cfg.repo + end end def store file, outputs, opt={} @@ -70,7 +77,10 @@ class Git < Output def version node, group begin repo = @cfg.repo - if group + path = node + if group and @cfg.single_repo? + path = "#{group}/#{node}" + elsif group repo = File.join File.dirname(repo), group + '.git' end repo = Rugged::Repository.new repo @@ -80,7 +90,7 @@ class Git < Output i = -1 tab = [] walker.each do |commit| - if commit.diff(paths: [node]).size > 0 + if commit.diff(paths: [path]).size > 0 hash = {} hash[:date] = commit.time.to_s hash[:oid] = commit.oid @@ -100,8 +110,10 @@ class Git < Output def get_version node, group, oid begin repo = @cfg.repo - if group && group != '' + if group && group != '' && !@cfg.single_repo? repo = File.join File.dirname(repo), group + '.git' + elsif group && group != '' + node = File.join group, node end repo = Rugged::Repository.new repo repo.blob_at(oid,node).content @@ -115,7 +127,7 @@ class Git < Output begin repo = @cfg.repo diff_commits = nil - if group && group != '' + if group && group != '' && !@cfg.single_repo? repo = File.join File.dirname(repo), group + '.git' end repo = Rugged::Repository.new repo @@ -147,13 +159,19 @@ class Git < Output def update repo, file, data return if data.empty? + if @opt[:group] if @cfg.single_repo? file = File.join @opt[:group], file else - repo = File.join File.dirname(repo), @opt[:group] + '.git' + repo = if repo.is_a?(::String) + File.join File.dirname(repo), @opt[:group] + '.git' + else + repo[@opt[:group]] + end end end + begin repo = Rugged::Repository.new repo update_repo repo, file, data, @msg, @user, @email diff --git a/lib/oxidized/version.rb b/lib/oxidized/version.rb index c06a14a..428cd19 100644 --- a/lib/oxidized/version.rb +++ b/lib/oxidized/version.rb @@ -1,3 +1,3 @@ module Oxidized - VERSION = '0.12.2' + VERSION = '0.14.3' end diff --git a/lib/oxidized/worker.rb b/lib/oxidized/worker.rb index 324dcb5..1952d01 100644 --- a/lib/oxidized/worker.rb +++ b/lib/oxidized/worker.rb @@ -14,17 +14,21 @@ module Oxidized ended.each { |job| process job } @jobs.work while @jobs.size < @jobs.want - Oxidized.logger.debug "Jobs #{@jobs.size}, Want: #{@jobs.want}" + Oxidized.logger.debug "lib/oxidized/worker.rb: Jobs #{@jobs.size}, Want: #{@jobs.want}" # ask for next node in queue non destructive way nextnode = @nodes.first unless nextnode.last.nil? - break if nextnode.last.end + Oxidized.config.interval > Time.now.utc + # Set unobtainable value for 'last' if interval checking is disabled + last = Oxidized.config.interval == 0 ? Time.now.utc + 10 : nextnode.last.end + break if last + Oxidized.config.interval > Time.now.utc end # shift nodes and get the next node node = @nodes.get node.running? ? next : node.running = true @jobs.push Job.new node + Oxidized.logger.debug "lib/oxidized/worker.rb: Added #{node.name} to the job queue" end + Oxidized.logger.debug("lib/oxidized/worker.rb: #{@jobs.size} jobs running in parallel") unless @jobs.empty? end def process job diff --git a/oxidized.gemspec b/oxidized.gemspec index efa21db..9ff795c 100644 --- a/oxidized.gemspec +++ b/oxidized.gemspec @@ -21,11 +21,11 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.0.0' s.add_runtime_dependency 'asetus', '~> 0.1' s.add_runtime_dependency 'slop', '~> 3.5' - s.add_runtime_dependency 'net-ssh', '~> 3.0', '>= 3.0.2' - s.add_runtime_dependency 'rugged', '~> 0.21', '>= 0.21.4' - s.add_development_dependency 'pry', '~> 0' - s.add_development_dependency 'bundler', '~> 1.10' - s.add_development_dependency 'rake', '~> 10.0' + s.add_runtime_dependency 'net-ssh', '>= 3.0.0', '<3.1' + s.add_runtime_dependency 'rugged', '~> 0.21', '>= 0.21.4' + s.add_development_dependency 'pry', '~> 0' + s.add_development_dependency 'bundler', '~> 1.10' + s.add_development_dependency 'rake', '~> 10.0' s.add_development_dependency 'minitest', '~> 5.8' - s.add_development_dependency 'mocha', '~> 1.1' + s.add_development_dependency 'mocha', '~> 1.1' end diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 0a6c91b..eb9872e 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -2,23 +2,20 @@ require 'spec_helper' require 'oxidized/cli' describe Oxidized::CLI do - let(:asetus) { mock() } - - after { ARGV.replace @original } before { @original = ARGV } + after { ARGV.replace @original } %w[-v --version].each do |option| describe option do - before { ARGV.replace [option] } + before { ARGV.replace([option]) } it 'prints the version and exits' do Oxidized::Config.expects(:load) Oxidized.expects(:setup_logger) + File.expects(:expand_path) Kernel.expects(:exit) - proc { - Oxidized::CLI.new - }.must_output "#{Oxidized::VERSION}\n" + assert_output("#{Oxidized::VERSION}\n") { Oxidized::CLI.new } end end end diff --git a/spec/input/ssh_spec.rb b/spec/input/ssh_spec.rb index c4210f2..2550d5c 100644 --- a/spec/input/ssh_spec.rb +++ b/spec/input/ssh_spec.rb @@ -4,6 +4,7 @@ require 'oxidized/input/ssh' describe Oxidized::SSH do before(:each) do Oxidized.asetus = Asetus.new + Oxidized.setup_logger Oxidized::Node.any_instance.stubs(:resolve_input) Oxidized::Node.any_instance.stubs(:resolve_output) @node = Oxidized::Node.new(name: 'example.com', diff --git a/spec/node_spec.rb b/spec/node_spec.rb index 21c6e34..1c38558 100644 --- a/spec/node_spec.rb +++ b/spec/node_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe Oxidized::Node do before(:each) do - Oxidized.stubs(:asetus).returns(Asetus.new) + Oxidized.asetus = Asetus.new + Oxidized.setup_logger Oxidized::Node.any_instance.stubs(:resolve_output) @node = Oxidized::Node.new(name: 'example.com', diff --git a/spec/nodes_spec.rb b/spec/nodes_spec.rb index 5f2ef95..4560bdb 100644 --- a/spec/nodes_spec.rb +++ b/spec/nodes_spec.rb @@ -3,7 +3,9 @@ require 'spec_helper' describe Oxidized::Nodes do before(:each) do Resolv.any_instance.stubs(:getaddress) - Oxidized.stubs(:asetus).returns(Asetus.new) + Oxidized.asetus = Asetus.new + Oxidized.setup_logger + opts = { input: 'ssh', output: 'git', |