oxidized 0.24.0 → 0.25.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.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +4 -0
  3. data/.rubocop.yml +3 -0
  4. data/CHANGELOG.md +26 -2
  5. data/Dockerfile +8 -32
  6. data/README.md +17 -5
  7. data/bin/oxidized +1 -1
  8. data/docs/Configuration.md +41 -3
  9. data/docs/Hooks.md +26 -0
  10. data/docs/Model-Notes/AireOS.md +1 -2
  11. data/docs/Model-Notes/ArbOS.md +1 -2
  12. data/docs/Model-Notes/Comware.md +1 -2
  13. data/docs/Model-Notes/EOS.md +1 -2
  14. data/docs/Model-Notes/JunOS.md +1 -2
  15. data/docs/Model-Notes/Netgear.md +5 -6
  16. data/docs/Model-Notes/Nokia.md +9 -0
  17. data/docs/Model-Notes/README.md +3 -2
  18. data/docs/Model-Notes/VRP-Huawei.md +1 -2
  19. data/docs/Model-Notes/Viptela.md +12 -0
  20. data/docs/Model-Notes/XGS4600-Zyxel.md +1 -2
  21. data/docs/Ruby-API.md +54 -2
  22. data/docs/Supported-OS-Types.md +12 -0
  23. data/extra/oxidized.service +7 -0
  24. data/lib/oxidized/cli.rb +7 -0
  25. data/lib/oxidized/config.rb +3 -0
  26. data/lib/oxidized/core.rb +1 -0
  27. data/lib/oxidized/hook/ciscosparkdiff.rb +11 -17
  28. data/lib/oxidized/hook/slackdiff.rb +5 -11
  29. data/lib/oxidized/hook/xmppdiff.rb +1 -0
  30. data/lib/oxidized/input/ssh.rb +43 -27
  31. data/lib/oxidized/input/telnet.rb +1 -0
  32. data/lib/oxidized/model/acos.rb +2 -2
  33. data/lib/oxidized/model/acsw.rb +6 -6
  34. data/lib/oxidized/model/adtran.rb +22 -0
  35. data/lib/oxidized/model/aen.rb +2 -2
  36. data/lib/oxidized/model/aireos.rb +3 -2
  37. data/lib/oxidized/model/alteonos.rb +2 -2
  38. data/lib/oxidized/model/aos.rb +1 -1
  39. data/lib/oxidized/model/aos7.rb +1 -1
  40. data/lib/oxidized/model/aosw.rb +5 -3
  41. data/lib/oxidized/model/apc_aos.rb +1 -1
  42. data/lib/oxidized/model/arbos.rb +2 -2
  43. data/lib/oxidized/model/asa.rb +8 -2
  44. data/lib/oxidized/model/awplus.rb +1 -1
  45. data/lib/oxidized/model/axos.rb +16 -0
  46. data/lib/oxidized/model/c4cmts.rb +3 -5
  47. data/lib/oxidized/model/casa.rb +1 -1
  48. data/lib/oxidized/model/catos.rb +1 -1
  49. data/lib/oxidized/model/ciscosma.rb +1 -1
  50. data/lib/oxidized/model/ciscosmb.rb +10 -4
  51. data/lib/oxidized/model/comtrol.rb +41 -0
  52. data/lib/oxidized/model/comware.rb +1 -1
  53. data/lib/oxidized/model/coriantgroove.rb +4 -6
  54. data/lib/oxidized/model/cumulus.rb +14 -1
  55. data/lib/oxidized/model/datacom.rb +1 -2
  56. data/lib/oxidized/model/dcnos.rb +1 -1
  57. data/lib/oxidized/model/dellx.rb +76 -0
  58. data/lib/oxidized/model/dlink.rb +2 -2
  59. data/lib/oxidized/model/dnos.rb +3 -1
  60. data/lib/oxidized/model/eciapollo.rb +34 -0
  61. data/lib/oxidized/model/edgecos.rb +1 -0
  62. data/lib/oxidized/model/edgeos.rb +6 -1
  63. data/lib/oxidized/model/eos.rb +3 -2
  64. data/lib/oxidized/model/fiberdriver.rb +1 -1
  65. data/lib/oxidized/model/firebrick.rb +31 -0
  66. data/lib/oxidized/model/firewareos.rb +1 -1
  67. data/lib/oxidized/model/fortios.rb +5 -4
  68. data/lib/oxidized/model/ftos.rb +4 -1
  69. data/lib/oxidized/model/fujitsupy.rb +3 -3
  70. data/lib/oxidized/model/gaiaos.rb +1 -1
  71. data/lib/oxidized/model/gcombnps.rb +3 -1
  72. data/lib/oxidized/model/hatteras.rb +1 -1
  73. data/lib/oxidized/model/hirschmann.rb +2 -2
  74. data/lib/oxidized/model/hpebladesystem.rb +1 -1
  75. data/lib/oxidized/model/ios.rb +21 -13
  76. data/lib/oxidized/model/ipos.rb +3 -3
  77. data/lib/oxidized/model/ironware.rb +3 -3
  78. data/lib/oxidized/model/isam.rb +1 -1
  79. data/lib/oxidized/model/junos.rb +1 -1
  80. data/lib/oxidized/model/masteros.rb +2 -3
  81. data/lib/oxidized/model/mlnxos.rb +5 -5
  82. data/lib/oxidized/model/model.rb +3 -0
  83. data/lib/oxidized/model/ndms.rb +1 -2
  84. data/lib/oxidized/model/netgear.rb +7 -9
  85. data/lib/oxidized/model/netonix.rb +1 -1
  86. data/lib/oxidized/model/netscaler.rb +6 -1
  87. data/lib/oxidized/model/nos.rb +2 -2
  88. data/lib/oxidized/model/oneos.rb +1 -1
  89. data/lib/oxidized/model/openbsd.rb +8 -22
  90. data/lib/oxidized/model/openwrt.rb +1 -0
  91. data/lib/oxidized/model/opnsense.rb +1 -1
  92. data/lib/oxidized/model/panos.rb +9 -9
  93. data/lib/oxidized/model/pfsense.rb +2 -1
  94. data/lib/oxidized/model/planet.rb +1 -1
  95. data/lib/oxidized/model/powerconnect.rb +7 -4
  96. data/lib/oxidized/model/procurve.rb +7 -5
  97. data/lib/oxidized/model/routeros.rb +1 -1
  98. data/lib/oxidized/model/saos.rb +1 -1
  99. data/lib/oxidized/model/screenos.rb +3 -3
  100. data/lib/oxidized/model/sros.rb +2 -2
  101. data/lib/oxidized/model/stoneos.rb +1 -1
  102. data/lib/oxidized/model/tmos.rb +2 -0
  103. data/lib/oxidized/model/tplink.rb +4 -0
  104. data/lib/oxidized/model/viptela.rb +29 -0
  105. data/lib/oxidized/model/voltaire.rb +5 -5
  106. data/lib/oxidized/model/voss.rb +4 -4
  107. data/lib/oxidized/model/vrp.rb +1 -1
  108. data/lib/oxidized/model/vyatta.rb +1 -1
  109. data/lib/oxidized/model/weos.rb +1 -1
  110. data/lib/oxidized/model/xos.rb +9 -2
  111. data/lib/oxidized/node.rb +20 -31
  112. data/lib/oxidized/nodes.rb +3 -0
  113. data/lib/oxidized/output/git.rb +17 -20
  114. data/lib/oxidized/output/gitcrypt.rb +2 -1
  115. data/lib/oxidized/output/http.rb +19 -12
  116. data/lib/oxidized/source/csv.rb +15 -8
  117. data/lib/oxidized/source/http.rb +26 -22
  118. data/lib/oxidized/string.rb +9 -4
  119. data/lib/oxidized/version.rb +2 -2
  120. data/lib/oxidized/worker.rb +44 -36
  121. data/oxidized.gemspec +1 -4
  122. metadata +26 -16
