oxidized 0.33.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +4 -1
  3. data/.github/ISSUE_TEMPLATE/support-request.md +4 -1
  4. data/.github/workflows/ruby.yml +4 -2
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +29 -6
  7. data/.rubocop_todo.yml +2 -35
  8. data/CHANGELOG.md +49 -0
  9. data/CONTRIBUTING.md +10 -3
  10. data/Dockerfile +4 -4
  11. data/README.md +52 -55
  12. data/Rakefile +2 -3
  13. data/docs/Configuration.md +97 -0
  14. data/docs/DeviceSimulation.md +19 -7
  15. data/docs/Docker.md +9 -4
  16. data/docs/Issues.md +11 -2
  17. data/docs/ModelUnitTests.md +35 -25
  18. data/docs/Outputs.md +83 -2
  19. data/docs/Release.md +30 -22
  20. data/docs/Supported-OS-Types.md +4 -0
  21. data/docs/Troubleshooting.md +4 -18
  22. data/extra/device2yaml.rb +24 -9
  23. data/extra/rest_client.rb +2 -1
  24. data/extra/syslog.rb +8 -3
  25. data/lib/oxidized/cli.rb +7 -3
  26. data/lib/oxidized/config/vars.rb +7 -3
  27. data/lib/oxidized/config.rb +0 -1
  28. data/lib/oxidized/core.rb +5 -4
  29. data/lib/oxidized/hook/ciscosparkdiff.rb +11 -9
  30. data/lib/oxidized/hook/exec.rb +5 -4
  31. data/lib/oxidized/hook/githubrepo.rb +23 -17
  32. data/lib/oxidized/hook/noophook.rb +2 -2
  33. data/lib/oxidized/hook/slackdiff.rb +9 -8
  34. data/lib/oxidized/hook/xmppdiff.rb +9 -9
  35. data/lib/oxidized/hook.rb +10 -8
  36. data/lib/oxidized/input/cli.rb +8 -3
  37. data/lib/oxidized/input/exec.rb +1 -1
  38. data/lib/oxidized/input/ftp.rb +2 -2
  39. data/lib/oxidized/input/http.rb +5 -5
  40. data/lib/oxidized/input/input.rb +1 -0
  41. data/lib/oxidized/input/scp.rb +2 -2
  42. data/lib/oxidized/input/ssh.rb +21 -14
  43. data/lib/oxidized/input/telnet.rb +3 -3
  44. data/lib/oxidized/input/tftp.rb +1 -1
  45. data/lib/oxidized/job.rb +7 -4
  46. data/lib/oxidized/logger.rb +51 -0
  47. data/lib/oxidized/model/acos.rb +1 -0
  48. data/lib/oxidized/model/aos7.rb +6 -0
  49. data/lib/oxidized/model/aoscx.rb +2 -0
  50. data/lib/oxidized/model/aosw.rb +22 -17
  51. data/lib/oxidized/model/aricentiss.rb +2 -2
  52. data/lib/oxidized/model/asa.rb +3 -3
  53. data/lib/oxidized/model/awplus.rb +13 -10
  54. data/lib/oxidized/model/edgecos.rb +2 -1
  55. data/lib/oxidized/model/edgeos.rb +7 -6
  56. data/lib/oxidized/model/edgeswitch.rb +3 -1
  57. data/lib/oxidized/model/efos.rb +41 -0
  58. data/lib/oxidized/model/eltex.rb +1 -1
  59. data/lib/oxidized/model/fabricos.rb +1 -1
  60. data/lib/oxidized/model/fastiron.rb +3 -1
  61. data/lib/oxidized/model/firelinuxos.rb +12 -3
  62. data/lib/oxidized/model/fortios.rb +2 -1
  63. data/lib/oxidized/model/gaiaos.rb +4 -4
  64. data/lib/oxidized/model/ios.rb +15 -5
  65. data/lib/oxidized/model/ironware.rb +1 -1
  66. data/lib/oxidized/model/junos.rb +4 -0
  67. data/lib/oxidized/model/linksyssrw.rb +3 -3
  68. data/lib/oxidized/model/mlnxos.rb +14 -7
  69. data/lib/oxidized/model/model.rb +4 -3
  70. data/lib/oxidized/model/netgear.rb +2 -0
  71. data/lib/oxidized/model/nsxdfw.rb +2 -1
  72. data/lib/oxidized/model/nsxfirewall.rb +2 -1
  73. data/lib/oxidized/model/nxos.rb +2 -2
  74. data/lib/oxidized/model/openwrt.rb +6 -6
  75. data/lib/oxidized/model/procurve.rb +3 -1
  76. data/lib/oxidized/model/qtech.rb +3 -1
  77. data/lib/oxidized/model/quantaos.rb +8 -6
  78. data/lib/oxidized/model/routeros.rb +3 -2
  79. data/lib/oxidized/model/saos10.rb +38 -0
  80. data/lib/oxidized/model/sixwind.rb +28 -0
  81. data/lib/oxidized/model/sonicos.rb +1 -1
  82. data/lib/oxidized/model/supermicro.rb +1 -1
  83. data/lib/oxidized/model/timos.rb +1 -1
  84. data/lib/oxidized/model/tmos.rb +1 -0
  85. data/lib/oxidized/model/tnsr.rb +53 -0
  86. data/lib/oxidized/model/trango.rb +3 -1
  87. data/lib/oxidized/model/unifiap.rb +7 -5
  88. data/lib/oxidized/model/vrp.rb +3 -1
  89. data/lib/oxidized/model/xos.rb +3 -1
  90. data/lib/oxidized/model/zhoneolt.rb +3 -1
  91. data/lib/oxidized/model/zynos.rb +3 -3
  92. data/lib/oxidized/node.rb +44 -27
  93. data/lib/oxidized/nodes.rb +8 -4
  94. data/lib/oxidized/output/file.rb +28 -0
  95. data/lib/oxidized/output/git.rb +66 -9
  96. data/lib/oxidized/output/gitcrypt.rb +15 -13
  97. data/lib/oxidized/output/http.rb +5 -4
  98. data/lib/oxidized/output/output.rb +14 -0
  99. data/lib/oxidized/source/http.rb +4 -2
  100. data/lib/oxidized/version.rb +2 -2
  101. data/lib/oxidized/worker.rb +11 -8
  102. data/lib/oxidized.rb +3 -24
  103. data/oxidized.gemspec +8 -5
  104. metadata +54 -21
