skippy-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.
Files changed (163) hide show
  1. data/CHANGELOG +159 -0
  2. data/COPYING +339 -0
  3. data/Manifest +162 -0
  4. data/README.textile +214 -0
  5. data/Rakefile +36 -0
  6. data/TODO +102 -0
  7. data/ec2onrails.gemspec +42 -0
  8. data/examples/Capfile +3 -0
  9. data/examples/deploy.rb +101 -0
  10. data/examples/s3.yml +9 -0
  11. data/lib/ec2onrails/capistrano_utils.rb +43 -0
  12. data/lib/ec2onrails/recipes.rb +844 -0
  13. data/lib/ec2onrails/version.rb +31 -0
  14. data/lib/ec2onrails.rb +20 -0
  15. data/server/build-ec2onrails.sh +44 -0
  16. data/server/files/etc/aliases +5 -0
  17. data/server/files/etc/aliases.db +0 -0
  18. data/server/files/etc/apache2/apache2.conf +295 -0
  19. data/server/files/etc/apache2/conf.d/app.proxy_cluster.conf +7 -0
  20. data/server/files/etc/apache2/conf.d/app.proxy_frontend.conf +10 -0
  21. data/server/files/etc/apache2/mods-available/proxy.conf +18 -0
  22. data/server/files/etc/apache2/sites-available/app.common +56 -0
  23. data/server/files/etc/apache2/sites-available/app.custom +0 -0
  24. data/server/files/etc/apache2/sites-available/default +14 -0
  25. data/server/files/etc/apache2/sites-available/default-ssl +19 -0
  26. data/server/files/etc/cron.d/backup_app_db_to_s3 +16 -0
  27. data/server/files/etc/cron.daily/app +9 -0
  28. data/server/files/etc/cron.daily/logrotate_post +19 -0
  29. data/server/files/etc/cron.hourly/app +10 -0
  30. data/server/files/etc/cron.monthly/app +10 -0
  31. data/server/files/etc/cron.weekly/app +10 -0
  32. data/server/files/etc/denyhosts.conf +628 -0
  33. data/server/files/etc/dpkg/dpkg.cfg +13 -0
  34. data/server/files/etc/ec2onrails/README +32 -0
  35. data/server/files/etc/ec2onrails/balancer_members +6 -0
  36. data/server/files/etc/ec2onrails/roles.yml +5 -0
  37. data/server/files/etc/environment +2 -0
  38. data/server/files/etc/god/app.god +35 -0
  39. data/server/files/etc/god/db.god +17 -0
  40. data/server/files/etc/god/examples/have_god_daemonize.god +18 -0
  41. data/server/files/etc/god/master.conf +35 -0
  42. data/server/files/etc/god/memcache.god +15 -0
  43. data/server/files/etc/god/notifications.god +14 -0
  44. data/server/files/etc/god/system.god +34 -0
  45. data/server/files/etc/god/web.god +36 -0
  46. data/server/files/etc/init.d/ec2-every-startup +29 -0
  47. data/server/files/etc/init.d/ec2-first-startup +36 -0
  48. data/server/files/etc/init.d/god +42 -0
  49. data/server/files/etc/init.d/nginx +78 -0
  50. data/server/files/etc/init.d/set_roles +3 -0
  51. data/server/files/etc/logrotate.d/apache2 +16 -0
  52. data/server/files/etc/logrotate.d/mongrel +11 -0
  53. data/server/files/etc/logrotate.d/nginx +11 -0
  54. data/server/files/etc/memcached.conf +47 -0
  55. data/server/files/etc/mongrel_cluster/app.yml +9 -0
  56. data/server/files/etc/motd.tail +13 -0
  57. data/server/files/etc/mysql/my.cnf +149 -0
  58. data/server/files/etc/nginx/nginx.conf +296 -0
  59. data/server/files/etc/postfix/main.cf +4 -0
  60. data/server/files/etc/rcS.d/S91ec2-first-startup +1 -0
  61. data/server/files/etc/rcS.d/S92ec2-every-startup +1 -0
  62. data/server/files/etc/rcS.d/S99set_roles +1 -0
  63. data/server/files/etc/ssh/sshd_config +94 -0
  64. data/server/files/etc/sudoers +1 -0
  65. data/server/files/etc/sudoers.full_access +26 -0
  66. data/server/files/etc/sudoers.restricted_access +28 -0
  67. data/server/files/etc/syslog.conf +69 -0
  68. data/server/files/usr/bin/god +26 -0
  69. data/server/files/usr/local/ec2onrails/COPYING +339 -0
  70. data/server/files/usr/local/ec2onrails/bin/archive_file.rb +44 -0
  71. data/server/files/usr/local/ec2onrails/bin/backup_app_db.rb +159 -0
  72. data/server/files/usr/local/ec2onrails/bin/ec2_meta_data.rb +80 -0
  73. data/server/files/usr/local/ec2onrails/bin/exec_runner +73 -0
  74. data/server/files/usr/local/ec2onrails/bin/init_services.rb +64 -0
  75. data/server/files/usr/local/ec2onrails/bin/optimize_mysql.rb +348 -0
  76. data/server/files/usr/local/ec2onrails/bin/rails_env +35 -0
  77. data/server/files/usr/local/ec2onrails/bin/rebundle.sh +70 -0
  78. data/server/files/usr/local/ec2onrails/bin/restore_app_db.rb +58 -0
  79. data/server/files/usr/local/ec2onrails/bin/set_rails_env +40 -0
  80. data/server/files/usr/local/ec2onrails/bin/set_roles.rb +87 -0
  81. data/server/files/usr/local/ec2onrails/bin/setup_web_proxy.rb +109 -0
  82. data/server/files/usr/local/ec2onrails/config +30 -0
  83. data/server/files/usr/local/ec2onrails/lib/aws_helper.rb +76 -0
  84. data/server/files/usr/local/ec2onrails/lib/god_helper.rb +129 -0
  85. data/server/files/usr/local/ec2onrails/lib/god_patch.rb +43 -0
  86. data/server/files/usr/local/ec2onrails/lib/mysql_helper.rb +101 -0
  87. data/server/files/usr/local/ec2onrails/lib/roles_helper.rb +151 -0
  88. data/server/files/usr/local/ec2onrails/lib/s3_helper.rb +99 -0
  89. data/server/files/usr/local/ec2onrails/lib/utils.rb +16 -0
  90. data/server/files/usr/local/ec2onrails/lib/vendor/ini.rb +268 -0
  91. data/server/files/usr/local/ec2onrails/startup-scripts/every-startup/get-hostname.sh +25 -0
  92. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/README +5 -0
  93. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/create-dirs.sh +39 -0
  94. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/generate-default-web-cert-and-key.sh +49 -0
  95. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/misc.sh +27 -0
  96. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/prepare-mysql-data-dir.sh +24 -0
  97. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-credentials.sh +29 -0
  98. data/server/files/usr/local/ec2onrails/startup-scripts/first-startup/setup-file-permissions.sh +30 -0
  99. data/server/rakefile.rb +242 -0
  100. data/setup.rb +1585 -0
  101. data/test/autobench.conf +60 -0
  102. data/test/spec/lib/s3_helper_spec.rb +134 -0
  103. data/test/spec/lib/s3_old.yml +3 -0
  104. data/test/spec/test_files/test1 +0 -0
  105. data/test/spec/test_files/test2 +0 -0
  106. data/test/test_app/Capfile +3 -0
  107. data/test/test_app/README +182 -0
  108. data/test/test_app/Rakefile +10 -0
  109. data/test/test_app/app/controllers/application.rb +7 -0
  110. data/test/test_app/app/controllers/db_fast_controller.rb +6 -0
  111. data/test/test_app/app/controllers/fast_controller.rb +5 -0
  112. data/test/test_app/app/controllers/slow_controller.rb +6 -0
  113. data/test/test_app/app/controllers/very_slow_controller.rb +6 -0
  114. data/test/test_app/app/helpers/application_helper.rb +3 -0
  115. data/test/test_app/app/helpers/db_fast_helper.rb +2 -0
  116. data/test/test_app/app/helpers/fast_helper.rb +2 -0
  117. data/test/test_app/app/helpers/slow_helper.rb +2 -0
  118. data/test/test_app/app/helpers/very_slow_helper.rb +2 -0
  119. data/test/test_app/config/boot.rb +109 -0
  120. data/test/test_app/config/database.yml +19 -0
  121. data/test/test_app/config/deploy.rb +21 -0
  122. data/test/test_app/config/environment.rb +60 -0
  123. data/test/test_app/config/environments/development.rb +21 -0
  124. data/test/test_app/config/environments/production.rb +18 -0
  125. data/test/test_app/config/environments/test.rb +19 -0
  126. data/test/test_app/config/routes.rb +27 -0
  127. data/test/test_app/db/schema.rb +7 -0
  128. data/test/test_app/doc/README_FOR_APP +2 -0
  129. data/test/test_app/public/404.html +30 -0
  130. data/test/test_app/public/500.html +30 -0
  131. data/test/test_app/public/dispatch.cgi +10 -0
  132. data/test/test_app/public/dispatch.fcgi +24 -0
  133. data/test/test_app/public/dispatch.rb +10 -0
  134. data/test/test_app/public/favicon.ico +0 -0
  135. data/test/test_app/public/images/rails.png +0 -0
  136. data/test/test_app/public/javascripts/application.js +2 -0
  137. data/test/test_app/public/javascripts/controls.js +963 -0
  138. data/test/test_app/public/javascripts/dragdrop.js +972 -0
  139. data/test/test_app/public/javascripts/effects.js +1120 -0
  140. data/test/test_app/public/javascripts/prototype.js +4225 -0
  141. data/test/test_app/public/robots.txt +1 -0
  142. data/test/test_app/script/about +3 -0
  143. data/test/test_app/script/breakpointer +3 -0
  144. data/test/test_app/script/console +3 -0
  145. data/test/test_app/script/destroy +3 -0
  146. data/test/test_app/script/generate +3 -0
  147. data/test/test_app/script/performance/benchmarker +3 -0
  148. data/test/test_app/script/performance/profiler +3 -0
  149. data/test/test_app/script/performance/request +3 -0
  150. data/test/test_app/script/plugin +3 -0
  151. data/test/test_app/script/process/inspector +3 -0
  152. data/test/test_app/script/process/reaper +3 -0
  153. data/test/test_app/script/process/spawner +3 -0
  154. data/test/test_app/script/runner +3 -0
  155. data/test/test_app/script/server +3 -0
  156. data/test/test_app/test/functional/db_fast_controller_test.rb +18 -0
  157. data/test/test_app/test/functional/fast_controller_test.rb +18 -0
  158. data/test/test_app/test/functional/slow_controller_test.rb +18 -0
  159. data/test/test_app/test/functional/very_slow_controller_test.rb +18 -0
  160. data/test/test_app/test/test_helper.rb +28 -0
  161. data/test/test_ec2onrails.rb +11 -0
  162. data/test/test_helper.rb +2 -0
  163. metadata +274 -0
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This file is part of EC2 on Rails.
4
+ # http://rubyforge.org/projects/ec2onrails/
5
+ #
6
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
7
+ #
8
+ # EC2 on Rails is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # EC2 on Rails is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #
21
+ # This script allows you to ONLY execute within a shell IF the role of
22
+ # the server (as defined by capistrano) matches the role specified.
23
+ # ex.
24
+ # * exec_runner -role :db -exec 'echo "hello world"'
25
+ # # will only run if the server is in the db role
26
+ # * exec_runner -role :app -exec /some/app/specific/script/to/call
27
+ #
28
+
29
+ require "rubygems"
30
+ require "optiflag"
31
+
32
+ require "fileutils"
33
+ require "#{File.dirname(__FILE__)}/../lib/roles_helper"
34
+ require "#{File.dirname(__FILE__)}/../lib/utils"
35
+
36
+ include Ec2onrails::RolesHelper
37
+
38
+ module CommandLineArgs extend OptiFlagSet
39
+ optional_flag "role" do
40
+ description "The role of this server, as defined by capistrano. ex. 'db', or 'app' If not used, will be applied to all roles"
41
+ end
42
+
43
+ optional_flag "only_env" do
44
+ description "Only apply the script if it is running within this environment"
45
+ end
46
+
47
+ flag "exec" do
48
+ description "what to run if the role of the server matches the -role passed in"
49
+ end
50
+
51
+ and_process!
52
+ end
53
+
54
+ #strip out the ':', in case the user enters ':db', or ':app'
55
+ role = ARGV.flags.role.sub(/^:/, '').to_sym
56
+ if ARGV.flags.role && !in_role?(role)
57
+ puts "This script is not being run because the server is not running under the #{role} role"
58
+ exit
59
+ end
60
+
61
+ curr_env = Ec2onrails::Utils.rails_env
62
+ if ARGV.flags.only_env && ARGV.flags.only_env.strip != curr_env
63
+ puts "This script is not being run because the server is not running under the #{curr_env} environment"
64
+ exit
65
+ end
66
+
67
+
68
+ # set the default to the current directory; makes it easier to
69
+ Dir.chdir('/mnt/app/current')
70
+
71
+ ENV['RAILS_ENV'] = curr_env
72
+ run ARGV.flags.exec
73
+
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This file is part of EC2 on Rails.
4
+ # http://rubyforge.org/projects/ec2onrails/
5
+ #
6
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
7
+ #
8
+ # EC2 on Rails is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # EC2 on Rails is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ require "#{File.dirname(__FILE__)}/../lib/roles_helper"
22
+ include Ec2onrails::RolesHelper
23
+
24
+
25
+ #TODO:
26
+ # if not in a role, we want to make sure that the service is stopped....
27
+ # it gets a little tricky with the web_proxy, which is not enabled if it is
28
+ # not already in a web role. Leave as is, as all it does is throw an error
29
+ # until GOD is in the picture, at which case it should be easy to enable
30
+ # and let it handle it instead of the init.d script....
31
+
32
+ # memcache role:
33
+ if in_role?(:memcache)
34
+ # increase memory size, etc if no other roles exist?
35
+ start(:memcache, "memcached")
36
+ else
37
+ stop(:memcache, "memcached")
38
+ end
39
+
40
+ # db primary role:
41
+ if in_role?(:db_primary)
42
+ start(:db, "mysql", "mysqld")
43
+ else
44
+ stop(:db, "mysql", "mysqld")
45
+ end
46
+
47
+ # web role:
48
+ if in_role?(:web)
49
+ #we symlink the web_proxy we are using....
50
+ start(:web, "web_proxy", 'nginx apache')
51
+ # sleep(5)
52
+ # run("/etc/init.d/web_proxy reload")
53
+ else
54
+ #not started...
55
+ stop(:web, "web_proxy", 'nginx apache')
56
+ end
57
+
58
+
59
+ # app role:
60
+ if in_role?(:app)
61
+ start(:app, "mongrel", "mongrel_rails")
62
+ else
63
+ stop(:app, "mongrel", "mongrel_rails")
64
+ end
@@ -0,0 +1,348 @@
1
+ #!/usr/bin/ruby
2
+
3
+
4
+ ## Notes about optimizations are inline below.
5
+ # based upon recommendations listed here:
6
+ # http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/
7
+ #
8
+ # For best effect, call this script after every other service has been started.
9
+ #
10
+
11
+ require 'fileutils'
12
+ require "/usr/local/ec2onrails/lib/roles_helper"
13
+ require "/usr/local/ec2onrails/lib/vendor/ini"
14
+ require "/usr/local/ec2onrails/lib/mysql_helper"
15
+ require "/usr/local/ec2onrails/lib/utils"
16
+
17
+ include Ec2onrails::RolesHelper
18
+
19
+ DEFAULT_CONFIG_LOC = "/etc/mysql/my.cnf"
20
+
21
+ exit unless in_role?(:db_primary)
22
+
23
+ local_roles = roles.collect{|r| r.first if r.last.include?('127.0.0.1')}.compact
24
+ only_db_role = local_roles.size < 2
25
+
26
+
27
+ #lets make a copy of the original...but do not overwrite if it already exists!
28
+ FileUtils.copy(DEFAULT_CONFIG_LOC, "#{DEFAULT_CONFIG_LOC}.pre_optimized") unless File.exists?("#{DEFAULT_CONFIG_LOC}.pre_optimized")
29
+
30
+
31
+ ##### ************************** COMPUTE METRICS ************************** #####
32
+ # define metrics used to modify my.cnf. These metrics are used as guidelines
33
+ # and are not meant to be exact measurements or limits.
34
+ #
35
+ # * how much free memory is available?
36
+ #
37
+ # * how many other roles is the db server taking on? Based upon the type
38
+ # and number of other roles, change the amout of memory we should dedicate
39
+ # to the db. This ratio is not the absolute ratio but is used as a guideline
40
+ #
41
+ # * how many cores does the slice have. Then, based upon the Engineyard
42
+ # recommendation that upto 4 mongrels generally take up one core, compute
43
+ # the number of estimated available cores
44
+ #
45
+ # * how many max connections are allowed, and how many database tables exist
46
+ ##### ************************ END COMPUTE METRICS ************************ #####
47
+
48
+ #default is one core
49
+ num_cores = `cat /proc/cpuinfo`.find_all{|o| o =~ /^\s*processor\s+/}.size rescue 1
50
+ #if also running app, just search for ruby because that will
51
+ #include mongrel but also daemons and other scripts
52
+ num_ruby_instances = local_roles.include?(:app) ? `ps ax | grep ruby | grep -v 'grep ruby'`.split("\n").size : 0
53
+ avail_cores = num_cores - num_ruby_instances/4
54
+ avail_cores = 0 if avail_cores.nil? || avail_cores < 0
55
+
56
+
57
+ mem_opt = nil
58
+ mem_opt ||= 0.15 if local_roles.include?(:app) && local_roles.include?(:web) && local_roles.include?(:memcache)
59
+ mem_opt ||= 0.25 if local_roles.include?(:app) && local_roles.include?(:memcache)
60
+ mem_opt ||= 0.35 if local_roles.include?(:app) || local_roles.include?(:memcache)
61
+ mem_opt ||= 0.50 if local_roles.include?(:web)
62
+ mem_opt ||= 0.70 #if only db, lets use a 70% ratio
63
+
64
+ orig_free_mem = (`free -m` =~ /buffers\/cache:\s+\d+\s+(\d+)/; $1).to_i rescue 1024
65
+
66
+ #TODO: take into account memcached settings if memcached is running on this server
67
+ ruby_mem_reserved = num_ruby_instances * 180
68
+ if orig_free_mem > 4098 && (orig_free_mem * mem_opt + ruby_mem_reserved) * 1.25 < orig_free_mem
69
+ mem_opt *= 1.5
70
+ end
71
+ free_mem = (orig_free_mem * mem_opt).to_i
72
+
73
+ @mysql = Ec2onrails::MysqlHelper.new
74
+
75
+ # result = sudo("god start db")
76
+ result = sudo("/etc/init.d/mysql start")
77
+ if result
78
+ puts <<-MSG
79
+ ****** WOOPS ******
80
+ mysql was not successfully started up.
81
+ Not optimizing mysql config file
82
+ MSG
83
+ exit 1
84
+ end
85
+ # sleep(10) #make sure the db has some time to start up!
86
+
87
+ num_connections = 100
88
+ mysql_cmd = %{mysql -u #{@mysql.user} -e "select @@max_connections;"}
89
+ mysql_cmd += " -p'#{@mysql.password}' " unless @mysql.password.nil?
90
+ if `#{mysql_cmd}` =~ /(\d+)/imx
91
+ num_connections = $1.to_i
92
+ end
93
+
94
+ num_tables = 100
95
+ mysql_cmd = %{mysql -u #{@mysql.user} -e "SELECT count(*) TABLES from information_schema.tables where TABLE_SCHEMA = '#{@mysql.database}';"}
96
+ mysql_cmd += " -p'#{@mysql.password}' " unless @mysql.password.nil?
97
+ if `#{mysql_cmd}` =~ /(\d+)/imx
98
+ num_tables = $1.to_i
99
+ end
100
+
101
+ # the default my.cnf is already different than the default example files... it has already
102
+ # been modified for ec2. So lets use that one rather than starting from scratch again.
103
+ # default_mysql_config = if free_mem > 2048
104
+ # "my-huge.cnf"
105
+ # elsif free_mem > 768
106
+ # "my-large.cnf"
107
+ # else
108
+ # "my-medium.cnf"
109
+ # end
110
+
111
+ puts <<-MSG
112
+
113
+ Optimizing mysql based off of these stats:
114
+ * sharing server with these roles : #{local_roles.inspect}
115
+ * num cores (est avail cores) : #{num_cores} (#{avail_cores})
116
+ * avail mem (mem for db) : #{orig_free_mem} (#{free_mem})
117
+ * num database tables : #{num_tables}
118
+ * max num conns : #{num_connections}
119
+ MSG
120
+
121
+
122
+ #lets figure out which default config file to start with:
123
+ # new_config = "/etc/mysql/#{default_mysql_config}"
124
+
125
+
126
+ ##### ******************** Modifying MYSQL config file ******************** #####
127
+ configs = Ini.load(DEFAULT_CONFIG_LOC, :comment => '#')
128
+ configs['mysqld']['key_buffer_size'] ||= configs['mysqld']['key_buffer']
129
+
130
+ modifying_keys = %w(thread_concurrency thread_cache_size query_cache_size table_cache
131
+ key_buffer_size innodb_flush_log_at_trx_commit
132
+ innodb_buffer_pool_size innodb_additional_mem_pool_size
133
+ innodb_log_buffer_size innodb_log_file_size)
134
+
135
+ original_values = modifying_keys.inject([]){|all, key| all << [key, configs['mysqld'][key.to_s]]}
136
+
137
+
138
+ ##### thread_concurrency: only turn on thread concurrency if
139
+ # there are some spare 'cores' available
140
+ if avail_cores < 2
141
+ configs['mysqld'].delete('thread_concurrency')
142
+ elsif
143
+ # Try number of CPU's*2 for thread_concurrency
144
+ configs['mysqld']['thread_concurrency'] = (avail_cores) * 2
145
+ end
146
+
147
+
148
+ #### thread_cache: we don't want threads being created on a regular basis, but
149
+ # if we don't have available cores it doesn't make much sense to cache
150
+ # to many threads
151
+ configs['mysqld']['thread_cache_size'] = if avail_cores > 6
152
+ 24
153
+ elsif avail_cores > 3
154
+ 16
155
+ else
156
+ 8
157
+ end
158
+
159
+
160
+ #### query_cache_size: Important for read-heavy db loads, but it gets expensive
161
+ # to maintain if it gets too large.
162
+ configs['mysqld']['query_cache_size'] = if free_mem > 4096
163
+ only_db_role ? 512 : 384
164
+ elsif free_mem > 2048
165
+ only_db_role ? 256 : 128
166
+ elsif free_mem > 1024
167
+ only_db_role ? 128 : 64
168
+ else
169
+ 64
170
+ end
171
+ configs['mysqld']['query_cache_size'] = "#{configs['mysqld']['query_cache_size']}M"
172
+
173
+
174
+ #### table_cache: Opening tables can be expensive, so this cache helps mitigate that.
175
+ # Each connection needs its own entry in the table cache, but this is less important for innodb
176
+ # heavy database (which most rails apps are).
177
+ # based upont he observation that a cache size of 1024 is a good size for a db with a few hundred tables
178
+ configs['mysqld']['table_cache'] = (num_connections * num_tables)/10
179
+
180
+
181
+ #### key_buffer_size: Does not need to be very large because most rails
182
+ # applications do not use MyISAM, or use if very little (usually to store
183
+ # db-based sessions). Keep space available for temp tables and other
184
+ # little mysql needs
185
+ configs['mysqld']['key_buffer_size'] = if free_mem > 4096
186
+ only_db_role ? 256 : 128
187
+ elsif free_mem > 2048
188
+ only_db_role ? 128 : 64
189
+ elsif free_mem > 1024
190
+ only_db_role ? 64 : 32
191
+ else
192
+ 16
193
+ end
194
+ configs['mysqld']['key_buffer_size'] = "#{configs['mysqld']['key_buffer_size']}M"
195
+ #can use either key_buffer or key_buffer_size.
196
+ #Since we are using key_buffer_size, lets remove the other one
197
+ configs['mysqld'].delete('key_buffer')
198
+
199
+
200
+ #### innodb_flush_log_at_trx_commit: this makes INNODB *much* faster, but
201
+ # it is not 100% ACID compliant. Instead of flushing to disk for every
202
+ # commit, this flushes to the OS file cache. That means that if MySQL
203
+ # crashes, the data will be written, but if the OS crashes, 1-2
204
+ # seconds of information could be lost
205
+ configs['mysqld']['innodb_flush_log_at_trx_commit'] = 2
206
+
207
+
208
+ # * innodb_buffer_pool_size upto 70% of memory..but if sharing and small data sizes, use less (50%?)
209
+
210
+ #### innodb_buffer_pool_size: this is where we should put most of our free memory, since
211
+ # rails apps are heavy users of innodb. Need to be careful NOT to specify TOO much memory
212
+ configs['mysqld']['innodb_buffer_pool_size'] = if free_mem > 4096
213
+ free_mem - 512
214
+ elsif free_mem > 2048
215
+ free_mem - 384
216
+ elsif free_mem > 1024
217
+ free_mem - 256
218
+ elsif free_mem > 512
219
+ free_mem - 192
220
+ elsif free_mem > 256
221
+ free_mem - 128
222
+ else
223
+ free_mem - 98
224
+ end
225
+ configs['mysqld']['innodb_buffer_pool_size'] = "#{configs['mysqld']['innodb_buffer_pool_size']}M"
226
+
227
+
228
+ #### innodb_additional_mem_pool_size: This is not really needed as most OS's do a good job
229
+ # of allocating memory.
230
+ configs['mysqld']['innodb_additional_mem_pool_size'] ||= '16M'
231
+
232
+
233
+ #### innodb_log_buffer_size: This is flushed every second anyway, so 8-16M is generally ok
234
+ configs['mysqld']['innodb_log_buffer_size'] ||= '12M'
235
+
236
+
237
+ #### innodb_log_file_size: Help with heavy writes,
238
+ # BUT if it is too large recovery times can be a lot longer
239
+ configs['mysqld']['innodb_log_file_size'] = if free_mem > 4096
240
+ 512
241
+ elsif free_mem > 2048
242
+ 256
243
+ elsif free_mem > 1024
244
+ 128
245
+ else
246
+ 64
247
+ end
248
+ configs['mysqld']['innodb_log_file_size'] = "#{configs['mysqld']['innodb_log_file_size']}M"
249
+ ##### ****************** END Modifying MYSQL config file ****************** #####
250
+
251
+
252
+
253
+ new_values = modifying_keys.inject([]){|all, key| all << [key, configs['mysqld'][key.to_s]]}
254
+ msg = "\nModified these mysqld parameters:\n"
255
+ msg += <<-MSG
256
+ mysqld key: new value (original value)
257
+ -----------------------------------------------
258
+ MSG
259
+ new_values.each_with_index do |v, i|
260
+ orig_value = original_values[i].last.nil? ? 'not set' : original_values[i].last
261
+ msg += <<-MSG
262
+ * #{v.first}: #{v.last} (#{orig_value})
263
+ MSG
264
+ end
265
+ puts msg
266
+
267
+ config_file_loc = DEFAULT_CONFIG_LOC
268
+ #We need to shut down mysql BEFORE we move the new configs over...
269
+ puts "\nCleanly stopping mysql to replace its config file."
270
+
271
+ #make sure the mysql has time to startup before we shut it down again
272
+ #TODO: can we improve this?
273
+ sleep(5)
274
+
275
+ # result = sudo("god stop db")
276
+ # not using god because it doesn't wait for the script to finish
277
+ # before returning....
278
+ # result = sudo("god stop db")
279
+ result = sudo("/etc/init.d/mysql stop")
280
+ clean_stop = true
281
+ if result
282
+ config_file_loc += ".optimized"
283
+ clean_stop = false
284
+ puts <<-MSG
285
+ ****** WOOPS ******
286
+ mysql was not successfully shut down, so we dare not
287
+ update the config file (it can cause problems with the
288
+ ib_logfile cache). We have saved the new config file at
289
+ #{config_file_loc}
290
+ in case you still want to use it in place of
291
+ #{DEFAULT_CONFIG_LOC}
292
+ MSG
293
+ else
294
+ puts <<-MSG
295
+ cleanly shutdown mysql. Replacing config file:
296
+ #{config_file_loc}
297
+ The original config file can be found here:
298
+ #{DEFAULT_CONFIG_LOC}.pre_optimized
299
+
300
+ Starting mysql...
301
+ MSG
302
+ end
303
+
304
+ configs.save(config_file_loc)
305
+
306
+ config_file = File.read(DEFAULT_CONFIG_LOC)
307
+ File.open(DEFAULT_CONFIG_LOC, 'w') do |file|
308
+ file << <<-MSG
309
+ # This file is generated by '#{__FILE__}'
310
+ # Based upon the default '#{DEFAULT_CONFIG_LOC}'
311
+ # which is now saved at '#{DEFAULT_CONFIG_LOC}.pre_optimized'
312
+
313
+ # See file for comments:
314
+ # #{__FILE__}
315
+ #
316
+ #
317
+
318
+ MSG
319
+ file << config_file
320
+ end
321
+
322
+ if clean_stop
323
+ #before we can start, we need to move the old cache files...
324
+ old_logs = []
325
+ Dir.glob("/mnt/mysql_data/ib_logfile*").each do |f|
326
+ FileUtils.mv(f, f + "_old")
327
+ old_logs << "#{f}_old"
328
+ end
329
+ puts <<-MSG
330
+ Moving the old mysql ib logfiles because we might have changed the
331
+ default logfile cache size. If mysql startups up successfully,
332
+ these files can be removed:
333
+ #{old_logs.join("\n ")}
334
+ MSG
335
+
336
+
337
+ # result = sudo("god start db")
338
+ #using init.d instead of god, because god doesn't wait for the command to finish...
339
+ #it fires it off and then checks it in x seconds
340
+ result = sudo("/etc/init.d/mysql start")
341
+ if result
342
+ puts <<-MSG
343
+ ****** WOOPS ******
344
+ mysql was not successfully started up.
345
+ Check syslog, as the culprit will be logged there.
346
+ MSG
347
+ end
348
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This file is part of EC2 on Rails.
4
+ # http://rubyforge.org/projects/ec2onrails/
5
+ #
6
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
7
+ #
8
+ # EC2 on Rails is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # EC2 on Rails is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+
22
+ # This script runs a command with RAILS_ENV set to the value that's specified
23
+ # in the the mongrel_cluster config file. If a command isn't given as an
24
+ # argument it simply prints the value of RAILS_ENV
25
+
26
+ require "yaml"
27
+
28
+ @rails_env = YAML::load_file("/etc/mongrel_cluster/app.yml")["environment"]
29
+
30
+ if ARGV.any?
31
+ result = system "env RAILS_ENV=#{@rails_env} #{ARGV.join(' ')}"
32
+ raise("error: #{$?}") unless result
33
+ else
34
+ puts @rails_env
35
+ end
@@ -0,0 +1,70 @@
1
+ #!/bin/bash
2
+
3
+ # This file is part of EC2 on Rails.
4
+ # http://rubyforge.org/projects/ec2onrails/
5
+ #
6
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
7
+ #
8
+ # EC2 on Rails is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # EC2 on Rails is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+
22
+ cleanup() {
23
+ rm -f /ec2onrails-first-boot
24
+ }
25
+
26
+ fail() {
27
+ echo "`basename $0`: ERROR: $1"
28
+ cleanup
29
+ exit 1
30
+ }
31
+
32
+ if [ `whoami` != 'root' ] ; then
33
+ fail "This script must be run as root, use 'sudo $0'".
34
+ fi
35
+
36
+ . "/usr/local/ec2onrails/config"
37
+
38
+ TIMESTAMP="`date '+%Y-%m-%d--%H-%M-%S'`"
39
+ NEW_BUCKET_NAME="$BUCKET_BASE_NAME-image-$TIMESTAMP"
40
+
41
+ if [ ! -e /usr/local/ec2-api-tools ] ; then
42
+ echo "The EC2 api command-line tools don't seem to be installed."
43
+ echo "To install them (and Java, which they require), press enter..."
44
+ read
45
+ curl http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip > /tmp/ec2-api-tools.zip || fail "couldn't download ec2-api-tools.zip"
46
+ unzip /tmp/ec2-api-tools.zip -d /usr/local || fail "couldn't unzip ec2-api-tools.zip"
47
+ chmod -R go-w /usr/local/ec2-api-tools*
48
+ ln -sf /usr/local/ec2-api-tools-* /usr/local/ec2-api-tools
49
+ aptitude install -y sun-java6-jre || fail "couldn't install Java package"
50
+ fi
51
+
52
+ echo "--> Clearing apt cache..."
53
+ aptitude clean
54
+
55
+ touch /ec2onrails-first-boot || fail
56
+
57
+ echo "--> Clearing sensitive files..."
58
+ rm -f /root/{.bash_history,.lesshst}
59
+
60
+ echo "--> Creating image..."
61
+ ec2-bundle-vol -e "/root/.ssh,/home/app/.ssh,/tmp,/mnt" -d /mnt -k "$EC2_PRIVATE_KEY" -c "$EC2_CERT" -u "$AWS_ACCOUNT_ID" || fail "ec2-bundle-vol failed"
62
+
63
+ echo "--> Uploading image to $NEW_BUCKET_NAME"
64
+ ec2-upload-bundle -b "$NEW_BUCKET_NAME" -m /mnt/image.manifest.xml -a "$AWS_ACCESS_KEY_ID" -s "$AWS_SECRET_ACCESS_KEY" || fail "ec2-upload-bundle failed"
65
+
66
+ echo "--> Registering image..."
67
+ ec2-register "$NEW_BUCKET_NAME/image.manifest.xml" || fail "ec2-register failed"
68
+
69
+ echo "--> Done."
70
+ cleanup
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This file is part of EC2 on Rails.
4
+ # http://rubyforge.org/projects/ec2onrails/
5
+ #
6
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
7
+ #
8
+ # EC2 on Rails is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # EC2 on Rails is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ require "rubygems"
22
+ require "optiflag"
23
+ require "fileutils"
24
+ require "#{File.dirname(__FILE__)}/../lib/mysql_helper"
25
+ require "#{File.dirname(__FILE__)}/../lib/s3_helper"
26
+ require "#{File.dirname(__FILE__)}/../lib/utils"
27
+
28
+ module CommandLineArgs extend OptiFlagSet
29
+ optional_flag "bucket"
30
+ optional_flag "dir"
31
+ and_process!
32
+ end
33
+
34
+ bucket = ARGV.flags.bucket
35
+ dir = ARGV.flags.dir || "database"
36
+ @s3 = Ec2onrails::S3Helper.new(bucket, dir)
37
+ @mysql = Ec2onrails::MysqlHelper.new
38
+ @temp_dir = "/mnt/tmp/ec2onrails-backup-#{@s3.bucket}-#{dir.gsub(/\//, "-")}"
39
+ if File.exists?(@temp_dir)
40
+ puts "Temp dir exists (#{@temp_dir}), aborting. Is another backup process running?"
41
+ exit
42
+ end
43
+
44
+ begin
45
+ FileUtils.mkdir_p @temp_dir
46
+
47
+ file = "#{@temp_dir}/dump.sql.gz"
48
+ @s3.retrieve_file(file)
49
+ @mysql.load_from_dump(file)
50
+
51
+ @s3.retrieve_files("mysql-bin.", @temp_dir)
52
+ logs = Dir.glob("#{@temp_dir}/mysql-bin.[0-9]*").sort
53
+ logs.each {|log| @mysql.execute_binary_log(log) }
54
+
55
+ @mysql.execute_sql "reset master" # TODO maybe we shouldn't do this if we're not going to delete the logs from the S3 bucket because this restarts the numbering again
56
+ ensure
57
+ FileUtils.rm_rf(@temp_dir)
58
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This file is part of EC2 on Rails.
4
+ # http://rubyforge.org/projects/ec2onrails/
5
+ #
6
+ # Copyright 2007 Paul Dowman, http://pauldowman.com/
7
+ #
8
+ # EC2 on Rails is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # EC2 on Rails is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+
22
+ # This script updates the value of "environment" in the the mongrel_cluster
23
+ # config file.
24
+
25
+ require "yaml"
26
+ require "erb"
27
+
28
+ if ARGV.length != 1
29
+ puts "usage: set_rails_env <value>"
30
+ exit 1
31
+ end
32
+
33
+ @rails_env = ARGV[0]
34
+
35
+ # update mongrel_cluster config
36
+ config = YAML::load_file("/etc/mongrel_cluster/app.yml")
37
+ config["environment"] = @rails_env
38
+ File.open("/etc/mongrel_cluster/app.yml", 'w') do |f|
39
+ YAML.dump(config, f)
40
+ end