oxidized 0.20.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (222) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +4 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
  4. data/.github/no-response.yml +13 -0
  5. data/.github/workflows/publishdocker.yml +13 -0
  6. data/.gitignore +4 -0
  7. data/.rubocop.yml +73 -0
  8. data/.rubocop_todo.yml +120 -0
  9. data/.travis.yml +6 -1
  10. data/CHANGELOG.md +693 -243
  11. data/Dockerfile +27 -19
  12. data/LICENSE +201 -0
  13. data/README.md +234 -913
  14. data/Rakefile +48 -7
  15. data/TODO.md +29 -23
  16. data/bin/console +1 -1
  17. data/bin/oxidized +6 -5
  18. data/docs/Configuration.md +313 -0
  19. data/docs/Creating-Models.md +140 -0
  20. data/docs/Hooks.md +274 -0
  21. data/docs/Model-Notes/AireOS.md +11 -0
  22. data/docs/Model-Notes/ArbOS.md +11 -0
  23. data/docs/Model-Notes/Comware.md +13 -0
  24. data/docs/Model-Notes/Cumulus.md +40 -0
  25. data/docs/Model-Notes/EOS.md +12 -0
  26. data/docs/Model-Notes/IOS.md +29 -0
  27. data/docs/Model-Notes/JunOS.md +33 -0
  28. data/docs/Model-Notes/LinuxGeneric.md +24 -0
  29. data/docs/Model-Notes/Netgear.md +87 -0
  30. data/docs/Model-Notes/Nokia.md +9 -0
  31. data/docs/Model-Notes/README.md +24 -0
  32. data/docs/Model-Notes/SmartAX-Huawei.md +35 -0
  33. data/docs/Model-Notes/VRP-Huawei.md +34 -0
  34. data/docs/Model-Notes/Viptela.md +12 -0
  35. data/docs/Model-Notes/XGS4600-Zyxel.md +36 -0
  36. data/docs/Outputs.md +190 -0
  37. data/docs/Ruby-API.md +199 -0
  38. data/docs/Sources.md +171 -0
  39. data/docs/Supported-OS-Types.md +227 -0
  40. data/docs/Troubleshooting.md +66 -0
  41. data/extra/nagios_check_failing_nodes.rb +9 -2
  42. data/extra/oxidized-report-git-commits +21 -40
  43. data/extra/oxidized-ubuntu.haproxy +45 -0
  44. data/extra/oxidized.logrotate +7 -0
  45. data/extra/oxidized.service +13 -0
  46. data/extra/rest_client.rb +7 -10
  47. data/extra/syslog.rb +47 -42
  48. data/lib/oxidized/cli.rb +41 -31
  49. data/lib/oxidized/config/vars.rb +9 -14
  50. data/lib/oxidized/config.rb +20 -13
  51. data/lib/oxidized/core.rb +8 -10
  52. data/lib/oxidized/hook/awssns.rb +6 -7
  53. data/lib/oxidized/hook/ciscosparkdiff.rb +43 -0
  54. data/lib/oxidized/hook/exec.rb +19 -24
  55. data/lib/oxidized/hook/githubrepo.rb +17 -17
  56. data/lib/oxidized/hook/noophook.rb +1 -1
  57. data/lib/oxidized/hook/slackdiff.rb +32 -19
  58. data/lib/oxidized/hook/xmppdiff.rb +59 -0
  59. data/lib/oxidized/hook.rb +63 -64
  60. data/lib/oxidized/input/cli.rb +22 -12
  61. data/lib/oxidized/input/exec.rb +28 -0
  62. data/lib/oxidized/input/ftp.rb +16 -15
  63. data/lib/oxidized/input/http.rb +72 -0
  64. data/lib/oxidized/input/input.rb +6 -6
  65. data/lib/oxidized/input/ssh.rb +64 -56
  66. data/lib/oxidized/input/telnet.rb +59 -102
  67. data/lib/oxidized/input/tftp.rb +9 -10
  68. data/lib/oxidized/jobs.rb +9 -10
  69. data/lib/oxidized/manager.rb +42 -44
  70. data/lib/oxidized/model/acos.rb +19 -20
  71. data/lib/oxidized/model/acsw.rb +62 -0
  72. data/lib/oxidized/model/adtran.rb +26 -0
  73. data/lib/oxidized/model/aen.rb +19 -0
  74. data/lib/oxidized/model/aireos.rb +9 -10
  75. data/lib/oxidized/model/airfiber.rb +22 -0
  76. data/lib/oxidized/model/alteonos.rb +58 -0
  77. data/lib/oxidized/model/alvarion.rb +0 -4
  78. data/lib/oxidized/model/aos.rb +11 -5
  79. data/lib/oxidized/model/aos7.rb +6 -7
  80. data/lib/oxidized/model/aosw.rb +30 -27
  81. data/lib/oxidized/model/apc_aos.rb +2 -5
  82. data/lib/oxidized/model/arbos.rb +26 -0
  83. data/lib/oxidized/model/aricentiss.rb +49 -0
  84. data/lib/oxidized/model/asa.rb +61 -22
  85. data/lib/oxidized/model/asyncos.rb +46 -0
  86. data/lib/oxidized/model/audiocodes.rb +28 -0
  87. data/lib/oxidized/model/audiocodesmp.rb +28 -0
  88. data/lib/oxidized/model/awplus.rb +84 -0
  89. data/lib/oxidized/model/axos.rb +16 -0
  90. data/lib/oxidized/model/boss.rb +77 -0
  91. data/lib/oxidized/model/br6910.rb +42 -45
  92. data/lib/oxidized/model/c4cmts.rb +6 -10
  93. data/lib/oxidized/model/cambium.rb +23 -0
  94. data/lib/oxidized/model/casa.rb +1 -1
  95. data/lib/oxidized/model/catos.rb +1 -3
  96. data/lib/oxidized/model/cisconga.rb +1 -3
  97. data/lib/oxidized/model/ciscosma.rb +42 -0
  98. data/lib/oxidized/model/ciscosmb.rb +30 -10
  99. data/lib/oxidized/model/ciscovpn3k.rb +11 -0
  100. data/lib/oxidized/model/cnos.rb +33 -0
  101. data/lib/oxidized/model/comnetms.rb +43 -0
  102. data/lib/oxidized/model/comtrol.rb +41 -0
  103. data/lib/oxidized/model/comware.rb +28 -16
  104. data/lib/oxidized/model/coriant8600.rb +3 -5
  105. data/lib/oxidized/model/coriantgroove.rb +26 -0
  106. data/lib/oxidized/model/corianttmos.rb +1 -3
  107. data/lib/oxidized/model/cumulus.rb +60 -49
  108. data/lib/oxidized/model/datacom.rb +1 -4
  109. data/lib/oxidized/model/dcnos.rb +46 -0
  110. data/lib/oxidized/model/dellx.rb +76 -0
  111. data/lib/oxidized/model/dlink.rb +5 -4
  112. data/lib/oxidized/model/dnos.rb +11 -5
  113. data/lib/oxidized/model/eciapollo.rb +34 -0
  114. data/lib/oxidized/model/edgecos.rb +49 -0
  115. data/lib/oxidized/model/edgeos.rb +12 -5
  116. data/lib/oxidized/model/edgeswitch.rb +2 -4
  117. data/lib/oxidized/model/enterasys.rb +28 -0
  118. data/lib/oxidized/model/eos.rb +8 -8
  119. data/lib/oxidized/model/fabricos.rb +4 -6
  120. data/lib/oxidized/model/fastiron.rb +66 -0
  121. data/lib/oxidized/model/fiberdriver.rb +2 -2
  122. data/lib/oxidized/model/firebrick.rb +31 -0
  123. data/lib/oxidized/model/firelinuxos.rb +41 -0
  124. data/lib/oxidized/model/firewareos.rb +3 -6
  125. data/lib/oxidized/model/fortios.rb +31 -19
  126. data/lib/oxidized/model/ftos.rb +8 -5
  127. data/lib/oxidized/model/fujitsupy.rb +5 -7
  128. data/lib/oxidized/model/gaiaos.rb +7 -11
  129. data/lib/oxidized/model/gcombnps.rb +84 -0
  130. data/lib/oxidized/model/grandstream.rb +9 -0
  131. data/lib/oxidized/model/hatteras.rb +9 -6
  132. data/lib/oxidized/model/hirschmann.rb +39 -0
  133. data/lib/oxidized/model/hpebladesystem.rb +20 -18
  134. data/lib/oxidized/model/hpemsa.rb +10 -0
  135. data/lib/oxidized/model/hpmsm.rb +84 -0
  136. data/lib/oxidized/model/ibos.rb +55 -0
  137. data/lib/oxidized/model/icotera.rb +27 -0
  138. data/lib/oxidized/model/ios.rb +63 -70
  139. data/lib/oxidized/model/iosxe.rb +5 -0
  140. data/lib/oxidized/model/iosxr.rb +2 -3
  141. data/lib/oxidized/model/ipos.rb +10 -6
  142. data/lib/oxidized/model/ironware.rb +20 -19
  143. data/lib/oxidized/model/isam.rb +5 -6
  144. data/lib/oxidized/model/junos.rb +9 -11
  145. data/lib/oxidized/model/linuxgeneric.rb +74 -0
  146. data/lib/oxidized/model/masteros.rb +3 -6
  147. data/lib/oxidized/model/mlnxos.rb +9 -10
  148. data/lib/oxidized/model/model.rb +72 -46
  149. data/lib/oxidized/model/mtrlrfs.rb +1 -4
  150. data/lib/oxidized/model/ndms.rb +23 -0
  151. data/lib/oxidized/model/netgear.rb +35 -15
  152. data/lib/oxidized/model/netonix.rb +2 -2
  153. data/lib/oxidized/model/netscaler.rb +6 -3
  154. data/lib/oxidized/model/nos.rb +5 -7
  155. data/lib/oxidized/model/nsxconfig.rb +22 -0
  156. data/lib/oxidized/model/nsxfirewall.rb +22 -0
  157. data/lib/oxidized/model/nxos.rb +13 -3
  158. data/lib/oxidized/model/oneos.rb +15 -9
  159. data/lib/oxidized/model/openbsd.rb +63 -0
  160. data/lib/oxidized/model/opengear.rb +3 -5
  161. data/lib/oxidized/model/openwrt.rb +78 -0
  162. data/lib/oxidized/model/opnsense.rb +19 -0
  163. data/lib/oxidized/model/os10.rb +46 -0
  164. data/lib/oxidized/model/outputs.rb +5 -7
  165. data/lib/oxidized/model/panos.rb +11 -12
  166. data/lib/oxidized/model/pfsense.rb +11 -6
  167. data/lib/oxidized/model/planet.rb +14 -17
  168. data/lib/oxidized/model/powerconnect.rb +24 -19
  169. data/lib/oxidized/model/procurve.rb +43 -11
  170. data/lib/oxidized/model/purityos.rb +12 -0
  171. data/lib/oxidized/model/qtech.rb +41 -0
  172. data/lib/oxidized/model/quantaos.rb +4 -6
  173. data/lib/oxidized/model/raisecom.rb +19 -0
  174. data/lib/oxidized/model/routeros.rb +26 -8
  175. data/lib/oxidized/model/saos.rb +1 -2
  176. data/lib/oxidized/model/screenos.rb +8 -11
  177. data/lib/oxidized/model/sgos.rb +45 -0
  178. data/lib/oxidized/model/siklu.rb +1 -3
  179. data/lib/oxidized/model/slxos.rb +59 -0
  180. data/lib/oxidized/model/smartax.rb +25 -0
  181. data/lib/oxidized/model/sonicos.rb +51 -0
  182. data/lib/oxidized/model/speedtouch.rb +34 -0
  183. data/lib/oxidized/model/sros.rb +96 -0
  184. data/lib/oxidized/model/stoneos.rb +32 -0
  185. data/lib/oxidized/model/supermicro.rb +6 -41
  186. data/lib/oxidized/model/tdre.rb +30 -0
  187. data/lib/oxidized/model/telco.rb +24 -0
  188. data/lib/oxidized/model/timos.rb +6 -114
  189. data/lib/oxidized/model/tmos.rb +6 -3
  190. data/lib/oxidized/model/tplink.rb +11 -11
  191. data/lib/oxidized/model/trango.rb +21 -42
  192. data/lib/oxidized/model/ucs.rb +30 -0
  193. data/lib/oxidized/model/viptela.rb +29 -0
  194. data/lib/oxidized/model/voltaire.rb +9 -12
  195. data/lib/oxidized/model/voss.rb +17 -6
  196. data/lib/oxidized/model/vrp.rb +11 -6
  197. data/lib/oxidized/model/vyatta.rb +8 -6
  198. data/lib/oxidized/model/weos.rb +20 -0
  199. data/lib/oxidized/model/xos.rb +20 -8
  200. data/lib/oxidized/model/zhoneolt.rb +2 -2
  201. data/lib/oxidized/model/zynos.rb +1 -3
  202. data/lib/oxidized/model/zynoscli.rb +36 -0
  203. data/lib/oxidized/model/zynosgs.rb +38 -0
  204. data/lib/oxidized/node/stats.rb +33 -8
  205. data/lib/oxidized/node.rb +86 -95
  206. data/lib/oxidized/nodes.rb +48 -44
  207. data/lib/oxidized/output/file.rb +32 -37
  208. data/lib/oxidized/output/git.rb +138 -153
  209. data/lib/oxidized/output/gitcrypt.rb +228 -242
  210. data/lib/oxidized/output/http.rb +35 -34
  211. data/lib/oxidized/output/output.rb +2 -3
  212. data/lib/oxidized/source/csv.rb +50 -44
  213. data/lib/oxidized/source/http.rb +58 -58
  214. data/lib/oxidized/source/source.rb +9 -10
  215. data/lib/oxidized/source/sql.rb +47 -45
  216. data/lib/oxidized/string.rb +18 -14
  217. data/lib/oxidized/version.rb +17 -1
  218. data/lib/oxidized/worker.rb +72 -33
  219. data/oxidized.gemspec +20 -19
  220. metadata +180 -36
  221. data/.ruby-version +0 -1
  222. data/Gemfile.lock +0 -44
