poolparty 0.0.4 → 0.2.6

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.
Files changed (247) hide show
  1. data/History.txt +25 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +203 -0
  4. data/PostInstall.txt +18 -0
  5. data/README.txt +21 -82
  6. data/Rakefile +25 -18
  7. data/bin/cloud +31 -0
  8. data/bin/cloud-add-keypair +23 -0
  9. data/bin/cloud-configure +31 -0
  10. data/bin/cloud-contract +27 -0
  11. data/bin/cloud-expand +27 -0
  12. data/bin/cloud-list +32 -0
  13. data/bin/cloud-maintain +36 -0
  14. data/bin/cloud-osxcopy +22 -0
  15. data/bin/cloud-provision +31 -0
  16. data/bin/cloud-refresh +26 -0
  17. data/bin/cloud-ssh +18 -0
  18. data/bin/cloud-start +32 -0
  19. data/bin/cloud-terminate +23 -0
  20. data/bin/pool +25 -27
  21. data/bin/pool-console +12 -0
  22. data/bin/pool-describe +9 -0
  23. data/bin/pool-list +28 -0
  24. data/bin/pool-provision +34 -0
  25. data/bin/pool-spec +17 -0
  26. data/bin/pool-start +32 -0
  27. data/bin/pool-start-monitor +1 -0
  28. data/config/hoe.rb +115 -0
  29. data/config/requirements.rb +15 -0
  30. data/examples/basic.rb +20 -0
  31. data/examples/plugin_without_plugin_directory.rb +13 -0
  32. data/examples/poolparty.rb +12 -0
  33. data/examples/with_apache_plugin.rb +22 -0
  34. data/generators/poolspec/USAGE +5 -0
  35. data/generators/poolspec/poolspec_generator.rb +65 -0
  36. data/generators/poolspec/templates/pool_spec_template.erb +9 -0
  37. data/lib/erlang/eb_server.erl +27 -0
  38. data/lib/poolparty.rb +56 -0
  39. data/lib/poolparty/base_packages/haproxy.rb +42 -0
  40. data/lib/poolparty/base_packages/heartbeat.rb +45 -0
  41. data/lib/poolparty/base_packages/poolparty.rb +36 -0
  42. data/lib/poolparty/base_packages/ruby.rb +43 -0
  43. data/lib/poolparty/core/array.rb +24 -0
  44. data/lib/{core → poolparty/core}/exception.rb +0 -0
  45. data/lib/poolparty/core/float.rb +13 -0
  46. data/lib/poolparty/core/hash.rb +29 -0
  47. data/lib/poolparty/core/kernel.rb +37 -0
  48. data/lib/{core → poolparty/core}/module.rb +18 -0
  49. data/lib/poolparty/core/my_open_struct.rb +18 -0
  50. data/lib/poolparty/core/object.rb +54 -0
  51. data/lib/poolparty/core/proc.rb +7 -0
  52. data/lib/poolparty/core/string.rb +72 -0
  53. data/lib/poolparty/core/symbol.rb +8 -0
  54. data/lib/{core → poolparty/core}/time.rb +15 -0
  55. data/lib/poolparty/exceptions/RemoteException.rb +12 -0
  56. data/lib/poolparty/exceptions/ResourceException.rb +7 -0
  57. data/lib/poolparty/exceptions/RuntimeException.rb +7 -0
  58. data/lib/poolparty/exceptions/SpecException.rb +7 -0
  59. data/lib/poolparty/exceptions/TemplateNotFound.rb +7 -0
  60. data/lib/poolparty/helpers/binary.rb +31 -0
  61. data/lib/poolparty/helpers/console.rb +30 -0
  62. data/lib/poolparty/helpers/display.rb +34 -0
  63. data/lib/poolparty/helpers/optioner.rb +64 -0
  64. data/lib/poolparty/helpers/provisioner_base.rb +250 -0
  65. data/lib/poolparty/helpers/provisioners/master.rb +136 -0
  66. data/lib/poolparty/helpers/provisioners/slave.rb +44 -0
  67. data/lib/poolparty/modules/cloud_resourcer.rb +89 -0
  68. data/lib/poolparty/modules/configurable.rb +34 -0
  69. data/lib/poolparty/modules/definable_resource.rb +59 -0
  70. data/lib/poolparty/modules/file_writer.rb +55 -0
  71. data/lib/poolparty/modules/method_missing_sugar.rb +53 -0
  72. data/lib/poolparty/modules/output.rb +13 -0
  73. data/lib/poolparty/modules/pretty_printer.rb +39 -0
  74. data/lib/{core/string.rb → poolparty/modules/s3_string.rb} +5 -22
  75. data/lib/{modules → poolparty/modules}/safe_instance.rb +0 -0
  76. data/lib/poolparty/monitors/base_monitor.rb +16 -0
  77. data/lib/poolparty/net/remote.rb +35 -0
  78. data/lib/poolparty/net/remote_bases/ec2.rb +148 -0
  79. data/lib/poolparty/net/remote_instance.rb +69 -0
  80. data/lib/poolparty/net/remoter.rb +224 -0
  81. data/lib/poolparty/net/remoter_base.rb +117 -0
  82. data/lib/poolparty/plugins/gem_package.rb +17 -0
  83. data/lib/poolparty/plugins/git.rb +41 -0
  84. data/lib/poolparty/plugins/line.rb +76 -0
  85. data/lib/poolparty/plugins/svn.rb +48 -0
  86. data/lib/poolparty/pool/base.rb +75 -0
  87. data/lib/poolparty/pool/cloud.rb +164 -0
  88. data/lib/poolparty/pool/custom_resource.rb +61 -0
  89. data/lib/poolparty/pool/loggable.rb +29 -0
  90. data/lib/poolparty/pool/plugin.rb +41 -0
  91. data/lib/poolparty/pool/plugin_model.rb +48 -0
  92. data/lib/poolparty/pool/pool.rb +55 -0
  93. data/lib/poolparty/pool/resource.rb +248 -0
  94. data/lib/poolparty/pool/resources/class_package.rb +64 -0
  95. data/lib/poolparty/pool/resources/conditional.rb +41 -0
  96. data/lib/poolparty/pool/resources/cron.rb +14 -0
  97. data/lib/poolparty/pool/resources/directory.rb +23 -0
  98. data/lib/poolparty/pool/resources/exec.rb +26 -0
  99. data/lib/poolparty/pool/resources/file.rb +23 -0
  100. data/lib/poolparty/pool/resources/gem.rb +14 -0
  101. data/lib/poolparty/pool/resources/host.rb +14 -0
  102. data/lib/poolparty/pool/resources/package.rb +14 -0
  103. data/lib/poolparty/pool/resources/remote_file.rb +22 -0
  104. data/lib/poolparty/pool/resources/service.rb +21 -0
  105. data/lib/poolparty/pool/resources/sshkey.rb +19 -0
  106. data/lib/poolparty/pool/resources/variable.rb +27 -0
  107. data/lib/poolparty/pool/script.rb +44 -0
  108. data/lib/poolparty/templates/authkeys +2 -0
  109. data/{config/monit/nginx.monit.conf → lib/poolparty/templates/cib.xml} +0 -0
  110. data/lib/poolparty/templates/fileserver.conf +4 -0
  111. data/lib/poolparty/templates/gem +25 -0
  112. data/{config/heartbeat.conf → lib/poolparty/templates/ha.cf} +3 -2
  113. data/{config → lib/poolparty/templates}/haproxy.conf +13 -6
  114. data/lib/poolparty/templates/namespaceauth.conf +19 -0
  115. data/lib/poolparty/templates/puppet.conf +17 -0
  116. data/lib/poolparty/version.rb +9 -0
  117. data/lib/poolpartycl.rb +3 -0
  118. data/poolparty.gemspec +56 -47
  119. data/script/destroy +14 -0
  120. data/script/generate +14 -0
  121. data/script/txt2html +82 -0
  122. data/setup.rb +1585 -0
  123. data/spec/poolparty/base_packages/haproxy_spec.rb +13 -0
  124. data/spec/poolparty/base_packages/heartbeat_spec.rb +30 -0
  125. data/spec/poolparty/bin/console_spec.rb +80 -0
  126. data/spec/poolparty/core/array_spec.rb +26 -0
  127. data/spec/poolparty/core/float.rb +13 -0
  128. data/spec/poolparty/core/hash_spec.rb +63 -0
  129. data/spec/poolparty/core/kernel_spec.rb +24 -0
  130. data/spec/poolparty/core/module_spec.rb +15 -0
  131. data/spec/poolparty/core/object_spec.rb +40 -0
  132. data/spec/poolparty/core/string_spec.rb +152 -0
  133. data/spec/poolparty/core/time_spec.rb +52 -0
  134. data/spec/poolparty/helpers/binary_spec.rb +26 -0
  135. data/spec/poolparty/helpers/display_spec.rb +13 -0
  136. data/spec/poolparty/helpers/optioner_spec.rb +39 -0
  137. data/spec/poolparty/helpers/provisioner_base_spec.rb +121 -0
  138. data/spec/poolparty/helpers/provisioners/master_spec.rb +54 -0
  139. data/spec/poolparty/helpers/provisioners/slave_spec.rb +28 -0
  140. data/spec/poolparty/modules/cloud_resourcer_spec.rb +135 -0
  141. data/spec/poolparty/modules/configurable_spec.rb +26 -0
  142. data/spec/poolparty/modules/definable_resource.rb +9 -0
  143. data/spec/poolparty/modules/file_writer_spec.rb +49 -0
  144. data/spec/poolparty/modules/s3_string_spec.rb +15 -0
  145. data/spec/poolparty/modules/tmp/willy/nilly.rb +1 -0
  146. data/spec/poolparty/net/remote_bases/ec2_spec.rb +92 -0
  147. data/spec/poolparty/net/remote_instance_spec.rb +70 -0
  148. data/spec/poolparty/net/remote_spec.rb +286 -0
  149. data/spec/poolparty/net/remoter_base_spec.rb +80 -0
  150. data/spec/poolparty/net/remoter_spec.rb +191 -0
  151. data/spec/poolparty/plugins/git_spec.rb +33 -0
  152. data/spec/poolparty/plugins/line_spec.rb +16 -0
  153. data/spec/poolparty/plugins/svn_spec.rb +16 -0
  154. data/spec/poolparty/pool/base_spec.rb +108 -0
  155. data/spec/poolparty/pool/cloud_spec.rb +299 -0
  156. data/spec/poolparty/pool/configurers/files/ruby_basic.rb +17 -0
  157. data/spec/poolparty/pool/configurers/files/ruby_plugins.rb +16 -0
  158. data/spec/poolparty/pool/configurers/ruby_spec.rb +58 -0
  159. data/spec/poolparty/pool/custom_resource_spec.rb +115 -0
  160. data/spec/poolparty/pool/example_spec.rb +112 -0
  161. data/spec/poolparty/pool/plugin_model_spec.rb +63 -0
  162. data/spec/poolparty/pool/plugin_spec.rb +85 -0
  163. data/spec/poolparty/pool/pool_spec.rb +83 -0
  164. data/spec/poolparty/pool/resource_spec.rb +224 -0
  165. data/spec/poolparty/pool/resources/class_package_spec.rb +84 -0
  166. data/spec/poolparty/pool/resources/conditional_spec.rb +38 -0
  167. data/spec/poolparty/pool/resources/cron_spec.rb +49 -0
  168. data/spec/poolparty/pool/resources/directory_spec.rb +40 -0
  169. data/spec/poolparty/pool/resources/exec_spec.rb +37 -0
  170. data/spec/poolparty/pool/resources/file_spec.rb +40 -0
  171. data/spec/poolparty/pool/resources/gem_spec.rb +16 -0
  172. data/spec/poolparty/pool/resources/host_spec.rb +28 -0
  173. data/spec/poolparty/pool/resources/package_spec.rb +44 -0
  174. data/spec/poolparty/pool/resources/remote_file_spec.rb +40 -0
  175. data/spec/poolparty/pool/resources/service_spec.rb +45 -0
  176. data/spec/poolparty/pool/resources/sshkey_spec.rb +48 -0
  177. data/spec/poolparty/pool/resources/variable_spec.rb +20 -0
  178. data/spec/poolparty/pool/script_spec.rb +51 -0
  179. data/spec/poolparty/pool/test_plugins/sshkey_test +2 -0
  180. data/{test/test_pool_party.rb → spec/poolparty/pool/test_plugins/virtual_host_template.erb} +0 -0
  181. data/spec/poolparty/pool/test_plugins/webserver.rb +46 -0
  182. data/spec/poolparty/poolparty_spec.rb +33 -0
  183. data/spec/poolparty/spec_helper.rb +120 -0
  184. data/tasks/cloud.rake +57 -0
  185. data/tasks/deployment.rake +34 -0
  186. data/tasks/development.rake +78 -0
  187. data/tasks/ec2.rake +20 -0
  188. data/tasks/environment.rake +7 -0
  189. data/tasks/instance.rake +63 -0
  190. data/tasks/server.rake +42 -0
  191. data/tasks/spec.rake +17 -0
  192. data/tasks/website.rake +17 -0
  193. data/test/test_generator_helper.rb +29 -0
  194. data/test/test_helper.rb +2 -0
  195. data/test/test_pool_spec_generator.rb +47 -0
  196. data/test/test_poolparty.rb +11 -0
  197. data/test_manifest.pp +538 -0
  198. data/website/index.html +107 -0
  199. data/website/index.txt +95 -0
  200. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  201. data/website/stylesheets/code.css +29 -0
  202. data/website/stylesheets/screen.css +147 -0
  203. data/website/template.html.erb +49 -0
  204. metadata +282 -101
  205. data/CHANGELOG +0 -4
  206. data/Manifest +0 -55
  207. data/bin/instance +0 -54
  208. data/config/config.yml +0 -23
  209. data/config/create_proxy_ami.sh +0 -582
  210. data/config/heartbeat_authkeys.conf +0 -2
  211. data/config/monit.conf +0 -8
  212. data/config/monit/haproxy.monit.conf +0 -7
  213. data/config/nginx.conf +0 -24
  214. data/lib/core/array.rb +0 -10
  215. data/lib/core/kernel.rb +0 -9
  216. data/lib/core/object.rb +0 -14
  217. data/lib/modules/callback.rb +0 -55
  218. data/lib/modules/ec2_wrapper.rb +0 -74
  219. data/lib/pool_party.rb +0 -69
  220. data/lib/pool_party/application.rb +0 -133
  221. data/lib/pool_party/init.rb +0 -4
  222. data/lib/pool_party/master.rb +0 -189
  223. data/lib/pool_party/monitors.rb +0 -13
  224. data/lib/pool_party/monitors/cpu.rb +0 -18
  225. data/lib/pool_party/monitors/memory.rb +0 -21
  226. data/lib/pool_party/monitors/web.rb +0 -18
  227. data/lib/pool_party/optioner.rb +0 -16
  228. data/lib/pool_party/os.rb +0 -11
  229. data/lib/pool_party/os/ubuntu.rb +0 -78
  230. data/lib/pool_party/remote_instance.rb +0 -180
  231. data/lib/pool_party/remoting.rb +0 -112
  232. data/lib/pool_party/scheduler.rb +0 -93
  233. data/lib/pool_party/tasks.rb +0 -220
  234. data/lib/s3/s3_object_store_folders.rb +0 -44
  235. data/spec/application_spec.rb +0 -32
  236. data/spec/callback_spec.rb +0 -65
  237. data/spec/helpers/ec2_mock.rb +0 -56
  238. data/spec/helpers/remote_instance_mock.rb +0 -11
  239. data/spec/kernel_spec.rb +0 -11
  240. data/spec/master_spec.rb +0 -147
  241. data/spec/monitor_spec.rb +0 -16
  242. data/spec/optioner_spec.rb +0 -22
  243. data/spec/poolparty_spec.rb +0 -8
  244. data/spec/remote_instance_spec.rb +0 -29
  245. data/spec/remoting_spec.rb +0 -75
  246. data/spec/spec_helper.rb +0 -38
  247. data/spec/string_spec.rb +0 -28
