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
@@ -1,3 +1,5 @@
1
+ require 'rubyipmi/freeipmi/errorcodes'
2
+
1
3
  module Rubyipmi::Freeipmi
2
4
 
3
5
  class BaseCommand < Rubyipmi::BaseCommand
@@ -5,27 +7,29 @@ module Rubyipmi::Freeipmi
5
7
  def setpass
6
8
  super
7
9
  @options["config-file"] = @passfile.path
8
- @passfile.puts "password #{@options["password"]}\n"
9
- @passfile.puts "username #{@options["username"]}"
10
-
10
+ @passfile.write "username #{@options["username"]}\n"
11
+ @passfile.write "password #{@options["password"]}\n"
11
12
  @passfile.close
13
+
14
+ end
15
+
16
+ def max_retry_count
17
+ @max_retry_count ||= Rubyipmi::Freeipmi::ErrorCodes.length
12
18
  end
13
19
 
14
20
  def makecommand
15
21
  # need to format the options to freeipmi format
16
22
  args = @options.collect { |k, v|
23
+ # must remove from command line as its handled via conf file
24
+ next if k == 'password'
25
+ next if k == 'username'
17
26
  if not v
18
27
  "--#{k}"
19
28
  else
20
29
  "--#{k}=#{v}"
21
30
  end
22
31
  }.join(" ")
23
- # must remove from command line as its handled via conf file
24
- args.delete("--password")
25
- args.delete("--username")
26
-
27
-
28
- return "#{cmd} #{args}"
32
+ return "#{cmd} #{args.rstrip}"
29
33
  end
30
34
 
31
35
  # This method will check if the results are really valid as the exit code can be misleading and incorrect
@@ -35,39 +39,39 @@ module Rubyipmi::Freeipmi
35
39
  # until ipmipower returns the correct exit status this is a hack
36
40
  # essentially any result greater than 23 characters is an error
37
41
  if @result.length > 23
38
- return false
42
+ raise "Error occurred"
39
43
  end
40
44
  when "bmc-config"
41
45
  if @result.length > 100
42
46
  return true
47
+ else
48
+ raise "Error occurred"
49
+ end
50
+ else
51
+ if exitstatus.success?
52
+ return true
53
+ else
54
+ raise "Error occurred"
43
55
  end
44
- end
45
- return exitstatus.success?
46
56
 
57
+ end
47
58
  end
48
59
 
49
60
  # The findfix method acts like a recursive method and applies fixes defined in the errorcodes
50
61
  # If a fix is found it is applied to the options hash, and then the last run command is retried
51
62
  # until all the fixes are exhausted or a error not defined in the errorcodes is found
52
- def findfix(result, args, debug, runmethod)
63
+ def find_fix(result)
53
64
  if result
54
65
  # The errorcode code hash contains the fix
55
- fix = Rubyipmi::Freeipmi::ErrorCodes.code[result]
56
- if not fix
57
- raise "#{result}"
58
- else
66
+ begin
67
+ fix = ErrorCodes.search(result)
59
68
  @options.merge_notify!(fix)
60
- # retry the last called method
61
- # its quicker to explicitly call these commands than calling a command block
62
- if runmethod == "runcmd"
63
- runcmd(debug)
64
- else
65
- runcmd_without_opts(args, debug)
66
- end
67
69
 
70
+ rescue
71
+ raise "Could not find fix for error code: \n#{result}"
68
72
  end
69
-
70
73
  end
71
74
  end
75
+
72
76
  end
73
77
  end
@@ -1,12 +1,12 @@
1
1
  module Rubyipmi::Freeipmi
2
2
 
3
- class Bmc
3
+ class Bmc < Rubyipmi::Freeipmi::BaseCommand
4
4
 
5
- attr_accessor :options
5
+ #attr_accessor :options
6
6
  attr_accessor :config
7
7
 
8
8
  def initialize(opts = ObservableHash.new)
9
- @options = opts
9
+ super("bmc-device", opts)
10
10
  @bmcinfo = {}
11
11
  end
12
12
 
@@ -9,12 +9,12 @@ module Rubyipmi::Freeipmi
9
9
  end
10
10
 
11
11
  def section(section)
12
- @options["checkout"] = false
13
- @options["section"] = section
14
- value = runcmd
15
- @options.delete_notify("checkout")
16
- @options.delete_notify("section")
17
- @result
12
+ @options["checkout"] = false
13
+ @options["section"] = section
14
+ value = runcmd
15
+ @options.delete_notify("checkout")
16
+ @options.delete_notify("section")
17
+ return @result
18
18
  end
19
19
 
20
20
  def setsection(section, key, value)
@@ -9,9 +9,9 @@ module Rubyipmi::Freeipmi
9
9
 
10
10
 
11
11
  def guid
12
- @options["guid"] = false
12
+ options["get-device-guid"] = false
13
13
  status = runcmd
14
- @options.delete_notify["guid"]
14
+ options.delete_notify("get-device-guid")
15
15
  if not status
16
16
  raise @result
17
17
  else