@@ -1,5 +1,8 @@
1
1
  require 'slack'
2
2
 
3
+ # defaults to posting a diff, if messageformat is supplied them a message will be posted too
4
+ # diff defaults to true
5
+
3
6
  class SlackDiff < Oxidized::Hook
4
7
  def validate_cfg!
5
8
  raise KeyError, 'hook.token is required' unless cfg.has_key?('token')
@@ -7,28 +10,38 @@ class SlackDiff < Oxidized::Hook
7
10
  end
8
11
 
9
12
  def run_hook(ctx)
10
- if ctx.node
11
- if ctx.event.to_s == "post_store"
12
- log "Connecting to slack"
13
- Slack.configure do |config|
14
- config.token = cfg.token
15
- config.proxy = cfg.proxy if cfg.has_key?('proxy')
16
- end
17
- client = Slack::Client.new
18
- client.auth_test
19
- log "Connected"
20
- gitoutput = ctx.node.output.new
21
- diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
22
- title = "#{ctx.node.name.to_s} #{ctx.node.group.to_s} #{ctx.node.model.class.name.to_s.downcase}"
13
+ return unless ctx.node
14
+ return unless ctx.event.to_s == "post_store"
15
+
16
+ log "Connecting to slack"
17
+ Slack.configure do |config|
18
+ config.token = cfg.token
19
+ config.proxy = cfg.proxy if cfg.has_key?('proxy')
20
+ end
21
+ client = Slack::Client.new
22
+ client.auth_test
23
+ log "Connected"
24
+ if cfg.has_key?("diff") ? cfg.diff : true
25
+ gitoutput = ctx.node.output.new
26
+ diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
27
+ unless diff == "no diffs"
28
+ title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
23
29
  log "Posting diff as snippet to #{cfg.channel}"
