oxidized 0.28.0 → 0.29.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/publishdocker.yml +8 -1
- data/.github/workflows/ruby.yml +42 -0
- data/.rubocop.yml +30 -10
- data/.rubocop_todo.yml +95 -41
- data/CHANGELOG.md +139 -2
- data/Dockerfile +13 -9
- data/README.md +66 -32
- data/Rakefile +2 -0
- data/docs/Configuration.md +49 -7
- data/docs/Creating-Models.md +10 -4
- data/docs/Hooks.md +35 -6
- data/docs/Model-Notes/ADVA.md +12 -0
- data/docs/Model-Notes/Cumulus.md +7 -1
- data/docs/Model-Notes/IOS.md +36 -0
- data/docs/Model-Notes/JunOS.md +3 -3
- data/docs/Model-Notes/LenovoNOS.md +29 -0
- data/docs/Model-Notes/LinksysSRW.md +15 -0
- data/docs/Model-Notes/Nokia.md +3 -0
- data/docs/Model-Notes/OS10.md +33 -0
- data/docs/Model-Notes/PanOS_API.md +28 -0
- data/docs/Model-Notes/README.md +2 -0
- data/docs/Sources.md +18 -0
- data/docs/Supported-OS-Types.md +51 -6
- data/docs/Troubleshooting.md +1 -1
- data/extra/gitdiff-msteams.sh +91 -0
- data/extra/nagios_check_failing_nodes.rb +6 -9
- data/extra/oxidized-report-git-commits +71 -14
- data/extra/oxidized.init +2 -5
- data/extra/oxidized.logrotate +1 -0
- data/extra/oxidized.runit +4 -1
- data/extra/oxidized.service +5 -8
- data/extra/rest_client.rb +1 -1
- data/extra/syslog.rb +2 -2
- data/lib/oxidized/cli.rb +1 -1
- data/lib/oxidized/config/vars.rb +5 -2
- data/lib/oxidized/config.rb +6 -3
- data/lib/oxidized/core.rb +1 -1
- data/lib/oxidized/hook/exec.rb +6 -6
- data/lib/oxidized/hook/githubrepo.rb +42 -11
- data/lib/oxidized/hook/slackdiff.rb +2 -2
- data/lib/oxidized/hook/xmppdiff.rb +45 -25
- data/lib/oxidized/hook.rb +4 -8
- data/lib/oxidized/input/exec.rb +1 -1
- data/lib/oxidized/input/input.rb +1 -0
- data/lib/oxidized/input/ssh.rb +23 -20
- data/lib/oxidized/input/telnet.rb +52 -44
- data/lib/oxidized/job.rb +1 -0
- data/lib/oxidized/jobs.rb +11 -6
- data/lib/oxidized/manager.rb +1 -0
- data/lib/oxidized/model/acmepacket.rb +38 -0
- data/lib/oxidized/model/adtran.rb +5 -3
- data/lib/oxidized/model/adva.rb +66 -0
- data/lib/oxidized/model/airfiber.rb +1 -1
- data/lib/oxidized/model/aoscx.rb +96 -0
- data/lib/oxidized/model/aosw.rb +1 -1
- data/lib/oxidized/model/asa.rb +2 -0
- data/lib/oxidized/model/awplus.rb +1 -1
- data/lib/oxidized/model/bdcom.rb +49 -0
- data/lib/oxidized/model/cambiumepmp.rb +17 -0
- data/lib/oxidized/model/casa.rb +4 -1
- data/lib/oxidized/model/ciscoce.rb +12 -0
- data/lib/oxidized/model/ciscosmb.rb +2 -0
- data/lib/oxidized/model/comware.rb +16 -1
- data/lib/oxidized/model/cumulus.rb +58 -44
- data/lib/oxidized/model/dellx.rb +1 -3
- data/lib/oxidized/model/dlink.rb +2 -1
- data/lib/oxidized/model/edgecos.rb +22 -2
- data/lib/oxidized/model/edgeswitch.rb +4 -4
- data/lib/oxidized/model/eltex.rb +48 -0
- data/lib/oxidized/model/enterasys.rb +18 -3
- data/lib/oxidized/model/enterasys800.rb +29 -0
- data/lib/oxidized/model/eos.rb +2 -1
- data/lib/oxidized/model/fabricos.rb +1 -1
- data/lib/oxidized/model/fastiron.rb +3 -2
- data/lib/oxidized/model/fortios.rb +24 -11
- data/lib/oxidized/model/fortiwlc.rb +24 -0
- data/lib/oxidized/model/gaiaos.rb +40 -3
- data/lib/oxidized/model/h3c.rb +40 -0
- data/lib/oxidized/model/hatteras.rb +2 -2
- data/lib/oxidized/model/hios.rb +38 -0
- data/lib/oxidized/model/hpebladesystem.rb +1 -1
- data/lib/oxidized/model/ios.rb +13 -10
- data/lib/oxidized/model/iosxe.rb +1 -1
- data/lib/oxidized/model/ironware.rb +8 -4
- data/lib/oxidized/model/junos.rb +5 -1
- data/lib/oxidized/model/lancom.rb +23 -0
- data/lib/oxidized/model/lenovonos.rb +82 -0
- data/lib/oxidized/model/linksyssrw.rb +71 -0
- data/lib/oxidized/model/mlnxos.rb +2 -0
- data/lib/oxidized/model/model.rb +29 -3
- data/lib/oxidized/model/necix.rb +30 -0
- data/lib/oxidized/model/netgear.rb +5 -2
- data/lib/oxidized/model/netscaler.rb +38 -1
- data/lib/oxidized/model/nodegrid.rb +23 -0
- data/lib/oxidized/model/nxos.rb +3 -2
- data/lib/oxidized/model/openbsd.rb +9 -0
- data/lib/oxidized/model/opengear.rb +1 -1
- data/lib/oxidized/model/opnsense.rb +12 -4
- data/lib/oxidized/model/panos_api.rb +71 -0
- data/lib/oxidized/model/pfsense.rb +12 -7
- data/lib/oxidized/model/powerconnect.rb +1 -3
- data/lib/oxidized/model/procurve.rb +2 -2
- data/lib/oxidized/model/purityos.rb +8 -1
- data/lib/oxidized/model/quantaos.rb +1 -5
- data/lib/oxidized/model/routeros.rb +15 -2
- data/lib/oxidized/model/slxos.rb +1 -0
- data/lib/oxidized/model/smartcs.rb +40 -0
- data/lib/oxidized/model/sonicos.rb +9 -1
- data/lib/oxidized/model/srosmd.rb +97 -0
- data/lib/oxidized/model/stoneos.rb +6 -2
- data/lib/oxidized/model/supermicro.rb +1 -1
- data/lib/oxidized/model/swos.rb +9 -0
- data/lib/oxidized/model/timos.rb +1 -1
- data/lib/oxidized/model/tmos.rb +2 -1
- data/lib/oxidized/model/tplink.rb +2 -0
- data/lib/oxidized/model/trango.rb +11 -11
- data/lib/oxidized/model/truenas.rb +20 -0
- data/lib/oxidized/model/vrp.rb +1 -1
- data/lib/oxidized/model/xos.rb +4 -3
- data/lib/oxidized/model/yamaha.rb +57 -0
- data/lib/oxidized/model/zteolt.rb +52 -0
- data/lib/oxidized/model/zy1308.rb +11 -0
- data/lib/oxidized/node/stats.rb +1 -0
- data/lib/oxidized/node.rb +16 -11
- data/lib/oxidized/nodes.rb +7 -6
- data/lib/oxidized/output/file.rb +2 -1
- data/lib/oxidized/output/git.rb +4 -3
- data/lib/oxidized/output/gitcrypt.rb +5 -8
- data/lib/oxidized/output/http.rb +2 -0
- data/lib/oxidized/source/csv.rb +1 -0
- data/lib/oxidized/source/http.rb +4 -0
- data/lib/oxidized/source/source.rb +7 -2
- data/lib/oxidized/source/sql.rb +15 -5
- data/lib/oxidized/string.rb +9 -3
- data/lib/oxidized/version.rb +2 -2
- data/lib/oxidized/worker.rb +5 -5
- data/oxidized.gemspec +22 -16
- metadata +116 -29
- data/.travis.yml +0 -10
@@ -4,18 +4,32 @@ class GithubRepo < Oxidized::Hook
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def run_hook(ctx)
|
7
|
-
repo
|
7
|
+
repo = Rugged::Repository.new(ctx.node.repo)
|
8
|
+
creds = credentials(ctx.node)
|
9
|
+
url = remote_repo(ctx.node)
|
10
|
+
|
11
|
+
if url.nil? || url.empty?
|
12
|
+
log "No repository defined for #{ctx.node.group}/#{ctx.node.name}", :debug
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
8
16
|
log "Pushing local repository(#{repo.path})..."
|
9
|
-
|
10
|
-
log "to remote: #{remote.url}"
|
17
|
+
log "to remote: #{url}"
|
11
18
|
|
12
|
-
|
19
|
+
if repo.remotes['origin'].nil?
|
20
|
+
repo.remotes.create('origin', url)
|
21
|
+
elsif repo.remotes['origin'].url != url
|
22
|
+
repo.remotes.set_url('origin', url)
|
23
|
+
end
|
24
|
+
remote = repo.remotes['origin']
|
25
|
+
|
26
|
+
fetch_and_merge_remote(repo, creds)
|
13
27
|
|
14
|
-
remote.push([repo.head.name], credentials:
|
28
|
+
remote.push([repo.head.name], credentials: creds)
|
15
29
|
end
|
16
30
|
|
17
|
-
def fetch_and_merge_remote(repo)
|
18
|
-
result = repo.fetch('origin', [repo.head.name], credentials:
|
31
|
+
def fetch_and_merge_remote(repo, creds)
|
32
|
+
result = repo.fetch('origin', [repo.head.name], credentials: creds)
|
19
33
|
log result.inspect, :debug
|
20
34
|
|
21
35
|
unless result[:total_deltas].positive?
|
@@ -43,15 +57,20 @@ class GithubRepo < Oxidized::Hook
|
|
43
57
|
|
44
58
|
private
|
45
59
|
|
46
|
-
def credentials
|
60
|
+
def credentials(node)
|
47
61
|
Proc.new do |_url, username_from_url, _allowed_types| # rubocop:disable Style/Proc
|
48
62
|
git_user = cfg.has_key?('username') ? cfg.username : (username_from_url || 'git')
|
49
63
|
if cfg.has_key?('password')
|
50
64
|
log "Authenticating using username and password as '#{git_user}'", :debug
|
51
65
|
Rugged::Credentials::UserPassword.new(username: git_user, password: cfg.password)
|
52
|
-
elsif cfg.has_key?('
|
66
|
+
elsif cfg.has_key?('privatekey')
|
67
|
+
pubkey = cfg.has_key?('publickey') ? cfg.publickey : nil
|
53
68
|
log "Authenticating using ssh keys as '#{git_user}'", :debug
|
54
|
-
|
69
|
+
rugged_sshkey(git_user: git_user, privkey: cfg.privatekey, pubkey: pubkey)
|
70
|
+
elsif cfg.has_key?('remote_repo') && cfg.remote_repo.has_key?(node.group) && cfg.remote_repo[node.group].has_key?('privatekey')
|
71
|
+
pubkey = cfg.remote_repo[node.group].has_key?('publickey') ? cfg.remote_repo[node.group].publickey : nil
|
72
|
+
log "Authenticating using ssh keys as '#{git_user}' for '#{node.group}/#{node.name}'", :debug
|
73
|
+
rugged_sshkey(git_user: git_user, privkey: cfg.remote_repo[node.group].privatekey, pubkey: pubkey)
|
55
74
|
else
|
56
75
|
log "Authenticating using ssh agent as '#{git_user}'", :debug
|
57
76
|
Rugged::Credentials::SshKeyFromAgent.new(username: git_user)
|
@@ -59,11 +78,23 @@ class GithubRepo < Oxidized::Hook
|
|
59
78
|
end
|
60
79
|
end
|
61
80
|
|
81
|
+
def rugged_sshkey(args = {})
|
82
|
+
git_user = args[:git_user]
|
83
|
+
privkey = args[:privkey]
|
84
|
+
pubkey = args[:pubkey] || (privkey + '.pub')
|
85
|
+
Rugged::Credentials::SshKey.new(username: git_user,
|
86
|
+
publickey: File.expand_path(pubkey),
|
87
|
+
privatekey: File.expand_path(privkey),
|
88
|
+
passphrase: ENV.fetch("OXIDIZED_SSH_PASSPHRASE", nil))
|
89
|
+
end
|
90
|
+
|
62
91
|
def remote_repo(node)
|
63
92
|
if node.group.nil? || cfg.remote_repo.is_a?(String)
|
64
93
|
cfg.remote_repo
|
65
|
-
|
94
|
+
elsif cfg.remote_repo[node.group].is_a?(String)
|
66
95
|
cfg.remote_repo[node.group]
|
96
|
+
elsif cfg.remote_repo[node.group].url.is_a?(String)
|
97
|
+
cfg.remote_repo[node.group].url
|
67
98
|
end
|
68
99
|
end
|
69
100
|
end
|
@@ -14,11 +14,11 @@ class SlackDiff < Oxidized::Hook
|
|
14
14
|
return unless ctx.event.to_s == "post_store"
|
15
15
|
|
16
16
|
log "Connecting to slack"
|
17
|
-
Slack.configure do |config|
|
17
|
+
Slack::Web::Client.configure do |config|
|
18
18
|
config.token = cfg.token
|
19
19
|
config.proxy = cfg.proxy if cfg.has_key?('proxy')
|
20
20
|
end
|
21
|
-
client = Slack::Client.new
|
21
|
+
client = Slack::Web::Client.new
|
22
22
|
client.auth_test
|
23
23
|
log "Connected"
|
24
24
|
if cfg.has_key?("diff") ? cfg.diff : true
|
@@ -2,6 +2,44 @@ require 'xmpp4r'
|
|
2
2
|
require 'xmpp4r/muc/helper/simplemucclient'
|
3
3
|
|
4
4
|
class XMPPDiff < Oxidized::Hook
|
5
|
+
def connect
|
6
|
+
@client = Jabber::Client.new(Jabber::JID.new(cfg.jid))
|
7
|
+
|
8
|
+
log "Connecting to XMPP"
|
9
|
+
begin
|
10
|
+
Timeout.timeout(15) do
|
11
|
+
begin
|
12
|
+
@client.connect
|
13
|
+
rescue StandardError => e
|
14
|
+
log "Failed to connect to XMPP: #{e}"
|
15
|
+
end
|
16
|
+
sleep 1
|
17
|
+
|
18
|
+
log "Authenticating to XMPP"
|
19
|
+
@client.auth(cfg.password)
|
20
|
+
sleep 1
|
21
|
+
|
22
|
+
log "Connected to XMPP"
|
23
|
+
|
24
|
+
@muc = Jabber::MUC::SimpleMUCClient.new(@client)
|
25
|
+
@muc.join(cfg.channel + "/" + cfg.nick)
|
26
|
+
|
27
|
+
log "Joined #{cfg.channel}"
|
28
|
+
end
|
29
|
+
rescue Timeout::Error
|
30
|
+
log "timed out"
|
31
|
+
@client = nil
|
32
|
+
@muc = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
@client.on_exception do
|
36
|
+
log "XMPP connection aborted, reconnecting"
|
37
|
+
@client = nil
|
38
|
+
@muc = nil
|
39
|
+
connect
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
5
43
|
def validate_cfg!
|
6
44
|
raise KeyError, 'hook.jid is required' unless cfg.has_key?('jid')
|
7
45
|
raise KeyError, 'hook.password is required' unless cfg.has_key?('password')
|
@@ -21,35 +59,17 @@ class XMPPDiff < Oxidized::Hook
|
|
21
59
|
interesting = diff[:patch].lines.to_a[4..-1].any? do |line|
|
22
60
|
["+", "-"].include?(line[0]) && (not ["#", "!"].include?(line[1]))
|
23
61
|
end
|
24
|
-
interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '-' }
|
25
|
-
interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '+' }
|
26
62
|
|
27
63
|
if interesting
|
28
|
-
|
29
|
-
client = Jabber::Client.new(Jabber::JID.new(cfg.jid))
|
30
|
-
client.connect
|
31
|
-
sleep 1
|
32
|
-
client.auth(cfg.password)
|
33
|
-
sleep 1
|
34
|
-
|
35
|
-
log "Connected"
|
36
|
-
|
37
|
-
m = Jabber::MUC::SimpleMUCClient.new(client)
|
38
|
-
m.join(cfg.channel + "/" + cfg.nick)
|
39
|
-
|
40
|
-
log "Joined"
|
41
|
-
|
42
|
-
title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
|
43
|
-
log "Posting diff as snippet to #{cfg.channel}"
|
44
|
-
|
45
|
-
m.say(title + "\n\n" + diff[:patch].lines.to_a[4..-1].join)
|
46
|
-
|
47
|
-
sleep 1
|
48
|
-
|
49
|
-
client.close
|
64
|
+
connect if @muc.nil?
|
50
65
|
|
51
|
-
|
66
|
+
# Maybe connecting failed, so only proceed if we actually joined the MUC
|
67
|
+
unless @muc.nil?
|
68
|
+
title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
|
69
|
+
log "Posting diff as snippet to #{cfg.channel}"
|
52
70
|
|
71
|
+
@muc.say(title + "\n\n" + diff[:patch].lines.to_a[4..-1].join)
|
72
|
+
end
|
53
73
|
end
|
54
74
|
end
|
55
75
|
rescue Timeout::Error
|
data/lib/oxidized/hook.rb
CHANGED
@@ -55,12 +55,10 @@ module Oxidized
|
|
55
55
|
ctx.event = event
|
56
56
|
|
57
57
|
@registered_hooks[event].each do |r_hook|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
"(#{e.inspect}) for event #{event.inspect}"
|
63
|
-
end
|
58
|
+
r_hook.hook.run_hook ctx
|
59
|
+
rescue StandardError => e
|
60
|
+
Oxidized.logger.error "Hook #{r_hook.name} (#{r_hook.hook}) failed " \
|
61
|
+
"(#{e.inspect}) for event #{event.inspect}"
|
64
62
|
end
|
65
63
|
end
|
66
64
|
end
|
@@ -69,8 +67,6 @@ module Oxidized
|
|
69
67
|
class Hook
|
70
68
|
attr_reader :cfg
|
71
69
|
|
72
|
-
def initialize; end
|
73
|
-
|
74
70
|
def cfg=(cfg)
|
75
71
|
@cfg = cfg
|
76
72
|
validate_cfg! if respond_to? :validate_cfg!
|
data/lib/oxidized/input/exec.rb
CHANGED
@@ -6,8 +6,8 @@ module Oxidized
|
|
6
6
|
|
7
7
|
def connect(node)
|
8
8
|
@node = node
|
9
|
-
@node.model.cfg["exec"].each { |cb| instance_exec(&cb) }
|
10
9
|
@log = File.open(Oxidized::Config::Log + "/#{@node.ip}-exec", "w") if Oxidized.config.input.debug?
|
10
|
+
@node.model.cfg["exec"].each { |cb| instance_exec(&cb) }
|
11
11
|
end
|
12
12
|
|
13
13
|
def cmd(cmd_str)
|
data/lib/oxidized/input/input.rb
CHANGED
data/lib/oxidized/input/ssh.rb
CHANGED
@@ -122,34 +122,27 @@ module Oxidized
|
|
122
122
|
def make_ssh_opts
|
123
123
|
secure = Oxidized.config.input.ssh.secure?
|
124
124
|
ssh_opts = {
|
125
|
-
number_of_password_prompts:
|
126
|
-
keepalive:
|
127
|
-
verify_host_key:
|
128
|
-
|
129
|
-
|
130
|
-
|
125
|
+
number_of_password_prompts: 0,
|
126
|
+
keepalive: vars(:ssh_no_keepalive) ? false : true,
|
127
|
+
verify_host_key: secure ? :always : :never,
|
128
|
+
append_all_supported_algorithms: true,
|
129
|
+
password: @node.auth[:password],
|
130
|
+
timeout: Oxidized.config.timeout,
|
131
|
+
port: (vars(:ssh_port) || 22).to_i,
|
132
|
+
forward_agent: false
|
131
133
|
}
|
132
134
|
|
133
135
|
auth_methods = vars(:auth_methods) || %w[none publickey password]
|
134
136
|
ssh_opts[:auth_methods] = auth_methods
|
135
137
|
Oxidized.logger.debug "AUTH METHODS::#{auth_methods}"
|
136
138
|
|
137
|
-
|
138
|
-
proxy_command = "ssh "
|
139
|
-
proxy_command += "-o StrictHostKeyChecking=no " unless secure
|
140
|
-
if (proxy_port = vars(:ssh_proxy_port))
|
141
|
-
proxy_command += "-p #{proxy_port} "
|
142
|
-
end
|
143
|
-
proxy_command += "#{proxy_host} -W %h:%p"
|
144
|
-
proxy = Net::SSH::Proxy::Command.new(proxy_command)
|
145
|
-
ssh_opts[:proxy] = proxy
|
146
|
-
end
|
139
|
+
ssh_opts[:proxy] = make_ssh_proxy_command(vars(:ssh_proxy), vars(:ssh_proxy_port), secure) if vars(:ssh_proxy)
|
147
140
|
|
148
|
-
ssh_opts[:keys] = [vars(:ssh_keys)].flatten
|
149
|
-
ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/)
|
141
|
+
ssh_opts[:keys] = [vars(:ssh_keys)].flatten if vars(:ssh_keys)
|
142
|
+
ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex)
|
150
143
|
ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption)
|
151
|
-
ssh_opts[:host_key] = vars(:ssh_host_key).split(/,\s*/)
|
152
|
-
ssh_opts[:hmac] = vars(:ssh_hmac).split(/,\s*/)
|
144
|
+
ssh_opts[:host_key] = vars(:ssh_host_key).split(/,\s*/) if vars(:ssh_host_key)
|
145
|
+
ssh_opts[:hmac] = vars(:ssh_hmac).split(/,\s*/) if vars(:ssh_hmac)
|
153
146
|
|
154
147
|
if Oxidized.config.input.debug?
|
155
148
|
ssh_opts[:logger] = Oxidized.logger
|
@@ -158,5 +151,15 @@ module Oxidized
|
|
158
151
|
|
159
152
|
ssh_opts
|
160
153
|
end
|
154
|
+
|
155
|
+
def make_ssh_proxy_command(proxy_host, proxy_port, secure)
|
156
|
+
return nil unless !proxy_host.nil? && !proxy_host.empty?
|
157
|
+
|
158
|
+
proxy_command = "ssh "
|
159
|
+
proxy_command += "-o StrictHostKeyChecking=no " unless secure
|
160
|
+
proxy_command += "-p #{proxy_port} " if proxy_port
|
161
|
+
proxy_command += "#{proxy_host} -W [%h]:%p"
|
162
|
+
Net::SSH::Proxy::Command.new(proxy_command)
|
163
|
+
end
|
161
164
|
end
|
162
165
|
end
|
@@ -35,13 +35,15 @@ module Oxidized
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def cmd(cmd_str, expect = @node.prompt)
|
38
|
+
Oxidized.logger.debug "Telnet: #{cmd_str} @#{@node.name}"
|
38
39
|
return send(cmd_str + "\r\n") unless expect
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
@telnet.
|
41
|
+
# create a string to be passed to oxidized_expect and modified _there_
|
42
|
+
# default to a single space so it shouldn't be coerced to nil by any models.
|
43
|
+
out = String(' ')
|
44
|
+
@telnet.puts(cmd_str)
|
45
|
+
@telnet.oxidized_expect(timeout: @timeout, expect: expect, out: out)
|
46
|
+
out
|
45
47
|
end
|
46
48
|
|
47
49
|
def send(data)
|
@@ -69,46 +71,52 @@ module Oxidized
|
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
74
|
+
module Net
|
75
|
+
class Telnet
|
76
|
+
## how to do this, without redefining the whole damn thing
|
77
|
+
## FIXME: we also need output (not sure I'm going to support this)
|
78
|
+
attr_reader :output
|
79
|
+
|
80
|
+
def oxidized_expect(options) ## rubocop:disable Metrics/PerceivedComplexity
|
81
|
+
model = @options["Model"]
|
82
|
+
@log = @options["Log"]
|
83
|
+
|
84
|
+
expects = [options[:expect]].flatten
|
85
|
+
time_out = options[:timeout] || @options["Timeout"] || Oxidized.config.timeout?
|
86
|
+
|
87
|
+
Timeout.timeout(time_out) do
|
88
|
+
line = ""
|
89
|
+
rest = ""
|
90
|
+
buf = ""
|
91
|
+
loop do
|
92
|
+
c = @sock.readpartial(1024 * 1024)
|
93
|
+
@output = c
|
94
|
+
c = rest + c
|
95
|
+
|
96
|
+
if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) <
|
97
|
+
Integer(c.rindex(/#{IAC}#{SB}/no) || 0)
|
98
|
+
buf = preprocess(c[0...c.rindex(/#{IAC}#{SB}/no)])
|
99
|
+
rest = c[c.rindex(/#{IAC}#{SB}/no)..-1]
|
100
|
+
elsif (pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) ||
|
101
|
+
c.rindex(/\r\z/no))
|
102
|
+
buf = preprocess(c[0...pt])
|
103
|
+
rest = c[pt..-1]
|
104
|
+
else
|
105
|
+
buf = preprocess(c)
|
106
|
+
rest = ''
|
107
|
+
end
|
108
|
+
if Oxidized.config.input.debug?
|
109
|
+
@log.print buf
|
110
|
+
@log.flush
|
111
|
+
end
|
112
|
+
line += buf
|
113
|
+
line = model.expects line
|
114
|
+
# match is a regexp object. we need to return that for logins to work.
|
115
|
+
match = expects.find { |re| line.match re }
|
116
|
+
# stomp on the out string object if we have one. (thus we were called by cmd?)
|
117
|
+
options[:out]&.replace(line)
|
118
|
+
return match if match
|
107
119
|
end
|
108
|
-
line += buf
|
109
|
-
line = model.expects line
|
110
|
-
match = expects.find { |re| line.match re }
|
111
|
-
return match if match
|
112
120
|
end
|
113
121
|
end
|
114
122
|
end
|
data/lib/oxidized/job.rb
CHANGED
data/lib/oxidized/jobs.rb
CHANGED
@@ -4,13 +4,14 @@ module Oxidized
|
|
4
4
|
MAX_INTER_JOB_GAP = 300 # add job if more than X from last job started
|
5
5
|
attr_accessor :interval, :max, :want
|
6
6
|
|
7
|
-
def initialize(max, interval, nodes)
|
8
|
-
@max
|
7
|
+
def initialize(max, use_max_threads, interval, nodes)
|
8
|
+
@max = max
|
9
|
+
@use_max_threads = use_max_threads
|
9
10
|
# Set interval to 1 if interval is 0 (=disabled) so we don't break
|
10
11
|
# the 'ceil' function
|
11
|
-
@interval
|
12
|
-
@nodes
|
13
|
-
@last
|
12
|
+
@interval = interval.zero? ? 1 : interval
|
13
|
+
@nodes = nodes
|
14
|
+
@last = Time.now.utc
|
14
15
|
@durations = Array.new @nodes.size, AVERAGE_DURATION
|
15
16
|
duration AVERAGE_DURATION
|
16
17
|
super()
|
@@ -33,7 +34,11 @@ module Oxidized
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def new_count
|
36
|
-
@want =
|
37
|
+
@want = if @use_max_threads
|
38
|
+
@max
|
39
|
+
else
|
40
|
+
((@nodes.size * @duration) / @interval).ceil
|
41
|
+
end
|
37
42
|
@want = 1 if @want < 1
|
38
43
|
@want = @nodes.size if @want > @nodes.size
|
39
44
|
@want = @max if @want > @max
|
data/lib/oxidized/manager.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
class ACMEPACKET < Oxidized::Model
|
2
|
+
# Oracle ACME Packet 3k, 4k, 6k series
|
3
|
+
|
4
|
+
prompt /^\r*([\w.@()-\/]+[#>]\s?)$/
|
5
|
+
|
6
|
+
comment '! '
|
7
|
+
|
8
|
+
cmd :all do |cfg, cmdstring|
|
9
|
+
new_cfg = comment "COMMAND: #{cmdstring}\n"
|
10
|
+
new_cfg << cfg.cut_both
|
11
|
+
end
|
12
|
+
|
13
|
+
cmd 'show version' do |cfg|
|
14
|
+
comment cfg
|
15
|
+
end
|
16
|
+
|
17
|
+
cmd 'show running-config' do |cfg|
|
18
|
+
cfg
|
19
|
+
end
|
20
|
+
|
21
|
+
cfg :telnet do
|
22
|
+
password /^Password:/i
|
23
|
+
end
|
24
|
+
|
25
|
+
cfg :telnet, :ssh do
|
26
|
+
# preferred way to handle additional passwords
|
27
|
+
post_login do
|
28
|
+
if vars(:enable) == true
|
29
|
+
cmd "enable"
|
30
|
+
elsif vars(:enable)
|
31
|
+
cmd "enable", /^[pP]assword:/
|
32
|
+
cmd vars(:enable)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
pre_logout 'exit'
|
36
|
+
pre_logout 'exit'
|
37
|
+
end
|
38
|
+
end
|
@@ -15,9 +15,11 @@ class Adtran < Oxidized::Model
|
|
15
15
|
cmd 'show running-config'
|
16
16
|
|
17
17
|
cfg :ssh do
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
if vars :enable
|
19
|
+
post_login do
|
20
|
+
send "enable\n"
|
21
|
+
cmd vars(:enable)
|
22
|
+
end
|
21
23
|
end
|
22
24
|
post_login 'terminal length 0'
|
23
25
|
pre_logout 'exit'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Oxidized model for ADVA devices
|
2
|
+
#
|
3
|
+
# IMPORTANT: To get this working, cli-paging must be disabled
|
4
|
+
# for the user that is used to fetch the configuration.
|
5
|
+
|
6
|
+
class ADVA < Oxidized::Model
|
7
|
+
prompt /\w+\-+[#>]\s?$/
|
8
|
+
comment '# '
|
9
|
+
|
10
|
+
cmd :secret do |cfg|
|
11
|
+
cfg.gsub! /community "[^"]+"/, 'community "<hidden>"'
|
12
|
+
cfg
|
13
|
+
end
|
14
|
+
|
15
|
+
cmd :all do |cfg|
|
16
|
+
cfg.cut_both
|
17
|
+
end
|
18
|
+
|
19
|
+
cmd 'show running-config current' do |cfg|
|
20
|
+
cfg.each_line.reject { |line| line.match /^Preparing configuration file.*/ }.join
|
21
|
+
end
|
22
|
+
|
23
|
+
cmd 'show system' do |cfg|
|
24
|
+
cfg = cfg.each_line.reject { |line| line.match /(up time|local time)/i }.join
|
25
|
+
|
26
|
+
cfg = "COMMAND: show system\n\n" + cfg
|
27
|
+
cfg = comment cfg
|
28
|
+
"\n\n" + cfg
|
29
|
+
end
|
30
|
+
|
31
|
+
cmd 'network-element ne-1'
|
32
|
+
|
33
|
+
cmd 'show shelf-info' do |cfg|
|
34
|
+
cfg = "COMMAND: show shelf-info\n\n" + cfg
|
35
|
+
cfg = comment cfg
|
36
|
+
"\n\n" + cfg
|
37
|
+
end
|
38
|
+
|
39
|
+
post do
|
40
|
+
ports = []
|
41
|
+
ports_output = ''
|
42
|
+
|
43
|
+
cmd 'show ports' do |cfg|
|
44
|
+
cfg.each_line do |line|
|
45
|
+
port = line.match(/\|((access|network)[^\|]+)\|/)
|
46
|
+
ports << port if port
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
ports.each do |port|
|
51
|
+
port_command = 'show ' + port[2] + '-port ' + port[1]
|
52
|
+
|
53
|
+
ports_output << cmd(port_command) do |cfg|
|
54
|
+
cfg = "COMMAND: " + port_command + "\n\n" + cfg
|
55
|
+
cfg = comment cfg
|
56
|
+
"\n\n" + cfg
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
ports_output
|
61
|
+
end
|
62
|
+
|
63
|
+
cfg :ssh do
|
64
|
+
pre_logout 'logout'
|
65
|
+
end
|
66
|
+
end
|