oxidized 0.31.0 → 0.32.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -3
  3. data/.rubocop.yml +1 -2
  4. data/.rubocop_todo.yml +6 -6
  5. data/CHANGELOG.md +32 -0
  6. data/Dockerfile +5 -2
  7. data/Rakefile +28 -0
  8. data/docs/Configuration.md +14 -2
  9. data/docs/Creating-Models.md +52 -22
  10. data/docs/DeviceSimulation.md +184 -0
  11. data/docs/Hooks.md +5 -5
  12. data/docs/Issues.md +15 -9
  13. data/docs/Model-Notes/APC_AOS.md +29 -16
  14. data/docs/Model-Notes/FSOS.md +1 -0
  15. data/docs/ModelUnitTests.md +186 -0
  16. data/docs/Supported-OS-Types.md +3 -2
  17. data/examples/podman-compose/Makefile +1 -2
  18. data/{examples/device-simulation → extra}/device2yaml.rb +32 -12
  19. data/extra/gitdiff-msteams.sh +32 -5
  20. data/extra/nagios_check_failing_nodes.rb +1 -1
  21. data/extra/rest_client.rb +1 -1
  22. data/lib/oxidized/config.rb +1 -1
  23. data/lib/oxidized/input/ssh.rb +13 -5
  24. data/lib/oxidized/model/aos7.rb +2 -0
  25. data/lib/oxidized/model/aosw.rb +1 -1
  26. data/lib/oxidized/model/apc_aos.rb +1 -1
  27. data/lib/oxidized/model/arubainstant.rb +1 -1
  28. data/lib/oxidized/model/asa.rb +2 -1
  29. data/lib/oxidized/model/asyncos.rb +1 -1
  30. data/lib/oxidized/model/cumulus.rb +16 -2
  31. data/lib/oxidized/model/enterprise_sonic.rb +46 -0
  32. data/lib/oxidized/model/fsos.rb +5 -1
  33. data/lib/oxidized/model/garderos.rb +4 -4
  34. data/lib/oxidized/model/junos.rb +1 -1
  35. data/lib/oxidized/model/kornfeldos.rb +33 -0
  36. data/lib/oxidized/model/model.rb +2 -2
  37. data/lib/oxidized/model/sonicos.rb +8 -2
  38. data/lib/oxidized/model/tplink.rb +1 -0
  39. data/lib/oxidized/model/xos.rb +1 -1
  40. data/lib/oxidized/source/source.rb +32 -2
  41. data/lib/oxidized/version.rb +2 -2
  42. data/oxidized.gemspec +7 -6
  43. metadata +33 -35
  44. data/examples/device-simulation/README.md +0 -173
  45. data/examples/device-simulation/cmdsets/aoscx +0 -9
  46. data/examples/device-simulation/cmdsets/arubainstant +0 -5
  47. data/examples/device-simulation/cmdsets/asa +0 -7
  48. data/examples/device-simulation/cmdsets/ios +0 -7
  49. data/examples/device-simulation/cmdsets/nxos +0 -5
  50. data/examples/device-simulation/cmdsets/routeros +0 -5
  51. data/examples/device-simulation/cmdsets/srosmd +0 -11
  52. data/examples/device-simulation/yaml/aoscx_R0X25A-6410_FL.10.10.1100.yaml +0 -2281
  53. data/examples/device-simulation/yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml +0 -451
  54. data/examples/device-simulation/yaml/arubainstant_IAP515_8.10.0.6_VWLC.yaml +0 -213
  55. data/examples/device-simulation/yaml/asa_5512_9.12-4-67_single-context.yaml +0 -531
  56. data/examples/device-simulation/yaml/asr920_16.8.1b.yaml +0 -1122
  57. data/examples/device-simulation/yaml/garderos_R7709_003_006_068.yaml +0 -101
  58. data/examples/device-simulation/yaml/iosxe_C9200L-24P-4G_17.09.04a.yaml +0 -514
  59. data/examples/device-simulation/yaml/iosxe_C9800-L-F-K9_17.06.05.yaml +0 -417
  60. data/examples/device-simulation/yaml/riverbed_915.yaml +0 -123
  61. data/examples/device-simulation/yaml/routeros_CHR_7.10.1.yaml +0 -145
  62. data/examples/device-simulation/yaml/routeros_CHR_7.16.yaml +0 -79
  63. data/examples/device-simulation/yaml/routeros_L009UiGS_7.15.2.yaml +0 -353
@@ -7,6 +7,7 @@ This has been tested against the following models and OS versions
7
7
  |S3400-48T4SP |Version 2.0.2J Build 81736 |
8
8
  |S3400-48T4SP |Version 2.0.2J Build 95262 |
9
9
  |S3400-48T6SP |Version 2.2.0F Build 109661 |
10
+ |S3400-48T4SP |Version 2.0.2J Build 120538 |
10
11
  |S3410-24TS-P |S3410_FSOS 11.4(1)B74S5 |
