auser-poolparty 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CHANGELOG +12 -0
  2. data/Manifest +115 -0
  3. data/README.txt +140 -0
  4. data/Rakefile +27 -0
  5. data/bin/instance +61 -0
  6. data/bin/pool +62 -0
  7. data/config/cloud_master_takeover +17 -0
  8. data/config/create_proxy_ami.sh +582 -0
  9. data/config/haproxy.conf +29 -0
  10. data/config/heartbeat.conf +8 -0
  11. data/config/heartbeat_authkeys.conf +2 -0
  12. data/config/installers/ubuntu_install.sh +77 -0
  13. data/config/monit/haproxy.monit.conf +7 -0
  14. data/config/monit/nginx.monit.conf +0 -0
  15. data/config/monit.conf +9 -0
  16. data/config/nginx.conf +24 -0
  17. data/config/reconfigure_instances_script.sh +18 -0
  18. data/config/sample-config.yml +23 -0
  19. data/config/scp_instances_script.sh +12 -0
  20. data/lib/core/array.rb +13 -0
  21. data/lib/core/exception.rb +9 -0
  22. data/lib/core/float.rb +13 -0
  23. data/lib/core/hash.rb +11 -0
  24. data/lib/core/kernel.rb +12 -0
  25. data/lib/core/module.rb +22 -0
  26. data/lib/core/object.rb +18 -0
  27. data/lib/core/proc.rb +15 -0
  28. data/lib/core/string.rb +49 -0
  29. data/lib/core/time.rb +41 -0
  30. data/lib/modules/callback.rb +133 -0
  31. data/lib/modules/ec2_wrapper.rb +82 -0
  32. data/lib/modules/safe_instance.rb +31 -0
  33. data/lib/modules/vlad_override.rb +82 -0
  34. data/lib/poolparty/application.rb +170 -0
  35. data/lib/poolparty/init.rb +6 -0
  36. data/lib/poolparty/master.rb +329 -0
  37. data/lib/poolparty/monitors/cpu.rb +19 -0
  38. data/lib/poolparty/monitors/memory.rb +26 -0
  39. data/lib/poolparty/monitors/web.rb +23 -0
  40. data/lib/poolparty/monitors.rb +13 -0
  41. data/lib/poolparty/optioner.rb +16 -0
  42. data/lib/poolparty/plugin.rb +43 -0
  43. data/lib/poolparty/plugin_manager.rb +67 -0
  44. data/lib/poolparty/provider/packages/essential.rb +6 -0
  45. data/lib/poolparty/provider/packages/git.rb +4 -0
  46. data/lib/poolparty/provider/packages/haproxy.rb +20 -0
  47. data/lib/poolparty/provider/packages/heartbeat.rb +4 -0
  48. data/lib/poolparty/provider/packages/monit.rb +6 -0
  49. data/lib/poolparty/provider/packages/rsync.rb +4 -0
  50. data/lib/poolparty/provider/packages/ruby.rb +37 -0
  51. data/lib/poolparty/provider/packages/s3fuse.rb +11 -0
  52. data/lib/poolparty/provider/provider.rb +60 -0
  53. data/lib/poolparty/provider.rb +2 -0
  54. data/lib/poolparty/remote_instance.rb +216 -0
  55. data/lib/poolparty/remoter.rb +106 -0
  56. data/lib/poolparty/remoting.rb +112 -0
  57. data/lib/poolparty/scheduler.rb +103 -0
  58. data/lib/poolparty/tasks/cloud.rake +57 -0
  59. data/lib/poolparty/tasks/development.rake +38 -0
  60. data/lib/poolparty/tasks/ec2.rake +20 -0
  61. data/lib/poolparty/tasks/instance.rake +63 -0
  62. data/lib/poolparty/tasks/plugins.rake +30 -0
  63. data/lib/poolparty/tasks/server.rake +42 -0
  64. data/lib/poolparty/tasks.rb +29 -0
  65. data/lib/poolparty/tmp.rb +46 -0
  66. data/lib/poolparty.rb +105 -0
  67. data/lib/s3/s3_object_store_folders.rb +44 -0
  68. data/misc/basics_tutorial.txt +142 -0
  69. data/poolparty.gemspec +72 -0
  70. data/spec/application_spec.rb +39 -0
  71. data/spec/callback_spec.rb +194 -0
  72. data/spec/core_spec.rb +15 -0
  73. data/spec/helpers/ec2_mock.rb +44 -0
  74. data/spec/kernel_spec.rb +11 -0
  75. data/spec/master_spec.rb +203 -0
  76. data/spec/monitors/cpu_monitor_spec.rb +38 -0
  77. data/spec/monitors/memory_spec.rb +50 -0
  78. data/spec/monitors/misc_monitor_spec.rb +50 -0
  79. data/spec/monitors/web_spec.rb +39 -0
  80. data/spec/optioner_spec.rb +22 -0
  81. data/spec/plugin_manager_spec.rb +31 -0
  82. data/spec/plugin_spec.rb +101 -0
  83. data/spec/pool_binary_spec.rb +10 -0
  84. data/spec/poolparty_spec.rb +15 -0
  85. data/spec/provider_spec.rb +17 -0
  86. data/spec/remote_instance_spec.rb +149 -0
  87. data/spec/remoter_spec.rb +65 -0
  88. data/spec/remoting_spec.rb +84 -0
  89. data/spec/scheduler_spec.rb +75 -0
  90. data/spec/spec_helper.rb +39 -0
  91. data/spec/string_spec.rb +28 -0
  92. data/web/static/conf/nginx.conf +22 -0
  93. data/web/static/site/images/balloon.png +0 -0
  94. data/web/static/site/images/cb.png +0 -0
  95. data/web/static/site/images/clouds.png +0 -0
  96. data/web/static/site/images/railsconf_preso_img.png +0 -0
  97. data/web/static/site/index.html +71 -0
  98. data/web/static/site/javascripts/application.js +3 -0
  99. data/web/static/site/javascripts/corner.js +178 -0
  100. data/web/static/site/javascripts/jquery-1.2.6.pack.js +11 -0
  101. data/web/static/site/misc.html +42 -0
  102. data/web/static/site/storage/pool_party_presentation.pdf +0 -0
  103. data/web/static/site/stylesheets/application.css +100 -0
  104. data/web/static/site/stylesheets/reset.css +17 -0
  105. data/web/static/src/layouts/application.haml +25 -0
  106. data/web/static/src/pages/index.haml +25 -0
  107. data/web/static/src/pages/misc.haml +5 -0
  108. data/web/static/src/stylesheets/application.sass +100 -0
  109. metadata +260 -0
