Module: PoolParty::Remote

Includes:
Pinger
Included in:
PoolParty, Cloud::Cloud, Pool::Pool, Provision::BootStrapper, Provision::DrConfigure, RemoterBase
Defined in:
lib/poolparty/net/remoter_base.rb,
lib/poolparty/net/remote_instance.rb,
lib/poolparty/net/remoter/connections.rb,
lib/poolparty/net/remoter/interactive.rb,
lib/poolparty/net/remoter/cloud_control.rb,
lib/poolparty/net/remoter_bases/ec2/ec2.rb,
lib/poolparty/net/remoter_bases/vmrun/vmrun.rb,
lib/poolparty/net/remoter_bases/vmrun/vmrun_instance.rb,
lib/poolparty/net/remoter_bases/ec2/ec2_remote_instance.rb

Defined Under Namespace

Classes: Ec2, Ec2RemoteInstance, RemoteInstance, RemoterBase, Vmrun, VmwareInstance

Instance Method Summary collapse

Methods included from Pinger

included

Instance Method Details

#_nodesObject

Cache the instances_by_status here



22
23
24
# File 'lib/poolparty/net/remoter/interactive.rb', line 22

def _nodes
  @_nodes ||= {}
end

#are_any_nodes_exceeding_minimum_runtime?Boolean

Returns:

  • (Boolean)


192
193
194
# File 'lib/poolparty/net/remoter/cloud_control.rb', line 192

def are_any_nodes_exceeding_minimum_runtime?
  !list_of_nodes_exceeding_minimum_runtime.blank?
end

#are_too_few_instances_running?Boolean

# Are too few instances running?

Returns:

  • (Boolean)


7
8
9
# File 'lib/poolparty/net/remoter/cloud_control.rb', line 7

def are_too_few_instances_running?
  nodes(:status => "running").size < minimum_instances.to_i
end

#are_too_many_instances_running?Boolean

# Are there more instances than allowed?

Returns:

  • (Boolean)


11
12
13
# File 'lib/poolparty/net/remoter/cloud_control.rb', line 11

def are_too_many_instances_running?
  nodes(:status => "running").size > maximum_instances.to_i
end

#commandsObject



51
52
53
# File 'lib/poolparty/net/remoter/connections.rb', line 51

def commands
  @commands ||= Array.new
end

#execute!(cmds = commands) ⇒ Object

TODO: make extendable multithreaded version



56
57
58
59
60
61
# File 'lib/poolparty/net/remoter/connections.rb', line 56

def execute!(cmds=commands)
  netssh(
    [cmds.compact.join(' && ')],
    :host=>target_host, :user=>'root')
  # commands.each {|c| run_remote(c, target_host) }
end

#is_master_running?Boolean

Is there a node that is running with the name master

Returns:

  • (Boolean)


196
197
198
# File 'lib/poolparty/net/remoter/cloud_control.rb', line 196

def is_master_running?
  !nodes(:status => "running").select {|a| a.name == "master"}.first.nil?
end

#list_of_instancesObject

Select the list of instances, either based on the neighborhoods loaded from /etc/poolparty/neighborhood.json or by the remote_base on keypair



29
30
31
32
33
34
# File 'lib/poolparty/net/remoter/interactive.rb', line 29

def list_of_instances
  return @list_of_instances if @list_of_instances
  @containing_cloud = self
  n = Neighborhoods.load_default
  @list_of_instances = (n.empty? ? _list_of_instances : n.instances)
end

#list_of_nodes_exceeding_minimum_runtimeObject

######## # TODO: deprecate methods below here (only if they are deprecate-able) ########

# Request to launch a number of instances def request_launch_new_instances(num=1)

out = []
num.times {out << launch_new_instance!(options) }
out

end def request_launch_master_instance

@inst = launch_new_instance!
wait "5.seconds"
when_no_pending_instances do
  vputs "Master has launched"
  reset!
  after_launch_master(@inst)
end

end

def after_launch_master(inst=nil)

vputs "After launch master in remoter"

end # Let’s terminate an instance that is not the master instance def request_termination_of_non_master_instance

inst = nonmaster_nonterminated_instances.last
terminate_instance!(inst.instance_id) if inst

end # Can we start a new instance? def can_start_a_new_instance?

