auser-poolparty 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/Manifest +115 -0
- data/README.txt +140 -0
- data/Rakefile +27 -0
- data/bin/instance +61 -0
- data/bin/pool +62 -0
- data/config/cloud_master_takeover +17 -0
- data/config/create_proxy_ami.sh +582 -0
- data/config/haproxy.conf +29 -0
- data/config/heartbeat.conf +8 -0
- data/config/heartbeat_authkeys.conf +2 -0
- data/config/installers/ubuntu_install.sh +77 -0
- data/config/monit/haproxy.monit.conf +7 -0
- data/config/monit/nginx.monit.conf +0 -0
- data/config/monit.conf +9 -0
- data/config/nginx.conf +24 -0
- data/config/reconfigure_instances_script.sh +18 -0
- data/config/sample-config.yml +23 -0
- data/config/scp_instances_script.sh +12 -0
- data/lib/core/array.rb +13 -0
- data/lib/core/exception.rb +9 -0
- data/lib/core/float.rb +13 -0
- data/lib/core/hash.rb +11 -0
- data/lib/core/kernel.rb +12 -0
- data/lib/core/module.rb +22 -0
- data/lib/core/object.rb +18 -0
- data/lib/core/proc.rb +15 -0
- data/lib/core/string.rb +49 -0
- data/lib/core/time.rb +41 -0
- data/lib/modules/callback.rb +133 -0
- data/lib/modules/ec2_wrapper.rb +82 -0
- data/lib/modules/safe_instance.rb +31 -0
- data/lib/modules/vlad_override.rb +82 -0
- data/lib/poolparty/application.rb +170 -0
- data/lib/poolparty/init.rb +6 -0
- data/lib/poolparty/master.rb +329 -0
- data/lib/poolparty/monitors/cpu.rb +19 -0
- data/lib/poolparty/monitors/memory.rb +26 -0
- data/lib/poolparty/monitors/web.rb +23 -0
- data/lib/poolparty/monitors.rb +13 -0
- data/lib/poolparty/optioner.rb +16 -0
- data/lib/poolparty/plugin.rb +43 -0
- data/lib/poolparty/plugin_manager.rb +67 -0
- data/lib/poolparty/provider/packages/essential.rb +6 -0
- data/lib/poolparty/provider/packages/git.rb +4 -0
- data/lib/poolparty/provider/packages/haproxy.rb +20 -0
- data/lib/poolparty/provider/packages/heartbeat.rb +4 -0
- data/lib/poolparty/provider/packages/monit.rb +6 -0
- data/lib/poolparty/provider/packages/rsync.rb +4 -0
- data/lib/poolparty/provider/packages/ruby.rb +37 -0
- data/lib/poolparty/provider/packages/s3fuse.rb +11 -0
- data/lib/poolparty/provider/provider.rb +60 -0
- data/lib/poolparty/provider.rb +2 -0
- data/lib/poolparty/remote_instance.rb +216 -0
- data/lib/poolparty/remoter.rb +106 -0
- data/lib/poolparty/remoting.rb +112 -0
- data/lib/poolparty/scheduler.rb +103 -0
- data/lib/poolparty/tasks/cloud.rake +57 -0
- data/lib/poolparty/tasks/development.rake +38 -0
- data/lib/poolparty/tasks/ec2.rake +20 -0
- data/lib/poolparty/tasks/instance.rake +63 -0
- data/lib/poolparty/tasks/plugins.rake +30 -0
- data/lib/poolparty/tasks/server.rake +42 -0
- data/lib/poolparty/tasks.rb +29 -0
- data/lib/poolparty/tmp.rb +46 -0
- data/lib/poolparty.rb +105 -0
- data/lib/s3/s3_object_store_folders.rb +44 -0
- data/misc/basics_tutorial.txt +142 -0
- data/poolparty.gemspec +72 -0
- data/spec/application_spec.rb +39 -0
- data/spec/callback_spec.rb +194 -0
- data/spec/core_spec.rb +15 -0
- data/spec/helpers/ec2_mock.rb +44 -0
- data/spec/kernel_spec.rb +11 -0
- data/spec/master_spec.rb +203 -0
- data/spec/monitors/cpu_monitor_spec.rb +38 -0
- data/spec/monitors/memory_spec.rb +50 -0
- data/spec/monitors/misc_monitor_spec.rb +50 -0
- data/spec/monitors/web_spec.rb +39 -0
- data/spec/optioner_spec.rb +22 -0
- data/spec/plugin_manager_spec.rb +31 -0
- data/spec/plugin_spec.rb +101 -0
- data/spec/pool_binary_spec.rb +10 -0
- data/spec/poolparty_spec.rb +15 -0
- data/spec/provider_spec.rb +17 -0
- data/spec/remote_instance_spec.rb +149 -0
- data/spec/remoter_spec.rb +65 -0
- data/spec/remoting_spec.rb +84 -0
- data/spec/scheduler_spec.rb +75 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/string_spec.rb +28 -0
- data/web/static/conf/nginx.conf +22 -0
- data/web/static/site/images/balloon.png +0 -0
- data/web/static/site/images/cb.png +0 -0
- data/web/static/site/images/clouds.png +0 -0
- data/web/static/site/images/railsconf_preso_img.png +0 -0
- data/web/static/site/index.html +71 -0
- data/web/static/site/javascripts/application.js +3 -0
- data/web/static/site/javascripts/corner.js +178 -0
- data/web/static/site/javascripts/jquery-1.2.6.pack.js +11 -0
- data/web/static/site/misc.html +42 -0
- data/web/static/site/storage/pool_party_presentation.pdf +0 -0
- data/web/static/site/stylesheets/application.css +100 -0
- data/web/static/site/stylesheets/reset.css +17 -0
- data/web/static/src/layouts/application.haml +25 -0
- data/web/static/src/pages/index.haml +25 -0
- data/web/static/src/pages/misc.haml +5 -0
- data/web/static/src/stylesheets/application.sass +100 -0
- metadata +260 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Allow for plugins based in callbacks
|
3
|
+
|
4
|
+
A plugin should be able to hook into any method and run their command
|
5
|
+
either before or after the plugin.
|
6
|
+
=end
|
7
|
+
module PoolParty
|
8
|
+
class Plugin
|
9
|
+
|
10
|
+
# Create a class-level method for the name on the class
|
11
|
+
# For instance:
|
12
|
+
# create_methods :install, RemoteInstance
|
13
|
+
# will give the following methods to the class
|
14
|
+
# before_install and after_install on the RemoteInstance
|
15
|
+
def self.create_methods(name, klass)
|
16
|
+
str = ""
|
17
|
+
%w(before after).each do |time|
|
18
|
+
str << <<-EOE
|
19
|
+
def self.#{time}_#{name}(*meth)
|
20
|
+
callee = self
|
21
|
+
#{klass}.class_eval do
|
22
|
+
meth.each {|m| #{time} :#{name}, {m.to_sym => callee.to_s}}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
EOE
|
26
|
+
end
|
27
|
+
eval str
|
28
|
+
end
|
29
|
+
|
30
|
+
%w(install configure associate_public_ip become_master).each do |method|
|
31
|
+
create_methods method, RemoteInstance
|
32
|
+
end
|
33
|
+
%w(start start_monitor scale_cloud reconfiguration add_instance terminate_instance check_stats).each do |method|
|
34
|
+
create_methods method, Master
|
35
|
+
end
|
36
|
+
%w(define_tasks).each do |method|
|
37
|
+
create_methods method, Tasks
|
38
|
+
end
|
39
|
+
%w(run_tasks).each do |method|
|
40
|
+
create_methods method, Scheduler
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
A convenience method for working with plugins.
|
3
|
+
|
4
|
+
Sits on top of github.
|
5
|
+
=end
|
6
|
+
require "git"
|
7
|
+
module PoolParty
|
8
|
+
def installed_plugins
|
9
|
+
@@installed_plugins ||= PluginManager.extract_git_repos_from_plugin_dirs.uniq
|
10
|
+
end
|
11
|
+
class PluginManager
|
12
|
+
include Callbacks
|
13
|
+
|
14
|
+
def self.install_plugin(location)
|
15
|
+
unless File.directory?(plugin_directory(location))
|
16
|
+
begin
|
17
|
+
Git.clone(location, plugin_directory(location))
|
18
|
+
reset!
|
19
|
+
rescue Exception => e
|
20
|
+
puts "There was an error"
|
21
|
+
puts e
|
22
|
+
end
|
23
|
+
else
|
24
|
+
puts "Plugin already installed"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.remove_plugin(name)
|
29
|
+
Dir["#{PoolParty.root_dir}/#{PoolParty.plugin_dir}/*"].select {|a| a =~ /#{name}/}.each do |dir|
|
30
|
+
FileUtils.rm_rf dir
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.scan
|
35
|
+
returning Array.new do |a|
|
36
|
+
plugin_dirs.each do |plugin|
|
37
|
+
a << File.basename(plugin)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.extract_git_repos_from_plugin_dirs
|
43
|
+
returning [] do |arr|
|
44
|
+
plugin_dirs.each do |dir|
|
45
|
+
begin
|
46
|
+
arr << open(File.join(dir, ".git", "config")).read[/url[\s]*=[\s](.*)/,1]
|
47
|
+
rescue Exception => e
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.plugin_dirs
|
54
|
+
Dir["#{PoolParty.user_dir}/vendor/*"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.plugin_directory(path)
|
58
|
+
File.join(base_plugin_dir, File.basename(path, File.extname(path)))
|
59
|
+
end
|
60
|
+
def self.create_plugin_directory
|
61
|
+
FileUtils.mkdir_p base_plugin_dir rescue ""
|
62
|
+
end
|
63
|
+
def self.base_plugin_dir
|
64
|
+
File.join(PoolParty.root_dir, "vendor")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Install haproxy
|
2
|
+
|
3
|
+
def post_install_string
|
4
|
+
%w(
|
5
|
+
"echo 'Configuring haproxy logging'"
|
6
|
+
"sed -i 's/ENABLED=0/ENABLED=1/g' /etc/default/haproxy"
|
7
|
+
"sed -i 's/SYSLOGD=\"\"/SYSLOGD=\"-r\"/g' /etc/default/syslogd"
|
8
|
+
"echo 'local0.* /var/log/haproxy.log' >> /etc/syslog.conf && /etc/init.d/sysklogd restart"
|
9
|
+
"/etc/init.d/haproxy restart"
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
package :haproxy, :provides => :proxy do
|
14
|
+
description 'Haproxy proxy'
|
15
|
+
# version '1.2.18'
|
16
|
+
# source "http://haproxy.1wt.eu/download/1.2/src/haproxy-#{version}.tar.gz"
|
17
|
+
apt %w( haproxy )
|
18
|
+
|
19
|
+
post :install, post_install_string
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
package :ruby do
|
2
|
+
description 'Ruby Virtual Machine'
|
3
|
+
# version '1.8.6'
|
4
|
+
# source "ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-#{version}-p111.tar.gz" # implicit :style => :gnu
|
5
|
+
apt %w( ruby )
|
6
|
+
requires :ruby_dependencies
|
7
|
+
end
|
8
|
+
|
9
|
+
package :ruby_dependencies do
|
10
|
+
description 'Ruby Virtual Machine Build Dependencies'
|
11
|
+
apt %w( bison zlib1g-dev libssl-dev libreadline5-dev libncurses5-dev file )
|
12
|
+
end
|
13
|
+
|
14
|
+
package :rubygems do
|
15
|
+
description 'Ruby Gems Package Management System'
|
16
|
+
# version '1.0.1'
|
17
|
+
# source "http://rubyforge.org/frs/download.php/29548/rubygems-#{version}.tgz" do
|
18
|
+
# custom_install 'ruby setup.rb'
|
19
|
+
# end
|
20
|
+
apt %w( rubygems )
|
21
|
+
post :install, "gem update --system"
|
22
|
+
requires :ruby
|
23
|
+
end
|
24
|
+
|
25
|
+
package :poolparty_required_gems do
|
26
|
+
description "required gems"
|
27
|
+
gems %w(SQS aws-s3 amazon-ec2 aska rake)
|
28
|
+
end
|
29
|
+
|
30
|
+
package :poolparty do
|
31
|
+
description "Pool party gem"
|
32
|
+
gem "auser-pool-party" do
|
33
|
+
source 'http://gems.github.com'
|
34
|
+
end
|
35
|
+
|
36
|
+
required :poolparty_required_gems
|
37
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
package :s3fs do
|
2
|
+
description "S3 Fuse project"
|
3
|
+
source "http://s3fs.googlecode.com/files/s3fs-r166-source.tar.gz"
|
4
|
+
|
5
|
+
requires :s3fs_deps
|
6
|
+
end
|
7
|
+
|
8
|
+
package :s3fs_deps do
|
9
|
+
description "S3 Fuse project dependencies"
|
10
|
+
apt %w( libcurl4-openssl-dev libxml2-dev libfuse-dev )
|
11
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "sprinkle"
|
2
|
+
|
3
|
+
module PoolParty
|
4
|
+
class Provider
|
5
|
+
|
6
|
+
def self.install_poolparty(ips)
|
7
|
+
|
8
|
+
$:.unshift( File.dirname(__FILE__) )
|
9
|
+
|
10
|
+
load_str = []
|
11
|
+
|
12
|
+
Dir["#{File.expand_path(File.dirname(__FILE__))}/packages/*"].each {|f| load_str << open(f).read}
|
13
|
+
|
14
|
+
script=<<-EOS
|
15
|
+
|
16
|
+
#{load_str.join("\n")}
|
17
|
+
|
18
|
+
policy :poolparty, :roles => :app do
|
19
|
+
requires :git
|
20
|
+
requires :ruby
|
21
|
+
requires :monit
|
22
|
+
requires :s3fs
|
23
|
+
requires :rsync
|
24
|
+
requires :heartbeat
|
25
|
+
requires :poolparty
|
26
|
+
end
|
27
|
+
|
28
|
+
deployment do
|
29
|
+
delivery :vlad do
|
30
|
+
|
31
|
+
set :ssh_cmd, '#{RemoteInstance.ssh_string}'
|
32
|
+
|
33
|
+
#{string_roles_from_ips(ips)}
|
34
|
+
end
|
35
|
+
|
36
|
+
source do
|
37
|
+
prefix '/usr/local'
|
38
|
+
archives '/root/sources'
|
39
|
+
builds '/root/builds'
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
EOS
|
44
|
+
|
45
|
+
PoolParty.message "Installing required poolparty paraphernalia"
|
46
|
+
install_from_sprinkle_string script
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.install_from_sprinkle_string(str)
|
50
|
+
Sprinkle::Script.sprinkle str
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.string_roles_from_ips(ips)
|
54
|
+
ips.collect do |ip|
|
55
|
+
"role :app, '#{ip}'"
|
56
|
+
end.join("\n")
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
module PoolParty
|
2
|
+
class RemoteInstance
|
3
|
+
# ############################
|
4
|
+
include Remoter
|
5
|
+
# ############################
|
6
|
+
include PoolParty
|
7
|
+
include Callbacks
|
8
|
+
|
9
|
+
attr_reader :ip, :instance_id, :name, :status, :launching_time, :stack_installed
|
10
|
+
attr_accessor :name, :number, :scp_configure_file, :configure_file, :plugin_string
|
11
|
+
|
12
|
+
# CALLBACKS
|
13
|
+
after :install, :mark_installed
|
14
|
+
|
15
|
+
def initialize(obj={})
|
16
|
+
super
|
17
|
+
|
18
|
+
@ip = obj[:ip]
|
19
|
+
@instance_id = obj[:instance_id]
|
20
|
+
@name = obj[:name] || "node"
|
21
|
+
@number = obj[:number] || 0 # Defaults to the master
|
22
|
+
@status = obj[:status] || "running"
|
23
|
+
@launching_time = obj[:launching_time] || Time.now
|
24
|
+
end
|
25
|
+
|
26
|
+
# Host entry for this instance
|
27
|
+
def hosts_entry
|
28
|
+
"#{@ip} #{name}"
|
29
|
+
end
|
30
|
+
# Internal host entry for this instance
|
31
|
+
def local_hosts_entry
|
32
|
+
"127.0.0.1 #{name}\n127.0.0.1 localhost.localdomain localhost ubuntu"
|
33
|
+
end
|
34
|
+
# Node entry for heartbeat
|
35
|
+
def node_entry
|
36
|
+
"node #{name}"
|
37
|
+
end
|
38
|
+
# Internal naming scheme
|
39
|
+
def name
|
40
|
+
"#{@name}#{@number}"
|
41
|
+
end
|
42
|
+
# Entry for the heartbeat config file
|
43
|
+
def heartbeat_entry
|
44
|
+
"#{name} #{ip} #{Application.managed_services}"
|
45
|
+
end
|
46
|
+
# Entry for haproxy
|
47
|
+
def haproxy_entry
|
48
|
+
"\tserver #{name} #{@ip}:#{Application.client_port} weight 1 minconn 3 maxconn 6 check inter 20000 check"
|
49
|
+
end
|
50
|
+
def haproxy_resources_entry
|
51
|
+
"#{name} #{@ip}"
|
52
|
+
end
|
53
|
+
# Is this the master?
|
54
|
+
def master?
|
55
|
+
@number == 0
|
56
|
+
end
|
57
|
+
def secondary?
|
58
|
+
@number == 1
|
59
|
+
end
|
60
|
+
def set_hosts(c)
|
61
|
+
end
|
62
|
+
# Let's define some stuff for monit
|
63
|
+
%w(stop start restart).each do |cmd|
|
64
|
+
define_method "#{cmd}_with_monit" do
|
65
|
+
ssh("monit #{cmd} all")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# Configure the server with the new, sexy shell script
|
69
|
+
# This compiles all the scp commands into a shell script and then executes it
|
70
|
+
# then it will compile a list of the commands to operate on the instance
|
71
|
+
# and execute it
|
72
|
+
# This is how the cloud reconfigures itself
|
73
|
+
def configure(caller=nil)
|
74
|
+
associate_public_ip
|
75
|
+
scp_basic_config_files
|
76
|
+
|
77
|
+
Master.with_nodes do |node|
|
78
|
+
# These are node-specific
|
79
|
+
PoolParty.message "configuring #{node.name}"
|
80
|
+
node.scp_specific_config_files
|
81
|
+
end
|
82
|
+
configure_basics_through_ssh
|
83
|
+
end
|
84
|
+
|
85
|
+
def configure_basics_through_ssh
|
86
|
+
# -l #{Application.plugin_dir}
|
87
|
+
cmd=<<-EOC
|
88
|
+
#{update_plugin_string}
|
89
|
+
chmod 700 /etc/monit/monitrc
|
90
|
+
pool maintain -c ~/.config
|
91
|
+
hostname -v #{name}
|
92
|
+
/usr/bin/s3fs #{Application.shared_bucket} -o accessKeyId=#{Application.access_key} -o secretAccessKey=#{Application.secret_access_key} -o nonempty /data
|
93
|
+
EOC
|
94
|
+
execute_tasks do
|
95
|
+
ssh(cmd.runnable)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def scp_string(src,dest,opts={})
|
100
|
+
end
|
101
|
+
|
102
|
+
def scp_basic_config_files
|
103
|
+
cmd=<<-EOC
|
104
|
+
mkdir -p /etc/ha.d/resource.d
|
105
|
+
mkdir -p /etc/monit
|
106
|
+
mkdir -p /etc/monit.d
|
107
|
+
EOC
|
108
|
+
execute_tasks do
|
109
|
+
scp(Application.heartbeat_authkeys_config_file, "/etc/ha.d", :dir => "/etc/ha.d/resource.d")
|
110
|
+
scp(conf_file("cloud_master_takeover"), "/etc/ha.d/resource.d/cloud_master_takeover", :dir => "/etc/ha.d/resource.d/")
|
111
|
+
|
112
|
+
scp(Application.config_file, "~/.config") if Application.config_file
|
113
|
+
Dir["#{root_dir}/config/resource.d/*"].each do |file|
|
114
|
+
scp(file, "/etc/ha.d/resource.d/#{File.basename(file)}")
|
115
|
+
end
|
116
|
+
scp(Application.monit_config_file, "/etc/monit/monitrc", :dir => "/etc/monit")
|
117
|
+
Dir["#{root_dir}/config/monit.d/*"].each do |file|
|
118
|
+
scp(file, "/etc/monit.d/#{File.basename(file)}")
|
119
|
+
end
|
120
|
+
|
121
|
+
`mkdir -p tmp/`
|
122
|
+
File.open("tmp/pool-party-haproxy.cfg", 'w') {|f| f.write(Master.build_haproxy_file) }
|
123
|
+
scp("tmp/pool-party-haproxy.cfg", "/etc/haproxy.cfg")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
def scp_specific_config_files
|
127
|
+
execute_tasks({:dont_set_hosts => true}) do
|
128
|
+
if Master.requires_heartbeat?
|
129
|
+
hafile = "tmp/#{name}-pool-party-ha.cf"
|
130
|
+
File.open(hafile, 'w') {|f| f.write(Master.build_heartbeat_config_file_for(self)) }
|
131
|
+
single_scp(hafile, "/etc/ha.d/ha.cf")
|
132
|
+
|
133
|
+
haresources_file = "tmp/#{name}-pool-party-haresources"
|
134
|
+
File.open(haresources_file, 'w') {|f| f.write(Master.build_heartbeat_resources_file_for(self)) }
|
135
|
+
single_scp(haresources_file, "/etc/ha/haresources", :dir => "/etc/ha")
|
136
|
+
end
|
137
|
+
hosts_file = "tmp/#{name}-pool-party-hosts"
|
138
|
+
File.open(hosts_file, 'w') {|f| f.write(Master.build_hosts_file_for(self)) }
|
139
|
+
single_scp(hosts_file, "/etc/hosts")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Installs with one commandline and an scp, rather than 10
|
144
|
+
def install
|
145
|
+
# unless stack_installed?
|
146
|
+
# execute_tasks do
|
147
|
+
# # scp(base_install_script, "~/base_install.sh")
|
148
|
+
# ssh("chmod +x base_install.sh && /bin/sh base_install.sh && rm base_install.sh && echo 'installed!' ")
|
149
|
+
# end
|
150
|
+
# PoolParty.message "After install execute_tasks"
|
151
|
+
# mark_installed
|
152
|
+
# end
|
153
|
+
end
|
154
|
+
# Login to store the authenticity
|
155
|
+
def login_once
|
156
|
+
run_now "ls -l"
|
157
|
+
end
|
158
|
+
# Associate a public ip if it is set and this is the master
|
159
|
+
def associate_public_ip
|
160
|
+
associate_address_with(Application.public_ip, @instance_id) if master? && Application.public_ip && !Application.public_ip.empty?
|
161
|
+
end
|
162
|
+
# Become the new master
|
163
|
+
def become_master
|
164
|
+
@master = Master.new
|
165
|
+
@number = 0
|
166
|
+
@master.nodes[0] = self
|
167
|
+
configure
|
168
|
+
end
|
169
|
+
def update_plugin_string
|
170
|
+
reset!
|
171
|
+
str = "mkdir -p #{Application.plugin_dir} && cd #{Application.plugin_dir}\n"
|
172
|
+
installed_plugins.each do |plugin_source|
|
173
|
+
str << "git clone #{plugin_source}\n"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
def update_plugins(c)
|
177
|
+
ssh(c.update_plugin_string)
|
178
|
+
end
|
179
|
+
after :configure, :update_plugins
|
180
|
+
# Is this the master and if not, is the master running?
|
181
|
+
def is_not_master_and_master_is_not_running?
|
182
|
+
!master? && !Master.is_master_responding?
|
183
|
+
end
|
184
|
+
# User conf file if it exists, or default one
|
185
|
+
def conf_file(name)
|
186
|
+
user_conf = File.join(PoolParty.user_dir, "config", name)
|
187
|
+
if File.file?(user_conf)
|
188
|
+
File.join(PoolParty.user_dir, "config", name)
|
189
|
+
else
|
190
|
+
File.join(PoolParty.root_dir, "config", name)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Description in the rake task
|
195
|
+
def description
|
196
|
+
case @status
|
197
|
+
when "running"
|
198
|
+
"#{@number}: INSTANCE: #{name} - #{@ip} - #{@instance_id} - #{@launching_time}"
|
199
|
+
when "shutting-down"
|
200
|
+
"(terminating) INSTANCE: #{name} - #{@ip} - #{@instance_id} - #{@launching_time}"
|
201
|
+
when "pending"
|
202
|
+
"(booting) INSTANCE: #{name} - #{@ip} - #{@instance_id} - #{@launching_time}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
def stack_installed?
|
206
|
+
@stack_installed ||= (run_now('echo ~/.installed') == "installed")
|
207
|
+
end
|
208
|
+
def mark_installed(caller=nil)
|
209
|
+
run_now("echo 'installed' > ~/.installed")
|
210
|
+
@stack_installed = true
|
211
|
+
end
|
212
|
+
def base_install_script
|
213
|
+
"#{root_dir}/config/installers/#{Application.os.downcase}_install.sh"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Handle the remoting aspects of the remote_instances
|
3
|
+
=end
|
4
|
+
module PoolParty
|
5
|
+
module Remoter
|
6
|
+
module ClassMethods
|
7
|
+
def ssh_string
|
8
|
+
"ssh -i #{Application.keypair_path} -o StrictHostKeyChecking=no -l #{Application.username}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
include Callbacks
|
14
|
+
include Scheduler
|
15
|
+
|
16
|
+
def scp local, remote, opts={}
|
17
|
+
data = open(local).read
|
18
|
+
begin
|
19
|
+
|
20
|
+
cmd = "rsync --delete -azP -e '#{self.class.ssh_string} -l #{Application.username} -i #{Application.keypair_path}' "
|
21
|
+
|
22
|
+
if opts[:dir]
|
23
|
+
ssh("mkdir -p #{opts[:dir]}")
|
24
|
+
end
|
25
|
+
|
26
|
+
if opts[:single]
|
27
|
+
scp_tasks << "#{cmd} #{local} #{Application.username}@#{opts[:single]}:#{remote}"
|
28
|
+
else
|
29
|
+
target_hosts.each do |ip|
|
30
|
+
scp_tasks << "#{cmd} #{local} #{Application.username}@#{ip}:#{remote}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
rescue Exception => e
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def single_scp local, remote, opts={}
|
39
|
+
scp local, remote, opts.merge({:single => self.ip})
|
40
|
+
end
|
41
|
+
|
42
|
+
def ssh command="", opts={}, &block
|
43
|
+
cmd = self.class.ssh_string
|
44
|
+
if command.empty?
|
45
|
+
system("#{cmd} #{Application.username}@#{self.ip}")
|
46
|
+
else
|
47
|
+
if opts[:single]
|
48
|
+
ssh_tasks << "#{cmd} #{Application.username}@#{self.ip} '#{command.runnable}'"
|
49
|
+
else
|
50
|
+
target_hosts.each do |ip|
|
51
|
+
ssh_tasks << "#{cmd} #{Application.username}@#{ip} '#{command.runnable}'"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_now command=""
|
58
|
+
system("#{self.class.ssh_string} #{Application.username}@#{self.ip} #{command.runnable}")
|
59
|
+
end
|
60
|
+
|
61
|
+
def install *names
|
62
|
+
names.each {|name| install_tasks << name }
|
63
|
+
end
|
64
|
+
|
65
|
+
def ssh_tasks;@ssh_tasks ||= [];end
|
66
|
+
def scp_tasks;@scp_tasks ||= [];end
|
67
|
+
def install_tasks;@install_tasks ||= [];end
|
68
|
+
|
69
|
+
def reset!
|
70
|
+
@ssh_tasks = @scp_tasks = nil
|
71
|
+
@hosts = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def execute_tasks(opts={})
|
75
|
+
# reset!
|
76
|
+
|
77
|
+
set_hosts(nil) unless opts[:dont_set_hosts]
|
78
|
+
|
79
|
+
yield if block_given?
|
80
|
+
|
81
|
+
run_array_of_tasks(scp_tasks)
|
82
|
+
run_array_of_tasks(ssh_tasks)
|
83
|
+
|
84
|
+
PoolParty.message "running #{ssh_tasks.size} tasks"
|
85
|
+
end
|
86
|
+
|
87
|
+
def target_hosts
|
88
|
+
@hosts ||= Master.collect_nodes {|a| a.ip }
|
89
|
+
end
|
90
|
+
|
91
|
+
def run_array_of_tasks(task_list)
|
92
|
+
add_task {`#{task_list.join(" && ")}`}
|
93
|
+
run_thread_list
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_hosts(c=nil)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.included(receiver)
|
102
|
+
receiver.extend ClassMethods
|
103
|
+
receiver.send :include, InstanceMethods
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|