oxidized 0.32.1 → 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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +45 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  4. data/.github/ISSUE_TEMPLATE/support-request.md +39 -0
  5. data/.github/workflows/publishdocker.yml +35 -16
  6. data/.github/workflows/ruby.yml +4 -2
  7. data/.gitignore +2 -0
  8. data/.rubocop.yml +29 -8
  9. data/.rubocop_todo.yml +1 -60
  10. data/CHANGELOG.md +103 -2
  11. data/CONTRIBUTING.md +20 -10
  12. data/Dockerfile +37 -64
  13. data/README.md +47 -141
  14. data/Rakefile +9 -11
  15. data/docs/Configuration.md +236 -27
  16. data/docs/DeviceSimulation.md +19 -7
  17. data/docs/Docker.md +245 -0
  18. data/docs/Issues.md +27 -1
  19. data/docs/Model-Notes/EatonNetwork.md +18 -0
  20. data/docs/Model-Notes/HPEAruba.md +3 -2
  21. data/docs/ModelUnitTests.md +35 -25
  22. data/docs/Outputs.md +83 -2
  23. data/docs/Release.md +34 -24
  24. data/docs/Supported-OS-Types.md +7 -0
  25. data/docs/Troubleshooting.md +4 -13
  26. data/extra/device2yaml.rb +24 -9
  27. data/extra/rest_client.rb +3 -2
  28. data/extra/syslog.rb +8 -3
  29. data/lib/oxidized/cli.rb +7 -3
  30. data/lib/oxidized/config/vars.rb +22 -14
  31. data/lib/oxidized/config.rb +3 -2
  32. data/lib/oxidized/core.rb +30 -8
  33. data/lib/oxidized/hook/ciscosparkdiff.rb +11 -9
  34. data/lib/oxidized/hook/exec.rb +5 -4
  35. data/lib/oxidized/hook/githubrepo.rb +23 -17
  36. data/lib/oxidized/hook/noophook.rb +2 -2
  37. data/lib/oxidized/hook/slackdiff.rb +9 -8
  38. data/lib/oxidized/hook/xmppdiff.rb +9 -9
  39. data/lib/oxidized/hook.rb +10 -8
  40. data/lib/oxidized/input/cli.rb +8 -3
  41. data/lib/oxidized/input/exec.rb +1 -1
  42. data/lib/oxidized/input/ftp.rb +2 -2
  43. data/lib/oxidized/input/http.rb +6 -6
  44. data/lib/oxidized/input/input.rb +1 -0
  45. data/lib/oxidized/input/scp.rb +2 -2
  46. data/lib/oxidized/input/ssh.rb +21 -14
  47. data/lib/oxidized/input/telnet.rb +3 -3
  48. data/lib/oxidized/input/tftp.rb +1 -1
  49. data/lib/oxidized/job.rb +7 -4
  50. data/lib/oxidized/logger.rb +51 -0
  51. data/lib/oxidized/model/acos.rb +1 -0
  52. data/lib/oxidized/model/aos7.rb +9 -0
  53. data/lib/oxidized/model/aoscx.rb +2 -0
  54. data/lib/oxidized/model/aosw.rb +22 -17
  55. data/lib/oxidized/model/aricentiss.rb +2 -2
  56. data/lib/oxidized/model/asa.rb +3 -3
  57. data/lib/oxidized/model/awplus.rb +13 -10
  58. data/lib/oxidized/model/eatonnetwork.rb +65 -0
  59. data/lib/oxidized/model/edgecos.rb +2 -1
  60. data/lib/oxidized/model/edgeos.rb +7 -6
  61. data/lib/oxidized/model/edgeswitch.rb +3 -1
  62. data/lib/oxidized/model/efos.rb +41 -0
  63. data/lib/oxidized/model/eltex.rb +1 -1
  64. data/lib/oxidized/model/fabricos.rb +1 -1
  65. data/lib/oxidized/model/fastiron.rb +3 -1
  66. data/lib/oxidized/model/firelinuxos.rb +12 -3
  67. data/lib/oxidized/model/fortios.rb +5 -4
  68. data/lib/oxidized/model/gaiaos.rb +4 -4
  69. data/lib/oxidized/model/ingate.rb +47 -0
  70. data/lib/oxidized/model/ios.rb +16 -5
  71. data/lib/oxidized/model/ironware.rb +1 -1
  72. data/lib/oxidized/model/junos.rb +4 -0
  73. data/lib/oxidized/model/linksyssrw.rb +3 -3
  74. data/lib/oxidized/model/mlnxos.rb +14 -7
  75. data/lib/oxidized/model/model.rb +4 -3
  76. data/lib/oxidized/model/netgear.rb +8 -0
  77. data/lib/oxidized/model/nsxdfw.rb +2 -1
  78. data/lib/oxidized/model/nsxfirewall.rb +2 -1
  79. data/lib/oxidized/model/nxos.rb +2 -2
  80. data/lib/oxidized/model/openwrt.rb +6 -6
  81. data/lib/oxidized/model/powerconnect.rb +31 -10
  82. data/lib/oxidized/model/procurve.rb +3 -1
  83. data/lib/oxidized/model/qtech.rb +3 -1
  84. data/lib/oxidized/model/quantaos.rb +8 -6
  85. data/lib/oxidized/model/routeros.rb +3 -2
  86. data/lib/oxidized/model/saos10.rb +38 -0
  87. data/lib/oxidized/model/sixwind.rb +28 -0
  88. data/lib/oxidized/model/sonicos.rb +1 -1
  89. data/lib/oxidized/model/srosmd.rb +1 -1
  90. data/lib/oxidized/model/supermicro.rb +1 -1
  91. data/lib/oxidized/model/timos.rb +1 -1
  92. data/lib/oxidized/model/tmos.rb +1 -0
  93. data/lib/oxidized/model/tnsr.rb +53 -0
  94. data/lib/oxidized/model/trango.rb +3 -1
  95. data/lib/oxidized/model/unifiap.rb +144 -0
  96. data/lib/oxidized/model/vrp.rb +3 -1
  97. data/lib/oxidized/model/xos.rb +3 -1
  98. data/lib/oxidized/model/zhoneolt.rb +3 -1
  99. data/lib/oxidized/model/zynos.rb +3 -3
  100. data/lib/oxidized/node.rb +44 -27
  101. data/lib/oxidized/nodes.rb +8 -4
  102. data/lib/oxidized/output/file.rb +28 -0
  103. data/lib/oxidized/output/git.rb +148 -41
  104. data/lib/oxidized/output/gitcrypt.rb +18 -13
  105. data/lib/oxidized/output/http.rb +5 -4
  106. data/lib/oxidized/output/output.rb +14 -0
  107. data/lib/oxidized/source/http.rb +4 -2
  108. data/lib/oxidized/version.rb +6 -4
  109. data/lib/oxidized/worker.rb +13 -13
  110. data/lib/oxidized.rb +3 -24
  111. data/lib/refinements.rb +2 -0
  112. data/oxidized.gemspec +10 -8
  113. metadata +74 -41
  114. data/examples/podman-compose/Makefile +0 -103
  115. data/examples/podman-compose/README.md +0 -94
  116. data/examples/podman-compose/docker-compose.yml +0 -30
  117. data/examples/podman-compose/gitserver/.gitignore +0 -1
  118. data/examples/podman-compose/gitserver/Dockerfile +0 -14
  119. data/examples/podman-compose/model-simulation/Dockerfile-model +0 -13
  120. data/examples/podman-compose/model-simulation/asternos.sh +0 -36
  121. data/examples/podman-compose/oxidized-config/.gitignore +0 -10
  122. data/examples/podman-compose/oxidized-config/config +0 -46
  123. data/examples/podman-compose/oxidized-config/config_csv-file +0 -46
  124. data/examples/podman-compose/oxidized-config/config_csv-gitserver +0 -56
  125. data/examples/podman-compose/oxidized-config/router.db +0 -1
  126. data/examples/podman-compose/oxidized-ssh/.gitignore +0 -1
  127. data/examples/podman-compose/oxidized-ssh/README.md +0 -14
