oxidized 0.31.0 → 0.32.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -9
  3. data/.rubocop.yml +8 -7
  4. data/.rubocop_todo.yml +6 -6
  5. data/CHANGELOG.md +40 -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/Release.md +18 -2
  17. data/docs/Supported-OS-Types.md +3 -2
  18. data/examples/podman-compose/Makefile +1 -2
  19. data/{examples/device-simulation → extra}/device2yaml.rb +32 -12
  20. data/extra/gitdiff-msteams.sh +32 -5
  21. data/extra/nagios_check_failing_nodes.rb +1 -1
  22. data/extra/rest_client.rb +1 -1
  23. data/lib/oxidized/config.rb +1 -1
  24. data/lib/oxidized/input/ssh.rb +13 -5
  25. data/lib/oxidized/model/aos7.rb +2 -0
  26. data/lib/oxidized/model/aosw.rb +1 -1
  27. data/lib/oxidized/model/apc_aos.rb +1 -1
  28. data/lib/oxidized/model/arubainstant.rb +1 -1
  29. data/lib/oxidized/model/asa.rb +2 -1
  30. data/lib/oxidized/model/asyncos.rb +1 -1
  31. data/lib/oxidized/model/cumulus.rb +16 -2
  32. data/lib/oxidized/model/enterprise_sonic.rb +46 -0
  33. data/lib/oxidized/model/fsos.rb +5 -1
  34. data/lib/oxidized/model/garderos.rb +4 -4
  35. data/lib/oxidized/model/junos.rb +1 -1
  36. data/lib/oxidized/model/kornfeldos.rb +33 -0
  37. data/lib/oxidized/model/model.rb +2 -2
  38. data/lib/oxidized/model/powerconnect.rb +1 -1
  39. data/lib/oxidized/model/sonicos.rb +8 -2
  40. data/lib/oxidized/model/tplink.rb +1 -0
  41. data/lib/oxidized/model/xos.rb +1 -1
  42. data/lib/oxidized/source/source.rb +32 -2
  43. data/lib/oxidized/version.rb +2 -2
  44. data/oxidized.gemspec +21 -11
  45. metadata +47 -71
  46. data/examples/device-simulation/README.md +0 -173
  47. data/examples/device-simulation/cmdsets/aoscx +0 -9
  48. data/examples/device-simulation/cmdsets/arubainstant +0 -5
  49. data/examples/device-simulation/cmdsets/asa +0 -7
  50. data/examples/device-simulation/cmdsets/ios +0 -7
  51. data/examples/device-simulation/cmdsets/nxos +0 -5
  52. data/examples/device-simulation/cmdsets/routeros +0 -5
  53. data/examples/device-simulation/cmdsets/srosmd +0 -11
  54. data/examples/device-simulation/yaml/aoscx_R0X25A-6410_FL.10.10.1100.yaml +0 -2281
  55. data/examples/device-simulation/yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml +0 -451
  56. data/examples/device-simulation/yaml/arubainstant_IAP515_8.10.0.6_VWLC.yaml +0 -213
  57. data/examples/device-simulation/yaml/asa_5512_9.12-4-67_single-context.yaml +0 -531
  58. data/examples/device-simulation/yaml/asr920_16.8.1b.yaml +0 -1122
  59. data/examples/device-simulation/yaml/garderos_R7709_003_006_068.yaml +0 -101
  60. data/examples/device-simulation/yaml/iosxe_C9200L-24P-4G_17.09.04a.yaml +0 -514
  61. data/examples/device-simulation/yaml/iosxe_C9800-L-F-K9_17.06.05.yaml +0 -417
  62. data/examples/device-simulation/yaml/riverbed_915.yaml +0 -123
  63. data/examples/device-simulation/yaml/routeros_CHR_7.10.1.yaml +0 -145
  64. data/examples/device-simulation/yaml/routeros_CHR_7.16.yaml +0 -79
  65. data/examples/device-simulation/yaml/routeros_L009UiGS_7.15.2.yaml +0 -353
@@ -1,29 +1,42 @@
1
1
  # APC AOS Configuration
2
2
 
