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
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTk3MjAzNzllY2Y0NWY0Y2RhNzc3MTFkZWZkYTdkY2M4ZjAxOGI5Nw==
5
+ data.tar.gz: !binary |-
6
+ MGY3MWY0ZDVlZmNiYmE1YTg2YzY1YzY0ODY3N2ZiMmFiZjM5YzdjMQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NDdiYmRlMjI3NjQ0Y2E3YmRkMTVmMmQzMDhkZmE0MTQwM2NkNGVjMTY0ODM2
10
+ M2Q1NzAwYzljZTdlYTE1NzU2ZjQ3NGUwZmI3NjdkMGE4MDNhZjNjY2UwNWRh
11
+ NGVlMjU5Mzc5NDRiODBkYjU4MWQxMjgyZDE0NWE2NzRmNmUyYjU=
12
+ data.tar.gz: !binary |-
13
+ N2YwMjM5YjI4NjhiNmY5ZmI1ZGRkYWIwNzZjMGY3NDQ0YjQwMGE2ZTUyYWIz
14
+ YTM5ODZlY2VhYjE2NzRjYjA3NDUxYzc1MzY1MjRlYmViOTA2OGUzZmUxOGMy
15
+ ODYxZGQ5ZjU0ZDBmMDEyMGI1NmNhYzAwYzc1YmIwNDczOGYxYzQ=
data/Gemfile CHANGED
@@ -6,9 +6,11 @@ source "http://rubygems.org"
6
6
  # Add dependencies to develop your gem here.
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
- gem "rspec", "~> 2.8.0"
9
+ gem "rspec", "<= 2.8.0"
10
10
  gem "rdoc", "~> 3.12"
11
- gem "bundler", "~> 1.1.5"
11
+ gem "bundler", ">= 1.1.5"
12
12
  gem "jeweler", "~> 1.8.4"
13
- gem "rcov", ">= 0"
13
+ gem "rcov", "< 1.0.0"
14
+ gem "highline"
15
+ gem "rake"
14
16
  end
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
  This gem is a ruby wrapper for the freeipmi and ipmitool command line tools.
3
3
  It provides a ruby implementation of ipmi commands that will make it simple to connect to BMC devices from ruby.
4
4
 
