auser-poolparty 0.1.2 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +22 -0
- data/License.txt +20 -0
- data/README.txt +52 -0
- data/Rakefile +4 -109
- data/bin/cloud +31 -0
- data/bin/cloud-add-keypair +23 -0
- data/bin/cloud-configure +35 -0
- data/bin/cloud-contract +27 -0
- data/bin/cloud-expand +27 -0
- data/bin/cloud-list +32 -0
- data/bin/cloud-maintain +36 -0
- data/bin/cloud-provision +30 -0
- data/bin/cloud-reconfigure +24 -0
- data/bin/cloud-ssh +18 -0
- data/bin/cloud-start +29 -0
- data/bin/pool +23 -75
- data/bin/pool-console +12 -0
- data/bin/pool-describe +9 -0
- data/bin/pool-list +28 -0
- data/bin/pool-provision +34 -0
- data/bin/pool-spec +17 -0
- data/bin/pool-start +32 -0
- data/examples/basic.rb +20 -0
- data/examples/plugin_without_plugin_directory.rb +13 -0
- data/examples/poolparty.rb +12 -0
- data/examples/with_apache_plugin.rb +22 -0
- data/generators/poolspec/USAGE +5 -0
- data/generators/poolspec/poolspec_generator.rb +65 -0
- data/generators/poolspec/templates/pool_spec_template.erb +9 -0
- data/lib/erlang/eb_server.erl +27 -0
- data/lib/poolparty.rb +40 -116
- data/lib/poolparty/base_packages/haproxy.rb +41 -0
- data/lib/poolparty/base_packages/heartbeat.rb +43 -0
- data/lib/poolparty/base_packages/poolparty.rb +18 -0
- data/lib/poolparty/base_packages/ruby.rb +27 -0
- data/lib/poolparty/core/array.rb +24 -0
- data/lib/{core → poolparty/core}/exception.rb +0 -0
- data/lib/{core → poolparty/core}/float.rb +0 -0
- data/lib/poolparty/core/hash.rb +29 -0
- data/lib/poolparty/core/kernel.rb +34 -0
- data/lib/{core → poolparty/core}/module.rb +18 -0
- data/lib/poolparty/core/my_open_struct.rb +18 -0
- data/lib/poolparty/core/object.rb +54 -0
- data/lib/poolparty/core/proc.rb +2 -0
- data/lib/poolparty/core/string.rb +72 -0
- data/lib/poolparty/core/symbol.rb +8 -0
- data/lib/{core → poolparty/core}/time.rb +15 -0
- data/lib/poolparty/exceptions/RemoteException.rb +12 -0
- data/lib/poolparty/exceptions/ResourceException.rb +7 -0
- data/lib/poolparty/exceptions/RuntimeException.rb +7 -0
- data/lib/poolparty/exceptions/SpecException.rb +7 -0
- data/lib/poolparty/exceptions/TemplateNotFound.rb +7 -0
- data/lib/poolparty/helpers/binary.rb +30 -0
- data/lib/poolparty/helpers/console.rb +30 -0
- data/lib/poolparty/helpers/display.rb +25 -0
- data/lib/poolparty/helpers/optioner.rb +61 -0
- data/lib/poolparty/helpers/provisioner_base.rb +226 -0
- data/lib/poolparty/helpers/provisioners/master.rb +120 -0
- data/lib/poolparty/helpers/provisioners/slave.rb +52 -0
- data/lib/poolparty/modules/cloud_resourcer.rb +72 -0
- data/lib/poolparty/modules/configurable.rb +34 -0
- data/lib/poolparty/modules/definable_resource.rb +59 -0
- data/lib/poolparty/modules/file_writer.rb +55 -0
- data/lib/poolparty/modules/method_missing_sugar.rb +17 -0
- data/lib/poolparty/modules/output.rb +13 -0
- data/lib/poolparty/modules/pretty_printer.rb +38 -0
- data/lib/{core/string.rb → poolparty/modules/s3_string.rb} +5 -29
- data/lib/{modules → poolparty/modules}/safe_instance.rb +0 -0
- data/lib/poolparty/monitors/base_monitor.rb +16 -0
- data/lib/poolparty/net/remote.rb +35 -0
- data/lib/poolparty/net/remote_bases/ec2.rb +145 -0
- data/lib/poolparty/net/remote_instance.rb +68 -0
- data/lib/poolparty/net/remoter.rb +209 -0
- data/lib/poolparty/net/remoter_base.rb +117 -0
- data/lib/poolparty/plugins/gem_package.rb +39 -0
- data/lib/poolparty/plugins/line.rb +76 -0
- data/lib/poolparty/plugins/svn.rb +48 -0
- data/lib/poolparty/pool/base.rb +74 -0
- data/lib/poolparty/pool/cloud.rb +132 -0
- data/lib/poolparty/pool/custom_resource.rb +61 -0
- data/lib/poolparty/pool/loggable.rb +29 -0
- data/lib/poolparty/pool/plugin.rb +42 -0
- data/lib/poolparty/pool/plugin_model.rb +48 -0
- data/lib/poolparty/pool/pool.rb +55 -0
- data/lib/poolparty/pool/resource.rb +235 -0
- data/lib/poolparty/pool/resources/class_package.rb +60 -0
- data/lib/poolparty/pool/resources/cron.rb +14 -0
- data/lib/poolparty/pool/resources/directory.rb +23 -0
- data/lib/poolparty/pool/resources/exec.rb +26 -0
- data/lib/poolparty/pool/resources/file.rb +23 -0
- data/lib/poolparty/pool/resources/gem.rb +14 -0
- data/lib/poolparty/pool/resources/host.rb +14 -0
- data/lib/poolparty/pool/resources/package.rb +14 -0
- data/lib/poolparty/pool/resources/remote_file.rb +20 -0
- data/lib/poolparty/pool/resources/service.rb +21 -0
- data/lib/poolparty/pool/resources/sshkey.rb +19 -0
- data/lib/poolparty/pool/resources/variable.rb +27 -0
- data/lib/poolparty/pool/script.rb +21 -0
- data/{config/heartbeat_authkeys.conf → lib/poolparty/templates/authkeys} +0 -0
- data/lib/poolparty/templates/cib.xml +1 -0
- data/lib/poolparty/templates/fileserver.conf +4 -0
- data/{config/heartbeat.conf → lib/poolparty/templates/ha.cf} +3 -1
- data/{config → lib/poolparty/templates}/haproxy.conf +13 -6
- data/lib/poolparty/templates/namespaceauth.conf +19 -0
- data/lib/poolparty/templates/puppet.conf +13 -0
- data/lib/poolparty/version.rb +9 -0
- data/lib/poolpartycl.rb +3 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/{lib/poolparty/tasks → tasks}/cloud.rake +1 -1
- data/tasks/deployment.rake +34 -0
- data/tasks/development.rake +78 -0
- data/{lib/poolparty/tasks → tasks}/ec2.rake +1 -1
- data/tasks/environment.rake +7 -0
- data/{lib/poolparty/tasks → tasks}/instance.rake +0 -0
- data/{lib/poolparty/tasks → tasks}/server.rake +0 -0
- data/tasks/spec.rake +17 -0
- data/tasks/website.rake +17 -0
- metadata +154 -249
- data/CHANGELOG +0 -23
- data/LICENSE +0 -22
- data/README +0 -139
- data/assets/clouds.png +0 -0
- data/bin/instance +0 -68
- data/bin/poolnotify +0 -34
- data/config/cloud_master_takeover +0 -17
- data/config/create_proxy_ami.sh +0 -582
- data/config/installers/ubuntu_install.sh +0 -77
- data/config/monit.conf +0 -9
- data/config/monit/haproxy.monit.conf +0 -8
- data/config/monit/nginx.monit.conf +0 -0
- data/config/nginx.conf +0 -24
- data/config/reconfigure_instances_script.sh +0 -37
- data/config/sample-config.yml +0 -23
- data/config/scp_instances_script.sh +0 -12
- data/lib/core/array.rb +0 -16
- data/lib/core/hash.rb +0 -11
- data/lib/core/kernel.rb +0 -12
- data/lib/core/object.rb +0 -21
- data/lib/core/proc.rb +0 -15
- data/lib/helpers/plugin_spec_helper.rb +0 -58
- data/lib/modules/callback.rb +0 -133
- data/lib/modules/ec2_wrapper.rb +0 -108
- data/lib/modules/file_writer.rb +0 -38
- data/lib/modules/sprinkle_overrides.rb +0 -27
- data/lib/modules/vlad_override.rb +0 -83
- data/lib/poolparty/application.rb +0 -199
- data/lib/poolparty/init.rb +0 -6
- data/lib/poolparty/master.rb +0 -492
- data/lib/poolparty/monitors.rb +0 -11
- data/lib/poolparty/monitors/cpu.rb +0 -23
- data/lib/poolparty/monitors/memory.rb +0 -33
- data/lib/poolparty/monitors/web.rb +0 -29
- data/lib/poolparty/optioner.rb +0 -20
- data/lib/poolparty/plugin.rb +0 -78
- data/lib/poolparty/provider.rb +0 -104
- data/lib/poolparty/provider/essential.rb +0 -6
- data/lib/poolparty/provider/git.rb +0 -8
- data/lib/poolparty/provider/haproxy.rb +0 -9
- data/lib/poolparty/provider/heartbeat.rb +0 -6
- data/lib/poolparty/provider/rsync.rb +0 -8
- data/lib/poolparty/provider/ruby.rb +0 -65
- data/lib/poolparty/provider/s3fuse.rb +0 -22
- data/lib/poolparty/remote_instance.rb +0 -250
- data/lib/poolparty/remoter.rb +0 -171
- data/lib/poolparty/remoting.rb +0 -137
- data/lib/poolparty/scheduler.rb +0 -93
- data/lib/poolparty/tasks.rb +0 -47
- data/lib/poolparty/tasks/development.rake +0 -78
- data/lib/poolparty/tasks/plugins.rake +0 -30
- data/lib/poolparty/thread_pool.rb +0 -94
- data/lib/s3/s3_object_store_folders.rb +0 -44
- data/poolparty.gemspec +0 -71
- data/spec/files/describe_response +0 -37
- data/spec/files/multi_describe_response +0 -69
- data/spec/files/remote_desc_response +0 -37
- data/spec/helpers/ec2_mock.rb +0 -57
- data/spec/lib/core/core_spec.rb +0 -26
- data/spec/lib/core/kernel_spec.rb +0 -24
- data/spec/lib/core/string_spec.rb +0 -28
- data/spec/lib/modules/callback_spec.rb +0 -213
- data/spec/lib/modules/file_writer_spec.rb +0 -74
- data/spec/lib/poolparty/application_spec.rb +0 -135
- data/spec/lib/poolparty/ec2_wrapper_spec.rb +0 -110
- data/spec/lib/poolparty/master_spec.rb +0 -479
- data/spec/lib/poolparty/optioner_spec.rb +0 -34
- data/spec/lib/poolparty/plugin_spec.rb +0 -115
- data/spec/lib/poolparty/poolparty_spec.rb +0 -60
- data/spec/lib/poolparty/provider_spec.rb +0 -74
- data/spec/lib/poolparty/remote_instance_spec.rb +0 -178
- data/spec/lib/poolparty/remoter_spec.rb +0 -72
- data/spec/lib/poolparty/remoting_spec.rb +0 -148
- data/spec/lib/poolparty/scheduler_spec.rb +0 -70
- data/spec/monitors/cpu_monitor_spec.rb +0 -39
- data/spec/monitors/memory_spec.rb +0 -51
- data/spec/monitors/misc_monitor_spec.rb +0 -51
- data/spec/monitors/web_spec.rb +0 -40
- data/spec/spec_helper.rb +0 -53
|
@@ -1,32 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
def hasherize(format=[])
|
|
3
|
-
hash = {}
|
|
4
|
-
i = 0
|
|
5
|
-
self.split(%r{[\n|\t|\s| ]+}).collect {|a| a.strip}.each do |f|
|
|
6
|
-
break unless format[i]
|
|
7
|
-
unless f == "" || f.nil?
|
|
8
|
-
hash[format[i]] = f
|
|
9
|
-
i+=1
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
hash
|
|
13
|
-
end
|
|
14
|
-
def ^(h={})
|
|
15
|
-
self.gsub(/:([\w]+)/) {h[$1.to_sym] if h.include?($1.to_sym)}
|
|
16
|
-
end
|
|
17
|
-
def arrayable
|
|
18
|
-
self.strip.split(/\n/)
|
|
19
|
-
end
|
|
20
|
-
def runnable(quite=true)
|
|
21
|
-
# map {|l| l << "#{" >/dev/null 2>/dev/null" if quite}" }.
|
|
22
|
-
self.strip.split(/\n/).join(" && ")
|
|
23
|
-
end
|
|
24
|
-
def nice_runnable(quite=true)
|
|
25
|
-
self.split(/ && /).join("\n")
|
|
26
|
-
end
|
|
27
|
-
def classify
|
|
28
|
-
self.capitalize
|
|
29
|
-
end
|
|
1
|
+
module S3String
|
|
30
2
|
def bucket_objects
|
|
31
3
|
AWS::S3::Bucket.objects(self)
|
|
32
4
|
end
|
|
@@ -53,4 +25,8 @@ class String
|
|
|
53
25
|
def delete_bucket
|
|
54
26
|
AWS::S3::Bucket.delete(self, :force => true) if bucket_exists?
|
|
55
27
|
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class String
|
|
31
|
+
include S3String
|
|
56
32
|
end
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/remoter_base"
|
|
2
|
+
require File.dirname(__FILE__) + "/remoter"
|
|
3
|
+
|
|
4
|
+
module PoolParty
|
|
5
|
+
module Remote
|
|
6
|
+
|
|
7
|
+
include PoolParty::Remote::Remoter
|
|
8
|
+
|
|
9
|
+
def using(t)
|
|
10
|
+
if available_bases.include?(t.to_sym)
|
|
11
|
+
unless using_remoter? || t.nil?
|
|
12
|
+
self.class.send :attr_reader, :remote_base
|
|
13
|
+
mod = "#{t}".preserved_module_constant
|
|
14
|
+
|
|
15
|
+
mod.send :include, PoolParty::Remote::RemoterBase
|
|
16
|
+
self.class.send :include, mod
|
|
17
|
+
self.extend mod
|
|
18
|
+
|
|
19
|
+
@remote_base = "#{t}".preserved_module_constant
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
puts "Unknown remote base"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def available_bases
|
|
27
|
+
remote_bases
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def using_remoter?
|
|
31
|
+
@remote_base ||= nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require "ec2"
|
|
2
|
+
class String
|
|
3
|
+
def convert_from_ec2_to_ip
|
|
4
|
+
self.gsub(/.compute-1.amazonaws.com*/, '').gsub(/ec2-/, '').gsub(/-/, '.')
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
module PoolParty
|
|
8
|
+
module Ec2
|
|
9
|
+
def launch_new_instance!
|
|
10
|
+
instance = ec2.run_instances(
|
|
11
|
+
:image_id => self.respond_to?(:ami) ? ami : Base.ami,
|
|
12
|
+
:user_data => "",
|
|
13
|
+
:minCount => 1,
|
|
14
|
+
:maxCount => 1,
|
|
15
|
+
:key_name => "#{self.respond_to?(:keypair) ? keypair : Base.keypair}",
|
|
16
|
+
:availability_zone => nil,
|
|
17
|
+
:size => "#{self.respond_to?(:size) ? size : Base.size}")
|
|
18
|
+
begin
|
|
19
|
+
item = instance#.instancesSet.item
|
|
20
|
+
EC2ResponseObject.get_hash_from_response(item)
|
|
21
|
+
rescue Exception => e
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
# Terminate an instance by id
|
|
25
|
+
def terminate_instance!(instance_id=nil)
|
|
26
|
+
ec2.terminate_instances(:instance_id => instance_id)
|
|
27
|
+
end
|
|
28
|
+
# Describe an instance's status
|
|
29
|
+
def describe_instance(id=nil)
|
|
30
|
+
describe_instances.select {|a| a[:name] == id}[0] rescue nil
|
|
31
|
+
end
|
|
32
|
+
def describe_instances
|
|
33
|
+
unless @describe_instances && !@describe_instances.empty?
|
|
34
|
+
@id = 0
|
|
35
|
+
@describe_instances = get_instances_description.each_with_index do |h,i|
|
|
36
|
+
if h[:status] == "running"
|
|
37
|
+
@name = "node#{@id}"
|
|
38
|
+
@id += 1
|
|
39
|
+
else
|
|
40
|
+
@name = "#{h[:status]}_node#{i}"
|
|
41
|
+
end
|
|
42
|
+
h.merge!({
|
|
43
|
+
:name => @name,
|
|
44
|
+
:hostname => h[:ip],
|
|
45
|
+
:ip => h[:ip].convert_from_ec2_to_ip
|
|
46
|
+
})
|
|
47
|
+
end
|
|
48
|
+
@describe_instances.first[:name] = "master" unless @describe_instances.empty?
|
|
49
|
+
end
|
|
50
|
+
@describe_instances
|
|
51
|
+
end
|
|
52
|
+
# Get the s3 description for the response in a hash format
|
|
53
|
+
def get_instances_description
|
|
54
|
+
@cached_descriptions ||= EC2ResponseObject.get_descriptions(ec2.describe_instances).sort_by {|a| a[:launching_time]}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Help create a keypair for the cloud
|
|
58
|
+
# This is a helper to create the keypair and add them to the cloud for you
|
|
59
|
+
def create_keypair
|
|
60
|
+
return false unless keypair
|
|
61
|
+
FileUtils.mkdir_p ::File.dirname(new_keypair_path) unless ::File.directory?(::File.dirname(new_keypair_path))
|
|
62
|
+
Kernel.system "ec2-add-keypair #{keypair} > #{new_keypair_path} && chmod 600 #{new_keypair_path}"
|
|
63
|
+
end
|
|
64
|
+
# EC2 connections
|
|
65
|
+
def ec2
|
|
66
|
+
@ec2 ||= EC2::Base.new( :access_key_id => (access_key || Base.access_key),
|
|
67
|
+
:secret_access_key => (secret_access_key || Base.secret_access_key)
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Callback
|
|
72
|
+
def custom_install_tasks_for(o)
|
|
73
|
+
[
|
|
74
|
+
"# ec2 installation tasks",
|
|
75
|
+
"# Set hostname",
|
|
76
|
+
# "if [ -z $(grep -v '#' /etc/hosts | grep '#{o.name}') ]; then echo \"$(curl http://169.254.169.254/latest/meta-data/public-ipv4) #{o.name}\" >> /etc/hosts; fi",
|
|
77
|
+
"if [ -z \"$(grep -v '#' /etc/hosts | grep '#{o.name}')\" ]; then echo '127.0.0.1 #{o.name}' >> /etc/hosts; fi",
|
|
78
|
+
"hostname #{o.name}",
|
|
79
|
+
"echo #{o.name} > /etc/hostname"
|
|
80
|
+
]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def custom_configure_tasks_for(o)
|
|
84
|
+
[
|
|
85
|
+
"# ec2 configuration"
|
|
86
|
+
]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def reset!
|
|
90
|
+
@describe_instances = @cached_descriptions = nil
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
register_remote_base :Ec2
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Provides a simple class to wrap around the amazon responses
|
|
97
|
+
class EC2ResponseObject
|
|
98
|
+
def self.get_descriptions(resp)
|
|
99
|
+
rs = get_response_from(resp)
|
|
100
|
+
|
|
101
|
+
# puts rs.methods.sort - rs.ancestors.methods
|
|
102
|
+
out = begin
|
|
103
|
+
if rs.respond_to?(:instancesSet)
|
|
104
|
+
[EC2ResponseObject.get_hash_from_response(rs.instancesSet.item)]
|
|
105
|
+
else
|
|
106
|
+
rs.collect {|r|
|
|
107
|
+
if r.instancesSet.item.class == Array
|
|
108
|
+
r.instancesSet.item.map {|t| EC2ResponseObject.get_hash_from_response(t)}
|
|
109
|
+
else
|
|
110
|
+
[EC2ResponseObject.get_hash_from_response(r.instancesSet.item)]
|
|
111
|
+
end
|
|
112
|
+
}.flatten.reject {|a| a.nil? }
|
|
113
|
+
end
|
|
114
|
+
rescue Exception => e
|
|
115
|
+
# Really weird bug with amazon's ec2 gem
|
|
116
|
+
rs.collect {|r| EC2ResponseObject.get_hash_from_response(r)}.reject {|a| a.nil? } rescue []
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
out
|
|
120
|
+
end
|
|
121
|
+
def self.get_response_from(resp)
|
|
122
|
+
begin
|
|
123
|
+
rs = resp.reservationSet.item unless resp.reservationSet.nil?
|
|
124
|
+
rs ||= resp.DescribeInstancesResponse.reservationSet.item
|
|
125
|
+
rs ||= rs.respond_to?(:instancesSet) ? rs.instancesSet : rs
|
|
126
|
+
rs.reject! {|a| a.nil? || a.empty? }
|
|
127
|
+
rescue Exception => e
|
|
128
|
+
end
|
|
129
|
+
rs
|
|
130
|
+
end
|
|
131
|
+
def self.get_hash_from_response(resp)
|
|
132
|
+
begin
|
|
133
|
+
{
|
|
134
|
+
:instance_id => resp.instanceId,
|
|
135
|
+
:name => resp.instanceId,
|
|
136
|
+
:ip => resp.dnsName || "not-assigned",
|
|
137
|
+
:status => resp.instanceState.name,
|
|
138
|
+
:launching_time => resp.launchTime,
|
|
139
|
+
:keypair => resp.keyName
|
|
140
|
+
}
|
|
141
|
+
rescue Exception => e
|
|
142
|
+
nil
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/remoter"
|
|
2
|
+
|
|
3
|
+
module PoolParty
|
|
4
|
+
module Remote
|
|
5
|
+
|
|
6
|
+
class RemoteInstance
|
|
7
|
+
include Remote
|
|
8
|
+
include Configurable
|
|
9
|
+
include CloudResourcer
|
|
10
|
+
|
|
11
|
+
def initialize(opts, parent=self)
|
|
12
|
+
set_parent(parent) if parent
|
|
13
|
+
set_vars_from_options(opts) unless opts.empty?
|
|
14
|
+
on_init
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Callback
|
|
18
|
+
def on_init
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Is this remote instance the master?
|
|
22
|
+
def master?
|
|
23
|
+
name == "master"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The remote instances is only valid if there is an ip and a name
|
|
27
|
+
def valid?
|
|
28
|
+
!(ip.nil? || name.nil?)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Determine if the RemoteInstance is responding
|
|
32
|
+
def responding?
|
|
33
|
+
!responding.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# This is how we get the current load of the instance
|
|
37
|
+
# The approach of this may change entirely, but the usage of
|
|
38
|
+
# it will always be the same
|
|
39
|
+
def load
|
|
40
|
+
current_load ||= 0.0
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Is this instance running?
|
|
44
|
+
def running?
|
|
45
|
+
!(status =~ /running/).nil?
|
|
46
|
+
end
|
|
47
|
+
# Is this instance pending?
|
|
48
|
+
def pending?
|
|
49
|
+
!(status =~ /pending/).nil?
|
|
50
|
+
end
|
|
51
|
+
# Is this instance terminating?
|
|
52
|
+
def terminating?
|
|
53
|
+
!(status =~ /shutting/).nil?
|
|
54
|
+
end
|
|
55
|
+
# Has this instance been terminated?
|
|
56
|
+
def terminated?
|
|
57
|
+
!(status =~ /terminated/).nil?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Printing. This is how we extract the instances into the listing on the
|
|
61
|
+
# local side into the local listing file
|
|
62
|
+
def to_s
|
|
63
|
+
"#{name} #{ip}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
=begin rdoc
|
|
2
|
+
This module is included by the remote module and defines the remoting methods
|
|
3
|
+
that the clouds can use to rsync or run remote commands
|
|
4
|
+
=end
|
|
5
|
+
require File.dirname(__FILE__) + "/../helpers/provisioner_base"
|
|
6
|
+
|
|
7
|
+
module PoolParty
|
|
8
|
+
module Remote
|
|
9
|
+
module Remoter
|
|
10
|
+
def rsync_storage_files_to_command(remote_instance)
|
|
11
|
+
if remote_instance
|
|
12
|
+
"#{rsync_command} #{Base.storage_directory} #{remote_instance.ip}:#{Base.remote_storage_path}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
def run_command_on_command(cmd="ls -l", remote_instance=nil)
|
|
16
|
+
"#{ssh_command(remote_instance)} '#{cmd}'"
|
|
17
|
+
end
|
|
18
|
+
def ssh_command(remote_instance)
|
|
19
|
+
"#{ssh_string} #{remote_instance.ip}"
|
|
20
|
+
end
|
|
21
|
+
# Generic commandable strings
|
|
22
|
+
def ssh_string
|
|
23
|
+
(["ssh"] << ssh_array).join(" ")
|
|
24
|
+
end
|
|
25
|
+
# Array of ssh options
|
|
26
|
+
# Includes StrictHostKeyChecking to no
|
|
27
|
+
# Ssh with the user in Base
|
|
28
|
+
# And including the keypair_path
|
|
29
|
+
def ssh_array
|
|
30
|
+
["-o StrictHostKeyChecking=no", "-l '#{Base.user}'", '-i "'+full_keypair_path+'"']
|
|
31
|
+
end
|
|
32
|
+
def rsync_command
|
|
33
|
+
"rsync --delete -azP --exclude cache -e '#{ssh_string}'"
|
|
34
|
+
end
|
|
35
|
+
# Open the cached local copy of the instances list and
|
|
36
|
+
# create a new RemoteInstance from each line
|
|
37
|
+
def list_from_local
|
|
38
|
+
list_file = get_working_listing_file
|
|
39
|
+
if list_file
|
|
40
|
+
out = returning Array.new do |instances|
|
|
41
|
+
open(list_file).read.split("\n").each do |line|
|
|
42
|
+
instances << RemoteInstance.new(line)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
else
|
|
46
|
+
out = list_from_remote(:cache => true)
|
|
47
|
+
end
|
|
48
|
+
return out
|
|
49
|
+
end
|
|
50
|
+
# List the instances that are known from the remoter_base
|
|
51
|
+
# Create a RemoteInstance for each of the instances from the hash
|
|
52
|
+
# returned by the list of instances, write them to the cached file
|
|
53
|
+
# and then return the array of instances
|
|
54
|
+
def list_from_remote(options={})
|
|
55
|
+
out_array = get_remote_nodes
|
|
56
|
+
write_to_file( local_instances_list_file_locations.first, out_array.map{|a| a.to_s }.join("\n")) if options[:cache]
|
|
57
|
+
out_array
|
|
58
|
+
end
|
|
59
|
+
# Get the names of the nodes. Mainly used for puppet templating
|
|
60
|
+
def list_of_node_names(options={})
|
|
61
|
+
list_of_running_instances.collect {|ri| ri.name }
|
|
62
|
+
end
|
|
63
|
+
# An array of node ips. Mainly used for puppet templating
|
|
64
|
+
def list_of_node_ips(options={})
|
|
65
|
+
list_of_running_instances.collect {|ri| ri.ip }
|
|
66
|
+
end
|
|
67
|
+
def get_remote_nodes
|
|
68
|
+
returning Array.new do |instances|
|
|
69
|
+
list_of_instances(respond_to?(:keypair) ? keypair : nil).each do |h|
|
|
70
|
+
instances << PoolParty::Remote::RemoteInstance.new(h)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
# Get the instance first instance file that exists on the system from the expected places
|
|
75
|
+
# denoted in the local_instances_list_file_locations
|
|
76
|
+
def get_working_listing_file
|
|
77
|
+
local_instances_list_file_locations.reject {|f| f unless File.file?(f) }.first
|
|
78
|
+
end
|
|
79
|
+
# Expected places for the instances.list to be located at on the machine
|
|
80
|
+
def local_instances_list_file_locations
|
|
81
|
+
[
|
|
82
|
+
"#{Base.storage_directory}/#{name}-instances.list",
|
|
83
|
+
"#{Base.base_config_directory}/#{name}-instances.list",
|
|
84
|
+
"~/.#{name}-instances.list",
|
|
85
|
+
"~/#{name}-instances.list",
|
|
86
|
+
"#{name}-instances.list"
|
|
87
|
+
]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# More functional methods
|
|
91
|
+
# Are the minimum number of instances running?
|
|
92
|
+
def minimum_number_of_instances_are_running?
|
|
93
|
+
list_of_running_instances.size >= minimum_instances
|
|
94
|
+
end
|
|
95
|
+
# Can we shutdown an instance?
|
|
96
|
+
def can_shutdown_an_instance?
|
|
97
|
+
list_of_running_instances.size > minimum_instances
|
|
98
|
+
end
|
|
99
|
+
# Request to launch a number of instances
|
|
100
|
+
def request_launch_new_instances(num=1)
|
|
101
|
+
out = []
|
|
102
|
+
num.times {out << launch_new_instance!}
|
|
103
|
+
out
|
|
104
|
+
end
|
|
105
|
+
# Let's terminate an instance that is not the master instance
|
|
106
|
+
def request_termination_of_non_master_instance
|
|
107
|
+
inst = nonmaster_nonterminated_instances.last
|
|
108
|
+
terminate_instance!(inst.instance_id) if inst
|
|
109
|
+
end
|
|
110
|
+
# Can we start a new instance?
|
|
111
|
+
def can_start_a_new_instance?
|
|
112
|
+
maximum_number_of_instances_are_not_running?
|
|
113
|
+
end
|
|
114
|
+
# Are the maximum number of instances running?
|
|
115
|
+
def maximum_number_of_instances_are_not_running?
|
|
116
|
+
list_of_running_instances.size < maximum_instances
|
|
117
|
+
end
|
|
118
|
+
# Launch new instance while waiting for the number of pending instances
|
|
119
|
+
# to be zero before actually launching. This ensures that we only
|
|
120
|
+
# launch one instance at a time
|
|
121
|
+
def request_launch_one_instance_at_a_time
|
|
122
|
+
when_no_pending_instances do
|
|
123
|
+
launch_new_instance!
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
# A convenience method for waiting until there are no more
|
|
127
|
+
# pending instances and then running the block
|
|
128
|
+
def when_no_pending_instances(&block)
|
|
129
|
+
reset!
|
|
130
|
+
if list_of_pending_instances.size > 0
|
|
131
|
+
wait "5.seconds"
|
|
132
|
+
when_no_pending_instances(&block)
|
|
133
|
+
else
|
|
134
|
+
block.call if block
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# This will launch the minimum_instances if the minimum number of instances are not running
|
|
139
|
+
# If the minimum number of instances are not running and if we can start a new instance
|
|
140
|
+
def launch_minimum_number_of_instances
|
|
141
|
+
if can_start_a_new_instance?
|
|
142
|
+
while !minimum_number_of_instances_are_running?
|
|
143
|
+
request_launch_one_instance_at_a_time
|
|
144
|
+
wait "5.seconds"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
# Stub method for the time being to handle expansion of the cloud
|
|
149
|
+
def should_expand_cloud?(force=false)
|
|
150
|
+
force || false
|
|
151
|
+
end
|
|
152
|
+
# Stub method for the time being to handle the contraction of the cloud
|
|
153
|
+
def should_contract_cloud?(force=false)
|
|
154
|
+
force || false
|
|
155
|
+
end
|
|
156
|
+
# Expand the cloud
|
|
157
|
+
# If we can start a new instance and the load requires us to expand
|
|
158
|
+
# the cloud, then we should request_launch_new_instances
|
|
159
|
+
# Wait for the instance to boot up and when it does come back
|
|
160
|
+
# online, then provision it as a slave, this way, it is ready for action from the
|
|
161
|
+
# get go
|
|
162
|
+
def expand_cloud_if_necessary(force=false)
|
|
163
|
+
if can_start_a_new_instance? && should_expand_cloud?(force)
|
|
164
|
+
@out = request_launch_new_instances(1)
|
|
165
|
+
|
|
166
|
+
reset!
|
|
167
|
+
when_no_pending_instances do
|
|
168
|
+
@ri = list_of_running_instances.last
|
|
169
|
+
PoolParty::Provisioner.provision_slave(@ri, self, !force)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
# Contract the cloud
|
|
174
|
+
# If we can shutdown an instnace and the load allows us to contract
|
|
175
|
+
# the cloud, then we should request_termination_of_non_master_instance
|
|
176
|
+
def contract_cloud_if_necessary(force=false)
|
|
177
|
+
if can_shutdown_an_instance?
|
|
178
|
+
request_termination_of_non_master_instance if should_contract_cloud?(force)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Rsync command to the instance
|
|
183
|
+
def rsync_storage_files_to(instance=nil)
|
|
184
|
+
hide_output do
|
|
185
|
+
Kernel.system "#{rsync_storage_files_to_command(instance)}" if instance
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
# Take the rsync command and execute it on the system
|
|
189
|
+
# if there is an instance given
|
|
190
|
+
def run_command_on(cmd, instance=nil)
|
|
191
|
+
Kernel.system "#{run_command_on_command(cmd, instance)}" if instance
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Ssh into the instance given
|
|
195
|
+
def ssh_into(instance=nil)
|
|
196
|
+
Kernel.system "#{ssh_command(instance)}" if instance
|
|
197
|
+
end
|
|
198
|
+
# Find the instance by the number given
|
|
199
|
+
# and then ssh into the instance
|
|
200
|
+
def ssh_into_instance_number(num=0)
|
|
201
|
+
ssh_into( get_instance_by_number( num || 0 ) )
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def self.included(receiver)
|
|
205
|
+
receiver.extend self
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|