@@ -19,27 +19,7 @@ module Rubyipmi::Freeipmi
19
19
  end
20
20
 
21
21
  end
22
- # freeipmi
23
- # Device ID: 17
24
- # Device Revision: 1
25
- # [SDR Support]
26
- # Firmware Revision: 2.09
27
- # [Device Available (normal operation)]
28
- # IPMI Version: 2.0
29
- # Additional Device Support:
30
- # [Sensor Device]
31
- # [SDR Repository Device]
32
- # [SEL Device]
33
- # [FRU Inventory Device]
34
- # Manufacturer ID: 11
35
- # Product ID: 8192
36
- # Channel Information:
37
- # Channel No: 2
38
- # Medium Type: 802.3 LAN
39
- # Protocol Type: IPMB-1.0
40
- # Channel No: 7
41
- # Medium Type: OEM
42
- # Protocol Type: KCS
22
+
43
23
  def retrieve
44
24
  bmcinfo = {}
45
25
  status = runcmd
@@ -2,48 +2,105 @@ module Rubyipmi::Freeipmi
2
2
 
3
3
  class Fru < Rubyipmi::Freeipmi::BaseCommand
4
4
 
5
+ attr_accessor :list
6
+
7
+ DEFAULT_FRU = 'default_fru_device'
8
+
5
9
  def initialize(opts = ObservableHash.new)
6
- super("ipmi-fru", opts)
10
+ super("ipmi-fru", opts)
11
+ @list = {}
7
12
  end
8
13
 
9
- # return the list of fru information in a hash
10
- def list
11
- @list ||= parse(command)
14
+ def get_from_list(key)
15
+ if list.has_key?(DEFAULT_FRU)
16
+ if list[DEFAULT_FRU].has_key?(key)
17
+ list[DEFAULT_FRU][key]
18
+ else
19
+ nil
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ def manufacturer
26
+ get_from_list('board_manufacturer')
27
+ end
28
+
29
+ def board_serial
30
+ get_from_list('board_serial_number')
12
31
  end
13
32
 
14
33
  def serial
15
- list["chassis_serial_number"]
34
+ get_from_list('board_serial_number')
16
35
  end
17
36
 
18
- def manufacturer
19
- list["board_manufacturer"]
37
+ def model
38
+ get_from_list('board_product_name')
39
+ end
40
+
41
+ # method to retrieve the raw fru data
42
+ def getfrus
43
+ command
44
+ return @result
20
45
  end
21
46
 
22
- def product
23
- list["board_product_name"]
47
+ def names
48
+ list.keys
49
+ end
50
+
51
+ # return the list of fru information in a hash
52
+ def list
53
+ if @list.count < 1
54
+ parse(getfrus)
55
+ end
56
+ @list
24
57
  end
25
58
 
26
59
  private
27
60
 
28
61
  def method_missing(method, *args, &block)
29
- if not list.has_key?(method.to_s)
30
- raise NoMethodError
31
- else
32
- list[method.to_s]
33
- end
34
- end
62
+ name = method.to_s
63
+ fru = list.fetch(name, nil)
64
+ # if the user wanted some data from the default fru, lets show the data for the fru. Otherwise
65
+ # we return the Fru with the given name
66
+ if fru.nil?
67
+ if list[DEFAULT_FRU].keys.include?(name)
68
+ return list[DEFAULT_FRU][name]
69
+ else
70
+ # maybe we should return nil instead? hmm...
71
+ raise NoMethodError
72
+ end
73
+ else
74
+ return fru
75
+ end
76
+ end
35
77
 
36
78
  # parse the fru information
37
79
  def parse(data)
38
- datalist = {}
39
- data.lines.each do |line|
40
- key, value = line.split(':')
41
- next if key =~ /\n/
42
- value = value.strip
43
- key = key.gsub(/FRU/, '').strip.gsub(/\ /, '_').downcase
44
- datalist[key] = value.strip
80
+ if ! data.nil? and ! data.empty?
81
+ parsed_data = []
82
+ data.lines.each do |line|
83
+ if line =~ /^FRU.*/
84
+ # this is the either the first line of of the fru or another fru
85
+ if parsed_data.count != 0
86
+ # we have reached a new fru device so lets record the previous fru
87
+ new_fru = FruData.new(parsed_data)
88
+ parsed_data = []
89
+ @list[new_fru[:name]] = new_fru
90
+ end
91
+
92
+ end
93
+ parsed_data << line
94
+ end
95
+ # process the last fru
96
+ if parsed_data.count != 0
97
+ # we have reached a new fru device so lets record the previous fru
98
+ new_fru = FruData.new(parsed_data)
99
+ parsed_data = []
100
+ @list[new_fru[:name]] = new_fru
101
+ end
45
102
  end
46
- return datalist
103
+ return @list
47
104
  end
48
105
 
49
106
  # run the command and return result
@@ -56,4 +113,41 @@ module Rubyipmi::Freeipmi
56
113
 
57
114
  end
58
115
 