@@ -14,10 +14,10 @@ class Voss < Oxidized::Model
14
14
  # Get sys-info and remove information that changes such has temperature and power
15
15
  cmd 'show sys-info' do |cfg|
16
16
  cfg.gsub! /(^((.*)SysUpTime(.*))$)/, 'removed SysUpTime'
17
- cfg.gsub! /^((.*)Temperature Info \:(.*\r?\n){4})/, 'removed Temperature Info and 3 more lines'
18
- cfg.gsub! /(^((.*)AmbientTemperature(.*)\:(.*))$)/, 'removed AmbientTemperature'
19
- cfg.gsub! /(^((.*)Temperature(.*)\:(.*))$)/, 'removed Temperature'
20
- cfg.gsub! /(^((.*)Total Power Usage(.*)\:(.*))$)/, 'removed Total Power Usage'
17
+ cfg.gsub! /^((.*)Temperature Info :(.*\r?\n){4})/, 'removed Temperature Info and 3 more lines'
18
+ cfg.gsub! /(^((.*)AmbientTemperature(.*):(.*))$)/, 'removed AmbientTemperature'
19
+ cfg.gsub! /(^((.*)Temperature(.*):(.*))$)/, 'removed Temperature'
20
+ cfg.gsub! /(^((.*)Total Power Usage(.*):(.*))$)/, 'removed Total Power Usage'
21
21
  comment "#{cfg}\n"