24
30
  client.files_upload(channels: cfg.channel, as_user: true,
25
- content: diff[:patch].lines.to_a[4..-1].join,
26
- filetype: "diff",
27
- title: title,
28
- filename: "change"
29
- )
30
- log "Finished"
31
+ content: diff[:patch].lines.to_a[4..-1].join,
32
+ filetype: "diff",
33
+ title: title,
34
+ filename: "change")
31
35
  end
32
36
  end
37
+ # message custom formatted - optional
38
+ if cfg.message?
39
+ log cfg.message
40
+ msg = cfg.message % { node: ctx.node.name.to_s, group: ctx.node.group.to_s, commitref: ctx.commitref, model: ctx.node.model.class.name.to_s.downcase }
41
+ log msg
42
+ log "Posting message to #{cfg.channel}"
43
+ client.chat_postMessage(channel: cfg.channel, text: msg, as_user: true)
44
+ end
45
+ log "Finished"
33
46
  end
34
47
  end
@@ -0,0 +1,59 @@
1
+ require 'xmpp4r'
2
+ require 'xmpp4r/muc/helper/simplemucclient'
3
+
4
+ class XMPPDiff < Oxidized::Hook
5
+ def validate_cfg!
6
+ raise KeyError, 'hook.jid is required' unless cfg.has_key?('jid')
7
+ raise KeyError, 'hook.password is required' unless cfg.has_key?('password')
8
+ raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
9
+ raise KeyError, 'hook.nick is required' unless cfg.has_key?('nick')
10
+ end
11
+
12
+ def run_hook(ctx)
13
+ return unless ctx.node
14
+ return unless ctx.event.to_s == "post_store"
15
+
16
+ begin
17
+ Timeout.timeout(15) do
18
+ gitoutput = ctx.node.output.new
19
+ diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
20
+
21
+ interesting = diff[:patch].lines.to_a[4..-1].any? do |line|
22
+ ["+", "-"].include?(line[0]) && (not ["#", "!"].include?(line[1]))
23
+ 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
+
27
+ if interesting
28
+ log "Connecting to XMPP"
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
50
+
51
+ log "Finished"
52
+
53
+ end
54
+ end
55
+ rescue Timeout::Error
56
+ log "timed out"
57
+ end
58
+ end
59
+ end
data/lib/oxidized/hook.rb CHANGED
@@ -1,88 +1,87 @@
1
1
  module Oxidized