116
+ class FruData < Hash
117
+
118
+ def name
119
+ self[:name]
120
+ end
121
+
122
+ def initialize(data)
123
+ parse(data)
124
+ end
125
+
126
+ # parse the fru information that should be an array of lines
127
+ def parse(data)
128
+ if ! data.nil?
129
+ data.each do |line|
130
+ key, value = line.split(':', 2)
131
+ if key =~ /^FRU.*/
132
+ if value =~ /([\w\s]*)\(.*\)/
133
+ self[:name] = $~[1].strip.gsub(/\ /, '_').downcase
134
+ end
135
+ else
136
+ key = key.strip.gsub(/\ /, '_').downcase.gsub(/fru_/, '')
137
+ if ! value.nil?
138
+ self[key] = value.strip
139
+
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ def method_missing(method, *args, &block)
149
+ self.fetch(method.to_s, nil)
150
+ end
151
+
152
+ end
59
153
  end
@@ -13,6 +13,7 @@ module Rubyipmi::Freeipmi
13
13
  @channel = 2
14
14
  end
15
15
 
16
+
16
17
  def info
17
18
  if @info.length < 1
18
19
  parse(@config.section("Lan_Conf"))
@@ -22,45 +23,27 @@ module Rubyipmi::Freeipmi
22
23
  end
23
24
 
24
25
  def dhcp?
25
- if @info.length < 1
26
- parse(@config.section("Lan_Conf"))
27
- end
28
- @info["ip_address_source"].match(/dhcp/i) != nil
26
+ info.fetch("ip_address_source",nil).match(/dhcp/i) != nil
29
27
  end
30
28
 
31
29
  def static?
32
- if @info.length < 1
33
- parse(@config.section("Lan_Conf"))
34
- end
35
- @info["ip_address_source"].match(/static/i) != nil
30
+ info.fetch("ip_address_source",nil).match(/static/i) != nil
36
31
  end
37
32
 
38
33
  def ip
39
- if @info.length < 1
40
- parse(@config.section("Lan_Conf"))
41
- end
42
- @info["ip_address"]
34
+ info.fetch("ip_address", nil)
43
35
  end
44
36
 
45
37
  def mac
46
- if @info.length < 1
47
- parse(@config.section("Lan_Conf"))
48
- end
49
- @info["mac_address"]
38
+ info.fetch("mac_address", nil)
50
39
  end
51
40
 
52
41
  def netmask
53
- if @info.length < 1
54
- parse(@config.section("Lan_Conf"))
55
- end
56
- @info["subnet_mask"]
42
+ info.fetch("subnet_mask", nil)
57
43
  end
58
44
 
59
45
  def gateway
60
- if @info.length < 1
61
- parse(@config.section("Lan_Conf"))
62
- end
63
- @info["default_gateway_ip_address"]
46
+ info.fetch("default_gateway_ip_address", nil)
64
47
  end
65
48
 
66
49
  # def snmp
@@ -75,16 +58,26 @@ module Rubyipmi::Freeipmi
75
58
  #
76
59
  # end
77
60
 
61
+ # validates that the address, returns true/false
62
+ def validaddr?(source)
63
+ valid = /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/.match("#{source}")
64
+ if valid.nil?
65
+ raise "#{source} is not a valid address"
66
+ else
67
+ return true
68
+ end
69
+ end
70
+
78
71
  def ip=(address)
79
- @config.setsection("Lan_Conf", "IP_Address", address)
72
+ @config.setsection("Lan_Conf", "IP_Address", address) if validaddr?(address)
80
73
  end
81
74
 
82
75
  def netmask=(netmask)
83
- @config.setsection("Lan_Conf", "Subnet_Mask", netmask)
76
+ @config.setsection("Lan_Conf", "Subnet_Mask", netmask) if validaddr?(netmask)
84
77
  end
85
78
 
86
79
  def gateway=(address)
87
- @config.setsection("Lan_Conf", "Default_Gateway_IP_Address", address)
80
+ @config.setsection("Lan_Conf", "Default_Gateway_IP_Address", address) if validaddr?(address)
88
81
  end
89
82
 
90
83
  # def vlanid=(vlan)
@@ -92,16 +85,18 @@ module Rubyipmi::Freeipmi
92
85
  # end
93
86
 
94
87
  def parse(landata)
95
- landata.lines.each do |line|
96
- # clean up the data from spaces
97
- next if line.match(/#+/)
98
- next if line.match(/Section/i)
99
- line.gsub!(/\t/, '')
100
- item = line.split(/\s+/)
101
- key = item.first.strip.downcase
102
- value = item.last.strip
103
- @info[key] = value
104
-
88
+ if ! landata.nil? and ! landata.empty?
89
+ landata.lines.each do |line|
90
+ # clean up the data from spaces
91
+ next if line.match(/#+/)
92
+ next if line.match(/Section/i)
93
+ line.gsub!(/\t/, '')
94
+ item = line.split(/\s+/)
95
+ key = item.first.strip.downcase
96
+ value = item.last.strip
97
+ @info[key] = value
98
+
99
+ end
105
100
  end
106
101
  return @info
107
102
  end