@@ -16,7 +16,7 @@ module Oxidized
16
16
  include Input::CLI
17
17
  class NoShell < OxidizedError; end
18
18
 
19
- def connect(node)
19
+ def connect(node) # rubocop:disable Naming/PredicateMethod
20
20
  @node = node
21
21
  @output = String.new('')
22
22
  @pty_options = { term: "vt100" }
@@ -24,10 +24,10 @@ module Oxidized
24
24
  if Oxidized.config.input.debug?
25
25
  logfile = Oxidized::Config::LOG + "/#{@node.ip}-ssh"
26
26
  @log = File.open(logfile, 'w')
27
- Oxidized.logger.debug "lib/oxidized/input/ssh.rb: I/O Debuging to #{logfile}"
27
+ logger.debug "I/O Debuging to #{logfile}"
28
28
  end
29
29
 
30
- Oxidized.logger.debug "lib/oxidized/input/ssh.rb: Connecting to #{@node.name}"
30
+ logger.debug "Connecting to #{@node.name}"
31
31
  @ssh = Net::SSH.start(@node.ip, @node.auth[:username], make_ssh_opts)
32
32
  unless @exec
33
33
  shell_open @ssh
@@ -45,9 +45,9 @@ module Oxidized
45
45
  end
46
46
 
47
47
  def cmd(cmd, expect = node.prompt)
48
- Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd.dump} @ #{node.name} with expect: #{expect.inspect}"
48
+ logger.debug "Sending '#{cmd.dump}' @ #{node.name} with expect: #{expect.inspect}"
49
49
  if Oxidized.config.input.debug?
50
- @log.puts "sent #{cmd.dump}"
50
+ @log.puts "sent cmd #{@exec ? cmd.dump : (cmd + newline).dump}"
51
51
  @log.flush
52
52
  end
53
53
  cmd_output = if @exec
@@ -60,6 +60,10 @@ module Oxidized
60
60
  end
61
61
 
62
62
  def send(data)
63
+ if Oxidized.config.input.debug?
64
+ @log.puts "sent data #{data.dump}"
65
+ @log.flush
66
+ end
63
67
  @ses.send_data data
64
68
  end
65
69
 
@@ -75,8 +79,11 @@ module Oxidized
75
79
  disconnect_cli
76
80
  # if disconnect does not disconnect us, give up after timeout
77
81
  Timeout.timeout(Oxidized.config.timeout) { @ssh.loop }
78
- rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError
79
- # These exceptions are intented and therefore not handled here
82
+ rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError => e
83
+ logger.debug 'The other side closed the connection while ' \
84
+ "disconnecting, rasing #{e.class} with #{e.messages}"
85
+ rescue Timeout::Error
86
+ logger.debug "#{@node.name} timed out while disconnecting"
80
87
  ensure
81
88
  @log.close if Oxidized.config.input.debug?
82
89
  (@ssh.close rescue true) unless @ssh.closed?
@@ -110,7 +117,7 @@ module Oxidized
110
117
 
111
118
  def cmd_shell(cmd, expect_re)
112
119
  @output = String.new('')
113
- @ses.send_data cmd + "\n"
120
+ @ses.send_data cmd + newline
114
121
  @ses.process
115
122
  expect expect_re if expect_re
116
123
  @output
@@ -118,7 +125,7 @@ module Oxidized
118
125
 
119
126
  def expect(*regexps)
120
127
  regexps = [regexps].flatten
121
- Oxidized.logger.debug "lib/oxidized/input/ssh.rb: expecting #{regexps.inspect} at #{node.name}"
128
+ logger.debug "Expecting #{regexps.inspect} at #{node.name}"
122
129
  Timeout.timeout(Oxidized.config.timeout) do
123
130
  @ssh.loop(0.1) do
124
131
  sleep 0.1
@@ -145,7 +152,7 @@ module Oxidized
145
152
 
146
153
  auth_methods = vars(:auth_methods) || %w[none publickey password]
147
154
  ssh_opts[:auth_methods] = auth_methods
148
- Oxidized.logger.debug "AUTH METHODS::#{auth_methods}"
155
+ logger.debug "AUTH METHODS::#{auth_methods}"
149
156
 
150
157
  ssh_opts[:proxy] = make_ssh_proxy_command(vars(:ssh_proxy), vars(:ssh_proxy_port), secure) if vars(:ssh_proxy)
151
158
 
@@ -155,10 +162,10 @@ module Oxidized
155
162
  ssh_opts[:host_key] = vars(:ssh_host_key).split(/,\s*/) if vars(:ssh_host_key)
156
163
  ssh_opts[:hmac] = vars(:ssh_hmac).split(/,\s*/) if vars(:ssh_hmac)