@@ -0,0 +1,77 @@
1
+ #!/bin/sh
2
+
3
+ apt-get clean && apt-get update
4
+
5
+ echo 'increasing the memory for apt'
6
+ echo 'APT::Cache-Limit "516777216";' >> /etc/apt/apt.conf.d/70debconf
7
+
8
+ echo 'running ubuntu_install.sh'
9
+ rm -rf /usr/local/src/*
10
+
11
+ echo 'updating apt'
12
+ apt-get update
13
+ # Get the essentials
14
+ echo 'building essentials'
15
+ apt-get -y install build-essential
16
+
17
+ echo 'Installing git'
18
+ apt-get -y install git-core rsync
19
+
20
+ # Install ruby
21
+ echo 'Installing ruby...'
22
+ apt-get -y install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8 libreadline-ruby1.8 libruby1.8
23
+ ln -sf /usr/bin/ruby1.8 /usr/local/bin/ruby
24
+ ln -sf /usr/bin/ri1.8 /usr/local/bin/ri
25
+ ln -sf /usr/bin/rdoc1.8 /usr/local/bin/rdoc
26
+ ln -sf /usr/bin/irb1.8 /usr/local/bin/irb
27
+
28
+ # Install rubygems
29
+ echo '-- Installing Rubygems'
30
+ # if [[ ! -f /usr/local/src/rubygems-1.1.1 ]]; then
31
+ cd /usr/local/src
32
+ wget http://rubyforge.org/frs/download.php/35283/rubygems-1.1.1.tgz
33
+ tar -xzf rubygems-1.1.1.tgz
34
+ rm rubygems-1.1.1.tgz
35
+ cd rubygems-1.1.1
36
+ ruby setup.rb --no-rdoc --no-ri
37
+ ln -sf /usr/bin/gem1.8 /usr/bin/gem
38
+ # fi
39
+
40
+ # Install gems
41
+ # if [[ which pool | grep -v "bin" ]]; then
42
+ gem update --system
43
+ gem install SQS aws-s3 amazon-ec2 aska rake poolparty --no-rdoc --no-ri --no-test
44
+ # fi
45
+
46
+ # Install haproxy
47
+ # if [[ which haproxy | grep -v "bin" ]]; then
48
+ apt-get -y install haproxy
49
+ echo 'Configuring haproxy logging'
50
+ sed -i 's/ENABLED=0/ENABLED=1/g' /etc/default/haproxy
51
+ sed -i 's/SYSLOGD=\"\"/SYSLOGD=\"-r\"/g' /etc/default/syslogd
52
+ echo 'local0.* /var/log/haproxy.log' >> /etc/syslog.conf && /etc/init.d/sysklogd restart
53
+ /etc/init.d/haproxy restart
54
+ # fi
55
+ # Install heartbeat
56
+ # if [[ which heartbeat | grep -v "bin" ]]; then
57
+ apt-get -y install heartbeat-2
58
+ # fi
59
+
60
+ # Install monit
61
+ # if [[ which monit | grep -v "bin" ]]; then
62
+ apt-get -y install monit
63
+ sudo mkdir /etc/monit
64
+ sed -i 's/startup=0/startup=1/g' /etc/default/monit
65
+ /etc/init.d/monit start
66
+ # fi
67
+
68
+ # Install s3fuse
69
+ # if [[ which s3fs | grep -v "bin" ]]; then
70
+ apt-get install -y libcurl4-openssl-dev libxml2-dev libfuse-dev
71
+ cd /usr/local/src && wget http://s3fs.googlecode.com/files/s3fs-r166-source.tar.gz
72
+ tar -zxf s3fs-r166-source.tar.gz
73
+ cd s3fs/ && make
74
+ mv s3fs /usr/bin
75
+ # fi
76
+
77
+ echo ' - installed from script!'
@@ -0,0 +1,7 @@
1
+ check process haproxy with pidfile /var/run/haproxy.pid
2
+ start program = "/usr/sbin/haproxy -f /etc/haproxy.cfg -p /var/run/haproxy.pid"
3
+ stop program = "/usr/bin/killall -9 haproxy"
4
+ if totalmem is greater than 100.0 MB for 4 cycles then restart
5
+ if cpu is greater than 50% for 2 cycles then alert
6
+ if cpu is greater than 80% for 3 cycles then restart
7
+ if loadavg(5min) greater than 10 for 8 cycles then restart
File without changes
data/config/monit.conf ADDED
@@ -0,0 +1,9 @@
1
+ # Configuration for Monit, a monitoring tool
2
+ set daemon 20 # Perform a check every 20 seconds
3
+ set logfile /var/log/monit.log
4
+
5
+ set httpd port 2812 and
6
+ use address 0.0.0.0
7
+ allow localhost
8
+
9
+ include /etc/monit.d/*
data/config/nginx.conf ADDED
@@ -0,0 +1,24 @@
1
+ user usr usr;
2
+ worker_processes 2;
3
+
4
+ http {
5
+ sendfile on;
6
+ tcp_nopush on;
7
+
8
+ keepalive_timeout 65;
9
+ tcp_nodelay on;
10
+
11
+ upstream fast_mongrels { server 127.0.0.1:4567; }
12
+
13
+ server {
14
+ listen 80;
15
+ server_name srv;
16
+ root /apps/pool-party;
17
+
18
+ location / {
19
+ proxy_pass http://fast_mongrels;
20
+ break;
21
+ }
22
+
23
+ }
24
+ }
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+
3
+ # Reconfigure master
4
+ :config_master
5
+ # Start this instance's master maintain script
6
+ :start_pool_maintain
7
+ # Make the ha.d/resource.d
8
+ sudo mkdir /etc/ha.d/resource.d/
9
+ # Set this hostname as appropriate in the cloud
10
+ :set_hostname
11
+ # Configure heartbeat
12
+ sudo mkdir /etc/ha.d/resource.d/
13
+ # Start heartbeat
14
+ /etc/init.d/heartbeat start
15
+ # Start s3fs
16
+ :start_s3fs
17
+ # Configure monit
18
+ mkdir /etc/monit.d
@@ -0,0 +1,23 @@
1
+ :app_name: "test_app"
2
+ :user_id: "1619-6456-1164"
3
+ :access_key: ""
4
+ :secret_access_key: ""
5
+ :ami: "ami-4f7a9f26"
6
+ :size: small
7
+ :polling_time: "30.seconds"
8
+ :minimum_instances: 2
9
+ :maximum_instances: 3
10
+ :ec2_dir: "/Users/auser/.ec2"
11
+ :keypair: auser
12
+ :os: ubuntu
13
+ :host_port: 80
14
+ :client_port: 8001
15
+ :shared_bucket: "pool-party-app-data"
16
+ :services: nginx
17
+ :environment: production
18
+ :contract_when:
19
+ web > 10
20
+ cpu < 0.2
21
+ :expand_when:
22
+ cpu > 0.45
23
+ web < 10
@@ -0,0 +1,12 @@
1
+ #!/bin/sh
2
+
3
+ :cloud_master_takeover
4
+ :config_file
5
+ :authkeys
6
+ :ha_d
7
+ :haresources
8
+ :resources
9
+ :monitrc
10
+ :monit_d
11
+ :haproxy
12
+ :hosts
data/lib/core/array.rb ADDED
@@ -0,0 +1,13 @@
1
+ =begin rdoc
2
+ Array extensions
3
+ =end
4
+ require "enumerator"
5
+ class Array
6
+ # Collection with the index
7
+ def collect_with_index &block
8
+ self.enum_for(:each_with_index).collect &block
9
+ end
10
+ def runnable
11
+ self.join(" \n ").runnable
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ =begin rdoc
2
+ Exception overloads
3
+ =end
4
+ class Exception
5
+ # Gives us a nice_message for exceptions
6
+ def nice_message(padding="")
7
+ "#{padding}#{message}\n#{padding}" + backtrace.join("\n#{padding}")
8
+ end
9
+ end
data/lib/core/float.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Float
2
+ def round_to(x)
3
+ (self * 10**x).round.to_f / 10**x
4
+ end
5
+
6
+ def ceil_to(x)
7
+ (self * 10**x).ceil.to_f / 10**x
8
+ end
9
+
10
+ def floor_to(x)
11
+ (self * 10**x).floor.to_f / 10**x
12
+ end
13
+ end
data/lib/core/hash.rb ADDED
@@ -0,0 +1,11 @@
1
+ =begin rdoc
2
+ Hash extentions
3
+ =end
4
+ class Hash
5
+ def safe_merge(other_hash)
6
+ merge(other_hash.delete_if {|k,v| has_key?(k) })
7
+ end
8
+ def safe_merge!(other_hash)
9
+ merge!(other_hash.delete_if {|k,v| has_key?(k) })
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ =begin rdoc
2
+ Kernel overloads
3
+ =end
4
+ module Kernel
5
+ # Nice wait instead of sleep
6
+ def wait(time=10)
7
+ sleep time.is_a?(String) ? eval(time) : time
8
+ end
9
+ def as(klass_or_obj, &block)
10
+ block.in_context(klass_or_obj).call
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ # Module overloads
2
+ class Module
3
+ # Gives us alias_method_chain from rails
4
+ def alias_method_chain(target, feature)
5
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
6
+ yield(aliased_target, punctuation) if block_given?
7
+
8
+ with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
9
+
10
+ alias_method without_method, target
11
+ alias_method target, with_method
12
+
13
+ case
14
+ when public_method_defined?(without_method)
15
+ public target
16
+ when protected_method_defined?(without_method)
17
+ protected target
18
+ when private_method_defined?(without_method)
19
+ private target
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ =begin rdoc
2
+ Basic, add an alias_method to the object class
3
+ Add returning to the object
4
+ =end
5
+ class Object
6
+ def alias_method(new_id, original_id)
7
+ original = self.method(original_id).to_proc
8
+ define_method(new_id){|*args| original.call(*args)}
9
+ end
10
+ def returning(receiver)
11
+ yield receiver
12
+ receiver
13
+ end
14
+ def extended(&block)
15
+ block.in_context(self).call
16
+ self
17
+ end
18
+ end
data/lib/core/proc.rb ADDED
@@ -0,0 +1,15 @@
1
+ class Proc
2
+ def bind(object)
3
+ block, time = self, Time.now
4
+ (class << object; self; end).class_eval do
5
+ method_name = "__bind_#{time.to_i}_#{time.usec}"
6
+ define_method(method_name, &block)
7
+ method = instance_method(method_name)
8
+ remove_method(method_name)
9
+ method
10
+ end.bind(object)
11
+ end
12
+ def in_context(klass_or_obj)
13
+ klass_or_obj.send(:eval, self.to_ruby)
14
+ end
15
+ end
@@ -0,0 +1,49 @@
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
23
+ def bucket_objects
24
+ AWS::S3::Bucket.objects(self)
25
+ end
26
+ def bucket_object(key)
27
+ AWS::S3::S3Object.value key, self if bucket_object_exists?(key)
28
+ end
29
+ def bucket_object_exists?(key)
30
+ AWS::S3::S3Object.exists? key, self
31
+ end
32
+ def store_bucket_value(key, data)
33
+ AWS::S3::S3Object.store key, data, self unless bucket_object_exists?(key)
34
+ end
35
+ def delete_bucket_value(key)
36
+ AWS::S3::S3Object.delete(key, self) if bucket_object_exists?(key)
37
+ end
38
+ def bucket_exists?
39
+ begin
40
+ AWS::S3::Bucket.find(self)
41
+ return true
42
+ rescue
43
+ return false
44
+ end
45
+ end
46
+ def delete_bucket
47
+ AWS::S3::Bucket.delete(self, :force => true) if bucket_exists?
48
+ end
49
+ end
data/lib/core/time.rb ADDED
@@ -0,0 +1,41 @@
1
+ =begin rdoc
2
+ Based off the rails Numeric class.
3
+ Gives us the ability to use nice phrases such as
4
+ 30.seconds, 5.days, etc.
5
+ =end
6
+ class Numeric
7
+ def ago(time = Time.now)
8
+ time - self
9
+ end
10
+ alias :until :ago
11
+
12
+ def since(time = Time.now)
13
+ time + self
14
+ end
15
+ alias :from_now :since
16
+
17
+ def seconds
18
+ self
19
+ end
20
+ alias :second :seconds
21
+
22
+ def minutes
23
+ self * 60
24
+ end
25
+ alias :minute :minutes
26
+
27
+ def hours
28
+ self * 60.minutes
29
+ end
30
+ alias :hour :hours
31
+
32
+ def days
33
+ self * 24.hours
34
+ end
35
+ alias :day :days
36
+
37
+ def weeks
38
+ self * 7.days
39
+ end
40
+ alias :week :weeks
41
+ end
@@ -0,0 +1,133 @@
1
+ =begin rdoc
2
+ Basic callbacks
3
+ =end
4
+ module PoolParty
5
+ module Callbacks
6
+ module ClassMethods
7
+ def define_callback_module(mod)
8
+ callbacks << mod
9
+ end
10
+ def define_callback_class(cla)
11
+ classes << cla
12
+ end
13
+ def callback(type, m, *args, &block)
14
+ arr = []
15
+ args.each do |arg|
16
+ arr << case arg.class.to_s
17
+ when "Hash"
18
+ arg.collect do |meth, klass|
19
+ case klass.class.to_s
20
+ when "String"
21
+ define_callback_class(klass)
22
+ "self.#{klass.to_s.downcase}.#{meth}(self)"
23
+ else
24
+ "#{klass}.send :#{meth}, self"
25
+ end
26
+ end
27
+ when "Symbol"
28
+ "self.send :#{arg}, self"
29
+ end
30
+ end
31
+
32
+ string = ""
33
+ if block_given?
34
+ num = store_proc(block.to_proc)
35
+ arr << <<-EOM
36
+ self.class.get_proc(#{num}).bind(self).call
37
+ EOM
38
+ end
39
+
40
+ string = create_eval_for_mod_with_string_and_type!(m, type) do
41
+ arr.join("\n")
42
+ end
43
+
44
+ mMode = Module.new {eval string}
45
+
46
+ define_callback_module(mMode)
47
+ end
48
+ def before(m, *args, &block)
49
+ callback(:before, m, *args, &block)
50
+ end
51
+ def after(m, *args, &block)
52
+ callback(:after, m, *args, &block)
53
+ end
54
+
55
+ def create_eval_for_mod_with_string_and_type!(meth, type=nil, &block)
56
+ str = ""
57
+ case type
58
+ when :before
59
+ str << <<-EOD
60
+ def #{meth}(*args)
61
+ #{yield}
62
+ super
63
+ end
64
+ EOD
65
+ when :after
66
+ str << <<-EOD
67
+ def #{meth}(*args)
68
+ super
69
+ #{yield}
70
+ end
71
+ EOD
72
+ else
73
+ str << <<-EOD
74
+ def #{meth}(*args)
75
+ #{yield}
76
+ end
77
+ EOD
78
+ end
79
+ str
80
+ end
81
+
82
+ def callbacks
83
+ @callbacks ||= []
84
+ end
85
+ def classes
86
+ @classes ||= []
87
+ end
88
+ end
89
+
90
+ module InstanceMethods
91
+ def initialize(*args)
92
+ extend_callbacks
93
+ extend_callback_methods
94
+ end
95
+
96
+ def extend_callback_methods
97
+ unless self.class.classes.empty?
98
+ self.class.classes.each do |klass|
99
+ m = %{def #{klass.to_s.downcase};@#{klass.to_s.downcase} ||= #{klass}.new;end}
100
+ self.class.class_eval m unless self.class.method_defined?(m)
101
+ end
102
+ end
103
+ end
104
+
105
+ def extend_callbacks
106
+ unless self.class.callbacks.empty?
107
+ self.class.callbacks.each do |mod|
108
+ self.extend(mod)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ module ProcStoreMethods
115
+ def store_proc(proc)
116
+ proc_storage << proc
117
+ proc_storage.index(proc)
118
+ end
119
+ def get_proc(num)
120
+ proc_storage[num]
121
+ end
122
+ def proc_storage
123
+ @proc_store ||= []
124
+ end
125
+ end
126
+
127
+ def self.included(receiver)
128
+ receiver.extend ClassMethods
129
+ receiver.extend ProcStoreMethods
130
+ receiver.send :include, InstanceMethods
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,82 @@
1
+ module PoolParty
2
+ extend self
3
+
4
+ module Ec2Wrapper
5
+
6
+ module ClassMethods
7
+ end
8
+
9
+ module InstanceMethods
10
+ # Run a new instance, with the user_data and the ami described in the config
11
+ def launch_new_instance!
12
+ instance = ec2.run_instances(
13
+ :image_id => Application.ami,
14
+ :user_data => "#{Application.launching_user_data}",
15
+ :minCount => 1,
16
+ :maxCount => 1,
17
+ :key_name => Application.keypair,
18
+ :size => "#{Application.size}")
19
+
20
+ item = instance.RunInstancesResponse.instancesSet.item
21
+ EC2ResponseObject.get_hash_from_response(item)
22
+ end
23
+ # Shutdown the instance by instance_id
24
+ def terminate_instance!(instance_id)
25
+ ec2.terminate_instances(:instance_id => instance_id)
26
+ end
27
+ def associate_address_with(ip, instance_id)
28
+ ec2.associate_address(:instance_id => instance_id, :public_ip => ip)
29
+ end
30
+ # Instance description
31
+ def describe_instance(id)
32
+ instance = ec2.describe_instances(:instance_id => id)
33
+ item = instance.DescribeInstancesResponse.reservationSet.item.instancesSet.item
34
+ EC2ResponseObject.get_hash_from_response(item)
35
+ end
36
+ # Get instance by id
37
+ def get_instance_by_id(id)
38
+ get_instances_description.select {|a| a.instance_id == id}[0] rescue nil
39
+ end
40
+ # Get the s3 description for the response in a hash format
41
+ def get_instances_description
42
+ @cached_descriptions ||= EC2ResponseObject.get_descriptions(ec2.describe_instances)
43
+ end
44
+
45
+ # EC2 connections
46
+ def ec2
47
+ @ec2 ||= EC2::Base.new(:access_key_id => Application.access_key, :secret_access_key => Application.secret_access_key)
48
+ end
49
+ end
50
+
51
+ def self.included(receiver)
52
+ receiver.extend ClassMethods
53
+ receiver.send :include, InstanceMethods
54
+ end
55
+ end
56
+ # Provides a simple class to wrap around the amazon responses
57
+ class EC2ResponseObject
58
+ def self.get_descriptions(resp)
59
+ rs = resp.DescribeInstancesResponse.reservationSet.item
60
+ rs = rs.respond_to?(:instancesSet) ? rs.instancesSet : rs
61
+ out = begin
62
+ rs.reject {|a| a.empty? }.collect {|r| EC2ResponseObject.get_hash_from_response(r.instancesSet.item)}.reject {|a| a.nil? }
63
+ rescue Exception => e
64
+ begin
65
+ # Really weird bug with amazon's ec2 gem
66
+ rs.reject {|a| a.empty? }.collect {|r| EC2ResponseObject.get_hash_from_response(r)}.reject {|a| a.nil? }
67
+ rescue Exception => e
68
+ []
69
+ end
70
+ end
71
+ out
72
+ end
73
+ def self.get_hash_from_response(resp)
74
+ {
75
+ :instance_id => resp.instanceId,
76
+ :ip => resp.dnsName,
77
+ :status => resp.instanceState.name,
78
+ :launching_time => resp.launchTime
79
+ } rescue nil
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,31 @@
1
+ =begin rdoc
2
+ Make a command thread-safe
3
+ =end
4
+ require "monitor"
5
+ module PoolParty
6
+ extend self
7
+
8
+ module ThreadSafeInstance
9
+
10
+ module ClassMethods
11
+ def make_safe(meth)
12
+ original_method = "_unsafe_#{meth}_"
13
+ alias_method original_method, meth
14
+ define_method(meth) {|*args| self.class.synchronize { self.send(original_method) } }
15
+ self
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ def make_safe meth
21
+ self.class.make_safe meth
22
+ end
23
+ end
24
+
25
+ def self.included(receiver)
26
+ receiver.extend MonitorMixin
27
+ receiver.extend ClassMethods
28
+ receiver.send :include, InstanceMethods
29
+ end
30
+ end
31
+ end