2021-02-16 08:49:58 +00:00
require 'net/ssh'
require 'pathname'
namespace :create_site do
desc " Copy Site from another site "
2023-02-23 04:52:58 +00:00
task :copy_site , [ :ip , :server_port , :user , :password , :site_name , :domain_name , :port , :db_name , :path , :site_construct_id , :template_site_construct_id , :only_copy_installed_module ] = > :environment do | task , args |
2021-02-16 08:49:58 +00:00
@password = args . password
template_site = SiteConstruct . find ( args . template_site_construct_id )
if args . site_construct_id . blank?
@site_construct = SiteConstruct . new
@site_construct . server_type = ( SiteServer . where ( :ip = > args . ip ) . first . server_name rescue args . ip )
@site_construct . site_name = args . site_name
@site_construct . domain_name = args . domain_name
2021-02-21 03:59:36 +00:00
@site_construct . db_name = args . db_name . gsub ( " " , " " )
2021-02-16 08:49:58 +00:00
@site_construct . port = args . port
@site_construct . path = args . path
@site_construct . school_name = args . site_name . split ( / [-_] / )
@site_construct . user_id = User . first . id . to_s
@site_construct . save
else
@site_construct = SiteConstruct . find ( args . site_construct_id )
end
begin
2022-03-31 05:53:05 +00:00
org_creating = ( @site_construct . status == " creating " )
2021-02-16 08:49:58 +00:00
@site_construct . update ( :status = > " creating " )
@site_construct . update! ( :infos = > [ ] )
begin
2024-01-14 14:55:38 +00:00
Net :: SSH . start ( args . ip , args . user , { password : @password , port : args . server_port } ) do | ssh |
2021-02-16 08:49:58 +00:00
end
rescue Net :: SSH :: HostKeyMismatch
system ( " ssh-keygen -f \" $HOME/.ssh/known_hosts \" -R #{ args . ip } " )
rescue Errno :: ENOTTY
system ( " ssh-add \" $HOME/.ssh/id_rsa \" " )
end
2024-01-14 14:55:38 +00:00
Net :: SSH . start ( args . ip , args . user , { password : @password , port : args . server_port } ) do | ssh |
2023-07-19 09:25:34 +00:00
update_infos ( " Setting nginx for #{ args . site_name } " )
2021-04-19 01:29:53 +00:00
nginx_setting_texts = @site_construct . generate_nginx_text
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " touch /etc/nginx/orbit_sites/ #{ @site_construct . get_site_name } " )
exec_ssh_command_by_sudo_for_copy ( ssh , " x=' #{ nginx_setting_texts . gsub ( / '{1,3} / , " \" \' \" " ) } '; echo ' #{ @password } ' | sudo -S sh -c \" echo '$x' > /etc/nginx/orbit_sites/ #{ @site_construct . get_site_name } \" " )
2023-07-19 09:25:34 +00:00
update_infos ( " Restarting nginx " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " sudo -p 'sudo password:' service nginx restart " )
2023-07-19 09:25:34 +00:00
update_infos ( " Finish restarting nginx " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " mkdir -p #{ args . path } " )
2023-07-19 09:25:34 +00:00
update_infos ( " Copying site's files for #{ args . site_name } " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_for_copy ( ssh , " sudo -p 'sudo password:' apt-get install -y rsync " )
2021-04-13 03:06:09 +00:00
extra_exclude_path = " "
if args . only_copy_installed_module == true || args . only_copy_installed_module == " true "
extra_exclude_path = " ,public/uploads/ "
end
2022-01-14 02:46:44 +00:00
server = SiteServer . where ( :server_name = > template_site . server_type ) . first
2023-07-19 09:22:39 +00:00
ls_out = exec_ssh_command_for_copy ( ssh , " if [ ! -d \" #{ @site_construct . full_site_path } /app \" ]; then echo 'No such file or directory: #{ @site_construct . full_site_path } /app'; fi " , false ) . join ( " \n " )
if ls_out . include? ( " No such file or directory " ) || org_creating
2022-01-14 03:20:39 +00:00
if @site_construct . server_type == template_site . server_type
2024-01-14 14:55:38 +00:00
exec_ssh_command_for_copy ( ssh , " rsync -ar -e 'ssh -o \" StrictHostKeyChecking=no \" -p 22' --info=progress2 --no-inc-recursive --delete --exclude={tmp/cache/,tmp/unicorn.sock,tmp/pids/* #{ extra_exclude_path } } #{ template_site . path } / #{ template_site . get_site_name } / #{ args . path } / #{ @site_construct . get_site_name } / " , true )
2022-01-14 03:20:39 +00:00
else
2022-09-19 04:07:27 +00:00
exec_ssh_command_for_copy ( ssh , " sudo -p 'sudo password:' apt-get install -y sshpass " )
2024-01-14 14:55:38 +00:00
outputs = exec_ssh_command_for_copy ( ssh , " sshpass -p \" #{ server . password } \" rsync -ar -e 'ssh -o \" StrictHostKeyChecking=no \" -p 22' --info=progress2 --no-inc-recursive --delete --exclude={tmp/cache/,tmp/unicorn.sock,tmp/pids/* #{ extra_exclude_path } } #{ server . account } @ #{ server . ip } : #{ template_site . path } / #{ template_site . get_site_name } / #{ args . path } / #{ @site_construct . get_site_name } / " , true )
2022-01-14 03:20:39 +00:00
if outputs . join ( " \n " ) . include? ( " Host key verification failed " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " ssh-keygen -f \" $HOME/.ssh/known_hosts \" -R #{ server . ip } " )
exec_ssh_command_by_sudo_for_copy ( ssh , " ssh-keyscan -H #{ server . ip } >> ~/.ssh/known_hosts " )
2023-07-19 04:37:28 +00:00
exec_ssh_command_for_copy ( ssh , " sshpass -p \" #{ server . password } \" rsync -ar --info=progress2 --no-inc-recursive --delete --exclude={tmp/cache/,tmp/unicorn.sock,tmp/pids/* #{ extra_exclude_path } } #{ server . account } @ #{ server . ip } : #{ template_site . path } / #{ template_site . get_site_name } / #{ args . path } / #{ @site_construct . get_site_name } / " , true )
2022-01-14 03:20:39 +00:00
end
end
2021-02-16 08:49:58 +00:00
end
update_infos ( " Finish copying site's files for #{ args . site_name } ! " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " sudo -p 'sudo password:' chown #{ args . user } : #{ args . user } #{ args . path } / #{ @site_construct . get_site_name } -R " )
exec_ssh_command_by_sudo_for_copy ( ssh , " sudo -p 'sudo password:' chmod 777 #{ args . path } / #{ @site_construct . get_site_name } -R " )
2021-02-16 08:49:58 +00:00
db_setting_text = ssh . exec! ( " cat #{ args . path } / #{ args . site_name } /config/mongoid.yml " )
2023-07-19 09:25:34 +00:00
update_infos ( " Setting dbname to #{ args . db_name } " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " sh -c \" echo ' #{ db_setting_text . gsub ( / database: .+ / , " database: " + args . db_name ) } ' > #{ args . path } / #{ @site_construct . get_site_name } /config/mongoid.yml \" " , true )
2021-04-13 03:06:09 +00:00
unless args . only_copy_installed_module == true || args . only_copy_installed_module == " true "
2023-07-19 09:25:34 +00:00
update_infos ( " Copying db from #{ template_site . db_name } to #{ args . db_name } " )
2021-04-13 03:06:09 +00:00
if @site_construct . server_type == template_site . server_type
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " mongodump -d #{ template_site . db_name } -o #{ args . path } / #{ @site_construct . get_site_name } /dump_xxxx " )
exec_ssh_command_by_sudo_for_copy ( ssh , " mongorestore --drop -d #{ args . db_name } #{ args . path } / #{ @site_construct . get_site_name } /dump_xxxx/ #{ template_site . db_name } " )
exec_ssh_command_by_sudo_for_copy ( ssh , " rm -rf #{ args . path } / #{ @site_construct . get_site_name } /dump_xxxx " )
2021-04-13 03:06:09 +00:00
else
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " sshpass -p ' #{ server . password } ' ssh #{ server . account } @ #{ server . ip } 'mongodump -d #{ template_site . db_name } -o #{ template_site . path } / #{ template_site . site_name } /dump_xxxx' " )
2023-07-19 04:37:28 +00:00
exec_ssh_command_for_copy ( ssh , " sshpass -p \" #{ server . password } \" rsync -ar --info=progress2 --no-inc-recursive --delete #{ server . account } @ #{ server . ip } : #{ template_site . path } / #{ template_site . get_site_name } /dump_xxxx/ #{ args . path } / #{ args . site_name } /dump_xxxx/ " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " mongorestore --drop -d #{ args . db_name } #{ args . path } / #{ @site_construct . get_site_name } /dump_xxxx/ #{ template_site . db_name } " )
exec_ssh_command_by_sudo_for_copy ( ssh , " rm -rf #{ args . path } / #{ @site_construct . get_site_name } /dump_xxxx " )
exec_ssh_command_by_sudo_for_copy ( ssh , " sshpass -p ' #{ server . password } ' ssh #{ server . account } @ #{ server . ip } 'rm -rf #{ template_site . path } / #{ template_site . get_site_name } /dump_xxxx' " )
2021-04-13 03:06:09 +00:00
end
update_infos ( " Finish copying database! " )
2021-02-16 08:49:58 +00:00
end
2021-02-23 06:18:25 +00:00
update_infos ( " Checking extensions! " )
extensions = [ " downloaded_extensions.rb " , " built_in_extensions.rb " ]
extensions . each do | extension_file |
2022-09-19 04:07:27 +00:00
outputs = exec_ssh_command_by_sudo_for_copy ( ssh , " cat #{ args . path } / #{ @site_construct . get_site_name } / #{ extension_file } " )
2021-03-09 13:31:22 +00:00
next if outputs . blank?
2021-02-23 06:18:25 +00:00
if ! outputs . include? ( " No such file or directory " )
read_lines = outputs . split ( " \n " ) . map { | l | l . split ( '#' ) . first }
2021-03-15 13:02:15 +00:00
include_path_lines = read_lines . select { | l | ( l . include? ( " path " ) rescue false ) }
2021-02-23 06:18:25 +00:00
include_path_lines . each do | line |
path = line . split ( / [:>] / ) . last . gsub ( / [ \ ' \ "] / , " " ) . strip
absolute_path = ( path [ 0 ] == " / " ) ? path : ( " #{ template_site . path } / #{ template_site . get_site_name } / #{ path } " )
absolute_path = ( absolute_path [ - 1 ] == " / " ) ? absolute_path : ( absolute_path + " / " )
if @site_construct . server_type == template_site . server_type
2023-07-19 04:37:28 +00:00
exec_ssh_command_for_copy ( ssh , " rsync -ar --info=progress2 --no-inc-recursive --delete #{ absolute_path } #{ args . path } / #{ args . site_name } / #{ Pathname . new ( absolute_path ) . basename } / " )
2021-02-23 06:18:25 +00:00
else
server = SiteServer . where ( :server_name = > template_site . server_type ) . first
2023-07-19 04:37:28 +00:00
exec_ssh_command_for_copy ( ssh , " sshpass -p \" #{ server . password } \" rsync -ar --info=progress2 --no-inc-recursive --delete #{ server . account } @ #{ server . ip } : #{ absolute_path } #{ args . path } / #{ args . site_name } / #{ Pathname . new ( absolute_path ) . basename } / " )
2021-02-23 06:18:25 +00:00
end
outputs = outputs . gsub ( path , " #{ args . path } / #{ args . site_name } / #{ Pathname . new ( absolute_path ) . basename } / " )
end
if include_path_lines . count != 0
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " sh -c \" echo ' #{ outputs . gsub ( " \" " , " \\ \" " ) . gsub ( " ' " , " \\ \" " ) } ' > #{ args . path } / #{ @site_construct . get_site_name } / #{ extension_file } \" " )
2021-02-23 06:18:25 +00:00
end
end
end
update_infos ( " Finish checking extensions! " )
2023-07-19 09:25:34 +00:00
update_infos ( " Execing bundle install... " )
2023-07-27 02:57:29 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " bash -l -c 'cd #{ args . path } / #{ @site_construct . get_site_name } \n rm -f Gemfile.lock tmp/unicorn_rails.sock tmp/unicorn_roda.sock tmp/unicorn.sock \n bundle install' " , true )
exec_ssh_command_by_sudo_for_copy ( ssh , " bash -l -c 'cd #{ args . path } / #{ @site_construct . get_site_name } \n rm -f Gemfile.lock tmp/unicorn_rails.sock tmp/unicorn_roda.sock tmp/unicorn.sock \n bundle install' " )
2023-07-19 09:25:34 +00:00
update_infos ( " Finish execing bundle install " )
update_infos ( " Starting #{ args . site_name } web server to development " )
2022-09-19 04:07:27 +00:00
outputs = exec_ssh_command_by_sudo_for_copy ( ssh , " bash -l -c 'cd #{ args . path } / #{ @site_construct . get_site_name } \n kill -s TERM `fuser tmp/unicorn.sock` \n sudo -p \" sudo password: \" kill -s TERM `sudo -p \" sudo password: \" fuser tmp/unicorn.sock` \n sudo -p \" sudo password: \" rm -f tmp/pids/unicorn.pid \n bundle exec unicorn_rails -c config/unicorn.rb -D -E development \n ' " )
2021-03-15 13:02:15 +00:00
if ( outputs . include? " not writable " rescue false )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " sudo -p 'sudo password:' chown #{ args . user } : #{ args . user } #{ args . path } / #{ @site_construct . get_site_name } -R " )
exec_ssh_command_by_sudo_for_copy ( ssh , " sudo -p 'sudo password:' chmod 777 #{ args . path } / #{ @site_construct . get_site_name } -R " )
2021-02-16 08:49:58 +00:00
end
2023-07-19 09:25:34 +00:00
update_infos ( " Finish creating #{ args . site_name } " )
2022-09-19 04:07:27 +00:00
exec_ssh_command_by_sudo_for_copy ( ssh , " chmod 777 #{ args . path } / #{ @site_construct . get_site_name } -R " )
2021-02-16 08:49:58 +00:00
@site_construct . update ( :status = > " finish " )
puts " finish creating #{ args . site_name } on #{ args . ip } "
end
rescue = > e
@site_construct . update ( :status = > " error " , :infos = > @site_construct . infos . push ( " #{ e } " ) )
end
end
def exec_ssh_command_by_sudo ( session , command )
output = session . exec! ( " echo ' #{ @password } ' | sudo -S #{ command } " )
# output = session.exec!("echo '#{@password}' | sudo -S -s #{command}")
if output . include? ( " sudo: " ) && output . include? ( " command not found " )
output = session . exec! ( command )
end
2022-07-21 16:10:04 +00:00
return output . encode! ( " UTF-8 " , :invalid = > :replace , :undef = > :replace , :replace = > '' )
2021-02-16 08:49:58 +00:00
end
2023-07-19 07:39:53 +00:00
def exec_ssh_command_for_copy ( session , command , update_outputs = false )
2021-02-16 08:49:58 +00:00
outputs = [ ]
2023-07-19 09:22:39 +00:00
if update_outputs
update_infos_for_exec ( " " )
end
2021-02-16 08:49:58 +00:00
session . open_channel do | channel |
channel . request_pty do | channel , success |
2023-07-19 09:22:39 +00:00
channel . exec ( " LANG=en.UTF8 && #{ command } " ) do | ch , success |
2021-02-16 08:49:58 +00:00
abort " could not execute command: #{ command } " unless success
channel . on_data do | ch , data |
2023-07-19 07:39:53 +00:00
data_str = data . to_s
data_str . encode! ( " UTF-8 " , :invalid = > :replace , :undef = > :replace , :replace = > '' )
if data_str . include? ( " sudo password: " ) || data_str . include? ( " Password: " )
channel . send_data " #{ @password } \n "
else
print data_str unless @no_stdout
data_str . gsub! ( " \r \n " , " \n " )
rm_idx = data_str . index ( " \r " )
if rm_idx . nil?
@remove_last_line = false
2021-02-16 08:49:58 +00:00
else
2023-07-19 07:39:53 +00:00
@remove_last_line = ( outputs . count > 0 && data_str [ 0 ... rm_idx ] . exclude? ( " \n " ) )
end
data_str . gsub! ( / .* \ r / , '' )
next if data_str . length == 0
if data_str . include? ( " \n " ) || outputs . empty?
output_lines = data_str . split ( " \n " )
first_output = output_lines [ 0 ]
if first_output
if @remove_last_line
outputs = outputs [ 1 .. - 1 ]
outputs = [ ] if outputs . nil?
end
if outputs . count != 0
outputs [ - 1 ] += first_output
else
outputs << first_output
end
end
new_arr = output_lines [ 1 .. - 1 ]
new_arr = [ ] if new_arr . nil?
if data_str [ - 1 ] == " \n "
new_arr << " "
end
outputs += new_arr
if update_outputs
if first_output
update_infos_for_exec ( first_output , true )
end
update_infos_for_exec ( new_arr , false , true )
end
else
if @remove_last_line
outputs = outputs [ 1 .. - 1 ]
outputs = [ ] if outputs . nil?
end
if outputs . count == 0
outputs . push ( data_str )
else
outputs [ - 1 ] += ( data_str rescue " " )
end
if update_outputs
update_infos_for_exec ( data_str , true )
end
2021-02-16 08:49:58 +00:00
end
end
end
end
end
end
session . loop
return outputs
end
2022-09-19 04:07:27 +00:00
def exec_ssh_command_by_sudo_for_copy ( session , command , update = false )
outputs = exec_ssh_command_for_copy ( session , command , update )
tmp = outputs . join ( " \n " )
2021-02-16 08:49:58 +00:00
if outputs . join ( " \n " ) . include? ( " Permission denied " ) || outputs . join ( " \n " ) . include? ( " Operation not permitted " )
2022-09-19 04:07:27 +00:00
outputs = exec_ssh_command_for_copy ( session , " sudo -p 'sudo password:' #{ command } " , update )
tmp = outputs . join ( " \n " )
2021-02-16 08:49:58 +00:00
end
2022-09-19 04:07:27 +00:00
return tmp
2021-02-16 08:49:58 +00:00
end
2023-07-19 07:39:53 +00:00
def update_infos_for_exec ( info , update_last = false , update_array = false )
return if @site_construct . nil?
2021-02-16 08:49:58 +00:00
if update_last && ! @site_construct . infos . empty?
2023-07-19 07:39:53 +00:00
if @remove_last_line
@site_construct . infos [ - 1 ] = info . to_s
else
@site_construct . infos [ - 1 ] += info . to_s
end
2021-02-16 08:49:58 +00:00
else
2023-07-19 07:39:53 +00:00
if @remove_last_line
@site_construct . infos = @site_construct . infos [ 0 ... - 1 ]
end
if update_array
@site_construct . infos += info
else
@site_construct . infos . push ( info . to_s )
end
2021-02-16 08:49:58 +00:00
end
@site_construct . save!
return @site_construct . infos
end
def update_infos ( info )
puts info
@site_construct . infos = @site_construct . infos . push ( info )
@site_construct . save!
return @site_construct . infos
end
end