oxidized 0.34.3 → 0.35.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codeql.yml +4 -4
  3. data/.github/workflows/publishdocker.yml +82 -11
  4. data/.github/workflows/ruby.yml +1 -1
  5. data/.github/workflows/stale.yml +1 -1
  6. data/.rubocop.yml +1 -0
  7. data/.rubocop_todo.yml +1 -1
  8. data/CHANGELOG.md +39 -1
  9. data/Dockerfile +74 -66
  10. data/README.md +2 -2
  11. data/Rakefile +21 -3
  12. data/docs/Configuration.md +92 -0
  13. data/docs/Creating-Models.md +85 -19
  14. data/docs/Ruby-API.md +52 -0
  15. data/docs/Supported-OS-Types.md +4 -1
  16. data/extra/oxidized.runit +1 -1
  17. data/lib/oxidized/core.rb +2 -1
  18. data/lib/oxidized/input/http.rb +9 -2
  19. data/lib/oxidized/input/scp.rb +3 -3
  20. data/lib/oxidized/input/ssh.rb +3 -3
  21. data/lib/oxidized/input/telnet.rb +2 -2
  22. data/lib/oxidized/model/adva.rb +1 -1
  23. data/lib/oxidized/model/airfiber.rb +1 -1
  24. data/lib/oxidized/model/aoscx.rb +29 -44
  25. data/lib/oxidized/model/aosw.rb +1 -1
  26. data/lib/oxidized/model/arubainstant.rb +18 -6
  27. data/lib/oxidized/model/asternos.rb +1 -1
  28. data/lib/oxidized/model/axos.rb +1 -1
  29. data/lib/oxidized/model/comtrol.rb +1 -1
  30. data/lib/oxidized/model/cumulus.rb +2 -7
  31. data/lib/oxidized/model/eatonnetwork.rb +5 -0
  32. data/lib/oxidized/model/eltex.rb +1 -1
  33. data/lib/oxidized/model/enterasys800.rb +1 -1
  34. data/lib/oxidized/model/fabricos.rb +1 -1
  35. data/lib/oxidized/model/fsos.rb +1 -1
  36. data/lib/oxidized/model/garderos.rb +1 -6
  37. data/lib/oxidized/model/ironware.rb +1 -1
  38. data/lib/oxidized/model/mlnxos.rb +3 -10
  39. data/lib/oxidized/model/model.rb +101 -12
  40. data/lib/oxidized/model/netgear.rb +1 -0
  41. data/lib/oxidized/model/netonix.rb +1 -1
  42. data/lib/oxidized/model/netscaler.rb +1 -1
  43. data/lib/oxidized/model/nxos.rb +9 -9
  44. data/lib/oxidized/model/onefinity.rb +1 -1
  45. data/lib/oxidized/model/opnsense.rb +8 -0
  46. data/lib/oxidized/model/perle.rb +35 -0
  47. data/lib/oxidized/model/pfsense.rb +8 -0
  48. data/lib/oxidized/model/saos10.rb +1 -1
  49. data/lib/oxidized/model/siklu.rb +1 -1
  50. data/lib/oxidized/model/siklumhtg.rb +1 -1
  51. data/lib/oxidized/model/sixwind.rb +1 -1
  52. data/lib/oxidized/model/slxos.rb +1 -1
  53. data/lib/oxidized/model/sonicos.rb +1 -1
  54. data/lib/oxidized/model/speedtouch.rb +1 -1
  55. data/lib/oxidized/model/telco.rb +1 -1
  56. data/lib/oxidized/model/tnsr.rb +7 -3
  57. data/lib/oxidized/model/trango.rb +1 -1
  58. data/lib/oxidized/model/ucs.rb +1 -1
  59. data/lib/oxidized/model/voltaire.rb +1 -1
  60. data/lib/oxidized/model/vyatta.rb +1 -1
  61. data/lib/oxidized/model/vyos.rb +34 -0
  62. data/lib/oxidized/model/zhoneolt.rb +1 -1
  63. data/lib/oxidized/model/zynoscli.rb +1 -1
  64. data/lib/oxidized/node.rb +6 -1
  65. data/lib/oxidized/source/http.rb +10 -2
  66. data/lib/oxidized/version.rb +2 -2
  67. data/oxidized.gemspec +4 -5
  68. metadata +13 -29
  69. data/lib/oxidized/model/timos.rb +0 -10
@@ -8,6 +8,10 @@ This methodology allows local site changes to be preserved during Oxidized versi
8
8
 
9
9
  ## Index