@@ -0,0 +1,13 @@
1
+ module PoolParty
2
+ module Output
3
+
4
+ def output(*args)
5
+ returning (@output ||= []) do |output|
6
+ args.each do |line|
7
+ (output ||= []) << line
8
+ end
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ module PoolParty
2
+ module PrettyPrinter
3
+
4
+ def pretty_print(prev="\t")
5
+ returning Array.new do |out|
6
+ out << pretty_name(prev, self)
7
+ out << pretty_options(prev, self)
8
+
9
+ if self.respond_to?(:clouds)
10
+ clouds.each do |name, cl|
11
+ out << pretty_name(prev*2, cl)
12
+ out << pretty_options(prev*2, cl) #cl.pretty_print("#{prev}\t")
13
+ end
14
+ end
15
+ if self.respond_to?(:plugins)
16
+ out << "#{prev}\t\tPlugins"
17
+ out << "#{prev}\t\t" + plugins.map {|a| a}.join("\n")
18
+ end
19
+ end.join("\n")
20
+ end
21
+
22
+ # Gather options on the object
23
+ # Do not print if the option is nil or empty.
24
+ # Also, don't show the option if the option is empty or the default option on the cloud
25
+ def pretty_options(prev, o)
26
+ return "" unless o.respond_to?(:options)
27
+ print_options = (o.respond_to?(:parent) && o.parent && o.parent.respond_to?(:options)) ?
28
+ (o.options.delete_if {|k,v| o.parent.options.has_key?(k) && o.parent.options[k] == o.options[k] && !o.options[k].nil? } ) :
29
+ o.options
30
+ print_options = print_options.map {|k,v| [k, o.send(k.to_sym).to_s] }.inject({}) { |r,e| r[e[0]] = e[1] unless o.class.default_options[e[0]] == e[1] || e[1].nil? || e[1].empty?; r }
31
+ print_options.flush_out("#{prev}\t")
32
+ end
33
+
34
+ def pretty_name(prev, o)
35
+ "#{prev}#{o.class.to_s.top_level_class.capitalize}: #{o.name if o.respond_to?(:name)}"
36
+ end
37
+
38
+ end
39
+ end
@@ -1,25 +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 runnable
18
- self.strip.gsub(/\n/, " && ")
19
- end
20
- def classify
21
- self.capitalize
22
- end
1
+ module S3String
23
2
  def bucket_objects
