oxidized 0.30.1 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +3 -4
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +18 -3
- data/.rubocop_todo.yml +4 -11
- data/CHANGELOG.md +93 -1
- data/CONTRIBUTING.md +5 -0
- data/Dockerfile +84 -20
- data/README.md +5 -21
- data/Rakefile +31 -2
- data/docs/Configuration.md +50 -14
- data/docs/Creating-Models.md +75 -4
- data/docs/DeviceSimulation.md +184 -0
- data/docs/Hooks.md +39 -5
- data/docs/Issues.md +97 -0
- data/docs/Model-Notes/APC_AOS.md +29 -16
- data/docs/Model-Notes/Cumulus.md +5 -0
- data/docs/Model-Notes/FSOS.md +6 -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/ModelUnitTests.md +186 -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 +14 -7
- data/docs/Troubleshooting.md +35 -0
- data/examples/podman-compose/Makefile +59 -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/extra/device2yaml.rb +245 -0
- data/extra/gitdiff-msteams.sh +32 -5
- data/extra/nagios_check_failing_nodes.rb +1 -1
- data/extra/rest_client.rb +1 -1
- data/lib/oxidized/config.rb +8 -2
- 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/ssh.rb +13 -5
- data/lib/oxidized/input/telnet.rb +1 -1
- data/lib/oxidized/manager.rb +17 -16
- data/lib/oxidized/model/aos7.rb +2 -0
- data/lib/oxidized/model/aoscx.rb +16 -2
- data/lib/oxidized/model/aosw.rb +8 -2
- data/lib/oxidized/model/apc_aos.rb +1 -1
- data/lib/oxidized/model/arubainstant.rb +90 -0
- data/lib/oxidized/model/asa.rb +2 -1
- data/lib/oxidized/model/asyncos.rb +1 -1
- data/lib/oxidized/model/audiocodes.rb +2 -2
- data/lib/oxidized/model/cnos.rb +13 -10
- data/lib/oxidized/model/cumulus.rb +19 -2
- 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/enterprise_sonic.rb +46 -0
- 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/fsos.rb +5 -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/junos.rb +1 -1
- data/lib/oxidized/model/kornfeldos.rb +33 -0
- data/lib/oxidized/model/lenovonos.rb +2 -0
- data/lib/oxidized/model/linuxgeneric.rb +1 -1
- data/lib/oxidized/model/model.rb +2 -2
- 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/sonicos.rb +8 -2
- data/lib/oxidized/model/tplink.rb +1 -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 +73 -18
- data/lib/oxidized/source/sql.rb +66 -59
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +25 -18
- metadata +115 -21
data/extra/gitdiff-msteams.sh
CHANGED
@@ -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
|
-
|
90
|
-
|
91
|
-
|
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(
|
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 =
|
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
|
data/lib/oxidized/config.rb
CHANGED
@@ -17,7 +17,9 @@ 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
|
-
|
20
|
+
# configuration file with full path as a class instance variable
|
21
|
+
@configfile = File.join(usrdir, cfgfile)
|
22
|
+
asetus = Asetus.new(name: 'oxidized', load: false, usrdir: usrdir, cfgfile: cfgfile)
|
21
23
|
Oxidized.asetus = asetus
|
22
24
|
|
23
25
|
asetus.default.username = 'username'
|
@@ -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/input/ssh.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
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/aos7.rb
CHANGED
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
|
@@ -111,7 +117,7 @@ class AOSW < Oxidized::Model
|
|
111
117
|
next if line =~ /Output \d Config/i
|
112
118
|
next if line =~ /(Tachometers|Temperatures|Voltages)/
|
113
119
|
next if line =~ /((Card|CPU) Temperature|Chassis Fan|VMON1[0-9])/
|
114
|
-
next if line =~ /[0-9]+\s+(RPMS?|m?V|C)/i
|
120
|
+
next if line =~ /[0-9]+\s+(RPMS?|m?V|C|W)/i
|
115
121
|
|
116
122
|
out << line.strip
|
117
123
|
end
|
@@ -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
|
data/lib/oxidized/model/asa.rb
CHANGED
@@ -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
|
|
@@ -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
|