11
12
  |S5850-48T4Q |Version 7.0.4.34 |
12
13
  |S5800-48MBQ |Version 7.0.4.21 |
@@ -0,0 +1,186 @@
1
+ # Model Unit Tests
2
+ Oxidized includes automated unit tests for its models, which require very little
3
+ effort to use. There are three different default unit tests for models:
4
+ - [Device Simulation](ModelUnitTests.md#device-simulation)
5
+ - [Device Prompt](ModelUnitTests.md#device-prompt)
6
+ - [Secrets](ModelUnitTests.md#secrets)
7
+
8
+ You only need to provide test files under [/spec/model/data](/spec/model/data),
9
+ and the tests will be run automatically with `rake test`. See
10
+ [CONTRIBUTING.md](/CONTRIBUTING.md) for explanations on how to set up a
11
+ development environment. In the following examples, we use
12
+ [Bundler](https://bundler.io/) and prefix all commands with `bundle exec`.
13
+
14
+ In addition, you can write [custom unit tests](ModelUnitTests.md#custom-tests)
15
+ for your model
16
+
17
+ ## Device Simulation
18
+ ### YAML Simulation File
19
+ You need a [YAML simulation file](/docs/DeviceSimulation.md) for your device.
20
+ See the link for instructions on how to produce it.
21
+
22
+ The YAML simulation files are stored under
23
+ [/spec/model/data/](/spec/model/data/), with the naming convention
24
+ `<model>:<description>:simulation.yaml`, where `<model>` is the lowercase name
25
+ of the Oxidized model and `<description>` is the name of the test case.
26
+ `<description>` is generally formatted as `<hardware>_<software>` or
27
+ `<hardware>_<software>_<information>`.
28
+
29
+ Using a correct name for the file is important to ensure it is included in
30
+ automatic model unit tests.
31
+
32
+ ### Expected Output
33
+ You need a second file that contains the expected output, which has the same
34
+ name as the YAML simulation file but ends with `:output.txt` instead of
35
+ `:simulation.yaml`.
36
+
37
+ You can automatically produce an output file based on the current model for all
38
+ YAML simulation files missing an `:output.txt`:
39
+ ```shell
40
+ bundle exec ruby spec/model/atoms_generate.rb
41
+ ```
42
+
43
+ In the following example,
44
+ `spec/model/data/aoscx:R8N85A-C6000-48G-CL4_PL.10.08.1010:output.txt` (the
45
+ second file in the list) was missing:
46
+
47
+ ```shell
48
+ oxidized$ bundle exec ruby spec/model/atoms_generate.rb
49
+ Run options: --seed 57811
50
+
51
+ # Running:
52
+
53
+ Generating output file for aoscx:R0X25A-6410_FL.10.10.1100:simulation... SKIP, output already exists
54
+ Generating output file for aoscx:R8N85A-C6000-48G-CL4_PL.10.08.1010:simulation... OK
55
+ Generating output file for arubainstant:IAP515_8.10.0.6_VWLC:simulation... SKIP, output already exists
56
+ Generating output file for asa:5512_9.12-4-67_single-context:simulation... SKIP, output already exists
57
+ Generating output file for garderos:R7709_003_006_068:simulation... SKIP, output already exists
58
+ Generating output file for ios:C8200L_16.12.1:simulation... FAIL, no simulation file
59
+ Generating output file for ios:C9200L-24P-4G_17.09.04a:simulation... SKIP, output already exists
60
+ Generating output file for ios:C9800-L-F-K9_17.06.05:simulation... SKIP, output already exists
61
+ Generating output file for ios:asr920_16.8.1b:simulation... SKIP, output already exists
62
+ Generating output file for junos:srx300_22.4:simulation... SKIP, output already exists
63
+ Generating output file for opnsense:nano_23.7:simulation... SKIP, output already exists
64
+ Generating output file for pfsense:CE_2.7.2:simulation... SKIP, output already exists
65
+ Generating output file for routeros:CHR_7.10.1:simulation... SKIP, output already exists
66
+ Generating output file for routeros:CHR_7.16:simulation... SKIP, output already exists
67
+ Generating output file for routeros:L009UiGS_7.15.2:simulation... SKIP, output already exists
68
+ .
69
+
70
+ Finished in 0.904792s, 1.1052 runs/s, 0.0000 assertions/s.
71
+
72
+ 1 runs, 0 assertions, 0 failures, 0 errors, 0 skips
73
+ Coverage report generated for RSpec to /home/xxx/oxidized/coverage/coverage.xml. 651 / 1122 LOC (58.02%) covered
74
+ Coverage report generated for RSpec to /home/xxx/oxidized/coverage.
75
+ Line Coverage: 58.02% (651 / 1122)
76
+ ```
77
+
78
+ ### Running the Tests
79
+ You can modify the `:output.txt` file to match your expectations and modify the
80
+ model accordingly. Run `bundle exec rake` to run the tests.
81
+
82
+ Here is an example when the output of the VTP command is missing in the expected
83
+ output:
84
+
85
+ ```
86
+ oxidized$ bundle exec rake test
87
+ /usr/bin/ruby3.1 -I"lib:spec" /home/xxx/oxidized/vendor/bundle/ruby/3.1.0/gems/rake-13.2.1/lib/rake/rake_test_loader.rb "spec/cli_spec.rb" "spec/config_spec.rb" "spec/hook/githubrepo_spec.rb" "spec/input/ssh_spec.rb" "spec/manager_spec.rb" "spec/model/apc_aos_spec.rb" "spec/model/model_atoms_spec.rb" "spec/model/model_helper_spec.rb" "spec/node_spec.rb" "spec/nodes_spec.rb" "spec/output/file_spec.rb" "spec/output/git_spec.rb" "spec/refinements_spec.rb" "spec/source/csv_spec.rb" "spec/source/http_spec.rb" "spec/source/jsonfile_spec.rb" "spec/source/sql_spec.rb"
88
+ Run options: --seed 31447
89
+
90
+ # Running:
91
+
92
+ ...............................................................SS..................F.............................SS..
93
+
94
+ Finished in 7.963602s, 14.6918 runs/s, 48.7217 assertions/s.
95
+
96
+ 1) Failure:
97
+ ATOMS tests#test_0006_ios:C9200L-24P-4G_17.09.04a:output has expected output [spec/model/model_atoms_spec.rb:12]:
98
+ --- expected
99
+ +++ actual
100
+ @@ -9,6 +9,21 @@
101
+ ! CPU: ARM64
102
+ ! Memory: nvram 2048K
103
+ !
104
+ +! VTP: VTP Version capable : 1 to 3
105
+ +! VTP: VTP version running : 1
106
+ +! VTP: VTP Domain Name : Oxidized
107
+ +! VTP: VTP Pruning Mode : Disabled (Operationally Disabled)
108
+ +! VTP: VTP Traps Generation : Disabled
109
+ +! VTP: Device ID : 40f0.7800.0000
110
+ +! VTP: Feature VLAN:
111
+ +! VTP: --------------
112
+ +! VTP: VTP Operating Mode : Transparent
113
+ +! VTP: Maximum VLANs supported locally : 1005
114
+ +! VTP: Number of existing VLANs : 10
115
+ +! VTP: Configuration Revision : 0
116
+ +! VTP: MD5 digest : 0x35 0x00 0x00 0x00 0x00 0x00 0x7F 0xB4
117
+ +! VTP: 0x07 0x00 0x00 0x00 0x00 0x00 0x09 0x6D
118
+ +!
119
+ ! NAME: \"c92xxL Stack\", DESCR: \"c92xxL Stack\"
120
+ ! PID: C9200L-24P-4G , VID: V01 , SN: JAE24FFFFFF
121
+ !
122
+
123
+
124
+ 117 runs, 388 assertions, 1 failures, 0 errors, 4 skips
125
+
126
+ You have skipped tests. Run with --verbose for details.
127
+ Coverage report generated for RSpec to /home/xxx/oxidized/coverage/coverage.xml. 2167 / 3131 LOC (69.21%) covered
128
+ Coverage report generated for RSpec to /home/xxx/oxidized/coverage.
129
+ Line Coverage: 69.21% (2167 / 3131)
130
+ rake aborted!
131
+ Command failed with status (1): [ruby -I"lib:spec" /home/xxx/oxidized/vendor/bundle/ruby/3.1.0/gems/rake-13.2.1/lib/rake/rake_test_loader.rb "spec/cli_spec.rb" "spec/config_spec.rb" "spec/hook/githubrepo_spec.rb" "spec/input/ssh_spec.rb" "spec/manager_spec.rb" "spec/model/apc_aos_spec.rb" "spec/model/model_atoms_spec.rb" "spec/model/model_helper_spec.rb" "spec/node_spec.rb" "spec/nodes_spec.rb" "spec/output/file_spec.rb" "spec/output/git_spec.rb" "spec/refinements_spec.rb" "spec/source/csv_spec.rb" "spec/source/http_spec.rb" "spec/source/jsonfile_spec.rb" "spec/source/sql_spec.rb" ]
132
+ /home/xxx/oxidized/vendor/bundle/ruby/3.1.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
133
+ Tasks: TOP => test
134
+ (See full trace by running task with --trace)
135
+ ```
136
+
137
+ If you want to be sure that your model has been tested, run
138
+ `bundle exec rake test TESTOPTS="--verbose"` and search for your models unter
139
+ `ATOMS tests`
140
+
141
+ ## Device Prompt
142
+ You can specify device prompts to test in a YAML file named
143
+ `spec/model/data/<model>:generic:prompt.yaml`.
144
+
145
+ The YAML file has three sections containing a list of prompts to test:
146
+ - pass: these prompts will pass the prompt regexp.
147
+ - pass_with_expect: these prompts will pass the prompt regexp after having been
148
+ cleaned by the expect commands.
149
+ - fail: these prompts will fail the prompt regexp.
150
+
151
+ Here is an example:
152
+ ```yaml
153
+ pass:
154
+ - "LAB-R1234_Garderos# "
155
+ pass_with_expect:
156
+ - "\e[4m\rLAB-R1234_Garderos#\e[m "
157
+ fail:
158
+ - "\e[4m\rLAB-R1234_Garderos#\e[m "
159
+ - "#LAB#"
160
+ ```
161
+
162
+ ## Secrets
163
+ You can test if the model effectively removes secrets from your YAML simulation
164
+ file with a YAML file named like the YAML simulation, but with the suffix
165
+ `:secret.yaml`.
166
+
167
+ The YAML file has two sections containing a list of strings to test:
168
+ - fail: the test will fail if the output contains these strings.
169
+ - pass: the test will pass only if the output contains these strings.
170
+
171
+ ```yaml
172
+ fail:
173
+ - 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCC'
174
+ pass:
175
+ - 'snmp-server host 10.10.42.12 version 2c <secret removed> inform'
176
+ - 'hash-mgmt-user oxidized password hash <secret removed>'
177
+ - 'hash-mgmt-user rocks password hash <secret removed> usertype read-only'
178
+ ```
179
+
180
+ ## Custom tests
181
+ When you write custom tests for your models, please do not use the filenames
182
+ mentioned above, as it will interfere with the standard tests. If you need to
183
+ store a custom simulation file, use `model:description:custom_simulation.yaml`.
184
+
185
+ The [cumulus test](/spec/model/cumulus_spec.rb) is an example of a custom
186
+ test.
@@ -8,8 +8,8 @@
8
8
  |AddPack |AddPack |[addpack](/lib/oxidized/model/addpack.rb)
9
9
  |Adtran |Total Access (AOS) |[adtran](/lib/oxidized/model/adtran.rb)
10
10
  | |ADVA |[adva](/lib/oxidized/model/adva.rb) | |[ADVA](Model-Notes/ADVA.md)
11
- |Alcatel-Lucent |AOS |[aos](/lib/oxidized/model/aos.rb)
12
- | |AOS7 |[aos7](/lib/oxidized/model/aos7.rb)
11
+ |Alcatel-Lucent |AOS |[aos](/lib/oxidized/model/aos.rb) | |AOS6 - vxworks-based
12
+ | |AOS7 |[aos7](/lib/oxidized/model/aos7.rb) | |AOS7 and AOS8 - linux-based
13
13
  | |ISAM |[isam](/lib/oxidized/model/isam.rb)
14
14
  | |SR OS (Formerly TiMOS) |[sros](/lib/oxidized/model/sros.rb)
15
15
  | |Wireless |[aosw](/lib/oxidized/model/aosw.rb) | |Same model as Aruba Wireless
@@ -175,6 +175,7 @@
175
175
  | |NSX Distributed Firewall |[nsxdfw](/lib/oxidized/model/nsxdfw.rb)
176
176
  |Watchguard |Fireware OS |[firewareos](/lib/oxidized/model/firewareos.rb)
177
177
  |Westell |Westell 8178G, Westell 8266G |[weos](/lib/oxidized/model/weos.rb)
178
+ |Yadro |KornfeldOS |[kornfeldos](/lib/oxidized/model/kornfeldos.rb)
178
179
  |YAMAHA |YAMAHA NVR/RTX Series |[yamaha](/lib/oxidized/model/yamaha.rb)
179
180
  |Zhone |Zhone (OLT and MX) |[zhoneolt](/lib/oxidized/model/zhoneolt.rb)
180
181
  |ZPE |Nodegrid OS |[nodegrid](/lib/oxidized/model/nodegrid.rb)
@@ -71,8 +71,7 @@ images: model-image gitserver-image oxidized-image
71
71
 
72
72
  # build the oxidized image from the curent repository
73
73
  oxidized-image:
74
- podman image exists local/oxidized || \
75
- podman build -t local/oxidized ../../
74
+ podman build -t oxidized:`git describe --tags` -t oxidized:latest ../../
76
75
 
77
76
  # removes the oxidized image
78
77
  oxidized-image-clean:
@@ -8,6 +8,7 @@ require 'timeout'
8
8
 
9
9
  # This scripts logs in a network device and outputs a yaml file that can be
10
10
  # used for model unit tests in spec/model/
11
+ # For more information, see docs/DeviceSimulation.md
11
12
 
12
13
  # This script is quick & dirty - it grew with the time an could be a project
13
14
  # for its own. It works, and that should be enough ;-)
@@ -113,15 +114,29 @@ end
113
114
  # Define options
114
115
  options = {}
115
116
  optparse = OptionParser.new do |opts|
116
- opts.banner = "Usage: device2yaml.rb [user@]host [options]"
117
+ opts.banner = <<~HEREDOC
118
+ Usages:
119
+ - device2yaml.rb [user@]host -i file [options]
120
+ - device2yaml.rb [user@]host -c "command1
121
+ command2
122
+ command3" [options]
117
123
 
118
- opts.on('-c', '--cmdset file', 'Mandatory: specify the commands to be run') do |file|
119
- options[:cmdset] = file
124
+ -i and -c are mutualy exclusive, one must be specified
125
+
126
+ [options]:
127
+ HEREDOC
128
+
129
+ opts.on('-c', '--commands "command list"', 'specify the commands to be run') do |cmds|
130
+ options[:commands] = cmds
131
+ end
132
+ opts.on('-i', '--input file', 'Specify an input file for commands to be run') do |file|
133
+ options[:input] = file
120
134
  end
121
135
  opts.on('-o', '--output file', 'Specify an output YAML-file') do |file|
122
136
  options[:output] = file
123
137
  end
124
- opts.on('-t', '--timeout value', Integer, 'Specify the idle timeout beween commands (default: 5 seconds)') do |timeout|
138
+ opts.on('-t', '--timeout value', Integer,
139
+ 'Specify the idle timeout beween commands (default: 5 seconds)') do |timeout|
125
140
  options[:timeout] = timeout
126
141
  end
127
142
  opts.on('-e', '--exec-mode', 'Run ssh in exec mode (without tty)') { @exec_mode = true }
@@ -151,14 +166,22 @@ end
151
166
  optparse.parse!
152
167
 
153
168
  # Get the commands to be run against ssh_host
154
- unless options[:cmdset]
155
- puts 'Missing a command set, use option -c'
169
+ # ^ = xor = exclusive or
170
+ unless options[:commands].nil? ^ options[:input].nil?
171
+ puts "Please provide commands to be run against #{ssh_host} with either option -c or -i"
156
172
  puts
157
173
  puts optparse
158
174
  exit 1
159
175
  end
160
- # make an array of commands to send, ignore empty lines
161
- ssh_commands = File.read(options[:cmdset]).split(/\n+|\r+/)
176
+
177
+ if options[:commands]
178
+ ssh_commands = []
179
+ options[:commands].each_line(chomp: true) { |command| ssh_commands << command }
180
+ elsif options[:input]
181
+ ssh_commands = File.read(options[:input]).split(/\n+|\r+/)
182
+ end
183
+
184
+ puts "Running #{ssh_commands} on #{ssh_user}@#{ssh_host}"
162
185
 
163
186
  # Defaut idle timeout: 5 seconds, as tests showed that 2 seconds is too short
164
187
  @idle_timeout = options[:timeout] || 5
@@ -209,7 +232,7 @@ else
209
232
  yaml_output ' '
210
233
  end
211
234
 
212
- @output&.puts "commands:"
235
+ @output&.puts 'commands:'
213
236
 
214
237
  begin
215
238
  ssh_commands.each do |cmd|
@@ -219,7 +242,4 @@ rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError => e
219
242
  puts "### Connection closed with message: #{e.message}"
220
243
  end
221
244
 
222
- @output&.puts 'oxidized_output: |'
223
- @output&.puts ' !! needs to be written by hand or copy & paste from model output'
224
-
225
245
  cleanup
@@ -15,12 +15,31 @@
15
15
  # timeout: 120
16
16
  #
17
17
  # Add webhook to your MS Teams channel and set the next variable to the full url
18
+ # If INCLUDE_GITHUB_LINK is set to true, there will be a button that links to GITURL in the bottom of each teams post. the commit id is added at the end of the url.
19
+ # MAXSIZE is set to respect the 28 KB limit for teams webhooks, but you might need to change it if you modify the Adaptive Card
18
20
 
19
21
  weburl="https://contoso.webhook.office.com/webhookb2/etc etc etc"
22
+ GITURL="https://github.example.com/My-org/oxidized/commit/"
23
+ INCLUDE_GITHUB_LINK=false
24
+ # Max size for summary text.
25
+ MAXSIZE=24500
26
+
27
+ if [ "$INCLUDE_GITHUB_LINK" = true ]; then
28
+ github_action=",
29
+ { \"type\": \"ActionSet\",
30
+ \"actions\":
31
+ [
32
+ {
33
+ \"type\": \"Action.OpenUrl\",
34
+ \"title\": \"Click to see diff in github\",
35
+ \"url\": \"${GITURL}${OX_REPO_COMMITREF}\"
36
+ }
37
+ ]
38
+ }"
39
+ fi
20
40
 
21
41
  postdata()
22
42
  {
23
- COMMIT=$(git --bare --git-dir="${OX_REPO_NAME}" show --pretty='' --no-color "${OX_REPO_COMMITREF}" | jq --raw-input --slurp --compact-output)
24
43
  cat <<EOF
25
44
  {
26
45
  "type":"message",
@@ -77,7 +96,7 @@ postdata()
77
96
  "size": "small"
78
97
  }
79
98
  ]
80
- }
99
+ }${github_action}
81
100
  ]
82
101
  }
83
102
  }