2
- class HookManager
3
- class << self
4
- def from_config cfg
5
- mgr = new
6
- cfg.hooks.each do |name,h_cfg|
7
- h_cfg.events.each do |event|
8
- mgr.register event.to_sym, name, h_cfg.type, h_cfg
2
+ class HookManager
3
+ class << self
4
+ def from_config(cfg)
5
+ mgr = new
6
+ cfg.hooks.each do |name, h_cfg|
7
+ h_cfg.events.each do |event|
8
+ mgr.register event.to_sym, name, h_cfg.type, h_cfg
9
+ end
9
10
  end
11
+ mgr
10
12
  end
11
- mgr
12
13
  end
13
- end
14
-
15
- # HookContext is passed to each hook. It can contain anything related to the
16
- # event in question. At least it contains the event name
17
- class HookContext < OpenStruct; end
18
14
 
19
- # RegisteredHook is a container for a Hook instance
20
- class RegisteredHook < Struct.new(:name, :hook); end
15
+ # HookContext is passed to each hook. It can contain anything related to the
16
+ # event in question. At least it contains the event name
17
+ class HookContext < OpenStruct; end
21
18
 
22
- Events = [
23
- :node_success,
24
- :node_fail,
25
- :post_store,
26
- ]
27
- attr_reader :registered_hooks
19
+ # RegisteredHook is a container for a Hook instance
20
+ RegisteredHook = Struct.new(:name, :hook)
28
21
 