maximum_number_of_instances_are_not_running? && list_of_pending_instances.size == 0

end # Are the maximum number of instances not running? def maximum_number_of_instances_are_not_running?

nodes(:status => "running").size < maximum_instances.to_i

end # Are the maximum number of instances running? def maximum_number_of_instances_are_running?

nodes(:status => "running").size >= maximum_instances.to_i

end # Launch new instance while waiting for the number of pending instances # to be zero before actually launching. This ensures that we only # launch one instance at a time def request_launch_one_instance_at_a_time

when_no_pending_instances { launch_new_instance! }

end

# A convenience method for waiting until all the instances have an ip # assigned to them. This is useful when shifting the ip addresses # around on the instances def when_all_assigned_ips(&block)

reset!
if list_of_nonterminated_instances.select {|a| a.ip == 'not.assigned' }.empty?          
  block.call if block
else
  vprint "."
  wait "5.seconds"
  when_all_assigned_ips(&block)
end

end def running_instance_ips

remote_instances_list.select {|inst| 
  inst.running? and inst.ip!='not.assigned'
}.collect{|n| n.ip}

end

# This will launch the minimum_instances if the minimum number of instances are not running # If the minimum number of instances are not running and if we can start a new instance def launch_minimum_number_of_instances

if can_start_a_new_instance? && !minimum_number_of_instances_are_running?         
  list_of_pending_instances.size == 0 ? request_launch_one_instance_at_a_time : wait("5.seconds")
  reset!
  launch_minimum_number_of_instances
  provision_slaves_from_n(minimum_instances.to_i)
  after_launched
end

end

def provision_slaves_from_n(num=1)

vputs "In provision_slaves_from_n: #{num}"
reset!
when_no_pending_instances do
  vputs "Waiting for 10 seconds"
  wait "10.seconds" # Give some time for ssh to startup          
  @num_instances = nodes(:status => "running").size
  vputs "(@num_instances - (num))..(@num_instances): #{(@num_instances - (num))..(@num_instances)}"
  last_instances = nonmaster_nonterminated_instances[(@num_instances - (num))..(@num_instances)]
  last_instances.each do |inst|
    vputs "Provision slave: #{inst}"
    verbose ? provisioner_for(inst).install(testing) : hide_output { provisioner_for(inst).install(testing)}
  end
  # PoolParty::Provisioner.reconfigure_master(self)
end

end



188
189
190
# File 'lib/poolparty/net/remoter/cloud_control.rb', line 188

def list_of_nodes_exceeding_minimum_runtime
  nodes(:status => "running").reject{|i| i.elapsed_runtime < minimum_runtime}
end

#masterObject

#DEPRECATE We’ll stub the ip to be the master ip for ease and accessibility def ip(i=nil)

puts "DEPRECATED:  ip will only be callable against a RemoteInstance in the next release."
i ? options[:ip] = i : (master ? master.ip : options[:ip])

end #DEPRECATE: get the master instance



10
11
12
13
# File 'lib/poolparty/net/remoter/interactive.rb', line 10

def master
  puts "DEPRECATED:  'master' is deprecated and will be removed in the next major release."
  get_instance_by_number(0)
end

#netssh(cmds = [], opts = {}) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/poolparty/net/remoter/connections.rb', line 63

def netssh(cmds=[], opts={})
  user = opts.delete(:user) || user #rescue 'root'
  host = opts.delete(:host) || target_host
  ssh_options_hash = {:keys => [keypair.full_filepath],
                      :auth_methods => 'publickey',
                      :paranoid => false
                       }.merge(opts)
  
  # Start the connection
  Net::SSH.start(host, user, ssh_options_hash) do |ssh|  
    cmds.each do |command|
      ssh.exec!(command) do |ch, stream, data|
        if stream == :stdout
         print data
        else
          $stderr.print "#{host} stderr => #{data}"
        end
      end
    end
  end
end

#nodes(hsh = {}) ⇒ Object

Select a list of instances based on their status



16
17
18
19
# File 'lib/poolparty/net/remoter/interactive.rb', line 16

def nodes(hsh={})
  # _nodes[hsh] ||= 
  list_of_instances.select_with_hash(hsh)
end

#remote_rsync_commandObject



128
129
130
# File 'lib/poolparty/net/remoter/connections.rb', line 128