@@ -86,6 +105,14 @@ postdata()
86
105
  EOF
87
106
  }
88
107
 
89
- curl -i \
90
- -H "Content-Type: application/json" \
91
- -X POST --data "$(postdata)" "${weburl}"
108
+ COMMIT=$(git --bare --git-dir="${OX_REPO_NAME}" show --pretty='' --no-color "${OX_REPO_COMMITREF}" | jq --raw-input --slurp --compact-output)
109
+ URL=""
110
+
111
+ size=$(postdata | wc -c)
112
+ if [ "$size" -gt "$MAXSIZE" ]; then
113
+ COMMIT=$(git --bare --git-dir="${OX_REPO_NAME}" show --pretty='' --no-color "${OX_REPO_COMMITREF}" | head -c $MAXSIZE)
114
+ COMMIT+="$NEWLINE...$NEWLINE Shortened because of length"
115
+ COMMIT=$(echo "${COMMIT}" | jq --raw-input --slurp --compact-output )
116
+ fi
117
+
118
+ curl -i -H "Content-Type: application/json" -X POST --data "$(postdata)" "${weburl}"
@@ -10,7 +10,7 @@ pending = false
10
10
  critical_nodes = []
11
11
  pending_nodes = []
12
12
 
13
- json = JSON.parse(open("http://localhost:8888/nodes.json").read)
13
+ json = JSON.parse(URI("http://localhost:8888/nodes.json").open(&:read))
14
14
  json.each do |node|
