nagios-dashboard 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +3 -0
  3. data/README.org +37 -0
  4. data/Rakefile +2 -0
  5. data/bin/nagios-dashboard +9 -0
  6. data/lib/nagios-dashboard/app.rb +164 -0
  7. data/lib/nagios-dashboard/static/css/style.css +103 -0
  8. data/lib/nagios-dashboard/static/fancybox/blank.gif +0 -0
  9. data/lib/nagios-dashboard/static/fancybox/fancy_close.png +0 -0
  10. data/lib/nagios-dashboard/static/fancybox/fancy_loading.png +0 -0
  11. data/lib/nagios-dashboard/static/fancybox/fancy_nav_left.png +0 -0
  12. data/lib/nagios-dashboard/static/fancybox/fancy_nav_right.png +0 -0
  13. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_e.png +0 -0
  14. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_n.png +0 -0
  15. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_ne.png +0 -0
  16. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_nw.png +0 -0
  17. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_s.png +0 -0
  18. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_se.png +0 -0
  19. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_sw.png +0 -0
  20. data/lib/nagios-dashboard/static/fancybox/fancy_shadow_w.png +0 -0
  21. data/lib/nagios-dashboard/static/fancybox/fancy_title_left.png +0 -0
  22. data/lib/nagios-dashboard/static/fancybox/fancy_title_main.png +0 -0
  23. data/lib/nagios-dashboard/static/fancybox/fancy_title_over.png +0 -0
  24. data/lib/nagios-dashboard/static/fancybox/fancy_title_right.png +0 -0
  25. data/lib/nagios-dashboard/static/fancybox/fancybox-x.png +0 -0
  26. data/lib/nagios-dashboard/static/fancybox/fancybox-y.png +0 -0
  27. data/lib/nagios-dashboard/static/fancybox/fancybox.png +0 -0
  28. data/lib/nagios-dashboard/static/fancybox/jquery.easing-1.3.pack.js +72 -0
  29. data/lib/nagios-dashboard/static/fancybox/jquery.fancybox-1.3.4.css +359 -0
  30. data/lib/nagios-dashboard/static/fancybox/jquery.fancybox-1.3.4.js +1156 -0
  31. data/lib/nagios-dashboard/static/fancybox/jquery.fancybox-1.3.4.pack.js +46 -0
  32. data/lib/nagios-dashboard/static/fancybox/jquery.mousewheel-3.0.4.pack.js +14 -0
  33. data/lib/nagios-dashboard/static/favicon.ico +0 -0
  34. data/lib/nagios-dashboard/static/img/bg.jpg +0 -0
  35. data/lib/nagios-dashboard/static/js/FABridge.js +604 -0
  36. data/lib/nagios-dashboard/static/js/WebSocketMain.swf +0 -0
  37. data/lib/nagios-dashboard/static/js/nagios-dashboard.js +59 -0
  38. data/lib/nagios-dashboard/static/js/swfobject.js +4 -0
  39. data/lib/nagios-dashboard/static/js/web_socket.js +312 -0
  40. data/lib/nagios-dashboard/version.rb +5 -0
  41. data/lib/nagios-dashboard/views/dashboard.haml +24 -0
  42. data/nagios-dashboard.gemspec +35 -0
  43. metadata +229 -0