157
164
 
158
- if Oxidized.config.input.debug?
159
- ssh_opts[:logger] = Oxidized.logger
160
- ssh_opts[:verbose] = Logger::DEBUG
161
- end
165
+ # Use our logger for Net:SSH
166
+ ssh_logger = SemanticLogger[Net::SSH]
167
+ ssh_logger.level = Oxidized.config.input.debug? ? :debug : :error
168
+ ssh_opts[:logger] = ssh_logger
162
169
 
163
170
  ssh_opts
164
171
  end
@@ -6,7 +6,7 @@ module Oxidized
6
6
  include Input::CLI
7
7
  attr_reader :telnet
8
8
 
9
- def connect(node)
9
+ def connect(node) # rubocop:disable Naming/PredicateMethod
10
10
  @node = node
11
11
  @timeout = Oxidized.config.timeout
12
12
  @node.model.cfg['telnet'].each { |cb| instance_exec(&cb) }
@@ -35,7 +35,7 @@ module Oxidized
35
35
  end
36
36
 
37
37
  def cmd(cmd_str, expect = @node.prompt)
38
- Oxidized.logger.debug "Telnet: #{cmd_str} @#{@node.name}"
38
+ logger.debug "Telnet: #{cmd_str} @#{@node.name}"
39
39
  return send(cmd_str + "\r\n") unless expect
40
40
 
41
41
  # create a string to be passed to oxidized_expect and modified _there_
@@ -78,7 +78,7 @@ module Net
78
78
  ## FIXME: we also need output (not sure I'm going to support this)
79
79
  attr_reader :output
80
80
 
81
- def oxidized_expect(options) ## rubocop:disable Metrics/PerceivedComplexity
81
+ def oxidized_expect(options)
82
82
  model = @options["Model"]
83
83
  @log = @options["Log"]
84
84
 
@@ -21,7 +21,7 @@ module Oxidized
21
21
  end
22
22
 
23
23
  def cmd(file)
24
- Oxidized.logger.debug "TFTP: #{file} @ #{@node.name}"
24
+ logger.debug "TFTP: #{file} @ #{@node.name}"
25
25
  config = StringIO.new
26
26
  @tftp.getbinary file, config
27
27
  config.rewind
data/lib/oxidized/job.rb CHANGED
@@ -1,16 +1,19 @@
1
1
  module Oxidized
2
2
  class Job < Thread
3
+ include SemanticLogger::Loggable
4
+
3
5
  attr_reader :start, :end, :status, :time, :node, :config
4
6
 
5
7
  def initialize(node)
6
- @node = node
7
- @start = Time.now.utc
8
+ @node = node
9
+ @start = Time.now.utc
10
+ self.name = "Oxidized::Job '#{@node.name}'"
8
11
  super do
9
- Oxidized.logger.debug "lib/oxidized/job.rb: Starting fetching process for #{@node.name} at #{Time.now.utc}"
12
+ logger.debug "Starting fetching process for #{@node.name} at #{Time.now.utc}"
10
13
  @status, @config = @node.run
11
14
  @end = Time.now.utc
12
15
  @time = @end - @start
13
- Oxidized.logger.debug "lib/oxidized/job.rb: Config fetched for #{@node.name} at #{@end}"
16
+ logger.debug "Config fetched for #{@node.name} at #{@end}"
14
17
  end
15
18
  end
16
19
  end
@@ -0,0 +1,51 @@
1
+ require 'semantic_logger'
2
+
3
+ module Oxidized
4
+ module Logger
5
+ include SemanticLogger::Loggable
6
+
7
+ def self.setup
8
+ config = Oxidized.config
9
+ FileUtils.mkdir_p(Config::LOG) unless File.directory?(Config::LOG)
10
+
11
+ SemanticLogger.add_signal_handler
12
+
13
+ if config.use_syslog?
14
+ SemanticLogger.add_appender(appender: :syslog)
15
+ logger.warn("The configuration 'use_syslog' is deprecated. " \
16
+ "Remove it and use 'logger' instead")
17
+ elsif config.log?
18
+ SemanticLogger.add_appender(file_name: File.expand_path(config.log))
19
+ logger.warn("The configuration 'log' is deprecated. " \
20
+ "Remove it and use 'logger' instead")
21
+ elsif config.logger?
22
+ SemanticLogger.default_level = config.logger.level if config.logger.level?
23
+ config.logger.appenders.each { |a| add_appender a } if config.logger.has_key?('appenders')
24
+ end
25
+
26
+ # No appenders configured
27
+ SemanticLogger.add_appender(io: $stderr) if SemanticLogger.appenders.empty?
28
+
29
+ return if %i[trace debug].include?(SemanticLogger.default_level)
30
+
31
+ SemanticLogger.default_level = :debug if config.debug?
32
+ end
33
+
34
+ def self.add_appender(appender)
35
+ case appender['type']
36
+ when 'file'
37
+ params = { file_name: File.expand_path(appender['file']) }
38
+ when 'stderr'
39
+ params = { io: $stderr }
40
+ when 'stdout'
41
+ params = { io: $stdout }
42
+ when 'syslog'
43
+ params = { appender: :syslog, application: "oxidized" }
44
+ else
45
+ raise InvalidConfig, "Unknown logger #{appender['type']}, edit #{Oxidized::Config.configfile}"
46
+ end
47
+ params[:level] = appender['level'] if appender.has_key?('level')
48
+ SemanticLogger.add_appender(**params)
49
+ end
50
+ end
51
+ end
@@ -20,6 +20,7 @@ class ACOS < Oxidized::Model
20
20
  cfg.gsub! /\s(Memory).*/, ' \\1 <removed>'
