Module: SshHax

Included in:
Server, ServerInternal
Defined in:
lib/rest_connection/ssh_hax.rb

Overview

This is a mixin module run_recipes until api support is ready for checking result of recipe run. The mixin typically used from Server#run_recipe

Constant Summary collapse

SSH_RETRY_COUNT =
3

Instance Method Summary collapse

Instance Method Details

#spot_check(command, ssh_key = nil, host_dns = self.reachable_ip) {|| ... } ⇒ Object

Yields:

  • ()


52
53
54
55
56
# File 'lib/rest_connection/ssh_hax.rb', line 52

def spot_check(command, ssh_key=nil, host_dns=self.reachable_ip, &block)
  puts "SshHax::Probe method #{__method__}() entered..."
  results = spot_check_command(command, ssh_key, host_dns)
  yield results[:output]
end

#spot_check_command(command, ssh_key = nil, host_dns = self.reachable_ip, do_not_log_result = false) ⇒ Object

returns hash of exit_status and output from command Note that “sudo” is prepended to <command> and the ‘rightscale’ user is used.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rest_connection/ssh_hax.rb', line 71

def spot_check_command(command, ssh_key=nil, host_dns=self.reachable_ip, do_not_log_result=false)
  puts "SshHax::Probe method #{__method__}() entered..."
  raise "FATAL: spot_check_command called on a server with no reachable_ip. You need to run .settings on the server to populate this attribute." unless host_dns
  connection.logger "SSHing to #{host_dns} using key(s) #{ssh_key_config(ssh_key).inspect}"
  status = nil
  output = ""
  success = false
  retry_count = 0
  while (!success && retry_count < SSH_RETRY_COUNT) do
    begin
      Net::SSH.start(host_dns, 'rightscale', :keys => ssh_key_config(ssh_key), :timeout => 60, :user_known_hosts_file => "/dev/null") do |ssh|
        cmd_channel = ssh.open_channel do |ch1|
          ch1.on_request('exit-status') do |ch, data|
            status = data.read_long
          end
          # Request a pseudo-tty, this is needed as all calls use sudo to support RightLink 5.8
          ch1.request_pty do |ch, success|
            raise "Could not obtain a pseudo-tty!" if !success
          end
          # Now execute the command with "sudo" prepended to it.
          # NOTE: The use of single quotes is required to keep Ruby from interpretting the command string passed in and messing up regex's
          sudo_command = 'sudo ' + command
          puts 'SshHax::Probe executing ' + sudo_command + '...'
          ch1.exec(sudo_command) do |ch2, success|
            unless success
              status = 1
            end
            ch2.on_data do |ch, data|
              output += data
            end
            ch2.on_extended_data do |ch, type, data|
              output += data
            end
          end
          # IMPORTANT NOTE REGARDING RUBY VERSIONS!
          #
          # In Ruby 1.9.3 the next line of code is required. In Ruby 1.8.x, block variables were introduced into the
          # scope that the block was called from. Now, in Ruby 1.9.1, blocks introduce their own scope for the block
          # parameters only. That means, when a block taking a single parameter called x is called, if there are local
          # variables x and y in scope, then any reference to the variable x within the scope refers to the new
          # variable the block parameter brings into scope. However, any reference to the variable y in the block
          # refers to the variable y in scope where the block was called.
          #
          # See http://ruby.about.com/od/newinruby191/a/blockvariscope.htm for more details.
          #
          # Without the next line of code, the while will never terminate in Ruby 1.9.3. In Ruby 1.8.7 it is
          # essentially a no-op as success will already be set to true.
          success = true
        end
      end
    rescue Exception => e
      retry_count += 1 # opening the ssh channel failed -- try again.
      connection.logger "ERROR during SSH session to #{host_dns}, retrying #{retry_count}: #{e} #{e.backtrace}"
      sleep 10
      raise e unless retry_count < SSH_RETRY_COUNT
    end
  end
  connection.logger "SSH Run: #{command} on #{host_dns}. Retry was #{retry_count}. Exit status was #{status}. Output below ---\n#{output}\n---" unless do_not_log_result
  puts "SshHax::Probe method #{__method__}() exiting..."
  return {:status => status, :output => output}
end

#spot_check_command?(command, ssh_key = nil, host_dns = self.reachable_ip) ⇒ Boolean

returns true or false based on command success

Returns:

  • (Boolean)


61
62
63
64
65
# File 'lib/rest_connection/ssh_hax.rb', line 61

def spot_check_command?(command, ssh_key=nil, host_dns=self.reachable_ip)
  puts "SshHax::Probe method #{__method__}() entered..."
  results = spot_check_command(command, ssh_key, host_dns)
  return results[:status] == 0
end

#ssh_key_config(item) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rest_connection/ssh_hax.rb', line 32

def ssh_key_config(item)
  if item.is_a?(Array)
    ssh_keys = item
  elsif item.is_a?(String)
    ssh_keys = [item]
  elsif connection_key = connection.settings[:ssh_key]
    ssh_keys = [connection_key]
  elsif connection_keys = connection.settings[:ssh_keys]
    ssh_keys = connection_keys
  else
    # If no key(s) provided, assume a standard monkey configuration which uses '/root/.ssh/api_user_key'.
    api_user_key_ssh_key_file_name = '/root/.ssh/api_user_key'
    raise "FATAL ERROR: #{api_user_key_ssh_key_file_name} does not exist." if !File.exist?(api_user_key_ssh_key_file_name)
    ssh_keys = [api_user_key_ssh_key_file_name]
  end
  ssh_keys
end