24
3
  AWS::S3::Bucket.objects(self)
25
4
  end
@@ -46,4 +25,8 @@ class String
46
25
  def delete_bucket
47
26
  AWS::S3::Bucket.delete(self, :force => true) if bucket_exists?
48
27
  end
28
+ end
29
+
30
+ class String
31
+ include S3String
49
32
  end
@@ -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,148 @@
1
+ require 'rubygems'
2
+ require 'EC2'
3
+
4
+ class String
5
+ def convert_from_ec2_to_ip
6
+ self.gsub(/.compute-1.amazonaws.com*/, '').gsub(/ec2-/, '').gsub(/-/, '.')
7
+ end
8
+ end
9
+ module PoolParty
10
+ module Ec2
11
+ def launch_new_instance!(num=1)
12
+ instance = ec2.run_instances(
13
+ :image_id => (ami || Base.ami),
14
+ :user_data => "",
15
+ :minCount => 1,
16
+ :maxCount => num,
17
+ :key_name => (keypair || Base.keypair),
18
+ :availability_zone => nil,
19
+ :size => "#{size || Base.size}")
20
+ begin
21
+ item = instance#.instancesSet.item
22
+ EC2ResponseObject.get_hash_from_response(item)
23
+ rescue Exception => e
24
+ end
25
+ end
26
+ # Terminate an instance by id
27
+ def terminate_instance!(instance_id=nil)
28
+ ec2.terminate_instances(:instance_id => instance_id)
29
+ end
30
+ # Describe an instance's status
31
+ def describe_instance(id=nil)
32
+ describe_instances.select {|a| a[:name] == id}[0] rescue nil
33
+ end
34
+ def describe_instances
35
+ unless @describe_instances && !@describe_instances.empty?
36
+ @id = 0
37
+ @describe_instances = get_instances_description.each_with_index do |h,i|
38
+ if h[:status] == "running"
39
+ @name = @id == 0 ? "master" : "node#{@id}"
40
+ @id += 1
41
+ else
42
+ @name = "#{h[:status]}_node#{i}"
43
+ end
44
+ h.merge!({
45
+ :name => @name,
46
+ :hostname => h[:ip],
47
+ :ip => h[:ip].convert_from_ec2_to_ip
48
+ })
49
+ end
50
+ end
51
+ @describe_instances
52
+ end
53
+ # Get the s3 description for the response in a hash format
54
+ def get_instances_description
55
+ @cached_descriptions ||= EC2ResponseObject.get_descriptions(ec2.describe_instances).sort_by {|a| a[:launching_time]}
56
+ end
57
+
58
+ # Help create a keypair for the cloud
59
+ # This is a helper to create the keypair and add them to the cloud for you
60
+ def create_keypair
61
+ return false unless keypair
62
+ unless ::File.exists?( new_keypair_path )
63
+ FileUtils.mkdir_p ::File.dirname( new_keypair_path )
64
+ Kernel.system "ec2-add-keypair #{keypair} > #{new_keypair_path} && chmod 600 #{new_keypair_path}"
65
+ end
66
+ end
67
+ # EC2 connections
68
+ def ec2
69
+ @ec2 ||= EC2::Base.new( :access_key_id => (access_key || Base.access_key),
70
+ :secret_access_key => (secret_access_key || Base.secret_access_key)
71
+ )
72
+ end
73
+
74
+ # Callback
75
+ def custom_install_tasks_for(o)
76
+ [
77
+ "# ec2 installation tasks",
78
+ "# Set hostname",
79
+ # "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",
80
+ "if [ -z \"$(grep -v '#' /etc/hosts | grep '#{o.name}')\" ]; then echo '127.0.0.1 #{o.name}' >> /etc/hosts; fi",
81
+ "hostname #{o.name}",
82
+ "echo #{o.name} > /etc/hostname"
83
+ ]
84
+ end
85
+
86
+ def custom_configure_tasks_for(o)
87
+ [
88
+ "# ec2 configuration"
89
+ ]
90
+ end
91
+
92
+ def reset!
93
+ @describe_instances = @cached_descriptions = nil
94
+ end
95
+ end
96
+ register_remote_base :Ec2
97
+ end
98
+
99
+ # Provides a simple class to wrap around the amazon responses
100
+ class EC2ResponseObject
101
+ def self.get_descriptions(resp)
102
+ rs = get_response_from(resp)
103
+
104
+ # puts rs.methods.sort - rs.ancestors.methods
105
+ out = begin
106
+ if rs.respond_to?(:instancesSet)
107
+ [EC2ResponseObject.get_hash_from_response(rs.instancesSet.item)]
108
+ else
109
+ rs.collect {|r|
110
+ if r.instancesSet.item.class == Array
111
+ r.instancesSet.item.map {|t| EC2ResponseObject.get_hash_from_response(t)}
112
+ else
113
+ [EC2ResponseObject.get_hash_from_response(r.instancesSet.item)]
114
+ end
115
+ }.flatten.reject {|a| a.nil? }
116
+ end
117
+ rescue Exception => e
118
+ # Really weird bug with amazon's ec2 gem
119
+ rs.collect {|r| EC2ResponseObject.get_hash_from_response(r)}.reject {|a| a.nil? } rescue []
120
+ end
121
+
122
+ out
123
+ end
124
+ def self.get_response_from(resp)
125
+ begin
126
+ rs = resp.reservationSet.item unless resp.reservationSet.nil?
127
+ rs ||= resp.DescribeInstancesResponse.reservationSet.item
128
+ rs ||= rs.respond_to?(:instancesSet) ? rs.instancesSet : rs
129
+ rs.reject! {|a| a.nil? || a.empty? }
130
+ rescue Exception => e
131
+ end
132
+ rs
133
+ end
134
+ def self.get_hash_from_response(resp)
135
+ begin
136
+ {
137
+ :instance_id => resp.instanceId,
138
+ :name => resp.instanceId,
139
+ :ip => resp.dnsName || "not-assigned",
140
+ :status => resp.instanceState.name,
141
+ :launching_time => resp.launchTime,
142
+ :keypair => resp.keyName
143
+ }
144
+ rescue Exception => e
145
+ nil
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,69 @@
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
+ @parent = parent
13
+ set_vars_from_options(parent.options) if parent && parent.respond_to?(:options)
14
+ set_vars_from_options(opts) unless opts.nil? || opts.empty?
15
+ on_init
16
+ end
17
+
18
+ # Callback
19
+ def on_init
20
+ end
21
+
22
+ # Is this remote instance the master?
23
+ def master?
24
+ name == "master"
25
+ end
26
+
27
+ # The remote instances is only valid if there is an ip and a name
28
+ def valid?
29
+ !(ip.nil? || name.nil?)
30
+ end
31
+
32
+ # Determine if the RemoteInstance is responding
33
+ def responding?
34
+ !responding.nil?
35
+ end
36
+
37
+ # This is how we get the current load of the instance
38
+ # The approach of this may change entirely, but the usage of
39
+ # it will always be the same
40
+ def load
41
+ current_load ||= 0.0
42
+ end
43
+
44
+ # Is this instance running?
45
+ def running?
46
+ !(status =~ /running/).nil?
47
+ end
48
+ # Is this instance pending?
49
+ def pending?
50
+ !(status =~ /pending/).nil?
51
+ end
52
+ # Is this instance terminating?
53
+ def terminating?
54
+ !(status =~ /shutting/).nil?
55
+ end
56
+ # Has this instance been terminated?
57
+ def terminated?
58
+ !(status =~ /terminated/).nil?
59
+ end
60
+
61
+ # Printing. This is how we extract the instances into the listing on the
62
+ # local side into the local listing file
63
+ def to_s
64
+ "#{name} #{ip}"
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,224 @@
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
+ # List calculation methods
91
+ #
92
+ # Are the minimum number of instances running?
93
+ def minimum_number_of_instances_are_running?
94
+ list_of_running_instances.size >= minimum_instances.to_i
95
+ end
96
+ # Can we shutdown an instance?
97
+ def can_shutdown_an_instance?
98
+ list_of_running_instances.size > minimum_instances.to_i
99
+ end
100
+ # Request to launch a number of instances
101
+ def request_launch_new_instances(num=1)
102
+ out = []
103
+ num.times {out << launch_new_instance!}
104
+ out
105
+ end
106
+ # Let's terminate an instance that is not the master instance
107
+ def request_termination_of_non_master_instance
108
+ inst = nonmaster_nonterminated_instances.last
109
+ terminate_instance!(inst.instance_id) if inst
110
+ end
111
+ # Can we start a new instance?
112
+ def can_start_a_new_instance?
113
+ maximum_number_of_instances_are_not_running?
114
+ end
115
+ # Are the maximum number of instances running?
116
+ def maximum_number_of_instances_are_not_running?
117
+ list_of_running_instances.size < maximum_instances.to_i
118
+ end
119
+ # Launch new instance while waiting for the number of pending instances
120
+ # to be zero before actually launching. This ensures that we only
121
+ # launch one instance at a time
122
+ def request_launch_one_instance_at_a_time
123
+ when_no_pending_instances { launch_new_instance! }
124
+ end
125
+ # A convenience method for waiting until there are no more
126
+ # pending instances and then running the block
127
+ def when_no_pending_instances(&block)
128
+ reset!
129
+ if list_of_pending_instances.size == 0
130
+ block.call if block
131
+ else
132
+ wait "5.seconds"
133
+ when_no_pending_instances(&block)
134
+ end
135
+ end
136
+
137
+ # This will launch the minimum_instances if the minimum number of instances are not running
138
+ # If the minimum number of instances are not running and if we can start a new instance
139
+ def launch_minimum_number_of_instances
140
+ if can_start_a_new_instance? && !minimum_number_of_instances_are_running?
141
+ list_of_pending_instances.size == 0 ? request_launch_one_instance_at_a_time : wait("5.seconds")
142
+ reset!
143
+ launch_minimum_number_of_instances unless minimum_number_of_instances_are_running?
144
+ end
145
+ end
146
+ # Launch the master and let the master handle the starting of the cloud
147
+ # We should only launch an instance if there are no pending instances, in the case
148
+ # that the master has launched, but is still pending
149
+ # and if the master is not running AND we can start a new instance
150
+ # Then wait for the master to launch
151
+ def launch_and_configure_master!(testing=false)
152
+ request_launch_new_instances(1) if list_of_pending_instances.size.zero? && can_start_a_new_instance? && !is_master_running?
153
+
154
+ when_no_pending_instances do
155
+ wait "10.seconds"
156
+ hide_output { Provisioner.provision_master(self, testing) }
157
+ end
158
+
159
+ end
160
+ def is_master_running?
161
+ !list_of_running_instances.select {|a| a.name == "master"}.first.nil?
162
+ end
163
+ # Stub method for the time being to handle expansion of the cloud
164
+ def should_expand_cloud?(force=false)
165
+ force || false
166
+ end
167
+ # Stub method for the time being to handle the contraction of the cloud
168
+ def should_contract_cloud?(force=false)
169
+ force || false
170
+ end
171
+ # Expand the cloud
172
+ # If we can start a new instance and the load requires us to expand
173
+ # the cloud, then we should request_launch_new_instances
174
+ # Wait for the instance to boot up and when it does come back
175
+ # online, then provision it as a slave, this way, it is ready for action from the
176
+ # get go
177
+ def expand_cloud_if_necessary(force=false)
178
+ if can_start_a_new_instance? && should_expand_cloud?(force)
179
+ @out = request_launch_new_instances(1)
180
+
181
+ reset!
182
+ when_no_pending_instances do
183
+ @ri = list_of_running_instances.last
184
+ PoolParty::Provisioner.provision_slave(@ri, self, !force)
185
+ end
186
+ end
187
+ end
188
+ # Contract the cloud
189
+ # If we can shutdown an instnace and the load allows us to contract
190
+ # the cloud, then we should request_termination_of_non_master_instance
191
+ def contract_cloud_if_necessary(force=false)
192
+ if can_shutdown_an_instance?
193
+ request_termination_of_non_master_instance if should_contract_cloud?(force)
194
+ end
195
+ end
196
+
197
+ # Rsync command to the instance
198
+ def rsync_storage_files_to(instance=nil)
199
+ hide_output do
200
+ Kernel.system "#{rsync_storage_files_to_command(instance)}" if instance
201
+ end
202
+ end
203
+ # Take the rsync command and execute it on the system
204
+ # if there is an instance given
205
+ def run_command_on(cmd, instance=nil)
206
+ Kernel.system "#{run_command_on_command(cmd, instance)}" if instance
207
+ end
208
+
209
+ # Ssh into the instance given
210
+ def ssh_into(instance=nil)
211
+ Kernel.system "#{ssh_command(instance)}" if instance
212
+ end
213
+ # Find the instance by the number given
214
+ # and then ssh into the instance
215
+ def ssh_into_instance_number(num=0)
216
+ ssh_into( get_instance_by_number( num || 0 ) )
217
+ end
218
+
219
+ def self.included(receiver)
220
+ receiver.extend self
221
+ end
222
+ end
223
+ end
224
+ end