21
21
  cfg.gsub! /\s(Current time is).*/, ' \\1 <removed>'
22
22
  cfg.gsub! /\s(The system has been up).*/, ' \\1 <removed>'
23
+ cfg.gsub! /\s(Hardware: \d+ CPUs\(Stepping \d+\). Single \d+G drive. Free storage is).*/, ' \\1 <removed>'
23
24
  comment cfg
24
25
  end
25
26
 
@@ -33,10 +33,16 @@ class AOS7 < Oxidized::Model
33
33
  end
34
34
 
35
35
  cmd 'show running-directory' do |cfg|
36
+ # Remove extra lines occuring when the command runs slow
37
+ cfg.gsub! /^Please wait...\n/, ''
38
+ cfg.gsub! /^\n\n/, "\n"
36
39
  comment cfg
37
40
  end
38
41
 
39
42
  cmd 'show configuration snapshot' do |cfg|
43
+ # Remove extra lines occuring when the command runs slow
44
+ cfg.gsub! /^Please wait...\n/, ''
45
+ cfg.gsub! /^\n\n/, "\n"
40
46
  cfg
41
47
  end
42
48
 
@@ -58,6 +58,8 @@ class Aoscx < Oxidized::Model
58
58
  cfg.gsub! /^(\d\/\d\/\d.*\s+)\d+\s+$/, '\\1<hidden>'
59
59
  cfg.gsub! /^(\d+\/?\S+\s+\S+\s+)\d+\.\d+\s+C\s+(.*)/, '\\1<hidden> \\2'
60
60
  cfg.gsub! /^(LC.*\s+)\d+\.\d+\s+(C.*)$/, '\\1 <hidden> \\2'
61
+ # match show environment No speed shown for switches CX83xx, e.g. "PSU-1/1/1 N/A N/A N/A front-to-back ok 7360"
62
+ cfg.gsub! /^PSU(\S+\s+\S+\s+\s+\S+\s+)(slow|normal|medium|fast|max|N\/A)\s+(\S+\s+\S+\s+)\d+[[:blank:]]+/, '\\1<speed> \\3<rpm>'
61
63
  cfg.gsub! /^(\S+\s+\S+\s+\s+\S+\s+)(slow|normal|medium|fast|max)\s+(\S+\s+\S+\s+)\d+[[:blank:]]+/, '\\1<speed> \\3<rpm>'
62
64
  # match show environment power-consumption on VSF or standadlone, non-chassis and non-6400 switch, e.g. "2 6300M 48G 4SFP56 Swch 156.00 155.94"
63
65
  cfg.gsub! /^(\d+\s+.+\s+)(\s{2}\d{2}\.\d{2}|\s{1}\d{3}\.\d{2}|\d{4}\.\d{2})(\s+)(\s{2}\d{2}\.\d{2}|\s{1}\d{3}\.\d{2}|\d{4}\.\d{2})$/, '\\1<power>\\3<power>'
@@ -25,24 +25,25 @@ class AOSW < Oxidized::Model
25
25
  end
26
26
 
27
27
  cmd :secret do |cfg|
28
- cfg.gsub!(/secret (\S+)$/, 'secret <secret removed>')
29
- cfg.gsub!(/enable secret (\S+)$/, 'enable secret <secret removed>')
30
- cfg.gsub!(/PRE-SHARE (\S+)$/, 'PRE-SHARE <secret removed>')
31
- cfg.gsub!(/ipsec (\S+)$/, 'ipsec <secret removed>')
32
- cfg.gsub!(/community (\S+)$/, 'community <secret removed>')
28
+ cfg.gsub!(/secret (\S+)\s?$/, 'secret <secret removed>')
29
+ cfg.gsub!(/enable secret (\S+)\s?$/, 'enable secret <secret removed>')
30
+ cfg.gsub!(/PRE-SHARE (\S+)\s?$/, 'PRE-SHARE <secret removed>')
31
+ cfg.gsub!(/ipsec (\S+)\s?$/, 'ipsec <secret removed>')
32
+ cfg.gsub!(/community (\S+)\s?$/, 'community <secret removed>')
33
33
  cfg.gsub!(/ sha (\S+)/, ' sha <secret removed>')
34
34
  cfg.gsub!(/ des (\S+)/, ' des <secret removed>')
35
35
  cfg.gsub!(/mobility-manager (\S+) user (\S+) (\S+)/, 'mobility-manager \1 user \2 <secret removed>')
36
- cfg.gsub!(/mgmt-user (\S+) (root|guest-provisioning|network-operations|read-only|location-api-mgmt) (\S+)$/, 'mgmt-user \1 \2 <secret removed>') # MAS & Wireless Controler
37
- cfg.gsub!(/mgmt-user (\S+) (\S+)( (read-only|guest-mgmt))?$/, 'mgmt-user \1 <secret removed> \3') # IAP
36
+ cfg.gsub!(/mgmt-user (\S+) (root|guest-provisioning|network-operations|read-only|location-api-mgmt) (\S+)\s?$/, 'mgmt-user \1 \2 <secret removed>') # MAS & Wireless Controler
37
+ cfg.gsub!(/mgmt-user (\S+) (\S+)( (read-only|guest-mgmt))?\s?$/, 'mgmt-user \1 <secret removed> \3') # IAP
38
38
  # MAS format: mgmt-user <username> <accesslevel> <password hash>
39
39
  # IAP format (root user): mgmt-user <username> <password hash>
40
40
  # IAP format: mgmt-user <username> <password hash> <access level>