15
15
  next if !ARGV.empty? && (ARGV[0] != node['name'])
16
16
 
data/extra/rest_client.rb CHANGED
@@ -6,7 +6,7 @@ module Oxidized
6
6
  require 'asetus'
7
7
 
8
8
  class Config
9
- Root = Root = ENV['OXIDIZED_HOME'] || File.join(Dir.home, '.config', 'oxidized')
9
+ Root = ENV['OXIDIZED_HOME'] || File.join(Dir.home, '.config', 'oxidized')
10
10
  end
11
11
 
12
12
  CFGS = Asetus.new name: 'oxidized', load: false, key_to_s: true
@@ -19,7 +19,7 @@ module Oxidized
19
19
  cfgfile = cmd_opts[:config_file] || 'config'
20
20
  # configuration file with full path as a class instance variable
21
21
  @configfile = File.join(usrdir, cfgfile)
22
- asetus = Asetus.new(name: 'oxidized', load: false, key_to_s: true, usrdir: usrdir, cfgfile: cfgfile)
22
+ asetus = Asetus.new(name: 'oxidized', load: false, usrdir: usrdir, cfgfile: cfgfile)
23
23
  Oxidized.asetus = asetus
24
24
 
25
25
  asetus.default.username = 'username'
@@ -18,10 +18,14 @@ module Oxidized
18
18
 
