oxidized 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/no-response.yml +13 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +37 -0
- data/.rubocop_todo.yml +714 -0
- data/.travis.yml +7 -1
- data/CHANGELOG.md +341 -243
- data/Dockerfile +44 -16
- data/LICENSE +201 -0
- data/README.md +114 -82
- data/Rakefile +19 -0
- data/TODO.md +29 -23
- data/bin/oxidized +1 -2
- data/docs/Configuration.md +71 -31
- data/docs/Creating-Models.md +78 -0
- data/docs/Hooks.md +145 -41
- data/docs/Model-Notes/AireOS.md +12 -0
- data/docs/Model-Notes/ArbOS.md +12 -0
- data/docs/Model-Notes/Comware.md +14 -0
- data/docs/Model-Notes/EOS.md +9 -0
- data/docs/Model-Notes/JunOS.md +34 -0
- data/docs/Model-Notes/Netgear.md +68 -0
- data/docs/Model-Notes/README.md +19 -0
- data/docs/{VRP-Huawei.md → Model-Notes/VRP-Huawei.md} +10 -2
- data/docs/Model-Notes/XGS4600-Zyxel.md +39 -0
- data/docs/Outputs.md +27 -28
- data/docs/Ruby-API.md +38 -18
- data/docs/Sources.md +78 -16
- data/docs/Supported-OS-Types.md +171 -148
- data/extra/oxidized.logrotate +7 -0
- data/extra/oxidized.service +1 -1
- data/extra/rest_client.rb +4 -5
- data/extra/syslog.rb +16 -16
- data/lib/oxidized/cli.rb +3 -3
- data/lib/oxidized/config.rb +7 -4
- data/lib/oxidized/core.rb +3 -3
- data/lib/oxidized/hook.rb +64 -65
- data/lib/oxidized/hook/awssns.rb +2 -3
- data/lib/oxidized/hook/ciscosparkdiff.rb +49 -0
- data/lib/oxidized/hook/exec.rb +5 -5
- data/lib/oxidized/hook/githubrepo.rb +20 -14
- data/lib/oxidized/hook/slackdiff.rb +38 -19
- data/lib/oxidized/hook/xmppdiff.rb +58 -0
- data/lib/oxidized/input/cli.rb +5 -6
- data/lib/oxidized/input/ftp.rb +8 -7
- data/lib/oxidized/input/http.rb +39 -0
- data/lib/oxidized/input/ssh.rb +24 -22
- data/lib/oxidized/input/telnet.rb +38 -32
- data/lib/oxidized/jobs.rb +3 -4
- data/lib/oxidized/manager.rb +9 -4
- data/lib/oxidized/model/acos.rb +15 -16
- data/lib/oxidized/model/acsw.rb +3 -8
- data/lib/oxidized/model/aen.rb +1 -2
- data/lib/oxidized/model/aireos.rb +3 -5
- data/lib/oxidized/model/alteonos.rb +16 -18
- data/lib/oxidized/model/alvarion.rb +0 -4
- data/lib/oxidized/model/aos.rb +2 -4
- data/lib/oxidized/model/aos7.rb +2 -3
- data/lib/oxidized/model/aosw.rb +13 -15
- data/lib/oxidized/model/apc_aos.rb +0 -3
- data/lib/oxidized/model/arbos.rb +26 -0
- data/lib/oxidized/model/aricentiss.rb +51 -0
- data/lib/oxidized/model/asa.rb +33 -35
- data/lib/oxidized/model/asyncos.rb +41 -44
- data/lib/oxidized/model/audiocodes.rb +4 -8
- data/lib/oxidized/model/awplus.rb +84 -0
- data/lib/oxidized/model/boss.rb +6 -5
- data/lib/oxidized/model/br6910.rb +43 -45
- data/lib/oxidized/model/c4cmts.rb +3 -5
- data/lib/oxidized/model/cambium.rb +22 -0
- data/lib/oxidized/model/catos.rb +0 -2
- data/lib/oxidized/model/cisconga.rb +1 -3
- data/lib/oxidized/model/ciscosma.rb +37 -40
- data/lib/oxidized/model/ciscosmb.rb +7 -4
- data/lib/oxidized/model/comnetms.rb +43 -0
- data/lib/oxidized/model/comware.rb +9 -9
- data/lib/oxidized/model/coriant8600.rb +3 -5
- data/lib/oxidized/model/coriantgroove.rb +3 -5
- data/lib/oxidized/model/corianttmos.rb +1 -3
- data/lib/oxidized/model/cumulus.rb +26 -32
- data/lib/oxidized/model/datacom.rb +0 -2
- data/lib/oxidized/model/dcnos.rb +46 -0
- data/lib/oxidized/model/dlink.rb +1 -1
- data/lib/oxidized/model/dnos.rb +9 -5
- data/lib/oxidized/model/edgecos.rb +45 -0
- data/lib/oxidized/model/edgeos.rb +5 -3
- data/lib/oxidized/model/edgeswitch.rb +1 -3
- data/lib/oxidized/model/enterasys.rb +1 -3
- data/lib/oxidized/model/eos.rb +6 -8
- data/lib/oxidized/model/fabricos.rb +3 -5
- data/lib/oxidized/model/firewareos.rb +2 -5
- data/lib/oxidized/model/fortios.rb +21 -17
- data/lib/oxidized/model/ftos.rb +2 -4
- data/lib/oxidized/model/fujitsupy.rb +2 -4
- data/lib/oxidized/model/gaiaos.rb +6 -10
- data/lib/oxidized/model/gcombnps.rb +82 -0
- data/lib/oxidized/model/hatteras.rb +8 -5
- data/lib/oxidized/model/hirschmann.rb +8 -10
- data/lib/oxidized/model/hpebladesystem.rb +19 -17
- data/lib/oxidized/model/hpemsa.rb +0 -3
- data/lib/oxidized/model/ios.rb +54 -55
- data/lib/oxidized/model/iosxe.rb +5 -0
- data/lib/oxidized/model/iosxr.rb +1 -3
- data/lib/oxidized/model/ipos.rb +1 -3
- data/lib/oxidized/model/ironware.rb +12 -15
- data/lib/oxidized/model/isam.rb +4 -5
- data/lib/oxidized/model/junos.rb +8 -7
- data/lib/oxidized/model/masteros.rb +1 -3
- data/lib/oxidized/model/mlnxos.rb +3 -4
- data/lib/oxidized/model/model.rb +15 -7
- data/lib/oxidized/model/mtrlrfs.rb +1 -4
- data/lib/oxidized/model/ndms.rb +24 -0
- data/lib/oxidized/model/netgear.rb +3 -4
- data/lib/oxidized/model/netscaler.rb +0 -2
- data/lib/oxidized/model/nos.rb +1 -3
- data/lib/oxidized/model/nxos.rb +13 -3
- data/lib/oxidized/model/oneos.rb +6 -8
- data/lib/oxidized/model/openbsd.rb +76 -0
- data/lib/oxidized/model/opengear.rb +3 -5
- data/lib/oxidized/model/openwrt.rb +77 -0
- data/lib/oxidized/model/opnsense.rb +19 -0
- data/lib/oxidized/model/outputs.rb +1 -3
- data/lib/oxidized/model/panos.rb +1 -2
- data/lib/oxidized/model/pfsense.rb +9 -5
- data/lib/oxidized/model/planet.rb +8 -12
- data/lib/oxidized/model/powerconnect.rb +6 -9
- data/lib/oxidized/model/procurve.rb +18 -4
- data/lib/oxidized/model/quantaos.rb +3 -5
- data/lib/oxidized/model/routeros.rb +3 -2
- data/lib/oxidized/model/saos.rb +0 -1
- data/lib/oxidized/model/screenos.rb +3 -5
- data/lib/oxidized/model/sgos.rb +2 -3
- data/lib/oxidized/model/siklu.rb +0 -2
- data/lib/oxidized/model/slxos.rb +59 -0
- data/lib/oxidized/model/sros.rb +117 -0
- data/lib/oxidized/model/stoneos.rb +32 -0
- data/lib/oxidized/model/supermicro.rb +6 -41
- data/lib/oxidized/model/timos.rb +6 -114
- data/lib/oxidized/model/tmos.rb +1 -3
- data/lib/oxidized/model/tplink.rb +7 -11
- data/lib/oxidized/model/trango.rb +6 -7
- data/lib/oxidized/model/ucs.rb +0 -1
- data/lib/oxidized/model/voltaire.rb +3 -6
- data/lib/oxidized/model/voss.rb +1 -2
- data/lib/oxidized/model/vrp.rb +4 -5
- data/lib/oxidized/model/vyatta.rb +6 -4
- data/lib/oxidized/model/weos.rb +1 -3
- data/lib/oxidized/model/xos.rb +6 -5
- data/lib/oxidized/model/zhoneolt.rb +2 -2
- data/lib/oxidized/model/zynos.rb +1 -3
- data/lib/oxidized/model/zynoscli.rb +36 -0
- data/lib/oxidized/node.rb +11 -11
- data/lib/oxidized/node/stats.rb +15 -2
- data/lib/oxidized/nodes.rb +8 -8
- data/lib/oxidized/output/file.rb +41 -42
- data/lib/oxidized/output/git.rb +113 -115
- data/lib/oxidized/output/gitcrypt.rb +241 -242
- data/lib/oxidized/output/http.rb +23 -27
- data/lib/oxidized/output/output.rb +1 -2
- data/lib/oxidized/source/csv.rb +44 -45
- data/lib/oxidized/source/http.rb +52 -49
- data/lib/oxidized/source/source.rb +6 -7
- data/lib/oxidized/source/sql.rb +55 -51
- data/lib/oxidized/string.rb +3 -4
- data/lib/oxidized/version.rb +17 -1
- data/lib/oxidized/worker.rb +12 -3
- data/oxidized.gemspec +19 -13
- metadata +139 -51
- data/.ruby-version +0 -1
- data/Gemfile.lock +0 -44
data/Rakefile
CHANGED
@@ -1,9 +1,22 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rake/testtask'
|
3
|
+
require_relative 'lib/oxidized/version'
|
3
4
|
|
4
5
|
gemspec = eval(File.read(Dir['*.gemspec'].first))
|
5
6
|
file = [gemspec.name, gemspec.version].join('-') + '.gem'
|
6
7
|
|
8
|
+
# Integrate Rubocop if available
|
9
|
+
begin
|
10
|
+
require 'rubocop/rake_task'
|
11
|
+
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
task(:default).prerequisites << task(:rubocop)
|
14
|
+
rescue LoadError
|
15
|
+
task :rubocop do
|
16
|
+
puts 'Install rubocop to run its rake tasks'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
7
20
|
desc 'Validate gemspec'
|
8
21
|
task :gemspec do
|
9
22
|
gemspec.validate
|
@@ -19,6 +32,12 @@ task :test do
|
|
19
32
|
end
|
20
33
|
end
|
21
34
|
|
35
|
+
task :build => :version_set
|
36
|
+
task :version_set do
|
37
|
+
Oxidized.version_set
|
38
|
+
Bundler::GemHelper.instance.gemspec.version = Oxidized::VERSION
|
39
|
+
end
|
40
|
+
|
22
41
|
## desc 'Install gem'
|
23
42
|
## task :install => :build do
|
24
43
|
## system "sudo -Es sh -c \'umask 022; gem install gems/#{file}\'"
|
data/TODO.md
CHANGED
@@ -1,23 +1,29 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
# To Do
|
2
|
+
|
3
|
+
## refactor core
|
4
|
+
|
5
|
+
* move state from memory to disk, sqlite probably
|
6
|
+
* allows us to retain stats etc over restart
|
7
|
+
* simplifies code
|
8
|
+
* keep only running nodes in memory
|
9
|
+
* negligible I/O cost, as majority is I/O wait getting config
|
10
|
+
|
11
|
+
## separate login to own package
|
12
|
+
|
13
|
+
* oxidized-script is not only use-case
|
14
|
+
* it would be good to have minimal package used to login to routers
|
15
|
+
* oxidized just one consumer of that functionality
|
16
|
+
* what to do with models, we need model to know how to login. Should models be separated to another package? oxidized-core, oxidized-models and oxidized-login?
|
17
|
+
* how can we allow interactive login in oxidized-login? With functional VTY etc? REPL loop in input/ssh and input/telnet?
|
18
|
+
|
19
|
+
## thread number
|
20
|
+
|
21
|
+
* think about algo
|
22
|
+
* if job ended later than now-iteration have rand(node.size) == 0 to add thread
|
23
|
+
* if now is less than job_ended+iteration same chance to remove thread?
|
24
|
+
* should we try to avoid max threads from being hit? (like maybe non-success thread is pulling average?)
|
25
|
+
|
26
|
+
## docs, testing
|
27
|
+
|
28
|
+
* yard docs
|
29
|
+
* minitest tests
|
data/bin/oxidized
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
3
|
# FIX ME, killing oxidized needs -9
|
5
4
|
trap("INT") { exit } # sinatra will otherwise steal this from us
|
6
5
|
|
@@ -9,6 +8,6 @@ begin
|
|
9
8
|
Oxidized::CLI.new.run
|
10
9
|
rescue => error
|
11
10
|
warn "#{error}"
|
12
|
-
debug =
|
11
|
+
debug = Oxidized.config.debug rescue true
|
13
12
|
raise if debug
|
14
13
|
end
|
data/docs/Configuration.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Configuration
|
2
|
+
|
3
|
+
## Debugging
|
4
|
+
|
3
5
|
In case a model plugin doesn't work correctly (ios, procurve, etc.), you can enable live debugging of SSH/Telnet sessions. Just add a `debug` option containing the value true to the `input` section. The log files will be created depending on the parent directory of the logfile option.
|
4
6
|
|
5
|
-
The following example will log an active ssh/telnet session `/home/oxidized/.config/oxidized/log/<IP-
|
7
|
+
The following example will log an active ssh/telnet session `/home/oxidized/.config/oxidized/log/<IP-Address>-<PROTOCOL>`. The file will be truncated on each consecutive ssh/telnet session, so you need to put a `tailf` or `tail -f` on that file!
|
6
8
|
|
7
|
-
```
|
9
|
+
```yaml
|
8
10
|
log: /home/oxidized/.config/oxidized/log
|
9
11
|
|
10
12
|
...
|
@@ -16,54 +18,68 @@ input:
|
|
16
18
|
secure: false
|
17
19
|
```
|
18
20
|
|
19
|
-
|
21
|
+
## Privileged mode
|
20
22
|
|
21
23
|
To start privileged mode before pulling the configuration, Oxidized needs to send the enable command. You can globally enable this, by adding the following snippet to the global section of the configuration file.
|
22
24
|
|
23
|
-
```
|
25
|
+
```yaml
|
24
26
|
vars:
|
25
27
|
enable: S3cre7
|
26
28
|
```
|
27
29
|
|
28
|
-
|
30
|
+
## Removing secrets
|
29
31
|
|
30
|
-
To strip out secrets from configurations before storing them, Oxidized needs the
|
32
|
+
To strip out secrets from configurations before storing them, Oxidized needs the `remove_secret` flag. You can globally enable this by adding the following snippet to the global section of the configuration file.
|
31
33
|
|
32
|
-
```
|
34
|
+
```yaml
|
33
35
|
vars:
|
34
36
|
remove_secret: true
|
35
37
|
```
|
36
38
|
|
37
|
-
Device models
|
39
|
+
Device models that contain substitution filters to remove sensitive data will now be run on any fetched configuration.
|
38
40
|
|
39
41
|
As a partial example from ios.rb:
|
40
42
|
|
41
|
-
```
|
43
|
+
```ruby
|
42
44
|
cmd :secret do |cfg|
|
43
45
|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
|
44
46
|
(...)
|
45
47
|
cfg
|
46
48
|
end
|
47
49
|
```
|
50
|
+
|
48
51
|
The above strips out snmp community strings from your saved configs.
|
49
52
|
|
50
53
|
**NOTE:** Removing secrets reduces the usefulness as a full configuration backup, but it may make sharing configs easier.
|
51
54
|
|
52
|
-
|
55
|
+
## Disabling SSH exec channels
|
53
56
|
|
54
|
-
Oxidized uses exec channels to make information extraction simpler, but there are some situations where this doesn't work well, e.g. configuring devices.
|
57
|
+
Oxidized uses exec channels to make information extraction simpler, but there are some situations where this doesn't work well, e.g. configuring devices. This feature can be turned off by setting the `ssh_no_exec`
|
55
58
|
variable.
|
56
59
|
|
57
|
-
```
|
60
|
+
```yaml
|
58
61
|
vars:
|
59
62
|
ssh_no_exec: true
|
60
63
|
```
|
61
64
|
|
62
|
-
|
65
|
+
## SSH Auth Methods
|
63
66
|
|
64
|
-
Oxidized
|
67
|
+
By default, Oxidized registers the following auth methods: `none`, `publickey` and `password`. However you can configure this globally, by groups, models or nodes.
|
65
68
|
|
66
69
|
```
|
70
|
+
vars:
|
71
|
+
auth_methods: none, publickey, password, keyboard-interactive
|
72
|
+
```
|
73
|
+
|
74
|
+
## SSH Proxy Command
|
75
|
+
|
76
|
+
Oxidized can `ssh` through a proxy as well. To do so we just need to set `ssh_proxy` variable with the proxy host information.
|
77
|
+
|
78
|
+
This can be provided on a per-node basis by mapping the proper fields from your source.
|
79
|
+
|
80
|
+
An example for a `csv` input source that maps the 4th field as the `ssh_proxy` value.
|
81
|
+
|
82
|
+
```yaml
|
67
83
|
...
|
68
84
|
map:
|
69
85
|
name: 0
|
@@ -74,16 +90,26 @@ vars_map:
|
|
74
90
|
...
|
75
91
|
```
|
76
92
|
|
77
|
-
|
93
|
+
## FTP Passive Mode
|
78
94
|
|
79
|
-
|
95
|
+
Oxidized uses ftp passive mode by default. Some devices require passive mode to be disabled. To do so, we can set `input.ftp.passive` to false - this will make use of FTP active mode.
|
80
96
|
|
97
|
+
```yaml
|
98
|
+
input:
|
99
|
+
ftp:
|
100
|
+
passive: false
|
81
101
|
```
|
102
|
+
|
103
|
+
## Advanced Configuration
|
104
|
+
|
105
|
+
Below is an advanced example configuration. You will be able to (optionally) override options per device. The router.db format used is `hostname:model:username:password:enable_password`. Hostname and model will be the only required options, all others override the global configuration sections.
|
106
|
+
|
107
|
+
```yaml
|
82
108
|
---
|
83
109
|
username: oxidized
|
84
110
|
password: S3cr3tx
|
85
111
|
model: junos
|
86
|
-
interval: 3600
|
112
|
+
interval: 3600 #interval in seconds
|
87
113
|
log: ~/.config/oxidized/log
|
88
114
|
debug: false
|
89
115
|
threads: 30
|
@@ -121,14 +147,13 @@ source:
|
|
121
147
|
model_map:
|
122
148
|
cisco: ios
|
123
149
|
juniper: junos
|
124
|
-
|
125
150
|
```
|
126
151
|
|
127
|
-
|
152
|
+
## Advanced Group Configuration
|
128
153
|
|
129
154
|
For group specific credentials
|
130
155
|
|
131
|
-
```
|
156
|
+
```yaml
|
132
157
|
groups:
|
133
158
|
mikrotik:
|
134
159
|
username: admin
|
@@ -137,16 +162,19 @@ groups:
|
|
137
162
|
username: ubnt
|
138
163
|
password: ubnt
|
139
164
|
```
|
165
|
+
|
140
166
|
and add group mapping
|
141
|
-
|
167
|
+
|
168
|
+
```yaml
|
142
169
|
map:
|
143
170
|
model: 0
|
144
171
|
name: 1
|
145
172
|
group: 2
|
146
173
|
```
|
174
|
+
|
147
175
|
For model specific credentials
|
148
176
|
|
149
|
-
```
|
177
|
+
```yaml
|
150
178
|
models:
|
151
179
|
junos:
|
152
180
|
username: admin
|
@@ -161,26 +189,38 @@ models:
|
|
161
189
|
password: password
|
162
190
|
```
|
163
191
|
|
164
|
-
|
192
|
+
## RESTful API and Web Interface
|
165
193
|
|
166
194
|
The RESTful API and Web Interface is enabled by configuring the `rest:` parameter in the config file. This parameter can optionally contain a relative URI.
|
167
195
|
|
168
|
-
```
|
196
|
+
```yaml
|
169
197
|
# Listen on http://127.0.0.1:8888/
|
170
198
|
rest: 127.0.0.1:8888
|
171
199
|
```
|
172
200
|
|
173
|
-
```
|
201
|
+
```yaml
|
174
202
|
# Listen on http://10.0.0.1:8000/oxidized/
|
175
203
|
rest: 10.0.0.1:8000/oxidized
|
176
204
|
```
|
177
205
|
|
178
|
-
|
206
|
+
## Triggered backups
|
179
207
|
|
180
|
-
A node can be moved to head-of-queue via the REST API `GET/POST /node/next/[NODE]`.
|
208
|
+
A node can be moved to head-of-queue via the REST API `GET/POST /node/next/[NODE]`. This can be useful to immediately schedule a fetch of the configuration after some other event such as a syslog message indicating a configuration update on the device.
|
181
209
|
|
182
|
-
In the default configuration this node will be processed when the next job worker becomes available, it could take some time if existing backups are in progress. To execute moved jobs immediately a new job can be added:
|
210
|
+
In the default configuration this node will be processed when the next job worker becomes available, it could take some time if existing backups are in progress. To execute moved jobs immediately a new job can be added automatically:
|
183
211
|
|
184
|
-
```
|
212
|
+
```yaml
|
185
213
|
next_adds_job: true
|
186
214
|
```
|
215
|
+
|
216
|
+
This will allow for a more timely fetch of the device configuration.
|
217
|
+
|
218
|
+
## Disabling DNS resolution
|
219
|
+
|
220
|
+
In some instances it might not be desirable to attempt to resolve names of nodes. One such use case is when nodes are accessed through an SSH proxy, where the remote end resolves the names differently than the host on which Oxidized runs would.
|
221
|
+
|
222
|
+
Names can instead be passed verbatim to the input:
|
223
|
+
|
224
|
+
```yaml
|
225
|
+
resolve_dns: false
|
226
|
+
```
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Creating and Extending Models
|
2
|
+
|
3
|
+
Oxidized supports a growing list of [operating system types](Supported-OS-Types.md). Out of the box, most model implementations collect configuration data. Some implementations also include a conservative set of additional commands that collect basic device information (device make and model, software version, licensing information, ...) which are appended to the configuration as comments.
|
4
|
+
|
5
|
+
A user may wish to extend an existing model to collect the output of additional commands. Oxidized offers smart loading of models in order to facilitate this with ease, without the need to introduce changes to the upstream source code.
|
6
|
+
|
7
|
+
This methodology allows local site changes to be preserved during Oxidized version updates / gem updates.
|
8
|
+
|
9
|
+
## Extending an existing model with a new command
|
10
|
+
|
11
|
+
The example below can be used to extend the `JunOS` model to collect the output of `show interfaces diagnostics optics` and append the output to the configuration file as a comment. This command retrieves DOM information on pluggable optics present in a `JunOS`-powered chassis.
|
12
|
+
|
13
|
+
Create the file `~/.config/oxidized/model/junos.rb` with the following contents:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'oxidized/model/junos.rb'
|
17
|
+
|
18
|
+
|
19
|
+
class JunOS
|
20
|
+
|
21
|
+
|
22
|
+
cmd 'show interfaces diagnostics optics' do |cfg|
|
23
|
+
comment cfg
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
Due to smart loading, the user-supplied `~/.config/oxidized/model/junos.rb` file will take precedence over the model with the same name included in the Oxidized distribution.
|
31
|
+
|
32
|
+
The code then uses `require` to initially load the Oxidized-supplied model, and extends the class defined therein with an additional command.
|
33
|
+
|
34
|
+
Intuitively, it is also possible to:
|
35
|
+
|
36
|
+
* Completely re-define an existing model by creating a file in `~/.config/oxidized/model/` with the same name as an existing model, but not `require`-ing the upstream model file.
|
37
|
+
* Create a named variation of an existing model, by creating a file with a new name (such as `~/.config/oxidized/model/junos-extra.rb`), Then `require` the original model and extend its base class as in the above example. The named variation can then be specified as an OS type for specific devices that can benefit from the extra functionality. This allows for preservation of the base functionality for the default model types.
|
38
|
+
* Create a completely new model, with a new name, for a new operating system type.
|
39
|
+
* Testing/validation of an updated model from the [Oxidized GitHub repo models](https://github.com/ytti/oxidized/tree/master/lib/oxidized/model) by placing an updated model in the proper location without disrupting the gem-supplied model files.
|
40
|
+
|
41
|
+
## Advanced features
|
42
|
+
|
43
|
+
The loosely-coupled architecture of Oxidized allows for easy extensibility in more advanced use cases as well.
|
44
|
+
|
45
|
+
The example below extends the functionality of the `JunOS` model further to collect `display set` formatted configuration from the device, and utilizes the multi-output functionality of the `git` output to place the returned configuration in a separate file within a git repository.
|
46
|
+
|
47
|
+
It is possible to configure the `git` output to create new subdirectories under an existing repository instead of creating new repositories for each new defined output type (the default) by including the following configuration in the `~/.config/oxidized/config` file:
|
48
|
+
|
49
|
+
```yaml
|
50
|
+
output:
|
51
|
+
git:
|
52
|
+
type_as_directory: true
|
53
|
+
```
|
54
|
+
|
55
|
+
Then, `~/.config/oxidized/model/junos.rb` is adapted as following:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
require 'oxidized/model/junos.rb'
|
59
|
+
|
60
|
+
|
61
|
+
class JunOS
|
62
|
+
|
63
|
+
|
64
|
+
cmd 'show interface diagnostic optics' do |cfg|
|
65
|
+
comment cfg
|
66
|
+
end
|
67
|
+
|
68
|
+
cmd 'show configuration | display set' do |cfg|
|
69
|
+
cfg.type = "junos-set"
|
70
|
+
cfg.name = "set"
|
71
|
+
cfg
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
The output of the `show configuration | display set` command is marked with a new arbitrary alternative output type, `junos-set`. The `git` output will use the output type to create a new subdirectory by the same name. In this subdirectory, the `git` output will create files with the name `<devicename>--set` that will contain the output of this command for each device.
|
data/docs/Hooks.md
CHANGED
@@ -1,46 +1,52 @@
|
|
1
1
|
# Hooks
|
2
|
-
|
2
|
+
|
3
|
+
You can define an arbitrary number of hooks that subscribe to different events. The hook system is modular and different kind of hook types can be enabled.
|
3
4
|
|
4
5
|
## Configuration
|
6
|
+
|
5
7
|
Following configuration keys need to be defined for all hooks:
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
* `events`: which events to subscribe. Needs to be an array. See below for the list of available events.
|
10
|
+
* `type`: what hook class to use. See below for the list of available hook types.
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
## Events
|
13
|
+
|
14
|
+
* `node_success`: triggered when configuration is successfully pulled from a node and right before storing the configuration.
|
15
|
+
* `node_fail`: triggered after `retries` amount of failed node pulls.
|
16
|
+
* `post_store`: triggered after node configuration is stored (this is executed only when the configuration has changed).
|
17
|
+
* `nodes_done`: triggered after finished fetching all nodes.
|
15
18
|
|
16
19
|
## Hook type: exec
|
20
|
+
|
17
21
|
The `exec` hook type allows users to run an arbitrary shell command or a binary when triggered.
|
18
22
|
|
19
23
|
The command is executed on a separate child process either in synchronous or asynchronous fashion. Non-zero exit values cause errors to be logged. STDOUT and STDERR are currently not collected.
|
20
24
|
|
21
25
|
Command is executed with the following environment:
|
22
|
-
|
26
|
+
|
27
|
+
```text
|
23
28
|
OX_EVENT
|
24
29
|
OX_NODE_NAME
|
25
30
|
OX_NODE_IP
|
26
31
|
OX_NODE_FROM
|
27
32
|
OX_NODE_MSG
|
28
33
|
OX_NODE_GROUP
|
34
|
+
OX_NODE_MODEL
|
29
35
|
OX_JOB_STATUS
|
30
36
|
OX_JOB_TIME
|
31
37
|
OX_REPO_COMMITREF
|
32
38
|
OX_REPO_NAME
|
33
39
|
```
|
34
40
|
|
35
|
-
Exec hook recognizes following configuration keys:
|
41
|
+
Exec hook recognizes the following configuration keys:
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
43
|
+
* `timeout`: hard timeout (in seconds) for the command execution. SIGTERM will be sent to the child process after the timeout has elapsed. Default: `60`
|
44
|
+
* `async`: Execute the command in an asynchronous fashion. The main thread by default will wait for the hook command execution to complete. Set this to `true` for long running commands so node configuration pulls are not blocked. Default: `false`
|
45
|
+
* `cmd`: command to run.
|
40
46
|
|
47
|
+
### exec hook configuration example
|
41
48
|
|
42
|
-
|
43
|
-
```
|
49
|
+
```yaml
|
44
50
|
hooks:
|
45
51
|
name_for_example_hook1:
|
46
52
|
type: exec
|
@@ -54,21 +60,31 @@ hooks:
|
|
54
60
|
timeout: 120
|
55
61
|
```
|
56
62
|
|
57
|
-
|
63
|
+
## Hook type: githubrepo
|
64
|
+
|
65
|
+
The `githubrepo` hook executes a `git push` to a configured `remote_repo` when the specified event is triggered.
|
58
66
|
|
59
|
-
|
67
|
+
Several authentication methods are supported:
|
60
68
|
|
61
|
-
`
|
69
|
+
* Provide a `password` for username + password authentication
|
70
|
+
* Provide both a `publickey` and a `privatekey` for ssh key-based authentication
|
71
|
+
* Don't provide any credentials for ssh-agent authentication
|
62
72
|
|
63
|
-
|
64
|
-
* `username`: username for repository auth.
|
65
|
-
* `password`: password for repository auth.
|
66
|
-
* `publickey`: publickey for repository auth.
|
67
|
-
* `privatekey`: privatekey for repository auth.
|
73
|
+
The username will be set to the relevant part of the `remote_repo` URI, with a fallback to `git`. It is also possible to provide one by setting the `username` configuration key.
|
68
74
|
|
69
|
-
|
75
|
+
For ssh key-based authentication, it is possible to set the environment variable `OXIDIZED_SSH_PASSPHRASE` to a passphrase if the private key requires it.
|
70
76
|
|
71
|
-
|
77
|
+
`githubrepo` hook recognizes the following configuration keys:
|
78
|
+
|
79
|
+
* `remote_repo`: the remote repository to be pushed to.
|
80
|
+
* `username`: username for repository auth.
|
81
|
+
* `password`: password for repository auth.
|
82
|
+
* `publickey`: public key file path for repository auth.
|
83
|
+
* `privatekey`: private key file path for repository auth.
|
84
|
+
|
85
|
+
When using groups, each group must have a unique entry in the `remote_repo` config.
|
86
|
+
|
87
|
+
```yaml
|
72
88
|
hooks:
|
73
89
|
push_to_remote:
|
74
90
|
remote_repo:
|
@@ -77,10 +93,11 @@ hooks:
|
|
77
93
|
firewalls: git@git.intranet:oxidized/firewalls.git
|
78
94
|
```
|
79
95
|
|
96
|
+
### githubrepo hook configuration example
|
80
97
|
|
81
|
-
|
98
|
+
Authenticate with a username and a password without groups in use:
|
82
99
|
|
83
|
-
```
|
100
|
+
```yaml
|
84
101
|
hooks:
|
85
102
|
push_to_remote:
|
86
103
|
type: githubrepo
|
@@ -90,20 +107,37 @@ hooks:
|
|
90
107
|
password: pass
|
91
108
|
```
|
92
109
|
|
110
|
+
Authenticate with the username `git` and an ssh key:
|
111
|
+
|
112
|
+
```yaml
|
113
|
+
hooks:
|
114
|
+
push_to_remote:
|
115
|
+
type: githubrepo
|
116
|
+
events: [post_store]
|
117
|
+
remote_repo: git@git.intranet:oxidized/test.git
|
118
|
+
publickey: /root/.ssh/id_rsa.pub
|
119
|
+
privatekey: /root/.ssh/id_rsa
|
120
|
+
```
|
121
|
+
|
93
122
|
## Hook type: awssns
|
94
123
|
|
95
124
|
The `awssns` hook publishes messages to AWS SNS topics. This allows you to notify other systems of device configuration changes, for example a config orchestration pipeline. Multiple services can subscribe to the same AWS topic.
|
96
125
|
|
97
126
|
Fields sent in the message:
|
98
127
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
128
|
+
* `event`: Event type (e.g. `node_success`)
|
129
|
+
* `group`: Group name
|
130
|
+
* `model`: Model name (e.g. `eos`)
|
131
|
+
* `node`: Device hostname
|
132
|
+
|
103
133
|
|
104
|
-
|
134
|
+
The AWS SNS hook requires the following configuration keys:
|
105
135
|
|
106
|
-
|
136
|
+
* `region`: AWS Region name
|
137
|
+
* `topic_arn`: ASN Topic reference
|
138
|
+
### awssns hook configuration example
|
139
|
+
|
140
|
+
```yaml
|
107
141
|
hooks:
|
108
142
|
hook_script:
|
109
143
|
type: awssns
|
@@ -112,11 +146,6 @@ hooks:
|
|
112
146
|
topic_arn: arn:aws:sns:us-east-1:1234567:oxidized-test-backup_events
|
113
147
|
```
|
114
148
|
|
115
|
-
AWS SNS hook requires the following configuration keys:
|
116
|
-
|
117
|
-
* `region`: AWS Region name
|
118
|
-
* `topic_arn`: ASN Topic reference
|
119
|
-
|
120
149
|
Your AWS credentials should be stored in `~/.aws/credentials`.
|
121
150
|
|
122
151
|
## Hook type: slackdiff
|
@@ -125,13 +154,13 @@ The `slackdiff` hook posts colorized config diffs to a [Slack](http://www.slack.
|
|
125
154
|
|
126
155
|
You will need to manually install the `slack-api` gem on your system:
|
127
156
|
|
128
|
-
```
|
157
|
+
```shell
|
129
158
|
gem install slack-api
|
130
159
|
```
|
131
160
|
|
132
|
-
|
161
|
+
### slackdiff hook configuration example
|
133
162
|
|
134
|
-
```
|
163
|
+
```yaml
|
135
164
|
hooks:
|
136
165
|
slack:
|
137
166
|
type: slackdiff
|
@@ -140,4 +169,79 @@ hooks:
|
|
140
169
|
channel: "#network-changes"
|
141
170
|
```
|
142
171
|
|
172
|
+
Optionally you can disable snippets and post a formatted message, for instance linking to a commit in a git repo. Named parameters `%{node}`, `%{group}`, `%{model}` and `%{commitref}` are available.
|
173
|
+
|
174
|
+
```yaml
|
175
|
+
hooks:
|
176
|
+
slack:
|
177
|
+
type: slackdiff
|
178
|
+
events: [post_store]
|
179
|
+
token: SLACK_BOT_TOKEN
|
180
|
+
channel: "#network-changes"
|
181
|
+
diff: false
|
182
|
+
message: "%{node} %{group} %{model} updated https://git.intranet/network-changes/commit/%{commitref}"
|
183
|
+
```
|
184
|
+
|
185
|
+
Note the channel name must be in quotes.
|
186
|
+
|
187
|
+
## Hook type: ciscosparkdiff
|
188
|
+
|
189
|
+
The `ciscosparkdiff` hook posts config diffs to a [Cisco Spark](https://www.ciscospark.com/) space of your choice. It only triggers for `post_store` events.
|
190
|
+
|
191
|
+
You will need to manually install the `cisco_spark` gem on your system (see [cisco_spark-ruby](https://github.com/NGMarmaduke/cisco_spark-ruby)) and generate either a [Bot or OAUTH access key](https://developer.ciscospark.com/apps.html), and retrieve the [Spark Space ID](https://developer.ciscospark.com/endpoint-rooms-get.html)
|
192
|
+
|
193
|
+
```shell
|
194
|
+
gem install cisco_spark
|
195
|
+
```
|
196
|
+
|
197
|
+
### ciscosparkdiff hook configuration example
|
198
|
+
|
199
|
+
```yaml
|
200
|
+
hooks:
|
201
|
+
ciscospark:
|
202
|
+
type: ciscosparkdiff
|
203
|
+
events: [post_store]
|
204
|
+
accesskey: SPARK_BOT_API_OR_OAUTH_KEY
|
205
|
+
space: SPARK_SPACE_ID
|
206
|
+
diff: true
|
207
|
+
```
|
208
|
+
|
209
|
+
Optionally you can disable snippets and post a formatted message, for instance linking to a commit in a git repo. Named parameters `%{node}`, `%{group}`, `%{model}` and `%{commitref}` are available.
|
210
|
+
|
211
|
+
```yaml
|
212
|
+
hooks:
|
213
|
+
ciscospark:
|
214
|
+
type: ciscosparkdiff
|
215
|
+
events: [post_store]
|
216
|
+
accesskey: SPARK_BOT_API_OR_OAUTH_KEY
|
217
|
+
space: SPARK_SPACE_ID
|
218
|
+
diff: false
|
219
|
+
message: "%{node} %{group} %{model} updated https://git.intranet/network-changes/commit/%{commitref}"
|
220
|
+
```
|
221
|
+
|
222
|
+
Note the space and access tokens must be in quotes.
|
223
|
+
|
224
|
+
## Hook type: xmppdiff
|
225
|
+
|
226
|
+
The `xmppdiff` hook posts config diffs to a [XMPP](https://en.wikipedia.org/wiki/XMPP) chatroom of your choice. It only triggers for `post_store` events.
|
227
|
+
|
228
|
+
You will need to manually install the `xmpp4r` gem on your system:
|
229
|
+
|
230
|
+
```shell
|
231
|
+
gem install xmpp4r
|
232
|
+
```
|
233
|
+
|
234
|
+
### xmppdiff hook configuration example
|
235
|
+
|
236
|
+
```yaml
|
237
|
+
hooks:
|
238
|
+
xmpp:
|
239
|
+
type: xmppdiff
|
240
|
+
events: [post_store]
|
241
|
+
jid: "user@server.tld/resource"
|
242
|
+
password: "password"
|
243
|
+
channel: "room@server.tld"
|
244
|
+
nick: "nickname"
|
245
|
+
```
|
246
|
+
|
143
247
|
Note the channel name must be in quotes.
|