29
- def initialize
30
- @registered_hooks = Hash.new {|h,k| h[k] = []}
31
- end
22
+ Events = %i[
23
+ node_success
24
+ node_fail
25
+ post_store
26
+ nodes_done
27
+ ].freeze
28
+ attr_reader :registered_hooks
32
29
 
33
- def register event, name, hook_type, cfg
34
- unless Events.include? event
35
- raise ArgumentError,
36
- "unknown event #{event}, available: #{Events.join ','}"
30
+ def initialize
31
+ @registered_hooks = Hash.new { |h, k| h[k] = [] }
37
32
  end
38
33
 
39
- Oxidized.mgr.add_hook hook_type
40
- begin
41
- hook = Oxidized.mgr.hook.fetch(hook_type).new
42
- rescue KeyError
43
- raise KeyError, "cannot find hook #{hook_type.inspect}"
44
- end
34
+ def register(event, name, hook_type, cfg)
35
+ unless Events.include? event
36
+ raise ArgumentError,
37
+ "unknown event #{event}, available: #{Events.join ','}"
38
+ end
45
39
 
46
- hook.cfg = cfg
40
+ Oxidized.mgr.add_hook(hook_type) || raise("cannot load hook '#{hook_type}', not found")
41
+ begin
42
+ hook = Oxidized.mgr.hook.fetch(hook_type).new
43
+ rescue KeyError
44
+ raise KeyError, "cannot find hook #{hook_type.inspect}"
45
+ end
47
46
 