19
19
  def connect(node)
20
20
  @node = node
21
- @output = ''
21
+ @output = String.new('')
22
22
  @pty_options = { term: "vt100" }
23
23
  @node.model.cfg['ssh'].each { |cb| instance_exec(&cb) }
24
- @log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug?
24
+ if Oxidized.config.input.debug?
25
+ logfile = Oxidized::Config::LOG + "/#{@node.ip}-ssh"
26
+ @log = File.open(logfile, 'w')
27
+ Oxidized.logger.debug "lib/oxidized/input/ssh.rb: I/O Debuging to #{logfile}"
28
+ end
25
29
 
26
30
  Oxidized.logger.debug "lib/oxidized/input/ssh.rb: Connecting to #{@node.name}"
27
31
  @ssh = Net::SSH.start(@node.ip, @node.auth[:username], make_ssh_opts)
@@ -41,7 +45,11 @@ module Oxidized
41
45
  end
42
46
 
43
47
  def cmd(cmd, expect = node.prompt)
44
- Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd} @ #{node.name} with expect: #{expect.inspect}"
48
+ Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd.dump} @ #{node.name} with expect: #{expect.inspect}"
49
+ if Oxidized.config.input.debug?
50
+ @log.puts "sent #{cmd.dump}"
51
+ @log.flush
52
+ end
45
53
  cmd_output = if @exec
