oxidized 0.20.0 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +4 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- data/.github/no-response.yml +13 -0
- data/.github/workflows/publishdocker.yml +13 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +73 -0
- data/.rubocop_todo.yml +120 -0
- data/.travis.yml +6 -1
- data/CHANGELOG.md +693 -243
- data/Dockerfile +27 -19
- data/LICENSE +201 -0
- data/README.md +234 -913
- data/Rakefile +48 -7
- data/TODO.md +29 -23
- data/bin/console +1 -1
- data/bin/oxidized +6 -5
- data/docs/Configuration.md +313 -0
- data/docs/Creating-Models.md +140 -0
- data/docs/Hooks.md +274 -0
- data/docs/Model-Notes/AireOS.md +11 -0
- data/docs/Model-Notes/ArbOS.md +11 -0
- data/docs/Model-Notes/Comware.md +13 -0
- data/docs/Model-Notes/Cumulus.md +40 -0
- data/docs/Model-Notes/EOS.md +12 -0
- data/docs/Model-Notes/IOS.md +29 -0
- data/docs/Model-Notes/JunOS.md +33 -0
- data/docs/Model-Notes/LinuxGeneric.md +24 -0
- data/docs/Model-Notes/Netgear.md +87 -0
- data/docs/Model-Notes/Nokia.md +9 -0
- data/docs/Model-Notes/README.md +24 -0
- data/docs/Model-Notes/SmartAX-Huawei.md +35 -0
- data/docs/Model-Notes/VRP-Huawei.md +34 -0
- data/docs/Model-Notes/Viptela.md +12 -0
- data/docs/Model-Notes/XGS4600-Zyxel.md +36 -0
- data/docs/Outputs.md +190 -0
- data/docs/Ruby-API.md +199 -0
- data/docs/Sources.md +171 -0
- data/docs/Supported-OS-Types.md +227 -0
- data/docs/Troubleshooting.md +66 -0
- data/extra/nagios_check_failing_nodes.rb +9 -2
- data/extra/oxidized-report-git-commits +21 -40
- data/extra/oxidized-ubuntu.haproxy +45 -0
- data/extra/oxidized.logrotate +7 -0
- data/extra/oxidized.service +13 -0
- data/extra/rest_client.rb +7 -10
- data/extra/syslog.rb +47 -42
- data/lib/oxidized/cli.rb +41 -31
- data/lib/oxidized/config/vars.rb +9 -14
- data/lib/oxidized/config.rb +20 -13
- data/lib/oxidized/core.rb +8 -10
- data/lib/oxidized/hook/awssns.rb +6 -7
- data/lib/oxidized/hook/ciscosparkdiff.rb +43 -0
- data/lib/oxidized/hook/exec.rb +19 -24
- data/lib/oxidized/hook/githubrepo.rb +17 -17
- data/lib/oxidized/hook/noophook.rb +1 -1
- data/lib/oxidized/hook/slackdiff.rb +32 -19
- data/lib/oxidized/hook/xmppdiff.rb +59 -0
- data/lib/oxidized/hook.rb +63 -64
- data/lib/oxidized/input/cli.rb +22 -12
- data/lib/oxidized/input/exec.rb +28 -0
- data/lib/oxidized/input/ftp.rb +16 -15
- data/lib/oxidized/input/http.rb +72 -0
- data/lib/oxidized/input/input.rb +6 -6
- data/lib/oxidized/input/ssh.rb +64 -56
- data/lib/oxidized/input/telnet.rb +59 -102
- data/lib/oxidized/input/tftp.rb +9 -10
- data/lib/oxidized/jobs.rb +9 -10
- data/lib/oxidized/manager.rb +42 -44
- data/lib/oxidized/model/acos.rb +19 -20
- data/lib/oxidized/model/acsw.rb +62 -0
- data/lib/oxidized/model/adtran.rb +26 -0
- data/lib/oxidized/model/aen.rb +19 -0
- data/lib/oxidized/model/aireos.rb +9 -10
- data/lib/oxidized/model/airfiber.rb +22 -0
- data/lib/oxidized/model/alteonos.rb +58 -0
- data/lib/oxidized/model/alvarion.rb +0 -4
- data/lib/oxidized/model/aos.rb +11 -5
- data/lib/oxidized/model/aos7.rb +6 -7
- data/lib/oxidized/model/aosw.rb +30 -27
- data/lib/oxidized/model/apc_aos.rb +2 -5
- data/lib/oxidized/model/arbos.rb +26 -0
- data/lib/oxidized/model/aricentiss.rb +49 -0
- data/lib/oxidized/model/asa.rb +61 -22
- data/lib/oxidized/model/asyncos.rb +46 -0
- data/lib/oxidized/model/audiocodes.rb +28 -0
- data/lib/oxidized/model/audiocodesmp.rb +28 -0
- data/lib/oxidized/model/awplus.rb +84 -0
- data/lib/oxidized/model/axos.rb +16 -0
- data/lib/oxidized/model/boss.rb +77 -0
- data/lib/oxidized/model/br6910.rb +42 -45
- data/lib/oxidized/model/c4cmts.rb +6 -10
- data/lib/oxidized/model/cambium.rb +23 -0
- data/lib/oxidized/model/casa.rb +1 -1
- data/lib/oxidized/model/catos.rb +1 -3
- data/lib/oxidized/model/cisconga.rb +1 -3
- data/lib/oxidized/model/ciscosma.rb +42 -0
- data/lib/oxidized/model/ciscosmb.rb +30 -10
- data/lib/oxidized/model/ciscovpn3k.rb +11 -0
- data/lib/oxidized/model/cnos.rb +33 -0
- data/lib/oxidized/model/comnetms.rb +43 -0
- data/lib/oxidized/model/comtrol.rb +41 -0
- data/lib/oxidized/model/comware.rb +28 -16
- data/lib/oxidized/model/coriant8600.rb +3 -5
- data/lib/oxidized/model/coriantgroove.rb +26 -0
- data/lib/oxidized/model/corianttmos.rb +1 -3
- data/lib/oxidized/model/cumulus.rb +60 -49
- data/lib/oxidized/model/datacom.rb +1 -4
- data/lib/oxidized/model/dcnos.rb +46 -0
- data/lib/oxidized/model/dellx.rb +76 -0
- data/lib/oxidized/model/dlink.rb +5 -4
- data/lib/oxidized/model/dnos.rb +11 -5
- data/lib/oxidized/model/eciapollo.rb +34 -0
- data/lib/oxidized/model/edgecos.rb +49 -0
- data/lib/oxidized/model/edgeos.rb +12 -5
- data/lib/oxidized/model/edgeswitch.rb +2 -4
- data/lib/oxidized/model/enterasys.rb +28 -0
- data/lib/oxidized/model/eos.rb +8 -8
- data/lib/oxidized/model/fabricos.rb +4 -6
- data/lib/oxidized/model/fastiron.rb +66 -0
- data/lib/oxidized/model/fiberdriver.rb +2 -2
- data/lib/oxidized/model/firebrick.rb +31 -0
- data/lib/oxidized/model/firelinuxos.rb +41 -0
- data/lib/oxidized/model/firewareos.rb +3 -6
- data/lib/oxidized/model/fortios.rb +31 -19
- data/lib/oxidized/model/ftos.rb +8 -5
- data/lib/oxidized/model/fujitsupy.rb +5 -7
- data/lib/oxidized/model/gaiaos.rb +7 -11
- data/lib/oxidized/model/gcombnps.rb +84 -0
- data/lib/oxidized/model/grandstream.rb +9 -0
- data/lib/oxidized/model/hatteras.rb +9 -6
- data/lib/oxidized/model/hirschmann.rb +39 -0
- data/lib/oxidized/model/hpebladesystem.rb +20 -18
- data/lib/oxidized/model/hpemsa.rb +10 -0
- data/lib/oxidized/model/hpmsm.rb +84 -0
- data/lib/oxidized/model/ibos.rb +55 -0
- data/lib/oxidized/model/icotera.rb +27 -0
- data/lib/oxidized/model/ios.rb +63 -70
- data/lib/oxidized/model/iosxe.rb +5 -0
- data/lib/oxidized/model/iosxr.rb +2 -3
- data/lib/oxidized/model/ipos.rb +10 -6
- data/lib/oxidized/model/ironware.rb +20 -19
- data/lib/oxidized/model/isam.rb +5 -6
- data/lib/oxidized/model/junos.rb +9 -11
- data/lib/oxidized/model/linuxgeneric.rb +74 -0
- data/lib/oxidized/model/masteros.rb +3 -6
- data/lib/oxidized/model/mlnxos.rb +9 -10
- data/lib/oxidized/model/model.rb +72 -46
- data/lib/oxidized/model/mtrlrfs.rb +1 -4
- data/lib/oxidized/model/ndms.rb +23 -0
- data/lib/oxidized/model/netgear.rb +35 -15
- data/lib/oxidized/model/netonix.rb +2 -2
- data/lib/oxidized/model/netscaler.rb +6 -3
- data/lib/oxidized/model/nos.rb +5 -7
- data/lib/oxidized/model/nsxconfig.rb +22 -0
- data/lib/oxidized/model/nsxfirewall.rb +22 -0
- data/lib/oxidized/model/nxos.rb +13 -3
- data/lib/oxidized/model/oneos.rb +15 -9
- data/lib/oxidized/model/openbsd.rb +63 -0
- data/lib/oxidized/model/opengear.rb +3 -5
- data/lib/oxidized/model/openwrt.rb +78 -0
- data/lib/oxidized/model/opnsense.rb +19 -0
- data/lib/oxidized/model/os10.rb +46 -0
- data/lib/oxidized/model/outputs.rb +5 -7
- data/lib/oxidized/model/panos.rb +11 -12
- data/lib/oxidized/model/pfsense.rb +11 -6
- data/lib/oxidized/model/planet.rb +14 -17
- data/lib/oxidized/model/powerconnect.rb +24 -19
- data/lib/oxidized/model/procurve.rb +43 -11
- data/lib/oxidized/model/purityos.rb +12 -0
- data/lib/oxidized/model/qtech.rb +41 -0
- data/lib/oxidized/model/quantaos.rb +4 -6
- data/lib/oxidized/model/raisecom.rb +19 -0
- data/lib/oxidized/model/routeros.rb +26 -8
- data/lib/oxidized/model/saos.rb +1 -2
- data/lib/oxidized/model/screenos.rb +8 -11
- data/lib/oxidized/model/sgos.rb +45 -0
- data/lib/oxidized/model/siklu.rb +1 -3
- data/lib/oxidized/model/slxos.rb +59 -0
- data/lib/oxidized/model/smartax.rb +25 -0
- data/lib/oxidized/model/sonicos.rb +51 -0
- data/lib/oxidized/model/speedtouch.rb +34 -0
- data/lib/oxidized/model/sros.rb +96 -0
- data/lib/oxidized/model/stoneos.rb +32 -0
- data/lib/oxidized/model/supermicro.rb +6 -41
- data/lib/oxidized/model/tdre.rb +30 -0
- data/lib/oxidized/model/telco.rb +24 -0
- data/lib/oxidized/model/timos.rb +6 -114
- data/lib/oxidized/model/tmos.rb +6 -3
- data/lib/oxidized/model/tplink.rb +11 -11
- data/lib/oxidized/model/trango.rb +21 -42
- data/lib/oxidized/model/ucs.rb +30 -0
- data/lib/oxidized/model/viptela.rb +29 -0
- data/lib/oxidized/model/voltaire.rb +9 -12
- data/lib/oxidized/model/voss.rb +17 -6
- data/lib/oxidized/model/vrp.rb +11 -6
- data/lib/oxidized/model/vyatta.rb +8 -6
- data/lib/oxidized/model/weos.rb +20 -0
- data/lib/oxidized/model/xos.rb +20 -8
- 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/model/zynosgs.rb +38 -0
- data/lib/oxidized/node/stats.rb +33 -8
- data/lib/oxidized/node.rb +86 -95
- data/lib/oxidized/nodes.rb +48 -44
- data/lib/oxidized/output/file.rb +32 -37
- data/lib/oxidized/output/git.rb +138 -153
- data/lib/oxidized/output/gitcrypt.rb +228 -242
- data/lib/oxidized/output/http.rb +35 -34
- data/lib/oxidized/output/output.rb +2 -3
- data/lib/oxidized/source/csv.rb +50 -44
- data/lib/oxidized/source/http.rb +58 -58
- data/lib/oxidized/source/source.rb +9 -10
- data/lib/oxidized/source/sql.rb +47 -45
- data/lib/oxidized/string.rb +18 -14
- data/lib/oxidized/version.rb +17 -1
- data/lib/oxidized/worker.rb +72 -33
- data/oxidized.gemspec +20 -19
- metadata +180 -36
- data/.ruby-version +0 -1
- data/Gemfile.lock +0 -44
data/lib/oxidized/node.rb
CHANGED
@@ -6,26 +6,28 @@ module Oxidized
|
|
6
6
|
class ModelNotFound < OxidizedError; end
|
7
7
|
class Node
|
8
8
|
attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :vars, :last, :repo
|
9
|
-
attr_accessor :running, :user, :msg, :from, :stats, :retry
|
10
|
-
alias
|
11
|
-
|
9
|
+
attr_accessor :running, :user, :email, :msg, :from, :stats, :retry
|
10
|
+
alias running? running
|
11
|
+
|
12
|
+
def initialize(opt)
|
12
13
|
Oxidized.logger.debug 'resolving DNS for %s...' % opt[:name]
|
13
14
|
# remove the prefix if an IP Address is provided with one as IPAddr converts it to a network address.
|
14
|
-
ip_addr,
|
15
|
+
ip_addr, = opt[:ip].to_s.split("/")
|
15
16
|
Oxidized.logger.debug 'IPADDR %s' % ip_addr.to_s
|
16
|
-
@name
|
17
|
-
@ip
|
18
|
-
@ip
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
27
|
-
@
|
28
|
-
@
|
17
|
+
@name = opt[:name]
|
18
|
+
@ip = IPAddr.new(ip_addr).to_s rescue nil
|
19
|
+
@ip ||= Resolv.new.getaddress(@name) if Oxidized.config.resolve_dns?
|
20
|
+
@ip ||= @name
|
21
|
+
@group = opt[:group]
|
22
|
+
@model = resolve_model opt
|
23
|
+
@input = resolve_input opt
|
24
|
+
@output = resolve_output opt
|
25
|
+
@auth = resolve_auth opt
|
26
|
+
@prompt = resolve_prompt opt
|
27
|
+
@vars = opt[:vars]
|
28
|
+
@stats = Stats.new
|
29
|
+
@retry = 0
|
30
|
+
@repo = resolve_repo opt
|
29
31
|
|
30
32
|
# model instance needs to access node instance
|
31
33
|
@model.node = self
|
@@ -36,9 +38,10 @@ module Oxidized
|
|
36
38
|
@input.each do |input|
|
37
39
|
# don't try input if model is missing config block, we may need strong config to class_name map
|
38
40
|
cfg_name = input.to_s.split('::').last.downcase
|
39
|
-
next unless @model.cfg[cfg_name]
|
41
|
+
next unless @model.cfg[cfg_name] && (not @model.cfg[cfg_name].empty?)
|
42
|
+
|
40
43
|
@model.input = input = input.new
|
41
|
-
if config=run_input(input)
|
44
|
+
if (config = run_input(input))
|
42
45
|
Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} ran for #{name} successfully"
|
43
46
|
status = :success
|
44
47
|
break
|
@@ -51,62 +54,66 @@ module Oxidized
|
|
51
54
|
[status, config]
|
52
55
|
end
|
53
56
|
|
54
|
-
def run_input
|
57
|
+
def run_input(input)
|
55
58
|
rescue_fail = {}
|
56
59
|
[input.class::RescueFail, input.class.superclass::RescueFail].each do |hash|
|
57
|
-
hash.each do |level,errors|
|
60
|
+
hash.each do |level, errors|
|
58
61
|
errors.each do |err|
|
59
62
|
rescue_fail[err] = level
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
63
66
|
begin
|
64
|
-
input.connect(self)
|
67
|
+
input.connect(self) && input.get
|
65
68
|
rescue *rescue_fail.keys => err
|
66
|
-
resc
|
67
|
-
|
68
|
-
resc = err.class.ancestors.find{|e|rescue_fail.
|
69
|
+
resc = ''
|
70
|
+
unless (level = rescue_fail[err.class])
|
71
|
+
resc = err.class.ancestors.find { |e| rescue_fail.has_key?(e) }
|
69
72
|
level = rescue_fail[resc]
|
70
73
|
resc = " (rescued #{resc})"
|
71
74
|
end
|
72
|
-
Oxidized.logger.send(level, '%s raised %s%s with msg "%s"' % [
|
73
|
-
|
74
|
-
rescue => err
|
75
|
-
|
76
|
-
|
75
|
+
Oxidized.logger.send(level, '%s raised %s%s with msg "%s"' % [ip, err.class, resc, err.message])
|
76
|
+
false
|
77
|
+
rescue StandardError => err
|
78
|
+
crashdir = Oxidized.config.crash.directory
|
79
|
+
crashfile = Oxidized.config.crash.hostnames? ? name : ip.to_s
|
80
|
+
FileUtils.mkdir_p(crashdir) unless File.directory?(crashdir)
|
81
|
+
|
82
|
+
File.open File.join(crashdir, crashfile), 'w' do |fh|
|
77
83
|
fh.puts Time.now.utc
|
78
84
|
fh.puts err.message + ' [' + err.class.to_s + ']'
|
79
85
|
fh.puts '-' * 50
|
80
86
|
fh.puts err.backtrace
|
81
87
|
end
|
82
|
-
Oxidized.logger.error '%s raised %s with msg "%s", %s saved' % [
|
83
|
-
|
88
|
+
Oxidized.logger.error '%s raised %s with msg "%s", %s saved' % [ip, err.class, err.message, crashfile]
|
89
|
+
false
|
84
90
|
end
|
85
91
|
end
|
86
92
|
|
87
93
|
def serialize
|
88
94
|
h = {
|
89
|
-
:
|
90
|
-
:
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
94
|
-
:
|
95
|
-
:
|
95
|
+
name: @name,
|
96
|
+
full_name: @name,
|
97
|
+
ip: @ip,
|
98
|
+
group: @group,
|
99
|
+
model: @model.class.to_s,
|
100
|
+
last: nil,
|
101
|
+
vars: @vars,
|
102
|
+
mtime: @stats.mtime
|
96
103
|
}
|
97
104
|
h[:full_name] = [@group, @name].join('/') if @group
|
98
105
|
if @last
|
99
106
|
h[:last] = {
|
100
|
-
:
|
101
|
-
:
|
102
|
-
:
|
103
|
-
:
|
107
|
+
start: @last.start,
|
108
|
+
end: @last.end,
|
109
|
+
status: @last.status,
|
110
|
+
time: @last.time
|
104
111
|
}
|
105
112
|
end
|
106
113
|
h
|
107
114
|
end
|
108
115
|
|
109
|
-
def last=
|
116
|
+
def last=(job)
|
110
117
|
if job
|
111
118
|
ostruct = OpenStruct.new
|
112
119
|
ostruct.start = job.start
|
@@ -120,95 +127,81 @@ module Oxidized
|
|
120
127
|
end
|
121
128
|
|
122
129
|
def reset
|
123
|
-
@user = @msg = @from = nil
|
130
|
+
@user = @email = @msg = @from = nil
|
124
131
|
@retry = 0
|
125
132
|
end
|
126
133
|
|
134
|
+
def modified
|
135
|
+
@stats.update_mtime
|
136
|
+
end
|
137
|
+
|
127
138
|
private
|
128
139
|
|
129
|
-
def resolve_prompt
|
140
|
+
def resolve_prompt(opt)
|
130
141
|
opt[:prompt] || @model.prompt || Oxidized.config.prompt
|
131
142
|
end
|
132
143
|
|
133
|
-
def resolve_auth
|
144
|
+
def resolve_auth(opt)
|
134
145
|
# Resolve configured username/password
|
135
146
|
{
|
136
|
-
username:
|
137
|
-
password:
|
147
|
+
username: resolve_key(:username, opt),
|
148
|
+
password: resolve_key(:password, opt)
|
138
149
|
}
|
139
150
|
end
|
140
151
|
|
141
|
-
def resolve_input
|
152
|
+
def resolve_input(opt)
|
142
153
|
inputs = resolve_key :input, opt, Oxidized.config.input.default
|
143
154
|
inputs.split(/\s*,\s*/).map do |input|
|
144
|
-
|
145
|
-
Oxidized.mgr.add_input input or raise MethodNotFound, "#{input} not found for node #{ip}"
|
146
|
-
end
|
155
|
+
Oxidized.mgr.add_input(input) || raise(MethodNotFound, "#{input} not found for node #{ip}") unless Oxidized.mgr.input[input]
|
147
156
|
Oxidized.mgr.input[input]
|
148
157
|
end
|
149
158
|
end
|
150
159
|
|
151
|
-
def resolve_output
|
160
|
+
def resolve_output(opt)
|
152
161
|
output = resolve_key :output, opt, Oxidized.config.output.default
|
153
|
-
|
154
|
-
Oxidized.mgr.add_output output or raise MethodNotFound, "#{output} not found for node #{ip}"
|
155
|
-
end
|
162
|
+
Oxidized.mgr.add_output(output) || raise(MethodNotFound, "#{output} not found for node #{ip}") unless Oxidized.mgr.output[output]
|
156
163
|
Oxidized.mgr.output[output]
|
157
164
|
end
|
158
165
|
|
159
|
-
def resolve_model
|
166
|
+
def resolve_model(opt)
|
160
167
|
model = resolve_key :model, opt
|
161
|
-
|
168
|
+
unless Oxidized.mgr.model[model]
|
162
169
|
Oxidized.logger.debug "lib/oxidized/node.rb: Loading model #{model.inspect}"
|
163
|
-
Oxidized.mgr.add_model
|
170
|
+
Oxidized.mgr.add_model(model) || raise(ModelNotFound, "#{model} not found for node #{ip}")
|
164
171
|
end
|
165
172
|
Oxidized.mgr.model[model].new
|
166
173
|
end
|
167
174
|
|
168
|
-
def resolve_repo
|
169
|
-
|
170
|
-
|
175
|
+
def resolve_repo(opt)
|
176
|
+
type = git_type opt
|
177
|
+
return nil unless type
|
171
178
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
File.join(File.dirname(remote_repo), @group + '.git')
|
177
|
-
end
|
178
|
-
else
|
179
|
-
remote_repo[@group]
|
180
|
-
end
|
181
|
-
elsif is_gitcrypt? opt
|
182
|
-
remote_repo = Oxidized.config.output.gitcrypt.repo
|
183
|
-
|
184
|
-
if remote_repo.is_a?(::String)
|
185
|
-
if Oxidized.config.output.gitcrypt.single_repo? || @group.nil?
|
186
|
-
remote_repo
|
187
|
-
else
|
188
|
-
File.join(File.dirname(remote_repo), @group + '.git')
|
189
|
-
end
|
179
|
+
remote_repo = Oxidized.config.output.send(type).repo
|
180
|
+
if remote_repo.is_a?(::String)
|
181
|
+
if Oxidized.config.output.send(type).single_repo? || @group.nil?
|
182
|
+
remote_repo
|
190
183
|
else
|
191
|
-
remote_repo
|
184
|
+
File.join(File.dirname(remote_repo), @group + '.git')
|
192
185
|
end
|
193
186
|
else
|
194
|
-
|
187
|
+
remote_repo[@group]
|
195
188
|
end
|
196
189
|
end
|
197
190
|
|
198
|
-
def resolve_key
|
191
|
+
def resolve_key(key, opt, global = nil)
|
199
192
|
# resolve key, first get global, then get group then get node config
|
200
193
|
key_sym = key.to_sym
|
201
194
|
key_str = key.to_s
|
202
195
|
value = global
|
203
196
|
Oxidized.logger.debug "node.rb: resolving node key '#{key}', with passed global value of '#{value}' and node value '#{opt[key_sym]}'"
|
204
197
|
|
205
|
-
#global
|
206
|
-
if not value
|
198
|
+
# global
|
199
|
+
if (not value) && Oxidized.config.has_key?(key_str)
|
207
200
|
value = Oxidized.config[key_str]
|
208
201
|
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from global"
|
209
202
|
end
|
210
203
|
|
211
|
-
#group
|
204
|
+
# group
|
212
205
|
if Oxidized.config.groups.has_key?(@group)
|
213
206
|
if Oxidized.config.groups[@group].has_key?(key_str)
|
214
207
|
value = Oxidized.config.groups[@group][key_str]
|
@@ -216,7 +209,7 @@ module Oxidized
|
|
216
209
|
end
|
217
210
|
end
|
218
211
|
|
219
|
-
#model
|
212
|
+
# model
|
220
213
|
if Oxidized.config.models.has_key?(@model.class.name.to_s.downcase)
|
221
214
|
if Oxidized.config.models[@model.class.name.to_s.downcase].has_key?(key_str)
|
222
215
|
value = Oxidized.config.models[@model.class.name.to_s.downcase][key_str]
|
@@ -224,19 +217,17 @@ module Oxidized
|
|
224
217
|
end
|
225
218
|
end
|
226
219
|
|
227
|
-
#node
|
220
|
+
# node
|
228
221
|
value = opt[key_sym] || value
|
229
222
|
Oxidized.logger.debug "node.rb: returning node key '#{key}' with value '#{value}'"
|
230
223
|
value
|
231
224
|
end
|
232
225
|
|
233
|
-
def
|
234
|
-
|
235
|
-
|
226
|
+
def git_type(opt)
|
227
|
+
type = opt[:output] || Oxidized.config.output.default
|
228
|
+
return nil unless type[0..2] == "git"
|
236
229
|
|
237
|
-
|
238
|
-
(opt[:output] || Oxidized.config.output.default) == 'gitcrypt'
|
230
|
+
type
|
239
231
|
end
|
240
|
-
|
241
232
|
end
|
242
233
|
end
|
data/lib/oxidized/nodes.rb
CHANGED
@@ -5,79 +5,82 @@ module Oxidized
|
|
5
5
|
class Oxidized::NodeNotFound < OxidizedError; end
|
6
6
|
class Nodes < Array
|
7
7
|
attr_accessor :source, :jobs
|
8
|
-
alias
|
9
|
-
def load
|
8
|
+
alias put unshift
|
9
|
+
def load(node_want = nil)
|
10
10
|
with_lock do
|
11
11
|
new = []
|
12
12
|
@source = Oxidized.config.source.default
|
13
|
-
Oxidized.mgr.add_source @source
|
13
|
+
Oxidized.mgr.add_source(@source) || raise(MethodNotFound, "cannot load node source '#{@source}', not found")
|
14
14
|
Oxidized.logger.info "lib/oxidized/nodes.rb: Loading nodes"
|
15
|
-
Oxidized.mgr.source[@source].new.load
|
15
|
+
nodes = Oxidized.mgr.source[@source].new.load node_want
|
16
|
+
nodes.each do |node|
|
16
17
|
# we want to load specific node(s), not all of them
|
17
18
|
next unless node_want? node_want, node
|
19
|
+
|
18
20
|
begin
|
19
|
-
|
20
|
-
new.push
|
21
|
+
node_obj = Node.new node
|
22
|
+
new.push node_obj
|
21
23
|
rescue ModelNotFound => err
|
22
24
|
Oxidized.logger.error "node %s raised %s with message '%s'" % [node, err.class, err.message]
|
23
25
|
rescue Resolv::ResolvError => err
|
24
26
|
Oxidized.logger.error "node %s is not resolvable, raised %s with message '%s'" % [node, err.class, err.message]
|
25
27
|
end
|
26
28
|
end
|
27
|
-
size
|
29
|
+
size.zero? ? replace(new) : update_nodes(new)
|
28
30
|
Oxidized.logger.info "lib/oxidized/nodes.rb: Loaded #{size} nodes"
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
def node_want?
|
34
|
+
def node_want?(node_want, node)
|
33
35
|
return true unless node_want
|
36
|
+
|
34
37
|
node_want_ip = (IPAddr.new(node_want) rescue false)
|
35
38
|
name_is_ip = (IPAddr.new(node[:name]) rescue false)
|
36
|
-
if name_is_ip
|
39
|
+
if name_is_ip && (node_want_ip == node[:name])
|
37
40
|
true
|
38
|
-
elsif node[:ip]
|
41
|
+
elsif node[:ip] && (node_want_ip == node[:ip])
|
39
42
|
true
|
40
43
|
elsif node_want.match node[:name]
|
41
44
|
true unless name_is_ip
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
|
-
|
46
48
|
def list
|
47
49
|
with_lock do
|
48
50
|
map { |e| e.serialize }
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
|
-
def show
|
54
|
+
def show(node)
|
53
55
|
with_lock do
|
54
56
|
i = find_node_index node
|
55
57
|
self[i].serialize
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
def fetch
|
61
|
+
def fetch(node_name, group)
|
60
62
|
yield_node_output(node_name) do |node, output|
|
61
63
|
output.fetch node, group
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
65
67
|
# @param node [String] name of the node moved into the head of array
|
66
|
-
def next
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
68
|
+
def next(node, opt = {})
|
69
|
+
return unless waiting.find_node_index(node)
|
70
|
+
|
71
|
+
with_lock do
|
72
|
+
n = del node
|
73
|
+
n.user = opt['user']
|
74
|
+
n.email = opt['email']
|
75
|
+
n.msg = opt['msg']
|
76
|
+
n.from = opt['from']
|
77
|
+
# set last job to nil so that the node is picked for immediate update
|
78
|
+
n.last = nil
|
79
|
+
put n
|
80
|
+
jobs.want += 1 if Oxidized.config.next_adds_job?
|
78
81
|
end
|
79
82
|
end
|
80
|
-
alias
|
83
|
+
alias top next
|
81
84
|
|
82
85
|
# @return [String] node from the head of the array
|
83
86
|
def get
|
@@ -88,23 +91,23 @@ module Oxidized
|
|
88
91
|
|
89
92
|
# @param node node whose index number in Nodes to find
|
90
93
|
# @return [Fixnum] index number of node in Nodes
|
91
|
-
def find_node_index
|
92
|
-
find_index
|
94
|
+
def find_node_index(node)
|
95
|
+
find_index(node) || raise(Oxidized::NodeNotFound, "unable to find '#{node}'")
|
93
96
|
end
|
94
97
|
|
95
|
-
def version
|
98
|
+
def version(node_name, group)
|
96
99
|
yield_node_output(node_name) do |node, output|
|
97
100
|
output.version node, group
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
101
|
-
def get_version
|
104
|
+
def get_version(node_name, group, oid)
|
102
105
|
yield_node_output(node_name) do |node, output|
|
103
106
|
output.get_version node, group, oid
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
107
|
-
def get_diff
|
110
|
+
def get_diff(node_name, group, oid1, oid2)
|
108
111
|
yield_node_output(node_name) do |node, output|
|
109
112
|
output.get_diff node, group, oid1, oid2
|
110
113
|
end
|
@@ -112,39 +115,39 @@ module Oxidized
|
|
112
115
|
|
113
116
|
private
|
114
117
|
|
115
|
-
def initialize
|
118
|
+
def initialize(opts = {})
|
116
119
|
super()
|
117
120
|
node = opts.delete :node
|
118
|
-
@mutex= Mutex.new
|
119
|
-
if nodes = opts.delete(:nodes)
|
121
|
+
@mutex = Mutex.new # we compete for the nodes with webapi thread
|
122
|
+
if (nodes = opts.delete(:nodes))
|
120
123
|
replace nodes
|
121
124
|
else
|
122
125
|
load node
|
123
126
|
end
|
124
127
|
end
|
125
128
|
|
126
|
-
def with_lock
|
129
|
+
def with_lock(&block)
|
127
130
|
@mutex.synchronize(&block)
|
128
131
|
end
|
129
132
|
|
130
|
-
def find_index
|
131
|
-
index { |e| e.name
|
133
|
+
def find_index(node)
|
134
|
+
index { |e| [e.name, e.ip].include? node }
|
132
135
|
end
|
133
136
|
|
134
137
|
# @param node node which is removed from nodes list
|
135
138
|
# @return [Node] deleted node
|
136
|
-
def del
|
139
|
+
def del(node)
|
137
140
|
delete_at find_node_index(node)
|
138
141
|
end
|
139
142
|
|
140
143
|
# @return [Nodes] list of nodes running now
|
141
144
|
def running
|
142
|
-
Nodes.new :
|
145
|
+
Nodes.new nodes: select { |node| node.running? }
|
143
146
|
end
|
144
147
|
|
145
148
|
# @return [Nodes] list of nodes waiting (not running)
|
146
149
|
def waiting
|
147
|
-
Nodes.new :
|
150
|
+
Nodes.new nodes: select { |node| not node.running? }
|
148
151
|
end
|
149
152
|
|
150
153
|
# walks list of new nodes, if old node contains same name, adds last and
|
@@ -152,16 +155,16 @@ module Oxidized
|
|
152
155
|
#
|
153
156
|
# @todo can we trust name to be unique identifier, what about when groups are used?
|
154
157
|
# @param [Array] nodes Array of nodes used to replace+update old
|
155
|
-
def update_nodes
|
156
|
-
old =
|
158
|
+
def update_nodes(nodes)
|
159
|
+
old = dup
|
157
160
|
replace(nodes)
|
158
161
|
each do |node|
|
159
162
|
begin
|
160
|
-
if i = old.find_node_index(node.name)
|
163
|
+
if (i = old.find_node_index(node.name))
|
161
164
|
node.stats = old[i].stats
|
162
165
|
node.last = old[i].last
|
163
166
|
end
|
164
|
-
rescue
|
167
|
+
rescue Oxidized::NodeNotFound
|
165
168
|
end
|
166
169
|
end
|
167
170
|
sort_by! { |x| x.last.nil? ? Time.new(0) : x.last.end }
|
@@ -172,6 +175,7 @@ module Oxidized
|
|
172
175
|
node = find { |n| n.name == node_name }
|
173
176
|
output = node.output.new
|
174
177
|
raise Oxidized::NotSupported unless output.respond_to? :fetch
|
178
|
+
|
175
179
|
yield node, output
|
176
180
|
end
|
177
181
|
end
|
data/lib/oxidized/output/file.rb
CHANGED
@@ -1,59 +1,54 @@
|
|
1
1
|
module Oxidized
|
2
|
-
class OxidizedFile < Output
|
3
|
-
|
2
|
+
class OxidizedFile < Output
|
3
|
+
require 'fileutils'
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :commitref
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def initialize
|
8
|
+
@cfg = Oxidized.config.output.file
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup
|
12
|
+
return unless @cfg.empty?
|
10
13
|
|
11
|
-
def setup
|
12
|
-
if @cfg.empty?
|
13
14
|
Oxidized.asetus.user.output.file.directory = File.join(Config::Root, 'configs')
|
14
15
|
Oxidized.asetus.save :user
|
15
16
|
raise NoConfig, 'no output file config, edit ~/.config/oxidized/config'
|
16
17
|
end
|
17
|
-
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def store(node, outputs, opt = {})
|
20
|
+
file = File.expand_path @cfg.directory
|
21
|
+
file = File.join File.dirname(file), opt[:group] if opt[:group]
|
22
|
+
FileUtils.mkdir_p file
|
23
|
+
file = File.join file, node
|
24
|
+
File.open(file, 'w') { |fh| fh.write outputs.to_cfg }
|
25
|
+
@commitref = file
|
23
26
|
end
|
24
|
-
FileUtils.mkdir_p file
|
25
|
-
file = File.join file, node
|
26
|
-
open(file, 'w') { |fh| fh.write outputs.to_cfg }
|
27
|
-
@commitref = file
|
28
|
-
end
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
def fetch(node, group)
|
29
|
+
cfg_dir = File.expand_path @cfg.directory
|
30
|
+
node_name = node.name
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
if File.exists? File.join(cfg_dir, node_name) # node configuration file is stored on base directory
|
32
|
+
if group # group is explicitly defined by user
|
33
|
+
cfg_dir = File.join File.dirname(cfg_dir), group
|
34
|
+
File.read File.join(cfg_dir, node_name)
|
35
|
+
elsif File.exist? File.join(cfg_dir, node_name) # node configuration file is stored on base directory
|
39
36
|
File.read File.join(cfg_dir, node_name)
|
40
37
|
else
|
41
38
|
path = Dir.glob(File.join(File.dirname(cfg_dir), '**', node_name)).first # fetch node in all groups
|
42
39
|
File.read path
|
43
40
|
end
|
41
|
+
rescue Errno::ENOENT
|
42
|
+
nil
|
44
43
|
end
|
45
|
-
rescue Errno::ENOENT
|
46
|
-
return nil
|
47
|
-
end
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
def version(_node, _group)
|
46
|
+
# not supported
|
47
|
+
[]
|
48
|
+
end
|
53
49
|
|
54
|
-
|
55
|
-
|
50
|
+
def get_version(_node, _group, _oid)
|
51
|
+
'not supported'
|
52
|
+
end
|
56
53
|
end
|
57
|
-
|
58
|
-
end
|
59
54
|
end
|