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,112 @@
1
+ module PoolParty
2
+ extend self
3
+
4
+ class Remoting
5
+ include PoolParty
6
+ include Ec2Wrapper
7
+ include Scheduler
8
+
9
+ # == GENERAL METHODS
10
+ # == LISTING
11
+ # List all the running instances associated with this account
12
+ def list_of_running_instances
13
+ list_of_nonterminated_instances.select {|a| a[:status] =~ /running/}
14
+ end
15
+ # Get a list of the pending instances
16
+ def list_of_pending_instances
17
+ list_of_nonterminated_instances.select {|a| a[:status] =~ /pending/}
18
+ end
19
+ # list of shutting down instances
20
+ def list_of_terminating_instances
21
+ list_of_nonterminated_instances.select {|a| a[:status] =~ /shutting/}
22
+ end
23
+ # list all the nonterminated instances
24
+ def list_of_nonterminated_instances
25
+ list_of_instances.reject {|a| a[:status] =~ /terminated/}
26
+ end
27
+ # List the instances, regardless of their states
28
+ def list_of_instances
29
+ get_instances_description
30
+ end
31
+ # Get number of pending instances
32
+ def number_of_pending_instances
33
+ list_of_pending_instances.size
34
+ end
35
+ # get the number of running instances
36
+ def number_of_running_instances
37
+ list_of_running_instances.size
38
+ end
39
+ # get the number of pending and running instances
40
+ def number_of_pending_and_running_instances
41
+ number_of_running_instances + number_of_pending_instances
42
+ end
43
+ # == LAUNCHING
44
+ # Request to launch a new instance
45
+ def request_launch_new_instance
46
+ if can_start_a_new_instance?
47
+ request_launch_one_instance_at_a_time
48
+ return true
49
+ else
50
+ return false
51
+ end
52
+ end
53
+ # Can we start a new instance?
54
+ def can_start_a_new_instance?
55
+ maximum_number_of_instances_are_not_running?
56
+ end
57
+ # Are the maximum number of instances running?
58
+ def maximum_number_of_instances_are_not_running?
59
+ list_of_running_instances.size < Application.maximum_instances
60
+ end
61
+ # Request to launch a number of instances
62
+ def request_launch_new_instances(num=1)
63
+ out = []
64
+ num.times {out << request_launch_one_instance_at_a_time}
65
+ out
66
+ end
67
+ # Launch one instance at a time
68
+ def request_launch_one_instance_at_a_time
69
+ reset!
70
+ while !number_of_pending_instances.zero?
71
+ wait "5.seconds"
72
+ reset!
73
+ end
74
+ return launch_new_instance!
75
+ end
76
+ # == SHUTDOWN
77
+ # Terminate all running instances
78
+ def request_termination_of_running_instances
79
+ list_of_running_instances.each {|a| terminate_instance!(a[:instance_id])}
80
+ end
81
+ # Request termination of all instances regardless of their state (includes pending instances)
82
+ def request_termination_of_all_instances
83
+ get_instances_description.each {|a| terminate_instance!(a[:instance_id])}
84
+ end
85
+ # Terminate instance by id
86
+ def request_termination_of_instance(id)
87
+ if can_shutdown_an_instance?
88
+ terminate_instance! id
89
+ return true
90
+ else
91
+ return false
92
+ end
93
+ end
94
+ # Can we shutdown an instance?
95
+ def can_shutdown_an_instance?
96
+ minimum_number_of_instances_are_running?
97
+ end
98
+ # Are the minimum number of instances running?
99
+ def minimum_number_of_instances_are_running?
100
+ list_of_running_instances.size > Application.minimum_instances
101
+ end
102
+ # Get the cached running_instances
103
+ def running_instances
104
+ @running_instances ||= update_instance_values
105
+ end
106
+ # Update the instance values
107
+ def update_instance_values
108
+ @running_instances = list_of_running_instances.collect {|a| RemoteInstance.new(a) }.sort
109
+ end
110
+ end
111
+
112
+ end
@@ -0,0 +1,103 @@
1
+ module PoolParty
2
+ extend self
3
+ # Schedule tasks container
4
+ class ScheduleTasks
5
+ include ThreadSafeInstance
6
+ # Initialize tasks array and run
7
+ def tasks
8
+ @_tasks ||= []
9
+ end
10
+ # Synchronize the running threaded tasks
11
+ def run
12
+ unless tasks.empty?
13
+ self.class.synchronize do
14
+ tasks.reject!{|a|
15
+ begin
16
+ a.run
17
+ a.join
18
+ rescue Exception => e
19
+ puts "There was an error in the task: #{e} #{e.backtrace.join("\n")}"
20
+ end
21
+ true
22
+ }
23
+ end
24
+ end
25
+ end
26
+ # Add a task in a new thread
27
+ def <<(a, *args)
28
+ thread = Thread.new(a) do |task|
29
+ Thread.stop
30
+ Thread.current[:callee] = task
31
+ a.call args
32
+ end
33
+ tasks << thread
34
+ end
35
+ alias_method :push, :<<
36
+ # In the ThreadSafeInstance
37
+ make_safe :<<
38
+ end
39
+ # Scheduler class
40
+ module Scheduler
41
+ attr_reader :tasker
42
+ # Get the tasks or ScheduleTasks
43
+ def _tasker
44
+ @_tasker ||= ScheduleTasks.new
45
+ end
46
+ # Add a task to the new threaded block
47
+ def add_task(&blk)
48
+ _tasker.push proc{blk.call}
49
+ end
50
+ # Grab the polling_time
51
+ def interval
52
+ @interval ||= Application.polling_time
53
+ end
54
+ # Run the threads
55
+ def run_threads
56
+ _tasker.run
57
+ end
58
+ alias_method :run_tasks, :run_threads
59
+ # Daemonize the process
60
+ def daemonize
61
+ PoolParty.message "Daemonizing..."
62
+
63
+ pid = fork do
64
+ Signal.trap('HUP', 'IGNORE') # Don't die upon logout
65
+ File.open("/dev/null", "r+") do |devnull|
66
+ $stdout.reopen(devnull)
67
+ $stderr.reopen(devnull)
68
+ $stdin.reopen(devnull) unless @use_stdin
69
+ end
70
+ yield if block_given?
71
+ end
72
+ Process.detach(pid)
73
+ pid
74
+ end
75
+ # Run the loop and wait the amount of time between running the tasks
76
+ # You can send it daemonize => true and it will daemonize
77
+ def run_thread_loop(opts={}, &block)
78
+ block = lambda {
79
+ loop do
80
+ begin
81
+ run_thread_list(&block)
82
+ wait interval
83
+ reset!
84
+ rescue Exception => e
85
+ puts "There was an error in the run_thread_loop: #{e}"
86
+ end
87
+ end
88
+ }
89
+ # Run the tasks
90
+ opts[:daemonize] ? daemonize(&block) : block.call
91
+ end
92
+
93
+ def run_thread_list
94
+ yield if block_given?
95
+ run_threads
96
+ end
97
+ # Reset
98
+ def reset!
99
+ cached_variables.each {|cached| cached = nil }
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,57 @@
1
+ # Cloud tasks
2
+ namespace(:cloud) do
3
+ # Setup
4
+ task :init do
5
+ setup_application
6
+ raise Exception.new("You must specify your access_key and secret_access_key") unless Application.access_key && Application.secret_access_key
7
+ end
8
+ # Install the stack on all of the nodes
9
+ desc "Prepare all servers"
10
+ task :prepare => :init do
11
+ PoolParty::Master.new.nodes.each do |node|
12
+ node.install
13
+ end
14
+ end
15
+ # Start the cloud
16
+ desc "Start the cloud"
17
+ task :start => :init do
18
+ PoolParty::Master.new.start_cloud!
19
+ end
20
+ # Reload the cloud with the new updated data
21
+ desc "Reload all instances with updated data"
22
+ task :reload => :init do
23
+ PoolParty::Master.new.nodes.each do |node|
24
+ node.configure
25
+ node.restart_with_monit
26
+ end
27
+ end
28
+ # List the cloud
29
+ desc "List cloud"
30
+ task :list => :init do
31
+ PoolParty::Master.new.list
32
+ end
33
+ # Shutdown the cloud
34
+ desc "Shutdown the entire cloud"
35
+ task :shutdown => :init do
36
+ PoolParty::Master.new.request_termination_of_all_instances
37
+ end
38
+ # Watch the cloud and scale it if necessary
39
+ desc "Watch the cloud and maintain it"
40
+ task :scale => :init do
41
+ begin
42
+ PoolParty::Master.new.scale_cloud!
43
+ rescue Exception => e
44
+ puts "There was an error scaling the cloud: #{e}"
45
+ end
46
+
47
+ end
48
+ # Maintain the cloud in a background process
49
+ desc "Maintain the cloud (run on the master)"
50
+ task :maintain => :init do
51
+ begin
52
+ PoolParty::Master.new.start_monitor!
53
+ rescue Exception => e
54
+ puts "There was an error starting the monitor: #{e}"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,38 @@
1
+ namespace(:dev) do
2
+ task :init do
3
+ setup_application
4
+ run "mkdir ~/.ec2 >/dev/null 2>/dev/null" unless File.directory?("~/.ec2")
5
+ end
6
+ # Setup a basic development environment for the user
7
+ desc "Setup development environment specify the config_file"
8
+ task :setup => [:init] do
9
+ keyfilename = ".#{Application.keypair}_pool_keys"
10
+ run <<-EOR
11
+ echo 'export AWS_ACCESS_KEY_ID=\"#{Application.access_key}\"' > $HOME/#{keyfilename}
12
+ echo 'export AWS_SECRET_ACCESS_ID=\"#{Application.secret_access_key}\"' >> $HOME/#{keyfilename}
13
+ echo 'export EC2_HOME=\"#{Application.ec2_dir}\"' >> $HOME/#{keyfilename}
14
+ echo 'export KEYPAIR_NAME=\"#{Application.keypair}\"' >> $HOME/#{keyfilename}
15
+ echo 'export CONFIG_FILE=\"#{Application.config_file}\"' >> $HOME/#{keyfilename}
16
+ echo 'export EC2_PRIVATE_KEY=`ls ~/.ec2/#{Application.keypair}/pk-*.pem`;' >> $HOME/#{keyfilename}
17
+ echo 'export EC2_CERT=`ls ~/.ec2/#{Application.keypair}/cert-*.pem`;' >> $HOME/#{keyfilename}
18
+ source $HOME/#{keyfilename}
19
+ EOR
20
+ end
21
+ desc "Generate a keypair"
22
+ task :setup_keypair => :init do
23
+ unless File.file?(Application.keypair_path)
24
+ Application.keypair = "cloud"
25
+ run <<-EOR
26
+ ec2-add-keypair cloud > #{Application.keypair_path}
27
+ chmod 600 #{Application.keypair_path}
28
+ EOR
29
+ end
30
+ end
31
+ desc "Authorize base ports for application"
32
+ task :authorize_ports => :init do
33
+ run <<-EOR
34
+ ec2-authorize -p 22 default
35
+ ec2-authorize -p 80 default
36
+ EOR
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ namespace(:ec2) do
2
+ task :init do
3
+ Application.options
4
+ end
5
+ # Start a new instance in the cloud
6
+ desc "Add and start an instance to the pool"
7
+ task :start_new_instance => [:init] do
8
+ puts PoolParty::Remoting.new.launch_new_instance!
9
+ end
10
+ # Stop all the instances via command-line
11
+ desc "Stop all running instances"
12
+ task :stop_running_instances => [:init] do
13
+ Thread.new {`ec2-describe-instances | grep INSTANCE | grep running | awk '{print $2}' | xargs ec2-terminate-instances`}
14
+ end
15
+ # Reboot the instances via commandline
16
+ desc "Restart all running instances"
17
+ task :restart_running_instances => [:init] do
18
+ Thread.new {`ec2-describe-instances | grep INSTANCE | grep running | awk '{print $2}' | xargs ec2-reboot-instances`}
19
+ end
20
+ end
@@ -0,0 +1,63 @@
1
+ namespace(:instance) do
2
+ # Find the instance we want to deal with
3
+ # interface can be: num=0, i=0, inst=0, 0
4
+ # defaults to the master instance (0)
5
+ task :init do
6
+ num = (ENV['num'] || ENV["i"] || ENV["inst"] || ARGV.shift || 0).to_i
7
+ raise Exception.new("Please set the number of the instance (i.e. num=1, i=1, or as an argument)") unless num
8
+ @node = PoolParty::Master.new.get_node(num)
9
+ end
10
+ # Ssh into the node
11
+ desc "Remotely login to the remote instance"
12
+ task :ssh => [:init] do
13
+ @node.ssh
14
+ end
15
+ desc "Send a file to the remote instance"
16
+ task :exec => :init do
17
+ @node.ssh ENV['cmd']
18
+ end
19
+ # Send a file to the remote instance
20
+ # as designated by src='' and dest=''
21
+ desc "Send a file to the remote instance"
22
+ task :scp => :init do
23
+ @node.scp ENV['src'], ENV['dest']
24
+ end
25
+ # Execute a command on the remote instance as designated
26
+ # by cmd=''
27
+ desc "Execute cmd on a remote instance"
28
+ task :exec => [:init] do
29
+ cmd = ENV['cmd'] || "ls -l"
30
+ puts @node.ssh(cmd.runnable)
31
+ end
32
+ # Restart all the services monitored by monit
33
+ desc "Restart all the services"
34
+ task :reload => [:init] do
35
+ @node.restart_with_monit
36
+ end
37
+ # Start all the services monitored by monit
38
+ desc "Start all services"
39
+ task :load => [:init] do
40
+ @node.start_with_monit
41
+ end
42
+ # Stop the services monitored by monit
43
+ desc "Stop all services"
44
+ task :stop => [:init] do
45
+ @node.stop_with_monit
46
+ end
47
+ # Install the required services on this node
48
+ desc "Install stack on this node"
49
+ task :install => :init do
50
+ @node.install
51
+ end
52
+ # Turnoff this instance
53
+ desc "Teardown instance"
54
+ task :shutdown => :init do
55
+ `ec2-terminate-instances #{@node.instance_id}`
56
+ end
57
+ # Configure this node and start the services
58
+ desc "Configure the stack on this node"
59
+ task :configure => :init do
60
+ @node.configure
61
+ @node.restart_with_monit
62
+ end
63
+ end
@@ -0,0 +1,30 @@
1
+ namespace(:plugin) do
2
+ task :init do
3
+ @command = ARGV.shift # Get rid of the command
4
+ @name = (ENV['location'] || ENV["l"] || ARGV.shift)
5
+ unless @name
6
+ puts <<-EOM
7
+ Usage:
8
+ rake #{@command} location
9
+
10
+ Example:
11
+ rake #{@command} git://github.com/auser/pool-party-plugins.git
12
+
13
+ Check the help does for more information how to install a plugin
14
+ http://poolpartyrb.com
15
+
16
+ EOM
17
+ exit
18
+ end
19
+ end
20
+ desc "Install a plugin from a git repository"
21
+ task :install => :init do |command|
22
+ PoolParty::PluginManager.install_plugin @name
23
+ end
24
+ desc "Remove an installed plugin"
25
+ task :remove => :init do |command|
26
+ PoolParty::PluginManager.remove_plugin @name
27
+ end
28
+ rule "" do |t|
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ # Tasks to be run on the server
2
+ namespace(:server) do
3
+ task :init do
4
+ PoolParty::Coordinator.init(false)
5
+ end
6
+ # bundle, upload and register your bundle on the server
7
+ desc "Bundle, upload and register your ami"
8
+ task :all => [:bundle, :upload, :register] do
9
+ puts "== your ami is ready"
10
+ end
11
+ # Cleanup the /mnt directory
12
+ desc "Clean the /mnt directory"
13
+ task :clean_mnt do
14
+ `rm -rf /mnt/image* img*`
15
+ end
16
+ # Before we can bundle, we have to make sure we have the cert and pk files
17
+ desc "Ensure the required bundle files are present in /mnt"
18
+ task :check_bundle_files do
19
+ raise Exception.new("You must have a private key in your /mnt directory") unless File.exists?("/mnt/pk-*.pem")
20
+ raise Exception.new("You must have your access key in your /mnt directory") unless File.exists?("/mnt/cert-*.pem")
21
+ end
22
+ # Bundle the image
23
+ desc "Bundle this image into the /mnt directory"
24
+ task :bundle => [:clean_mnt, :check_bundle_files] do
25
+ puts `ec2-bundle-vol -k /mnt/pk-*.pem -u '#{Planner.user_id}' -d /mnt -c /mnt/cert-*.pem -r i386`
26
+ end
27
+ # Upload the bundle into the app_name bucket
28
+ desc "Upload the bundle to your bucket with a unique name: deletes old ami"
29
+ task :upload => [:init, :delete_bucket] do
30
+ puts `ec2-upload-bundle -b #{Planner.app_name} -m /mnt/image.manifest.xml -a #{Planner.access_key} -s #{Planner.secret_access_key}`
31
+ end
32
+ # Register the bucket with amazon and get back an ami
33
+ desc "Register the bundle with amazon"
34
+ task :register do
35
+ puts `ec2-register -K /mnt/pk-*.pem -C /mnt/cert-*.pem #{Planner.app_name}/image.manifest.xml`
36
+ end
37
+ # Delete the bucket
38
+ desc "Delete the bucket with the bundle under tha app name"
39
+ task :delete_bucket do
40
+ Planner.app_name.delete_bucket
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ module PoolParty
2
+ class Tasks
3
+ include Callbacks
4
+
5
+ # Setup and define all the tasks
6
+ def initialize
7
+ yield self if block_given?
8
+ end
9
+ # Define the tasks in the rakefile
10
+ # From the rakefile
11
+ def define_tasks
12
+ # Run the command on the local system
13
+ def run(cmd)
14
+ system(cmd.runnable)
15
+ end
16
+ # Basic setup action
17
+ def setup_application
18
+ PoolParty.options({:config_file => (ENV["CONFIG_FILE"] || ENV["config"]) })
19
+ end
20
+
21
+ # Require the poolparty specific tasks
22
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].each { |t| eval open(t).read }
23
+
24
+ Dir["#{PoolParty.plugin_dir}/*/Rakefile"].each {|t| load "#{t}" }
25
+
26
+ true
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ require "backcall"
3
+ require "remoter"
4
+ class Test
5
+ include PoolParty::Remoter
6
+ include Callbacks
7
+
8
+ after :initialize, :set_hosts
9
+ def rt
10
+ @rt ||= Rake::RemoteTask
11
+ end
12
+
13
+ def set_hosts(c)
14
+ rt.host "myslice", :app, :db
15
+ end
16
+
17
+ def rtask(name, *args, &block)
18
+ rt.remote_task(name.to_sym => args, &block)
19
+ end
20
+
21
+ def scp local, remote
22
+ require "tempfile"
23
+ rtask(:scp) do
24
+ put remote do
25
+ open(local).read
26
+ end
27
+ end.execute
28
+ end
29
+ before :scp, :set_hosts
30
+ def ssh command=nil, &block
31
+ block = Proc.new do
32
+ run command
33
+ end
34
+ rtask(:ssh, &block).execute
35
+ end
36
+ before :ssh, :set_hosts
37
+ end
38
+
39
+ t = Test.new
40
+ t.scp("/Users/auser/Sites/work/citrusbyte/internal/gems/pool-party/pool/CHANGELOG", "ho")
41
+ t.ssh("ls -l")
42
+ t.ssh <<-EOE
43
+ ls -l
44
+ mv ho CHANGELOG
45
+ cat CHANGELOG
46
+ EOE
data/lib/poolparty.rb ADDED
@@ -0,0 +1,105 @@
1
+ =begin rdoc
2
+ The main file, contains the client and the server application methods
3
+ =end
4
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
5
+
6
+ # rubygems
7
+ require 'rubygems'
8
+ require "aws/s3"
9
+ require "sqs"
10
+ require "EC2"
11
+ require 'thread'
12
+ require "pp"
13
+ require "tempfile"
14
+ require "aska"
15
+ require "vlad"
16
+ begin
17
+ require 'fastthread'
18
+ require 'thin'
19
+ require 'system_timer'
20
+ Timer = SystemTimer
21
+ rescue LoadError
22
+ require 'timeout'
23
+ Timer = Timeout
24
+ end
25
+
26
+ ## Load PoolParty
27
+ pwd = File.dirname(__FILE__)
28
+
29
+ # Load the required files
30
+ # If there is an init file, load that, otherwise
31
+ # require all the files in each directory
32
+ %w(core modules s3 poolparty).each do |dir|
33
+ Dir["#{pwd}/#{dir}"].each do |dir|
34
+ begin
35
+ require File.join(dir, "init")
36
+ rescue LoadError => e
37
+ Dir["#{pwd}/#{File.basename(dir)}/**"].each {|file| require File.join(dir, File.basename(file))}
38
+ end
39
+ end
40
+ end
41
+
42
+ module PoolParty
43
+ module Version #:nodoc:
44
+ MAJOR = 0
45
+ MINOR = 0
46
+ TINY = 8
47
+
48
+ STRING = [MAJOR, MINOR, TINY].join('.')
49
+ end
50
+ # PoolParty options
51
+ def options(opts={})
52
+ Application.options(opts)
53
+ end
54
+ # Are we working in verbose-mode
55
+ def verbose?
56
+ options.verbose == true
57
+ end
58
+ # Send a message if we are in verbose-mode
59
+ def message(msg="")
60
+ puts "-- #{msg}" if verbose?
61
+ end
62
+ # Root directory of the application
63
+ def root_dir
64
+ File.expand_path(File.dirname(__FILE__) + "/..")
65
+ end
66
+ # User directory
67
+ def user_dir
68
+ Dir.pwd
69
+ end
70
+ # Write string to a tempfile
71
+ def write_to_temp_file(str="")
72
+ tempfile = Tempfile.new("rand#{rand(1000)}-#{rand(1000)}")
73
+ tempfile.print(str)
74
+ tempfile.flush
75
+ tempfile
76
+ end
77
+ def register_monitor(*names)
78
+ names.each do |name|
79
+ PoolParty::Monitors.extend name
80
+
81
+ PoolParty::Master.send :include, name::Master
82
+ PoolParty::RemoteInstance.send :include, name::Remote
83
+ end
84
+ end
85
+ def load_plugins
86
+ Dir["#{plugin_dir}/**/init.rb"].each {|a| require a}
87
+ end
88
+ def reset!
89
+ @@installed_plugins = nil
90
+ Application.options = nil
91
+ end
92
+ def plugin_dir
93
+ "#{user_dir}/vendor"
94
+ end
95
+ def read_config_file(filename)
96
+ return {} unless filename
97
+ YAML.load(open(filename).read)
98
+ end
99
+ def include_cloud_tasks
100
+ Tasks.new.define_tasks
101
+ end
102
+
103
+ alias_method :tasks, :include_cloud_tasks
104
+ alias_method :include_tasks, :include_cloud_tasks
105
+ end
@@ -0,0 +1,44 @@
1
+ =begin rdoc
2
+ S3 overloads
3
+ =end
4
+ module AWS
5
+ module S3
6
+ class S3Object
7
+ class << self
8
+
9
+ alias :original_store :store
10
+ def store(key, data, bucket = nil, options = {})
11
+ store_folders(key, bucket, options) if options[:use_virtual_directories]
12
+ original_store(key, data, bucket, options)
13
+ end
14
+
15
+ def streamed_store(key, filepath, bucket = nil, options = {})
16
+ store_folders(key, bucket, options) if options[:use_virtual_directories]
17
+ store(key,File.open(filepath), bucket)
18
+ end
19
+
20
+ def store_directory(directory, bucket, options = {})
21
+ Dir[File.join(directory, "*")].each do |file|
22
+ streamed_store("#{File.basename(File.dirname(file))}/#{File.basename(file)}", file, bucket, options.update(:use_virtual_directories => true))
23
+ end
24
+ end
25
+
26
+ def store_folders(key, bucket = nil, options = {})
27
+ folders = key.split("/")
28
+ folders.slice!(0)
29
+ folders.pop
30
+ current_folder = "/"
31
+ folders.each {|folder|
32
+ current_folder += folder
33
+ store_folder(current_folder, bucket, options)
34
+ current_folder += "/"
35
+ }
36
+ end
37
+
38
+ def store_folder(key, bucket = nil, options = {})
39
+ original_store(key + "_$folder$", "", bucket, options) # store the magic entry that emulates a folder
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end