rubyipmi 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +5 -3
  3. data/README.md +24 -14
  4. data/Rakefile +82 -4
  5. data/VERSION +1 -1
  6. data/lib/rubyipmi.rb +36 -14
  7. data/lib/rubyipmi/commands/basecommand.rb +57 -119
  8. data/lib/rubyipmi/freeipmi/commands/basecommand.rb +29 -25
  9. data/lib/rubyipmi/freeipmi/commands/bmc.rb +3 -3
  10. data/lib/rubyipmi/freeipmi/commands/bmcconfig.rb +6 -6
  11. data/lib/rubyipmi/freeipmi/commands/bmcinfo.rb +3 -23
  12. data/lib/rubyipmi/freeipmi/commands/fru.rb +117 -23
  13. data/lib/rubyipmi/freeipmi/commands/lan.rb +32 -37
  14. data/lib/rubyipmi/freeipmi/commands/power.rb +1 -1
  15. data/lib/rubyipmi/freeipmi/commands/sensors.rb +53 -50
  16. data/lib/rubyipmi/freeipmi/connection.rb +16 -2
  17. data/lib/rubyipmi/freeipmi/errorcodes.rb +25 -2
  18. data/lib/rubyipmi/ipmitool/commands/basecommand.rb +20 -37
  19. data/lib/rubyipmi/ipmitool/commands/bmc.rb +1 -24
  20. data/lib/rubyipmi/ipmitool/commands/chassis.rb +1 -0
  21. data/lib/rubyipmi/ipmitool/commands/fru.rb +112 -30
  22. data/lib/rubyipmi/ipmitool/commands/lan.rb +55 -77
  23. data/lib/rubyipmi/ipmitool/commands/power.rb +10 -4
  24. data/lib/rubyipmi/ipmitool/commands/sensors.rb +53 -80
  25. data/lib/rubyipmi/ipmitool/connection.rb +19 -3
  26. data/lib/rubyipmi/ipmitool/errorcodes.rb +51 -3
  27. data/rubyipmi.gemspec +73 -33
  28. data/spec/Vagrantfile +45 -0
  29. data/spec/fixtures/freeipmi/bmc_config.txt +317 -0
  30. data/spec/fixtures/freeipmi/bmc_config_lan_conf.txt +19 -0
  31. data/spec/fixtures/freeipmi/bmc_info.txt +32 -0
  32. data/spec/fixtures/freeipmi/errors.txt +3 -0
  33. data/spec/fixtures/freeipmi/fru.txt +13 -0
  34. data/spec/fixtures/freeipmi/sensors.txt +29 -0
  35. data/spec/fixtures/ipmitool/bmc_info.txt +20 -0
  36. data/spec/fixtures/ipmitool/errors.txt +10 -0
  37. data/spec/fixtures/ipmitool/fru.txt +96 -0
  38. data/spec/fixtures/ipmitool/lan.txt +17 -0
  39. data/spec/fixtures/ipmitool/sensors.txt +105 -0
  40. data/spec/integration/bmc_spec.rb +49 -0
  41. data/spec/{chassis_config_spec.rb → integration/chassis_config_spec.rb} +6 -6
  42. data/spec/integration/chassis_spec.rb +26 -0
  43. data/spec/integration/connection_spec.rb +35 -0
  44. data/spec/{fru_spec.rb → integration/fru_spec.rb} +11 -10
  45. data/spec/{lan_spec.rb → integration/lan_spec.rb} +9 -7
  46. data/spec/integration/power_spec.rb +40 -0
  47. data/spec/{rubyipmi_spec.rb → integration/rubyipmi_spec.rb} +7 -10
  48. data/spec/{sensor_spec.rb → integration/sensor_spec.rb} +5 -20
  49. data/spec/manifests/default.pp +50 -0
  50. data/spec/puppetmodules/archive/LICENSE-2.0.txt +202 -0
  51. data/spec/puppetmodules/archive/Modulefile +8 -0
  52. data/spec/puppetmodules/archive/README.md +40 -0
  53. data/spec/puppetmodules/archive/manifests/download.pp +157 -0
  54. data/spec/puppetmodules/archive/manifests/extract.pp +81 -0
  55. data/spec/puppetmodules/archive/manifests/init.pp +70 -0
  56. data/spec/puppetmodules/archive/manifests/tar-gz.pp +7 -0
  57. data/spec/puppetmodules/archive/manifests/zip.pp +7 -0
  58. data/spec/puppetmodules/archive/metadata.json +26 -0
  59. data/spec/spec_helper.rb +35 -3
  60. data/spec/unit/freeipmi/bmc-info_spec.rb +42 -0
  61. data/spec/unit/freeipmi/bmc_spec.rb +44 -0
  62. data/spec/unit/freeipmi/connection_spec.rb +56 -0
  63. data/spec/unit/freeipmi/errorcodes_spec.rb +34 -0
  64. data/spec/unit/freeipmi/fru_spec.rb +77 -0
  65. data/spec/unit/freeipmi/lan_spec.rb +0 -0
  66. data/spec/unit/freeipmi/sensors_spec.rb +83 -0
  67. data/spec/unit/ipmitool/bmc_spec.rb +78 -0
  68. data/spec/unit/ipmitool/connection_spec.rb +58 -0
  69. data/spec/unit/ipmitool/errorcodes_spec.rb +34 -0
  70. data/spec/unit/ipmitool/fru_spec.rb +77 -0
  71. data/spec/unit/ipmitool/lan_spec.rb +93 -0
  72. data/spec/unit/ipmitool/sensors_spec.rb +95 -0
  73. data/spec/unit/rubyipmi_spec.rb +31 -0
  74. data/spec/vagrant +27 -0
  75. data/spec/vagrant.pub +1 -0
  76. metadata +157 -106
  77. data/.document +0 -5
  78. data/.rspec +0 -1
  79. data/Gemfile.lock +0 -33
  80. data/spec/bmc_spec.rb +0 -46
  81. data/spec/chassis_spec.rb +0 -26
  82. data/spec/connection_spec.rb +0 -31
  83. 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
