carnac 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # Carnac - Hard Drive Failure Prediction Tool
2
+
3
+ ## Usage
4
+
5
+ ```
6
+ $> gem install carnac
7
+ $> carnac -d DEVICE
8
+ ```
9
+
10
+ ## License
11
+
12
+ (MIT License) - Copyright (c) 2012 Michael Pellon
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/carnac ADDED
@@ -0,0 +1,28 @@
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 'carnac'
7
+ require 'optparse'
8
+
9
+ ARGV << '--help' if ARGV.empty?
10
+
11
+ options = {}
12
+ OptionParser.new do |opts|
13
+ opts.banner = "Usage: carnac [options]"
14
+
15
+ opts.on("-d", "--device PATH", String, "The path to the device to be checked") do |v|
16
+ options[:device] = v
17
+ end
18
+
19
+ opts.on("-n", "--notify EMAIL", String, "The email address to send notifications to") do |v|
20
+ options[:notify] = v
21
+ end
22
+
23
+ opts.on("-x", "-- EMAIL", String, "") do |v|
24
+ options[:notify] = v
25
+ end
26
+ end.parse!
27
+
28
+ Carnac::Check.new(options).run!
data/carnac.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "carnac/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "carnac"
7
+ s.version = Carnac::VERSION
8
+ s.authors = ["Michael Pellon"]
9
+ s.email = ["michael@p3ll0n.net"]
10
+ s.homepage = "https://github.com/p3ll0n/carnac"
11
+ s.summary = "Implementation of simple hard drive failure prediction heuristic"
12
+ s.description = s.summary
13
+
14
+ s.rubyforge_project = "carnac"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
data/lib/carnac.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "carnac/version"
2
+ require "carnac/check"
@@ -0,0 +1,71 @@
1
+ require 'net/smtp'
2
+ require 'socket'
3
+
4
+ module Carnac
5
+
6
+ class Check
7
+ def initialize(options)
8
+ @device = options.delete(:device) || '/dev/sda'
9
+ @notify = options.delete(:notify) || ''
10
+ @flags = options.delete(:flags) || ''
11
+ @hostname = Socket.gethostname
12
+ end
13
+
14
+ def send_email(to,opts={})
15
+ opts[:server] ||= "localhost"
16
+ opts[:from] ||= "carnac@#{@hostname}"
17
+ opts[:subject] ||= "[#{@hostname}] - Hard Drive Failure Predicted!"
18
+ opts[:body] ||= ""
19
+
20
+ msg = <<END_OF_MESSAGE
21
+ From: #{opts[:from_alias]} <#{opts[:from]}>
22
+ To: <#{to}>
23
+ Subject: #{opts[:subject]}
24
+
25
+ #{opts[:body]}
26
+ END_OF_MESSAGE
27
+
28
+ Net::SMTP.start(opts[:server]) do |smtp|
29
+ smtp.send_message msg, opts[:from], to
30
+ end
31
+ end
32
+
33
+ def field_by_header(header_row, data_row, key)
34
+ pos = header_row.index key
35
+ data_row[pos..-1].split(' ').first
36
+ end
37
+
38
+ def run!
39
+ if @flags.empty?
40
+ lines = `smartctl -a #{@device}`.split("\n")
41
+ else
42
+ lines = `smartctl -a #{@flags} #{@device}`.split("\n")
43
+ end
44
+
45
+ header = lines.grep(/^ID#/).first
46
+ header_idx = lines.index header
47
+
48
+ data = {}
49
+ lines[header_idx+1..-1].each do |row|
50
+ break if row.empty?
51
+ key = field_by_header(header, row, 'ATTRIBUTE_NAME')
52
+ value = field_by_header(header, row, 'RAW_VALUE')
53
+ data[key] = value
54
+ end
55
+
56
+ if data.values_at(*%w(Reallocated_Sector_Ct Current_Pending_Sector)).any?
57
+ msg = "#{@device}: #{data['Airflow_Temperature_Cel']}°C, #{data['Reallocated_Sector_Ct']} sector reallocations"
58
+ if data['Current_Pending_Sector'] && Integer(data['Current_Pending_Sector']) > 0
59
+ msg << " (#{data['Current_Pending_Sector']} pending)"
60
+ end
61
+ if @notify.empty?
62
+ send_email "#{@notify}", :body => msg
63
+ else
64
+ puts msg
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,3 @@
1
+ module Carnac
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carnac
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Pellon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-27 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Implementation of simple hard drive failure prediction heuristic
15
+ email:
16
+ - michael@p3ll0n.net
17
+ executables:
18
+ - carnac
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - README.md
25
+ - Rakefile
26
+ - bin/carnac
27
+ - carnac.gemspec
28
+ - lib/carnac.rb
29
+ - lib/carnac/check.rb
30
+ - lib/carnac/version.rb
31
+ homepage: https://github.com/p3ll0n/carnac
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project: carnac
51
+ rubygems_version: 1.8.24
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Implementation of simple hard drive failure prediction heuristic
55
+ test_files: []
56
+ has_rdoc: