dribbled 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright (c) 2012 by Evernote Corporation, All rights reserved.
3
+ *
4
+ * Use of the source code and binary libraries included in this package
5
+ * is permitted under the following terms:
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions
9
+ * are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
29
+ * not use this file except in compliance with the License. You may obtain a
30
+ * copy of the License at http://www.apache.org/licenses/LICENSE-2.0
31
+ */
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # OVERVIEW
2
+
3
+ *Dribbled* collects and displays information about [DRBD](http://www.drbd.org/home/what-is-drbd/ "DRBD") devices.
4
+
5
+ *Dribbled* is available as a Rubygem: [gem install dribbled](https://rubygems.org/gems/dribbled "Dribbled")
6
+
7
+ # SYNOPSIS
8
+
9
+ dribbled [options] <action> [options]
10
+
11
+ Options are as follows:
12
+
13
+ General options:
14
+ -D, --drbdadm DRBDADM Path to drbdadm binary
15
+ -P, --procdrbd PROCDRBD Path to /proc/drbd
16
+ -X, --xmldump XMLDUMP Path to output for drbdadm --dump-xml
17
+ -H, --hostname HOSTNAME Hostname
18
+ -d, --debug Enable debug mode
19
+ -a, --about Display dribbled information
20
+ -V, --version Display dribbled version
21
+ --help Show this messageSenedsa options
22
+
23
+ With no options or arguments, `dribbled` displays help (as shown above).
24
+
25
+ # PERSONALITIES
26
+
27
+ *Dribbled* has two personalities: when run as `dribbled`, it behaves according to the action and parameters used; when run as `check_drbd`, it assumes the `check` action, which enables Nagios plugin behavior.
28
+
29
+ gerir@boxie:~:dribbled show
30
+ 0 r0 Connected UpToDate/UpToDate Secondary/Primary sourcehost /dev/drbd0 desthost /dev/drbd0
31
+ 1 r1 Connected UpToDate/UpToDate Secondary/Primary sourcehost /dev/drbd1 desthost /dev/drbd1
32
+ 5 r5 Connected UpToDate/UpToDate Secondary/Primary sourcehost /dev/drbd5 desthost /dev/drbd5
33
+ 6 r6 SyncTarget [ 4%] Inconsistent/UpToDate Secondary/Primary sourcehost /dev/drbd6 desthost /dev/drbd6
34
+
35
+ gerir@boxie:~:dribbled check
36
+ warning: 6:cs:SyncTarget[4.6%%];ds:Inconsistent/UpToDate
37
+
38
+ gerir@boxie:~:dribbled check
39
+ warning: 6:cs:SyncTarget[4.6%%];ds:Inconsistent/UpToDate
40
+
41
+ Currently, there is no way to configure what constitutes alert conditions, but generally, a **critical** alert will be generated when a resource is found in non-`Connected` and non-`UpToDate` state, except when said resource is in `SyncSource`, `SyncTarget`, `VerifyS`, `VerifyT`, `PausedSyncS`, `PausedSyncT`, or `StandAlone` connection state, which causes a **warning**. Also, resources that are `Connected` and `UpToDate` but missing from the configuration will generate a **warning**.
42
+
data/bin/check_drbd ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require 'rubygems'
7
+ require 'dribbled'
8
+
9
+ module Dribbled
10
+
11
+ ID = File.basename($PROGRAM_NAME).to_sym
12
+
13
+ app = CLI.new(ARGV)
14
+ app.run
15
+
16
+ end
data/bin/dribbled ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require 'rubygems'
7
+ require 'dribbled'
8
+
9
+ module Dribbled
10
+
11
+ ID = File.basename($PROGRAM_NAME).to_sym
12
+
13
+ app = CLI.new(ARGV)
14
+ app.run
15
+
16
+ end
data/lib/dribbled.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'dribbled/version'
3
+ require 'dribbled/about'
4
+ require 'dribbled/logger'
5
+ require 'dribbled/drbd'
6
+ require 'dribbled/cli'
7
+
8
+ module Dribbled
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'dribbled/version'
2
+ module Dribbled
3
+ ME = :dribbled
4
+ ABOUT = "#{ME} v#{VERSION}\nhttps://github.com/evernote/ops-#{ME}\nCopyright (c) 2012 by Evernote Corporation\nLicensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)"
5
+ end
@@ -0,0 +1,244 @@
1
+ require 'optparse'
2
+ require 'syslog'
3
+ require 'io/wait'
4
+ require 'senedsa'
5
+ require 'socket'
6
+ require 'dribbled'
7
+
8
+ module Dribbled
9
+
10
+ class CLI
11
+
12
+ include Senedsa
13
+
14
+ COMMANDS = %w(show check snap)
15
+ COMPONENTS = %w(resources)
16
+ DEFAULT_CONFIG_FILE = File.join(ENV['HOME'],"/.senedsa/config")
17
+
18
+ def initialize(arguments)
19
+ @arguments = arguments
20
+ @whoami = File.basename($PROGRAM_NAME).to_sym
21
+
22
+ @global_options = { :debug => false, :drbdadm => 'drbdadm', :xmldump => nil, :procdrbd => '/proc/drbd', :hostname => nil }
23
+ @action_options = { :monitor => :nagios, :mode => :active, :suffix => nil, :directory => '/tmp' }
24
+ @action = nil
25
+ end
26
+
27
+ def run
28
+ begin
29
+ parsed_options?
30
+
31
+ @log = Dribbled::Logger.instance.log
32
+ @log.level = Log4r::INFO unless @global_options[:debug]
33
+ @global_options[:log] = @log
34
+
35
+ config_options?
36
+ arguments_valid?
37
+ options_valid?
38
+ process_options
39
+ process_arguments
40
+ process_command
41
+
42
+ rescue => e
43
+ if @global_options[:debug]
44
+ output_message "#{e.message}\n #{e.backtrace.join("\n ")}",3
45
+ else
46
+ output_message e.message,3
47
+ end
48
+ end
49
+ end
50
+
51
+ protected
52
+
53
+ def parsed_options?
54
+ opts = OptionParser.new
55
+
56
+ opts.banner = "Usage: #{ID} [options] <action> [options]"
57
+ opts.separator ""
58
+ opts.separator "Actions:"
59
+ opts.separator " show Displays component information"
60
+ opts.separator " check Performs health checks"
61
+ opts.separator " snap Saves contents of /proc/drbd and 'drbdadm dump-xml'"
62
+ opts.separator ""
63
+ opts.separator "General options:"
64
+ opts.on('-D', '--drbdadm DRBDADM', String, "Path to drbdadm binary") { |drbdadm| @global_options[:drbdadm] = drbdadm }
65
+ opts.on('-P', '--procdrbd PROCDRBD', String, "Path to /proc/drbd") { |procdrbd| @global_options[:procdrbd] = procdrbd }
66
+ opts.on('-X', '--xmldump XMLDUMP', String, "Path to output for drbdadm --dump-xml") { |xmldump| @global_options[:xmldump] = xmldump}
67
+ opts.on('-H', '--hostname HOSTNAME', String, "Hostname") { |hostname| @global_options[:hostname] = hostname }
68
+ opts.on('-d', '--debug', "Enable debug mode") { @global_options[:debug] = true}
69
+ opts.on('-a', '--about', "Display #{ID} information") { output_message ABOUT, 0 }
70
+ opts.on('-V', '--version', "Display #{ID} version") { output_message VERSION, 0 }
71
+ opts.on_tail('--help', "Show this message") { @global_options[:HELP] = true }
72
+
73
+ actions = {
74
+ :show => OptionParser.new do |aopts|
75
+ aopts.banner = "Usage: #{ID} [options] show <component>"
76
+ aopts.separator ""
77
+ aopts.separator " <component> is resources|res"
78
+ end,
79
+ :check => OptionParser.new do |aopts|
80
+ aopts.banner = "Usage: #{ID} [options] check [check_options]"
81
+ aopts.separator ""
82
+ aopts.separator "Check Options"
83
+ aopts.on('-M', '--monitor [nagios]', [:nagios], "Monitoring system") { |monitor| @action_options[:monitor] = monitor }
84
+ aopts.on('-m', '--mode [active|passive]', [:active, :passive], "Monitoring mode") { |mode| @action_options[:mode] = mode }
85
+ aopts.on('-H', '--nsca_hostname HOSTNAME', String, "NSCA hostname to send passive checks") { |nsca_hostname| @action_options[:nsca_hostname] = nsca_hostname }
86
+ aopts.on('-c', '--config CONFIG', String, "Path to Senedsa (send_nsca) configuration" ) { |config| @action_options[:senedsa_config] = config }
87
+ aopts.on('-S', '--svc_descr SVC_DESR', String, "Nagios service description") { |svc_descr| @action_options[:svc_descr] = svc_descr }
88
+ aopts.on('-h', '--hostname HOSTNAME', String, "Service hostname") { |hostname| @action_options[:svc_hostname] = hostname }
89
+ end,
90
+ :snap => OptionParser.new do |aopts|
91
+ aopts.banner = "Usage: #{ID} [options] snap [snap_options]"
92
+ aopts.separator ""
93
+ aopts.separator "Snap Options"
94
+ aopts.on('-S','--suffix SUFFIX', String, "Suffix (defaults to PID)") { |suffix| @action_options[:suffix] = suffix }
95
+ aopts.on('-D', '--directory DIRECTORY', String, "Directory (defaults to /tmp)") { |directory| @action_options[:directory] = directory }
96
+ end
97
+ }
98
+
99
+ opts.order!(@arguments)
100
+ output_message opts, 0 if (@arguments.size == 0 and @whoami != :check_drbd) or @global_options[:HELP]
101
+
102
+ @action = @whoami == :check_drbd ? :check : @arguments.shift.to_sym
103
+ raise OptionParser::InvalidArgument, "invalid action #@action" if actions[@action].nil?
104
+ actions[@action].order!(@arguments)
105
+ end
106
+
107
+ def config_options?
108
+ cfg_file = nil
109
+ cfg_file = @action_options[:senedsa_config] unless @action_options[:senedsa_config].nil?
110
+ cfg_file = DEFAULT_CONFIG_FILE if @action_options[:senedsa_config].nil? and File.readable? DEFAULT_CONFIG_FILE
111
+
112
+ unless cfg_file.nil?
113
+ @action_options.merge!(Senedsa::SendNsca.configure(cfg_file))
114
+ @action_options[:senedsa_config] = cfg_file
115
+ end
116
+ end
117
+
118
+ def arguments_valid?
119
+ true
120
+ end
121
+
122
+ def options_valid?
123
+
124
+ @global_options[:hostname] = Socket.gethostname if @global_options[:hostname].nil?
125
+
126
+ case @action
127
+ when :check
128
+ raise OptionParser::MissingArgument, "NSCA hostname (-H) must be specified" if @action_options[:nsca_hostname].nil? and @action_options[:mode] == 'passive'
129
+ raise OptionParser::MissingArgument, "service description (-S) must be specified" if @action_options[:svc_descr].nil? and @action_options[:mode] == 'passive'
130
+ end
131
+ end
132
+
133
+ def process_options
134
+ true
135
+ end
136
+
137
+ def process_arguments
138
+ true
139
+ end
140
+
141
+ def process_command
142
+
143
+ @drbdset = DrbdSet.new @global_options
144
+
145
+ case @action
146
+ when :show then run_show
147
+ when :check then run_check
148
+ when :snap then run_snap
149
+ end
150
+
151
+ end
152
+
153
+ def run_show
154
+ #raise ArgumentError, "missing component" if @arguments.size == 0
155
+ component = 'res'
156
+
157
+ case component
158
+ when 'resource', 'res'
159
+ @drbdset.each do |r,resource|
160
+ puts resource.to_s
161
+ end
162
+ when 'version'
163
+ puts @drbdset.version
164
+ end
165
+ end
166
+
167
+ def run_check
168
+
169
+ plugin_output = ""
170
+ plugin_status = ""
171
+
172
+ # check for configuration vs running resources
173
+
174
+ #unconfigured_resources = @drbdset.select { |k,v| v.cstate == "Unconfigured" }
175
+
176
+ # unless unconfigured_resources.empty?
177
+ # plugin_output = "DRBD unconfigured resources found: #{unconfigured_resources.keys.join(' ')}"
178
+ # plugin_status = :warning
179
+ # end
180
+
181
+ # check dstate, state and cstate for each resource
182
+ # + cstate should be: Connected
183
+ # + dstate should be: UpToDate/UpToDate
184
+
185
+ @drbdset.each do |r,res|
186
+ next if res.cstate == 'Unconfigured'
187
+
188
+ po_cstate = ""
189
+ po_dstate = ""
190
+
191
+ po_cstate = "cs:#{res.cstate}" unless res.cstate == "Connected" and res.in_kernel? and res.in_configuration?
192
+ po_dstate = "ds:#{res.dstate}" unless res.dstate == "UpToDate/UpToDate" and res.in_kernel? and res.in_configuration?
193
+
194
+ unless po_cstate.gsub('cs:','').empty? and po_dstate.gsub('ds:','').empty?
195
+ if ['SyncSource','SyncTarget','VerifyS','VerifyT','PausedSyncS','PausedSyncT','StandAlone'].include? res.cstate
196
+ plugin_status = :warning
197
+ plugin_output += res.percent.nil? ? " #{res.id}:#{po_cstate};#{po_dstate}" : " #{res.id}:#{po_cstate}[#{res.percent}%%];#{po_dstate}"
198
+ elsif not res.in_configuration?
199
+ plugin_status = :warning
200
+ plugin_output += " #{res.id}[unconfigured]>#{po_cstate}/;#{po_dstate}"
201
+ else
202
+ plugin_output += " #{res.id}>#{po_cstate};#{po_dstate}"
203
+ plugin_status = :critical
204
+ end
205
+ end
206
+ end
207
+
208
+ plugin_output = " all DRBD resources Connected, UpToDate/UpToDate" if plugin_output.empty? and plugin_status.empty?
209
+ plugin_status = :ok if plugin_status.empty?
210
+
211
+ case @action_options[:monitor]
212
+ when :nagios
213
+ case @action_options[:mode]
214
+ when :active
215
+ puts "#{plugin_status}:#{plugin_output}"
216
+ exit SendNsca::STATUS[plugin_status]
217
+ when :passive
218
+ sn = SendNsca.new @action_options
219
+ begin
220
+ sn.send plugin_status , plugin_output
221
+ rescue SendNsca::SendNscaError => e
222
+ output_message "send_nsca failed: #{e.message}", 1
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ def run_snap
229
+ @action_options[:suffix] = $$ if @action_options[:suffix].nil?
230
+ procdrbd_file = "#{@action_options[:directory]}/procdrbd.#{@action_options[:suffix]}"
231
+ xmldump_file = "#{@action_options[:directory]}/xmldump.#{@action_options[:suffix]}"
232
+ File.open(procdrbd_file, 'w') {|f| f.write(@drbdset.resources_run_raw) }
233
+ File.open(xmldump_file, 'w') {|f| f.write(@drbdset.resources_cfg_raw) }
234
+ end
235
+
236
+ def output_message(message, exitstatus=nil)
237
+ m = (! exitstatus.nil? and exitstatus > 0) ? "%s: error: %s" % [ID, message] : message
238
+ Syslog.open(ID.to_s, Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.err "error: #{message}" } unless @global_options[:debug]
239
+ $stderr.write "#{m}\n" if STDIN.tty?
240
+ exit exitstatus unless exitstatus.nil?
241
+ end
242
+
243
+ end
244
+ end
@@ -0,0 +1,186 @@
1
+ require 'xmlsimple'
2
+ require 'ostruct'
3
+ #require 'awesome_print'
4
+
5
+ module Dribbled
6
+
7
+ class DrbdSet < Hash
8
+
9
+ attr_reader :resources_cfg_raw, :resources_run_raw
10
+
11
+ PROCDRBD_VERSION_RE = /^version:\s+(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)\s+\(api:(?<api>\d+)\/proto:(?<proto>[0-9-]+)/
12
+ PROCDRBD_RESOURCE_RE = /^\s*(?<id>\d+):\s+cs:(?<cstate>[\w\/]+)\s+(st|ro):(?<state>[\w\/]+)\s+ds:(?<dstate>[\w\/]+)\s+/
13
+ PROCDRBD_URESOURCE_RE = /^\s*(?<id>\d+):\s+cs:(?<cstate>[\w\/]+)/
14
+ PROCDRBD_ACTIVITY_RE = /^\s+\[[.>=]+\]\s+(?<activity>[a-z']+):\s+(?<percent>[0-9.]+)%/
15
+
16
+ def initialize(options)
17
+ @log = options[:log].nil? ? nil : options[:log]
18
+ @hostname = options[:hostname]
19
+
20
+ resources_run_src = options[:procdrbd]
21
+ @resources_run_raw = nil
22
+ @resources_run = _read_procdrbd(resources_run_src) # sets @resources_run_raw as side-effect; it shouldn't
23
+ @resources_run.each do |r,res|
24
+ self[res.id] = res unless res.nil?
25
+ end
26
+
27
+ resources_cfg_src = options[:xmldump].nil? ? IO.popen("#{options[:drbdadm]} dump-xml 2>/dev/null") : options[:xmldump]
28
+ @resources_cfg_raw = nil
29
+ @resources_cfg = _read_xmldump(resources_cfg_src) # sets @resources_cfg_raw as side-effect; it shouldn't
30
+
31
+ @resources_cfg.each do |name,res|
32
+ _process_xml_resource(name,res)
33
+ end
34
+
35
+ end
36
+
37
+ def version
38
+ "#@version_major.#@version_minor.#@version_path"
39
+ end
40
+
41
+ protected
42
+
43
+ def _read_procdrbd(resources_run_src)
44
+ @log.debug "Running configuration source: #{resources_run_src}" unless @log.nil?
45
+ resources_run = {}
46
+ @resources_run_raw = File.open(resources_run_src,"r") { |f| f.read }
47
+ r = nil
48
+ @resources_run_raw.each_line do |line|
49
+ if /^\s*(\d+):/.match(line)
50
+ r = $1.to_i
51
+ resources_run[r] = DrbdResource.new r, @hostname
52
+ resources_run[r].in_kernel = true
53
+ if PROCDRBD_RESOURCE_RE.match(line)
54
+ m = PROCDRBD_RESOURCE_RE.match(line)
55
+ resources_run[r].cstate = m[:cstate]
56
+ resources_run[r].state = m[:state]
57
+ resources_run[r].dstate = m[:dstate]
58
+ elsif PROCDRBD_URESOURCE_RE.match(line)
59
+ resources_run[r].cstate = PROCDRBD_URESOURCE_RE.match(line)[:cstate]
60
+ end
61
+ @log.debug " #{resources_run[r].inspect}" unless @log.nil?
62
+ elsif PROCDRBD_ACTIVITY_RE.match(line)
63
+ m = PROCDRBD_ACTIVITY_RE.match(line)
64
+ resources_run[r].activity = m[:activity].gsub(/'/,"").to_sym
65
+ resources_run[r].percent = m[:percent].to_f
66
+ elsif PROCDRBD_VERSION_RE.match(line)
67
+ @version_major = $1
68
+ @version_minor = $2
69
+ @version_path = $3
70
+ end
71
+ end
72
+ resources_run
73
+ end
74
+
75
+ def _read_xmldump(resources_cfg_src)
76
+ @log.debug "Stable configuration source: #{resources_cfg_src}" unless @log.nil?
77
+ @resources_cfg_raw = resources_cfg_src.is_a?(String) ? File.open(resources_cfg_src,"r") { |f| f.read } : resources_cfg_src.read
78
+ XmlSimple.xml_in(@resources_cfg_raw, { 'KeyAttr' => 'name' })['resource']
79
+ end
80
+
81
+ def _process_xml_resource(name,res)
82
+ res['host'].each_key do |hostname|
83
+ @log.debug " resource xml processing: host #{hostname}"
84
+ if res['host'][hostname]['device'][0]['minor'].nil?
85
+ r = res['host'][hostname]['device'][0].split('drbd')[1].to_i
86
+ @log.debug " #{version}: #{res['host'][hostname]['device'][0]}; r = #{r}"
87
+ disk = res['host'][hostname]['disk'][0]
88
+ device = res['host'][hostname]['device'][0]
89
+ else
90
+ r = res['host'][hostname]['device'][0]['minor'].to_i
91
+ @log.debug " #{version}: #{res['host'][hostname]['device'][0]}; r = #{r}"
92
+ disk = res['host'][hostname]['disk'][0]
93
+ device = res['host'][hostname]['device'][0]['content']
94
+ end
95
+ if self[r].nil?
96
+ self[r] = DrbdResource.new r, @hostname
97
+ self[r].cstate = "StandAlone"
98
+ self[r].dstate = "DUnknown"
99
+ self[r].state = "Unknown"
100
+ end
101
+ self[r].name = name
102
+ self[r].in_configuration = true
103
+ @log.debug " resource: #{r}, state: #{self[r].state}"
104
+ if self[r].state == 'Primary/Secondary'
105
+ if hostname == @hostname
106
+ @log.debug " resource: #{r}, primary"
107
+ self[r].primary[:disk] = disk
108
+ self[r].primary[:device] = device
109
+ self[r].primary[:hostname] = hostname
110
+ else
111
+ @log.debug " resource: #{r}, secondary"
112
+ self[r].secondary[:disk] = disk
113
+ self[r].secondary[:device] = device
114
+ self[r].secondary[:hostname] = hostname
115
+ end
116
+ elsif self[r].state == 'Secondary/Primary' or self[r].state == 'Unknown'
117
+ if hostname == @hostname
118
+ @log.debug " resource: #{r}, secondary"
119
+ self[r].secondary[:disk] = disk
120
+ self[r].secondary[:device] = device
121
+ self[r].secondary[:hostname] = hostname
122
+ else
123
+ @log.debug " resource: #{r}, primary"
124
+ self[r].primary[:disk] = disk
125
+ self[r].primary[:device] = device
126
+ self[r].primary[:hostname] = hostname
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ class DrbdResource
134
+
135
+ attr_reader :id
136
+ attr_accessor :name, :cstate, :dstate, :state, :config, :primary, :secondary, :activity, :percent, :in_kernel, :in_configuration
137
+
138
+ def initialize(res,hostname)
139
+ @id = res
140
+ @name = nil
141
+ @config = nil
142
+ @dstate = nil
143
+ @cstate = nil
144
+ @state = nil
145
+ @activity = nil
146
+ @percent = nil
147
+ @primary = { :hostname => nil, :disk => nil, :device => nil }
148
+ @secondary = { :hostname => nil, :disk => nil, :device => nil }
149
+ @in_kernel = false
150
+ @in_configuration = false
151
+ end
152
+
153
+ def in_kernel?
154
+ @in_kernel
155
+ end
156
+
157
+ def in_configuration?
158
+ @in_configuration
159
+ end
160
+
161
+ def to_s
162
+ ph = @primary[:hostname].gsub(/\.[a-z0-9-]+\.[a-z0-9-]+$/,"") unless @primary[:hostname].nil?
163
+ sh = @secondary[:hostname].gsub(/\.[a-z0-9-]+\.[a-z0-9-]+$/,"") unless @secondary[:hostname].nil?
164
+
165
+ if @state == 'Primary/Secondary'
166
+ h1 = ph; dev1 = @primary[:device]
167
+ h2 = sh; dev2 = @secondary[:device]
168
+ else
169
+ h1 = sh; dev1 = @secondary[:device]
170
+ h2 = ph; dev2 = @primary[:device]
171
+ end
172
+
173
+ percent = @activity.nil? ? nil : "[%3d%%]" % @percent
174
+
175
+ "%2d %6s %-13s %6s %-22s %-20s %10s %-11s %10s %-11s" % [@id,@name,@cstate,percent,@dstate,@state,h1,dev1,h2,dev2]
176
+ end
177
+
178
+ def inspect
179
+ "#{self.class}: #@id[#@name]: #@cstate,#@dstate,#@state"
180
+ end
181
+
182
+ def check
183
+
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,18 @@
1
+ require 'singleton'
2
+ require 'log4r'
3
+
4
+ module Dribbled
5
+
6
+ class Logger
7
+
8
+ include Singleton
9
+
10
+ attr_reader :log
11
+
12
+ def initialize
13
+ @log = Log4r::Logger.new("dribbled")
14
+ @log.add Log4r::StderrOutputter.new('console', :formatter => Log4r::PatternFormatter.new(:pattern => "%c [%l] %m"), :level => Log4r::DEBUG)
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Dribbled
2
+ VERSION = "0.6.0"
3
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dribbled
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gerardo López-Fernádez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: xml-simple
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: log4r
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: senedsa
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.2.9
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.9
62
+ description: Provides a wrapper around DRBD to gather information and perform monitoring
63
+ checks
64
+ email: gerir@evernote.com
65
+ executables:
66
+ - dribbled
67
+ - check_drbd
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - lib/dribbled/about.rb
72
+ - lib/dribbled/cli.rb
73
+ - lib/dribbled/drbd.rb
74
+ - lib/dribbled/logger.rb
75
+ - lib/dribbled/version.rb
76
+ - lib/dribbled.rb
77
+ - bin/check_drbd
78
+ - bin/dribbled
79
+ - LICENSE
80
+ - README.md
81
+ homepage: https://github.com/evernote/ops-dribbled
82
+ licenses:
83
+ - Apache License, Version 2.0
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: 1.3.5
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 1.8.23
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: DRBD tool
106
+ test_files: []