3
- Currently, the configuration of APC Network Management Cards can be downloaded with FTP only.
3
+ The configuration of APC Network Management Cards can be downloaded using FTP
4
+ and SCP.
5
+
6
+ To download with SCP, you need a
7
+ [patch](https://github.com/net-ssh/net-scp/pull/71) to
8
+ [Net::SCP](https://github.com/net-ssh/net-scp, which has been included
9
+ upstream, but there is currently no new release of Net::SCP and its authors are
10
+ unresponsive.
11
+
12
+ To temporarily solve this,
13
+ [@robertcheramy forked Net::SCP](https://github.com/robertcheramy/net-scp). You
14
+ can build or download the gem there. This gem is already included in the
15
+ oxidized container image (in the release coming after 0.31.0).
4
16
 
5
- A download of the configuration with SCP is [work in progress](https://github.com/ytti/oxidized/issues/1802).
6
- As the APC has an unusual behavior (the connection is closed without an exit-status), this has to be
7
- [fixed](https://github.com/net-ssh/net-scp/pull/71) upstream in [Net::SCP](https://github.com/net-ssh/net-scp).
8
- As soon as there is a release of Net::SCP supporting the behavior of APC OS, we will activate SCP in oxidized.
9
17
 
10
18
  ## Can I collect more information than just the configuration?
11
- APC OS does not have the ability to show the config.ini within an SSH-session. As oxidized can only get the
12
- configuration with one input type at a time, it is not possible to fetch config.ini via FTP/SCP and get the output of
13
- some commands via SSH at the same time.
19
+ APC OS does not have the ability to show the config.ini within an SSH-session.
20
+ As oxidized can only get the configuration with one input type at a time, it is
21
+ not possible to fetch config.ini via FTP/SCP and get the output of
22
+ some commands via SSH at the same time. Feature request #3334 has been opened
23
+ to support multiple inputs in oxidized.
24
+
25
+ A ticket has been opened with APC support in order to enable "cat config.ini"
26
+ within an SSH-session, but APC is not willing to support this.
14
27
 
15
- A ticket has been opened with APC support in order to support "cat config.ini" within an SSH-session, but
16
- the chances it will be supported at some time are not very good, and older versions will still not support it.
17
28
 
18
- ## How do I activate FTP input?
19
- In order to download the configuration with FTP (and in the future with SCP), you have to activate it as an
20
- input in the oxidized configuration. If you do not activate the input, oxidized will fail for the node with
21
- a rather unspecific error (`WARN -- : /apc status fail, retry attempt 1`).
29
+ ## How do I activate FTP/SCP input?
30
+ In order to download the configuration with FTP or SCP, you have to activate it
31
+ as an input in the oxidized configuration. If you do not activate the input,
32
+ oxidized will fail for the node with a
33
+ [rather unspecific error](https://github.com/ytti/oxidized/issues/3346)
34
+ (`WARN -- : /apc status fail, retry attempt 1`).
22
35
 
23
36
  The configuration can be done either globally or only for the model apc_aos.
24
37
 
25
- The global configuration would look like this. Note that Oxidized will try every input type in the given order
26
- until it succeeds, or it will report a failure.
38
+ The global configuration would look like this. Note that Oxidized will try every
39
+ input type in the given order until it succeeds, or it will report a failure.
27
40
  ```yaml
28
41
  input:
29
42
  default: ssh, ftp, scp
@@ -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.
data/docs/Release.md CHANGED
@@ -7,8 +7,24 @@ all the changes that have been done. Have a specific look at changes you don't u
7
7
 
8
8
  For a graphical compare, use `git difftool -d 0.30.0..master`.
9
9
 
10
- ## Test, test test!
11
- Test the git code and the container against as much device types an environments as you can.
10
+ ## Update the gem dependencies to the latest versions
11
+ ```
12
+ bundle outaded
13
+ bundle update
14
+ bundle outaded
15
+ ```
16
+
17
+ ## Update rubocup .rubocop_todo.yml
18
+ Run `bundle exec rubocop --auto-gen-config`,
19
+ and make sure `bundle exec rake` passes after it.
20
+
21
+ If you change some code => Restart the release process at the beginning ;-)
22
+
23
+ ## Make sure the file permissions are correct
24
+ Run `bundle exec rake chmod`
25
+
26
+ ## Test !
27
+ Test the git code and the container against as much device types and environments as you can.
12
28
 
13
29
  Do not integrate late PRs into master if they do not fix issues for the release. The must wait for the next release.
14
30
 
@@ -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'