rubyipmi 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +5 -3
- data/README.md +24 -14
- data/Rakefile +82 -4
- data/VERSION +1 -1
- data/lib/rubyipmi.rb +36 -14
- data/lib/rubyipmi/commands/basecommand.rb +57 -119
- data/lib/rubyipmi/freeipmi/commands/basecommand.rb +29 -25
- data/lib/rubyipmi/freeipmi/commands/bmc.rb +3 -3
- data/lib/rubyipmi/freeipmi/commands/bmcconfig.rb +6 -6
- data/lib/rubyipmi/freeipmi/commands/bmcinfo.rb +3 -23
- data/lib/rubyipmi/freeipmi/commands/fru.rb +117 -23
- data/lib/rubyipmi/freeipmi/commands/lan.rb +32 -37
- data/lib/rubyipmi/freeipmi/commands/power.rb +1 -1
- data/lib/rubyipmi/freeipmi/commands/sensors.rb +53 -50
- data/lib/rubyipmi/freeipmi/connection.rb +16 -2
- data/lib/rubyipmi/freeipmi/errorcodes.rb +25 -2
- data/lib/rubyipmi/ipmitool/commands/basecommand.rb +20 -37
- data/lib/rubyipmi/ipmitool/commands/bmc.rb +1 -24
- data/lib/rubyipmi/ipmitool/commands/chassis.rb +1 -0
- data/lib/rubyipmi/ipmitool/commands/fru.rb +112 -30
- data/lib/rubyipmi/ipmitool/commands/lan.rb +55 -77
- data/lib/rubyipmi/ipmitool/commands/power.rb +10 -4
- data/lib/rubyipmi/ipmitool/commands/sensors.rb +53 -80
- data/lib/rubyipmi/ipmitool/connection.rb +19 -3
- data/lib/rubyipmi/ipmitool/errorcodes.rb +51 -3
- data/rubyipmi.gemspec +73 -33
- data/spec/Vagrantfile +45 -0
- data/spec/fixtures/freeipmi/bmc_config.txt +317 -0
- data/spec/fixtures/freeipmi/bmc_config_lan_conf.txt +19 -0
- data/spec/fixtures/freeipmi/bmc_info.txt +32 -0
- data/spec/fixtures/freeipmi/errors.txt +3 -0
- data/spec/fixtures/freeipmi/fru.txt +13 -0
- data/spec/fixtures/freeipmi/sensors.txt +29 -0
- data/spec/fixtures/ipmitool/bmc_info.txt +20 -0
- data/spec/fixtures/ipmitool/errors.txt +10 -0
- data/spec/fixtures/ipmitool/fru.txt +96 -0
- data/spec/fixtures/ipmitool/lan.txt +17 -0
- data/spec/fixtures/ipmitool/sensors.txt +105 -0
- data/spec/integration/bmc_spec.rb +49 -0
- data/spec/{chassis_config_spec.rb → integration/chassis_config_spec.rb} +6 -6
- data/spec/integration/chassis_spec.rb +26 -0
- data/spec/integration/connection_spec.rb +35 -0
- data/spec/{fru_spec.rb → integration/fru_spec.rb} +11 -10
- data/spec/{lan_spec.rb → integration/lan_spec.rb} +9 -7
- data/spec/integration/power_spec.rb +40 -0
- data/spec/{rubyipmi_spec.rb → integration/rubyipmi_spec.rb} +7 -10
- data/spec/{sensor_spec.rb → integration/sensor_spec.rb} +5 -20
- data/spec/manifests/default.pp +50 -0
- data/spec/puppetmodules/archive/LICENSE-2.0.txt +202 -0
- data/spec/puppetmodules/archive/Modulefile +8 -0
- data/spec/puppetmodules/archive/README.md +40 -0
- data/spec/puppetmodules/archive/manifests/download.pp +157 -0
- data/spec/puppetmodules/archive/manifests/extract.pp +81 -0
- data/spec/puppetmodules/archive/manifests/init.pp +70 -0
- data/spec/puppetmodules/archive/manifests/tar-gz.pp +7 -0
- data/spec/puppetmodules/archive/manifests/zip.pp +7 -0
- data/spec/puppetmodules/archive/metadata.json +26 -0
- data/spec/spec_helper.rb +35 -3
- data/spec/unit/freeipmi/bmc-info_spec.rb +42 -0
- data/spec/unit/freeipmi/bmc_spec.rb +44 -0
- data/spec/unit/freeipmi/connection_spec.rb +56 -0
- data/spec/unit/freeipmi/errorcodes_spec.rb +34 -0
- data/spec/unit/freeipmi/fru_spec.rb +77 -0
- data/spec/unit/freeipmi/lan_spec.rb +0 -0
- data/spec/unit/freeipmi/sensors_spec.rb +83 -0
- data/spec/unit/ipmitool/bmc_spec.rb +78 -0
- data/spec/unit/ipmitool/connection_spec.rb +58 -0
- data/spec/unit/ipmitool/errorcodes_spec.rb +34 -0
- data/spec/unit/ipmitool/fru_spec.rb +77 -0
- data/spec/unit/ipmitool/lan_spec.rb +93 -0
- data/spec/unit/ipmitool/sensors_spec.rb +95 -0
- data/spec/unit/rubyipmi_spec.rb +31 -0
- data/spec/vagrant +27 -0
- data/spec/vagrant.pub +1 -0
- metadata +157 -106
- data/.document +0 -5
- data/.rspec +0 -1
- data/Gemfile.lock +0 -33
- data/spec/bmc_spec.rb +0 -46
- data/spec/chassis_spec.rb +0 -26
- data/spec/connection_spec.rb +0 -31
- data/spec/power_spec.rb +0 -42
@@ -4,6 +4,7 @@ module Rubyipmi::Ipmitool
|
|
4
4
|
|
5
5
|
attr_accessor :info
|
6
6
|
attr_accessor :channel
|
7
|
+
MAX_RETRY = 1
|
7
8
|
|
8
9
|
def initialize(opts = ObservableHash.new)
|
9
10
|
super("ipmitool", opts)
|
@@ -12,65 +13,58 @@ module Rubyipmi::Ipmitool
|
|
12
13
|
|
13
14
|
end
|
14
15
|
|
16
|
+
# sets the info var to be empty causing the variable to repopulate upon the next call to info
|
17
|
+
def refresh
|
18
|
+
@info = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def channel=(num)
|
22
|
+
refresh
|
23
|
+
@channel = num
|
24
|
+
end
|
25
|
+
|
15
26
|
def info
|
27
|
+
retrycount = 0
|
16
28
|
if @info.length < 1
|
17
|
-
|
29
|
+
begin
|
30
|
+
parse(print)
|
31
|
+
rescue
|
32
|
+
# sometimes we need to get the info from channel 1,
|
33
|
+
# wait for error to occur then retry using channel 1
|
34
|
+
if retrycount < MAX_RETRY
|
35
|
+
@channel = 1
|
36
|
+
retry
|
37
|
+
end
|
38
|
+
end
|
18
39
|
else
|
40
|
+
# return the cached info
|
19
41
|
@info
|
20
42
|
end
|
21
43
|
end
|
22
44
|
|
23
|
-
def
|
24
|
-
|
25
|
-
value = runcmd
|
26
|
-
@options.delete_notify("cmdargs")
|
27
|
-
if value
|
28
|
-
@result
|
29
|
-
end
|
45
|
+
def snmp
|
46
|
+
info.fetch("snmp_community_string",nil)
|
30
47
|
end
|
31
48
|
|
32
|
-
# def snmp
|
33
|
-
# if @info.length < 1
|
34
|
-
# parse(print)
|
35
|
-
# end
|
36
|
-
# # Some systems do not report the snmp string
|
37
|
-
# @info["snmp community string"]
|
38
|
-
# end
|
39
|
-
|
40
49
|
def ip
|
41
|
-
|
42
|
-
parse(print)
|
43
|
-
end
|
44
|
-
@info["ip address"]
|
50
|
+
info.fetch("ip_address",nil)
|
45
51
|
end
|
46
52
|
|
47
53
|
def mac
|
48
|
-
|
49
|
-
parse(print)
|
50
|
-
end
|
51
|
-
@info["mac address"]
|
54
|
+
info.fetch("mac_address",nil)
|
52
55
|
end
|
53
56
|
|
54
57
|
def netmask
|
55
|
-
|
56
|
-
parse(print)
|
57
|
-
end
|
58
|
-
@info["subnet mask"]
|
58
|
+
info.fetch("subnet_mask",nil)
|
59
59
|
end
|
60
60
|
|
61
61
|
def gateway
|
62
|
-
|
63
|
-
parse(print)
|
64
|
-
end
|
65
|
-
@info["default gateway ip"]
|
62
|
+
info.fetch("default_gateway_ip",nil)
|
66
63
|
end
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
# end
|
72
|
-
# @info["802.1q vlan id"]
|
73
|
-
# end
|
65
|
+
def vlanid
|
66
|
+
info.fetch("802.1q_vlan_id",nil)
|
67
|
+
end
|
74
68
|
|
75
69
|
# def snmp=(community)
|
76
70
|
# @options["cmdargs"] = "lan set #{channel} snmp #{community}"
|
@@ -94,42 +88,43 @@ module Rubyipmi::Ipmitool
|
|
94
88
|
end
|
95
89
|
|
96
90
|
def gateway=(address)
|
97
|
-
@options["cmdargs"] = "lan set #{channel} defgw #{address}"
|
91
|
+
@options["cmdargs"] = "lan set #{channel} defgw ipaddr #{address}"
|
98
92
|
value = runcmd
|
99
93
|
@options.delete_notify("cmdargs")
|
100
94
|
return value
|
101
95
|
end
|
102
96
|
|
103
97
|
def dhcp?
|
104
|
-
|
105
|
-
parse(print)
|
106
|
-
end
|
107
|
-
@info["ip address source"].match(/dhcp/i) != nil
|
98
|
+
info.fetch("ip_address_source",nil).match(/dhcp/i) != nil
|
108
99
|
end
|
109
100
|
|
110
101
|
def static?
|
111
|
-
|
112
|
-
parse(print)
|
113
|
-
end
|
114
|
-
@info["ip address source"].match(/static/i) != nil
|
102
|
+
info.fetch("ip_address_source",nil).match(/static/i) != nil
|
115
103
|
end
|
116
104
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
105
|
+
def vlanid=(vlan)
|
106
|
+
@options["cmdargs"] = "lan set #{channel} vlan id #{vlan}"
|
107
|
+
value = runcmd
|
108
|
+
@options.delete_notify("cmdargs")
|
109
|
+
return value
|
110
|
+
end
|
123
111
|
|
112
|
+
private
|
124
113
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
114
|
+
def print
|
115
|
+
@options["cmdargs"] = "lan print"
|
116
|
+
value = runcmd
|
117
|
+
@options.delete_notify("cmdargs")
|
118
|
+
if value
|
119
|
+
@result
|
120
|
+
end
|
121
|
+
end
|
128
122
|
|
123
|
+
def parse(landata)
|
129
124
|
landata.lines.each do |line|
|
130
125
|
# clean up the data from spaces
|
131
126
|
item = line.split(':', 2)
|
132
|
-
key = item.first.strip
|
127
|
+
key = normalize(item.first.strip)
|
133
128
|
value = item.last.strip
|
134
129
|
@info[key] = value
|
135
130
|
|
@@ -137,26 +132,9 @@ module Rubyipmi::Ipmitool
|
|
137
132
|
return @info
|
138
133
|
end
|
139
134
|
|
140
|
-
|
141
|
-
|
135
|
+
def normalize(text)
|
136
|
+
text.gsub(/\ /, '_').gsub(/\./, '').downcase
|
137
|
+
end
|
142
138
|
|
143
139
|
end
|
144
140
|
end
|
145
|
-
|
146
|
-
#Set in Progress : Set Complete
|
147
|
-
#Auth Type Support :
|
148
|
-
#Auth Type Enable : Callback :
|
149
|
-
# : User : NONE MD2 MD5 PASSWORD OEM
|
150
|
-
# : Operator : NONE MD2 MD5
|
151
|
-
# : Admin : MD2 MD5
|
152
|
-
# : OEM :
|
153
|
-
#IP Address Source : DHCP Address
|
154
|
-
#IP Address : 192.168.1.41
|
155
|
-
#Subnet Mask : 255.255.255.0
|
156
|
-
#MAC Address : 00:17:a4:49:ab:70
|
157
|
-
#BMC ARP Control : ARP Responses Enabled, Gratuitous ARP Disabled
|
158
|
-
#Gratituous ARP Intrvl : 0.0 seconds
|
159
|
-
#Default Gateway IP : 192.168.1.1
|
160
|
-
#802.1q VLAN ID : Disabled
|
161
|
-
#802.1q VLAN Priority : 0
|
162
|
-
#Cipher Suite Priv Max : Not Available
|
@@ -16,12 +16,20 @@ module Rubyipmi::Ipmitool
|
|
16
16
|
|
17
17
|
# Turn on the system
|
18
18
|
def on
|
19
|
-
|
19
|
+
if off?
|
20
|
+
command("on")
|
21
|
+
else
|
22
|
+
return true
|
23
|
+
end
|
20
24
|
end
|
21
25
|
|
22
26
|
# Turn off the system
|
23
27
|
def off
|
24
|
-
|
28
|
+
if off?
|
29
|
+
return true
|
30
|
+
else
|
31
|
+
command("off")
|
32
|
+
end
|
25
33
|
end
|
26
34
|
|
27
35
|
# Power cycle the system
|
@@ -68,7 +76,5 @@ module Rubyipmi::Ipmitool
|
|
68
76
|
status == "off"
|
69
77
|
end
|
70
78
|
|
71
|
-
|
72
|
-
|
73
79
|
end
|
74
80
|
end
|
@@ -8,129 +8,102 @@ module Rubyipmi::Ipmitool
|
|
8
8
|
|
9
9
|
def refresh
|
10
10
|
@sensors = nil
|
11
|
-
|
11
|
+
list
|
12
12
|
end
|
13
13
|
|
14
14
|
def list
|
15
|
-
sensors
|
15
|
+
@sensors ||= parse(getsensors)
|
16
16
|
end
|
17
17
|
|
18
18
|
def count
|
19
|
-
|
19
|
+
list.count
|
20
20
|
end
|
21
21
|
|
22
22
|
def names
|
23
|
-
|
23
|
+
list.keys
|
24
24
|
end
|
25
25
|
|
26
|
+
# returns a hash of fan sensors where the key is fan name and value is the sensor
|
26
27
|
def fanlist(refreshdata=false)
|
27
28
|
refresh if refreshdata
|
28
|
-
flist =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if match[1] == "fan"
|
33
|
-
num = (match[2].to_i) -1
|
34
|
-
flist[num] = sensor.last[:value]
|
29
|
+
flist = {}
|
30
|
+
list.each do | name,sensor |
|
31
|
+
if name =~ /.*fan.*/
|
32
|
+
flist[name] = sensor
|
35
33
|
end
|
36
34
|
end
|
37
|
-
flist
|
35
|
+
return flist
|
38
36
|
end
|
39
37
|
|
38
|
+
# returns a hash of sensors where each key is the name of the sensor and the value is the sensor
|
40
39
|
def templist(refreshdata=false)
|
41
40
|
refresh if refreshdata
|
42
|
-
tlist =
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if match[1] == "temp"
|
47
|
-
num = (match[2].to_i) -1
|
48
|
-
tlist[num] = sensor.last[:value]
|
41
|
+
tlist = {}
|
42
|
+
list.each do | name , sensor |
|
43
|
+
if sensor[:unit] =~ /.*degree.*/ || name =~ /.*temp.*/
|
44
|
+
tlist[name] = sensor
|
49
45
|
end
|
50
46
|
end
|
51
|
-
tlist
|
47
|
+
return tlist
|
52
48
|
end
|
53
49
|
|
54
|
-
|
50
|
+
def getsensors
|
51
|
+
options["cmdargs"] = "sensor"
|
52
|
+
value = runcmd
|
53
|
+
options.delete_notify("cmdargs")
|
54
|
+
@result
|
55
|
+
end
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
|
-
def sensors
|
59
|
-
@sensors ||= parse(getsensors)
|
60
|
-
end
|
61
|
-
|
62
59
|
def method_missing(method, *args, &block)
|
63
|
-
if not
|
60
|
+
if not list.has_key?(method.to_s)
|
64
61
|
raise NoMethodError
|
65
62
|
else
|
66
|
-
|
63
|
+
list[method.to_s]
|
67
64
|
end
|
68
65
|
end
|
69
66
|
|
70
|
-
def getsensors
|
71
|
-
options["cmdargs"] = "sensor"
|
72
|
-
value = runcmd
|
73
|
-
options.delete_notify("cmdargs")
|
74
|
-
@result
|
75
|
-
end
|
76
|
-
|
77
67
|
def parse(data)
|
78
68
|
sensorlist = {}
|
79
|
-
data.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
sensor[:status] = data[3].strip
|
86
|
-
sensor[:type] = nil
|
87
|
-
sensor[:state] = nil
|
88
|
-
#sensor[:lower_nonrec] = data[4].strip
|
89
|
-
#sensor[:lower_crit] = data[5].strip
|
90
|
-
#sensor[:lower_noncrit] = data[6].strip
|
91
|
-
#sensor[:upper_noncrit] = data[7].strip
|
92
|
-
#sensor[:upper_crit] = data[8].strip
|
93
|
-
#sensor[:upper_nonrec] = data[9].strip
|
94
|
-
sensorlist[sensor[:name]] = sensor
|
95
|
-
|
69
|
+
if ! data.nil?
|
70
|
+
data.lines.each do | line|
|
71
|
+
# skip the header
|
72
|
+
sensor = Sensor.new(line)
|
73
|
+
sensorlist[sensor[:name]] = sensor
|
74
|
+
end
|
96
75
|
end
|
97
76
|
return sensorlist
|
98
|
-
|
99
77
|
end
|
100
|
-
|
101
78
|
end
|
102
79
|
|
103
|
-
class Sensor < Hash
|
104
80
|
|
105
|
-
|
106
|
-
|
107
|
-
|
81
|
+
class Sensor < Hash
|
82
|
+
def initialize(line)
|
83
|
+
parse(line)
|
84
|
+
self[:name] = normalize(self[:name])
|
108
85
|
end
|
109
86
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
#def parse(data)
|
116
|
-
# values = data.lines.collect do |line|
|
117
|
-
# line.split(':').last.strip
|
118
|
-
# end
|
119
|
-
# # first 4 entries are lines we don't care about
|
120
|
-
# value = values[4].split(/\([\w\W]+\)/)
|
121
|
-
# self[:value] = value.first.strip
|
122
|
-
# self[:unit] = value.last.strip
|
123
|
-
# self[:status] = values[5].strip.chomp
|
124
|
-
# self[:lower_nonrec] = values[6].strip.chomp
|
125
|
-
# self[:lower_crit] = values[7].strip.chomp
|
126
|
-
# self[:lower_noncrit] = values[8].strip.chomp
|
127
|
-
# self[:upper_noncrit] = values[9].strip.chomp
|
128
|
-
# self[:upper_crit] = values[10].strip.chomp
|
129
|
-
# self[:upper_nonrec] = values[11].strip.chomp
|
130
|
-
|
131
|
-
|
132
|
-
#end
|
87
|
+
private
|
88
|
+
def normalize(text)
|
89
|
+
text.gsub(/\ /, '_').gsub(/\./, '').downcase
|
90
|
+
end
|
133
91
|
|
92
|
+
# Parse the individual sensor
|
93
|
+
# Note: not all fields will exist on every server
|
94
|
+
def parse(line)
|
95
|
+
fields = [:name, :value, :unit, :status, :type, :state, :lower_nonrec,
|
96
|
+
:lower_crit,:lower_noncrit, :upper_crit, :upper_nonrec, :asserts_enabled, :deasserts_enabled ]
|
97
|
+
# skip the header
|
98
|
+
data = line.split(/\|/)
|
99
|
+
# should we ever encounter a field not in the fields list, just use a counter based fieldname
|
100
|
+
i = 0
|
101
|
+
data.each do | value |
|
102
|
+
field ||= fields.shift || "field#{i}"
|
103
|
+
self[field] = value.strip
|
104
|
+
i = i.next
|
105
|
+
end
|
106
|
+
end
|
134
107
|
end
|
135
108
|
|
136
109
|
end
|
@@ -12,10 +12,12 @@ module Rubyipmi
|
|
12
12
|
|
13
13
|
class Connection
|
14
14
|
|
15
|
-
attr_accessor :options
|
15
|
+
attr_accessor :options, :debug
|
16
|
+
attr_reader :debug
|
16
17
|
|
17
18
|
|
18
|
-
def initialize(user, pass, host)
|
19
|
+
def initialize(user, pass, host,debug_value=false)
|
20
|
+
@debug = debug_value
|
19
21
|
@options = Rubyipmi::ObservableHash.new
|
20
22
|
raise("Must provide a host to connect to") unless host
|
21
23
|
@options["H"] = host
|
@@ -25,7 +27,7 @@ module Rubyipmi
|
|
25
27
|
@options["P"] = pass if pass
|
26
28
|
# default to IPMI 2.0 communication, this means that older devices will not work
|
27
29
|
# Those old servers should be recycled by now, as the 1.0, 1.5 spec came out in 2005ish and is 2013.
|
28
|
-
|
30
|
+
#@options["I"] = "lanplus"
|
29
31
|
|
30
32
|
#getWorkArounds
|
31
33
|
end
|
@@ -50,6 +52,20 @@ module Rubyipmi
|
|
50
52
|
@chassis ||= Rubyipmi::Ipmitool::Chassis.new(@options)
|
51
53
|
end
|
52
54
|
|
55
|
+
def get_diag
|
56
|
+
data = {}
|
57
|
+
data['provider'] = provider
|
58
|
+
if @fru
|
59
|
+
data['frus'] = @fru.getfrus
|
60
|
+
end
|
61
|
+
if @sensors
|
62
|
+
data['sensors'] = @sensors.getsensors
|
63
|
+
end
|
64
|
+
if @bmc
|
65
|
+
data['bmc_info'] = @bmc.info
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
53
69
|
end
|
54
70
|
end
|
55
71
|
end
|