<%= f.label :server_type ,"Server", :class => "control-label muted" %>
diff --git a/app/views/admin/site_panel/_sites_list_table.html.erb b/app/views/admin/site_panel/_sites_list_table.html.erb
index 3b94737..9588ddf 100644
--- a/app/views/admin/site_panel/_sites_list_table.html.erb
+++ b/app/views/admin/site_panel/_sites_list_table.html.erb
@@ -30,7 +30,10 @@
<% end%>
Exec commands
" title="See <%=site.domain_name%> detail" class="btn btn-primary see_detail" data-id="<%=site.id.to_s%>">Detail
-
" title="Delete <%=site.domain_name%> from list" class="btn btn-primary see_detail" data-id="<%=site.id.to_s%>">Delete from list
+
" title="Delete <%=site.domain_name%> from list" class="btn btn-primary" data-id="<%=site.id.to_s%>">Delete from list
+ <% if site.status == "finish" || site.status == "closed" %>
+
" title="Copy site to another site." class="btn btn-primary">Copy site
+ <% end %>
<% end %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 4c47224..dd51bbd 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,5 +1,6 @@
en:
client_management:
+ copy_source: Copy Source
see_sites: See sites on the server
client_management: Client Management
my_sites: My Sites
diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml
index 59e304a..a637a5b 100644
--- a/config/locales/zh_tw.yml
+++ b/config/locales/zh_tw.yml
@@ -1,5 +1,6 @@
zh_tw:
client_management:
+ copy_source: 複製來源
see_sites: 查看主機上的網站
client_management: Client Management
my_sites: My Sites
diff --git a/lib/tasks/copy_site.rake b/lib/tasks/copy_site.rake
new file mode 100644
index 0000000..45fa1c0
--- /dev/null
+++ b/lib/tasks/copy_site.rake
@@ -0,0 +1,181 @@
+require 'net/ssh'
+require 'pathname'
+namespace :create_site do
+ desc "Copy Site from another site"
+ task :copy_site,[:ip,:user,:password,:site_name,:domain_name,:port,:db_name,:path,:site_construct_id,:template_site_construct_id] => :environment do |task,args|
+ @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
+ @site_construct.db_name = args.db_name
+ @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
+ @site_construct.update(:status=>"creating")
+ @site_construct.update!(:infos=>[])
+ begin
+ Net::SSH.start(args.ip , args.user , password: args.password) do |ssh|
+ 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
+ Net::SSH.start(args.ip , args.user , password: args.password) do |ssh|
+ update_infos("setting nginx for #{args.site_name}")
+ nginx_setting_texts = ('upstream '+args.site_name+'_sock {\n'+
+ ' server unix:'+args.path+'/'+args.site_name+'/tmp/unicorn.sock;\n'+
+ '}\n'+
+ 'server {\n'+
+ ' listen '+args.port+';\n\n'+
+ ' root '+args.path+'/'+args.site_name+'/public;\n\n'+
+ 'server_name '+args.domain_name+';\n\n'+
+ ' client_max_body_size 500m;\n\n'+
+ ' location / {\n'+
+ ' try_files \$uri \$uri/index.html \$uri.html @app;\n'+
+ ' }\n\n'+
+ ' location @app {\n'+
+ ' proxy_redirect off;\n'+
+ ' proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;\n'+
+ ' proxy_set_header Host \$http_host;\n'+
+ ' proxy_connect_timeout 360;\n'+
+ 'proxy_pass http://'+args.site_name+'_sock;\n'+
+ ' }\n'+
+ '}')
+ exec_ssh_command_by_sudo_for_create(ssh,"touch /etc/nginx/orbit_sites/#{args.site_name}")
+ exec_ssh_command_by_sudo_for_create(ssh,"sh -c \"echo '#{nginx_setting_texts}' > /etc/nginx/orbit_sites/#{args.site_name}\"")
+ update_infos("restarting nginx")
+ exec_ssh_command_by_sudo_for_create(ssh,"sudo -p 'sudo password:' service nginx restart")
+ update_infos("finish restarting nginx")
+ exec_ssh_command_by_sudo_for_create(ssh,"mkdir -p #{args.path}")
+
+ update_infos("copying site's files for #{args.site_name}")
+ exec_ssh_command_for_create(ssh,"sudo -p 'sudo password:' apt-get install -y rsync")
+ if @site_construct.server_type == template_site.server_type
+ exec_ssh_command_for_create(ssh,"rsync -arv --delete --exclude={tmp/cache/,tmp/unicorn.sock,tmp/pids/*} #{template_site.path}/#{template_site.site_name}/ #{args.path}/#{args.site_name}/",true)
+ else
+ server = SiteServer.where(:server_name => template_site.server_type).first
+ exec_ssh_command_for_create(ssh,"sudo -p 'sudo password:' apt-get install -y sshpass")
+ outputs = exec_ssh_command_for_create(ssh,"sshpass -p \"#{server.password}\" rsync -arv --delete --exclude={tmp/cache/,tmp/unicorn.sock,tmp/pids/*} #{server.account}@#{server.ip}:#{template_site.path}/#{template_site.site_name}/ #{args.path}/#{args.site_name}/",true)
+ if outputs.join("\n").include?("Host key verification failed")
+ exec_ssh_command_by_sudo_for_create(session,"ssh-keygen -f \"$HOME/.ssh/known_hosts\" -R #{server.ip}")
+ exec_ssh_command_by_sudo_for_create(session,"ssh-keyscan -H #{server.ip} >> ~/.ssh/known_hosts")
+ exec_ssh_command_for_create(ssh,"sshpass -p \"#{server.password}\" rsync -arv --delete --exclude={tmp/cache/,tmp/unicorn.sock,tmp/pids/*} #{server.account}@#{server.ip}:#{template_site.path}/#{template_site.site_name}/ #{args.path}/#{args.site_name}/",true)
+ end
+ end
+ update_infos("Finish copying site's files for #{args.site_name}!")
+
+ exec_ssh_command_by_sudo_for_create(ssh,"sudo -p 'sudo password:' chown #{args.user}:#{args.user} #{args.path}/#{args.site_name} -R")
+ exec_ssh_command_by_sudo_for_create(ssh,"sudo -p 'sudo password:' chmod 777 #{args.path}/#{args.site_name} -R")
+ db_setting_text = ssh.exec!("cat #{args.path}/#{args.site_name}/config/mongoid.yml")
+ update_infos("setting dbname to #{args.db_name}")
+ exec_ssh_command_by_sudo_for_create(ssh,"sh -c \"echo '#{db_setting_text.gsub(template_site.db_name,args.db_name)}' > #{args.path}/#{args.site_name}/config/mongoid.yml\"",true)
+
+ update_infos("copying db from #{template_site.db_name} to #{args.db_name}")
+ if @site_construct.server_type == template_site.server_type
+ exec_ssh_command_by_sudo_for_create(ssh,"mongodump -d #{template_site.db_name} -o #{args.path}/#{args.site_name}/dump_xxxx")
+ exec_ssh_command_by_sudo_for_create(ssh,"mongorestore --drop -d #{args.db_name} #{args.path}/#{args.site_name}/dump_xxxx/#{template_site.db_name}")
+ exec_ssh_command_by_sudo_for_create(ssh,"rm -rf #{args.path}/#{args.site_name}/dump_xxxx")
+ else
+ exec_ssh_command_by_sudo_for_create(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'")
+ exec_ssh_command_for_create(ssh,"sshpass -p \"#{server.password}\" rsync -arv --delete #{server.account}@#{server.ip}:#{template_site.path}/#{template_site.site_name}/dump_xxxx/ #{args.path}/#{args.site_name}/dump_xxxx/")
+ exec_ssh_command_by_sudo_for_create(ssh,"mongorestore --drop -d #{args.db_name} #{args.path}/#{args.site_name}/dump_xxxx/#{template_site.db_name}")
+ exec_ssh_command_by_sudo_for_create(ssh,"rm -rf #{args.path}/#{args.site_name}/dump_xxxx")
+ exec_ssh_command_by_sudo_for_create(ssh,"sshpass -p '#{server.password}' ssh #{server.account}@#{server.ip} 'rm -rf #{template_site.path}/#{template_site.site_name}/dump_xxxx'")
+ end
+ update_infos("Finish copying database!")
+
+ update_infos("execing bundle install...")
+ exec_ssh_command_by_sudo_for_create(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name}\nbundle install'",true)
+ exec_ssh_command_by_sudo_for_create(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name}\nbundle install'")
+ update_infos("finish execing bundle install")
+ update_infos("starting #{args.site_name} web server to development")
+ outputs = exec_ssh_command_by_sudo_for_create(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name}\nkill -s TERM `fuser tmp/unicorn.sock`\nsudo -p \"sudo password:\" kill -s TERM `sudo -p \"sudo password:\" fuser tmp/unicorn.sock`\nsudo -p \"sudo password:\" rm -f tmp/pids/unicorn.pid\nbundle exec unicorn_rails -c config/unicorn.rb -D -E development\n'")
+ if outputs.include? "not writable"
+ exec_ssh_command_by_sudo_for_create(ssh,"sudo -p 'sudo password:' chown #{args.user}:#{args.user} #{args.path}/#{args.site_name} -R")
+ exec_ssh_command_by_sudo_for_create(ssh,"sudo -p 'sudo password:' chmod 777 #{args.path}/#{args.site_name} -R")
+ end
+ update_infos("finish creating #{args.site_name}")
+ exec_ssh_command_by_sudo_for_create(ssh,"chmod 777 #{args.path}/#{args.site_name} -R")
+ @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
+ return output
+ end
+ def update_thread_infos_for_exec(info,update_last=false)
+ if update_last
+ @thread.status["infos"][-1] += info
+ else
+ @thread.status["infos"] = @thread.status["infos"].push(info)
+ end
+ @thread.save!
+ return @thread.status["infos"]
+ end
+ def exec_ssh_command_for_create(session,command,update=false)
+ outputs = []
+ session.open_channel do |channel|
+ channel.request_pty do |channel, success|
+ channel.exec(command) do |ch, success|
+ abort "could not execute command: #{command}" unless success
+ channel.on_data do |ch, data|
+ outputs.push(data)
+ print "#{data}"
+ if update
+ if data.include? "\n"
+ update_infos_for_exec(data)
+ else
+ update_infos_for_exec(data,true)
+ end
+ end
+ if data.to_s.include?("sudo password:") || data.to_s.include?("Password:")
+ channel.send_data "#{@password}\n"
+ end
+ end
+ end
+ end
+ end
+ session.loop
+ return outputs
+ end
+ def exec_ssh_command_by_sudo_for_create(session,command,update=false)
+ outputs = exec_ssh_command_for_create(session,command,update)
+ if outputs.join("\n").include?("Permission denied") || outputs.join("\n").include?("Operation not permitted")
+ outputs = exec_ssh_command_for_create(session,"sudo -p 'sudo password:' #{command}",update)
+ end
+ return outputs.join("\n")
+ end
+ def update_infos_for_exec(info,update_last=false)
+ if update_last && !@site_construct.infos.empty?
+ @site_construct.infos[-1] += info
+ else
+ @site_construct.infos = @site_construct.infos.push(info)
+ 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
\ No newline at end of file
diff --git a/lib/tasks/create_site.rake b/lib/tasks/create_site.rake
index 23c4dda..0c676b5 100644
--- a/lib/tasks/create_site.rake
+++ b/lib/tasks/create_site.rake
@@ -4,7 +4,6 @@ namespace :create_site do
desc "Create Site Script"
task :create_site,[:git_template_url,:git_extension_url,:git_url,:ip,:user,:password,:site_name,:domain_name,:port,:db_name,:path,:site_construct_id] => :environment do |task,args|
@password = args.password
- puts args
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)
@@ -56,11 +55,7 @@ namespace :create_site do
update_infos("restarting nginx")
exec_ssh_command_by_sudo_for_create(ssh,"service nginx restart")
update_infos("finish restarting nginx")
- dir = Pathname.new(args.path)
- while dir.to_s != '/' do
- exec_ssh_command_by_sudo_for_create(ssh,"mkdir #{dir}")
- dir = dir.dirname
- end
+ exec_ssh_command_by_sudo_for_create(ssh,"mkdir -p #{args.path}")
update_infos("cloning orbit4-5 from #{args.git_url} to #{args.path}/#{args.site_name}")
exec_ssh_command_by_sudo_for_create(ssh,"git clone #{args.git_url} #{args.path}/#{args.site_name}")
exec_ssh_command_by_sudo_for_create(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name} && git submodule add #{args.git_template_url} app/templates/default-theme'")