ubc-monitor 1.1.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.
@@ -0,0 +1,16 @@
1
+ 1.1.0 - 2008-11-07 Christian Johansen <christian@cjohansen.no>w
2
+ * Packaged project as gem
3
+ * Switched from Subversion to Git
4
+
5
+ 1.0.2 - 2008-04-25 Christian Johansen <christian@cjohansen.no>
6
+
7
+ * Added Changelog to project :)
8
+ * Added a boolean updated flag to Ubc::Report
9
+ * Changed check on failcounts to make sure failcounts higher than 0, but no higher than previous
10
+ failcount still gets written back to the log file
11
+
12
+ 1.0.1 - 2008-04-21 Christian Johansen <christian@cjohansen.no>
13
+
14
+ * Changed shebang to /usr/bin/env ruby
15
+ * Changed cat /proc/user_beancounters command (removed grep part which rendered it useless)
16
+ * Removed -t option for mail which didn't work under Debian
@@ -0,0 +1,16 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/ubc_monitor
7
+ lib/ubc_monitor.rb
8
+ lib/ubc_monitor/cli.rb
9
+ lib/ubc_monitor/monitor.rb
10
+ lib/ubc_monitor/report.rb
11
+ script/console
12
+ script/destroy
13
+ script/generate
14
+ test/test_helper.rb
15
+ test/test_ubc_monitor.rb
16
+ test/test_ubc_report.rb
@@ -0,0 +1,2 @@
1
+
2
+ For more information on ubc_monitor, see http://www.cjohansen.no/projects/ubc_monitor
@@ -0,0 +1,56 @@
1
+ = ubc_monitor
2
+
3
+ * http://www.cjohansen.no/projects/ubc_monitor
4
+
5
+ == DESCRIPTION:
6
+
7
+ ubc_monitor monitors resource usage in virtual servers run by
8
+ OpenVz.
9
+
10
+ Monitor /proc/user_beancounters and send an email to the systems
11
+ administrator if failcnt has increased since last time ubc_monitor
12
+ was run.
13
+
14
+ ubc_monitor uses a file (by default ~/.ubc_monitor) to keep track of
15
+ user_beancounter fail counts. When running without this file (such
16
+ as the first run) any fail count except 0 will be reported.
17
+
18
+ == SYNOPSIS:
19
+
20
+ ubc_monitor [options]
21
+
22
+ Options:
23
+
24
+ -f --file Log failcounts to this file, default is ~/.ubc_monitor
25
+ -n --no-log Don't log fail counts (only print results to STDOUT)
26
+ -t --email-recipient [EMAIL] The recipient of report emails. If this is not set, no email is sent
27
+ -s --email-subject [SUBJECT] Email subject. Default value is 'VPS has increased failcounts'
28
+
29
+ == INSTALL:
30
+
31
+ sudo gem install ubc_monitor
32
+
33
+ == LICENSE:
34
+
35
+ (The MIT License)
36
+
37
+ Copyright (c) 2008 Christian Johansen
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining
40
+ a copy of this software and associated documentation files (the
41
+ 'Software'), to deal in the Software without restriction, including
42
+ without limitation the rights to use, copy, modify, merge, publish,
43
+ distribute, sublicense, and/or sell copies of the Software, and to
44
+ permit persons to whom the Software is furnished to do so, subject to
45
+ the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be
48
+ included in all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
51
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
53
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
54
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
55
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
56
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/ubc_monitor'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('ubc-monitor', UbcMonitor::VERSION) do |p|
7
+ p.developer('Christian Johansen', 'christian@cjohansen.no')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = p.name # TODO this is default value
11
+ # p.extra_deps = [
12
+ # ['activesupport','>= 2.0.2'],
13
+ # ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Christian Johansen on 2008-11-3.
4
+ # Copyright (c) 2008. All rights reserved.
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/ubc_monitor")
7
+ require "ubc_monitor/cli"
8
+
9
+ Ubc::CLI.execute(ARGV)
@@ -0,0 +1,18 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'ubc_monitor/report'
5
+ require 'ubc_monitor/monitor'
6
+
7
+ #
8
+ # Monitor /proc/user_beancounters and send an email to the systems
9
+ # administrator if failcnt has increased since last time ubc_monitor
10
+ # was run.
11
+ #
12
+ # ubc_monitor uses a file (by default ~/.ubc_monitor) to keep track of
13
+ # user_beancounter fail counts. When running without this file (such
14
+ # as the first run) any fail count except 0 will be reported.
15
+ #
16
+ module UbcMonitor
17
+ VERSION = '1.1.0'
18
+ end
@@ -0,0 +1,46 @@
1
+ require 'optparse'
2
+
3
+ module UbcMonitor
4
+ #
5
+ # Run the monitor
6
+ #
7
+ class CLI
8
+ def self.execute(arguments=[])
9
+ options = { :file => File.expand_path('~/.ubc_monitor'),
10
+ :email_recipient => nil,
11
+ :email_subject => 'User beancounters has new errors' }
12
+
13
+ OptionParser.new do |opts|
14
+ opts.banner = <<-BANNER.gsub(/^ /,'')
15
+ Monitor /proc/user_beancounters and send an email to the systems
16
+ administrator if failcnt has increased since last time ubc_monitor
17
+ was run.
18
+
19
+ ubc_monitor uses a file (by default ~/.ubc_monitor) to keep track of
20
+ user_beancounter fail counts. When running without this file (such
21
+ as the first run) any fail count except 0 will be reported.
22
+
23
+ Usage: #{File.basename(__FILE__)} [options]
24
+ BANNER
25
+ opts.on("-f", "--file [FILE]", "Log failcounts to this file, default\n" +
26
+ " is #{options[:file]}") { |f| options[:file] = File.expand_path f }
27
+ opts.on("-n", "--no-log", "Don't log fail counts") { |r| options[:file] = nil }
28
+ opts.on("-t", "--email-recipient [EMAIL]", "The recipient of report emails.\n" +
29
+ " If this is not set, no email is sent") { |r| options[:email_recipient] = r }
30
+ opts.on("-s", "--email-subject [SUBJECT]", "Email subject. Default\n" +
31
+ " 'value is #{options[:email_subject]}'") { |s| options[:email_subject] = s }
32
+ end.parse!
33
+
34
+ monitor = UbcMonitor::Monitor.new(options)
35
+ report = monitor.run
36
+
37
+ if report.updated && !options[:email_recipient].nil?
38
+ `echo '"#{report.to_s}"' | mail -s "#{options[:email_subject]}" "#{options[:email_recipient]}"`
39
+ elsif report.updated
40
+ puts report.to_s
41
+ else
42
+ puts "All's swell!"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,77 @@
1
+ require 'net/smtp'
2
+ require 'ostruct'
3
+
4
+ # Namespace for the UbcMonitor script
5
+ module UbcMonitor
6
+
7
+ # The Monitor provides an interface for inspecting /proc/user_beancounters as well
8
+ # as a number of ways to report numbers that exceed given limits
9
+ class Monitor
10
+
11
+ def initialize(options = {})
12
+ @options = ({ :file => nil }).merge(options)
13
+ end
14
+
15
+ # Run the monitor. Uses a UbcMonitor::Report object to track runs so as to not
16
+ # report back errors that have already been reported
17
+ def run
18
+ filename = @options[:file]
19
+
20
+ # Fetch data from the previous run, this will be the baseline
21
+ report = filename.nil? ? Report.new : Report.load(filename)
22
+
23
+ # Update the report by scanning /proc/user_beancounters
24
+ report = scan(report)
25
+
26
+ # Log report back to file and return report
27
+ report.dump!(filename) unless filename.nil? || report.length == 0
28
+
29
+ report
30
+ end
31
+
32
+ # Generate the /proc/user_beancounters report by running cat on it.
33
+ # The method takes a UbcMonitor::Report object and returns a fresh report containing
34
+ # only VPS's that have increased failcounts
35
+ def scan(report = Report.new)
36
+ vps = nil
37
+ nrep = Report.new
38
+
39
+ proc_user_beancounters.split("\n").each do |line|
40
+ if line =~ /^\s+(\d+):/
41
+ vps = $1.to_sym
42
+ end
43
+
44
+ # If the VPS is set, and the line (that is, the failcount) does not end with
45
+ # a 0, set the resource/failcount pair
46
+ unless vps.nil? || line =~ /\s0$/
47
+ pieces = line.gsub(/^\s*(\d+:)?\s*/, '').split(/\s+/)
48
+ resource = pieces[0].to_sym
49
+
50
+ if report[vps, resource].nil? || report[vps, resource][:failcnt].nil? ||
51
+ pieces[5].to_i > report[vps, resource][:failcnt]
52
+ nrep[vps, resource] = { :held => pieces[1].to_i, :maxheld => pieces[2].to_i,
53
+ :barrier => pieces[3].to_i, :limit => pieces[4].to_i,
54
+ :failcnt => pieces[5].to_i }
55
+
56
+ # Mark report as updated if failcount has increased
57
+ nrep.updated = true if report[vps, resource].nil? || pieces[5].to_i > report[vps, resource][:failcnt]
58
+ end
59
+ end
60
+ end
61
+
62
+ nrep
63
+ end
64
+
65
+ private
66
+
67
+ # Reading /proc/user_beancounters itself is separated to allow for better testability
68
+ def proc_user_beancounters
69
+ unless File.readable? '/proc/user_beancounters'
70
+ puts "Unable to \'cat /proc/user_beancounters\'. Are you root?"
71
+ exit
72
+ end
73
+
74
+ `cat /proc/user_beancounters`
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,128 @@
1
+ # Namespace for the UbcMonitor script
2
+ module UbcMonitor
3
+
4
+ # The UbcMonitor::Report object holds information on the current state of failcounts in the
5
+ # /proc/user_beancounts table
6
+ #
7
+ # The Report is able to generate different views of the data it represents. It can use a
8
+ # file to log reports between uses in order to only report on failcounts that have increased
9
+ # since its last run.
10
+ #
11
+ # The log file contains sections for each VPS currently having failcounts. The VPS id introduces
12
+ # the section, followed by a newline and then resource: <failcount> pairs, one on each line.
13
+ # The VPS block is terminated by a double newline.
14
+ #
15
+ # Example file:
16
+ #
17
+ # 101
18
+ # privvmpages: 2
19
+ # kmemsize: 4
20
+ #
21
+ # 102
22
+ # privvmpages: 3
23
+ #
24
+ class Report
25
+ attr_accessor :updated
26
+
27
+ # Setup a new Report
28
+ def initialize
29
+ @resource_counts = {}
30
+ @updated = false
31
+ end
32
+
33
+ # Parse the ubc_monitor logfile and return a UbcMonitor::Report object
34
+ def self.load(file)
35
+ report = Report.new
36
+ vps = nil
37
+
38
+ return report if file.nil? || !File.exist?(file)
39
+
40
+ IO.read(file).each do |line|
41
+ if line =~ /^\s*$/
42
+ # This is a blank line separating VPS instances. Reset vps
43
+ vps = nil
44
+ elsif vps.nil?
45
+ # If the VPS has been reset, this line is expected to contain a new VPS id
46
+ vps = line.strip.to_sym
47
+ else
48
+ # Otherwise, this is a resource: <value> line belonging to the current VPS
49
+ resource, failcnt = line.split(':')
50
+ report[vps, resource.to_sym] = { :failcnt => failcnt.to_i }
51
+ end
52
+ end
53
+
54
+ return report
55
+ end
56
+
57
+ # Dump the report back to file
58
+ def dump!(file)
59
+ File.open(file, 'w+') do |f|
60
+ @resource_counts.each_pair do |vps, content|
61
+ # Each VPS in its own section, starting with the VPS id and followed by all the
62
+ # resources currently keeping a failcount, then terminated by a blank line.
63
+ # Resources whose failcounts are 0 are not dumped
64
+ str = ''
65
+ content.each_pair { |resource, numbers| str += "#{resource}: #{numbers[:failcnt]}\n" unless numbers[:failcnt] == 0 }
66
+ f.puts vps, str, '' unless str == ''
67
+ end
68
+ end
69
+ end
70
+
71
+ # Add a resource failcount. If resource and failcnt are nil, only allocate room for
72
+ # the VPS. Returns the VPS symbol
73
+ #
74
+ # +vps+ and +resource+ are both symbols while +limits+ should be a hash (unless
75
+ # +resource+ and +limits+ are both +nil+ in which case no resource/limits pair
76
+ # is actually appended). The hash can contain the following values:
77
+ # :held, :maxheld, :barrier, :limit, :failcnt
78
+ def []=(vps, resource, limits)
79
+ @resource_counts[vps] = {} if @resource_counts[vps].nil?
80
+ @resource_counts[vps][resource] = limits
81
+ vps
82
+ end
83
+
84
+ # Fetch the ubc numbers array for a given VPS
85
+ def [](vps, resource = nil)
86
+ has_vps = @resource_counts.key? vps
87
+ has_resource = has_vps && @resource_counts[vps].key?(resource)
88
+
89
+ return resource.nil? ?
90
+ (has_vps ? @resource_counts[vps] : nil) :
91
+ (has_resource ? @resource_counts[vps][resource] : nil)
92
+ end
93
+
94
+ # Returns true if no VPS's has any reported failcounts
95
+ def empty?
96
+ return length == 0
97
+ end
98
+
99
+ # Returns the number of VPSs in the report
100
+ def length
101
+ return @resource_counts.length
102
+ end
103
+
104
+ # Alias of +UbcMonitor::Monitor#length+
105
+ alias size length
106
+
107
+ # Return a nicely formatted report
108
+ def to_s
109
+ str = ''
110
+
111
+ @resource_counts.dup.each do |vps, content|
112
+ str += "VPS #{vps} has increased fail counts:\n"
113
+ str += "#{'resource'.rjust(20)}#{'held'.rjust(15)}#{'maxheld'.rjust(15)}" +
114
+ "#{'barrier'.rjust(15)}#{'limit'.rjust(15)}#{'failcount'.rjust(15)}\n"
115
+
116
+ content.each_pair do |resource, report|
117
+ str += resource.to_s.rjust(20)
118
+ [:held, :maxheld, :barrier, :limit, :failcnt].each { |sym| str += report[sym].to_s.rjust(15) }
119
+ str += "\n"
120
+ end
121
+
122
+ str += "\n"
123
+ end
124
+
125
+ str
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/ubc_monitor.rb'}"
9
+ puts "Loading ubc_monitor gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/ubc_monitor'
@@ -0,0 +1,117 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ # Mock cat /proc/user_beancounters
4
+ module UbcMonitor
5
+ class Monitor
6
+ def proc_user_beancounters
7
+ <<-EOF
8
+ Version: 2.5
9
+ uid resource held maxheld barrier limit failcnt
10
+ 101: kmemsize 1477444 2608200 8192000 9011200 3
11
+ lockedpages 0 0 2048 2048 4
12
+ numtcpsock 4 6 250 250 0
13
+ numflock 5 6 200 220 0
14
+ numpty 0 0 32 32 13
15
+ numsiginfo 0 2 256 256 0
16
+ tcpsndbuf 69504 90168 2682880 5242880 0
17
+ tcprcvbuf 65536 0 2682880 5242880 0
18
+ 102: kmemsize 5749546 6930244 18000000 48000000 0
19
+ lockedpages 0 0 2048 2048 0
20
+ tcprcvbuf 81920 0 2682880 5242880 0
21
+ othersockbuf 4592 11200 751616 20311616 0
22
+ dgramrcvbuf 0 8440 131072 131072 345
23
+ numothersock 3 10 250 250 0
24
+ dcachesize 0 0 2097152 2158592 0
25
+ 103: kmemsize 5749546 6930244 18000000 48000000 0
26
+ lockedpages 0 0 2048 2048 0
27
+ tcprcvbuf 81920 0 2682880 5242880 0
28
+ EOF
29
+ end
30
+ end
31
+ end
32
+
33
+ class TestUbcMonitor < Test::Unit::TestCase
34
+
35
+ def test_init_monitor
36
+ monitor = UbcMonitor::Monitor.new
37
+ assert_not_nil monitor
38
+ end
39
+
40
+ def test_monitor_scan
41
+ monitor = UbcMonitor::Monitor.new
42
+ report = monitor.scan
43
+
44
+ assert_equal 2, report.length
45
+ assert_equal 3, report[:'101'].length
46
+ assert_equal 1, report[:'102'].length
47
+
48
+ report[:'101', :kmemsize] = { :failcnt => 0 }
49
+ report[:'101', :numpty] = { :failcnt => 4 }
50
+ nrep = monitor.scan report
51
+
52
+ assert_equal 1, nrep.length
53
+ assert_equal 2, nrep[:'101'].length
54
+ assert_equal 13, nrep[:'101', :numpty][:failcnt]
55
+ assert_equal 3, nrep[:'101', :kmemsize][:failcnt]
56
+ end
57
+
58
+ def test_run
59
+ monitor = UbcMonitor::Monitor.new
60
+ report = monitor.run
61
+
62
+ assert_equal 2, report.length
63
+ assert_equal 3, report[:'101'].length
64
+ assert_equal 1, report[:'102'].length
65
+
66
+ filename = '.ubc_test_file'
67
+ monitor = UbcMonitor::Monitor.new :file => filename
68
+ report = monitor.run
69
+
70
+ assert_equal 2, report.length
71
+ assert_equal 3, report[:'101'].length
72
+ assert_equal 1, report[:'102'].length
73
+
74
+ contents = <<-EOF
75
+ 101
76
+ kmemsize: 3
77
+ lockedpages: 4
78
+ numpty: 13
79
+
80
+ 102
81
+ dgramrcvbuf: 345
82
+
83
+ EOF
84
+
85
+ assert_equal contents.split("\n").sort, IO.read(filename).split("\n").sort
86
+
87
+ # Again, this time the report should be empty, and the file unchanged
88
+ atime = File.new(filename).atime
89
+ monitor = UbcMonitor::Monitor.new :file => filename
90
+ report = monitor.run
91
+
92
+ assert_equal 0, report.length
93
+ assert_equal atime, File.new(filename).atime
94
+
95
+ File.delete filename
96
+ end
97
+
98
+ def test_to_s
99
+ monitor = UbcMonitor::Monitor.new
100
+ report = monitor.run
101
+
102
+ content = <<-EOF
103
+ VPS 101 has increased fail counts:
104
+ resource held maxheld barrier limit failcount
105
+ kmemsize 1477444 2608200 8192000 9011200 3
106
+ lockedpages 0 0 2048 2048 4
107
+ numpty 0 0 32 32 13
108
+
109
+ VPS 102 has increased fail counts:
110
+ resource held maxheld barrier limit failcount
111
+ dgramrcvbuf 0 8440 131072 131072 345
112
+
113
+ EOF
114
+
115
+ assert_equal content.split("\n").sort, report.to_s.split("\n").sort
116
+ end
117
+ end
@@ -0,0 +1,67 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestUbcReport < Test::Unit::TestCase
4
+
5
+ def test_init_report
6
+ report = UbcMonitor::Report.new
7
+ assert_not_nil report
8
+ assert report.empty?
9
+ end
10
+
11
+ def test_append
12
+ report = UbcMonitor::Report.new
13
+ assert report.empty?
14
+
15
+ assert :'196', report[:'196', :privvmpages] = { :failcnt => 4 }
16
+ assert !report.empty?
17
+ end
18
+
19
+ def test_getter
20
+ report = UbcMonitor::Report.new
21
+ numbers = { :failcnt => 4 }
22
+ vps = :'196'
23
+ report[vps, :privvmpages] = numbers
24
+ assert_equal numbers, report[:'196', :privvmpages]
25
+
26
+ # More complex hash
27
+ numbers = { :held => 1000, :maxheld => 1012, :barrier => 4000, :limit => 4050, :failcnt => 4 }
28
+ report[vps, :privvmpages] = numbers
29
+ assert_equal numbers, report[vps, :privvmpages]
30
+
31
+ assert !report.empty?
32
+ end
33
+
34
+ def test_load_dump
35
+ filename = '.ubc_test_file'
36
+ contents = <<-EOF
37
+ 196
38
+ privvmpages: 4
39
+
40
+ 197
41
+ kmemsize: 6
42
+ privvmpages: 5
43
+
44
+ EOF
45
+
46
+ File.open(filename, 'w') { |f| f.puts contents }
47
+
48
+ report = UbcMonitor::Report.load filename
49
+ assert_equal 1, report[:'196'].length, report[:'196'].inspect
50
+ assert_equal 1, report[:'196'][:privvmpages].length
51
+ assert_equal 2, report[:'197'].length
52
+
53
+ assert_equal 4, report[:'196'][:privvmpages][:failcnt]
54
+ assert_equal 5, report[:'197'][:privvmpages][:failcnt]
55
+ assert_equal 6, report[:'197'][:kmemsize][:failcnt]
56
+
57
+ assert_equal 2, report.length
58
+ assert_equal 2, report.size
59
+
60
+ report[:'197', :kmemsize] = { :held => 1000, :maxheld => 1050, :barrier => 4000, :limit => 4000, :failcnt => 8 }
61
+ assert_equal 8, report[:'197'][:kmemsize][:failcnt]
62
+
63
+ report.dump! filename
64
+ assert_equal "197\nprivvmpages: 5\nkmemsize: 8\n\n196\nprivvmpages: 4\n\n", IO.read(filename)
65
+ File.delete filename
66
+ end
67
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ubc-monitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christian Johansen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-09 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newgem
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.6
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.0
34
+ version:
35
+ description: ubc_monitor monitors resource usage in virtual servers run by OpenVz. Monitor /proc/user_beancounters and send an email to the systems administrator if failcnt has increased since last time ubc_monitor was run. ubc_monitor uses a file (by default ~/.ubc_monitor) to keep track of user_beancounter fail counts. When running without this file (such as the first run) any fail count except 0 will be reported.
36
+ email:
37
+ - christian@cjohansen.no
38
+ executables:
39
+ - ubc_monitor
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - History.txt
44
+ - Manifest.txt
45
+ - PostInstall.txt
46
+ - README.txt
47
+ files:
48
+ - History.txt
49
+ - Manifest.txt
50
+ - PostInstall.txt
51
+ - README.txt
52
+ - Rakefile
53
+ - bin/ubc_monitor
54
+ - lib/ubc_monitor.rb
55
+ - lib/ubc_monitor/cli.rb
56
+ - lib/ubc_monitor/monitor.rb
57
+ - lib/ubc_monitor/report.rb
58
+ - script/console
59
+ - script/destroy
60
+ - script/generate
61
+ - test/test_helper.rb
62
+ - test/test_ubc_monitor.rb
63
+ - test/test_ubc_report.rb
64
+ has_rdoc: true
65
+ homepage: http://www.cjohansen.no/projects/ubc_monitor
66
+ post_install_message: PostInstall.txt
67
+ rdoc_options:
68
+ - --main
69
+ - README.txt
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project: ubc-monitor
87
+ rubygems_version: 1.2.0
88
+ signing_key:
89
+ specification_version: 2
90
+ summary: ubc_monitor monitors resource usage in virtual servers run by OpenVz
91
+ test_files:
92
+ - test/test_helper.rb
93
+ - test/test_ubc_monitor.rb
94
+ - test/test_ubc_report.rb