@@ -5,13 +5,15 @@ class PowerConnect < Oxidized::Model
5
5
 
6
6
  comment '! '
7
7
 
8
- expect /^\s*--More--\s+.*$/ do |data, re|
8
+ expect /\n\s*--More--\s+.*/ do |data, re| # Also grab the blank line above the --More--
9
9
  send ' '
10
10
  data.sub re, ''
11
11
  end
12
12
 
13
+ # Filter all command output
13
14
  cmd :all do |cfg|
14
- cfg.each_line.to_a[1..-3].join
15
+ cfg.gsub! /\r+/, '' # Remove the CR characters echoed back from the commands
16
+ cfg.cut_tail # Drop the last line which is the next prompt
15
17
  end
16
18
 
17
19
  cmd :secret do |cfg|
@@ -32,7 +34,7 @@ class PowerConnect < Oxidized::Model
32
34
  end
33
35
 
34
36
  cmd 'show running-config' do |cfg|
35
- cfg.sub(/^(sflow \S+ destination owner \S+ timeout )\d+$/, '! \1<timeout>')
37
+ cfg.sub(/^(sflow \S+ destination owner \S+ timeout )\d+$/, '! \1<timeout>') # Remove changing timeout
36
38
  end
37
39
 
38
40
  cfg :telnet, :ssh do
