namespace :rubber do namespace :postgresql do rubber.allow_optional_tasks(self) after "rubber:create", "rubber:postgresql:validate_db_roles" task :validate_db_roles do db_instances = rubber_instances.for_role("postgresql_slave") db_instances.each do |instance| if instance.role_names.find {|n| n == 'postgresql_master'} fatal "Cannot have a postgresql slave and master on the same instance, please removing slave role for #{instance.name}" end end end after "rubber:bootstrap", "rubber:postgresql:bootstrap" # Bootstrap the production database config. Db bootstrap is special - the # user could be requiring the rails env inside some of their config # templates, which creates a catch 22 situation with the db, so we try and # bootstrap the db separate from the rest of the config task :bootstrap, :roles => [:postgresql_master, :postgresql_slave] do # Conditionaly bootstrap for each node/role only if that node has not # been boostrapped for that role before master_instances = rubber_instances.for_role("postgresql_master") & rubber_instances.filtered master_instances.each do |ic| task_name = "_bootstrap_postgresql_master_#{ic.full_name}".to_sym() task task_name, :hosts => ic.full_name do env = rubber_cfg.environment.bind("postgresql_master", ic.name) exists = capture("echo $(ls #{env.postgresql_data_dir}/ 2> /dev/null)") if exists.strip.size == 0 common_bootstrap("postgresql_master") create_user_cmd = "CREATE USER #{env.db_user} WITH NOSUPERUSER CREATEDB NOCREATEROLE" create_user_cmd << "PASSWORD '#{env.db_pass}'" if env.db_pass rubber.sudo_script "create_master_db", <<-ENDSCRIPT sudo -u postgres psql -c "#{create_user_cmd}" sudo -u postgres psql -c "CREATE DATABASE #{env.db_name} WITH OWNER #{env.db_user}" ENDSCRIPT end end send task_name end # Wait for postgresql 9.0 to be avlabel before allowing slaves # # slave_instances = rubber_instances.for_role("postgresql_slave") & rubber_instances.filtered # slave_instances.each do |ic| # task_name = "_bootstrap_postgresql_slave_#{ic.full_name}".to_sym() # task task_name, :hosts => ic.full_name do # env = rubber_cfg.environment.bind("postgresql_slave", ic.name) # exists = capture("echo $(ls #{env.db_data_dir}/ 2> /dev/null)") # if exists.strip.size == 0 # common_bootstrap("postgresql_slave") # # source = master = rubber_instances.for_role("postgresql_master").first # # slave_pub_key = capture("cat /root/.ssh/id_dsa.pub") # sudo "echo \"#{slave_pub_key}\" >> /root/.ssh/authorized_keys", :hosts => [master.full_name] # # base_backup_script = <<-ENDSCRIPT # sudo -u postgres psql -c "SELECT pg_start_backup('rubber_create_slave')" # tar --exclude pg_xlog -czf /tmp/postgresql-data.tgz #{env.postgresql_data_dir} # tar -czf /tmp/postgresql-archive.tgz #{env.postgresql_archive_dir} # sudo -u postgres psql -c "SELECT pg_stop_backup()" # ENDSCRIPT # # rubber.sudo_script "create_slave_db_from_master", base_backup_script, :hosts => [master.full_name] # # rsudo "psql -u root -e \"start slave;\"" # end # end # send task_name # end end # TODO: Make the setup/update happen just once per host def common_bootstrap(role) # postgresql package install starts postgresql, so stop it rsudo "#{rubber_env.postgresql_ctl} stop" rescue nil # After everything installed on machines, we need the source tree # on hosts in order to run rubber:config for bootstrapping the db rubber.update_code_for_bootstrap # Gen just the conf for the given postgresql role rubber.run_config(:RUBBER_ENV => RUBBER_ENV, :FILE => "role/#{role}|role/db/", :FORCE => true, :deploy_path => release_path) # reconfigure postgresql so that it sets up data dir in /mnt with correct files dirs = [rubber_env.postgresql_data_dir, rubber_env.postgresql_archive_dir] sudo_script 'reconfigure-postgresql', <<-ENDSCRIPT mkdir -p #{dirs.join(' ')} chown -R postgres:postgres #{dirs.join(' ')} sudo -u postgres /usr/lib/postgresql/#{rubber_env.postgresql_ver}/bin/initdb -D #{rubber_env.postgresql_data_dir} #{rubber_env.postgresql_ctl} start ENDSCRIPT sleep 5 end desc <<-DESC Starts the postgresql daemons DESC task :start, :roles => [:postgresql_master, :postgresql_slave] do rsudo "#{rubber_env.postgresql_ctl} start" end desc <<-DESC Stops the postgresql daemons DESC task :stop, :roles => [:postgresql_master, :postgresql_slave] do rsudo "#{rubber_env.postgresql_ctl} stop" end desc <<-DESC Restarts the postgresql daemons DESC task :restart, :roles => [:postgresql_master, :postgresql_slave] do rsudo "#{rubber_env.postgresql_ctl} restart" end end end