@@ -0,0 +1,8 @@
1
+ \#*
2
+ *~
3
+ *.gem
4
+ *.log
5
+ .DS_Store
6
+ .bundle
7
+ Gemfile.lock
8
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+ # specify gem dependencies in nagios-dashboard.gemspec
3
+ gemspec
@@ -0,0 +1,37 @@
1
+ #+TITLE: A Nagios dashboard with OpsCode Chef integration.
2
+ #+Options: num:nil
3
+ #+STARTUP: odd
4
+ #+Style: <style> h1,h2,h3 {font-family: arial, helvetica, sans-serif} </style>
5
+
6
+ * How It Works
7
+ Nagios-Dashboard parses the nagios status.dat file & sends the current status to clients via an HTML5 WebSocket.
8
+
9
+ The dashboard monitors the status.dat file for changes, any modifications trigger a client update (push).
10
+
11
+ Nagios-Dashboard queries a Chef server or Opscode platform organization for additional host information.
12
+
13
+ * Requirements
14
+ - A Linux distribution running Nagios http://www.nagios.org/
15
+ - An OpsCode Chef server or platform oranization http://opscode.com/chef/ http://opscode.com/platform/
16
+ - Credentials to query Chef, user & private key http://wiki.opscode.com/display/chef/Authentication
17
+ - Ruby MRI 1.8 or 1.9 & RubyGems http://www.ruby-lang.org/en/
18
+ - Bundler http://gembundler.com/
19
+
20
+ * Install
21
+ : cd opt
22
+ : wget --no-check-certificate https://github.com/downloads/portertech/nagios-dashboard/nagios-dashboard.tar.gz
23
+ : tar -xvf nagios-dashboard.tar
24
+ : cd nagios-dashboard && bundle install
25
+
26
+ * Run
27
+ : -> % ./dashboard -h
28
+ : Usage: ./dashboard.rb (options)
29
+ : -c, --chef SERVER Use a Chef SERVER
30
+ : -d, --datfile FILE Location of Nagios status.dat FILE
31
+ : -k, --key KEY Chef user KEY
32
+ : -l, --logfile FILE Log to a different FILE
33
+ : -o, --organization ORGANIZATION Use a OpsCode platform ORGANIZATION
34
+ : -p, --port PORT Listen on a different PORT
35
+ : -u, --user USER Chef USER name
36
+ : -v, --verbose Output debug messages to screen
37
+ : -h, --help Show this message
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require 'nagios-dashboard/app.rb'
4
+ rescue LoadError => e
5
+ require 'rubygems'
6
+ path = File.expand_path '../../lib', __FILE__
7
+ $:.unshift(path) if File.directory?(path) && !$:.include?(path)
8
+ require 'nagios-dashboard/app.rb'
9
+ end
@@ -0,0 +1,164 @@
1
+ %w{
2
+ mixlib/cli
3
+ mixlib/log
4
+ json
5
+ thin
6
+ eventmachine
7
+ em-websocket
8
+ directory_watcher
9
+ nagios_analyzer
10
+ sinatra/async
11
+ haml
12
+ spice
13
+ }.each do |gem|
14
+ require gem
15
+ end
16
+
17
+ class Options
18
+ include Mixlib::CLI
19
+ option :verbose,
20
+ :short => '-v',
21
+ :long => '--verbose',
22
+ :boolean => true,
23
+ :default => false,
24
+ :description => 'Output debug messages to screen'
25
+
26
+ option :datfile,
27
+ :short => '-d FILE',
28
+ :long => '--datfile FILE',
29
+ :default => '/var/cache/nagios3/status.dat',
30
+ :description => 'Location of Nagios status.dat FILE'
31
+
32
+ option :port,
33
+ :short => '-p PORT',
34
+ :long => '--port PORT',
35
+ :default => 80,
36
+ :description => 'Listen on a different PORT'
37
+
38
+ option :logfile,
39
+ :short => '-l FILE',
40
+ :long => '--logfile FILE',
41
+ :default => '/tmp/nagios-dashboard.log',
42
+ :description => 'Log to a different FILE'
43
+
44
+ option :chef,
45
+ :short => '-c SERVER',
46
+ :long => '--chef SERVER',
47
+ :description => 'Use a Chef SERVER'
48
+
49
+ option :user,
50
+ :short => '-u USER',
51
+ :long => '--user USER',
52
+ :description => 'Chef USER name'
53
+
54
+ option :key,
55
+ :short => '-k KEY',
56
+ :long => '--key KEY',
57
+ :default => '/etc/chef/client.pem',
58
+ :description => 'Chef user KEY'
59
+
60
+ option :organization,
61
+ :short => '-o ORGANIZATION',
62
+ :long => '--organization ORGANIZATION',
63
+ :description => 'Use a OpsCode platform ORGANIZATION'
64
+
65
+ option :help,
66
+ :short => "-h",
67
+ :long => "--help",
68
+ :description => "Show this message",
69
+ :on => :tail,
70
+ :boolean => true,
71
+ :show_options => true,
72
+ :exit => 0
73
+ end
74
+
75
+ class Log
76
+ extend Mixlib::Log
77
+ end
78
+
79
+ OPTIONS = Options.new
80
+ OPTIONS.parse_options
81
+
82
+ Log.init(OPTIONS.config[:logfile])
83
+ Log.debug('starting dashboard ...')
84
+
85
+ EventMachine.epoll if EventMachine.epoll?
86
+ EventMachine.kqueue if EventMachine.kqueue?
87
+ EventMachine.run do
88
+ class Dashboard < Sinatra::Base
89
+ register Sinatra::Async
90
+ set :root, File.dirname(__FILE__)
91
+ set :static, true
92
+ set :public, Proc.new { File.join(root, "static") }
93
+
94
+ Spice.setup do |s|
95
+ s.host = OPTIONS.config[:chef] || "api.opscode.com"
96
+ s.port = 443
97
+ s.scheme = "https"
98
+ s.url_path = '/organizations/' + OPTIONS.config[:organization] if OPTIONS.config[:chef].nil?
99
+ s.client_name = OPTIONS.config[:user]
100
+ s.key_file = OPTIONS.config[:key]
101
+ end
102
+ Spice.connect!
103
+
104
+ aget '/' do
105
+ EventMachine.defer(proc { haml :dashboard }, proc { |result| body result })
106
+ end
107
+
108
+ aget '/node/:hostname' do |hostname|
109
+ content_type 'application/json'
110
+ EventMachine.defer(proc { JSON.parse(Spice::Search.node('hostname:' + hostname))['rows'][0] }, proc { |result| body result.to_json })
111
+ end
112
+ end
113
+
114
+ def log_message(message)
115
+ if OPTIONS.config[:verbose]
116
+ puts message
117
+ end
118
+ EventMachine.defer(proc { Log.debug(message) })
119
+ end
120
+
121
+ websocket_connections = Array.new
122
+ EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 9000) do |websocket|
123
+ websocket.onopen do
124
+ websocket_connections.push websocket
125
+ log_message('client connected to websocket')
126
+ end
127
+ websocket.onclose do
128
+ websocket_connections.delete websocket
129
+ log_message('client disconnected from websocket')
130
+ end
131
+ end
132
+
133
+ nagios_status = proc do
134
+ begin
135
+ nagios = NagiosAnalyzer::Status.new(OPTIONS.config[:datfile])
136
+ nagios.items.to_json
137
+ rescue => error
138
+ log_message(error)
139
+ end
140
+ end
141
+
142
+ update_clients = proc do |nagios|
143
+ unless nagios.nil?
144
+ websocket_connections.each do |websocket|
145
+ websocket.send nagios
146
+ end
147
+ log_message('updated clients')
148
+ end
149
+ end
150
+
151
+ watcher = DirectoryWatcher.new File.dirname(File.expand_path(OPTIONS.config[:datfile])), :glob => '*.dat', :scanner => :em
152
+ watcher.add_observer do |*args|
153
+ args.each do |event|
154
+ unless websocket_connections.count == 0
155
+ EventMachine.defer(nagios_status, update_clients)
156
+ end
157
+ end
158
+ end
159
+ watcher.start
160
+
161
+ Dashboard.run!({:port => OPTIONS.config[:port]})
162
+ end
163
+
164
+ Log.debug('stopping dashboard ...')
@@ -0,0 +1,103 @@
1
+ body
2
+ {
3
+ background-color: #333;
4
+ background-image: url("/img/bg.jpg");
5
+ font-family: Helvetica;
6
+ margin: 0;
7
+ padding: 20px;
8
+ }
9
+
10
+ div#MainContainer
11
+ {
12
+ background-color: rgba(30, 30, 30, 0.7);
13
+ -webkit-border-radius: 6px;
14
+ -moz-border-radius: 6px;
15
+ border-radius: 6px;
16
+ }
17
+
18
+ div#MainContainer h1
19
+ {
20
+ color: #fff;
21
+ padding-left: 14px;
22
+ padding-top: 14px;
23
+ }
24
+
25
+ div#MainContainer table
26
+ {
27
+ border-collapse: collapse;
28
+ width: 100%;
29
+ }
30
+
31
+ div#MainContainer table thead tr
32
+ {
33
+ background-color: #000;
34
+ }
35
+
36
+ div#MainContainer table thead tr th
37
+ {
38
+ padding: 7px 14px 7px 14px;
39
+ text-align: left;
40
+ }
41
+
42
+ div#MainContainer table thead tr th:first-child
43
+ {
44
+ -webkit-border-top-left-radius: 6px;
45
+ -moz-border-radius-topleft: 6px;
46
+ border-top-left-radius: 6px;
47
+ width: 200px;
48
+ }
49
+
50
+ div#MainContainer table thead tr th:last-child
51
+ {
52
+ -webkit-border-top-right-radius: 6px;
53
+ -moz-border-radius-topright: 6px;
54
+ border-top-right-radius: 6px;
55
+ }
56
+
57
+ div#MainContainer table thead tr th
58
+ {
59
+ color: #fff;
60
+ font-weight: bold;
61
+ font-family: Helvetica;
62
+ font-size: 16px;
63
+ }
64
+
65
+ div#MainContainer table tbody tr:last-child td:first-child
66
+ {
67
+ -webkit-border-bottom-left-radius: 6px;
68
+ -moz-border-radius-bottomleft: 6px;
69
+ border-bottom-left-radius: 6px;
70
+ }
71
+
72
+ div#MainContainer table tbody tr:last-child td:last-child
73
+ {
74
+ -webkit-border-bottom-right-radius: 6px;
75
+ -moz-border-radius-bottomright: 6px;
76
+ border-bottom-right-radius: 6px;
77
+ }
78
+
79
+ div#MainContainer table tbody tr
80
+ {
81
+ cursor: pointer;
82
+ }
83
+
84
+ div#MainContainer table tbody tr.Critical
85
+ {
86
+ background-color: rgba(144, 0, 0, 0.6);
87
+ /*background-color: #900;*/
88
+ color: #fff;
89
+ }
90
+
91
+ div#MainContainer table tbody tr.Warning
92
+ {
93
+ background-color: rgba(255, 165, 0, 0.6);
94
+ /*background-color: #ffa500;*/
95
+ color: #fff;
96
+ }
97
+
98
+ div#MainContainer table tbody tr td
99
+ {
100
+ padding: 14px 14px 14px 14px;
101
+ font-family: Helvetica;
102
+ font-size: 14px;
103
+ }
@@ -0,0 +1,72 @@
1
+ /*
2
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3
+ *
4
+ * Uses the built in easing capabilities added In jQuery 1.1
5
+ * to offer multiple easing options
6
+ *
7
+ * TERMS OF USE - jQuery Easing
8
+ *
9
+ * Open source under the BSD License.
10
+ *
11
+ * Copyright © 2008 George McGinley Smith
12
+ * All rights reserved.
13
+ *
14
+ * Redistribution and use in source and binary forms, with or without modification,
15
+ * are permitted provided that the following conditions are met:
16
+ *
17
+ * Redistributions of source code must retain the above copyright notice, this list of
18
+ * conditions and the following disclaimer.
19
+ * Redistributions in binary form must reproduce the above copyright notice, this list
20
+ * of conditions and the following disclaimer in the documentation and/or other materials
21
+ * provided with the distribution.
22
+ *
23
+ * Neither the name of the author nor the names of contributors may be used to endorse
24
+ * or promote products derived from this software without specific prior written permission.
25
+ *
26
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
27
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
31
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
35
+ *
36
+ */
37
+
38
+ // t: current time, b: begInnIng value, c: change In value, d: duration
39
+ eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))
40
+
41
+ /*
42
+ *
43
+ * TERMS OF USE - EASING EQUATIONS
44
+ *
45
+ * Open source under the BSD License.
46
+ *
47
+ * Copyright © 2001 Robert Penner
48
+ * All rights reserved.
49
+ *
50
+ * Redistribution and use in source and binary forms, with or without modification,
51
+ * are permitted provided that the following conditions are met:
52
+ *
53
+ * Redistributions of source code must retain the above copyright notice, this list of
54
+ * conditions and the following disclaimer.
55
+ * Redistributions in binary form must reproduce the above copyright notice, this list
56
+ * of conditions and the following disclaimer in the documentation and/or other materials
57
+ * provided with the distribution.
58
+ *
59
+ * Neither the name of the author nor the names of contributors may be used to endorse
60
+ * or promote products derived from this software without specific prior written permission.
61
+ *
62
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
63
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
64
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
65
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
66
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
67
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
68
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
69
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
70
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
71
+ *
72
+ */