10
10
  - [Creating a new model](#creating-a-new-model)
11
+ - [Typical Tasks and Solutions](#typical-tasks-and-solutions)
12
+ - [Handling 'enable' mode](#handling-enable-mode)
13
+ - [Remove ANSI escape codes](#remove-ansi-escape-codes)
14
+ - [Conditional commands](#conditional-commands)
11
15
  - [Extending an existing model with a new command](#extending-an-existing-model-with-a-new-command)
12
16
  - [Create unit tests for the model](#create-unit-tests-for-the-model)
13
17
  - [Advanced features](#advanced-features)
@@ -54,7 +58,9 @@ The API documentation contains a list of [methods](https://github.com/ytti/oxidi
54
58
 
55
59
  A more fleshed out example can be found in the `IOS` and `JunOS` models.
56
60
 
57
- ### Common task: mechanism for handling 'enable' mode
61
+ ## Typical Tasks and Solutions
62
+
63
+ ### Handling 'enable' mode
58
64
  The following code snippet demonstrates how to handle sending the 'enable'
59
65
  command and an enable password.
60
66
 
@@ -74,31 +80,91 @@ need to enable privileged mode, either without providing a password (by setting
74
80
  end
75
81
  end
76
82
  ```
77
- Note: remove `:telnet, ` if your device does not support telnet.
78
-
79
- ### Common Task: remove ANSI escape codes
80
- > :warning: This common task is experimental.
81
- > If it does not work for you, please open an issue so that we can adapt the
82
- > code snippet.
83
+ Note: Remove `:telnet, ` if your device does not support telnet.
83
84
 
84
- Some devices produce ANSI escape codes to enhance the appearance of output.
85
+ ### Remove ANSI Escape Codes
86
+ Some devices produce [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands)
87
+ to enhance the appearance of their output.
85
88
  However, this can make prompt matching difficult and some of these ANSI escape
86
89
  codes might end up in the resulting configuration.
87
90
 
88
- You can remove most [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands) using the following Ruby
89
- code in your model:
91
+ You can remove most ANSI escape codes by inserting the following line in your
92
+ model:
93
+ ```ruby
94
+ clean :escape_codes
90
95
  ```
91
- # Remove ANSI escape codes
92
- expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
93
- data.gsub re, ''
96
+
97
+ When using clean `:escape_codes`, you don't have to worry about escape codes
98
+ in your prompt regexp, as they will be removed before the prompt detection runs.
99
+
100
+ If it doesn't work for your model, please open an issue and provide a
101
+ [device simulation file](/docs/DeviceSimulation.md) so that we can adapt the
102
+ code.
103
+
104
+ ### Conditional commands
105
+ Some times, you have to run commands depending on the output of the device or
106
+ a configured variable. For this, there are at least three solutions.
107
+
108
+ #### Nested `cmd`
109
+ You can nest `cmd` inside [`cmd` blocks](Ruby-API.md#cmd), the following example
110
+ is taken from [nxos.rb](/lib/oxidized/model/nxos.rb):
111
+ ```ruby
112
+ cmd 'show inventory all' do |cfg|
113
+ if cfg.include? "% Invalid parameter detected at '^' marker."
114
+ # 'show inventory all' isn't supported on older versions (See Issue #3657)
115
+ cfg = cmd 'show inventory'
116
+ end
117
+ comment cfg
118
+ end
119
+ ```
120
+
121
+ #### pre/post blocks
122
+ After all the [`cmd` blocks](Ruby-API.md#cmd) have been run, the [`pre`
123
+ and `post` blocks](Ruby-API.md#pre--post) are run. The following example is
124
+ taken from [junos.rb](/lib/oxidized/model/junos.rb):
125
+ ```ruby
126
+ post do
127
+ out = String.new
128
+ case @model
129
+ when 'mx960'
130
+ out << cmd('show chassis fabric reachability') { |cfg| comment cfg }
131
+ when /^(ex22|ex3[34]|ex4|ex8|qfx)/
132
+ out << cmd('show virtual-chassis') { |cfg| comment cfg }
133
+ when /^srx/
134
+ out << cmd('show chassis cluster status') do |cfg|
135
+ cfg.lines.count <= 1 && cfg.include?("error:") ? String.new : comment(cfg)
136
+ end
137
+ end
138
+ out
139
+ end
140
+ ```
141
+
142
+ In [pre/post blocks](Ruby-API.md#pre--post), you can also use dynamic generated
143
+ commands, for example in [eatonnetwok.rb](/lib/oxidized/model/eatonnetwork.rb):
144
+ ```ruby
145
+ post do
146
+ cmd "save_configuration -p #{@node.auth[:password]}"
147
+ end
148
+ ```
149
+
150
+ #### Conditional `cmd`
151
+ The `cmd "string"` method for accepts a lambda function via the `:if` argument
152
+ to execute the command only when the lambda evaluates to true.
153
+ The lambda function is evaluated at runtime in the instance context.
154
+
155
+ ```ruby
156
+ cmd 'conditional command', if: lambda {
157
+ # Use lambda when multiple lines are needed
158
+ vars("condition")
159
+ } do |cfg|
160
+ @run_second_command = "go"
161
+ comment cfg
162
+ end
163
+
164
+ cmd 'second command', if: -> { @run_second_command == "go" } do |cfg|
165
+ comment cfg
94
166
  end
95
167
  ```
96
- Explanation of the Regular Expression:
97
- - `\e\[` : Control Sequence Introducer (CSI), which starts with "ESC [".
98
- - `[0-?]*` : "Parameter" bytes (range 0x30–0x3F, corresponding to ASCII `0–9:;<=>?`).
99
- - `[ -\/]*`: "Intermediate" bytes (range 0x20–0x2F, corresponding to ASCII ` !"#$%&'()*+,-./`).
100
- - `[@-~]` : The "final" byte (range 0x40–0x7E, corresponding to ASCII ``@A–Z[\]^_`a–z{|}~).[``).
101
- - `\r?` : Some ESC codes include a carriage return, which we do not want in the resulting config.
102
168
 
103
169
  ## Extending an existing model with a new command
104
170
 
data/docs/Ruby-API.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  The following objects exist in Oxidized.
4
4
 
5
+ ## Index
6
+ - [Input](#input)
7
+ - [http](#http)
8
+ - [Output](#output)
9
+ - [Source](#source)
10
+ - [Model](#model)
11
+ - [At the top level](#at-the-top-level)
12
+ - [cfg](#cfg)
13
+ - [cmd](#cmd)
14
+ - [comment](#comment)
15
+ - [prompt](#prompt)
16
+ - [expect](#expect)
17
+ - [pre / post](#pre--post)
18
+ - [At the second level](#at-the-second-level)
19
+ - [comment](#comment-1)
20
+ - [password](#password)
21
+ - [post_login](#post_login)
22
+ - [pre_logout](#pre_logout)
23
+ - [send](#send)
24
+ - [cmd](#cmd-1)
25
+ - [Monkey patching](#monkey-patching)
26
+ - [clear: true](#clear-true)
27
+ - [prepend: true](#prepend-true)
28
+ - [Refinements - String Convenience Methods](#refinements)
29
+ - [cut_tail](#cut_tail)
30
+ - [cut_head](#cut_head)
31
+ - [cut_both](#cut_both)
32
+
5
33
  ## Input
6
34
 
7
35
  * gets config from nodes
@@ -91,8 +119,28 @@ string.
91
119
  Execution order is `:all`, `:secret`, and lastly the command specific block, if
92
120
  given.
93
121
 
122
+ The `cmd "string"` method for accepts a lambda function via the `:if` argument
123
+ to execute the command only when the lambda evaluates to true.
124
+ The lambda function is evaluated at runtime in the instance context.
125
+ See [Conditional `cmd`](Creating-Models.md#conditional-cmd) for details.
126
+
94
127
  Supports [monkey patching](#monkey-patching).
95
128
 
129
+ #### pre / post
130
+ After all `cmd` have been run, the blocks defined in pre and post are called. The
131
+ output of pre will be prepended to the output of the model, The output of post
132
+ will be appended.
133
+
134
+ ```ruby
135
+ pre do
136
+ "Prepended output after cmd blocks have been run\n"
137
+ end
138
+
139
+ post do
140
+ "Appended output after cmd blocks have been run\n"
141
+ end
142
+ ```
143
+
96
144
  #### `comment`
97
145
 
98
146
  Called with a single string containing the string to prepend for comments in
@@ -161,6 +209,10 @@ Supports [monkey patching](#monkey-patching).
161
209
  Usually used inside `expect` or blocks passed to `post_login`/`pre_logout`.
162
210
  Takes a single parameter: a string to be sent to the device.
163
211
 
212
+ #### `cmd`
213
+ You can nest a `cmd` block inside first level blocks. It will be executed at
214
+ runtime.
215
+
164
216
  ### Monkey patching
165
217
 
166
218
  Several model blocks accept behavior-modifying arguments that make monkey
@@ -35,7 +35,7 @@
35
35
  | |FastIron |[fastiron](/lib/oxidized/model/fastiron.rb)
36
36
  | |IronWare |[ironware](/lib/oxidized/model/ironware.rb)
37
37
  | |NOS (Network Operating System)|[nos](/lib/oxidized/model/nos.rb)
38
- | |Vyatta |[vyatta](/lib/oxidized/model/vyatta.rb)
38
+ | |Vyatta |[vyatta](/lib/oxidized/model/vyatta.rb) | | Also used for Vyos <= 1.2.x, for newer versions use the VyOS model
39
39
  | |6910 |[br6910](/lib/oxidized/model/br6910.rb)
40
40
  | |SLX-OS |[slxos](/lib/oxidized/model/slxos.rb)
41
41
  |Calix |AXOS |[axos](/lib/oxidized/model/axos.rb)
@@ -146,6 +146,7 @@
146
146
  |OPNsense | |[opnsense](/lib/oxidized/model/opnsense.rb)
147
147
  |Palo Alto |PanOS API |[panos_api](/lib/oxidized/model/panos_api.rb) | |[PanOS_API](Model-Notes/PanOS_API.md)
148
148
  | |PanOS |[panos](/lib/oxidized/model/panos.rb)
149
+ |[Perle](https://www.perle.com)|IOLAN Console Servers|[perle](/lib/oxidized/model/perle.rb) |@robertcheramy
149
150
  |PLANET SG/SGS Switches| |[planet](/lib/oxidized/model/planet.rb)
150
151
  |pfSense | |[pfsense](/lib/oxidized/model/pfsense.rb)
151
152
  |Pure Storage |PurityOS |[purityos](/lib/oxidized/model/purityos.rb)
@@ -180,6 +181,8 @@
180
181
  |VMWare |NSX Edge (configuration) |[nsxconfig](/lib/oxidized/model/nsxconfig.rb)
181
182
  | |NSX Edge (firewall rules) |[nsxfirewall](/lib/oxidized/model/nsxfirewall.rb)
182
183
  | |NSX Distributed Firewall |[nsxdfw](/lib/oxidized/model/nsxdfw.rb)
184
+ |VYOS Networks |VYOS |[vyos](/lib/oxidized/model/vyos.rb)
185
+ | |Fork of Vyatta, tracking the supported versions (>= 1.4.x)
183
186
  |Watchguard |Fireware OS |[firewareos](/lib/oxidized/model/firewareos.rb)
184
187
  |Westell |Westell 8178G, Westell 8266G |[weos](/lib/oxidized/model/weos.rb)
185
188
  |Yadro |KornfeldOS |[kornfeldos](/lib/oxidized/model/kornfeldos.rb)
data/extra/oxidized.runit CHANGED
@@ -2,4 +2,4 @@
2
2
  [ ! -d /home/oxidized/.config/oxidized ] && mkdir -p /home/oxidized/.config/oxidized
3
3
  [ -f /home/oxidized/.config/oxidized/pid ] && rm /home/oxidized/.config/oxidized/pid
4
4
  chown -R oxidized:oxidized /home/oxidized/.config/oxidized
5
- exec setuser oxidized oxidized
5
+ exec gosu oxidized oxidized
data/lib/oxidized/core.rb CHANGED
@@ -40,7 +40,8 @@ module Oxidized
40
40
  '"extensions.oxidized-web" and remove "rest" from the configuration'
41
41
  )
42
42
  configuration = Oxidized.config.rest
43
- elsif Oxidized.config.extensions['oxidized-web'].load?
43
+ elsif Oxidized.config.extensions &&
44
+ Oxidized.config.extensions['oxidized-web']&.load?
44
45
  # This comment stops rubocop complaining about Style/IfUnlessModifier
45
46
  configuration = Oxidized.config.extensions['oxidized-web']
46
47
  end
@@ -48,8 +48,7 @@ module Oxidized
48
48
  private
49
49
 
50
50
  def get_http(path)
51
- schema = @secure ? "https://" : "http://"
52
- uri = URI("#{schema}#{@node.ip}#{path}")
51
+ uri = get_uri(path)
53
52
 
54
53
  logger.debug "Making request to: #{uri}"
55
54
 
@@ -93,5 +92,13 @@ module Oxidized
93
92
  def disconnect
94
93
  @log.close if Oxidized.config.input.debug?
95
94
  end
95
+
96
+ def get_uri(path)
97
+ path = URI.parse(path)
98
+ uri_class = @secure ? URI::HTTPS : URI::HTTP
99
+ uri_class.build(host: @node.ip,
100
+ path: path.path,
101
+ query: path.query)
102
+ end
96
103
  end
97
104
  end
@@ -34,7 +34,7 @@ module Oxidized
34
34
  verify_host_key: secure ? :always : :never,
35
35
  append_all_supported_algorithms: true,
36
36
  password: @node.auth[:password],
37
- timeout: Oxidized.config.timeout,
37
+ timeout: @node.timeout,
38
38
  port: (vars(:ssh_port) || 22).to_i,
39
39
  forward_agent: false
40
40
  }
@@ -53,7 +53,7 @@ module Oxidized
53
53
 
54
54
  def cmd(file)
55
55
  logger.debug "SCP: #{file} @ #{@node.name}"
56
- Timeout.timeout(Oxidized.config.timeout) do
56
+ Timeout.timeout(@node.timeout) do
57
57
  @ssh.scp.download!(file)
58
58
  end
59
59
  end
@@ -69,7 +69,7 @@ module Oxidized
69
69
  private
70
70
 
71
71
  def disconnect
72
- Timeout.timeout(Oxidized.config.timeout) do
72
+ Timeout.timeout(@node.timeout) do
73
73
  @ssh.close
74
74
  end
75
75
  rescue Timeout::Error
@@ -79,7 +79,7 @@ module Oxidized
79
79
  def disconnect
80
80
  disconnect_cli
81
81
  # if disconnect does not disconnect us, give up after timeout
82
- Timeout.timeout(Oxidized.config.timeout) { @ssh.loop }
82
+ Timeout.timeout(@node.timeout) { @ssh.loop }
83
83
  rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError => e
84
84
  logger.debug 'The other side closed the connection while ' \
85
85
  "disconnecting, raising #{e.class} with #{e.message}"
@@ -127,7 +127,7 @@ module Oxidized
127
127
  def expect(*regexps)
128
128
  regexps = [regexps].flatten
129
129
  logger.debug "Expecting #{regexps.inspect} at #{node.name}"
130
- Timeout.timeout(Oxidized.config.timeout) do
130
+ Timeout.timeout(@node.timeout) do
131
131
  @ssh.loop(0.1) do
132
132
  sleep 0.1
133
133
  match = regexps.find { |regexp| @output.match regexp }
@@ -146,7 +146,7 @@ module Oxidized
146
146
  verify_host_key: secure ? :always : :never,
147
147
  append_all_supported_algorithms: true,
148
148
  password: @node.auth[:password],
149
- timeout: Oxidized.config.timeout,
149
+ timeout: @node.timeout,
150
150
  port: (vars(:ssh_port) || 22).to_i,
151
151
  forward_agent: false
152
152
  }
@@ -9,7 +9,7 @@ module Oxidized
9
9
 
10
10
  def connect(node) # rubocop:disable Naming/PredicateMethod
11
11
  @node = node
12
- @timeout = Oxidized.config.timeout
12
+ @timeout = @node.timeout
13
13
  @node.model.cfg['telnet'].each { |cb| instance_exec(&cb) }
14
14
  @log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-telnet", 'w') if Oxidized.config.input.debug?
15
15
  port = vars(:telnet_port) || 23
@@ -84,7 +84,7 @@ module Net
84
84
  @log = @options["Log"]
85
85
 
86
86
  expects = [options[:expect]].flatten
87
- time_out = options[:timeout] || @options["Timeout"] || Oxidized.config.timeout?
87
+ time_out = options[:timeout] || @options["Timeout"]
88
88
 
89
89
  Timeout.timeout(time_out) do
90
90
  line = ""
@@ -44,7 +44,7 @@ class ADVA < Oxidized::Model
44
44
 
45
45
  cmd 'show ports' do |cfg|
46
46
  cfg.each_line do |line|
47
- port = line.match(/\|((access|network)[^\|]+)\|/)
47
+ port = line.match(/\|((access|network)[^|]+)\|/)
48
48
  ports << port if port
49
49
  end
50
50
  end
@@ -3,7 +3,7 @@ class Airfiber < Oxidized::Model
3
3
 
4
4
  # Ubiquiti Airfiber (tested with Airfiber 11FX)
5
5
 
6
- prompt /^AF[\w\.-]+#/i
6
+ prompt /^AF[\w.-]+#/i
7
7
 
8
8
  cmd :all do |cfg|
9
9
  cfg.cut_both
@@ -1,25 +1,13 @@
1
1
  class Aoscx < Oxidized::Model
2
2
  using Refinements
3
+ # HPE Aruba Networking - ArubaOS-CX models
3
4
 
4
- # previous command is repeated followed by "\eE", which sometimes ends up on last line
5
- # ssh switches prompt may start with \r, followed by the prompt itself, regex ([\w\s.-]+[#>] ), which ends the line
6
- # telnet switchs may start with various vt100 control characters, regex (\e\[24;[0-9][hH]), follwed by the prompt, followed
7
- # by at least 3 other vt100 characters
8
- prompt /(^\r|\e\[24;[0-9][hH])?([\w\s.-]+[#>] )($|(\e\[24;[0-9][0-9]?[hH]){3})/
5
+ prompt /^[\w\s.-]+[#>] $/
6
+ clean :escape_codes
9
7
 
10
8
  comment '! '
11
9
 
12
- # replace next line control sequence with a new line
13
- expect /(\e\[1M\e\[\??\d+(;\d+)*[A-Za-z]\e\[1L)|(\eE)/ do |data, re|
14
- data.gsub re, "\n"
15
- end
16
-
17
- # replace all used vt100 control sequences
18
- expect /\e\[\??\d+(;\d+)*[A-Za-z]/ do |data, re|
19
- data.gsub re, ''
20
- end
21
-
22
- expect /Press any key to continue(\e\[\??\d+(;\d+)*[A-Za-z])*$/ do
10
+ expect /Press any key to continue$/ do
23
11
  send ' '
24
12
  ""
25
13
  end
@@ -30,13 +18,7 @@ class Aoscx < Oxidized::Model
30
18
  end
31
19
 
32
20
  cmd :all do |cfg|
33
- cfg = cfg.cut_both
34
- cfg = cfg.gsub /^\r/, ''
35
- # Additional filtering for elder switches sending vt100 control chars via telnet
36
- cfg.gsub! /\e\[\??\d+(;\d+)*[A-Za-z]/, ''
37
- # Additional filtering for power usage reporting which obviously changes over time
38
- cfg.gsub! /^(.*AC [0-9]{3}V\/?([0-9]{3}V)?) *([0-9]{1,3}) (.*)/, '\\1 <removed> \\4'
39
- cfg
21
+ cfg.cut_both
40
22
  end
41
23
 
42
24
  cmd :secret do |cfg|
@@ -54,27 +36,30 @@ class Aoscx < Oxidized::Model
54
36
  end
55
37
 
56
38
  cmd 'show environment' do |cfg|
57
- cfg.gsub! /^(LC.*\s+)\d+\s+$/, '\\1<hidden>'
58
- cfg.gsub! /^(\d\/\d\/\d.*\s+)\d+\s+$/, '\\1<hidden>'
59
- cfg.gsub! /^(\d+\/?\S+\s+\S+\s+)\d+\.\d+\s+C\s+(.*)/, '\\1<hidden> \\2'
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>'
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>'
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"
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>'
66
- # match show environment power-consumption on 6400 or chassis switches, e.g. "1/4 line-card-module R0X39A 6400 48p 1GbE CL4 PoE 4SFP56 Mod 54 W"
67
- cfg.gsub! /^(\d+\/?\d*\s+.+\s+)(\s{1,4}\d{1,3})\sW\s*$/, '\\1<power>'
68
- # match show environment power-consumption on 6400 or chassis switches, e.g. "Module Total Power Usage 13000 W", match up to a 5-digit number and keep table formatting.
69
- cfg.gsub! /^(Module|Chassis)\s(Total\sPower\sUsage)(\s+)\s(\s{4}\d{1}|\s{3}\d{2}|\s{2}\d{3}|\s{1}\d{4}|\d{5})\sW\s*$/, '\\1 <power>'
70
- # match show environment power-consumption on 6400 or chassis switches, e.g. "Chassis Total Power Usage 13000 W", match up to a 5-digit number and keep table formatting.
71
- cfg.gsub! /^(Chassis\sTotal\sPower\sUsage)(\s+)(\s{4}\d{1}|\s{3}\d{2}|\s{2}\d{3}|\s{1}\d{4}|\d{5})\sW\s*$/, '\\1\\2<power>'
72
- # match show environment power-consumption on 8400 or chassis switches, up to a 5-digit number, example matches:
73
- # e.g. "Chassis Total Power Allocated (total of all max wattages) 4130 W"
74
- # e.g. "Chassis Total Power Unallocated 15860 W"
75
- cfg.gsub! /^(Chassis\sTotal\sPower\s)(Allocated|Unallocated)(\s|\s\(total of all max wattages\))(\s+)(\s{4}\d{1}|\s{3}\d{2}|\s{2}\d{3}|\s{1}\d{4}|\d{5})\sW\s*$/, '\\1\\2\\3\\4<power>'
76
- # match Total Power Consumption:
77
- cfg.gsub! /^([t|T]otal\s[p|P]ower\s[c|C]onsumption\s+)(\d+\.\d\d)$/, '\\1<power>'
39
+ def with_section(cfg, section, &block)
40
+ cfg.sub!(/(show environment #{section}.*?-{10,}\n)(.*?)(?=\nshow environment|\z)/m) do
41
+ header = ::Regexp.last_match(1)
42
+ content = ::Regexp.last_match(2)
43
+ block.call(content) if block_given?
44
+ header + content
45
+ end
46
+ end
47
+
48
+ with_section(cfg, 'fan') do |content|
49
+ content.gsub!(/^(.*)(slow|normal|medium|fast|max) (.*?)\d+ +$/, '\\1<speed> \\3<rpm>')
50
+ end
51
+
52
+ with_section(cfg, 'power-consumption') do |content|
53
+ content.gsub!(/^(.*?) (?:\d+\.\d+ +)+\d+\.\d+$/, '\\1 <power hidden>')
54
+ end
55
+
56
+ with_section(cfg, 'power-allocation') do |content|
57
+ content.gsub!(/^(.*) \d+ W$/, '\\1 <power>')
58
+ end
59
+
60
+ with_section(cfg, 'temperature') do |content|
61
+ content.gsub!(/^(.*) \d+\.\d+ C (.*)$/, '\\1 <hidden>\\2')
62
+ end
78
63
  comment cfg
79
64
  end
80
65
 
@@ -13,7 +13,7 @@ class AOSW < Oxidized::Model
13
13
 
14
14
  comment '# '
15
15
  # see /spec/model/aosw_spec.rb for prompt examples
16
- prompt /^\(?[\w\:.@-]+\)? ?[*^]?(\[[\w\/]+\] ?)?[#>] ?$/
16
+ prompt /^\(?[\w:.@-]+\)? ?[*^]?(\[[\w\/]+\] ?)?[#>] ?$/
17
17
 
18
18
  # Ignore cariage returns - also for the prompt
19
19
  expect "\r" do |data, re|
@@ -4,7 +4,7 @@ class ArubaInstant < Oxidized::Model
4
4
  # Aruba IAP, Instant Controller
5
5
 
6
6
  comment '# '
7
- prompt(/^ ?[\w\:.@-]+[#>] $/)
7
+ prompt(/^ ?[\w:.@-]+[#>] $/)
8
8
 
9
9
  cmd :all do |cfg|
10
10
  # Remove command echo and prompt
@@ -61,11 +61,23 @@ class ArubaInstant < Oxidized::Model
61
61
  cmd 'show aps' do |cfg|
62
62
  out = ''
63
63
  cfg.each_line do |line|
64
- out += if line.match?(/^Name/)
65
- line.sub(/^(Name +IP Address +).*(Type +IPv6 Address +).*(Serial #).*$/, '\1\2\3')
66
- else
67
- line.sub(/^(\S+ +\S+ +)(?:\S+ +){3}(\S+ +\S+ +)(?:\S+ +){2}(\S+) +.*$/, '\1\2\3')
68
- end
64
+ out += line.sub(
65
+ /^(?'Name'(?:.+?|-{2,})\s{2,}) # \s{2,} = separator between columns
66
+ (?'IPv4'(?:
67
+ IP\ Address|-{2,}| # Header
68
+ (?:\d+\.){3}\S+ # Match an IPv4 to catch AP-Names with two spaces
69
+ )\s{2,})
70
+ (?:(?:.+?|-{2,})\s{2,}){3} # Ignore Mode, Spectrum, Clients
71
+ (?'Type'(?:.+?|-{2,})\s{2,})
72
+ (?'IPv6'(?:.+?|-{2,})\s{2,})
73
+ (?:(?:.+?|-{2,})\s{2,}) # Ignore Mesh Role
74
+ (?'Zone'(?:.+?|-{2,})\s{2,})
75
+ (?'Serial'(?:.+?|-{2,}))
76
+ \s{2,} # Last separator
77
+ .*$ # Ignore the rest
78
+ /x,
79
+ '\k<Name>\k<IPv4>\k<Type>\k<IPv6>\k<Zone>\k<Serial>'
80
+ )
69
81
  end
70
82
  comment out + "\n"
71
83
  end
@@ -1,7 +1,7 @@
1
1
  class AsterNOS < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- prompt /^[^\$]+\$/
4
+ prompt /^[^$]+\$/
5
5
  comment '# '
6
6
 
7
7
  cmd :all do |cfg|
@@ -1,7 +1,7 @@
1
1
  class AxOS < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- prompt /(\x1b\[\?7h)?([\w.@()-]+[#]\s?)$/
4
+ prompt /(\x1b\[\?7h)?([\w.@()-]+\#\s?)$/
5
5
  comment '! '
6
6
 
7
7
  cmd 'show running-config | nomore' do |cfg|
@@ -35,7 +35,7 @@ class Comtrol < Oxidized::Model
35
35
  expect /[pP]assword:\s?$/
36
36
  send vars(:enable) + "\n"
37
37
  end
38
- expect /^.+[#]\s?$/
38
+ expect /^.+\#\s?$/
39
39
  end
40
40
  end
41
41
  pre_logout 'exit'
@@ -1,19 +1,14 @@
1
1
  class Cumulus < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- # Remove ANSI escape codes
5
- expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
6
- data.gsub re, ''
7
- end
8
-
9
- # The prompt contains ANSI escape codes, which have already been removed
10
- # from the expect call above
4
+ # Regular expression explanation:
11
5
  # ^ : match begin of line, to have the most specific prompt
12
6
  # [\w.-]+@[\w.-]+ : user@hostname
13
7
  # (:mgmt)? : optional when logged in out of band
14
8
  # :~[#$] $ : end of prompt, containing the linux path,
15
9
  # which is always "~" in our context
16
10
  prompt /^[\w.-]+@[\w.-]+(:mgmt)?:~[#$] $/
11
+ clean :escape_codes
17
12
  comment '# '
18
13
 
19
14
  # add a comment in the final conf
@@ -54,6 +54,11 @@ class EatonNetwork < Oxidized::Model
54
54
  json['features']['userAndSessionManagement']['data']['settings']['all']['1.0']['radius']['1.0']['settings']['connectivity']['primaryServer'].delete('secret')
55
55
  json['features']['userAndSessionManagement']['data']['settings']['all']['1.0']['radius']['1.0']['settings']['connectivity']['secondaryServer'].delete('secret')
56
56
 
57
+ # Added in frimware v2.2.0
58
+ json['features']['peripherals']['data']['dmeData']['ethernet']['ports'].each do |n|
59
+ n.dig('dot1x', 'peap', 'password') && n['dot1x']['peap'].delete('password')
60
+ end
61
+
57
62
  cfg = JSON.pretty_generate(json)
58
63
  cfg
59
64
  end
@@ -3,7 +3,7 @@ class Eltex < Oxidized::Model
3
3
 
4
4
  # Tested with MES2324FB Version: 4.0.7.1 Build: 37 (master)
5
5
 
6
- prompt /^\s?[\w.@\(\)-]+[#>]\s?$/
6
+ prompt /^\s?[\w.@()-]+[#>]\s?$/
7
7
  comment '! '
8
8
 
9
9
  cmd :all do |cfg|
@@ -5,7 +5,7 @@ class Enterasys800 < Oxidized::Model
5
5
  # Tested with 08H20G4-24 Fast Ethernet Switch Firmware: Build 01.01.01.0017
6
6
  comment '# '
7
7
 
8
- prompt /([\w \(:.@-]+[#>]\s?)$/
8
+ prompt /([\w (:.@-]+[#>]\s?)$/
9
9
 
10
10
  cfg :telnet do
11
11
  username /UserName:/
@@ -4,7 +4,7 @@ class FabricOS < Oxidized::Model
4
4
  # Brocade Fabric OS model #
5
5
  ## FIXME: Only ssh exec mode support, no telnet, no ssh screenscraping
6
6
 
7
- prompt /^([\w]+:+[\w]+[>]\s)$/
7
+ prompt /^(\w+:+\w+>\s)$/
8
8
  comment '# '
9
9
 
10
10
  cmd 'chassisShow' do |cfg|
@@ -41,7 +41,7 @@ class FSOS < Oxidized::Model
41
41
  cfg :telnet, :ssh do
42
42
  post_login 'enable'
43
43
  post_login 'terminal length 0'
44
- post_login 'terminal width 512'
44
+ post_login 'terminal width 0'
45
45
  pre_logout 'exit'
46
46
  pre_logout 'exit'
47
47
  end
@@ -4,13 +4,8 @@ class Garderos < Oxidized::Model
4
4
  # Routers for harsh environments
5
5
  # grs = Garderos Router Software
6
6
 
7
- # Remove ANSI escape codes
8
- expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
9
- data.gsub re, ''
10
- end
11
-
12
- # the prompt does not need to match escape codes, as they have been removed above
13
7
  prompt /[\w-]+# /
8
+ clean :escape_codes
14
9
  comment '# '
15
10
 
16
11
  cmd :all do |cfg|
@@ -36,7 +36,7 @@ class IronWare < Oxidized::Model
36
36
  cfg.gsub! /current speed is [A-Z-]{2,6} \(\d{2,3}%\)/, ''
37
37
  cfg.gsub! /Fan \d* - STATUS: OK \D*\d*./, '' # Fix for ADX Fan speed reporting
38
38
  cfg.gsub! /\d* deg C/, '' # Fix for ADX temperature reporting
39
- cfg.gsub! /([\[]*)1([\]]*)<->([\[]*)2([\]]*)(<->([\[]*)3([\]]*))*/, ''
39
+ cfg.gsub! /(\[*)1(\]*)<->(\[*)2(\]*)(<->(\[*)3(\]*))*/, ''
40
40
  cfg.gsub! /\d+\.\d deg-C/, 'XX.X deg-C'
41
41
  if cfg.include? "TEMPERATURE"
42
42
  sc = StringScanner.new cfg