oxidized 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -2
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +18 -2
- data/.rubocop_todo.yml +5 -12
- data/CHANGELOG.md +61 -1
- data/CONTRIBUTING.md +5 -0
- data/Dockerfile +82 -21
- data/README.md +5 -21
- data/Rakefile +3 -2
- data/docs/Configuration.md +36 -12
- data/docs/Creating-Models.md +45 -4
- data/docs/Hooks.md +34 -0
- data/docs/Issues.md +91 -0
- data/docs/Model-Notes/Cumulus.md +5 -0
- data/docs/Model-Notes/FSOS.md +5 -0
- data/docs/Model-Notes/FortiOS.md +21 -5
- data/docs/Model-Notes/HPEAruba.md +31 -0
- data/docs/Model-Notes/OS6.md +10 -0
- data/docs/Model-Notes/RouterOS.md +15 -0
- data/docs/Model-Notes/SikluMHTG.md +7 -0
- data/docs/Outputs.md +2 -0
- data/docs/Release.md +18 -15
- data/docs/Sources.md +21 -0
- data/docs/Supported-OS-Types.md +11 -5
- data/docs/Troubleshooting.md +35 -0
- data/examples/device-simulation/README.md +173 -0
- data/examples/device-simulation/cmdsets/aoscx +9 -0
- data/examples/device-simulation/cmdsets/arubainstant +5 -0
- data/examples/device-simulation/cmdsets/asa +7 -0
- data/examples/device-simulation/cmdsets/ios +7 -0
- data/examples/device-simulation/cmdsets/nxos +5 -0
- data/examples/device-simulation/cmdsets/routeros +5 -0
- data/examples/device-simulation/cmdsets/srosmd +11 -0
- data/examples/device-simulation/device2yaml.rb +225 -0
- data/examples/device-simulation/yaml/aoscx_R0X25A-6410_FL.10.10.1100.yaml +2281 -0
- data/examples/device-simulation/yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml +451 -0
- data/examples/device-simulation/yaml/arubainstant_IAP515_8.10.0.6_VWLC.yaml +213 -0
- data/examples/device-simulation/yaml/asa_5512_9.12-4-67_single-context.yaml +531 -0
- data/examples/device-simulation/yaml/asr920_16.8.1b.yaml +1122 -0
- data/examples/device-simulation/yaml/garderos_R7709_003_006_068.yaml +101 -0
- data/examples/device-simulation/yaml/iosxe_C9200L-24P-4G_17.09.04a.yaml +514 -0
- data/examples/device-simulation/yaml/iosxe_C9800-L-F-K9_17.06.05.yaml +417 -0
- data/examples/device-simulation/yaml/riverbed_915.yaml +123 -0
- data/examples/device-simulation/yaml/routeros_CHR_7.10.1.yaml +145 -0
- data/examples/device-simulation/yaml/routeros_CHR_7.16.yaml +79 -0
- data/examples/device-simulation/yaml/routeros_L009UiGS_7.15.2.yaml +353 -0
- data/examples/podman-compose/Makefile +60 -17
- data/examples/podman-compose/README.md +63 -27
- data/examples/podman-compose/docker-compose.yml +11 -2
- data/examples/podman-compose/gitserver/.gitignore +1 -0
- data/examples/podman-compose/gitserver/Dockerfile +14 -0
- data/examples/podman-compose/model-simulation/Dockerfile-model +1 -1
- data/examples/podman-compose/model-simulation/asternos.sh +2 -0
- data/examples/podman-compose/oxidized-config/.gitignore +2 -0
- data/examples/podman-compose/oxidized-config/config +1 -1
- data/examples/podman-compose/oxidized-config/config_csv-file +46 -0
- data/examples/podman-compose/oxidized-config/config_csv-gitserver +56 -0
- data/examples/podman-compose/oxidized-ssh/.gitignore +1 -0
- data/lib/oxidized/config.rb +7 -1
- data/lib/oxidized/hook/githubrepo.rb +37 -7
- data/lib/oxidized/hook/slackdiff.rb +29 -7
- data/lib/oxidized/input/http.rb +1 -0
- data/lib/oxidized/input/telnet.rb +1 -1
- data/lib/oxidized/manager.rb +17 -16
- data/lib/oxidized/model/aoscx.rb +16 -2
- data/lib/oxidized/model/aosw.rb +7 -1
- data/lib/oxidized/model/arubainstant.rb +90 -0
- data/lib/oxidized/model/audiocodes.rb +2 -2
- data/lib/oxidized/model/cnos.rb +13 -10
- data/lib/oxidized/model/cumulus.rb +3 -0
- data/lib/oxidized/model/dlink.rb +1 -0
- data/lib/oxidized/model/dlinknextgen.rb +3 -0
- data/lib/oxidized/model/edgecos.rb +2 -1
- data/lib/oxidized/model/eos.rb +2 -0
- data/lib/oxidized/model/f5os.rb +17 -0
- data/lib/oxidized/model/firewareos.rb +10 -1
- data/lib/oxidized/model/fortios.rb +24 -1
- data/lib/oxidized/model/garderos.rb +43 -0
- data/lib/oxidized/model/h3c.rb +1 -1
- data/lib/oxidized/model/ibos.rb +1 -0
- data/lib/oxidized/model/ios.rb +20 -12
- data/lib/oxidized/model/iosxr.rb +1 -1
- data/lib/oxidized/model/lenovonos.rb +2 -0
- data/lib/oxidized/model/linuxgeneric.rb +1 -1
- data/lib/oxidized/model/netgear.rb +1 -1
- data/lib/oxidized/model/nodegrid.rb +1 -1
- data/lib/oxidized/model/nsxdfw.rb +30 -0
- data/lib/oxidized/model/nxos.rb +2 -1
- data/lib/oxidized/model/os6.rb +48 -0
- data/lib/oxidized/model/rgos.rb +1 -1
- data/lib/oxidized/model/riverbed.rb +104 -0
- data/lib/oxidized/model/routeros.rb +2 -2
- data/lib/oxidized/model/saos.rb +18 -1
- data/lib/oxidized/model/siklumhtg.rb +22 -0
- data/lib/oxidized/model/uplinkolt.rb +46 -0
- data/lib/oxidized/model/vyatta.rb +2 -2
- data/lib/oxidized/model/xos.rb +7 -0
- data/lib/oxidized/node.rb +30 -18
- data/lib/oxidized/nodes.rb +13 -5
- data/lib/oxidized/output/file.rb +45 -42
- data/lib/oxidized/output/git.rb +185 -160
- data/lib/oxidized/output/gitcrypt.rb +188 -186
- data/lib/oxidized/output/http.rb +53 -51
- data/lib/oxidized/output/output.rb +6 -4
- data/lib/oxidized/source/csv.rb +44 -49
- data/lib/oxidized/source/http.rb +63 -81
- data/lib/oxidized/source/jsonfile.rb +63 -0
- data/lib/oxidized/source/source.rb +43 -18
- data/lib/oxidized/source/sql.rb +66 -59
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +22 -16
- metadata +111 -15
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
services:
|
|
2
2
|
oxidized:
|
|
3
3
|
# Choose the image that you want to test
|
|
4
|
-
# image: docker.io/oxidized/oxidized:0.
|
|
5
|
-
image: docker.io/oxidized/oxidized:latest
|
|
4
|
+
# image: docker.io/oxidized/oxidized:0.30.1
|
|
5
|
+
# image: docker.io/oxidized/oxidized:latest
|
|
6
|
+
# local/oxidized is build by "make oxidized-image" and "make run"
|
|
7
|
+
image: local/oxidized
|
|
6
8
|
ports:
|
|
7
9
|
- 127.0.0.1:8042:8888/tcp
|
|
8
10
|
environment:
|
|
@@ -13,9 +15,16 @@ services:
|
|
|
13
15
|
volumes:
|
|
14
16
|
- ./oxidized-config:/home/oxidized/.config/oxidized
|
|
15
17
|
- ./oxidized-ssh:/home/oxidized/.ssh
|
|
18
|
+
|
|
16
19
|
# This is a simulated network device for the example to work out of the box
|
|
17
20
|
asternos-device:
|
|
18
21
|
image: localhost/local/model
|
|
19
22
|
volumes:
|
|
20
23
|
- ./model-simulation/asternos.sh:/home/oxidized/.profile
|
|
21
24
|
- ./model-simulation/asternos.sh:/home/admin/.profile
|
|
25
|
+
|
|
26
|
+
# This is a gitserver to push our configs
|
|
27
|
+
gitserver:
|
|
28
|
+
image: localhost/local/gitserver
|
|
29
|
+
volumes:
|
|
30
|
+
- ./gitserver/repo.git:/home/git/repo.git
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
repo.git
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM docker.io/phusion/baseimage:noble-1.0.0
|
|
2
|
+
|
|
3
|
+
# Use baseimage-docker's init system.
|
|
4
|
+
CMD ["/sbin/my_init"]
|
|
5
|
+
|
|
6
|
+
# enable ssh
|
|
7
|
+
RUN rm -f /etc/service/sshd/down
|
|
8
|
+
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
|
|
9
|
+
|
|
10
|
+
# Add user for the gitserver. The password is "git"
|
|
11
|
+
RUN useradd -m git -p '$6$32WDb0LTFyQkLffy$u15COVx7CQ4tgp4JT4DO4LJ96q/jwFSpuZC3WrllNQDNa6nW1LhJKW9rLV57ak3rj9Ln./aRA85jzeof1B0Gi1' -s /bin/bash -u 30001
|
|
12
|
+
|
|
13
|
+
# And install git
|
|
14
|
+
RUN install_clean git
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
username: oxidized
|
|
3
|
+
password: oxidized
|
|
4
|
+
resolve_dns: true
|
|
5
|
+
interval: 3600
|
|
6
|
+
use_syslog: false
|
|
7
|
+
debug: false
|
|
8
|
+
threads: 30
|
|
9
|
+
use_max_threads: true
|
|
10
|
+
timeout: 20
|
|
11
|
+
retries: 3
|
|
12
|
+
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
|
|
13
|
+
rest: 0.0.0.0:8888
|
|
14
|
+
next_adds_job: false
|
|
15
|
+
vars: {}
|
|
16
|
+
groups: {}
|
|
17
|
+
group_map: {}
|
|
18
|
+
models: {}
|
|
19
|
+
pid: "~/.config/oxidized/pid"
|
|
20
|
+
crash:
|
|
21
|
+
directory: "~/.config/oxidized/crashes"
|
|
22
|
+
hostnames: false
|
|
23
|
+
stats:
|
|
24
|
+
history_size: 10
|
|
25
|
+
input:
|
|
26
|
+
default: ssh
|
|
27
|
+
debug: false
|
|
28
|
+
ssh:
|
|
29
|
+
secure: false
|
|
30
|
+
ftp:
|
|
31
|
+
passive: true
|
|
32
|
+
utf8_encoded: true
|
|
33
|
+
output:
|
|
34
|
+
default: file
|
|
35
|
+
file:
|
|
36
|
+
directory: "~/.config/oxidized/configs/"
|
|
37
|
+
source:
|
|
38
|
+
default: csv
|
|
39
|
+
csv:
|
|
40
|
+
file: "~/.config/oxidized/router.db"
|
|
41
|
+
delimiter: !ruby/regexp /:/
|
|
42
|
+
map:
|
|
43
|
+
name: 0
|
|
44
|
+
model: 1
|
|
45
|
+
ip: 2
|
|
46
|
+
gpg: false
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
username: oxidized
|
|
3
|
+
password: oxidized
|
|
4
|
+
resolve_dns: true
|
|
5
|
+
interval: 3600
|
|
6
|
+
use_syslog: false
|
|
7
|
+
debug: false
|
|
8
|
+
threads: 30
|
|
9
|
+
use_max_threads: true
|
|
10
|
+
timeout: 20
|
|
11
|
+
retries: 3
|
|
12
|
+
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
|
|
13
|
+
rest: 0.0.0.0:8888
|
|
14
|
+
next_adds_job: false
|
|
15
|
+
vars: {}
|
|
16
|
+
groups: {}
|
|
17
|
+
group_map: {}
|
|
18
|
+
models: {}
|
|
19
|
+
pid: "~/.config/oxidized/pid"
|
|
20
|
+
crash:
|
|
21
|
+
directory: "~/.config/oxidized/crashes"
|
|
22
|
+
hostnames: false
|
|
23
|
+
stats:
|
|
24
|
+
history_size: 10
|
|
25
|
+
input:
|
|
26
|
+
default: ssh
|
|
27
|
+
debug: false
|
|
28
|
+
ssh:
|
|
29
|
+
secure: false
|
|
30
|
+
ftp:
|
|
31
|
+
passive: true
|
|
32
|
+
utf8_encoded: true
|
|
33
|
+
output:
|
|
34
|
+
default: git
|
|
35
|
+
git:
|
|
36
|
+
user: Oxidized
|
|
37
|
+
email: o@example.com
|
|
38
|
+
repo: "~/.config/oxidized/oxidized.git"
|
|
39
|
+
source:
|
|
40
|
+
default: csv
|
|
41
|
+
csv:
|
|
42
|
+
file: "~/.config/oxidized/router.db"
|
|
43
|
+
delimiter: !ruby/regexp /:/
|
|
44
|
+
map:
|
|
45
|
+
name: 0
|
|
46
|
+
model: 1
|
|
47
|
+
ip: 2
|
|
48
|
+
gpg: false
|
|
49
|
+
hooks:
|
|
50
|
+
push_to_remote:
|
|
51
|
+
type: githubrepo
|
|
52
|
+
events:
|
|
53
|
+
- post_store
|
|
54
|
+
remote_repo: git@gitserver:repo.git
|
|
55
|
+
username: git
|
|
56
|
+
password: git
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
known_hosts
|
data/lib/oxidized/config.rb
CHANGED
|
@@ -17,6 +17,8 @@ module Oxidized
|
|
|
17
17
|
def self.load(cmd_opts = {})
|
|
18
18
|
usrdir = File.expand_path(cmd_opts[:home_dir] || Oxidized::Config::ROOT)
|
|
19
19
|
cfgfile = cmd_opts[:config_file] || 'config'
|
|
20
|
+
# configuration file with full path as a class instance variable
|
|
21
|
+
@configfile = File.join(usrdir, cfgfile)
|
|
20
22
|
asetus = Asetus.new(name: 'oxidized', load: false, key_to_s: true, usrdir: usrdir, cfgfile: cfgfile)
|
|
21
23
|
Oxidized.asetus = asetus
|
|
22
24
|
|
|
@@ -65,13 +67,17 @@ module Oxidized
|
|
|
65
67
|
raise InvalidConfig, "Error loading config: #{e.message}"
|
|
66
68
|
end
|
|
67
69
|
|
|
68
|
-
raise NoConfig,
|
|
70
|
+
raise NoConfig, "edit #{@configfile}" if asetus.create
|
|
69
71
|
|
|
70
72
|
# override if comand line flag given
|
|
71
73
|
asetus.cfg.debug = cmd_opts[:debug] if cmd_opts[:debug]
|
|
72
74
|
|
|
73
75
|
asetus
|
|
74
76
|
end
|
|
77
|
+
|
|
78
|
+
class << self
|
|
79
|
+
attr_reader :configfile
|
|
80
|
+
end
|
|
75
81
|
end
|
|
76
82
|
|
|
77
83
|
class << self
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
require 'rugged'
|
|
2
|
+
|
|
1
3
|
class GithubRepo < Oxidized::Hook
|
|
2
4
|
def validate_cfg!
|
|
3
5
|
raise KeyError, 'hook.remote_repo is required' unless cfg.has_key?('remote_repo')
|
|
4
6
|
end
|
|
5
7
|
|
|
6
8
|
def run_hook(ctx)
|
|
9
|
+
unless ctx.node.repo
|
|
10
|
+
log "Oxidized output is not git, can't push to remote", :error
|
|
11
|
+
return
|
|
12
|
+
end
|
|
7
13
|
repo = Rugged::Repository.new(ctx.node.repo)
|
|
8
14
|
creds = credentials(ctx.node)
|
|
9
15
|
url = remote_repo(ctx.node)
|
|
10
16
|
|
|
11
17
|
if url.nil? || url.empty?
|
|
12
|
-
log "No repository defined for #{ctx.node.group}/#{ctx.node.name}", :
|
|
18
|
+
log "No repository defined for #{ctx.node.group}/#{ctx.node.name}", :error
|
|
13
19
|
return
|
|
14
20
|
end
|
|
15
21
|
|
|
@@ -23,21 +29,39 @@ class GithubRepo < Oxidized::Hook
|
|
|
23
29
|
end
|
|
24
30
|
remote = repo.remotes['origin']
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
begin
|
|
33
|
+
fetch_and_merge_remote(repo, creds)
|
|
34
|
+
remote.push([repo.head.name], credentials: creds)
|
|
35
|
+
rescue Rugged::NetworkError => e
|
|
36
|
+
if e.message == 'unsupported URL protocol'
|
|
37
|
+
log "Rugged does not support the git URL '#{url}'.", :warn
|
|
38
|
+
unless Rugged.features.include?(:ssh)
|
|
39
|
+
log 'You may need to install Rugged with ssh support ' \
|
|
40
|
+
'(gem install rugged -- --with-ssh)', :warn
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
# re-raise exception for the calling method
|
|
44
|
+
raise
|
|
45
|
+
end
|
|
29
46
|
end
|
|
30
47
|
|
|
31
48
|
def fetch_and_merge_remote(repo, creds)
|
|
32
49
|
result = repo.fetch('origin', [repo.head.name], credentials: creds)
|
|
33
50
|
log result.inspect, :debug
|
|
34
51
|
|
|
35
|
-
|
|
36
|
-
|
|
52
|
+
their_branch = remote_branch(repo)
|
|
53
|
+
|
|
54
|
+
unless their_branch
|
|
55
|
+
log 'remote branch does not exist yet, nothing to merge', :debug
|
|
37
56
|
return
|
|
38
57
|
end
|
|
39
58
|
|
|
40
|
-
|
|
59
|
+
result = repo.merge_analysis(their_branch.target_id)
|
|
60
|
+
|
|
61
|
+
if result.include? :up_to_date
|
|
62
|
+
log 'nothing to merge', :debug
|
|
63
|
+
return
|
|
64
|
+
end
|
|
41
65
|
|
|
42
66
|
log "merging fetched branch #{their_branch.name}", :debug
|
|
43
67
|
|
|
@@ -97,4 +121,10 @@ class GithubRepo < Oxidized::Hook
|
|
|
97
121
|
cfg.remote_repo[node.group].url
|
|
98
122
|
end
|
|
99
123
|
end
|
|
124
|
+
|
|
125
|
+
# Returns a Rugged::Branch to the remote branch or nil if it doen't exist
|
|
126
|
+
def remote_branch(repo)
|
|
127
|
+
head_branch = repo.branches[repo.head.name]
|
|
128
|
+
repo.branches['origin/' + head_branch.name]
|
|
129
|
+
end
|
|
100
130
|
end
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'slack_ruby_client'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'net/http'
|
|
2
4
|
|
|
3
5
|
# defaults to posting a diff, if messageformat is supplied them a message will be posted too
|
|
4
6
|
# diff defaults to true
|
|
@@ -9,6 +11,30 @@ class SlackDiff < Oxidized::Hook
|
|
|
9
11
|
raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
|
|
10
12
|
end
|
|
11
13
|
|
|
14
|
+
def slack_upload(client, title, content, channel)
|
|
15
|
+
log "Posting diff as snippet to #{channel}"
|
|
16
|
+
upload_dest = client.files_getUploadURLExternal(filename: "change",
|
|
17
|
+
length: content.length,
|
|
18
|
+
snippet_type: "diff")
|
|
19
|
+
file_uri = URI.parse(upload_dest[:upload_url])
|
|
20
|
+
|
|
21
|
+
http = Net::HTTP.new(file_uri.host, file_uri.port)
|
|
22
|
+
http.use_ssl = true
|
|
23
|
+
|
|
24
|
+
request = Net::HTTP::Post.new(file_uri.request_uri, { Host: file_uri.host })
|
|
25
|
+
request.body = content
|
|
26
|
+
response = http.request(request)
|
|
27
|
+
|
|
28
|
+
raise 'Slack file upload failed' unless response.is_a? Net::HTTPSuccess
|
|
29
|
+
|
|
30
|
+
files = [{
|
|
31
|
+
id: upload_dest[:file_id],
|
|
32
|
+
title: title
|
|
33
|
+
}]
|
|
34
|
+
client.files_completeUploadExternal(channel_id: channel,
|
|
35
|
+
files: files.to_json)
|
|
36
|
+
end
|
|
37
|
+
|
|
12
38
|
def run_hook(ctx)
|
|
13
39
|
return unless ctx.node
|
|
14
40
|
return unless ctx.event.to_s == "post_store"
|
|
@@ -26,12 +52,8 @@ class SlackDiff < Oxidized::Hook
|
|
|
26
52
|
diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
|
|
27
53
|
unless diff == "no diffs"
|
|
28
54
|
title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
|
|
29
|
-
|
|
30
|
-
client
|
|
31
|
-
content: diff[:patch].lines.to_a[4..-1].join,
|
|
32
|
-
filetype: "diff",
|
|
33
|
-
title: title,
|
|
34
|
-
filename: "change")
|
|
55
|
+
content = diff[:patch].lines.to_a[4..-1].join
|
|
56
|
+
slack_upload(client, title, content, cfg.channel)
|
|
35
57
|
end
|
|
36
58
|
end
|
|
37
59
|
# message custom formatted - optional
|
data/lib/oxidized/input/http.rb
CHANGED
data/lib/oxidized/manager.rb
CHANGED
|
@@ -5,15 +5,16 @@ module Oxidized
|
|
|
5
5
|
require 'oxidized/source/source'
|
|
6
6
|
class Manager
|
|
7
7
|
class << self
|
|
8
|
-
def load(dir, file)
|
|
8
|
+
def load(dir, file, namespace)
|
|
9
9
|
require File.join dir, file + '.rb'
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
|
|
11
|
+
# Search the object to load in namespace
|
|
12
|
+
klass = namespace.constants.find { |const| const.to_s.casecmp(file).zero? }
|
|
13
|
+
|
|
14
|
+
return false unless klass
|
|
15
|
+
|
|
16
|
+
klass = namespace.const_get klass
|
|
17
|
+
|
|
17
18
|
i = klass.new
|
|
18
19
|
i.setup if i.respond_to? :setup
|
|
19
20
|
{ file => klass }
|
|
@@ -33,32 +34,32 @@ module Oxidized
|
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
def add_input(name)
|
|
36
|
-
loader @input, Config::INPUT_DIR, "input", name
|
|
37
|
+
loader @input, Config::INPUT_DIR, "input", name, Oxidized
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def add_output(name)
|
|
40
|
-
loader @output, Config::OUTPUT_DIR, "output", name
|
|
41
|
+
loader @output, Config::OUTPUT_DIR, "output", name, Oxidized::Output
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def add_source(name)
|
|
44
|
-
loader @source, Config::SOURCE_DIR, "source", name
|
|
45
|
+
loader @source, Config::SOURCE_DIR, "source", name, Oxidized::Source
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
def add_model(name)
|
|
48
|
-
loader @model, Config::MODEL_DIR, "model", name
|
|
49
|
+
loader @model, Config::MODEL_DIR, "model", name, Object
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
def add_hook(name)
|
|
52
|
-
loader @hook, Config::HOOK_DIR, "hook", name
|
|
53
|
+
loader @hook, Config::HOOK_DIR, "hook", name, Object
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
private
|
|
56
57
|
|
|
57
58
|
# if local version of file exists, load it, else load global - return falsy value if nothing loaded
|
|
58
|
-
def loader(hash, global_dir, local_dir, name)
|
|
59
|
+
def loader(hash, global_dir, local_dir, name, namespace)
|
|
59
60
|
dir = File.join(Config::ROOT, local_dir)
|
|
60
|
-
map = Manager.load(dir, name) if File.exist? File.join(dir, name + ".rb")
|
|
61
|
-
map ||= Manager.load(global_dir, name)
|
|
61
|
+
map = Manager.load(dir, name, namespace) if File.exist? File.join(dir, name + ".rb")
|
|
62
|
+
map ||= Manager.load(global_dir, name, namespace)
|
|
62
63
|
hash.merge!(map) if map
|
|
63
64
|
end
|
|
64
65
|
end
|
data/lib/oxidized/model/aoscx.rb
CHANGED
|
@@ -56,9 +56,23 @@ class Aoscx < Oxidized::Model
|
|
|
56
56
|
cmd 'show environment' do |cfg|
|
|
57
57
|
cfg.gsub! /^(LC.*\s+)\d+\s+$/, '\\1<hidden>'
|
|
58
58
|
cfg.gsub! /^(\d\/\d\/\d.*\s+)\d+\s+$/, '\\1<hidden>'
|
|
59
|
-
cfg.gsub! /^(\d
|
|
59
|
+
cfg.gsub! /^(\d+\/?\S+\s+\S+\s+)\d+\.\d+\s+C\s+(.*)/, '\\1<hidden> \\2'
|
|
60
60
|
cfg.gsub! /^(LC.*\s+)\d+\.\d+\s+(C.*)$/, '\\1 <hidden> \\2'
|
|
61
|
-
cfg.gsub! /^(\S+\s+\S+\s+\s+\S+\s+)(slow|normal|medium|fast|max)(\
|
|
61
|
+
cfg.gsub! /^(\S+\s+\S+\s+\s+\S+\s+)(slow|normal|medium|fast|max)\s+(\S+\s+\S+\s+)\d+[[:blank:]]+/, '\\1<speed> \\3<rpm>'
|
|
62
|
+
# match show environment power-consumption on VSF or standadlone, non-chassis and non-6400 switch, e.g. "2 6300M 48G 4SFP56 Swch 156.00 155.94"
|
|
63
|
+
cfg.gsub! /^(\d+\s+.+\s+)(\s{2}\d{2}\.\d{2}|\s{1}\d{3}\.\d{2}|\d{4}\.\d{2})(\s+)(\s{2}\d{2}\.\d{2}|\s{1}\d{3}\.\d{2}|\d{4}\.\d{2})$/, '\\1<power>\\3<power>'
|
|
64
|
+
# match show environment power-consumption on 6400 or chassis switches, e.g. "1/4 line-card-module R0X39A 6400 48p 1GbE CL4 PoE 4SFP56 Mod 54 W"
|
|
65
|
+
cfg.gsub! /^(\d+\/?\d*\s+.+\s+)(\s{1,4}\d{1,3})\sW\s*$/, '\\1<power>'
|
|
66
|
+
# match show environment power-consumption on 6400 or chassis switches, e.g. "Module Total Power Usage 13000 W", match up to a 5-digit number and keep table formatting.
|
|
67
|
+
cfg.gsub! /^(Module|Chassis)\s(Total\sPower\sUsage)(\s+)\s(\s{4}\d{1}|\s{3}\d{2}|\s{2}\d{3}|\s{1}\d{4}|\d{5})\sW\s*$/, '\\1 <power>'
|
|
68
|
+
# match show environment power-consumption on 6400 or chassis switches, e.g. "Chassis Total Power Usage 13000 W", match up to a 5-digit number and keep table formatting.
|
|
69
|
+
cfg.gsub! /^(Chassis\sTotal\sPower\sUsage)(\s+)(\s{4}\d{1}|\s{3}\d{2}|\s{2}\d{3}|\s{1}\d{4}|\d{5})\sW\s*$/, '\\1\\2<power>'
|
|
70
|
+
# match show environment power-consumption on 8400 or chassis switches, up to a 5-digit number, example matches:
|
|
71
|
+
# e.g. "Chassis Total Power Allocated (total of all max wattages) 4130 W"
|
|
72
|
+
# e.g. "Chassis Total Power Unallocated 15860 W"
|
|
73
|
+
cfg.gsub! /^(Chassis\sTotal\sPower\s)(Allocated|Unallocated)(\s|\s\(total of all max wattages\))(\s+)(\s{4}\d{1}|\s{3}\d{2}|\s{2}\d{3}|\s{1}\d{4}|\d{5})\sW\s*$/, '\\1\\2\\3\\4<power>'
|
|
74
|
+
# match Total Power Consumption:
|
|
75
|
+
cfg.gsub! /^([t|T]otal\s[p|P]ower\s[c|C]onsumption\s+)(\d+\.\d\d)$/, '\\1<power>'
|
|
62
76
|
comment cfg
|
|
63
77
|
end
|
|
64
78
|
|
data/lib/oxidized/model/aosw.rb
CHANGED
|
@@ -12,7 +12,13 @@ class AOSW < Oxidized::Model
|
|
|
12
12
|
# All IAPs connected to a Instant Controller will have the same config output. Only the controller needs to be monitored.
|
|
13
13
|
|
|
14
14
|
comment '# '
|
|
15
|
-
prompt
|
|
15
|
+
# see /spec/model/aosw_spec.rb for prompt examples
|
|
16
|
+
prompt /^\(?[\w\:.@-]+\)? ?[*^]?(\[[\w\/]+\] ?)?[#>] ?$/
|
|
17
|
+
|
|
18
|
+
# Ignore cariage returns - also for the prompt
|
|
19
|
+
expect "\r" do |data, re|
|
|
20
|
+
data.gsub re, ''
|
|
21
|
+
end
|
|
16
22
|
|
|
17
23
|
cmd :all do |cfg|
|
|
18
24
|
cfg.cut_both
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
class ArubaInstant < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
# Aruba IAP, Instant Controller
|
|
5
|
+
|
|
6
|
+
comment '# '
|
|
7
|
+
prompt(/^[\w\:.@-]+[#>] $/)
|
|
8
|
+
|
|
9
|
+
cmd :all do |cfg|
|
|
10
|
+
# Remove command echo and prompt
|
|
11
|
+
cfg.cut_both
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
cmd :secret do |cfg|
|
|
15
|
+
cfg.gsub!(/ipsec (\S+)$/, 'ipsec <secret removed>')
|
|
16
|
+
cfg.gsub!(/community (\S+)$/, 'community <secret removed>')
|
|
17
|
+
cfg.gsub!(/^(snmp-server host [\d.]+ version 2c) \S+ (.*)$/, '\1 <secret removed> \2')
|
|
18
|
+
# MAS format: mgmt-user <username> <accesslevel> <password hash>
|
|
19
|
+
# IAP format (root user): mgmt-user <username> <password hash>
|
|
20
|
+
# IAP format: mgmt-user <username> <password hash> <access level>
|
|
21
|
+
cfg.gsub!(/mgmt-user (\S+) (root|guest-provisioning|network-operations|read-only|location-api-mgmt) (\S+)$/, 'mgmt-user \1 \2 <secret removed>') # MAS & Wireless Controler
|
|
22
|
+
cfg.gsub!(/mgmt-user (\S+) (\S+)( (read-only|guest-mgmt))?$/, 'mgmt-user \1 <secret removed> \3') # IAP
|
|
23
|
+
cfg.gsub!(/key (\S+)$/, 'key <secret removed>')
|
|
24
|
+
cfg.gsub!(/wpa-passphrase (\S+)$/, 'wpa-passphrase <secret removed>')
|
|
25
|
+
cfg.gsub!(/bkup-passwords (\S+)$/, 'bkup-passwords <secret removed>')
|
|
26
|
+
cfg.gsub!(/user (\S+) (\S+) (\S+)$/, 'user \1 <secret removed> \3')
|
|
27
|
+
cfg.gsub!(/virtual-controller-key (\S+)$/, 'virtual-controller-key <secret removed>')
|
|
28
|
+
cfg.gsub!(/^(hash-mgmt-user .* password \S+) \S+( usertype .*)?$/, '\1 <secret removed>\2')
|
|
29
|
+
cfg
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# get software version
|
|
33
|
+
cmd 'show version' do |cfg|
|
|
34
|
+
out = ''
|
|
35
|
+
cfg.each_line do |line|
|
|
36
|
+
next if line =~ /^(Switch|AP) uptime is /
|
|
37
|
+
|
|
38
|
+
next if line =~ /^Reboot Time and Cause/
|
|
39
|
+
|
|
40
|
+
out += line
|
|
41
|
+
end
|
|
42
|
+
comment out
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Get serial number
|
|
46
|
+
cmd 'show activate status' do |cfg|
|
|
47
|
+
out = ''
|
|
48
|
+
cfg.each_line do |line|
|
|
49
|
+
next if line =~ /^Activate /
|
|
50
|
+
|
|
51
|
+
next if line =~ /^Provision interval/
|
|
52
|
+
|
|
53
|
+
next if line =~ /^Cloud Activation Key/
|
|
54
|
+
|
|
55
|
+
out += line
|
|
56
|
+
end
|
|
57
|
+
comment out + "\n"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Get controlled WLAN-AP
|
|
61
|
+
cmd 'show aps' do |cfg|
|
|
62
|
+
out = ''
|
|
63
|
+
cfg.each_line do |line|
|
|
64
|
+
out += if line.match?(/^Name/)
|
|
65
|
+
line.sub(/^(Name +IP Address +).*(Type +IPv6 Address +).*(Serial #).*$/, '\1\2\3')
|
|
66
|
+
else
|
|
67
|
+
line.sub(/^(\S+ +\S+ +)(?:\S+ +){3}(\S+ +\S+ +)(?:\S+ +){2}(\S+) +.*$/, '\1\2\3')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
comment out + "\n"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
cmd 'show running-config no-encrypt'
|
|
74
|
+
|
|
75
|
+
cfg :telnet do
|
|
76
|
+
username(/^User:\s*/)
|
|
77
|
+
password(/^Password:\s*/)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
cfg :telnet, :ssh do
|
|
81
|
+
if vars :enable
|
|
82
|
+
post_login do
|
|
83
|
+
cmd "enable", /^[pP]assword:/
|
|
84
|
+
cmd vars(:enable)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
pre_logout 'exit' if vars :enable
|
|
88
|
+
pre_logout 'exit'
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -12,14 +12,14 @@ class AudioCodes < Oxidized::Model
|
|
|
12
12
|
data.sub re, ''
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
cmd
|
|
15
|
+
cmd "show running-config\r\n" do |cfg|
|
|
16
16
|
cfg
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
cfg :ssh do
|
|
20
20
|
username /^login as:\s$/
|
|
21
21
|
password /^.+password:\s$/
|
|
22
|
-
pre_logout
|
|
22
|
+
pre_logout "exit\r\n"
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
cfg :telnet do
|
data/lib/oxidized/model/cnos.rb
CHANGED
|
@@ -4,18 +4,20 @@ class CNOS < Oxidized::Model
|
|
|
4
4
|
|
|
5
5
|
comment '! '
|
|
6
6
|
|
|
7
|
-
cmd :
|
|
8
|
-
cfg.
|
|
7
|
+
cmd :secret do |cfg|
|
|
8
|
+
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
|
|
9
|
+
cfg.gsub! /^(username .+ (password|secret) \d) .+/, '\\1 <secret hidden>'
|
|
10
|
+
cfg.gsub! /^(enable (password|secret)( level \d+)?( \d)?) .+/, '\\1 <secret hidden>'
|
|
11
|
+
cfg
|
|
9
12
|
end
|
|
10
13
|
|
|
11
|
-
cmd
|
|
12
|
-
cfg
|
|
13
|
-
cfg.
|
|
14
|
-
cfg
|
|
14
|
+
cmd :all do |cfg|
|
|
15
|
+
cfg = cfg.delete("\r")
|
|
16
|
+
cfg.cut_both
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
cmd 'show version' do |cfg|
|
|
18
|
-
cfg.
|
|
20
|
+
cfg = cfg.each_line.reject { |line| line.match /\ uptime\ is\ / }.join
|
|
19
21
|
comment cfg
|
|
20
22
|
end
|
|
21
23
|
|
|
@@ -23,9 +25,10 @@ class CNOS < Oxidized::Model
|
|
|
23
25
|
comment cfg
|
|
24
26
|
end
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
cmd 'show running-config' do |cfg|
|
|
29
|
+
# remove empty lines
|
|
30
|
+
cfg = cfg.each_line.reject { |line| line.match /^[\r\n\s\u0000#]+$/ }.join
|
|
31
|
+
cfg
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
cfg :telnet, :ssh do
|
|
@@ -21,9 +21,12 @@ class Cumulus < Oxidized::Model
|
|
|
21
21
|
# show the persistent configuration
|
|
22
22
|
pre do
|
|
23
23
|
use_nclu = vars(:cumulus_use_nclu) || false
|
|
24
|
+
use_nvue = vars(:cumulus_use_nvue) || false
|
|
24
25
|
|
|
25
26
|
if use_nclu
|
|
26
27
|
cfg = cmd 'net show configuration commands'
|
|
28
|
+
elsif use_nvue
|
|
29
|
+
cfg = cmd 'nv config show --color off'
|
|
27
30
|
else
|
|
28
31
|
# Set FRR or Quagga in config
|
|
29
32
|
routing_daemon = vars(:cumulus_routing_daemon) ? vars(:cumulus_routing_daemon).downcase : 'quagga'
|
data/lib/oxidized/model/dlink.rb
CHANGED
|
@@ -35,6 +35,9 @@ class DlinkNextGen < Oxidized::Model
|
|
|
35
35
|
cmd 'show running-config' do |cfg|
|
|
36
36
|
cfg.gsub! /^(snmp-server community ["\w]+) \S+/, '\\1 <removed>'
|
|
37
37
|
cfg.gsub! /^(username [\w.@-]+ privilege \d{1,2} password \d{1,2}) \S+/, '\\1 <removed>'
|
|
38
|
+
cfg.gsub! /^(!System Up Time).*/, '\\1 <removed>'
|
|
39
|
+
cfg.gsub! /^(!Current SNTP Synchronized Time:).*/, '\\1 <removed>'
|
|
40
|
+
cfg.gsub! /^(\s+ppp (chap|pap) password \d) .+/, '\\1 <secret hidden>'
|
|
38
41
|
cfg
|
|
39
42
|
end
|
|
40
43
|
|