41
- cfg.gsub!(/key (\S+)$/, 'key <secret removed>')
42
- cfg.gsub!(/wpa-passphrase (\S+)$/, 'wpa-passphrase <secret removed>')
43
- cfg.gsub!(/bkup-passwords (\S+)$/, 'bkup-passwords <secret removed>')
44
- cfg.gsub!(/user (\S+) (\S+) (\S+)$/, 'user \1 <secret removed> \3')
45
- cfg.gsub!(/virtual-controller-key (\S+)$/, 'virtual-controller-key <secret removed>')
41
+ cfg.gsub!(/key (\S+)\s?$/, 'key <secret removed>')
42
+ cfg.gsub!(/vrrp-passphrase (\S+)\s?$/, 'vrrp-passphrase <secret removed>')
43
+ cfg.gsub!(/wpa-passphrase (\S+)\s?$/, 'wpa-passphrase <secret removed>')
44
+ cfg.gsub!(/bkup-passwords (\S+)\s?$/, 'bkup-passwords <secret removed>')
45
+ cfg.gsub!(/ap-console-password (\S+)\s?$/, 'ap-console-password <secret removed>')
46
+ cfg.gsub!(/virtual-controller-key (\S+)\s?$/, 'virtual-controller-key <secret removed>')
46
47
  cfg
47
48
  end
48
49
 
@@ -52,22 +53,26 @@ class AOSW < Oxidized::Model
52
53
  end
53
54
 
54
55
  cmd 'show inventory' do |cfg|
55
- cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
56
+ # Don't show for unsupported devices (IAP and MAS)
57
+ cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/
56
58
  rstrip_cfg clean cfg
57
59
  end
58
60
 
59
61
  cmd 'show slots' do |cfg|
60
- cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
62
+ # Don't show for unsupported devices (IAP and MAS)
63
+ cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/
61
64
  rstrip_cfg comment cfg
62
65
  end
63
66
 
64
67
  cmd 'show license' do |cfg|
65
- cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
68
+ # Don't show for unsupported devices (IAP and MAS)
69
+ cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/
66
70
  rstrip_cfg comment cfg
67
71
  end
68
72
 
69
73
  cmd 'show license passphrase' do |cfg|
70
- cfg = "" if cfg.match /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
74
+ # Don't show for unsupported devices (IAP and MAS)
75
+ cfg = "" if cfg.match /(Invalid input detected at '\^' marker|Parse error)/
71
76
  rstrip_cfg comment cfg
72
77
  end
73
78
 
@@ -117,7 +122,7 @@ class AOSW < Oxidized::Model
117
122
  next if line =~ /Output \d Config/i
118
123
  next if line =~ /(Tachometers|Temperatures|Voltages)/
119
124
  next if line =~ /((Card|CPU) Temperature|Chassis Fan|VMON1[0-9])/
120
- next if line =~ /[0-9]+\s+(RPMS?|m?V|C|W)/i
125
+ next if line =~ /[0-9.]{1,6}\s+(RPMS?|m?V|C|W)/i
121
126
 
122
127
  out << line.strip
123
128
  end
@@ -37,7 +37,7 @@ class AricentISS < Oxidized::Model
37
37
  cmd 'show system information' do |cfg|
38
38
  cfg.sub! /^Device Up Time.*\n/, ''
39
39
  cfg.delete! "\r"
40
- comment(cfg).gsub(/ +$/, '')
40
+ comment(cfg).rstrip
41
41
  end
42
42
 
43
43
  cmd 'show running-config' do |cfg|
@@ -53,6 +53,6 @@ class AricentISS < Oxidized::Model
53
53
  end
54
54
 
55
55
  l
56
- end.join.gsub(/ +$/, '')
56
+ end.join.rstrip
57
57
  end
58
58
  end
@@ -16,8 +16,7 @@ class ASA < Oxidized::Model
16
16
  cfg.gsub! /^passwd (\S+) (.*)/, 'passwd <secret hidden> \2'
17
17
  cfg.gsub! /username (\S+) password (\S+) (.*)/, 'username \1 password <secret hidden> \3'
18
18
  cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key( hex)?) (\S+)/, '\1 <secret hidden>'
19
- cfg.gsub! /^(aaa-server TACACS\+? \(\S+\) host[^\n]*\n(\s+[^\n]+\n)*\skey) \S+$/mi, '\1 <secret hidden>'
20
- cfg.gsub! /^(aaa-server \S+ \(\S+\) host[^\n]*\n(\s+[^\n]+\n)*\s+key) \S+$/mi, '\1 <secret hidden>'
19
+ cfg.gsub! /^(aaa-server \S+(?: \(\S+\))? host \S+\n(?: [^\n]+\n)* +key) \S+$/mi, '\1 <secret hidden>'
21
20
  cfg.gsub! /ldap-login-password (\S+)/, 'ldap-login-password <secret hidden>'
22
21
  cfg.gsub! /^snmp-server host (.*) community (\S+)/, 'snmp-server host \1 community <secret hidden>'
23
22
  cfg.gsub! /^(failover key) .+/, '\1 <secret hidden>'
@@ -97,7 +96,8 @@ class ASA < Oxidized::Model
97
96
  contexts = systemcfg.scan(/^context (\S+)$/)
98
97
  files = systemcfg.scan(/config-url (\S+)$/)
99
98
  contexts.each_with_index do |cont, i|
