Skip to content

Commit

Permalink
Consolr lazy load runners (#453)
Browse files Browse the repository at this point in the history
* Bit of housekeeping - fixed authors, and made .gitignore a bit better

Do not use pesimistic versioning for dependencies - all of these gems are decent
at symmantic versioning

* Load runners lazily

That is, wait until we are going to use a runner before we load it.

We have seen issues where running consolr a lot on a server will make the server run out of resourers.

We think loading runners with lots of dependencies takes a lot of resources, so I want to try to load
the runners we use more often earlier, and not load bigger, less used runners if they aren't needed.

* Version bump for consolr
  • Loading branch information
william-richard authored Jul 19, 2016
1 parent ecc62f3 commit 415efd6
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 79 deletions.
2 changes: 2 additions & 0 deletions support/ruby/consolr/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.bundle
coverage/
vendor/
16 changes: 8 additions & 8 deletions support/ruby/consolr/consolr.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require 'consolr/version'
Gem::Specification.new do |spec|
spec.name = "consolr"
spec.version = Consolr::VERSION
spec.authors = ["Will Richard", "Sashidhar Guntury"]
spec.email = ["[email protected]", "[email protected]", "[email protected]"]
spec.authors = ["Will Richard", "Sashidhar Guntury", "Felix Aronsson"]
spec.email = ["[email protected]"]
spec.summary = %q{consolr is a pure ruby wrapper over IPMI to allow Out of Band communiation with nodes.}
spec.description = %q{Consolr is a utility which speaks to Collins on our behalf and retrieves the address, username and password to connect to that node over IPMI. Passing different flags, we can performs a variety of taks on the node over IPMI. There are safeguards in place to prevent potentially catastrophic actions being performed on nodes.}
spec.homepage = "https://github.com/tumblr/collins/tree/master/support/ruby/consolr"
Expand All @@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_runtime_dependency "collins_auth", "~> 0.1.2"
spec.add_runtime_dependency "net-ping", "~> 1.7.7"
spec.add_runtime_dependency "collins_auth", "~> 0.1"
spec.add_runtime_dependency "net-ping", "~> 1.7"

spec.add_development_dependency "rake", "~> 10.4.2"
spec.add_development_dependency "rspec", "~> 3.3.0"
spec.add_development_dependency "simplecov", "~> 0.10.0"
spec.add_development_dependency "webmock", "~> 1.21.0"
spec.add_development_dependency "rake", "~> 10.4"
spec.add_development_dependency "rspec", "~> 3.3"
spec.add_development_dependency "simplecov", "~> 0.10"
spec.add_development_dependency "webmock", "~> 1.21"
end
142 changes: 72 additions & 70 deletions support/ruby/consolr/lib/consolr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,37 +97,10 @@ def start options
abort("Please pass either the hostname OR the tag but not both.")
end

if options[:runner].nil?
runners = load_runners(@config_params.fetch('runners', []))
# Default to the ipmitool runner for backwards compatibility
if runners.empty?
require 'consolr/runners/ipmitool'
runners = [Consolr::Runners::Ipmitool.new(@config_params.fetch('ipmitool', {}))]
end
else
runners = load_runners([options[:runner]])
if runners.empty?
abort('Specified runner could not be loaded. Aborting.')
end
end

# match assets like vm-67f5eh, zt-*, etc.
nodes = options[:tag] ? (collins.find :tag => options[:tag]) : (collins.find :hostname => options[:hostname])
@node = nodes.length == 1 ? nodes.first : abort("Found #{nodes.length} assets, aborting.")

# select the first runner that support the node
runner = runners.select {|runner|
runner.can_run? @node
}.first

if runner.nil?
abort("No runners available for node #{@node.hostname} (#{@node.tag})")
end

if not runner.verify @node
abort("Cannot verify asset #{@node.hostname} (#{@node.tag})")
end

selected_dangerous_actions = dangerous_actions.select { |o| options[o] }
if dangerous_assets.include?(@node.tag) and selected_dangerous_actions.any?
abort "Asset #{@node.tag} is a crucial asset. Can't ever execute dangerous actions on this asset.\n#{dangerous_body}"
Expand All @@ -137,54 +110,83 @@ def start options
abort "Cannot run dangerous commands on #{@node.hostname} (#{@node.tag} - #{@node.status}) because it is in a protected status. This can be overridden with the --force flag\n#{dangerous_body}"
end

case
when options[:console]
puts '--> Opening SOL session (type ~~. to quit)'
puts runner.console @node
when options[:kick]
puts runner.kick @node
when options[:identify]
puts runner.identify @node
when options[:sdr]
puts runner.sdr @node
when options[:log] == 'list'
puts runner.log_list @node
when options[:log] == 'clear'
puts runner.log_clear @node
when options[:on]
puts runner.on @node
when options[:off]
puts runner.off @node
when options[:soft_off]
puts runner.soft_off @node
when options[:reboot]
puts runner.reboot @node
when options[:soft_reboot]
puts runner.soft_reboot @node
when options[:status]
puts runner.status @node
when options[:sensors]
puts runner.sensors @node
when options[:get_sol_info]
puts runner.sol_info @node
else
begin
puts "specify an action"
exit 1
end
# use the command line runner, if it was provided
runner_names = [options[:runner]].compact

# if no runner specified on command line, use the runners from the config
if runner_names.empty?
runner_names = @config_params.fetch('runners', []).compact
end
end

private
def load_runners runners
runners.map {|runner|
# if neither of the above is true, default to using ipmitool
if runner_names.empty?
runner_names = ['ipmitool']
end

# select the first runner that support the node
runner_names.each do |runner_name|

# load the runner
begin
require "consolr/runners/#{runner}"
Consolr::Runners.const_get(runner.capitalize).new @config_params.fetch(runner, {})
require "consolr/runners/#{runner_name}"
runner = Consolr::Runners.const_get(runner_name.capitalize).new @config_params.fetch(runner_name, {})
rescue NameError, LoadError => e
puts "Could not load runner #{runner.capitalize}, skipping."
puts "Could not load runner #{runner_name.capitalize}, skipping."
next
end
}.compact

# if this runner can't work for this node, try the next runner
if not runner.can_run? @node
next
end

if not runner.verify @node
abort("Cannot verify asset #{@node.hostname} (#{@node.tag})")
end

# run the command!
case
when options[:console]
puts '--> Opening SOL session (type ~~. to quit)'
puts runner.console @node
when options[:kick]
puts runner.kick @node
when options[:identify]
puts runner.identify @node
when options[:sdr]
puts runner.sdr @node
when options[:log] == 'list'
puts runner.log_list @node
when options[:log] == 'clear'
puts runner.log_clear @node
when options[:on]
puts runner.on @node
when options[:off]
puts runner.off @node
when options[:soft_off]
puts runner.soft_off @node
when options[:reboot]
puts runner.reboot @node
when options[:soft_reboot]
puts runner.soft_reboot @node
when options[:status]
puts runner.status @node
when options[:sensors]
puts runner.sensors @node
when options[:get_sol_info]
puts runner.sol_info @node
else
begin
abort("specify an action")
end
end
# everything worked!
exit 0
end

# if we got here, all the runners did not work for this node
abort("No runners available for node #{@node.hostname} (#{@node.tag})")
end

end
end
2 changes: 1 addition & 1 deletion support/ruby/consolr/lib/consolr/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Consolr
VERSION = "1.1.4"
VERSION = "1.1.5"
end

0 comments on commit 415efd6

Please sign in to comment.