48
- @registered_hooks[event] << RegisteredHook.new(name, hook)
49
- Oxidized.logger.debug "Hook #{name.inspect} registered #{hook.class} for event #{event.inspect}"
50
- end
47
+ hook.cfg = cfg
51
48
 
52
- def handle event, ctx_params={}
53
- ctx = HookContext.new ctx_params
54
- ctx.event = event
49
+ @registered_hooks[event] << RegisteredHook.new(name, hook)
50
+ Oxidized.logger.debug "Hook #{name.inspect} registered #{hook.class} for event #{event.inspect}"
51
+ end
55
52
 
56
- @registered_hooks[event].each do |r_hook|
57
- begin
58
- r_hook.hook.run_hook ctx
59
- rescue => e
60
- Oxidized.logger.error "Hook #{r_hook.name} (#{r_hook.hook}) failed " +
61
- "(#{e.inspect}) for event #{event.inspect}"
53
+ def handle(event, ctx_params = {})
54
+ ctx = HookContext.new ctx_params
55
+ ctx.event = event
56
+
57
+ @registered_hooks[event].each do |r_hook|
58
+ begin
59
+ r_hook.hook.run_hook ctx
60
+ rescue StandardError => e
61
+ Oxidized.logger.error "Hook #{r_hook.name} (#{r_hook.hook}) failed " \
62
+ "(#{e.inspect}) for event #{event.inspect}"
63
+ end
62
64
  end
63
65
  end
64
66
  end
65
- end
66
67
 
67
- # Hook abstract base class
68
- class Hook
69
- attr_reader :cfg
68
+ # Hook abstract base class
69
+ class Hook
70
+ attr_reader :cfg
70
71
 
71
- def initialize
72
- end
72
+ def initialize; end
73
73
 
74
- def cfg=(cfg)
75
- @cfg = cfg
76
- validate_cfg! if self.respond_to? :validate_cfg!
77
- end
74
+ def cfg=(cfg)
75
+ @cfg = cfg
76
+ validate_cfg! if respond_to? :validate_cfg!
77
+ end
78
78
 
79
- def run_hook ctx
80
- raise NotImplementedError
81
- end
79
+ def run_hook(_ctx)
80
+ raise NotImplementedError
81
+ end
82
82
 
83
- def log(msg, level=:info)
84
- Oxidized.logger.send(level, "#{self.class.name}: #{msg}")
83
+ def log(msg, level = :info)
84
+ Oxidized.logger.send(level, "#{self.class.name}: #{msg}")
85
+ end
85
86
  end