5
+ [![Build Status](https://travis-ci.org/logicminds/rubyipmi.png)](https://travis-ci.org/logicminds/rubyipmi)
6
+
5
7
  ## Using the library in your code
6
8
 
7
9
  ### Install
@@ -12,10 +14,10 @@ It provides a ruby implementation of ipmi commands that will make it simple to c
12
14
 
13
15
  ### General Usage
14
16
 
15
- ` require 'rubyipmi' `
17
+ ``` require 'rubyipmi' ```
16
18
 
17
19
  #### Create a connection object
18
- `conn = Rubyipmi.connect("username", "password", "hostname", "providertype) `
20
+ ```conn = Rubyipmi.connect("username", "password", "hostname", "providertype) ```
19
21
 
20
22
  Providertype: optional (ipmitool or freeipmi)
21
23
 
@@ -25,38 +27,38 @@ It provides a ruby implementation of ipmi commands that will make it simple to c
25
27
 
26
28
 
27
29
  #### Use power functions (not all listed)
28
- `
30
+ ```
29
31
  conn.chassis.power.on
30
32
  conn.chassis.power.off
31
33
  conn.chassis.power.on?
32
34
  conn.chassis.power.off?
33
35
  conn.chassis.power.cycle
34
- `
36
+ ```
35
37
 
36
38
  #### Boot to specific device
37
- `
39
+ ```
38
40
  conn.chassis.bootpxe(true, false) # reboot after setting, one time boot only - non persistent
39
41
  conn.chassis.bootdisk(false, false) # boot to disk on next reboot, don't reboot automatically
40
42
 
41
- `
43
+ ```
42
44
 
43
45
 
44
46
  #### Sensors
45
- `
47
+ ```
46
48
  conn.sensors.names
47
49
  conn.sensors.list
48
50
  conn.sensors.<sensor name>
49
51
 
50
- `
52
+ ```
51
53
 
52
54
  #### Fru
53
- `
55
+ ```
54
56
  conn.fru.list
55
57
  conn.fru.serial
56
58
  conn.fru.manufacturer
57
59
  conn.fru.product
58
60
 
59
- `
61
+ ```
60
62
 
61
63
  ## Testing
62
64
  There are a series of automated rspec tests that test the functionality of this library with the ipmi device.
@@ -67,7 +69,8 @@ DO NOT PERFORM THESE TEST ON ANY PRODUCTION SYSTEM. THESE TESTS WILL TURN OFF T
67
69
 
68
70
  1. Install gem via source
69
71
  2. bundle install
70
- 3. rake ipmiuser=ipmiuser ipmipass=ipmiuserpass ipmihost=192.168.1.22 ipmiprovider=freeipmi (fill in your your details)
72
+ 3. rake (runs unit tests, does not require a ipmi device)
73
+ 3. rake integration ipmiuser=ipmiuser ipmipass=ipmiuserpass ipmihost=192.168.1.22 ipmiprovider=freeipmi (fill in your your details)
71
74
  4. report any failures with your make/model/firmware revision to corey@logicminds.biz
72
75
 
73
76
  ## Security
@@ -155,14 +158,21 @@ end
155
158
  ```
156
159
 
157
160
  ### How to get the results of the command
158
- After running a command it may be desirable to get the results for further processing. To get the results, follow the example below:
161
+ After running a command it may be desirable to get the results for further processing.
162
+ Note that there are two kinds of results.
163
+ 1. the text returned from the shell command, this is stored in @results
164
+ 2. the status value returned from the shell command (true or false only) this is returned from runcmd.
165
+
166
+ To get the results:
159
167
 
160
168
  Example:
161
169
 
162
170
  ```
163
171
  def status
164
- command("--stat")
165
- @result.split(":").last.chomp.trim
172
+ value = command("--stat")
173
+ if value == true
174
+ @result.split(":").last.chomp.trim
175
+ end
166
176
  end
167
177
 
168
178
  def command(opt)
data/Rakefile CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'bundler'
5
+ @base_dir = File.dirname(__FILE__)
6
+
7
+
5
8
  begin
6
9
  Bundler.setup(:default, :development)
7
10
  rescue Bundler::BundlerError => e
@@ -18,17 +21,49 @@ Jeweler::Tasks.new do |gem|
18
21
  gem.homepage = "http://github.com/logicminds/rubyipmi"
19
22
  gem.license = "GPLv3"
20
23
  gem.summary = %Q{A ruby wrapper for ipmi command line tools that supports ipmitool and freeipmi}
21
- gem.description = %Q{A ruby wrapper for ipmi command line tools that supports ipmitool and freeipmi}
24
+ gem.description = %Q{Provides a library for controlling IPMI devices using pure ruby code}
22
25
  gem.email = "corey@logicminds.biz"
23
26
  gem.authors = ["Corey Osman"]
27
+ gem.files.exclude '.travis.yml'
28
+ gem.files.exclude 'Gemfile.lock'
29
+ gem.files.exclude '.rspec'
30
+ gem.files.exclude '.gitignore'
31
+ gem.files.exclude '.document'
32
+ gem.files.exclude 'coverage/'
33
+
34
+
24
35
  # dependencies defined in Gemfile
25
36
  end
26
37
  Jeweler::RubygemsDotOrgTasks.new
27
38
 
28
39
  require 'rspec/core'
29
40
  require 'rspec/core/rake_task'
30
- RSpec::Core::RakeTask.new(:spec) do |spec|
31
- spec.pattern = FileList['spec/**/*_spec.rb']
41
+
42
+ desc "run unit tests"
43
+ RSpec::Core::RakeTask.new(:unit) do |spec|
44
+ spec.pattern = FileList['spec/unit/**/*_spec.rb']
45
+ end
46
+
47
+ desc "Run integrations tests against real systems using a vagrant box"
48
+ task :vintegration, :user, :pass, :host do |task, args|
49
+ vars = "ipmiuser=#{args[:user]} ipmipass=#{args[:pass]} ipmihost=#{args[:host]}"
50
+ ipmiprovider="freeipmi"
51
+ puts `cd #{@base_dir}/spec && vagrant up`
52
+ puts `cd #{@base_dir}/spec && vagrant provision`
53
+ puts `vagrant ssh \"/rubyipmi/rake integration #{vars}\"`
54
+ end
55
+
56
+ desc "Run integrations tests against real systems"
57
+ RSpec::Core::RakeTask.new :integration do |spec|
58
+ ENV['ipmiuser'] = 'admin'
59
+ ENV['ipmipass'] = 'password'
60
+ ENV['ipmihost'] = '10.0.1.16'
61
+ providers ||= ENV['ipmiprovider'].to_a || ['freeipmi', 'ipmitool']
62
+
63
+ providers.each do | provider |
64
+ ENV['ipmiprovider'] = provider
65
+ spec.pattern = FileList['spec/integration/**/*_spec.rb']
66
+ end
32
67
  end
33
68
 
34
69
  RSpec::Core::RakeTask.new(:rcov) do |spec|
@@ -36,7 +71,7 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
71
  spec.rcov = true
37
72
  end
38
73
 
39
- task :default => :spec
74
+ task :default => :unit
40
75
 
41
76
  require 'rdoc/task'
42
77
  Rake::RDocTask.new do |rdoc|
@@ -47,3 +82,46 @@ Rake::RDocTask.new do |rdoc|
47
82
  rdoc.rdoc_files.include('README*')
48
83
  rdoc.rdoc_files.include('lib/**/*.rb')
49
84
  end
85
+
86
+ desc "send diagnostics to logicminds for testing for the given host"
87
+ task :send_diag, :user, :pass, :host do |t, args |
88
+ require 'rubyipmi'
89
+ require 'net/smtp'
90
+ require 'json'
91
+ require "highline/import"
92
+
93
+ if args.count < 3
94
+ raise "You must provide arguments: rake send_diag[user, pass, host]"
95
+ end
96
+ data = Rubyipmi.get_diag(args[:user], args[:pass], args[:host])
97
+ emailto = 'corey@logicminds.biz'
98
+ subject = "Rubyipmi diagnostics data"
99
+ send_email(emailto, data.to_json, {:subject => subject})
100
+
101
+ end
102
+
103
+ def send_email(to,data, opts={})
104
+ gmail_id = ask("Enter your gmail account: ")
105
+ pass = ask("Enter your gmail password: ") { |q| q.echo = '*' }
106
+ opts[:from] = gmail_id
107
+ opts[:server] ||= 'smtp.gmail.com'
108
+ opts[:from_alias] ||= gmail_id
109
+ opts[:subject] ||= @subject
110
+ opts[:body] ||= data
111
+ opts[:to] ||= to
112
+ opts[:port] ||= 587
113
+ msg = <<END_OF_MESSAGE
114
+ From: #{opts[:from_alias]} <#{opts[:from]}>
115
+ To: <#{to}>
116
+ Subject: #{opts[:subject]}
117
+ Date: #{Time.now.rfc2822}
118
+
119
+ #{opts[:body]}
120
+ END_OF_MESSAGE
121
+
122
+ smtp = Net::SMTP.new(opts[:server],opts[:port])
123
+ smtp.enable_starttls
124
+ smtp.start(opts[:server],gmail_id,pass,:login) do
125
+ smtp.send_message(msg, gmail_id, to)
126
+ end
127
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.7.0
data/lib/rubyipmi.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'rubyipmi/ipmitool/connection'
2
2
  require 'rubyipmi/freeipmi/connection'
3
- require 'net/smtp'
4
3
 
5
4
 
6
5
  module Rubyipmi
@@ -9,7 +8,7 @@ module Rubyipmi
9
8
  # The connect method will create a connection object based the provider type passed in
10
9
  # If provider is left blank the function will use the first available provider
11
10
 
12
- def self.connect(user, pass, host, provider="any")
11
+ def self.connect(user, pass, host, provider="any",debug=false)
13
12
 
14
13
  # use this variable to reduce cmd calls
15
14
  installed = false
@@ -30,9 +29,9 @@ module Rubyipmi
30
29
  # If the provider is available create a connection object
31
30
  if installed or is_provider_installed?(provider)
32
31
  if provider == "freeipmi"
33
- @conn = Rubyipmi::Freeipmi::Connection.new(user, pass, host)
32
+ @conn = Rubyipmi::Freeipmi::Connection.new(user, pass, host, debug)
34
33
  elsif provider == "ipmitool"
35
- @conn = Rubyipmi::Ipmitool::Connection.new(user,pass,host)
34
+ @conn = Rubyipmi::Ipmitool::Connection.new(user,pass,host, debug)
36
35
  else
37
36
  raise "Incorrect provider given, must use freeipmi or ipmitool"
38
37
  end
@@ -48,17 +47,27 @@ module Rubyipmi
48
47
  raise "No Connection available, please use the connect method"
49
48
  end
50
49
 
50
+ # method used to find the command which also makes it easier to mock with
51
+ def self.locate_command(commandname)
52
+ location = `which #{commandname}`.strip
53
+ if not $?.success?
54
+ location = nil
55
+ end
56
+ return location
57
+ end
58
+
51
59
  # Return true or false if the provider is available
52
60
  def self.is_provider_installed?(provider)
53
61
  case provider
54
62
  when "freeipmi"
55
- cmdpath = `which ipmipower`.strip
63
+ cmdpath = locate_command('ipmipower')
56
64
  when "ipmitool"
57
- cmdpath = `which ipmitool`.strip
65
+ cmdpath = locate_command('ipmitool')
58
66
  else
59
67
  raise "Invalid BMC provider type"
60
68
  end
61
- return $?.success?
69
+ # return false if command was not found
70
+ return ! cmdpath.nil?
62
71
  end
63
72
 
64
73
  def self.providers
@@ -80,12 +89,25 @@ module Rubyipmi
80
89
  return available
81
90
  end
82
91
 
83
- def self.printdiag(user, pass, host)
84
- @conn = Rubyipmi::connect(user, pass, host)
85
- puts "Product: #{@conn.fru.product}"
86
- puts "Manufacturer: #{@conn.fru.manufacturer}"
87
- puts "BMC Info #{@conn.bmc.info.inspect}\n"
88
- puts "Please email to corey@logicminds.biz when troubleshooting"
89
- return true
92
+ # gets data from the bmc device and puts in a hash for diagnostics
93
+ def self.get_diag(user, pass, host)
94
+ data = {}
95
+
96
+ if Rubyipmi.is_provider_installed?('freeipmi')
97
+ @freeconn = Rubyipmi::connect(user, pass, host, 'freeipmi')
98
+ if @freeconn
99
+ puts "Retrieving freeipmi data"
100
+ data['freeipmi'] = @freeconn.get_diag
101
+ end
102
+ end
103
+ if Rubyipmi.is_provider_installed?('ipmitool')
104
+ @ipmiconn = Rubyipmi::connect(user, pass, host, 'ipmitool')
105
+ if @ipmiconn
106
+ puts "Retrieving ipmitool data"
107
+ data['ipmitool'] = @ipmiconn.get_diag
108
+ end
109
+ end
110
+ return data
90
111
  end
112
+
91
113
  end
@@ -5,11 +5,9 @@ module Rubyipmi
5
5
 
6
6
  class BaseCommand
7
7
  include Observable
8
-
9
-
10
- attr_reader :cmd
11
- attr_accessor :options
12
- attr_reader :lastcall
8
+ attr_reader :cmd, :max_retry_count
9
+ attr_accessor :options, :passfile
10
+ attr_reader :lastcall, :result
13
11
 
14
12
  def makecommand
15
13
  # override in subclass
@@ -17,170 +15,110 @@ module Rubyipmi
17
15
 
18
16
  def setpass
19
17
  @passfile = Tempfile.new('')
20
- @passfile.open
21
18
  end
22
19
 
23
20
  def removepass
24
- @passfile.close!
21
+ @passfile.unlink
25
22
  end
26
23
 
27
- def to_s
24
+ def dump_command
28
25
  makecommand
29
26
  end
30
27
 
31
28
  def initialize(commandname, opts = ObservableHash.new)
32
29
  # This will locate the command path or raise an error if not found
33
30
  @cmdname = commandname
34
- @cmd = `which #{commandname}`.strip
31
+ @options = opts
32
+ @options.add_observer(self)
33
+ end
34
+
35
+ def locate_command(commandname)
36
+ location = `which #{commandname}`.strip
35
37
  if not $?.success?
36
38
  raise "#{commandname} command not found, is #{commandname} installed?"
37
39
  end
38
- @options = opts
39
- @options.add_observer(self)
40
+ return location
40
41
  end
41
42
 
42
43
  # Use this function to run the command line tool, it will inherently use the options hash for all options
43
44
  # That need to be specified on the command line
44
45
  def runcmd(debug=false)
45
46
  @success = false
46
-
47
- result = catch(:ipmierror){
48
- @success = run(debug)
49
- }
50
- # if error occurs try and find the fix
51
- if result and not @success
52
- findfix(result, nil, debug, "runcmd")
47
+ @success = run(debug)
48
+ if ENV['rubyipmi_debug'] == 'true'
49
+ puts @lastcall.inspect unless @lastcall.nil?
53
50
  end
54
51
  return @success
55
-
56
-
57
52
  end
58
53
 
54
+ def run(debug=false)
55
+ # we search for the command everytime just in case its removed during execution
56
+ # we also don't want to add this to the initialize since mocking is difficult and we don't want to
57
+ # throw errors upon object creation
58
+ retrycount = 0
59
+ process_status = false
60
+ @cmd = locate_command(@cmdname)
61
+ setpass
62
+ @result = nil
63
+ if debug
64
+ # Log error
65
+ return makecommand
66
+ end
59
67
 
60
- def runcmd_without_opts(args=[], debug=false)
61
-
62
- @success = false
63
- result = catch(:ipmierror){
64
- @success = run_without_opts(args, debug)
68
+ begin
69
+ command = makecommand
70
+ @lastcall = "#{command}"
71
+ @result = `#{command} 2>&1`
72
+ # sometimes the command tool does not return the correct result so we have to validate it with additional
73
+ # code
74
+ process_status = validate_status($?)
75
+ rescue
76
+ if retrycount < max_retry_count
77
+ find_fix(@result)
78
+ retrycount = retrycount.next
79
+ retry
80
+ else
81
+ raise "Exhausted all auto fixes, cannot determine what the problem is"
82
+ end
83
+ ensure
84
+ removepass
85
+ return process_status
65
86
 
66
- }
67
- # if error occurs try and find the fix and rerun the method
68
- if result and not @success
69
- findfix(result, args, debug, "runcmd_with_args")
70
87
  end
71
- return @success
88
+
72
89
  end
73
90
 
74
91
  # The findfix method acts like a recursive method and applies fixes defined in the errorcodes
75
92
  # If a fix is found it is applied to the options hash, and then the last run command is retried
76
93
  # until all the fixes are exhausted or a error not defined in the errorcodes is found
77
- def findfix(result, args, debug, runmethod)
94
+ # this must be overrided in the subclass, as there are no generic errors that fit both providers
95
+ def find_fix(result)
78
96
  if result
79
97
  # The errorcode code hash contains the fix
80
- fix = ErrorCodes.code[result]
81
- if not fix
82
- raise "#{result}"
83
- else
98
+ begin
99
+ fix = ErrorCodes.search(result)
84
100
  @options.merge_notify!(fix)
85
- # retry the last called method
86
- # its quicker to explicitly call these commands than calling a command block
87
- if runmethod == "run"
88
- run(debug)
89
- else
90
- run_without_opts(args, debug)
91
- end
92
101
 
102
+ rescue
103
+ raise "Could not find fix for error code: \n#{result}"
93
104
  end
94
-
95
- end
96
- end
97
-
98
-
99
- def run(debug=false)
100
- setpass
101
- @result = nil
102
- command = makecommand
103
- if debug
104
- return command
105
- end
106
-
107
- @lastcall = "#{command}"
108
- @result = `#{command} 2>&1`
109
- removepass
110
- #puts "Last Call: #{@lastcall}"
111
-
112
- # sometimes the command tool doesnt return the correct result
113
- process_status = validate_status($?)
114
-
115
- if not process_status
116
- throwError
117
105
  end
118
- return process_status
119
- end
120
-
121
-
122
-
123
- def run_without_opts(args=[], debug=false)
124
- setpass
125
- @result = ""
126
- if debug
127
- return "#{cmd} #{args.join(" ")}"
128
- else
129
- @lastcall = "#{cmd} #{args.join(" ")}"
130
- @result = `#{cmd} #{args.join(" ")} 2>&1`
131
- removepass
132
- end
133
-
134
- process_status = validate_status($?)
135
-
136
- if not process_status
137
- throwError
138
- end
139
- return process_status
140
-
141
-
142
106
  end
143
107
 
144
108
  def update(opts)
145
109
  @options.merge!(opts)
146
- #puts "Options were updated: #{@options.inspect}"
147
110
  end
148
111
 
149
-
150
-
151
-
152
- # This method will check if the results are really valid as the exit code can be misleading and incorrect
112
+ # This method will check if the results are really valid as the exit code can be misleading and incorrect
153
113
  def validate_status(exitstatus)
154
114
  # override in child class if needed
155
- return exitstatus.success?
156
-
157
- end
158
-
159
- def throwError
160
- # Find out what kind of error is happening, parse results
161
- # Check for authentication or connection issue
162
- #puts "ipmi call: #{@lastcall}"
163
-
164
- if @result =~ /timeout|timed\ out/
165
- code = "ipmi call: #{@lastcall} timed out"
166
- raise code
115
+ if ! exitstatus.success?
116
+ raise "Error occurred"
167
117
  else
168
- code = @result.split(":").last.chomp.strip if not @result.empty?
118
+ return true
169
119
  end
170
- case code
171
- when "invalid hostname"
172
- raise code
173
- when "password invalid"
174
- raise code
175
- when "username invalid"
176
- raise code
177
- else
178
- throw :ipmierror, code
179
- end
180
-
181
120
  end
182
121
 
183
122
 
184
-
185
123
  end
186
124
  end