100
- allcfg = allcfg + "\n\n----------========== [ CONTEXT " + cont.join(" ") + " FILE " + files[i].join(" ") + " ] ==========----------\n\n"
99
+ allcfg = allcfg + "\n\n----------========== [ CONTEXT " + cont.join(" ") +
100
+ " FILE " + files[i].join(" ") + " ] ==========----------\n\n"
101
101
  cmd "more " + files[i].join(" ") do |cfgcontext|
102
102
  allcfg = allcfg + "\n\n" + cfgcontext
103
103
  end
@@ -61,25 +61,28 @@ class AWPlus < Oxidized::Model
61
61
  cfg
62
62
  end
63
63
 
64
- # Config required for telnet to detect username prompt
64
+ # Config required for telnet to detect username & password prompt.
65
65
  cfg :telnet do
66
66
  username /login:\s/
67
+ password /^Password:\s/
67
68
  end
68
69
 
69
- # Main login config
70
+ # Config required for ssh to specify newline characters.
70
71
  cfg :telnet, :ssh do
72
+ newline "\r\n"
73
+
71
74
  post_login do
72
- if vars :enable
73
- send "enable\n"
74
- expect /^Password:\s/
75
- cmd vars(:enable) + "\r\n"
76
- else
77
- cmd 'enable' # Required for Priv-Exec users without enable PW to be put into "enable mode".
75
+ if vars(:enable) == true
76
+ cmd "enable"
77
+ elsif vars(:enable)
78
+ cmd "enable", /^[pP]assword:/
79
+ cmd vars(:enable)
78
80
  end
79
- # cmd 'terminal length 0' #set so the entire config is output without intervention.
81
+ # cmd 'terminal length 0' # set so the entire config is output without intervention.
80
82
  end
83
+
81
84
  pre_logout do
82
- # cmd 'terminal no length' #Sets term length back to default on exit.
85
+ # cmd 'terminal no length' # sets term length back to default on exit.
83
86
  send "exit\r\n"
84
87
  end
85
88
  end
@@ -32,7 +32,8 @@ class EdgeCOS < Oxidized::Model
32
32
  cmd 'show system' do |cfg|
33
33
  cfg.gsub! /^.*\sUp Time\s*:.*\n/i, ''
34
34
  cfg.gsub! /(\sTemperature \d*:)\s*\d+ degrees/, '\\1 <temperature values hidden>'
35
- cfg.gsub! /^!?\s*Fan \d+ speed:\s+\d+ rpm\s+Fan \d+ speed:\s+\d+ rpm\s+Fan \d+ speed:\s+\d+ rpm$/, '<fan speeds hidden>'
35
+ cfg.gsub! /^!?\s*Fan \d+ speed:\s+\d+ rpm\s+Fan \d+ speed:\s+\d+ rpm\s+Fan \d+ speed:\s+\d+ rpm$/,
36
+ '<fan speeds hidden>'
36
37
  comment cfg
37
38
  end
38
39
 
@@ -1,7 +1,7 @@
1
1
  class Edgeos < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- # EdgeOS #
4
+ # Ubiquiti EdgeOS #
5
5
 
6
6
  prompt /@.*?:~\$\s/
7
7
 
@@ -10,11 +10,12 @@ class Edgeos < Oxidized::Model
10
10
  end
11
11
 
12
12
  cmd :secret do |cfg|
