auser-poolparty 0.1.2 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/History.txt +22 -0
  2. data/License.txt +20 -0
  3. data/README.txt +52 -0
  4. data/Rakefile +4 -109
  5. data/bin/cloud +31 -0
  6. data/bin/cloud-add-keypair +23 -0
  7. data/bin/cloud-configure +35 -0
  8. data/bin/cloud-contract +27 -0
  9. data/bin/cloud-expand +27 -0
  10. data/bin/cloud-list +32 -0
  11. data/bin/cloud-maintain +36 -0
  12. data/bin/cloud-provision +30 -0
  13. data/bin/cloud-reconfigure +24 -0
  14. data/bin/cloud-ssh +18 -0
  15. data/bin/cloud-start +29 -0
  16. data/bin/pool +23 -75
  17. data/bin/pool-console +12 -0
  18. data/bin/pool-describe +9 -0
  19. data/bin/pool-list +28 -0
  20. data/bin/pool-provision +34 -0
  21. data/bin/pool-spec +17 -0
  22. data/bin/pool-start +32 -0
  23. data/examples/basic.rb +20 -0
  24. data/examples/plugin_without_plugin_directory.rb +13 -0
  25. data/examples/poolparty.rb +12 -0
  26. data/examples/with_apache_plugin.rb +22 -0
  27. data/generators/poolspec/USAGE +5 -0
  28. data/generators/poolspec/poolspec_generator.rb +65 -0
  29. data/generators/poolspec/templates/pool_spec_template.erb +9 -0
  30. data/lib/erlang/eb_server.erl +27 -0
  31. data/lib/poolparty.rb +40 -116
  32. data/lib/poolparty/base_packages/haproxy.rb +41 -0
  33. data/lib/poolparty/base_packages/heartbeat.rb +43 -0
  34. data/lib/poolparty/base_packages/poolparty.rb +18 -0
  35. data/lib/poolparty/base_packages/ruby.rb +27 -0
  36. data/lib/poolparty/core/array.rb +24 -0
  37. data/lib/{core → poolparty/core}/exception.rb +0 -0
  38. data/lib/{core → poolparty/core}/float.rb +0 -0
  39. data/lib/poolparty/core/hash.rb +29 -0
  40. data/lib/poolparty/core/kernel.rb +34 -0
  41. data/lib/{core → poolparty/core}/module.rb +18 -0
  42. data/lib/poolparty/core/my_open_struct.rb +18 -0
  43. data/lib/poolparty/core/object.rb +54 -0
  44. data/lib/poolparty/core/proc.rb +2 -0
  45. data/lib/poolparty/core/string.rb +72 -0
  46. data/lib/poolparty/core/symbol.rb +8 -0
  47. data/lib/{core → poolparty/core}/time.rb +15 -0
  48. data/lib/poolparty/exceptions/RemoteException.rb +12 -0
  49. data/lib/poolparty/exceptions/ResourceException.rb +7 -0
  50. data/lib/poolparty/exceptions/RuntimeException.rb +7 -0
  51. data/lib/poolparty/exceptions/SpecException.rb +7 -0
  52. data/lib/poolparty/exceptions/TemplateNotFound.rb +7 -0
  53. data/lib/poolparty/helpers/binary.rb +30 -0
  54. data/lib/poolparty/helpers/console.rb +30 -0
  55. data/lib/poolparty/helpers/display.rb +25 -0
  56. data/lib/poolparty/helpers/optioner.rb +61 -0
  57. data/lib/poolparty/helpers/provisioner_base.rb +226 -0
  58. data/lib/poolparty/helpers/provisioners/master.rb +120 -0
  59. data/lib/poolparty/helpers/provisioners/slave.rb +52 -0
  60. data/lib/poolparty/modules/cloud_resourcer.rb +72 -0
  61. data/lib/poolparty/modules/configurable.rb +34 -0
  62. data/lib/poolparty/modules/definable_resource.rb +59 -0
  63. data/lib/poolparty/modules/file_writer.rb +55 -0
  64. data/lib/poolparty/modules/method_missing_sugar.rb +17 -0
  65. data/lib/poolparty/modules/output.rb +13 -0
  66. data/lib/poolparty/modules/pretty_printer.rb +38 -0
  67. data/lib/{core/string.rb → poolparty/modules/s3_string.rb} +5 -29
  68. data/lib/{modules → poolparty/modules}/safe_instance.rb +0 -0
  69. data/lib/poolparty/monitors/base_monitor.rb +16 -0
  70. data/lib/poolparty/net/remote.rb +35 -0
  71. data/lib/poolparty/net/remote_bases/ec2.rb +145 -0
  72. data/lib/poolparty/net/remote_instance.rb +68 -0
  73. data/lib/poolparty/net/remoter.rb +209 -0
  74. data/lib/poolparty/net/remoter_base.rb +117 -0
  75. data/lib/poolparty/plugins/gem_package.rb +39 -0
  76. data/lib/poolparty/plugins/line.rb +76 -0
  77. data/lib/poolparty/plugins/svn.rb +48 -0
  78. data/lib/poolparty/pool/base.rb +74 -0
  79. data/lib/poolparty/pool/cloud.rb +132 -0
  80. data/lib/poolparty/pool/custom_resource.rb +61 -0
  81. data/lib/poolparty/pool/loggable.rb +29 -0
  82. data/lib/poolparty/pool/plugin.rb +42 -0
  83. data/lib/poolparty/pool/plugin_model.rb +48 -0
  84. data/lib/poolparty/pool/pool.rb +55 -0
  85. data/lib/poolparty/pool/resource.rb +235 -0
  86. data/lib/poolparty/pool/resources/class_package.rb +60 -0
  87. data/lib/poolparty/pool/resources/cron.rb +14 -0
  88. data/lib/poolparty/pool/resources/directory.rb +23 -0
  89. data/lib/poolparty/pool/resources/exec.rb +26 -0
  90. data/lib/poolparty/pool/resources/file.rb +23 -0
  91. data/lib/poolparty/pool/resources/gem.rb +14 -0
  92. data/lib/poolparty/pool/resources/host.rb +14 -0
  93. data/lib/poolparty/pool/resources/package.rb +14 -0
  94. data/lib/poolparty/pool/resources/remote_file.rb +20 -0
  95. data/lib/poolparty/pool/resources/service.rb +21 -0
  96. data/lib/poolparty/pool/resources/sshkey.rb +19 -0
  97. data/lib/poolparty/pool/resources/variable.rb +27 -0
  98. data/lib/poolparty/pool/script.rb +21 -0
  99. data/{config/heartbeat_authkeys.conf → lib/poolparty/templates/authkeys} +0 -0
  100. data/lib/poolparty/templates/cib.xml +1 -0
  101. data/lib/poolparty/templates/fileserver.conf +4 -0
  102. data/{config/heartbeat.conf → lib/poolparty/templates/ha.cf} +3 -1
  103. data/{config → lib/poolparty/templates}/haproxy.conf +13 -6
  104. data/lib/poolparty/templates/namespaceauth.conf +19 -0
  105. data/lib/poolparty/templates/puppet.conf +13 -0
  106. data/lib/poolparty/version.rb +9 -0
  107. data/lib/poolpartycl.rb +3 -0
  108. data/script/destroy +14 -0
  109. data/script/generate +14 -0
  110. data/script/txt2html +82 -0
  111. data/{lib/poolparty/tasks → tasks}/cloud.rake +1 -1
  112. data/tasks/deployment.rake +34 -0
  113. data/tasks/development.rake +78 -0
  114. data/{lib/poolparty/tasks → tasks}/ec2.rake +1 -1
  115. data/tasks/environment.rake +7 -0
  116. data/{lib/poolparty/tasks → tasks}/instance.rake +0 -0
  117. data/{lib/poolparty/tasks → tasks}/server.rake +0 -0
  118. data/tasks/spec.rake +17 -0
  119. data/tasks/website.rake +17 -0
  120. metadata +154 -249
  121. data/CHANGELOG +0 -23
  122. data/LICENSE +0 -22
  123. data/README +0 -139
  124. data/assets/clouds.png +0 -0
  125. data/bin/instance +0 -68
  126. data/bin/poolnotify +0 -34
  127. data/config/cloud_master_takeover +0 -17
  128. data/config/create_proxy_ami.sh +0 -582
  129. data/config/installers/ubuntu_install.sh +0 -77
  130. data/config/monit.conf +0 -9
  131. data/config/monit/haproxy.monit.conf +0 -8
  132. data/config/monit/nginx.monit.conf +0 -0
  133. data/config/nginx.conf +0 -24
  134. data/config/reconfigure_instances_script.sh +0 -37
  135. data/config/sample-config.yml +0 -23
  136. data/config/scp_instances_script.sh +0 -12
  137. data/lib/core/array.rb +0 -16
  138. data/lib/core/hash.rb +0 -11
  139. data/lib/core/kernel.rb +0 -12
  140. data/lib/core/object.rb +0 -21
  141. data/lib/core/proc.rb +0 -15
  142. data/lib/helpers/plugin_spec_helper.rb +0 -58
  143. data/lib/modules/callback.rb +0 -133
  144. data/lib/modules/ec2_wrapper.rb +0 -108
  145. data/lib/modules/file_writer.rb +0 -38
  146. data/lib/modules/sprinkle_overrides.rb +0 -27
  147. data/lib/modules/vlad_override.rb +0 -83
  148. data/lib/poolparty/application.rb +0 -199
  149. data/lib/poolparty/init.rb +0 -6
  150. data/lib/poolparty/master.rb +0 -492
  151. data/lib/poolparty/monitors.rb +0 -11
  152. data/lib/poolparty/monitors/cpu.rb +0 -23
  153. data/lib/poolparty/monitors/memory.rb +0 -33
  154. data/lib/poolparty/monitors/web.rb +0 -29
  155. data/lib/poolparty/optioner.rb +0 -20
  156. data/lib/poolparty/plugin.rb +0 -78
  157. data/lib/poolparty/provider.rb +0 -104
  158. data/lib/poolparty/provider/essential.rb +0 -6
  159. data/lib/poolparty/provider/git.rb +0 -8
  160. data/lib/poolparty/provider/haproxy.rb +0 -9
  161. data/lib/poolparty/provider/heartbeat.rb +0 -6
  162. data/lib/poolparty/provider/rsync.rb +0 -8
  163. data/lib/poolparty/provider/ruby.rb +0 -65
  164. data/lib/poolparty/provider/s3fuse.rb +0 -22
  165. data/lib/poolparty/remote_instance.rb +0 -250
  166. data/lib/poolparty/remoter.rb +0 -171
  167. data/lib/poolparty/remoting.rb +0 -137
  168. data/lib/poolparty/scheduler.rb +0 -93
  169. data/lib/poolparty/tasks.rb +0 -47
  170. data/lib/poolparty/tasks/development.rake +0 -78
  171. data/lib/poolparty/tasks/plugins.rake +0 -30
  172. data/lib/poolparty/thread_pool.rb +0 -94
  173. data/lib/s3/s3_object_store_folders.rb +0 -44
  174. data/poolparty.gemspec +0 -71
  175. data/spec/files/describe_response +0 -37
  176. data/spec/files/multi_describe_response +0 -69
  177. data/spec/files/remote_desc_response +0 -37
  178. data/spec/helpers/ec2_mock.rb +0 -57
  179. data/spec/lib/core/core_spec.rb +0 -26
  180. data/spec/lib/core/kernel_spec.rb +0 -24
  181. data/spec/lib/core/string_spec.rb +0 -28
  182. data/spec/lib/modules/callback_spec.rb +0 -213
  183. data/spec/lib/modules/file_writer_spec.rb +0 -74
  184. data/spec/lib/poolparty/application_spec.rb +0 -135
  185. data/spec/lib/poolparty/ec2_wrapper_spec.rb +0 -110
  186. data/spec/lib/poolparty/master_spec.rb +0 -479
  187. data/spec/lib/poolparty/optioner_spec.rb +0 -34
  188. data/spec/lib/poolparty/plugin_spec.rb +0 -115
  189. data/spec/lib/poolparty/poolparty_spec.rb +0 -60
  190. data/spec/lib/poolparty/provider_spec.rb +0 -74
  191. data/spec/lib/poolparty/remote_instance_spec.rb +0 -178
  192. data/spec/lib/poolparty/remoter_spec.rb +0 -72
  193. data/spec/lib/poolparty/remoting_spec.rb +0 -148
  194. data/spec/lib/poolparty/scheduler_spec.rb +0 -70
  195. data/spec/monitors/cpu_monitor_spec.rb +0 -39
  196. data/spec/monitors/memory_spec.rb +0 -51
  197. data/spec/monitors/misc_monitor_spec.rb +0 -51
  198. data/spec/monitors/web_spec.rb +0 -40
  199. data/spec/spec_helper.rb +0 -53
@@ -1,32 +1,4 @@
1
- class String
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,16 @@
1
+ =begin rdoc
2
+ Monitor class
3
+
4
+ TODO: Fill this out
5
+ =end
6
+ module PoolParty
7
+ module Monitors
8
+
9
+ class BaseMonitor
10
+
11
+
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -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