@@ -50,15 +52,21 @@ class PowerConnect < Oxidized::Model
50
52
  end
51
53
  end
52
54
 
53
- post_login "terminal datadump"
54
- post_login "terminal length 0"
55
- pre_logout "logout"
56
- pre_logout "exit"
55
+ post_login do
56
+ cmd "terminal datadump"
57
+ cmd "terminal length 0"
58
+ end
59
+ pre_logout do
60
+ send "exit\r"
61
+ sleep(0.25)
62
+ send "logout\r"
63
+ end
57
64
  end
58
65
 
59
66
  def clean(cfg)
60
67
  out = []
61
- skip_blocks = 0
68
+ len1 = len2 = skip_blocks = 0
69
+
62
70
  cfg.each_line do |line|
63
71
  # If this is a stackable switch we should skip this block of information
64
72
  if line.match(/Up\sTime|Temperature|Power Suppl(ies|y)|Fans/i) && (@stackable == true)
@@ -71,9 +79,22 @@ class PowerConnect < Oxidized::Model
71
79
  skip_blocks -= 1 if /\S/ !~ line
72
80
  next
73
81
  end
74
- out << line.strip
82
+ line = line.strip
83
+ # If the temps were not removed by skipping blocks, then mask them out wih XXX
84
+ # The most recent set of dashes has the spacing we want to match
85
+ if (match = line.match(/^(---+ +)(---+ +)/))
86
+ one, two = match.captures
87
+ len1 = one.length
88
+ len2 = two.length
89
+ end
90
+ # This can only be a temperature, right? ;-)
91
+ if (match = line.match(/^(\d{1,2}) {3,}\d+ (.*)$/))
92
+ one, two = match.captures
93
+ line = one.to_s + (' ' * (len1 - one.length)) + "XXX" + (' ' * (len2 - 3)) + two.to_s
94
+ end
95
+ out << line
75
96
  end
76
- out = out.reject { |line| line[/Up\sTime/] }
97
+ out = out.reject { |line| line[/Up\sTime/] } # Filter out Up Time
77
98
  out = comment out.join "\n"
78
99
  out << "\n"
79
100
  end
@@ -75,7 +75,9 @@ class Procurve < Oxidized::Model
75
75
 
76
76
  # not supported on all models
77
77
  cmd 'show system information' do |cfg|
78
- cfg = cfg.each_line.reject { |line| line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/ }
78
+ cfg = cfg.each_line.reject do |line|
79
+ line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/
80
+ end
79
81
  cfg = cfg.join
80
82
  comment cfg
81
83
  end
@@ -16,7 +16,9 @@ class QTECH < Oxidized::Model
16
16
  end
17
17
 
18
18
  cmd 'show version' do |cfg|
19
- comment cfg.each_line.reject { |line| line.match /^ (Copyright |All rights reserved$|Uptime is |Last reboot is )/ }.join
19
+ comment cfg.each_line.reject { |line|
20
+ line.match /^ (Copyright |All rights reserved$|Uptime is |Last reboot is )/
21
+ }.join
20
22
  end
21
23
 
