class Pvcglue::Connection

TODO:  Check ssh config
 https://puppet.com/blog/speed-up-ssh-by-reusing-connections
~/.ssh/config

Host * ControlMaster auto

ControlPath ~/.ssh/sockets/%r@%h-%p

ControlPath ~/.ssh/%r@%h-%p ControlPersist 600

Way Faster!!!

Attributes

minion[RW]
minion_state_data[RW]

Public Class Methods

new(minion) click to toggle source
# File lib/pvcglue/connection.rb, line 15
def initialize(minion)
  @minion = minion
end

Public Instance Methods

chmod(user, remote, permissions, options = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 230
def chmod(user, remote, permissions, options = nil)
  ssh!(user, '', "chmod #{options} #{permissions} #{remote}")
end
chown(user, remote, owner, group, options = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 226
def chown(user, remote, owner, group, options = nil)
  ssh!(user, '', "chown #{options} #{owner}:#{group} #{remote}")
end
chown_chmod(user, remote, owner, group, permissions = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 216
def chown_chmod(user, remote, owner, group, permissions = nil)
  unless owner.nil? && group.nil?
    raise('Invalid owner or group for chown') if owner.nil? || group.nil?
    chown(user, remote, owner, group)
  end
  unless permissions.nil?
    chmod(user, remote, permissions)
  end
end
download_file(user, remote_file, local_file, raise_error = true) click to toggle source
# File lib/pvcglue/connection.rb, line 198
def download_file(user, remote_file, local_file, raise_error = true)

  cmd = %{scp #{scp_quiet_option}#{user}@#{minion.public_ip}:#{remote_file} #{local_file}}
  if raise_error
    system_command!(cmd)
  else
    system_command?(cmd)
  end
end
escape_ssh_command(cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 45
def escape_ssh_command(cmd)
  # cmd.gsub(/'/, "\\'")
  # cmd.gsub(/'/) { |match| "\\#{match}" }
  # cmd.gsub(/'/) { |match| '\\' + match } # "CREATEDB PASSWORD 'monkey'" #=> "CREATEDB PASSWORD \'monkey\'"
  # if cmd.include?("'") || cmd.include?('"')
  # # if cmd.include?('"')
  #   # "<<'EOF'\n#{cmd}\nEOF"
  #   # cmd.gsub(/'/) { |match| %Q('"'"') }
  #   # "$'" + cmd.gsub(/'/) { |match| '\\' + match } + "'"
  #   '"' + cmd.gsub(/"/) { |match| '\\' + match } + '"'
  # else
  #   "'#{cmd}'"
  # end
  # Another possible solution:  http://stackoverflow.com/a/21761956/444774
  '"' + cmd.gsub(/"/) { |match| '\\' + match } + '"'
end
file_exists?(user, file) click to toggle source
# File lib/pvcglue/connection.rb, line 22
def file_exists?(user, file)
  result = ssh?(user, '', "test -e #{file}")
  result.exitstatus == 0
end
file_matches?(user, data, remote_file) click to toggle source
# File lib/pvcglue/connection.rb, line 234
def file_matches?(user, data, remote_file)
  # NOTE:  This could be optimized
  return false unless file_exists?(user, remote_file)
  read_from_file(user, remote_file) == data
end
mkdir_p(user, remote_dir, owner = nil, group = nil, permissions = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 27
def mkdir_p(user, remote_dir, owner = nil, group = nil, permissions = nil)
  ssh!(user, '', "mkdir -p #{remote_dir}")
  chown_chmod(user, remote_dir, owner, group, permissions)
end
read_from_file(user, file) click to toggle source
# File lib/pvcglue/connection.rb, line 132
def read_from_file(user, file)
  tmp_file = Tempfile.new('pvc')
  begin
    download_file(user, file, tmp_file.path)
    data = tmp_file.read
    Pvcglue.verbose? { data }
  ensure
    tmp_file.close
    tmp_file.unlink # deletes the temp file
  end
  data
end
read_from_file_if_exists?(user, file) click to toggle source
# File lib/pvcglue/connection.rb, line 145
def read_from_file_if_exists?(user, file)
  tmp_file = Tempfile.new('pvc')
  begin
    result = download_file(user, file, tmp_file.path, false)
    if result.exitstatus == 0
      data = tmp_file.read
    elsif result.exitstatus == 1
      data = nil
    else
      raise $?.inspect
    end
    Pvcglue.verbose? { data }
  ensure
    tmp_file.close
    tmp_file.unlink # deletes the temp file
  end
  data

end
rsync_up(user, options, local_source_dir, remote_destination_dir, mkdir = true) click to toggle source
# File lib/pvcglue/connection.rb, line 240
def rsync_up (user, options, local_source_dir, remote_destination_dir, mkdir = true)
  mkdir_p(user, remote_destination_dir) if mkdir
  cmd = ''
  # cmd += "mkdir -p #{remote_destination_dir} && "
  cmd += %(rsync #{options} #{local_source_dir}/ #{user}@#{minion.public_ip}:#{remote_destination_dir}/)
  # cmd = (%(rsync -rzv --exclude=maintenance.on --delete -e 'ssh -p #{Pvcglue.cloud.port_in_node_context}' #{source_dir}/ #{node.get(:user)}@#{node.host}:#{dest_dir}/))
  system_command!(cmd)
end
run!(user, options, cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 104
def run!(user, options, cmd)
  ssh!(user, options, cmd)
end
run?(user, options, cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 108
def run?(user, options, cmd)
  ssh?(user, options, cmd)
  # puts user.inspect
  # cmd = 'pwd'
  # full_command = "ssh root@#{minion.public_ip} '#{cmd}'"
  # full_command = "ssh root@#{minion.public_ip} 'ls -ahl'"
  # puts "running:  #{full_command}"
  # puts `#{full_command}`
  # 1.times do
  # 100.times do
  # puts "running:  #{full_command}"
  # puts `#{full_command}`
  # puts `ls -ahl ~/.ssh/config`
  # system %Q(ssh root@#{minion.public_ip} -o strictHostKeyChecking=no -t 'pwd')
  # ap system %Q(ssh root@#{minion.public_ip} 'test -e test')
  # ap system %Q(ssh root@#{minion.public_ip} -t 'test -e test')
  # ap $?
  # ap system %Q(ssh root@#{minion.public_ip} 'test -e .bashrc')
  # ap $?
  # ap file_exists?(:root, 'test')
  # ap file_exists?(:root, '.bashrc')
  # end
end
run_get_stdout(user, options, cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 89
def run_get_stdout(user, options, cmd)
  full_cmd = "ssh #{user}@#{minion.public_ip} #{options} #{escape_ssh_command(cmd)}"
  Pvcglue.logger.debug { full_cmd }
  result = `#{full_cmd}`
  Pvcglue.verbose? { result }
  Pvcglue.logger.debug { "exit_code=#{$?.to_i}" }
  result
end
run_get_stdout!(user, options, cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 98
def run_get_stdout!(user, options, cmd)
  result = run_get_stdout(user, options, cmd)
  raise $?.inspect unless $?.exitstatus == 0
  result
end
scp_quiet_option() click to toggle source
# File lib/pvcglue/connection.rb, line 187
def scp_quiet_option
  case Pvcglue.logger.level
    when Logger::DEBUG # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
      ''
    when Logger::INFO
      '-q '
    else
      '-q '
  end
end
ssh!(user, options, cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 71
def ssh!(user, options, cmd)
  result = ssh?(user, options, cmd)
  raise result.inspect unless result.exitstatus == 0
end
ssh?(user, options, cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 62
def ssh?(user, options, cmd)
  # if cmd.include?("'") # DONE:  Quick fix, should be refactored to do proper escaping
  #   system_command?(%Q(ssh #{user}@#{minion.public_ip} #{options} "#{cmd}"))
  # else
  #   system_command?(%Q(ssh #{user}@#{minion.public_ip} #{options} '#{cmd}'))
  # end
  system_command?(%Q(ssh #{user}@#{minion.public_ip} #{options} #{escape_ssh_command(cmd)}))
end
ssh_retry_wait(user, options, cmd, times, wait) click to toggle source
# File lib/pvcglue/connection.rb, line 32
def ssh_retry_wait(user, options, cmd, times, wait)
  tries = 0
  begin
    result = ssh?(user, options, cmd)
    unless result.exitstatus == 0
      Pvcglue.logger.info("Command `#{cmd}` failed, retrying...")
      sleep(wait)
    end
    tries += 1
    raise "Exceeded #{times} retries:  #{result.inspect}" if tries >= times
  end until result.exitstatus == 0
end
system_command!(cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 84
def system_command!(cmd)
  result = system_command?(cmd)
  raise result.inspect unless result.exitstatus == 0
end
system_command?(cmd) click to toggle source
# File lib/pvcglue/connection.rb, line 76
def system_command?(cmd)
  Pvcglue.logger.debug { cmd }
  Pvcglue.docs.log_cmd(cmd)
  system(cmd)
  Pvcglue.logger.debug { "exit_code=#{$?.exitstatus}" }
  $?
end
upload_file(user, local_file, remote_file, owner = nil, group = nil, permissions = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 208
def upload_file(user, local_file, remote_file, owner = nil, group = nil, permissions = nil)
  if Pvcglue.command_line_options[:save_before_upload] && file_exists?(user, remote_file)
    download_file(user, remote_file, Pvcglue.configuration.build_log_extra_filename(minion, user, remote_file))
  end
  system_command!(%{scp #{local_file} #{user}@#{minion.public_ip}:#{remote_file}})
  chown_chmod(user, remote_file, owner, group, permissions)
end
write_to_file(user, data, file, owner = nil, group = nil, permissions = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 173
def write_to_file(user, data, file, owner = nil, group = nil, permissions = nil)
  Pvcglue.docs.log_file_write(user: user, style: :shell, data: data, file: file, owner: owner, group: group, permissions: permissions)
  tmp_file = Tempfile.new('pvc')
  begin
    tmp_file.write(data)
    tmp_file.flush
    upload_file(user, tmp_file.path, file, owner, group, permissions)
    Pvcglue.verbose? { data }
  ensure
    tmp_file.close
    tmp_file.unlink # deletes the temp file
  end
end
write_to_file_from_template(user, template_file_name, file, locals = nil, owner = nil, group = nil, permissions = nil) click to toggle source
# File lib/pvcglue/connection.rb, line 165
def write_to_file_from_template(user, template_file_name, file, locals = nil, owner = nil, group = nil, permissions = nil)
  Pvcglue.logger.debug { "Writing to #{file} from template '#{template_file_name}'" }
  template = Tilt.new(Pvcglue.template_file_name(template_file_name))
  data = template.render(self, {minion: minion}.merge(locals || {}))

  write_to_file(user, data, file, owner, group, permissions)
end