86
-
87
- end
88
87
  end
@@ -32,26 +32,36 @@ module Oxidized
32
32
  @pre_logout.each { |command, block| block ? block.call : (cmd command, nil) }
33
33
  end
34
34
 
35
- def post_login _post_login=nil, &block
36
- unless @exec
37
- @post_login << [_post_login, block]
38
- end
35
+ def post_login(cmd = nil, &block)
36
+ return if @exec
37
+
38
+ @post_login << [cmd, block]
39
39
  end
40
40
 
41
- def pre_logout _pre_logout=nil, &block
42
- unless @exec
43
- @pre_logout << [_pre_logout, block]
44
- end
41
+ def pre_logout(cmd = nil, &block)
42
+ return if @exec
43
+
44
+ @pre_logout << [cmd, block]
45
45
  end
46
46
 
47
- def username re=/^(Username|login)/
48
- @username or @username = re
47
+ def username(regex = /^(Username|login)/)
48
+ @username || (@username = regex)
49
49
  end
50
50
 
51
- def password re=/^Password/
52
- @password or @password = re
51
+ def password(regex = /^Password/)
52
+ @password || (@password = regex)
53
53
  end
54
54
 
55
+ def login
56
+ match_re = [@node.prompt]
57
+ match_re << @username if @username
58
+ match_re << @password if @password
59
+ until (match = expect(match_re)) == @node.prompt
60
+ cmd(@node.auth[:username], nil) if match == @username
61
+ cmd(@node.auth[:password], nil) if match == @password
62
+ match_re.delete match
63
+ end
64
+ end
55
65
  end
56
66
  end
57
67
  end