46
54
  @ssh.exec! cmd
47
55
  else
@@ -78,7 +86,7 @@ module Oxidized
78
86
  @ses = ssh.open_channel do |ch|
79
87
  ch.on_data do |_ch, data|
80
88
  if Oxidized.config.input.debug?
81
- @log.print data
89
+ @log.puts "received #{data.dump}"
82
90
  @log.flush
83
91
  end
84
92
  @output << data
@@ -101,7 +109,7 @@ module Oxidized
101
109
  end
102
110
 
103
111
  def cmd_shell(cmd, expect_re)
104
- @output = ''
112
+ @output = String.new('')
105
113
  @ses.send_data cmd + "\n"
106
114
  @ses.process
107
115
  expect expect_re if expect_re
@@ -4,6 +4,8 @@ class AOS7 < Oxidized::Model
4
4
  # Alcatel-Lucent Operating System Version 7 (Linux based)
5
5
  # used in OmniSwitch 6900/10k
6
6
 
7
+ prompt /^([\w.@-]+ ?[#>]\s?)$/
8
+
7
9
  comment '! '
8
10
 
9
11
  cmd :all do |cfg, cmdstring|
@@ -117,7 +117,7 @@ class AOSW < Oxidized::Model
117
117
  next if line =~ /Output \d Config/i
118
118
  next if line =~ /(Tachometers|Temperatures|Voltages)/
119
119
  next if line =~ /((Card|CPU) Temperature|Chassis Fan|VMON1[0-9])/
120
- next if line =~ /[0-9]+\s+(RPMS?|m?V|C)/i
120
+ next if line =~ /[0-9]+\s+(RPMS?|m?V|C|W)/i
121
121
 
122
122
  out << line.strip
123
123
  end
@@ -6,6 +6,6 @@ class Apc_aos < Oxidized::Model # rubocop:disable Naming/ClassAndModuleCamelCase
6
6
  cfg
7
7
  end
8
8
 
9
- cfg :ftp do
9
+ cfg :ftp, :scp do
10
10
  end
11
11
  end
@@ -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
@@ -15,7 +15,7 @@ class ASA < Oxidized::Model
15
15
  cfg.gsub! /enable password (\S+) (.*)/, 'enable password <secret hidden> \2'
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
- cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key) (\S+)/, '\1 <secret hidden>'
18
+ cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key( hex)?) (\S+)/, '\1 <secret hidden>'
19
19
  cfg.gsub! /^(aaa-server TACACS\+? \(\S+\) host[^\n]*\n(\s+[^\n]+\n)*\skey) \S+$/mi, '\1 <secret hidden>'
