ruby-ipmitool 0.1
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.
- data/lib/ruby-ipmitool.rb +190 -0
- metadata +66 -0
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'ping'
|
2
|
+
|
3
|
+
module Kernel
|
4
|
+
private
|
5
|
+
def this_method_name
|
6
|
+
caller[0] =~ /`([^']*)'/ && $1
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Hash
|
11
|
+
def method_missing(name, *args, &blk)
|
12
|
+
if self.keys.map(&:to_sym).include? name.to_sym
|
13
|
+
return self[name.to_sym]
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
=begin rdoc
|
22
|
+
This utility wraps the UNIX ipmitool command to provide common functions
|
23
|
+
|
24
|
+
All methods in this class return a hash, which can be read as accessors.
|
25
|
+
|
26
|
+
For more information on the output and its meanings, see the official ipmitool man page at http://ipmitool.sourceforge.net/manpage.html
|
27
|
+
=end
|
28
|
+
|
29
|
+
class Ipmitool
|
30
|
+
attr_reader :conn
|
31
|
+
|
32
|
+
#Instantiates a new Ipmitool object. Takes a hash containing :host, :user, and :password.
|
33
|
+
#
|
34
|
+
#Ex: Ipmitool.new(:host => '192.168.1.1', :user => 'username', :password => 'password')
|
35
|
+
def initialize(conn = {})
|
36
|
+
conn[:check_host] ||= true
|
37
|
+
raise ArgumentError, "Wrong number of arguments" if conn.count != 4
|
38
|
+
raise ArgumentError, "Host is required" if conn[:host].nil?
|
39
|
+
raise ArgumentError, "User is required" if conn[:user].nil?
|
40
|
+
raise ArgumentError, "Password is required" if conn[:password].nil?
|
41
|
+
@conn = conn
|
42
|
+
@conn[:binary] = `which ipmitool`.chomp
|
43
|
+
binary = system('which ipmitool > /dev/null')
|
44
|
+
raise ArgumentError, "Missing ipmitool" unless binary
|
45
|
+
if conn[:check_host]
|
46
|
+
raise ArgumentError, "Host is down or invalid!" unless check_host
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#Run a ping check to see if the host is responding
|
51
|
+
def check_host
|
52
|
+
return Ping.pingecho(@conn[:host], 2)
|
53
|
+
end
|
54
|
+
|
55
|
+
#Read sensor data from ipmitool and return a hash containing the value
|
56
|
+
#
|
57
|
+
#Returned format is {:sensor_name => ['value1', 'value2']}
|
58
|
+
#Ex. Ipmitool.new(:host => '192.168.1.1', :user => 'username', :password => 'password').sensor.fan1
|
59
|
+
def sensor
|
60
|
+
sensor_output = run_command(this_method_name).split("\n")
|
61
|
+
sensor_hash = split_output(sensor_output, '|')
|
62
|
+
return sensor_hash = sensor_hash.each { |k,v| sensor_hash[k.to_sym] = v.split(/\s\|\s/) }
|
63
|
+
end
|
64
|
+
|
65
|
+
#Same as sensor, but the output is a bit more formatted for everyday use
|
66
|
+
def sdr
|
67
|
+
sdr_output = run_command(this_method_name).split("\n")
|
68
|
+
sdr_hash = split_output(sdr_output, '|')
|
69
|
+
return sdr_hash = sdr_hash.each { |k,v| sdr_hash[k.to_sym] = v.split(/\s\|\s/) }
|
70
|
+
end
|
71
|
+
|
72
|
+
#Query and issue commands to the chassis itself. Useful for powering a box on and off, resets, etc
|
73
|
+
#
|
74
|
+
#Ex ipmi.chassis("power", "on").chassis_power_control
|
75
|
+
def chassis(chassis_command, *command_args)
|
76
|
+
chassis_hash = Hash.new
|
77
|
+
case chassis_command
|
78
|
+
when "status", "restart_cause", "poh", "selftest"
|
79
|
+
chassis_output = run_command(this_method_name, chassis_command)
|
80
|
+
chassis_output = chassis_output.split("\n")
|
81
|
+
chassis_hash = split_output(chassis_output, ':')
|
82
|
+
when "power"
|
83
|
+
raise ArgumentError, "#{chassis_command} requires an additional argument" if command_args.empty?
|
84
|
+
chassis_output = run_command(this_method_name, "#{chassis_command} #{command_args}")
|
85
|
+
chassis_hash = split_output(chassis_output.to_a, ":")
|
86
|
+
return chassis_hash
|
87
|
+
when "policy"
|
88
|
+
raise ArgumentError, "Policy requires a state" if command_args.empty?
|
89
|
+
if command_args.to_s == 'list'
|
90
|
+
chassis_output = run_command(this_method_name, "#{chassis_command} #{command_args}")
|
91
|
+
chassis_hash = split_output(chassis_output.split("\n"), ":")
|
92
|
+
else
|
93
|
+
chassis_hash[:result] = run_command(this_method_name, "#{chassis_command} #{command_args}").gsub("\n","")
|
94
|
+
return chassis_hash
|
95
|
+
end
|
96
|
+
when "bootdev"
|
97
|
+
raise ArgumentError, "bootdev requires an additional argument" if command_args.empty?
|
98
|
+
chassis_hash[:result] = run_command(this_method_name, "#{chassis_command} #{command_args}").gsub("\n","")
|
99
|
+
return chassis_hash
|
100
|
+
else
|
101
|
+
raise ArgumentError, "Invalid Chassis Command"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#Shortcut to ipmi.chassis("power"). Values returned are formatted exactly as ipmi.chassis.
|
106
|
+
#
|
107
|
+
#Ex. ipmi.power("on")
|
108
|
+
def power(power_command)
|
109
|
+
return chassis("power", power_command)
|
110
|
+
end
|
111
|
+
|
112
|
+
#Set channel options, including authentication. For options that require more than 1 option, that should be specified as separate options to the method.
|
113
|
+
#
|
114
|
+
#Ex. ipmi.channel("getciphers", "ipmi", "1").inspect
|
115
|
+
#
|
116
|
+
#The setaccess function gives no output
|
117
|
+
def channel(channel_command, *command_args)
|
118
|
+
channel_hash = Hash.new
|
119
|
+
case channel_command
|
120
|
+
when "authcap"
|
121
|
+
raise ArgumentError, "Authcap requires a channel number and privilege" if command_args.empty?
|
122
|
+
channel_output = run_command(this_method_name, "#{channel_command} #{command_args.join(' ')}")
|
123
|
+
return channel_hash = split_output(channel_output, ':')
|
124
|
+
when "getaccess"
|
125
|
+
raise ArgumentError, "Authcap requires a channel number and uid" if command_args.empty?
|
126
|
+
user_hash = user("list", command_args[0])
|
127
|
+
raise ArgumentError, "Invalid user specified" unless user_hash.has_key?("uid#{command_args[1]}".to_sym)
|
128
|
+
channel_output = run_command(this_method_name, "#{channel_command} #{command_args.join(' ')}")
|
129
|
+
channel_hash = split_output(channel_output, ':')
|
130
|
+
when "setaccess"
|
131
|
+
raise ArgumentError, "Authcap requires a channel number, uid, and privilege level" if command_args.empty?
|
132
|
+
user_hash = user("list", command_args[0])
|
133
|
+
raise ArgumentError, "Invalid user specified" unless user_hash.has_key?("uid#{command_args[1]}".to_sym)
|
134
|
+
command_args[2] = "privilege=#{command_args[2]}"
|
135
|
+
run_command(this_method_name, "#{channel_command} #{command_args.join(' ')}")
|
136
|
+
when "info"
|
137
|
+
raise ArgumentError, "Info requires a channel number" if command_args.empty?
|
138
|
+
channel_output = run_command(this_method_name, "#{channel_command} #{command_args}")
|
139
|
+
channel_output = channel_output.grep(/:/).each { |line| line.strip! }.delete_if { |line| line =~ /:$/ }
|
140
|
+
return channel_hash = split_output(channel_output, ':')
|
141
|
+
when "getciphers"
|
142
|
+
raise ArgumentError, "Info requires a protocol and channel number" if command_args.empty?
|
143
|
+
channel_output = run_command(this_method_name, "#{channel_command} #{command_args.join(' ')}").grep(/^[0-9]/)
|
144
|
+
channel_output.each { |c| channel_hash["id#{c.split[0]}".to_sym] = c.split[1..-1] }
|
145
|
+
return channel_hash
|
146
|
+
else
|
147
|
+
raise ArgumentError, "Invalid Channel Command"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
#Add and modify users.
|
152
|
+
#
|
153
|
+
#set name, set password, disable, enable, and priv do not give output
|
154
|
+
def user(user_command, *command_args)
|
155
|
+
user_hash = Hash.new
|
156
|
+
case user_command
|
157
|
+
when "list"
|
158
|
+
raise ArgumentError, "List requires a channel number" if command_args.empty?
|
159
|
+
user_output = run_command(this_method_name, "#{user_command} #{command_args}").grep(/^[0-9]/)
|
160
|
+
user_output.each { |u| user_hash["uid#{u.split[0]}".to_sym] = u.split[1..-1] }
|
161
|
+
return user_hash
|
162
|
+
when "set name", "set password", "priv"
|
163
|
+
raise ArgumentError, "#{user_command} requires 2 arguments" if command_args.empty?
|
164
|
+
run_command(this_method_name, "#{user_command} #{command_args.join(' ')}")
|
165
|
+
when "disable", "enable"
|
166
|
+
raise ArgumentError, "#{user_command} requires a UID" if command_args.empty?
|
167
|
+
run_command(this_method_name, "#{user_command} #{command_args}")
|
168
|
+
else
|
169
|
+
raise ArgumentError, "Invalid User Command"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
#This function takes no arguments and returns logging output
|
174
|
+
def sel
|
175
|
+
sel_output = run_command(this_method_name).split("\n").grep(/:/)
|
176
|
+
return sel_hash = split_output(sel_output, ':')
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
def run_command(command, *args)
|
181
|
+
`#{@conn[:binary]} -H #{@conn[:host]} -U #{@conn[:user]} -P #{@conn[:password]} #{command} #{args unless args.nil?}`.downcase!
|
182
|
+
end
|
183
|
+
|
184
|
+
def split_output(array, delimiter)
|
185
|
+
split_hash = Hash.new
|
186
|
+
delimiter = "\\#{delimiter}"
|
187
|
+
array.each { |stat| split_hash[stat.split(/\s*#{delimiter}\s?/)[0].gsub(/\s+/," ").gsub(' ','_').gsub('.','').gsub(/^#/,"number").to_sym] = stat.split(/\s*#{delimiter}\s?/,2)[1].strip }
|
188
|
+
return split_hash
|
189
|
+
end
|
190
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-ipmitool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: "0.1"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Eugene Howe
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-04-23 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Wraps most fucntionality of ipmitool including user, sensor, channel, and chassis functions
|
22
|
+
email:
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/ruby-ipmitool.rb
|
31
|
+
has_rdoc: true
|
32
|
+
homepage:
|
33
|
+
licenses: []
|
34
|
+
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
hash: 3
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.5.0
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Wrapper for the linux ipmitool command
|
65
|
+
test_files: []
|
66
|
+
|