22
24
  cmd 'show running-config' do |cfg|
@@ -1,15 +1,17 @@
1
1
  class QuantaOS < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- prompt /^\((\w|\S)+\) (>|#)$/
4
+ prompt /^\(\S+\) (>|#)$/
5
5
  comment '! '
6
6
 
7
+ cmd :all do |cfg|
8
+ # Remove command echo and prompt
9
+ cfg.cut_both
10
+ end
11
+
7
12
  cmd 'show run' do |cfg|
8
- cfg.each_line.select do |line|
9
- (not line.match /^!.*$/) &&
10
- (not line.match /^\((\w|\S)+\) (>|#)$/) &&
11
- (not line.match /^show run$/)
12
- end.join
13
+ # Remove commented lines
14
+ cfg.lines.grep_v(/^!/).join
13
15
  end
14
16
 
15
17
  cfg :telnet do
@@ -11,7 +11,7 @@ class RouterOS < Oxidized::Model
11
11
  cfg.gsub! /^\r+(.+)/, '\1'
12
12
  cfg.gsub! /([^\r]*)\r+$/, '\1'
13
13
  end
14
- cfg
14
+ cfg.lines.map { |line| line.rstrip }.join("\n") + "\n" # strip trailing whitespace
15
15
  end
16
16
 
17
17
  cmd '/system resource print' do |cfg|
@@ -30,7 +30,7 @@ class RouterOS < Oxidized::Model
30
30
  end
31
31
 
32
32
  post do
33
- Oxidized.logger.debug "lib/oxidized/model/routeros.rb: running /export for routeros version #{@ros_version}"
33
+ logger.debug "Running /export for routeros version #{@ros_version}"
34
34
  run_cmd = if vars(:remove_secret)
35
35
  '/export hide-sensitive'
36
36
  elsif (not @ros_version.nil?) && (@ros_version >= 7)
@@ -45,6 +45,7 @@ class RouterOS < Oxidized::Model
45
45
  cfg.gsub! "# poe-out status: short_circuit\r\n", '' # Remove intermittent POE short_circuit comment
46
46
  cfg.gsub! "# Firmware upgraded successfully, please reboot for changes to take effect!\r\n", '' # Remove transient firmware upgrade comment
47
47
  cfg.gsub! /# \S+ not ready\r\n/, '' # Remove intermittent $interface not ready comment
48
+ cfg.gsub! /# .+ please restart the device in order to apply the new setting\r\n/, '' # Remove intermittent restart needed comment. (e.g. for ipv6 settings)
48
49
  cfg = cfg.split("\n")
49
50
  cfg.reject! { |line| line[/^#\s\w{3}\/\d{2}\/\d{4}.*$/] } # Remove date time and 'by RouterOS' comment (v6)
50
51
  cfg.reject! { |line| line[/^#\s\d{4}-\d{2}-\d{2}.*$/] } # Remove date time and 'by RouterOS' comment (v7)
@@ -0,0 +1,38 @@
1
+ class SAOS10 < Oxidized::Model
2
+ using Refinements
3
+ # Ciena SAOS switch
4
+ # used for 10.x devices
5
+
6
+ prompt /^[\w\-]+\*?> ?$/
7
+ comment '# '
8
+
9
+ cmd :all do |cfg|
10
+ cfg.cut_both
11
+ end
12
+
13
+ cmd('show system hostname') { |cfg| comment cfg }
14
+
15
+ cmd('show software') { |cfg| comment cfg }
16
+
17
+ cmd('show system components') { |cfg| comment cfg }
18
+
19
+ cmd('show system health') { |cfg| comment cfg }
20
+
21
+ cmd('show system last-reset-reasons') { |cfg| comment cfg }
22
+
23
+ cmd 'show running config' do |cfg|
24
+ cfg.gsub! /^! Created: [^\n]*\n/, ''
25
+ cfg.gsub! /^! On terminal: [^\n]*\n/, ''
26
+ cfg
27
+ end
28
+
29
+ cfg :telnet do
30
+ username /login:/
31
+ password /assword:/
32
+ end
33
+
34
+ cfg :telnet, :ssh do
35
+ post_login 'set session more off'
36
+ pre_logout 'exit'
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ class SixWind < Oxidized::Model
2
+ using Refinements
3
+
4
+ prompt /^[\w\s\(\).@_\/:-]+[>] $/
5
+ comment '# '
6
+
7
+ cmd :all do |cfg|
8
+ cfg.cut_both
9
+ end
10
+
11
+ cmd :secret do |cfg|
12
+ cfg.gsub!(/(?<! {1})(?:password|secret) (?:\d )?\S+/, '\\1 <secret hidden>') # double space to exclude radius password template
13
+ cfg
14
+ end
15
+
16
+ cmd 'show product version' do |cfg|
17
+ comment cfg
18
+ end
19
+
20
+ cmd 'show config' do |cfg|
21
+ cfg
22
+ end
23
+
24
+ cfg :ssh do
25
+ post_login 'cliconfig pager enabled false'
26
+ pre_logout 'exit'
27
+ end
28
+ end
@@ -56,7 +56,7 @@ class SonicOS < Oxidized::Model
56
56
  next if line =~ /date \d{4}:\d{2}:\d{2}/
57
57
  next if line =~ /time \d{2}:\d{2}:\d{2}/
58
58
  next if line =~ /system-time "\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2}.\d+"/
59
- next if line =~ /system-uptime "((\s+up\s+\d+\s+)|(\d+\s\w+(,\s)?)*)"/
59
+ next if line =~ /system-uptime "(?:\s+up\s+\d+\s+|\d+ \w+(?:, \d+ \w+)*)"/
60
60
  next if line =~ /checksum \d+/
61
61
 
62
62
  line = line[1..-1] if line[0] == "\r"
@@ -26,7 +26,7 @@ class SROSMD < Oxidized::Model
26
26
  #
27
27
  # Strip uptime.
28
28
  #
29
- cfg.sub! /^System Up Time.*\n/, ''
29
+ cfg.gsub! /^System Up Time.*\n/, ''
30
30
  comment cfg
31
31
  end
32
32
 
@@ -5,6 +5,6 @@ require_relative 'edgecos'
5
5
 
6
6
  Supermicro = EdgeCOS
7
7
 
8
- Oxidized.logger.warn "Using deprecated model supermicro, use edgecos instead."
8
+ logger.warn "Using deprecated model supermicro, use edgecos instead."
9
9
 
10
10
  # Deprecated
@@ -5,6 +5,6 @@ require_relative 'sros'
5
5
 
6
6
  TiMOS = SROS
7
7
 
8
- Oxidized.logger.warn "Using deprecated model timos, use sros instead."
8
+ logger.warn "Using deprecated model timos, use sros instead."
9
9
 
10
10
  # Deprecated
@@ -32,6 +32,7 @@ class TMOS < Oxidized::Model
32
32
  cfg.gsub!(/^\s+bandwidth-bps (\d+)/, '')
33
33
  cfg.gsub!(/^\s+bandwidth-cps (\d+)/, '')
34
34
  cfg.gsub!(/^\s+bandwidth-pps (\d+)\n/, '')
35
+ cfg.gsub!(/^\s*\S*encrypted \S+\n/, '')
35
36
  cfg
36
37
  end
37
38
 
@@ -0,0 +1,53 @@
1
+ class TNSR < Oxidized::Model
2
+ using Refinements
3
+
4
+ # Netgate TNSR #
5
+
6
+ # prompt examples
7
+ # https://docs.netgate.com/tnsr/en/latest/basics/working-cli.html#command-prompt
8
+ # "<hostname> tnsr<(mode)># " <-- with trailing whitespace
9
+ # tnsr-dev-25-02 tnsr#
10
+ # tnsr-dev-25-02 tnsr(config)# <-- after "configure terminal", but this is not important for oxidized
11
+ # prompt from debug log
12
+ # received "Welcome to Netgate TNSR Version: 25.02-2\r\n\r\n\t* Documentation: https://docs.netgate.com/tnsr/en/latest/\r\n\t* Support: https://www.netgate.com/support\r\n\r\n _ __________\r\n _| |_ _ __ | ___ _ __ |\r\n|_ __| '_ \\ |/ __| '__||\r\n | |_| | | ||\\__ \\ | |\r\n \\__|_| |_|||___/_| |\r\n |__________|\r\n\r\n\r\n"
13
+ # received "\r\nVersion: 25.02-2\r\n\r\nFor information see 'show documentation'\r\n\r\n"
14
+ # received "\rbgp01 tnsr# "
15
+ # when the --More-- pager is the last line of paged output, the prompt contains \x08\x20\x08 orphans on the begin
16
+ # you can look for context into spec simulation:
17
+ # spec/model/data/tnsr:TNSR_24.10-3_short-config:simulation.yaml
18
+ # spec/model/data/tnsr:TNSR_25.02-2_long-config-and-pager-at-last-line:simulation.yaml
19
+ prompt /^((\x08{8}\x20{8}\x08{8})?\r?[\w-]+\stnsr#\s?)$/
20
+
21
+ comment '! '
22
+
23
+ expect /^--More--/ do |data, re|
24
+ send ' '
25
+ data.sub re, ''
26
+ end
27
+
28
+ cmd :all do |cfg|
29
+ # remove orphans \r
30
+ cfg.gsub! /^\r+(.+)/, '\1'
31
+ # handle pager orphans ^H^H^H^H^H^H^H^H ^H^H^H^H^H^H^H^H
32
+ cfg.gsub! /\x08{8}\x20{8}\x08{8}/, ''
33
+ cfg.cut_both
34
+ end
35
+
36
+ cmd :secret do |cfg|
37
+ cfg.gsub! /(password( \d+)?) (\S+).*/, '\\1 <secret hidden>'
38
+ cfg.gsub! /^(snmp community community-name )\S+ (.*)?/, '\\1 <configuration removed> \\2'
39
+ cfg
40
+ end
41
+
42
+ cmd 'show version all' do |cfg|
43
+ comment cfg
44
+ end
45
+
46
+ cmd 'show configuration running cli' do |cfg|
47
+ cfg
48
+ end
49
+
50
+ cfg :telnet, :ssh do
51
+ pre_logout 'exit'
52
+ end
53
+ end
@@ -18,7 +18,9 @@ class Trango < Oxidized::Model
18
18
  out << ("freq " + Regexp.last_match[1] + ' ' + Regexp.last_match[2]) if line =~ /\[Active Channel\] (\d+) (v|h)/
19
19
  out << ("peerid " + Regexp.last_match[1]) if line =~ /\[Peer ID\] ([A-F0-9]+)/
20
20
  out << ("utype " + Regexp.last_match[1]) if line =~ /\[Unit Type\] (\S+)/
21
- comments << ('# ' + Regexp.last_match[1] + ': ' + Regexp.last_match[2]) if line =~ /\[(Hardware Version|Firmware Version|Model|S\/N)\] (\S+)/
21
+ if line =~ /\[(Hardware Version|Firmware Version|Model|S\/N)\] (\S+)/
22
+ comments << ('# ' + Regexp.last_match[1] + ': ' + Regexp.last_match[2])
23
+ end
22
24
  out << ("remarks " + Regexp.last_match[1]) if line =~ /\[Remarks\] (\S+)/
23
25
  out << ("rssiled " + Regexp.last_match[1]) if line =~ /\[RSSI LED\] (on|off)/
24
26
  speed = Regexp.last_match[1] if line =~ /\[Speed\] (\d+) Mbps/
@@ -0,0 +1,144 @@
1
+ class Unifiap < Oxidized::Model
2
+ using Refinements
3
+
4
+ # Ubiquiti Unifi AP circa 6.x
5
+ # Should also work for unfi switches, and airOS, maybe they could be combined.
6
+ # Since it relies on exec channels, because the interactive session wouldn't
7
+ # capture all of the system.cfg output, you can't use telnet with this model.
8
+
9
+ # Sometimes there's a handy info command that summarizes some device attributes,
10
+ # but it doesn't seem to be available in exec mode. So we try to build up a similar
11
+ # list by extracting tidbits from various places. AirOS doesn't have some of these
12
+ # files, so we # may have to fall back on other commands, or locations.
13
+
14
+ # First get the board model
15
+ cmd 'head -4 /etc/board.info' do |cfg|
16
+ @model = Regexp.last_match(1) if cfg =~ /board\.name=(\S+)/i
17
+ ""
18
+ end
19
+
20
+ # and version
21
+ cmd 'cat /etc/version' do |cfg|
22
+ @version = Regexp.last_match(1) if cfg =~ /(\S+)$/i
23
+ ""
24
+ end
25
+
26
+ # Now the Mac address
27
+ cmd 'ifconfig eth0' do |cfg|
28
+ @mac = Regexp.last_match(1) if cfg =~ /eth0\s+Link encap:Ethernet\s+HWaddr\s+(\w+:\w+:\w+:\w+:\w+:\w+)/i
29
+ ""
30
+ end
31
+
32
+ # Next see if we can get our IP and host name out of /etc/hosts
33
+ cmd 'cat /etc/hosts' do |cfg|
34
+ cfg = cfg.split("\n").reject do |line|
35
+ line[/^\s*(127|0000:0000:0000:0000:0000:0000:0000:0001|0:0:0:0:0:0:0:1|::1)/]
36
+ end
37
+ cfg.select do |line|
38
+ if (match = line.match(/(\d+\.\d+\.\d+\.\d+)\s+(\S+)/))
39
+ @ip, @hostname = match.captures
40
+ end
41
+ end
42
+ ""
43
+ end
44
+
45
+ # We check here to see if we succeeded with /etc/hosts. If not, then we try again with ifconfig, and /tmp/system.cfg
46
+ cmd 'echo' do
47
+ unless @ip
48
+ cmd 'ifconfig br0' do |cfg|
49
+ @ip = Regexp.last_match(1) if cfg =~ /inet addr:\s*(\d+\.\d+\.\d+\.\d+)/i
50
+ end
51
+
52
+ unless @ip
53
+ cmd 'ifconfig eth0' do |cfg|
54
+ @ip = Regexp.last_match(1) if cfg =~ /inet addr:\s*(\d+\.\d+\.\d+\.\d+)/i
55
+ end
56
+ end
57
+ end
58
+
59
+ unless @hostname
60
+ cmd 'cat /tmp/system.cfg' do |cfg|
61
+ @hostname = Regexp.last_match(1) if cfg =~ /resolv.host.1.name=(\S+)/i
62
+ end
63
+ end
64
+ ""
65
+ end
66
+
67
+ # Check if ntpclient is running
68
+ cmd 'ps wwww' do |cfg|
69
+ @ntpserver = Regexp.last_match(1) if cfg =~ /bin\/ntpclient.+-h\s*(\S+)/i
70
+ ""
71
+ end
72
+
73
+ # If it's a Unifi device it may have NTP health indication
74
+ # If there are other places that Ubiquiti puts these status files, add them here.
75
+ cmd '[ -e /tmp/run/ntp.ready ] || [ -e /var/run/ntp.ready ] && echo "File(s) exist(s)" || echo "No such file"' do |cfg|
76
+ if cfg =~ /No such file/i
77
+ if @ntpserver
78
+ # Ok, now lets try getting the skew from the output of ntpclient
79
+ cmd "ntpclient -d -n -c 2 -i0 -h #{@ntpserver}" do |ntp_out|
80
+ @skew = ntpskew(ntp_out)
81
+ end
82
+ @sync = !@skew.nil? && @skew.to_f.abs < 1e6 ? "Synchronized" : "FAIL"
83
+ end
84
+ else
85
+ @ntpserver = true
86
+ @sync = "Synchronized"
87
+ end
88
+ ""
89
+ end
90
+
91
+ # Now we can display it all as a banner
92
+ cmd 'echo' do
93
+ out = []
94
+ out << "*************************"
95
+ out << "Model: #{@model}"
96
+ out << "Version: #{@version}"
97
+ out << "MAC Address: #{@mac}"
98
+ out << "IP Address: #{@ip}"
99
+ out << "Hostname: #{@hostname}"
100
+ out << "NTP: #{@sync}" if @ntpserver
101
+ out << "*************************"
102
+ comment out.join("\n") + "\n"
103
+ end
104
+
105
+ # Followed by the board info
106
+ cmd 'cat /etc/board.info' do |cfg|
107
+ cfg = "#\n# Board Info:\n#\n" + cfg
108
+ comment cfg
109
+ end
110
+
111
+ # Lastly the system config
112
+ cmd 'cat /tmp/system.cfg' do |cfg|
113
+ cfg = "#\n# System Config:\n#\n" + cfg
114
+ cfg + "\n"
115
+ end
116
+
117
+ cmd :secret do |cfg|
118
+ cfg.gsub! /^((?:users|snmp\.(?:user|community))\.\d+\.password)=.+/, "# \\1=<hidden>"
119
+ cfg
120
+ end
121
+
122
+ cfg :ssh do
123
+ exec true # Don't run shell, run each command in exec channel
124
+ end
125
+
126
+ # NTPskew: Return the skew in micro seconds from the ntpclient output
127
+ def ntpskew(cfg)
128
+ index = skew = nil
129
+
130
+ cfg.each_line do |line|
131
+ # Look for the header just before the stats line, and find which number is skew
132
+ if line.match(/^\s*[a-z]+\s+[a-z]+\s+[a-z]+\s+[a-z]+/i)
133
+ words = line.split
134
+ index = words.map(&:downcase).index("skew")
135
+ end
136
+ # Now look for the single stats line and grab the skew
137
+ if !index.nil? && line.match(/^\s*[\d.]+\s+[\d.]+\s+[\d.]+\s+[\d.]+/)
138
+ numbers = line.split
139
+ skew = numbers[index]
140
+ end
141
+ end
142
+ skew
143
+ end
144
+ end
@@ -27,7 +27,9 @@ class VRP < Oxidized::Model
27
27
  end
28
28
 
29
29
  cmd 'display version' do |cfg|
30
- cfg = cfg.each_line.reject { |l| l.match /uptime|^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d(\.\d\d\d)? ?(\+\d\d:\d\d)?$/ }.join
30
+ cfg = cfg.each_line.reject do |l|
31
+ l.match /uptime|^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d(\.\d\d\d)? ?(\+\d\d:\d\d)?$/
32
+ end.join
31
33
  comment cfg
32
34
  end
33
35
 
@@ -33,7 +33,9 @@ class XOS < Oxidized::Model
33
33
 
34
34
  cmd 'show switch' do |cfg|
35
35
  cfg.gsub! /Next periodic save on.*/, ''
36
- comment cfg.each_line.reject { |line| line.match(/Time:/) || line.match(/boot/i) || line.match(/Next periodic/) }.join
36
+ comment cfg.each_line.reject { |line|
37
+ line.match(/Time:/) || line.match(/boot/i) || line.match(/Next periodic/)
38
+ }.join
37
39
  end
38
40
 
39
41
  cmd 'show configuration' do |cfg|
@@ -36,7 +36,9 @@ class ZhoneOLT < Oxidized::Model
36
36
  end
37
37
 
38
38
  cmd 'ethrpshow' do |cfg|
39
- cfg = cfg.each_line.select { |line| line.match /Vendor (Name|OUI|Part|Revision)|Serial Number|Manufacturing Date/ }.join
39
+ cfg = cfg.each_line.select do |line|
40
+ line.match /Vendor (Name|OUI|Part|Revision)|Serial Number|Manufacturing Date/
41
+ end.join
40
42
  comment cfg
41
43
  end
42
44
 
@@ -1,9 +1,9 @@
1
1
  class ZyNOS < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- prompt /^([\w.@()-<]+[#>]\s?)$/
4
+ prompt /^([\w.@()\-<]+[#>]\s?)$/
5
5
  # if there is something you can not identify after prompt, uncomment next line and comment previous line
6
- # prompt /^([\w.@()-<]+[#>]\s?).*$/
6
+ # prompt /^([\w.@()\-<]+[#>]\s?).*$/
7
7
 
8
8
  comment '! '
9
9
 
@@ -21,7 +21,7 @@ class ZyNOS < Oxidized::Model
21
21
  end
22
22
 
23
23
  # ignore copyright motd
24
- expect /^(Copyright .*)\n^([\w.@()-<]+[#>]\s?)$/ do
24
+ expect /^(Copyright .*)\n^([\w.@()\-<]+[#>]\s?)$/ do
25
25
  send '\n'
26
26
  ""
27
27
  end