20
20
  cfg.gsub! /^(aaa-server \S+ \(\S+\) host[^\n]*\n(\s+[^\n]+\n)*\s+key) \S+$/mi, '\1 <secret hidden>'
21
21
  cfg.gsub! /ldap-login-password (\S+)/, 'ldap-login-password <secret hidden>'
@@ -38,6 +38,7 @@ class ASA < Oxidized::Model
38
38
  cfg = cfg.join
39
39
  cfg.gsub! /^Configuration has not been modified since last system restart.*\n/, ''
40
40
  cfg.gsub! /^Configuration last modified by.*\n/, ''
41
+ cfg.gsub! /^Start-up time.*\n/, ''
41
42
  comment cfg
42
43
  end
43
44
 
@@ -2,7 +2,7 @@ class AsyncOS < Oxidized::Model
2
2
  using Refinements
3
3
 
4
4
  # ESA prompt "(mail.example.com)> " or "mail.example.com> "
5
- prompt /^\r*([(]?[\w. ]+[)]?[#>]\s+)$/
5
+ prompt /^\r*\(?[\w.\- ]+\)?[#>]\s+$/
6
6
  comment '! '
7
7
 
8
8
  # Select passphrase display option
@@ -1,7 +1,19 @@
1
1
  class Cumulus < Oxidized::Model
2
2
  using Refinements
3
3
 
4
- prompt /^(([\w.-]*)@(.*)):/
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
11
+ # ^ : match begin of line, to have the most specific prompt
12
+ # [\w.-]+@[\w.-]+ : user@hostname
13
+ # (:mgmt)? : optional when logged in out of band
14
+ # :~[#$] $ : end of prompt, containing the linux path,
15
+ # which is always "~" in our context
16
+ prompt /^[\w.-]+@[\w.-]+(:mgmt)?:~[#$] $/
5
17
  comment '# '
6
18
 
7
19
  # add a comment in the final conf
@@ -79,7 +91,9 @@ class Cumulus < Oxidized::Model
79
91
  cfg += cmd 'cat /etc/cumulus/switchd.conf'
80
92
 
81
93
  cfg += add_comment 'PORTS'
82
- cfg += cmd 'cat /etc/cumulus/ports.conf'
94
+ # in some configurations, ports.conf has no trailing Line Feed,
95
+ # which breaks the prompt, so we add one
96
+ cfg += cmd "cat /etc/cumulus/ports.conf; echo"
83
97
 
84
98
  cfg += add_comment 'TRAFFIC'
85
99
  cfg += cmd 'cat /etc/cumulus/datapath/traffic.conf'
@@ -0,0 +1,46 @@
1
+ class Enterprise_SONiC < Oxidized::Model # rubocop:disable Naming/ClassAndModuleCamelCase
2
+ using Refinements
3
+
4
+ # Remove ANSI escape codes
5
+ expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
6
+ data.gsub re, ''
7
+ end
8
+
9
+ # Matches both sonic-cli and linux terminal
10
+ prompt /^(?:[\w.-]+@[\w.-]+:[~\w\/-]+\$|[\w.-]+#)\s*/
11
+ comment "# "
12
+
13
+ def add_comment(comment)
14
+ "\n##### #{comment} #####\n"
15
+ end
16
+
17
+ post do
18
+ cmd 'show running-configuration' do |cfg|
19
+ add_comment('CONFIGURATION') + cfg
20
+ end
21
+ end
22
+
23
+ cmd 'show version' do |cfg|
24
+ cfg = cfg.each_line.reject { |line| line.match /Uptime/ }.join
25
+ add_comment('VERSION') + cfg
26
+ end
27
+
28
+ cmd 'show platform syseeprom' do |cfg|
29
+ add_comment('SYSEEPROM') + cfg
30
+ end
31
+
32
+ cmd :all do |cfg|
33
+ cfg.cut_both
34
+ end
35
+
36
+ cfg :ssh do
37
+ # if user logs in to linux == has admin rights
38
+ if vars(:admin) == true
39
+ post_login do
40
+ cmd "sonic-cli\n"
41
+ end
42
+ end
43
+ post_login 'terminal length 0'
44
+ pre_logout 'exit'
45
+ end
46
+ end
@@ -2,6 +2,7 @@ class FSOS < Oxidized::Model
2
2
  # Fiberstore / fs.com
3
3
  using Refinements
4
4
  comment '! '
5
+ prompt /^([\w.@()-]+[#>]\s?)$/
5
6
 
6
7
  # Handle paging
7
8
  expect /^ --More--.*$/ do |data, re|
@@ -13,6 +14,9 @@ class FSOS < Oxidized::Model
13
14
  cfg.gsub! /(secret \w+) (\S+).*/, '\\1 <secret hidden>'
14
15
  cfg.gsub! /(password \d+) (\S+).*/, '\\1 <secret hidden>'
15
16
  cfg.gsub! /(snmp-server community \d+) (\S+).*/, '\\1 <secret hidden>'
17
+ cfg.gsub! /^(snmp-server host \S+( udp-port \d+)?( permit|deny \d+)?( informs?)?( traps?)?(( version v3 (priv|auth|noauth))|( version (v1|v2c))?)) +\S+( .*)?$*/, '\\1 <secret hidden>'
18
+ cfg.gsub! /^(snmp-server user \S+ \S+ v3( priv (des|aes128|aes256|aes256-c))?( auth (md5|sha|sha256) \d+)) +\S+( .*)?$*/, '\\1 <secret hidden>'
19
+ cfg.gsub! /^(.*key \d+) (\S+).*/, '\\1 <secret hidden>'
16
20
  cfg
17
21
  end
18
22
 
@@ -37,7 +41,7 @@ class FSOS < Oxidized::Model
37
41
  cfg :telnet, :ssh do
38
42
  post_login 'enable'
39
43
  post_login 'terminal length 0'
40
- post_login 'terminal width 256'
44
+ post_login 'terminal width 512'
41
45
  pre_logout 'exit'
42
46
  pre_logout 'exit'
43
47
  end
@@ -4,12 +4,12 @@ class Garderos < Oxidized::Model
4
4
  # Routers for harsh environments
5
5
  # grs = Garderos Router Software
6
6
 
7
- # remove all ANSI escape codes, as GRS uses them :-(
8
- # the prompt does not need to match escape codes, as they have been removed
9
- expect /\e\[\d*m\r?/ do |data, re|
7
+ # Remove ANSI escape codes
8
+ expect /\e\[[0-?]*[ -\/]*[@-~]\r?/ do |data, re|
10
9
  data.gsub re, ''
11
10
  end
12
11
 
12
+ # the prompt does not need to match escape codes, as they have been removed above
13
13
  prompt /[\w-]+# /
14
14
  comment '# '
15
15
 
@@ -29,7 +29,7 @@ class Garderos < Oxidized::Model
29
29
  # If we have a radio modem installed, we'd like to list the SIM Card
30
30
  cmd 'show hardware wwan wwan0 sim' do |cfg|
31
31
  if cfg.start_with? 'Unknown command'
32
- ''
32
+ String.new('')
33
33
  else
34
34
  comment "#{cfg}\n"
35
35
  end
@@ -26,7 +26,7 @@ class JunOS < Oxidized::Model
26
26
  end
27
27
 
28
28
  post do
29
- out = ''
29
+ out = String.new('')
30
30
  case @model
31
31
  when 'mx960'
32
32
  out << cmd('show chassis fabric reachability') { |cfg| comment cfg }