def remote_rsync_command
  "rsync -azP --exclude cache -e '#{remote_ssh_string}'"
end

#remote_ssh_arrayObject



122
123
124
# File 'lib/poolparty/net/remoter/connections.rb', line 122

def remote_ssh_array
  ["-o StrictHostKeyChecking=no", "-l '#{Default.user}'", '-i "'+remote_keypair_path+'"']
end

#remote_ssh_stringObject



125
126
127
# File 'lib/poolparty/net/remoter/connections.rb', line 125

def remote_ssh_string
  (["ssh"] << remote_ssh_array).join(" ")
end

#rsync(source_path, destination_path, rsync_opts = ['-v -a']) ⇒ Object



39
40
41
42
43
# File 'lib/poolparty/net/remoter/connections.rb', line 39

def rsync( source_path, destination_path, rsync_opts=['-v -a'] )
  dputs "rsync -e 'ssh #{ssh_options}' #{rsync_opts.join(' ')} #{source_path}  root@#{target_host}:#{destination_path}"
  out = %x{ rsync -e 'ssh #{ssh_options}' #{rsync_opts.join(' ')} #{source_path}  root@#{target_host}:#{destination_path} }
  puts out if debugging?
end

#rsync_commandObject



119
120
121
# File 'lib/poolparty/net/remoter/connections.rb', line 119

def rsync_command
  "rsync -azP --exclude cache -e '#{ssh_string} -l #{Default.user}'"
end

#rsync_storage_files_to(instance = nil) ⇒ Object

Rsync command to the instance



145
146
147
# File 'lib/poolparty/net/remoter/connections.rb', line 145

def rsync_storage_files_to(instance=nil)
  hide_output {Kernel.system "#{rsync_storage_files_to_command(instance)}" if instance}
end

#rsync_storage_files_to_command(remote_instance) ⇒ Object

TODO: Delete deprecated commands below here



89
90
91
92
# File 'lib/poolparty/net/remoter/connections.rb', line 89

def rsync_storage_files_to_command(remote_instance)
  #TODO: rsync_to_command("#{Default.storage_directory}/", Default.remote_storage_path, remote_storage_path) if remote_instance
  "#{rsync_command} #{Default.storage_directory}/ #{remote_instance.ip}:#{Default.remote_storage_path}" if remote_instance
end

#rsync_to(source, target = source, num = 0) ⇒ Object

Rsync a file or directory to a node. Rsync to master by default



138
139
140
141
142
# File 'lib/poolparty/net/remoter/connections.rb', line 138

def rsync_to(source, target=source, num=0)
  str = "#{rsync_to_command(source, target, get_instance_by_number( num ))}"
  dputs "Running: #{str}"
  verbose ?  Kernel.system(str) : hide_output {Kernel.system str}
end

#rsync_to_command(source, target = source, remote_instance = master) ⇒ Object

rsync a file to a node. By default to the master node.



94
95
96
# File 'lib/poolparty/net/remoter/connections.rb', line 94

def rsync_to_command(source, target=source, remote_instance=master)
  "#{rsync_command} #{source} #{remote_instance.ip}:#{target}"
end

#run_command_on(cmd, instance = nil) ⇒ Object

Take the rsync command and execute it on the system if there is an instance given



150
151
152
# File 'lib/poolparty/net/remoter/connections.rb', line 150

def run_command_on(cmd, instance=nil)        
  Kernel.system "#{run_command_on_command(cmd, instance)}"
end

#run_command_on_command(cmd = "ls -l", remote_instance = nil) ⇒ Object



97
98
99
100
# File 'lib/poolparty/net/remoter/connections.rb', line 97

def run_command_on_command(cmd="ls -l", remote_instance=nil)
  vputs "Running #{cmd} on #{remote_instance.name == %x[hostname].chomp ? "self (master)" : "#{remote_instance.name}"}"
  (remote_instance.nil? || remote_instance.name == %x[hostname].chomp) ? %x[#{cmd}] : "#{ssh_command(remote_instance)} '#{cmd}'"
end

#run_command_on_instance_number(cmd = "ls -l", num = 0) ⇒ Object

Run command on the instance by the number



167
168
169
# File 'lib/poolparty/net/remoter/connections.rb', line 167

def run_command_on_instance_number(cmd="ls -l", num=0)
  run_command_on(cmd, get_instance_by_number( num ) )
end

#run_local(commands) ⇒ Object



45
46
47
48
49
# File 'lib/poolparty/net/remoter/connections.rb', line 45

def run_local(commands)
  commands.each do |cmd|
    puts `#{cmd}`
  end
end

#run_remote(hst, cmds) ⇒ Object



22
23
24
# File 'lib/poolparty/net/remoter/connections.rb', line 22

def run_remote( hst, cmds )
  netssh hst, cmds
end

#scp_arrayObject



116
117
118
# File 'lib/poolparty/net/remoter/connections.rb', line 116

def scp_array
  ["-o StrictHostKeyChecking=no", '-i "'+full_keypair_path+'"']
end

#scp_to_command(source, dest = target, remote_instance = master) ⇒ Object



132
133
134
135
# File 'lib/poolparty/net/remoter/connections.rb', line 132

def scp_to_command(source, dest=target, remote_instance=master)
  #TODO: check if source is Directory and add -r if it is
  "scp #{source} #{remote_instance.ip}:#{dest} #{scp_array.join(' ')}"
end

#simplest_run_remote(host = target_host, command = [], extra_ssh_ops = {}) ⇒ Object

Simply shell out and call ssh, simple, reliable and fewest dependencies, but slow



15
16
17
18
19
20
# File 'lib/poolparty/net/remoter/connections.rb', line 15

def simplest_run_remote(host=target_host, command=[], extra_ssh_ops={})
  command = command.compact.join(' && ') if command.is_a? Array
  cmd = "ssh #{host} #{ssh_options(extra_ssh_ops)} '#{command}'"
  puts "\n--------------------------------\nrunning_remote:\n #{cmd}\n"
  puts %x{#{cmd}}
end

#ssh_arrayObject

Array of ssh options Includes StrictHostKeyChecking to no Ssh with the user in Base And including the keypair_path “-l ‘#Default.user’”,



113
114
115
# File 'lib/poolparty/net/remoter/connections.rb', line 113

def ssh_array
  ["-o StrictHostKeyChecking=no", "-l #{Default.user}", '-i "'+full_keypair_path+'"']
end

#ssh_command(remote_instance) ⇒ Object



101
102
103
# File 'lib/poolparty/net/remoter/connections.rb', line 101

def ssh_command(remote_instance)
  "#{ssh_string} #{remote_instance.ip}"
end

#ssh_into(inst, extra_ssh_ops = {}) ⇒ Object



26
27
28
29
# File 'lib/poolparty/net/remoter/connections.rb', line 26

def ssh_into(inst, extra_ssh_ops={} )
  ip =  ((inst.respond_to?(:has_key) && inst.has_key?(:ip)) || inst.respond_to?(:ip)) ? inst.ip : inst
  Kernel.system("ssh #{ssh_options(extra_ssh_ops)} #{ip}")
end

#ssh_into_instance_number(num = 0) ⇒ Object

Ssh into the instance given def ssh_into(instance)

cmd = "#{ssh_command(instance)}"
vputs "Running #{cmd}"
Kernel.system cmd if instance

end Find the instance by the number given and then ssh into the instance



162
163
164
# File 'lib/poolparty/net/remoter/connections.rb', line 162

def ssh_into_instance_number(num=0)
  ssh_into( get_instance_by_number( num ) )
end

#ssh_options(opts = {}) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/poolparty/net/remoter/connections.rb', line 31

def ssh_options(opts={})
  o = {"-i" => keypair.full_filepath,
       "-l" => user,
       "-o" =>"StrictHostKeyChecking=no"
       }.merge(opts)
  o.collect{ |k,v| "#{k} #{v}"}.join(' ')
end

#ssh_stringObject

Generic commandable strings



105
106
107
# File 'lib/poolparty/net/remoter/connections.rb', line 105

def ssh_string
  (["ssh"] << ssh_array).join(" ")
end

#target_host(dns_or_ip = nil) ⇒ Object



10
11
12
# File 'lib/poolparty/net/remoter/connections.rb', line 10

def target_host(dns_or_ip=nil)
  dns_or_ip ? @target_host=dns_or_ip : @target_host
end