13
- cfg.gsub! /encrypted-password (\S+).*/, 'encrypted-password <secret removed>'
14
- cfg.gsub! /plaintext-password (\S+).*/, 'plaintext-password <secret removed>'
15
- cfg.gsub! /password (\S+).*/, 'password <secret removed>'
16
- cfg.gsub! /pre-shared-secret (\S+).*/, 'pre-shared-secret <secret removed>'
17
- cfg.gsub! /community (\S+) {/, 'community <hidden> {'
13
+ cfg.gsub!(/(encrypted-password) \S+/, '\1 <secret removed>')
14
+ cfg.gsub!(/(plaintext-password) \S+/, '\1 <secret removed>')
15
+ cfg.gsub!(/(password) \S+/, '\1 <secret removed>')
16
+ cfg.gsub!(/(pre-shared-secret) \S+/, '\1 <secret removed>')
17
+ cfg.gsub!(/(community) \S+ {/, '\1 <hidden> {')
18
+ cfg.gsub!(/(commit-archive location) \S+/, '\1 <secret removed>')
18
19
  cfg
19
20
  end
20
21
 
@@ -8,7 +8,9 @@ class EdgeSwitch < Oxidized::Model
8
8
  prompt /\(.*\)\s[#>]/
9
9
 
10
10
  cmd 'show running-config' do |cfg|
11
- cfg.each_line.to_a[2..-2].reject { |line| line.match(/System Up Time.*/) || line.match(/Current SNTP Synchronized Time.*/) }.join
11
+ cfg.each_line.to_a[2..-2].reject do |line|
12
+ line.match(/System Up Time.*/) || line.match(/Current SNTP Synchronized Time.*/)
13
+ end.join
12
14
  end
13
15
 
14
16
  cfg :telnet do
@@ -0,0 +1,41 @@
1
+ class EFOS < Oxidized::Model
2
+ using Refinements
3
+
4
+ # Enhanced Fabric OS - Broadcom
5
+ comment '! '
6
+ prompt /^([\w.@()-]+[#>]\s?)$/
7
+
8
+ cmd :all do |cfg|
9
+ # Remove the echo of the entered command and the prompt after it
10
+ cfg.cut_both
11
+ end
12
+
13
+ cmd 'show bootvar' do |cfg|
14
+ comment cfg
15
+ end
16
+
17
+ cmd 'show fiber-ports optical-transceiver-info all' do |cfg|
18
+ comment cfg
19
+ end
20
+
21
+ cmd 'show running-config' do |cfg|
22
+ cfg.each_line
23
+ .reject { |line| line.match(/System Up Time/) }
24
+ .reject { |line| line.match(/Current System Time:/) }
25
+ .reject { |line| line.match(/Current SNTP Synchronized Time:/) }
26
+ .join
27
+ end
28
+
29
+ cfg :telnet, :ssh do
30
+ post_login do
31
+ if vars(:enable) == true
32
+ cmd 'enable'
33
+ elsif vars(:enable)
34
+ cmd 'enable', /^[pP]assword:/
35
+ cmd vars(:enable)
36
+ end
37
+ end
38
+ post_login 'terminal length 0'
39
+ pre_logout 'logout'
40
+ end
41
+ end
@@ -16,7 +16,7 @@ class Eltex < Oxidized::Model
16
16
  cfg.gsub! /^(enable (password|secret)( level \d+)? \d) .+/, '\\1 <secret hidden>'
17
17
  cfg.gsub! /^(\s+(?:password|secret)) (?:\d )?\S+/, '\\1 <secret hidden>'
18
18
  cfg.gsub! /^(tacacs-server (.+ )?key) .+/, '\\1 <secret hidden>'
19
- cfg.gsub! /^((tacacs|radius) server [^\n]+\n(\s+[^\n]+\n)*\s+key) [^\n]+$/m, '\1 <secret hidden>'
19
+ cfg.gsub! /^((tacacs|radius) server [^\n]+\n( +[^\n]+\n)*\s+key) [^\n]+$/m, '\1 <secret hidden>'
20
20
  cfg.gsub! /username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
21
21
  cfg.gsub! /^username \S+ password \d \S+/, '<secret hidden>'
22
22
  cfg.gsub! /^enable password \d \S+/, '<secret hidden>'
@@ -8,7 +8,7 @@ class FabricOS < Oxidized::Model
8
8
  comment '# '
9
9
 
10
10
  cmd 'chassisShow' do |cfg|
11
- comment cfg.each_line.reject { |line| line.match(/Time Awake:/) || line.match(/Power Usage \(Watts\):/) || line.match(/Power Usage:/) || line.match(/Time Alive:/) || line.match(/Update:/) }.join
11
+ comment cfg.each_line.reject { |line| line.match(/Time Awake:/) || line.match(/Power Usage \(Watts\):/) || line.match(/Power Usage:/) || line.match(/Time Alive:/) || line.match(/Update:/) || line.match(/PS Voltage input:/) }.join
12
12
  end
13
13
 
14
14
  cmd 'configShow -all' do |cfg|
@@ -19,7 +19,9 @@ class FastIron < Oxidized::Model
19
19
  lines.each_with_index do |line, _i|
20
20
  comments << "Version: #{Regexp.last_match(1)}" if line =~ /^\s+SW: Version (.*)$/
21
21
 
22
- comments << "Boot-Monitor Version: #{Regexp.last_match(1)}" if line =~ /^\s+Compressed Boot-Monitor Image size = \d+, Version:(.*)$/
22
+ if line =~ /^\s+Compressed Boot-Monitor Image size = \d+, Version:(.*)$/
23
+ comments << "Boot-Monitor Version: #{Regexp.last_match(1)}"
24
+ end
23
25
 
24
26
  comments << "Serial: #{Regexp.last_match(1)}" if line =~ /^\s+Serial #:(.*)$/
25
27
  end
@@ -3,12 +3,21 @@ class FireLinuxOS < Oxidized::Model
3
3
 
4
4
  # Fire Linux OS is what the new FTD (FirePOWER) series devices from Cisco run. At the backend, it's mostly identical to ASA's.
5
5
 
6
- prompt /^[#>]\(?.+\)?\s?/
7
- comment '! '
6
+ prompt /^[#>]\(?.+\)? ?$/
7
+ comment '! '
8
+
9
+ expect /^Syntax error: .*\n.*$/ do |data, re|
10
+ # The firepower does not remove the entered command, so
11
+ # Send CTRL-U and \n for a fresh prompt
12
+ send "\x15\n"
13
+ data.sub re, ''
14
+ end
8
15
 
9
16
  cmd :all do |cfg|
10
17
  cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
11
- cfg.each_line.to_a[1..-2].join
18
+ # Ged rid of ANSI escape codes
19
+ cfg.gsub! /\e\[[0-?]*[ -\/]*[@-~]\r?/, ''
20
+ cfg.cut_both
12
21
  end
13
22
 
14
23
  cmd :secret do |cfg|
@@ -96,7 +96,8 @@ class FortiOS < Oxidized::Model
96
96
 
97
97
  commandlist.each do |fullcmd|
98
98
  fullcfg = cmd(fullcmd)
99
- next if fullcfg.lines[1..3].join =~ /(Parsing error at|command parse error)/ # Don't show for unsupported devices (e.g. FortiAnalyzer, FortiManager, FortiMail)
99
+ # Don't show for unsupported devices (e.g. FortiAnalyzer, FortiManager, FortiMail)
100
+ next if fullcfg.lines[1..3].join =~ /(Parsing error at|command parse error)/
100
101
 
101
102
  fullcfg.gsub! /(set comments "Error \(No order (found )?for (account )?ID \d+\) on).*/, '\\1 <stripped>"'
102
103
 
@@ -26,7 +26,7 @@ class GaiaOS < Oxidized::Model
26
26
  # check for vsx / multiple context
27
27
  cmd 'show vsx' do |cfg|
28
28
  @is_vsx = cfg.include? 'VSX Enabled'
29
- Oxidized.logger.debug cfg
29
+ logger.debug cfg
30
30
  end
31
31
 
32
32
  cmd 'show asset all' do |cfg|
@@ -46,7 +46,7 @@ class GaiaOS < Oxidized::Model
46
46
  end
47
47
 
48
48
  def single_context
49
- Oxidized.logger.debug 'Single context tasks'
49
+ logger.debug 'Single context tasks'
50
50
  cmd 'show configuration' do |cfg|
51
51
  cfg.gsub! /^# Exported by \S+ on .*/, '# '
52
52
  cfg
@@ -54,7 +54,7 @@ class GaiaOS < Oxidized::Model
54
54
  end
55
55
 
56
56
  def multiple_context
57
- Oxidized.logger.debug 'Multi context tasks'
57
+ logger.debug 'Multi context tasks'
58
58
  cmd 'show virtual-system all' do |systems|
59
59
  vs_items = systems.scan(/^(?<VSID>\d+)\s+(?<VSNAME>.*[^\s])/)
60
60
  allcfg = ''
@@ -62,7 +62,7 @@ class GaiaOS < Oxidized::Model
62
62
  allcfg += "\n\n\n#--------======== [ VS #{item[0]} - #{item[1]} ] ========--------\n\n"
63
63
  allcfg += "set virtual-system #{item[0]}\n\n"
64
64
  cmd "set virtual-system #{item[0]}" do |vs|
65
- Oxidized.logger.debug vs
65
+ logger.debug vs
66
66
  cmd 'show configuration' do |vscfg|
67
67
  vscfg.gsub! /^# Exported by \S+ on .*/, '# '
68
68
  allcfg += vscfg
@@ -69,17 +69,25 @@ class IOS < Oxidized::Model
69
69
 
70
70
  comments << "Image:#{slave} Compiled: #{Regexp.last_match(1)}" if line =~ /^Compiled (.*)$/
71
71
 
72
- comments << "Image:#{slave} Software: #{Regexp.last_match(1)}, #{Regexp.last_match(2)}" if line =~ /^(?:Cisco )?IOS .* Software,? \(([A-Za-z0-9_-]*)\), .*Version\s+(.*)$/
72
+ if line =~ /^(?:Cisco )?IOS .* Software,? \(([A-Za-z0-9_-]*)\), .*Version\s+(.*)$/
73
+ comments << "Image:#{slave} Software: #{Regexp.last_match(1)}, #{Regexp.last_match(2)}"
74
+ end
73
75
 
74
- comments << "ROM Bootstrap: #{Regexp.last_match(3)}" if line =~ /^ROM: (IOS \S+ )?(System )?Bootstrap.*(Version.*)$/
76
+ if line =~ /^ROM: (IOS \S+ )?(System )?Bootstrap.*(Version.*)$/
77
+ comments << "ROM Bootstrap: #{Regexp.last_match(3)}"
78
+ end
75
79
 
76
80
  comments << "BOOTFLASH: #{Regexp.last_match(1)}" if line =~ /^BOOTFLASH: .*(Version.*)$/
77
81
 
78
82
  comments << "Memory: nvram #{Regexp.last_match(1)}" if line =~ /^(\d+[kK]) bytes of (non-volatile|NVRAM)/
79
83
 
80
- comments << "Memory: flash #{Regexp.last_match(1)}" if line =~ /^(\d+[kK]) bytes of (flash memory|flash internal|processor board System flash|ATA CompactFlash)/i
84
+ if line =~ /^(\d+[kK]) bytes of (flash memory|flash internal|processor board System flash|ATA CompactFlash)/i
85
+ comments << "Memory: flash #{Regexp.last_match(1)}"
86
+ end
81
87
 
82
- comments << "Memory: pcmcia #{Regexp.last_match(2)} #{Regexp.last_match(3)}#{Regexp.last_match(4)} #{Regexp.last_match(1)}" if line =~ /^(\d+[kK]) bytes of (Flash|ATA)?.*PCMCIA .*(slot|disk) ?(\d)/i
88
+ if line =~ /^(\d+[kK]) bytes of (Flash|ATA)?.*PCMCIA .*(slot|disk) ?(\d)/i
89
+ comments << "Memory: pcmcia #{Regexp.last_match(2)} #{Regexp.last_match(3)}#{Regexp.last_match(4)} #{Regexp.last_match(1)}"
90
+ end
83
91
 
84
92
  if line =~ /(\S+(?:\sseries)?)\s+(?:\(([\S ]+)\)\s+processor|\(revision[^)]+\)).*\s+with (\S+k) bytes/i
85
93
  sproc = Regexp.last_match(1)
@@ -120,7 +128,9 @@ class IOS < Oxidized::Model
120
128
  cmd cmd_line do |cfg|
121
129
  cfg = cfg.each_line.to_a[3..-1]
122
130
  cfg = cfg.reject { |line| line.match /^ntp clock-period / }.join
123
- cfg = cfg.each_line.reject { |line| line.match /^! (Last|No) configuration change (at|since).*/ unless line =~ /\d+\sby\s\S+$/ }.join
131
+ cfg = cfg.each_line.reject do |line|
132
+ line.match /^! (Last|No) configuration change (at|since).*/ unless line =~ /\d+\sby\s\S+$/
133
+ end.join
124
134
  cfg.gsub! /^Current configuration : [^\n]*\n/, ''
125
135
  cfg.gsub! /^ tunnel mpls traffic-eng bandwidth[^\n]*\n*(
126
136
  (?: [^\n]*\n*)*