-
Notifications
You must be signed in to change notification settings - Fork 0
/
poolboy.rb
151 lines (126 loc) · 3.71 KB
/
poolboy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
require 'trollop'
require 'yaml'
require 'openssl'
require 'net/smtp'
require 'pry'
class Options
attr_reader :options
def initialize()
@options = config_options
@options.merge! arg_options do |key, oldval, newval|
oldval unless oldval.nil?
end
end
def arg_options
opts = Trollop::options do
opt :email, "Email address", :type => :string
opt :email_password, "Email password", :type => :string
opt :email_server, "Email server", :type => :string
opt :send_email, "Include to send email with status"
opt :pools, "Pools to run against", :type => :strings
end
end
def config_options
config_file = File.join(ENV['HOME'], '.zpool_status.yaml')
option_set = { }
if File.exists? config_file
option_set = YAML.load_file(config_file)
end
option_set.each_with_object({}) do |(key, value), hash|
hash[key.to_sym] = value
end
end
end
class Pool_Email
def initialize(options)
@options = options
@smtp = Net::SMTP.new('smtp.gmail.com', 465)
@smtp.enable_tls
end
def send_email(message)
return unless use_email?
begin
@smtp.start(@options[:email_server], @options[:email], @options[:email_password], :plain) do |s|
s.send_message message,
@options[:email],
@options[:email]
end
rescue Exception => error
print_error("An error occurred sending an email: " + error.to_s)
end
end
def use_email?
should_send = @options.has_key?(:send_email) && @options[:send_email]
has_settings = [:email, :email_password, :email_server].all? { |option| !(@options[option].nil? || @options[option].empty?) }
$stderr.puts("send_email option must be included if you wish to send email") if !should_send && has_settings
$stderr.puts("email, email_password, and email_server must be set if you wish to send email") if should_send && !has_settings
should_send && has_settings
end
def print_error(error)
$stderr.puts error
end
end
class Poolboy
def initialize
@options = Options.new.options
@email = Pool_Email.new(@options)
end
def clean
if(@options[:pools].nil? || @options[:pools].empty?)
print_error "Pools need to be defined by --pools or :pools in .zpool_status.yaml"
return
end
remove_invalid_pools
@options[:pools].each do |pool|
start_scrub(pool)
wait_time = pool_wait_time(pool)
while(wait_time.to_i > 0)
sleep_time = wait_time <= 300 ? wait_time : 300
sleep(sleep_time)
wait_time = pool_wait_time pool
end
puts pool_status pool
end
send_email_for_pools
end
private
def pool_exists(pool_name)
status = `zpool status -v #{pool_name} 2>&1`
!status.include?("no such pool")
end
def start_scrub(pool_name)
`zpool scrub #{pool_name}`
end
def pool_status(pool_name)
`zpool status -v #{pool_name}`
end
def remove_invalid_pools
@options[:pools].delete_if do |pool_name|
nonexistant = !pool_exists(pool_name)
print_error("#{pool_name} does not exist")
nonexistant
end
end
def wait_time(status)
full, day, hour, min = *status.match(/(\d*d)?(\d*h)?(\d*m)? to go/)
totalSec = day.to_i * (24 * 60 * 60) +
hour.to_i * (60 * 60) +
min.to_i * 60
end
def pool_wait_time(pool_name)
wait_time pool_status(pool_name)
end
def send_email_for_pools
status = "From: #{@options[:email]}\n" +
"Subject: ZFS Pool status for pools: #{@options[:pools].join(", ")}\n\n"
@options[:pools].each do |pool|
status += pool_status(pool) + "\n"
end
@email.send_email(status)
end
def print_error(error)
$stderr.puts(error)
end
end
poolboy = Poolboy.new
poolboy.clean