mdh-ec2onrails 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +180 -0
- data/COPYING +339 -0
- data/Manifest +162 -0
- data/README.textile +214 -0
- data/Rakefile +36 -0
- data/TODO +102 -0
- data/ec2onrails.gemspec +42 -0
- data/examples/Capfile +3 -0
- data/examples/deploy.rb +101 -0
- data/examples/s3.yml +9 -0
- data/lib/ec2onrails.rb +20 -0
- data/lib/ec2onrails/capistrano_utils.rb +43 -0
- data/lib/ec2onrails/recipes.rb +844 -0
- data/lib/ec2onrails/version.rb +31 -0
- data/server/build-ec2onrails.sh +44 -0
- data/server/files/etc/aliases +5 -0
- data/server/files/etc/aliases.db +0 -0
- data/server/files/etc/apache2/apache2.conf +295 -0
- data/server/files/etc/apache2/conf.d/app.proxy_cluster.conf +7 -0
- data/server/files/etc/apache2/conf.d/app.proxy_frontend.conf +10 -0
- data/server/files/etc/apache2/mods-available/proxy.conf +18 -0
- data/server/files/etc/apache2/sites-available/app.common +56 -0
- data/server/files/etc/apache2/sites-available/app.custom +0 -0
- data/server/files/etc/apache2/sites-available/default +14 -0
- data/server/files/etc/apache2/sites-available/default-ssl +19 -0
- data/server/files/etc/cron.d/backup_app_db_to_s3 +16 -0
- data/server/files/etc/cron.daily/app +9 -0
- data/server/files/etc/cron.daily/logrotate_post +19 -0
- data/server/files/etc/cron.hourly/app +10 -0
- data/server/files/etc/cron.monthly/app +10 -0
- data/server/files/etc/cron.weekly/app +10 -0
- data/server/files/etc/denyhosts.conf +628 -0
- data/server/files/etc/dpkg/dpkg.cfg +13 -0
- data/server/files/etc/ec2onrails/README +32 -0
- data/server/files/etc/ec2onrails/balancer_members +6 -0
- data/server/files/etc/ec2onrails/roles.yml +5 -0
- data/server/files/etc/environment +2 -0
- data/server/files/etc/god/app.god +35 -0
- data/server/files/etc/god/db.god +17 -0
- data/server/files/etc/god/examples/have_god_daemonize.god +18 -0
- data/server/files/etc/god/master.conf +35 -0
- data/server/files/etc/god/memcache.god +15 -0
- data/server/files/etc/god/notifications.god +14 -0
- data/server/files/etc/god/system.god +34 -0
- data/server/files/etc/god/web.god +36 -0
- data/server/files/etc/init.d/ec2-every-startup +29 -0
- data/server/files/etc/init.d/ec2-first-startup +36 -0
- data/server/files/etc/init.d/god +42 -0
- data/server/files/etc/init.d/nginx +78 -0
- data/server/files/etc/init.d/set_roles +3 -0
- data/server/files/etc/logrotate.d/apache2 +16 -0
- data/server/files/etc/logrotate.d/mongrel +11 -0
- data/server/files/etc/logrotate.d/nginx +11 -0
- data/server/files/etc/memcached.conf +47 -0
- data/server/files/etc/mongrel_cluster/app.yml +9 -0
- data/server/files/etc/motd.tail +13 -0
- data/server/files/etc/mysql/my.cnf +152 -0
- data/server/files/etc/nginx/nginx.conf +296 -0
- data/server/files/etc/postfix/main.cf +4 -0
- data/server/files/etc/rcS.d/S91ec2-first-startup +1 -0
- data/server/files/etc/rcS.d/S92ec2-every-startup +1 -0
- data/server/files/etc/rcS.d/S99set_roles +1 -0
- data/server/files/etc/ssh/sshd_config +94 -0
- data/server/files/etc/sudoers +1 -0
- data/server/files/etc/sudoers.full_access +26 -0
- data/server/files/etc/sudoers.restricted_access +28 -0
- data/server/files/etc/syslog.conf +69 -0
- data/server/files/usr/bin/god +26 -0
- data/server/files/usr/local/ec2onrails/COPYING +339 -0
- data/server/files/usr/local/ec2onrails/bin/archive_file.rb +44 -0
- data/server/files/usr/local/ec2onrails/bin/backup_app_db.rb +159 -0
- data/server/files/usr/local/ec2onrails/bin/ec2_meta_data.rb +80 -0
- data/server/files/usr/local/ec2onrails/bin/exec_runner +73 -0
- data/server/files/usr/local/ec2onrails/bin/init_services.rb +64 -0
- data/server/files/usr/local/ec2onrails/bin/optimize_mysql.rb +348 -0
- data/server/files/usr/local/ec2onrails/bin/rails_env +35 -0
- data/server/files/usr/local/ec2onrails/bin/rebundle.sh +70 -0
- data/server/files/usr/local/ec2onrails/bin/restore_app_db.rb +58 -0
- data/server/files/usr/local/ec2onrails/bin/set_rails_env +40 -0
- data/server/files/usr/local/ec2onrails/bin/set_roles.rb +87 -0
- data/server/files/usr/local/ec2onrails/bin/setup_web_proxy.rb +109 -0
- data/server/files/usr/local/ec2onrails/config +30 -0
- data/server/files/usr/local/ec2onrails/lib/aws_helper.rb +76 -0
- data/server/files/usr/local/ec2onrails/lib/god_helper.rb +129 -0
- data/server/files/usr/local/ec2onrails/lib/god_patch.rb +43 -0
- data/server/files/usr/local/ec2onrails/lib/mysql_helper.rb +101 -0
- data/server/files/usr/local/ec2onrails/lib/roles_helper.rb +151 -0
- data/server/files/usr/local/ec2onrails/lib/s3_helper.rb +99 -0
- data/server/files/usr/local/ec2onrails/lib/utils.rb +16 -0
- data/server/files/usr/local/ec2onrails/lib/vendor/ini.rb +268 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/every-startup/get-hostname.sh +25 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/README +5 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/create-dirs.sh +39 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/generate-default-web-cert-and-key.sh +49 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/misc.sh +27 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/prepare-mysql-data-dir.sh +24 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-credentials.sh +29 -0
- data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-file-permissions.sh +30 -0
- data/server/rakefile.rb +248 -0
- data/setup.rb +1585 -0
- data/test/autobench.conf +60 -0
- data/test/spec/lib/s3_helper_spec.rb +134 -0
- data/test/spec/lib/s3_old.yml +3 -0
- data/test/spec/test_files/test1 +0 -0
- data/test/spec/test_files/test2 +0 -0
- data/test/test_app/Capfile +3 -0
- data/test/test_app/README +182 -0
- data/test/test_app/Rakefile +10 -0
- data/test/test_app/app/controllers/application.rb +7 -0
- data/test/test_app/app/controllers/db_fast_controller.rb +6 -0
- data/test/test_app/app/controllers/fast_controller.rb +5 -0
- data/test/test_app/app/controllers/slow_controller.rb +6 -0
- data/test/test_app/app/controllers/very_slow_controller.rb +6 -0
- data/test/test_app/app/helpers/application_helper.rb +3 -0
- data/test/test_app/app/helpers/db_fast_helper.rb +2 -0
- data/test/test_app/app/helpers/fast_helper.rb +2 -0
- data/test/test_app/app/helpers/slow_helper.rb +2 -0
- data/test/test_app/app/helpers/very_slow_helper.rb +2 -0
- data/test/test_app/config/boot.rb +109 -0
- data/test/test_app/config/database.yml +19 -0
- data/test/test_app/config/deploy.rb +21 -0
- data/test/test_app/config/environment.rb +60 -0
- data/test/test_app/config/environments/development.rb +21 -0
- data/test/test_app/config/environments/production.rb +18 -0
- data/test/test_app/config/environments/test.rb +19 -0
- data/test/test_app/config/routes.rb +27 -0
- data/test/test_app/db/schema.rb +7 -0
- data/test/test_app/doc/README_FOR_APP +2 -0
- data/test/test_app/public/404.html +30 -0
- data/test/test_app/public/500.html +30 -0
- data/test/test_app/public/dispatch.cgi +10 -0
- data/test/test_app/public/dispatch.fcgi +24 -0
- data/test/test_app/public/dispatch.rb +10 -0
- data/test/test_app/public/favicon.ico +0 -0
- data/test/test_app/public/images/rails.png +0 -0
- data/test/test_app/public/javascripts/application.js +2 -0
- data/test/test_app/public/javascripts/controls.js +963 -0
- data/test/test_app/public/javascripts/dragdrop.js +972 -0
- data/test/test_app/public/javascripts/effects.js +1120 -0
- data/test/test_app/public/javascripts/prototype.js +4225 -0
- data/test/test_app/public/robots.txt +1 -0
- data/test/test_app/script/about +3 -0
- data/test/test_app/script/breakpointer +3 -0
- data/test/test_app/script/console +3 -0
- data/test/test_app/script/destroy +3 -0
- data/test/test_app/script/generate +3 -0
- data/test/test_app/script/performance/benchmarker +3 -0
- data/test/test_app/script/performance/profiler +3 -0
- data/test/test_app/script/performance/request +3 -0
- data/test/test_app/script/plugin +3 -0
- data/test/test_app/script/process/inspector +3 -0
- data/test/test_app/script/process/reaper +3 -0
- data/test/test_app/script/process/spawner +3 -0
- data/test/test_app/script/runner +3 -0
- data/test/test_app/script/server +3 -0
- data/test/test_app/test/functional/db_fast_controller_test.rb +18 -0
- data/test/test_app/test/functional/fast_controller_test.rb +18 -0
- data/test/test_app/test/functional/slow_controller_test.rb +18 -0
- data/test/test_app/test/functional/very_slow_controller_test.rb +18 -0
- data/test/test_app/test/test_helper.rb +28 -0
- data/test/test_ec2onrails.rb +11 -0
- data/test/test_helper.rb +2 -0
- metadata +274 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module GodHelper
|
|
2
|
+
require '/usr/local/ec2onrails/lib/roles_helper'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
def default_configurations(w)
|
|
6
|
+
w.interval = 30.seconds
|
|
7
|
+
w.grace = 30.seconds
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
w.behavior(:clean_pid_file)
|
|
11
|
+
|
|
12
|
+
w.start_if do |start|
|
|
13
|
+
start.condition(:process_running) do |c|
|
|
14
|
+
c.notify = {:contacts => ['default'], :category => 'process not started...starting'}
|
|
15
|
+
c.interval = 5.seconds
|
|
16
|
+
c.running = false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# w.start_if do |start|
|
|
21
|
+
# start.condition(:process_running) do |c|
|
|
22
|
+
# c.interval = 5.seconds
|
|
23
|
+
# c.running = false
|
|
24
|
+
# c.notify = {:contacts => ['default'], :category => 'process exited...restarting'}
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
|
|
28
|
+
# determine when process has finished starting
|
|
29
|
+
# w.transition([:start, :restart], :up) do |on|
|
|
30
|
+
# on.condition(:process_running) do |c|
|
|
31
|
+
# c.running = true
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# # failsafe
|
|
35
|
+
# on.condition(:tries) do |c|
|
|
36
|
+
# c.times = 8
|
|
37
|
+
# c.within = 2.minutes
|
|
38
|
+
# c.transition = :start
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# # start if process is not running
|
|
43
|
+
# w.transition(:up, :start) do |on|
|
|
44
|
+
# on.condition(:process_exits) do |c|
|
|
45
|
+
# c.notify = {:contacts => ['default'], :category => 'process exited...restarting'}
|
|
46
|
+
# end
|
|
47
|
+
# end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def restart_if_resource_hog(w, options={})
|
|
51
|
+
options = {:memory_usage => 175.megabytes, :cpu_usage => 50.percent}.merge(options)
|
|
52
|
+
w.restart_if do |restart|
|
|
53
|
+
if options[:memory_usage]
|
|
54
|
+
restart.condition(:memory_usage) do |c|
|
|
55
|
+
c.notify = {:contacts => ['default'], :category => "process over #{options[:memory_usage]/1.megabyte}MB. restarting"}
|
|
56
|
+
c.above = options[:memory_usage]
|
|
57
|
+
c.times = [3,5]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if options[:cpu_usage]
|
|
62
|
+
restart.condition(:cpu_usage) do |c|
|
|
63
|
+
c.notify = {:contacts => ['default'], :category => "process over #{options[:cpu_usage]*100}%. restarting"}
|
|
64
|
+
c.above = options[:cpu_usage]
|
|
65
|
+
c.times = 5
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
yield restart if block_given?
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def create_pid_dir(w)
|
|
75
|
+
pid_dir = File.dirname(w.pid_file)
|
|
76
|
+
return if File.exist?(pid_dir)
|
|
77
|
+
|
|
78
|
+
#we need to make sure it is writable...but include all the directories we created...
|
|
79
|
+
starting_dir = pid_dir
|
|
80
|
+
starting_dir = File.dirname(starting_dir) until File.exist?(File.dirname(starting_dir))
|
|
81
|
+
|
|
82
|
+
FileUtils.mkdir_p(pid_dir)
|
|
83
|
+
FileUtils.chown_R(w.uid, w.gid, starting_dir)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def monitor_lifecycle(w)
|
|
87
|
+
# w.transition(:up, :unmonitored) do |on|
|
|
88
|
+
w.lifecycle do |on|
|
|
89
|
+
on.condition(:flapping) do |c|
|
|
90
|
+
c.notify = {:contacts => ['default'], :category => 'process flapping...restarting'}
|
|
91
|
+
c.to_state = [:start, :restart]
|
|
92
|
+
c.times = 5
|
|
93
|
+
c.within = 5.minutes
|
|
94
|
+
c.transition = :unmonitored
|
|
95
|
+
c.retry_in = 10.minutes
|
|
96
|
+
c.retry_times = 5
|
|
97
|
+
c.retry_within = 2.hours
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
# w.lifecycle do |on|
|
|
101
|
+
# on.condition(:flapping) do |c|
|
|
102
|
+
# c.notify = {:contacts => ['default'], :category => 'process flapping...restarting'}
|
|
103
|
+
# c.to_state = [:start, :restart]
|
|
104
|
+
# c.times = 5
|
|
105
|
+
# c.within = 60.seconds
|
|
106
|
+
# c.retry_in = 10.minutes
|
|
107
|
+
# c.retry_times = 5
|
|
108
|
+
# c.retry_within = 2.hours
|
|
109
|
+
# end
|
|
110
|
+
# end
|
|
111
|
+
|
|
112
|
+
# w.lifecycle do |on|
|
|
113
|
+
# on.condition(:flapping) do |c|
|
|
114
|
+
# c.to_state = [:start, :restart]
|
|
115
|
+
# c.times = 5
|
|
116
|
+
# c.within = 5.minutes
|
|
117
|
+
# c.transition = :unmonitored
|
|
118
|
+
# c.retry_in = 10.minutes
|
|
119
|
+
# c.retry_times = 5
|
|
120
|
+
# c.retry_within = 2.hours
|
|
121
|
+
# end
|
|
122
|
+
# end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
class Configs
|
|
126
|
+
include Ec2onrails::RolesHelper
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'god'
|
|
3
|
+
|
|
4
|
+
# this is a hack to put the bin directory back at the top of the load path....
|
|
5
|
+
# the /usr/bin/god script will try to load 'god', which is in the bin path of the gem
|
|
6
|
+
# but is also the name of the module.... it should really be called something like god_bin
|
|
7
|
+
# or god_cli, so then it would have no problem being found.
|
|
8
|
+
$:.unshift File.join($:[0], *%w[.. .. bin])
|
|
9
|
+
|
|
10
|
+
module God
|
|
11
|
+
def self.control(name, command)
|
|
12
|
+
# get the list of items
|
|
13
|
+
items = Array(self.watches[name] || self.groups[name]).dup
|
|
14
|
+
|
|
15
|
+
jobs = []
|
|
16
|
+
# do the command
|
|
17
|
+
case command
|
|
18
|
+
when "start", "monitor"
|
|
19
|
+
items.each { |w| jobs << Thread.new { w.monitor if w.state != :up } }
|
|
20
|
+
when "restart"
|
|
21
|
+
items.each { |w| jobs << Thread.new { w.move(:restart) } }
|
|
22
|
+
when "stop"
|
|
23
|
+
# items.each { |w| jobs << Thread.new { w.unmonitor.action(:stop) if w.state != :unmonitored } }
|
|
24
|
+
items.each do |w|
|
|
25
|
+
jobs << Thread.new do
|
|
26
|
+
w.unmonitor if w.state != :unmonitored
|
|
27
|
+
w.action(:stop) if w.alive?
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
when "unmonitor"
|
|
31
|
+
items.each { |w| jobs << Thread.new { w.unmonitor if w.state != :unmonitored } }
|
|
32
|
+
when "remove"
|
|
33
|
+
items.each { |w| self.unwatch(w) }
|
|
34
|
+
else
|
|
35
|
+
raise InvalidCommandError.new
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
jobs.each { |j| j.join }
|
|
39
|
+
|
|
40
|
+
items.map { |x| x.name }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# This file is part of EC2 on Rails.
|
|
2
|
+
# http://rubyforge.org/projects/ec2onrails/
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2007 Paul Dowman, http://pauldowman.com/
|
|
5
|
+
#
|
|
6
|
+
# EC2 on Rails is free software; you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# EC2 on Rails is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
require 'rubygems'
|
|
20
|
+
require 'aws/s3'
|
|
21
|
+
require 'yaml'
|
|
22
|
+
require 'erb'
|
|
23
|
+
require 'fileutils'
|
|
24
|
+
require "#{File.dirname(__FILE__)}/utils"
|
|
25
|
+
|
|
26
|
+
module Ec2onrails
|
|
27
|
+
class MysqlHelper
|
|
28
|
+
|
|
29
|
+
DEFAULT_CONFIG_FILE = "/mnt/app/current/config/database.yml"
|
|
30
|
+
|
|
31
|
+
attr_accessor :database
|
|
32
|
+
attr_accessor :user
|
|
33
|
+
attr_accessor :password
|
|
34
|
+
|
|
35
|
+
def initialize(config_file = DEFAULT_CONFIG_FILE, rails_env = Utils.rails_env)
|
|
36
|
+
@rails_env = rails_env
|
|
37
|
+
load_db_config(config_file)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def load_db_config(config_file)
|
|
41
|
+
db_config = YAML::load(ERB.new(File.read(config_file)).result)
|
|
42
|
+
if db_config && db_config[@rails_env].nil?
|
|
43
|
+
puts "the rails environment '#{@rails_env}' was not found in this db onfig file: #{config_file}"
|
|
44
|
+
end
|
|
45
|
+
db_config = db_config[@rails_env]
|
|
46
|
+
@database = db_config['database']
|
|
47
|
+
@user = db_config['username']
|
|
48
|
+
@password = db_config['password']
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def execute_sql(sql)
|
|
52
|
+
raise "@user not set" unless @user
|
|
53
|
+
raise "sql not given" unless sql
|
|
54
|
+
cmd = %{mysql -u #{@user} -e "#{sql}"}
|
|
55
|
+
cmd += " -p'#{@password}' " unless @password.nil?
|
|
56
|
+
Utils.run cmd
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def execute
|
|
60
|
+
require "mysql"
|
|
61
|
+
|
|
62
|
+
begin
|
|
63
|
+
# connect to the MySQL server
|
|
64
|
+
dbh = Mysql.real_connect("localhost", "#{@user}", "#{@password}", "#{@database}")
|
|
65
|
+
yield dbh
|
|
66
|
+
rescue Mysql::Error => e
|
|
67
|
+
puts "Error code: #{e.errno}"
|
|
68
|
+
puts "Error message: #{e.error}"
|
|
69
|
+
puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
|
|
70
|
+
ensure
|
|
71
|
+
# disconnect from server
|
|
72
|
+
dbh.close if dbh
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def dump(out_file, reset_logs)
|
|
79
|
+
cmd = "mysqldump --quick --single-transaction --create-options -u#{@user} "
|
|
80
|
+
if reset_logs
|
|
81
|
+
cmd += " --flush-logs --master-data=2 --delete-master-logs "
|
|
82
|
+
end
|
|
83
|
+
cmd += " -p'#{@password}' " unless @password.nil?
|
|
84
|
+
cmd += " #{@database} | gzip > #{out_file}"
|
|
85
|
+
Utils.run cmd
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def load_from_dump(in_file)
|
|
89
|
+
cmd = "gunzip -c #{in_file} | mysql -u#{@user} "
|
|
90
|
+
cmd += " -p'#{@password}' " unless @password.nil?
|
|
91
|
+
cmd += " #{@database}"
|
|
92
|
+
Utils.run cmd
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def execute_binary_log(log_file)
|
|
96
|
+
cmd = "mysqlbinlog --database=#{@database} #{log_file} | mysql -u#{@user} "
|
|
97
|
+
cmd += " -p'#{@password}' " unless @password.nil?
|
|
98
|
+
Utils.run cmd
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# This file is part of EC2 on Rails.
|
|
2
|
+
# http://rubyforge.org/projects/ec2onrails/
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2007 Paul Dowman, http://pauldowman.com/
|
|
5
|
+
#
|
|
6
|
+
# EC2 on Rails is free software; you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# EC2 on Rails is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
require 'net/http'
|
|
20
|
+
require 'pp'
|
|
21
|
+
require 'socket'
|
|
22
|
+
require 'yaml'
|
|
23
|
+
require 'erb'
|
|
24
|
+
|
|
25
|
+
module Ec2onrails
|
|
26
|
+
module RolesHelper
|
|
27
|
+
ROLES_FILE = "/etc/ec2onrails/roles.yml"
|
|
28
|
+
MONGREL_CONF_FILE = "/etc/mongrel_cluster/app.yml"
|
|
29
|
+
|
|
30
|
+
def local_address
|
|
31
|
+
@local_address ||= get_metadata "local-ipv4"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def public_address
|
|
35
|
+
@public_address ||= get_metadata "public-ipv4"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def roles
|
|
39
|
+
@roles ||= resolve_all_addresses(YAML::load_file(ROLES_FILE))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def start(role, service, prog_name = service)
|
|
43
|
+
puts "STARTING #{role} role (service: #{service}, program_name: #{prog_name})"
|
|
44
|
+
sudo "god start #{role}"
|
|
45
|
+
# sudo "god monitor #{role}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def stop(role, service, prog_name = service)
|
|
49
|
+
puts "STOPING #{role} role (service: #{service}, program_name: #{prog_name})"
|
|
50
|
+
# sudo "god monitor #{role}"
|
|
51
|
+
sudo "god stop #{role}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def run(cmd)
|
|
55
|
+
result = system(cmd)
|
|
56
|
+
puts("*****ERROR: #{cmd} returned #{$?}") unless result
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def sudo(cmd)
|
|
60
|
+
run("sudo #{cmd}")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def get_metadata(type)
|
|
64
|
+
data = Net::HTTP.get('169.254.169.254', "/latest/meta-data/#{type}").strip
|
|
65
|
+
|
|
66
|
+
raise "couldn't get instance data: #{type}" if data.nil? || data.strip.length == 0
|
|
67
|
+
# puts "#{type}: #{address}"
|
|
68
|
+
return data
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def resolve(hostname)
|
|
72
|
+
address = IPSocket.getaddress(hostname).strip
|
|
73
|
+
if address == local_address || address == public_address
|
|
74
|
+
"127.0.0.1"
|
|
75
|
+
else
|
|
76
|
+
address
|
|
77
|
+
end
|
|
78
|
+
rescue Exception => e
|
|
79
|
+
puts "couldn't resolve hostname '#{hostname}'"
|
|
80
|
+
raise e
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def resolve_all_addresses(original)
|
|
84
|
+
resolved = {}
|
|
85
|
+
original.each do |rolename, hostnames|
|
|
86
|
+
resolved[rolename] = hostnames.map{|hostname| resolve(hostname)} if hostnames
|
|
87
|
+
end
|
|
88
|
+
resolved
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def in_role?(role)
|
|
92
|
+
return false unless roles[role]
|
|
93
|
+
return roles[role].include?("127.0.0.1")
|
|
94
|
+
end
|
|
95
|
+
#to provide deprecated usage
|
|
96
|
+
alias :in_role :in_role?
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def add_etc_hosts_entry(entry_name, entry_addr)
|
|
100
|
+
host_file = "/etc/hosts"
|
|
101
|
+
run("cp #{host_file}.original #{host_file}") unless File.exists?("#{host_file}.original")
|
|
102
|
+
hosts = File.read(host_file)
|
|
103
|
+
if hosts =~ /\s*.+?\s+#{entry_name}\s*$/
|
|
104
|
+
hosts.sub!(/\s*.+?\s+#{entry_name}\s*$/, "\n#{entry_addr}\t#{entry_name}\n")
|
|
105
|
+
else
|
|
106
|
+
puts "adding '#{entry_addr}\t#{entry_name}' to /etc/hosts"
|
|
107
|
+
hosts << "\n#{entry_addr}\t#{entry_name}\n"
|
|
108
|
+
end
|
|
109
|
+
File.open(host_file, 'w') {|f| f.write(hosts) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def web_starting_port
|
|
113
|
+
mongrel_config['port'].to_i rescue 8000
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def web_num_instances
|
|
117
|
+
mongrel_config['servers'].to_i rescue 6
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def web_port_range
|
|
121
|
+
(web_starting_port..(web_starting_port + web_num_instances-1))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def server_environment
|
|
125
|
+
mongrel_config["environment"]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def user
|
|
129
|
+
mongrel_config['user']
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def group
|
|
133
|
+
mongrel_config['group']
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def application_root
|
|
137
|
+
mongrel_config['cwd']
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def pid_file
|
|
141
|
+
"#{application_root}/#{mongrel_config['pid_file']}"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
private
|
|
145
|
+
|
|
146
|
+
def mongrel_config
|
|
147
|
+
@mongrel_config ||= YAML::load_file(MONGREL_CONF_FILE)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# This file is part of EC2 on Rails.
|
|
2
|
+
# http://rubyforge.org/projects/ec2onrails/
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2007 Paul Dowman, http://pauldowman.com/
|
|
5
|
+
#
|
|
6
|
+
# EC2 on Rails is free software; you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# EC2 on Rails is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
require 'rubygems'
|
|
20
|
+
require 'aws/s3'
|
|
21
|
+
require 'yaml'
|
|
22
|
+
require 'erb'
|
|
23
|
+
require 'fileutils'
|
|
24
|
+
require "#{File.dirname(__FILE__)}/utils"
|
|
25
|
+
require "#{File.dirname(__FILE__)}/aws_helper"
|
|
26
|
+
|
|
27
|
+
module Ec2onrails
|
|
28
|
+
class S3Helper
|
|
29
|
+
|
|
30
|
+
# make attributes available for specs
|
|
31
|
+
attr_accessor :bucket
|
|
32
|
+
attr_accessor :dir
|
|
33
|
+
attr_accessor :config_file
|
|
34
|
+
attr_accessor :rails_env
|
|
35
|
+
attr_accessor :aws_access_key
|
|
36
|
+
attr_accessor :aws_secret_access_key
|
|
37
|
+
attr_accessor :bucket
|
|
38
|
+
|
|
39
|
+
def initialize(bucket, dir, config_file = Ec2onrails::AwsHelper.default_config_file, rails_env = Utils.rails_env)
|
|
40
|
+
@dir = dir
|
|
41
|
+
@config_file = config_file
|
|
42
|
+
@rails_env = rails_env
|
|
43
|
+
@awsHelper = Ec2onrails::AwsHelper.new(config_file, rails_env)
|
|
44
|
+
@aws_access_key = @awsHelper.aws_access_key
|
|
45
|
+
@aws_secret_access_key = @awsHelper.aws_secret_access_key
|
|
46
|
+
@bucket_base_name = @awsHelper.bucket_base_name
|
|
47
|
+
@bucket = bucket || "#{@bucket_base_name}-#{Ec2onrails::Utils.hostname}"
|
|
48
|
+
AWS::S3::Base.establish_connection!(:access_key_id => @aws_access_key, :secret_access_key => @aws_secret_access_key, :use_ssl => true)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def create_bucket
|
|
52
|
+
retries = 0
|
|
53
|
+
begin
|
|
54
|
+
AWS::S3::Bucket.find(@bucket)
|
|
55
|
+
rescue AWS::S3::NoSuchBucket
|
|
56
|
+
AWS::S3::Bucket.create(@bucket)
|
|
57
|
+
sleep 1 # If we try to use the bucket too quickly sometimes it's not found
|
|
58
|
+
retry if (retries += 1) < 15
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def store_file(file)
|
|
63
|
+
create_bucket
|
|
64
|
+
AWS::S3::S3Object.store(s3_key(file), open(file), @bucket)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def retrieve_file(file)
|
|
68
|
+
key = s3_key(file)
|
|
69
|
+
AWS::S3::S3Object.find(key, @bucket)
|
|
70
|
+
open(file, 'w') do |f|
|
|
71
|
+
AWS::S3::S3Object.stream(key, @bucket) do |chunk|
|
|
72
|
+
f.write chunk
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def list_keys(filename_prefix)
|
|
78
|
+
prefix = @dir ? "#{@dir}/#{filename_prefix}" : filename_prefix
|
|
79
|
+
AWS::S3::Bucket.objects(@bucket, :prefix => prefix).collect{|obj| obj.key}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def retrieve_files(filename_prefix, local_dir)
|
|
83
|
+
list_keys(filename_prefix).each do |k|
|
|
84
|
+
file = "#{local_dir}/#{File.basename(k)}"
|
|
85
|
+
retrieve_file(file)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def delete_files(filename_prefix)
|
|
90
|
+
list_keys(filename_prefix).each do |k|
|
|
91
|
+
AWS::S3::S3Object.delete(k, @bucket)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def s3_key(file)
|
|
96
|
+
@dir ? "#{@dir}/#{File.basename(file)}" : File.basename(file)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|