- parse(print)
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 print
24
- @options["cmdargs"] = "lan print"
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
- if @info.length < 1
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
- if @info.length < 1
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
- if @info.length < 1
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
- if @info.length < 1
63
- parse(print)
64
- end
65
- @info["default gateway ip"]
62
+ info.fetch("default_gateway_ip",nil)
66
63
  end
67
64
 
68
- # def vlanid
69
- # if @info.length < 1
70
- # parse(print)
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
- if @info.length < 1
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
- if @info.length < 1
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
- # def vlanid=(vlan)
118
- # @options["cmdargs"] = "lan set #{channel} vlan id #{vlan}"
119
- # value = runcmd
120
- # @options.delete_notify("cmdargs")
121
- # return value
122
- # end
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 parse(landata)
126
- multikey = ""
127
- multivalue = {}
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.downcase
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
- command("on")
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
- command("off")
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
- sensors
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
- sensors.count
19
+ list.count
20
20
  end
21
21
 
22
22
  def names
23
- sensors.keys
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
- values = sensors.each do |sensor|
30
- match = sensor.first.match(/(fan)_(\d+)/)
31
- next if match.nil?
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
- values = sensors.each do |sensor|
44
- match = sensor.first.match(/(temp)_(\d+)/)
45
- next if match.nil?
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 sensors.has_key?(method.to_s)
60
+ if not list.has_key?(method.to_s)
64
61
  raise NoMethodError
65
62
  else
66
- sensors[method.to_s]
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.lines.each do | line|
80
- # skip the header
81
- data = line.split(/\|/)
82
- sensor = Sensor.new(data.first.strip)
83
- sensor[:value] = data[1].strip
84
- sensor[:unit] = data[2].strip
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
- def initialize(sname)
106
- self[:fullname] = sname
107
- self[:name] = sname.gsub(/\ /, '_').gsub(/\./, '').downcase
81
+ class Sensor < Hash
82
+ def initialize(line)
83
+ parse(line)
84
+ self[:name] = normalize(self[:name])
108
85
  end
109
86
 
110
- #def refresh
111
- # data = "sensor get \"#{self[:fullname]}\" "
112
- # parse(data)
113
- #end
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
- @options["I"] = "lanplus"
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