@@ -0,0 +1,28 @@
1
+ module Oxidized
2
+ require "oxidized/input/cli"
3
+
4
+ class Exec < Input
5
+ include Input::CLI
6
+
7
+ def connect(node)
8
+ @node = node
9
+ @node.model.cfg["exec"].each { |cb| instance_exec(&cb) }
10
+ @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-exec", "w") if Oxidized.config.input.debug?
11
+ end
12
+
13
+ def cmd(cmd_str)
14
+ Oxidized.logger.debug "EXEC: #{cmd_str} @ #{@node.name}"
15
+ # I'd really like to do popen3 with separate arguments, but that would
16
+ # require refactoring cmd to take parameters
17
+ %x(#{cmd_str})
18
+ end
19
+
20
+ private
21
+
22
+ def disconnect
23
+ true
24
+ ensure
25
+ @log.close if Oxidized.config.input.debug?
26
+ end
27
+ end
28
+ end
@@ -5,35 +5,37 @@ module Oxidized
5
5
 
6
6
  class FTP < Input
7
7
  RescueFail = {
8
- :debug => [
9
- #Net::SSH::Disconnect,
8
+ debug: [
9
+ # Net::SSH::Disconnect,
10
10
  ],
11
- :warn => [
12
- #RuntimeError,
13
- #Net::SSH::AuthenticationFailed,
14
- ],
15
- }
11
+ warn: [
12
+ # RuntimeError,
13
+ # Net::SSH::AuthenticationFailed,
14
+ ]
15
+ }.freeze
16
16
  include Input::CLI
17
17
 
18
- def connect node
19
- @node = node
18
+ def connect(node)
19
+ @node = node
20
20
  @node.model.cfg['ftp'].each { |cb| instance_exec(&cb) }
21
21
  @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ftp", 'w') if Oxidized.config.input.debug?
22
- @ftp = Net::FTP.new @node.ip, @node.auth[:username], @node.auth[:password]
22
+ @ftp = Net::FTP.new(@node.ip)
23
+ @ftp.passive = Oxidized.config.input.ftp.passive
24
+ @ftp.login @node.auth[:username], @node.auth[:password]
23
25
  connected?
24
26
  end
25
27
 
26
28
  def connected?
27
- @ftp and not @ftp.closed?
29
+ @ftp && (not @ftp.closed?)
28
30
  end
29
31
 
30
- def cmd file
32
+ def cmd(file)
31
33
  Oxidized.logger.debug "FTP: #{file} @ #{@node.name}"
32
34
  @ftp.getbinaryfile file, nil
33
35
  end
34
36
 
35
37
  # meh not sure if this is the best way, but perhaps better than not implementing send
36
- def send my_proc
38
+ def send(my_proc)
37
39
  my_proc.call
38
40
  end
39
41
 
@@ -45,10 +47,9 @@ module Oxidized
45
47
 
46
48
  def disconnect
47
49
  @ftp.close
48
- #rescue Errno::ECONNRESET, IOError
50
+ # rescue Errno::ECONNRESET, IOError
49
51
  ensure
50
52
  @log.close if Oxidized.config.input.debug?
51
53
  end
52
-
53
54
  end
54
55
  end
@@ -0,0 +1,72 @@
1
+ module Oxidized
2
+ require "oxidized/input/cli"
3
+ require "net/http"
4
+ require "json"
5
+
6
+ class HTTP < Input
7
+ include Input::CLI
8
+
9
+ def connect(node)
10
+ @node = node
11
+ @secure = false
12
+ @username = nil
13
+ @password = nil
14
+ @headers = {}
15
+ @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-http", "w") if Oxidized.config.input.debug?
16
+ @node.model.cfg["http"].each { |cb| instance_exec(&cb) }
17
+
18
+ return true unless @main_page && defined?(login)
19
+
20
+ begin
21
+ require "mechanize"
22
+ rescue LoadError
23
+ raise OxidizedError, "mechanize not found: sudo gem install mechanize"
24
+ end
25
+
26
+ @m = Mechanize.new
27
+ url = URI::HTTP.build host: @node.ip, path: @main_page
28
+ @m_page = @m.get(url.to_s)
29
+ login
30
+ end
31
+
32
+ def cmd(callback_or_string)
33
+ return cmd_cb callback_or_string if callback_or_string.is_a?(Proc)
34
+
35
+ cmd_str callback_or_string
36
+ end
37
+
38
+ def cmd_cb(callback)
39
+ instance_exec(&callback)
40
+ end
41
+
42
+ def cmd_str(string)
43
+ path = string % { password: @node.auth[:password] }
44
+ get_http path
45
+ end
46
+
47
+ private
48
+
49
+ def get_http(path)
50
+ schema = @secure ? "https://" : "http://"
51
+ uri = URI("#{schema}#{@node.ip}#{path}")
52
+ req = Net::HTTP::Get.new(uri)
53
+ req.basic_auth @username, @password unless @username.nil?
54
+ @headers.each do |header, value|
55
+ req.add_field(header, value)
56
+ end
57
+ ssl_verify = Oxidized.config.input.http.ssl_verify? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
58
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", verify_mode: ssl_verify) do |http|
59
+ http.request(req)
60
+ end
61
+ res.body
62
+ end
63
+
64
+ def log(str)
65
+ @log&.write(str)
66
+ end
67
+
68
+ def disconnect
69
+ @log.close if Oxidized.config.input.debug?
70
+ end
71
+ end
72
+ end
@@ -4,10 +4,10 @@ module Oxidized
4
4
  include Oxidized::Config::Vars
5
5
 
6
6
  RescueFail = {
7
- :debug => [
8
- Errno::ECONNREFUSED,
7
+ debug: [
8
+ Errno::ECONNREFUSED
9
9
  ],
10
- :warn => [
10
+ warn: [
11
11
  IOError,
12
12
  PromptUndetect,
13
13
  Timeout::Error,
@@ -15,8 +15,8 @@ module Oxidized
15
15
  Errno::EHOSTUNREACH,
16
16
  Errno::ENETUNREACH,
17
17
  Errno::EPIPE,
18
- Errno::ETIMEDOUT,
19
- ],
20
- }
18
+ Errno::ETIMEDOUT
19
+ ]
20
+ }.freeze
21
21
  end
22
22
  end