22
22
  end
23
23
 
@@ -11,7 +11,7 @@ class VRP < Oxidized::Model
11
11
  end
12
12
 
13
13
  cmd :all do |cfg|
14
- cfg.each_line.to_a[1..-2].join
14
+ cfg.cut_both
15
15
  end
16
16
 
17
17
  cfg :telnet do
@@ -1,7 +1,7 @@
1
1
  class Vyatta < Oxidized::Model
2
2
  # Brocade Vyatta / VyOS model #
3
3
 
4
- prompt /\@.*?\:~\$\s/
4
+ prompt /@.*?:~\$\s/
5
5
 
6
6
  cmd :all do |cfg|
7
7
  cfg = cfg.lines.to_a[1..-2].join
@@ -4,7 +4,7 @@ class WEOS < Oxidized::Model
4
4
  prompt /^(\s[\w.@-]+[#>]\s?)$/
5
5
 
6
6
  cmd :all do |cfg|
7
- cfg.each_line.to_a[1..-2].join
7
+ cfg.cut_both
8
8
  end
9
9
 
10
10
  cmd 'show running-config' do |cfg|
@@ -27,7 +27,7 @@ class XOS < Oxidized::Model
27
27
  end
28
28
 
29
29
  cmd 'show configuration' do |cfg|
30
- cfg = cfg.each_line.reject { |line| line.match /^#(\s[\w]+\s)(Configuration generated)/ }.join
30
+ cfg = cfg.each_line.reject { |line| line.match /^#(\s[\w -]+\s)(Configuration generated)/ }.join
31
31
  cfg
32
32
  end
33
33
 
@@ -41,7 +41,14 @@ class XOS < Oxidized::Model
41
41
  end
42
42
 
43
43
  cfg :telnet, :ssh do
44
- post_login 'disable clipaging'
44
+ post_login do
45
+ data = cmd 'disable clipaging session'
46
+ match = data.match /^disable clipaging session\n\*?[\w .-]+(:\d+)? # $/m
47
+ next if match
48
+
49
+ cmd 'disable clipaging'
50
+ end
51
+
45
52
  pre_logout do
46
53
  send "exit\n"
47
54
  send "n\n"
@@ -39,6 +39,7 @@ module Oxidized
39
39
  # don't try input if model is missing config block, we may need strong config to class_name map
40
40
  cfg_name = input.to_s.split('::').last.downcase
41
41
  next unless @model.cfg[cfg_name] and not @model.cfg[cfg_name].empty?
42
+
42
43
  @model.input = input = input.new
43
44
  if config = run_input(input)
44
45
  Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} ran for #{name} successfully"
@@ -74,14 +75,17 @@ module Oxidized
74
75
  Oxidized.logger.send(level, '%s raised %s%s with msg "%s"' % [self.ip, err.class, resc, err.message])
75
76
  return false
76
77
  rescue => err
77
- file = Oxidized::Config::Crash + '.' + self.ip.to_s
78
- open file, 'w' do |fh|
78
+ crashdir = Oxidized.config.crash.directory
79
+ crashfile = Oxidized.config.crash.hostnames? ? self.name : self.ip.to_s
80
+ FileUtils.mkdir_p(crashdir) unless File.directory?(crashdir)
81
+
82
+ open File.join(crashdir, crashfile), 'w' do |fh|
79
83
  fh.puts Time.now.utc
80
84
  fh.puts err.message + ' [' + err.class.to_s + ']'
81
85
  fh.puts '-' * 50
82
86
  fh.puts err.backtrace
83
87
  end
84
- Oxidized.logger.error '%s raised %s with msg "%s", %s saved' % [self.ip, err.class, err.message, file]
88
+ Oxidized.logger.error '%s raised %s with msg "%s", %s saved' % [self.ip, err.class, err.message, crashfile]
85
89
  return false
86
90
  end
87
91
  end
@@ -173,32 +177,18 @@ module Oxidized
173
177
  end
174
178
 
175
179
  def resolve_repo opt
176
- if is_git? opt
177
- remote_repo = Oxidized.config.output.git.repo
178
-
179
- if remote_repo.is_a?(::String)
180
- if Oxidized.config.output.git.single_repo? || @group.nil?
181
- remote_repo
182
- else
183
- File.join(File.dirname(remote_repo), @group + '.git')
184
- end
185
- else
186
- remote_repo[@group]
187
- end
188
- elsif is_gitcrypt? opt
189
- remote_repo = Oxidized.config.output.gitcrypt.repo
190
-
191
- if remote_repo.is_a?(::String)
192
- if Oxidized.config.output.gitcrypt.single_repo? || @group.nil?
193
- remote_repo
194
- else
195
- File.join(File.dirname(remote_repo), @group + '.git')
196
- end
180
+ type = git_type opt
181
+ return nil unless type
182
+
183
+ remote_repo = Oxidized.config.output.send(type).repo
184
+ if remote_repo.is_a?(::String)
185
+ if Oxidized.config.output.send(type).single_repo? || @group.nil?
186
+ remote_repo
197
187
  else
198
- remote_repo[@group]
188
+ File.join(File.dirname(remote_repo), @group + '.git')
199
189
  end
200
190
  else
201
- return
191
+ remote_repo[@group]
202
192
  end
203
193
  end
204
194
 
@@ -237,12 +227,11 @@ module Oxidized
237
227
  value
238
228
  end
239
229
 
240
- def is_git? opt
241
- (opt[:output] || Oxidized.config.output.default) == 'git'
242
- end
230
+ def git_type opt
231
+ type = opt[:output] || Oxidized.config.output.default
232
+ return nil unless type[0..2] == "git"
243
233
 
244
- def is_gitcrypt? opt
245
- (opt[:output] || Oxidized.config.output.default) == 'gitcrypt'
234
+ type
246
235
  end
247
236
  end
248
237
  end
@@ -16,6 +16,7 @@ module Oxidized
16
16
  nodes.each do |node|
17
17
  # we want to load specific node(s), not all of them
18
18
  next unless node_want? node_want, node
19
+
19
20
  begin
20
21
  _node = Node.new node
21
22
  new.push _node
@@ -32,6 +33,7 @@ module Oxidized
32
33
 
33
34
  def node_want? node_want, node
34
35
  return true unless node_want
36
+
35
37
  node_want_ip = (IPAddr.new(node_want) rescue false)
36
38
  name_is_ip = (IPAddr.new(node[:name]) rescue false)
37
39
  if name_is_ip and node_want_ip == node[:name]
@@ -173,6 +175,7 @@ module Oxidized
173
175
  node = find { |n| n.name == node_name }
174
176
  output = node.output.new
175
177
  raise Oxidized::NotSupported unless output.respond_to? :fetch
178
+
176
179
  yield node, output
177
180
  end
178
181
  end
@@ -167,7 +167,7 @@ module Oxidized
167
167
 
168
168
  begin
169
169
  repo = Rugged::Repository.new repo
170
- update_repo repo, file, data, @msg, @user, @email
170
+ update_repo repo, file, data
171
171
  rescue Rugged::OSError, Rugged::RepositoryError => open_error
172
172
  begin
173
173
  Rugged::Repository.init_at repo, :bare
@@ -178,27 +178,24 @@ module Oxidized
178
178
  end
179
179
  end
180
180
 
181
- def update_repo repo, file, data, msg, user, email
181
+ def update_repo repo, file, data
182
+ oid_old = repo.blob_at(repo.head.target_id, file) rescue nil
183
+ return false if oid_old and oid_old.content == data
184
+
182
185
  oid = repo.write data, :blob
183
186
  index = repo.index
184
- index.read_tree repo.head.target.tree unless repo.empty?
185
-
186
- tree_old = index.write_tree repo
187
- index.add :path => file, :oid => oid, :mode => 0100644
188
- tree_new = index.write_tree repo
189
-
190
- if tree_old != tree_new
191
- repo.config['user.name'] = user
192
- repo.config['user.email'] = email
193
- @commitref = Rugged::Commit.create(repo,
194
- :tree => index.write_tree(repo),
195
- :message => msg,
196
- :parents => repo.empty? ? [] : [repo.head.target].compact,
197
- :update_ref => 'HEAD',)
198
-
199
- index.write
200
- true
201
- end
187
+ index.add path: file, oid: oid, mode: 0100644
188
+
189
+ repo.config['user.name'] = @user
190
+ repo.config['user.email'] = @email
191
+ @commitref = Rugged::Commit.create(repo,
192
+ tree: index.write_tree(repo),
193
+ message: @msg,
194
+ parents: repo.empty? ? [] : [repo.head.target].compact,
195
+ update_ref: 'HEAD')
196
+
197
+ index.write
198
+ true
202
199
  end
203
200
  end
204
201
  end
@@ -4,7 +4,7 @@ module Oxidized
4
4
  begin
5
5
  require 'git'
6
6
  rescue LoadError
7
- raise OxidizedError, 'git not found: sudo gem install ruby-git'
7
+ raise OxidizedError, 'git not found: sudo gem install git'
8
8
  end
9
9
 
10
10
  attr_reader :commitref
@@ -99,6 +99,7 @@ module Oxidized
99
99
  else
100
100
  File.read path
101
101
  end
102
+
102
103
  lock repo
103
104
  rescue
104
105
  'node not found'
@@ -14,28 +14,19 @@ module Oxidized
14
14
  raise NoConfig, 'no output http config, edit ~/.config/oxidized/config'
15
15
  end
16
16
  end
17
+
17
18
  require "net/http"
18
19
  require "uri"
19
20
  require "json"
21
+
20
22
  def store node, outputs, opt = {}
21
23
  @commitref = nil
22
- json = JSON.pretty_generate(
23
- {
24
- 'msg' => opt[:msg],
25
- 'user' => opt[:user],
26
- 'email' => opt[:email],
27
- 'group' => opt[:group],
28
- 'node' => node,
29
- 'config' => outputs.to_cfg,
30
- # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
31
- }
32
- )
33
24
  uri = URI.parse @cfg.url
34
25
  http = Net::HTTP.new uri.host, uri.port
35
26
  # http.use_ssl = true if uri.scheme = 'https'
36
27
  req = Net::HTTP::Post.new(uri.request_uri, initheader = { 'Content-Type' => 'application/json' })
37
28
  req.basic_auth @cfg.user, @cfg.password
38
- req.body = json
29
+ req.body = generate_json(node, outputs, opt)
39
30
  response = http.request req
40
31
 
41
32
  case response.code.to_i
@@ -50,5 +41,21 @@ module Oxidized
50
41
  Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
51
42
  end
52
43
  end
44
+
45
+ private
46
+
47
+ def generate_json node, outputs, opt
48
+ JSON.pretty_generate(
49
+ {
50
+ 'msg' => opt[:msg],
51
+ 'user' => opt[:user],
52
+ 'email' => opt[:email],
53
+ 'group' => opt[:group],
54
+ 'node' => node,
55
+ 'config' => outputs.to_cfg,
56
+ # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
57
+ }
58
+ )
59
+ end
53
60
  end
54
61
  end
@@ -20,17 +20,12 @@ module Oxidized
20
20
 
21
21
  def load _node_want = nil
22
22
  nodes = []
23
- file = File.expand_path(@cfg.file)
24
- file = if @cfg.gpg?
25
- crypto = GPGME::Crypto.new password: @cfg.gpg_password
26
- file = crypto.decrypt(File.open(file)).to_s
27
- else
28
- open(file)
29
- end
30
- file.each_line do |line|
23
+ open_file.each_line do |line|
31
24
  next if line.match(/^\s*#/)
25
+
32
26
  data = line.chomp.split(@cfg.delimiter, -1)
33
27
  next if data.empty?
28
+
34
29
  # map node parameters
35
30
  keys = {}
36
31
  @cfg.map.each do |key, position|
@@ -49,5 +44,17 @@ module Oxidized
49
44
  end
50
45
  nodes
51
46
  end
47
+
48
+ private
49
+
50
+ def open_file
51
+ file = File.expand_path(@cfg.file)
52
+ if @cfg.gpg?
53
+ crypto = GPGME::Crypto.new password: @cfg.gpg_password
54
+ crypto.decrypt(File.open(file)).to_s
55
+ else
56
+ open(file)
57
+ end
58
+ end
52
59
  end
53
60
  end
@@ -12,36 +12,17 @@ module Oxidized
12
12
  end
13
13
 
14
14
  require "net/http"
15
+ require "net/https"
15
16
  require "uri"
16
17
  require "json"
17
18
 
18
19
  def load node_want = nil
19
20
  nodes = []
20
- uri = URI.parse(@cfg.url)
21
- http = Net::HTTP.new(uri.host, uri.port)
22
- http.use_ssl = true if uri.scheme == 'https'
23
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @cfg.secure
24
-
25
- # map headers
26
- headers = {}
27
- @cfg.headers.each do |header, value|
28
- headers[header] = value
29
- end
30
-
31
- req_uri = uri.request_uri
32
- if node_want
33
- req_uri = "#{req_uri}/#{node_want}"
34
- end
35
- request = Net::HTTP::Get.new(req_uri, headers)
36
- if (@cfg.user? && @cfg.pass?)
37
- request.basic_auth(@cfg.user, @cfg.pass)
38
- end
39
-
40
- response = http.request(request)
41
- data = JSON.parse(response.body)
21
+ data = JSON.parse(read_http(node_want))
42
22
  data = string_navigate(data, @cfg.hosts_location) if @cfg.hosts_location?
43
23
  data.each do |node|
44
24
  next if node.empty?
25
+
45
26
  # map node parameters
46
27
  keys = {}
47
28
  @cfg.map.each do |key, want_position|
@@ -72,5 +53,28 @@ module Oxidized
72
53
  end
73
54
  object
74
55
  end
56
+
57
+ def read_http node_want
58
+ uri = URI.parse(@cfg.url)
59
+ http = Net::HTTP.new(uri.host, uri.port)
60
+ http.use_ssl = true if uri.scheme == 'https'
61
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @cfg.secure
62
+
63
+ # map headers
64
+ headers = {}
65
+ @cfg.headers.each do |header, value|
66
+ headers[header] = value
67
+ end
68
+
69
+ req_uri = uri.request_uri
70
+ if node_want
71
+ req_uri = "#{req_uri}/#{node_want}"
72
+ end
73
+ request = Net::HTTP::Get.new(req_uri, headers)
74
+ if (@cfg.user? && @cfg.pass?)
75
+ request.basic_auth(@cfg.user, @cfg.pass)
76
+ end
77
+ http.request(request).body
78
+ end
75
79
  end
76
80
  end
@@ -4,13 +4,18 @@ module Oxidized
4
4
  attr_accessor :type, :cmd, :name
5
5
 
6
6
  # @return [Oxidized::String] copy of self with last line removed
7
- def cut_tail
8
- Oxidized::String.new each_line.to_a[0..-2].join
7
+ def cut_tail lines = 1
8
+ Oxidized::String.new each_line.to_a[0..-1 - lines].join
9
9
  end
10
10
 
11
11
  # @return [Oxidized::String] copy of self with first line removed
12
- def cut_head
13
- Oxidized::String.new each_line.to_a[1..-1].join
12
+ def cut_head lines = 1
13
+ Oxidized::String.new each_line.to_a[lines..-1].join
14
+ end
15
+
16
+ # @return [Oxidized::String] copy of self with first and last lines removed
17
+ def cut_both head = 1, tail = 1
18
+ Oxidized::String.new each_line.to_a[head..-1 - tail].join
14
19
  end
15
20
 
16
21
  # sets @cmd and @name unless @name is already set
@@ -1,6 +1,6 @@
1
1
  module Oxidized
2
- VERSION = '0.24.0'
3
- VERSION_FULL = '0.24.0'
2
+ VERSION = '0.25.0'
3
+ VERSION_FULL = '0.25.0'
4
4
  def self.version_set
5
5
  version_full = %x(git describe --tags).chop rescue ""
6
6
  version = %x(git describe --tags --abbrev=0).chop rescue ""
@@ -28,8 +28,9 @@ module Oxidized
28
28
  # shift nodes and get the next node
29
29
  node = @nodes.get
30
30
  node.running? ? next : node.running = true
31
+
31
32
  @jobs.push Job.new node
32
- Oxidized.logger.debug "lib/oxidized/worker.rb: Added #{node.name} to the job queue"
33
+ Oxidized.logger.debug "lib/oxidized/worker.rb: Added #{node.group}/#{node.name} to the job queue"
33
34
  end
34
35
 
35
36
  run_done_hook if is_cycle_finished?
@@ -42,49 +43,56 @@ module Oxidized
42
43
  node.stats.add job
43
44
  @jobs.duration job.time
44
45
  node.running = false
45
-
46
46
  if job.status == :success
47
- @jobs_done += 1 # needed for :nodes_done hook
48
- Oxidized.Hooks.handle :node_success, :node => node,
49
- :job => job
50
- msg = "update #{node.name}"
51
- msg += " from #{node.from}" if node.from
52
- msg += " with message '#{node.msg}'" if node.msg
53
- output = node.output.new
54
- if output.store node.name, job.config,
55
- :msg => msg, :email => node.email, :user => node.user, :group => node.group
56
- node.modified
57
- Oxidized.logger.info "Configuration updated for #{node.group}/#{node.name}"
58
- Oxidized.Hooks.handle :post_store, :node => node,
59
- :job => job,
60
- :commitref => output.commitref
61
- end
62
- node.reset
47
+ process_success node, job
63
48
  else
64
- msg = "#{node.name} status #{job.status}"
65
- if node.retry < Oxidized.config.retries
66
- node.retry += 1
67
- msg += ", retry attempt #{node.retry}"
68
- @nodes.next node.name
69
- else
70
- # Only increment the @jobs_done when we give up retries for a node (or success).
71
- # As it would otherwise cause @jobs_done to be incremented with generic retries.
72
- # This would cause :nodes_done hook to desync from running at the end of the nodelist and
73
- # be fired when the @jobs_done > @nodes.count (could be mid-cycle on the next cycle).
74
- @jobs_done += 1
75
- msg += ", retries exhausted, giving up"
76
- node.retry = 0
77
- Oxidized.Hooks.handle :node_fail, :node => node,
78
- :job => job
79
- end
80
- Oxidized.logger.warn msg
49
+ process_failure node, job
81
50
  end
82
51
  rescue NodeNotFound
83
- Oxidized.logger.warn "#{node.name} not found, removed while collecting?"
52
+ Oxidized.logger.warn "#{node.group}/#{node.name} not found, removed while collecting?"
84
53
  end
85
54
 
86
55
  private
87
56
 
57
+ def process_success node, job
58
+ @jobs_done += 1 # needed for :nodes_done hook
59
+ Oxidized.Hooks.handle :node_success, node: node,
60
+ job: job
61
+ msg = "update #{node.group}/#{node.name}"
62
+ msg += " from #{node.from}" if node.from
63
+ msg += " with message '#{node.msg}'" if node.msg
64
+ output = node.output.new
65
+ if output.store node.name, job.config,
66
+ msg: msg, email: node.email, user: node.user, group: node.group
67
+ node.modified
68
+ Oxidized.logger.info "Configuration updated for #{node.group}/#{node.name}"
69
+ Oxidized.Hooks.handle :post_store, node: node,
70
+ job: job,
71
+ commitref: output.commitref
72
+ end
73
+ node.reset
74
+ end
75
+
76
+ def process_failure node, job
77
+ msg = "#{node.group}/#{node.name} status #{job.status}"
78
+ if node.retry < Oxidized.config.retries
79
+ node.retry += 1
80
+ msg += ", retry attempt #{node.retry}"
81
+ @nodes.next node.name
82
+ else
83
+ # Only increment the @jobs_done when we give up retries for a node (or success).
84
+ # As it would otherwise cause @jobs_done to be incremented with generic retries.
85
+ # This would cause :nodes_done hook to desync from running at the end of the nodelist and
86
+ # be fired when the @jobs_done > @nodes.count (could be mid-cycle on the next cycle).
87
+ @jobs_done += 1
88
+ msg += ", retries exhausted, giving up"
89
+ node.retry = 0
90
+ Oxidized.Hooks.handle :node_fail, :node => node,
91
+ :job => job
92
+ end
93
+ Oxidized.logger.warn msg
94
+ end
95
+
88
96
  def is_cycle_finished?
89
97
  if @jobs_done > @nodes.count
90
98
  true