Apply basic bluepill configuration, write capistrano recipe for it. Change deploy logic to integrate with bluepill. Refactor unicorn config. Cleanup depoy. Refactor mount_downloads script. Write autostart script. Remove old scripts. Refactor platform mount/umount methods. Fix bugs. Refs #1
This commit is contained in:
parent
bd8788fe49
commit
045b8441f6
1
Gemfile
1
Gemfile
|
@ -64,6 +64,7 @@ group :development do
|
||||||
# gem 'capistrano-exts', :require => false #, :git => 'git://github.com/chipiga/capistrano-exts.git'
|
# gem 'capistrano-exts', :require => false #, :git => 'git://github.com/chipiga/capistrano-exts.git'
|
||||||
# gem 'capistrano-recipes', :require => false
|
# gem 'capistrano-recipes', :require => false
|
||||||
gem 'capistrano_colors', :require => false
|
gem 'capistrano_colors', :require => false
|
||||||
|
gem 'bluepill', :require => false
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
|
|
|
@ -41,6 +41,11 @@ GEM
|
||||||
activerecord (>= 2.2.2)
|
activerecord (>= 2.2.2)
|
||||||
arel (2.0.10)
|
arel (2.0.10)
|
||||||
bcrypt-ruby (3.0.1)
|
bcrypt-ruby (3.0.1)
|
||||||
|
bluepill (0.0.51)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
daemons (~> 1.1.0)
|
||||||
|
i18n (>= 0.5.0)
|
||||||
|
state_machine (~> 0.9.4)
|
||||||
builder (2.1.2)
|
builder (2.1.2)
|
||||||
cancan (1.6.7)
|
cancan (1.6.7)
|
||||||
cape (1.0.1)
|
cape (1.0.1)
|
||||||
|
@ -180,6 +185,7 @@ GEM
|
||||||
i18n (>= 0.5.0)
|
i18n (>= 0.5.0)
|
||||||
sexp_processor (3.0.8)
|
sexp_processor (3.0.8)
|
||||||
silent-postgres (0.1.1)
|
silent-postgres (0.1.1)
|
||||||
|
state_machine (0.9.4)
|
||||||
thor (0.14.6)
|
thor (0.14.6)
|
||||||
treetop (1.4.10)
|
treetop (1.4.10)
|
||||||
polyglot
|
polyglot
|
||||||
|
@ -204,6 +210,7 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
airbrake (~> 3.0.5)
|
airbrake (~> 3.0.5)
|
||||||
ancestry (~> 1.2.4)
|
ancestry (~> 1.2.4)
|
||||||
|
bluepill
|
||||||
cancan (~> 1.6.7)
|
cancan (~> 1.6.7)
|
||||||
cape
|
cape
|
||||||
capistrano
|
capistrano
|
||||||
|
|
|
@ -55,8 +55,7 @@ class PlatformsController < ApplicationController
|
||||||
@platform.owner = (params[:admin_uname]) ? User.find_by_uname(params[:admin_uname]) : nil
|
@platform.owner = (params[:admin_uname]) ? User.find_by_uname(params[:admin_uname]) : nil
|
||||||
@platform.owner ||= get_owner
|
@platform.owner ||= get_owner
|
||||||
|
|
||||||
if @platform.save!
|
if @platform.save
|
||||||
# @platform.make_admin_relation(@platform.owner.id)
|
|
||||||
flash[:notice] = I18n.t("flash.platform.saved")
|
flash[:notice] = I18n.t("flash.platform.saved")
|
||||||
redirect_to @platform
|
redirect_to @platform
|
||||||
else
|
else
|
||||||
|
|
|
@ -60,6 +60,10 @@ class Platform < ActiveRecord::Base
|
||||||
build_path(name)
|
build_path(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mount_path
|
||||||
|
Rails.root.join("public", "downloads", name)
|
||||||
|
end
|
||||||
|
|
||||||
def hidden?
|
def hidden?
|
||||||
visibility == 'hidden'
|
visibility == 'hidden'
|
||||||
end
|
end
|
||||||
|
@ -106,31 +110,20 @@ class Platform < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def mount_directory_for_rsync
|
def mount_directory_for_rsync
|
||||||
#FileUtils.rm_rf "#{ Rails.root.join('tmp', 'umount', self.name) }" if File.exist? "#{ Rails.root.join('tmp', 'umount', name) }"
|
# umount_directory_for_rsync # TODO ignore errors
|
||||||
#FileUtils.mkdir_p "#{ Rails.root.join('tmp', 'mount', name) }"
|
system("sudo mkdir -p #{mount_path}")
|
||||||
system("sudo mkdir -p #{ Rails.root.join("public", "downloads") }/#{ name }")
|
system("sudo mount --bind #{path} #{mount_path}")
|
||||||
system("sudo mount --bind /home/share/platforms/#{ name } #{ Rails.root.join("public", "downloads") }/#{ name }")
|
|
||||||
#system("sudo cp -f /srv/rosa_build/current/tmp/mount/#{ name }/* /home/share/platforms/#{ name }/repository/")
|
|
||||||
#system("sudo rm -Rf \"/srv/rosa_build/current/tmp/mount/#{ name }\"")
|
|
||||||
Arch.all.each do |arch|
|
Arch.all.each do |arch|
|
||||||
host = EventLog.current_controller.request.host_with_port rescue ::Rosa::Application.config.action_mailer.default_url_options[:host]
|
host = EventLog.current_controller.request.host_with_port rescue ::Rosa::Application.config.action_mailer.default_url_options[:host]
|
||||||
url = "http://#{host}/downloads/#{name}/repository/"
|
url = "http://#{host}/downloads/#{name}/repository/"
|
||||||
str = "country=Russian Federation,city=Moscow,latitude=52.18,longitude=48.88,bw=1GB,version=2011,arch=#{arch.name},type=distrib,url=#{url}\n"
|
str = "country=Russian Federation,city=Moscow,latitude=52.18,longitude=48.88,bw=1GB,version=2011,arch=#{arch.name},type=distrib,url=#{url}\n"
|
||||||
File.open(Rails.root.join("public", 'downloads', name, "#{name}.#{arch.name}.list"), 'w') {|f| f.write(str) }
|
File.open(File.join(mount_path, "#{name}.#{arch.name}.list"), 'w') {|f| f.write(str) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def umount_directory_for_rsync
|
def umount_directory_for_rsync
|
||||||
system("sudo umount #{ Rails.root.join("public", "downloads") }/#{ name }")
|
system("sudo umount #{mount_path}")
|
||||||
system("sudo rm -Rf #{ Rails.root.join("public", "downloads") }/#{ name }")
|
system("sudo rm -Rf #{mount_path}")
|
||||||
#system("rm -Rf \"/srv/rosa_build/current/tmp/umount/#{ name }\"")
|
|
||||||
#FileUtils.rm_rf "#{ Rails.root.join('tmp', 'mount', name) }" if File.exist? "#{ Rails.root.join('tmp', 'mount', name) }"
|
|
||||||
#FileUtils.mkdir_p "#{ Rails.root.join('tmp', 'umount', name) }"
|
|
||||||
end
|
|
||||||
|
|
||||||
def make_admin_relation(user_id)
|
|
||||||
r = self.relations.build :object_id => user_id, :object_type => 'User', :role => 'admin'
|
|
||||||
r.save
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for f in `ls /srv`
|
||||||
|
do
|
||||||
|
sudo -u rosa rvmsudo bundle exec bluepill load /srv/$f/current/config/production.pill APP_NAME=$f
|
||||||
|
done
|
||||||
|
|
||||||
|
/srv/rosa_build/current/bin/mount_downloads.sh
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
for f in `ls /srv/rosa_build/shared/downloads`
|
for f in `ls /srv/rosa_build/shared/downloads`
|
||||||
do
|
do
|
||||||
if [ -d "/home/share/platforms/$f" ]
|
if [ -d /home/share/platforms/$f ]
|
||||||
then
|
then
|
||||||
mount --bind "/home/share/platforms/$f" "/srv/rosa_build/shared/downloads/$f"
|
sudo umount /srv/rosa_build/shared/downloads/$f 2>&1 >> /dev/null
|
||||||
|
sudo mount --bind /home/share/platforms/$f /srv/rosa_build/shared/downloads/$f
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for f in `ls /srv/rosa_build/current/tmp/mount`
|
|
||||||
do
|
|
||||||
mkdir -p "/srv/rosa_build/shared/downloads/$f"
|
|
||||||
mount --bind "/home/share/platforms/$f" "/srv/rosa_build/shared/downloads/$f"
|
|
||||||
cp -f /srv/rosa_build/current/tmp/mount/$f/* /home/share/platforms/$f/repository/
|
|
||||||
rm -Rf "/srv/rosa_build/current/tmp/mount/$f"
|
|
||||||
done
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
mv /srv/rosa_build/shared/log/nginx.access.log /srv/rosa_build/shared/log/nginx.access.log.0
|
|
||||||
/etc/init.d/nginx reload
|
|
||||||
chown rosa /srv/rosa_build/shared/log/nginx.access.log.0
|
|
||||||
# touch /home/rosa/i_was_launched.txt
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for f in `ls /srv/rosa_build/current/tmp/umount`
|
|
||||||
do
|
|
||||||
umount "/srv/rosa_build/shared/downloads/$f"
|
|
||||||
rm -Rf "/srv/rosa_build/shared/downloads/$f"
|
|
||||||
rm -Rf "/srv/rosa_build/current/tmp/umount/$f"
|
|
||||||
done
|
|
|
@ -29,6 +29,7 @@ set :scm, "git"
|
||||||
|
|
||||||
require 'lib/recipes/nginx'
|
require 'lib/recipes/nginx'
|
||||||
require 'lib/recipes/unicorn'
|
require 'lib/recipes/unicorn'
|
||||||
|
require 'lib/recipes/bluepill'
|
||||||
namespace :deploy do
|
namespace :deploy do
|
||||||
# task :restart, :roles => :app, :except => { :no_release => true } do
|
# task :restart, :roles => :app, :except => { :no_release => true } do
|
||||||
# run "touch #{current_release}/tmp/restart.txt"
|
# run "touch #{current_release}/tmp/restart.txt"
|
||||||
|
@ -50,16 +51,11 @@ namespace :deploy do
|
||||||
|
|
||||||
run "mkdir -p #{fetch :shared_path}/downloads"
|
run "mkdir -p #{fetch :shared_path}/downloads"
|
||||||
run "ln -nfs #{fetch :shared_path}/downloads/ #{fetch :release_path}/public/downloads"
|
run "ln -nfs #{fetch :shared_path}/downloads/ #{fetch :release_path}/public/downloads"
|
||||||
|
|
||||||
run "mkdir -p #{fetch :shared_path}/tmp"
|
|
||||||
run "ln -nfs #{fetch :shared_path}/pids/ #{fetch :shared_path}/tmp/pids"
|
|
||||||
run "ln -nfs #{fetch :shared_path}/tmp/ #{fetch :release_path}/tmp"
|
|
||||||
run "mkdir -p #{fetch :release_path}/tmp/mount"
|
|
||||||
run "mkdir -p #{fetch :release_path}/tmp/umount"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
after "deploy:update_code", "deploy:symlink_all", "deploy:migrate"
|
after "deploy:update_code", "deploy:symlink_all", "deploy:migrate"
|
||||||
|
after "deploy:update", "bluepill:quit", "bluepill:start"
|
||||||
after "deploy:restart", "delayed_job:restart", "deploy:cleanup"
|
after "deploy:restart", "delayed_job:restart", "deploy:cleanup"
|
||||||
|
|
||||||
require 'cape'
|
require 'cape'
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#! /usr/bin/env ruby
|
||||||
|
|
||||||
|
app_name = ENV['APP_NAME'] rescue 'rosa_build'
|
||||||
|
Bluepill.application(app_name) do |app|
|
||||||
|
app.uid = app.gid = 'rosa'
|
||||||
|
app.working_dir = "/srv/#{app_name}/current"
|
||||||
|
app.process("delayed_job") do |process|
|
||||||
|
process.start_grace_time = 10.seconds
|
||||||
|
process.stop_grace_time = 10.seconds
|
||||||
|
process.restart_grace_time = 10.seconds
|
||||||
|
|
||||||
|
process.start_command = "bundle exec script/delayed_job -e production start"
|
||||||
|
process.stop_command = "bundle exec script/delayed_job -e production stop"
|
||||||
|
process.pid_file = File.join('tmp', 'pids', 'delayed_job.pid')
|
||||||
|
end
|
||||||
|
|
||||||
|
app.process("unicorn") do |process|
|
||||||
|
process.start_grace_time = 8.seconds
|
||||||
|
process.stop_grace_time = 5.seconds
|
||||||
|
process.restart_grace_time = 13.seconds
|
||||||
|
|
||||||
|
process.start_command = "bundle exec unicorn -l /tmp/#{app_name}_unicorn.sock -c config/unicorn.rb -D"
|
||||||
|
process.stop_command = "kill -QUIT {{PID}}"
|
||||||
|
process.restart_command = "kill -USR2 {{PID}}"
|
||||||
|
process.pid_file = File.join('tmp', 'pids', 'unicorn.pid')
|
||||||
|
|
||||||
|
process.monitor_children do |child_process|
|
||||||
|
child_process.stop_command = "kill -QUIT {{PID}}"
|
||||||
|
|
||||||
|
child_process.checks :mem_usage, :every => 10.seconds, :below => 150.megabytes, :times => [3,4], :fires => :stop
|
||||||
|
child_process.checks :cpu_usage, :every => 10.seconds, :below => 20, :times => [3,4], :fires => :stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,11 +1,10 @@
|
||||||
|
base_path = File.expand_path(File.join File.dirname(__FILE__), '..')
|
||||||
rails_env = ENV['RAILS_ENV'] || 'production'
|
rails_env = ENV['RAILS_ENV'] || 'production'
|
||||||
|
|
||||||
worker_processes 4
|
worker_processes 4
|
||||||
|
working_directory base_path # available in 0.94.0+
|
||||||
|
|
||||||
preload_app true
|
# listen File.join(base_path, 'tmp', 'pids', 'unicorn.sock')
|
||||||
|
|
||||||
working_directory File.expand_path(File.join(File.dirname(__FILE__), "..")) # available in 0.94.0+
|
|
||||||
|
|
||||||
# listen '/tmp/rosa_build.sock', :backlog => 2048
|
|
||||||
# listen "/tmp/.sock", :backlog => 64
|
# listen "/tmp/.sock", :backlog => 64
|
||||||
# listen 8080, :tcp_nopush => true
|
# listen 8080, :tcp_nopush => true
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ working_directory File.expand_path(File.join(File.dirname(__FILE__), "..")) # a
|
||||||
timeout 600
|
timeout 600
|
||||||
|
|
||||||
# feel free to point this anywhere accessible on the filesystem
|
# feel free to point this anywhere accessible on the filesystem
|
||||||
pid File.expand_path(File.join(File.dirname(__FILE__), "..")) + '/tmp/pids/unicorn.pid'
|
pid File.join(base_path, 'tmp', 'pids', 'unicorn.pid')
|
||||||
|
|
||||||
# REE
|
# REE
|
||||||
# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
||||||
|
@ -24,8 +23,8 @@ end
|
||||||
# By default, the Unicorn logger will write to stderr.
|
# By default, the Unicorn logger will write to stderr.
|
||||||
# Additionally, ome applications/frameworks log to stderr or stdout,
|
# Additionally, ome applications/frameworks log to stderr or stdout,
|
||||||
# so prevent them from going to /dev/null when daemonized here:
|
# so prevent them from going to /dev/null when daemonized here:
|
||||||
stderr_path File.expand_path(File.join(File.dirname(__FILE__), "..")) + "/log/unicorn.stderr.log"
|
stderr_path File.join(base_path, 'log', 'unicorn.stderr.log')
|
||||||
stdout_path File.expand_path(File.join(File.dirname(__FILE__), "..")) + "/log/unicorn.stdout.log"
|
stdout_path File.join(base_path, 'log', 'unicorn.stdout.log')
|
||||||
|
|
||||||
# combine REE with "preload_app true" for memory savings
|
# combine REE with "preload_app true" for memory savings
|
||||||
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
||||||
|
@ -42,7 +41,7 @@ before_fork do |server, worker|
|
||||||
# we send it a QUIT.
|
# we send it a QUIT.
|
||||||
#
|
#
|
||||||
# Using this method we get 0 downtime deploys.
|
# Using this method we get 0 downtime deploys.
|
||||||
old_pid = File.expand_path(File.join(File.dirname(__FILE__), "..")) + '/tmp/pids/unicorn.pid.oldbin'
|
old_pid = File.join(base_path, 'tmp', 'pids', '/unicorn.pid.oldbin')
|
||||||
if File.exists?(old_pid) && server.pid != old_pid
|
if File.exists?(old_pid) && server.pid != old_pid
|
||||||
begin
|
begin
|
||||||
Process.kill("QUIT", File.read(old_pid).to_i)
|
Process.kill("QUIT", File.read(old_pid).to_i)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
Capistrano::Configuration.instance(:must_exist).load do
|
||||||
|
namespace :bluepill do
|
||||||
|
set(:bluepill_config) { File.join release_path, 'config', 'production.pill' }
|
||||||
|
|
||||||
|
desc "Stop processes that bluepill is monitoring and quit bluepill"
|
||||||
|
task :quit, :roles => [:app] do
|
||||||
|
sudo "bundle exec bluepill stop APP_NAME=#{fetch :application}"
|
||||||
|
sudo "bundle exec bluepill quit APP_NAME=#{fetch :application}"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Load bluepill configuration and start it"
|
||||||
|
task :start, :roles => [:app] do
|
||||||
|
sudo "bundle exec bluepill load #{bluepill_config} APP_NAME=#{fetch :application}"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Prints bluepills monitored processes statuses"
|
||||||
|
task :status, :roles => [:app] do
|
||||||
|
sudo "bundle exec bluepill status APP_NAME=#{fetch :application}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,7 +8,8 @@ Capistrano::Configuration.instance(:must_exist).load do
|
||||||
task :generate_configuration, :roles => :web, :except => { :no_release => true } do
|
task :generate_configuration, :roles => :web, :except => { :no_release => true } do
|
||||||
config = %Q{
|
config = %Q{
|
||||||
upstream #{application}_backend {
|
upstream #{application}_backend {
|
||||||
server 127.0.0.1:#{unicorn_port};
|
# server 127.0.0.1:#{unicorn_port};
|
||||||
|
server unix:/tmp/#{fetch :application}_unicorn.sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
Capistrano::Configuration.instance(:must_exist).load do
|
Capistrano::Configuration.instance(:must_exist).load do
|
||||||
namespace :deploy do
|
namespace :deploy do
|
||||||
set :unicorn_binary, "bundle exec unicorn"
|
set :unicorn_binary, "bundle exec unicorn"
|
||||||
set(:unicorn_config) { "#{fetch :current_path}/config/unicorn.rb" }
|
|
||||||
set(:unicorn_pid) { "#{fetch :shared_path}/tmp/pids/unicorn.pid" }
|
set(:unicorn_pid) { "#{fetch :shared_path}/tmp/pids/unicorn.pid" }
|
||||||
set :unicorn_port, 8080
|
# set :unicorn_port, 8080
|
||||||
|
|
||||||
task :start, :roles => :app, :except => { :no_release => true } do
|
task :start, :roles => :app, :except => { :no_release => true } do
|
||||||
run "cd #{fetch :current_path} && #{try_sudo} #{unicorn_binary} -c #{unicorn_config} -p #{unicorn_port} -E #{rails_env} -D"
|
run "cd #{fetch :current_path} && #{try_sudo} #{unicorn_binary} -l /tmp/#{fetch :application}_unicorn.sock -E #{rails_env} -c config/unicorn.rb -D" # -p #{unicorn_port}
|
||||||
end
|
end
|
||||||
task :stop, :roles => :app, :except => { :no_release => true } do
|
task :stop, :roles => :app, :except => { :no_release => true } do
|
||||||
run "#{try_sudo} kill `cat #{unicorn_pid}`" rescue warn 'deploy:stop FAILED'
|
run "#{try_sudo} kill `cat #{unicorn_pid}`" rescue warn 'deploy:stop FAILED'
|
||||||
|
|
Loading…
Reference in New Issue