Permalink
Browse files

ruby timeout is broken; not sure if this is works, but:

- in setup server worker, only use simple variables inside timeout
- add timeout to minecraft querier, only use simple variables inside timeout
  • Loading branch information...
Raekye committed Feb 3, 2015
1 parent 17a6145 commit e72c7d8a687d497d3e68bdf7617bd8a533314e10
Showing with 125 additions and 114 deletions.
  1. +24 −18 app/models/minecraft/querier.rb
  2. +93 −90 app/workers/setup_server_worker.rb
  3. +2 −2 test/integration/minecraft_flows_test.rb
  4. +6 −4 tests.sh
@@ -10,30 +10,36 @@ def initialize(ip_address, port = 25565)
@port = port
end

def handshake
@connection.send(self.create_packet(PACKET_TYPE_CHALLENGE), 0)
data = @connection.recvfrom(256)[0]
@challenge = data[5...-1].to_i
def handshake(connection)
connection.send(self.create_packet(PACKET_TYPE_CHALLENGE), 0)
data = connection.recvfrom(256)[0]
challenge = data[5...-1].to_i
return challenge
end

def read_all(tries = 4)
@connection = UDPSocket.new
@connection.connect(@ip_address, @port)
begin
for i in 0...tries do
begin
@challenge = 0
self.handshake
@connection.send(self.create_packet(PACKET_TYPE_QUERY) + [@challenge].pack('N'), 0) # 32 bit unsigned big endian
data = @connection.recvfrom(4096)[0][5...-1].split("\x00")
return data
rescue
data = nil
i = 0
while data.nil? && i < tries
if i != 0
sleep 2
end
connection = UDPSocket.new
begin
Timeout::timeout(2) do
connection.connect(@ip_address, @port)
challenge = self.handshake(connection)
connection.send(self.create_packet(PACKET_TYPE_QUERY) + [challenge].pack('N'), 0) # 32 bit unsigned big endian
data = connection.recvfrom(4096)[0][5...-1].split("\x00")
end
rescue => e
Rails.logger.info "Exception in #{self.class}#read_all, try #{i}: #{e}"
ensure
connection.close
end
ensure
@connection.close()
i += 1
end
return nil
return data
end

def create_packet(id)
@@ -62,6 +62,7 @@ def perform(user_id, server_id, times = 0)
else
server.update_columns(remote_setup_stage: 1)
self.base_install(user, server, host)
server.update_columns(remote_setup_stage: 2)
self.add_ssh_keys(user, server, host)
server.update_columns(remote_setup_stage: 3)
self.install_minecraft(user, server, host)
@@ -82,35 +83,33 @@ def perform(user_id, server_id, times = 0)
end

def base_install(user, server, host)
mcuser_password_escaped = shell_escape("#{user.email}+#{server.minecraft.name}")
begin
Timeout::timeout(512) do
ActiveRecord::Base.connection_pool.with_connection do |conn|
on host do
within '/tmp/' do
if test '! id -u mcuser'
execute :adduser, '-m', 'mcuser'
end
execute :echo, "'#{server.minecraft.user.email.gsub('\'', '\'"\'"\'')}+#{server.minecraft.name}'", '|', :passwd, '--stdin', 'mcuser'
execute :usermod, '-aG', 'wheel', 'mcuser'
if test '[ ! -f "/swapfile" ]'
execute :fallocate, '-l', '1G', '/swapfile'
execute :chmod, '600', '/swapfile'
execute :mkswap, '/swapfile'
execute :swapon, '/swapfile'
execute :echo, '/swapfile none swap defaults 0 0', '>>', '/etc/fstab'
end
server.update_columns(remote_setup_stage: 2)
execute :yum, '-y', 'install', *SYSTEM_PACKAGES
execute :yum, '-y', 'update', '--security'
execute 'firewall-cmd', '--add-port=5000/tcp'
execute 'firewall-cmd', '--permanent', '--add-port=5000/tcp'
execute 'firewall-cmd', '--add-port=25565/tcp'
execute 'firewall-cmd', '--permanent', '--add-port=25565/tcp'
execute 'firewall-cmd', '--add-port=25565/udp'
execute 'firewall-cmd', '--permanent', '--add-port=25565/udp'
execute :rm, '-rf', '/tmp/pip_build_root'
execute 'python3-pip', 'install', 'flask'
on host do
within '/tmp/' do
if test '! id -u mcuser'
execute :adduser, '-m', 'mcuser'
end
execute :echo, mcuser_password_escaped, '|', :passwd, '--stdin', 'mcuser'
execute :usermod, '-aG', 'wheel', 'mcuser'
if test '[ ! -f "/swapfile" ]'
execute :fallocate, '-l', '1G', '/swapfile'
execute :chmod, '600', '/swapfile'
execute :mkswap, '/swapfile'
execute :swapon, '/swapfile'
execute :echo, '/swapfile none swap defaults 0 0', '>>', '/etc/fstab'
end
execute :yum, '-y', 'install', *SYSTEM_PACKAGES
execute :yum, '-y', 'update', '--security'
execute 'firewall-cmd', '--add-port=5000/tcp'
execute 'firewall-cmd', '--permanent', '--add-port=5000/tcp'
execute 'firewall-cmd', '--add-port=25565/tcp'
execute 'firewall-cmd', '--permanent', '--add-port=25565/tcp'
execute 'firewall-cmd', '--add-port=25565/udp'
execute 'firewall-cmd', '--permanent', '--add-port=25565/udp'
execute :rm, '-rf', '/tmp/pip_build_root'
execute 'python3-pip', 'install', 'flask'
end
end
end
@@ -122,15 +121,13 @@ def base_install(user, server, host)
def base_update(user, server, host)
begin
Timeout::timeout(16) do
ActiveRecord::Base.connection_pool.with_connection do |conn|
on host do
within '/opt/gamocosm/' do
execute :su, 'mcuser', '-c', '"git checkout master"'
execute :su, 'mcuser', '-c', '"git pull origin master"'
execute :cp, '/opt/gamocosm/mcsw.service', '/etc/systemd/system/mcsw.service'
execute :systemctl, 'daemon-reload'
execute :systemctl, 'restart', 'mcsw'
end
on host do
within '/opt/gamocosm/' do
execute :su, 'mcuser', '-c', '"git checkout master"'
execute :su, 'mcuser', '-c', '"git pull origin master"'
execute :cp, '/opt/gamocosm/mcsw.service', '/etc/systemd/system/mcsw.service'
execute :systemctl, 'daemon-reload'
execute :systemctl, 'restart', 'mcsw'
end
end
end
@@ -149,24 +146,23 @@ def install_minecraft(user, server, host)
end
fv = server.minecraft.flavour.split('/')
minecraft_script = "/tmp/gamocosm-minecraft-flavours/#{fv[0]}.sh"
mc_flv_git_url = Gamocosm.minecraft_flavours_git_url
# estimated minutes * 60 secs/minute * 2 (buffer)
Timeout::timeout(fi[:time] * 60 * 2) do
ActiveRecord::Base.connection_pool.with_connection do |conn|
on host do
within '/tmp/' do
execute :rm, '-rf', 'gamocosm-minecraft-flavours'
execute :git, 'clone', Gamocosm.minecraft_flavours_git_url, 'gamocosm-minecraft-flavours'
end
within '/home/mcuser/' do
execute :mkdir, '-p', 'minecraft'
within :minecraft do
execute :chmod, 'u+x', minecraft_script
with minecraft_flavour_version: fv[1] do
execute :bash, '-c', minecraft_script
end
on host do
within '/tmp/' do
execute :rm, '-rf', 'gamocosm-minecraft-flavours'
execute :git, 'clone', mc_flv_git_url, 'gamocosm-minecraft-flavours'
end
within '/home/mcuser/' do
execute :mkdir, '-p', 'minecraft'
within :minecraft do
execute :chmod, 'u+x', minecraft_script
with minecraft_flavour_version: fv[1] do
execute :bash, '-c', minecraft_script
end
execute :chown, '-R', 'mcuser:mcuser', 'minecraft'
end
execute :chown, '-R', 'mcuser:mcuser', 'minecraft'
end
end
end
@@ -176,24 +172,25 @@ def install_minecraft(user, server, host)
end

def install_mcsw(user, server, host)
mcsw_git_url = Gamocosm.minecraft_server_wrapper_git_url
mcsw_username = Gamocosm.minecraft_wrapper_username
mcsw_password = server.minecraft.minecraft_wrapper_password
begin
Timeout::timeout(16) do
ActiveRecord::Base.connection_pool.with_connection do |conn|
on host do
within '/opt/' do
execute :rm, '-rf', 'gamocosm'
execute :git, 'clone', Gamocosm.minecraft_server_wrapper_git_url, 'gamocosm'
within :gamocosm do
execute :echo, "'#{Gamocosm.minecraft_wrapper_username}'", '>', 'mcsw-auth.txt'
execute :echo, "'#{server.minecraft.minecraft_wrapper_password}'", '>>', 'mcsw-auth.txt'
end
execute :chown, '-R', 'mcuser:mcuser', 'gamocosm'
end
within '/etc/systemd/system/' do
execute :cp, '/opt/gamocosm/mcsw.service', 'mcsw.service'
execute :systemctl, 'enable', 'mcsw'
execute :systemctl, 'start', 'mcsw'
on host do
within '/opt/' do
execute :rm, '-rf', 'gamocosm'
execute :git, 'clone', mcsw_git_url, 'gamocosm'
within :gamocosm do
execute :echo, mcsw_username, '>', 'mcsw-auth.txt'
execute :echo, mcsw_password, '>>', 'mcsw-auth.txt'
end
execute :chown, '-R', 'mcuser:mcuser', 'gamocosm'
end
within '/etc/systemd/system/' do
execute :cp, '/opt/gamocosm/mcsw.service', 'mcsw.service'
execute :systemctl, 'enable', 'mcsw'
execute :systemctl, 'start', 'mcsw'
end
end
end
@@ -203,18 +200,18 @@ def install_mcsw(user, server, host)
end

def modify_ssh_port(user, server, host)
ssh_port = server.ssh_port
if ssh_port == 22
return
end
begin
Timeout::timeout(8) do
ActiveRecord::Base.connection_pool.with_connection do |conn|
on host do
within '/tmp/' do
if server.ssh_port != 22
execute 'firewall-cmd', "--add-port=#{server.ssh_port}/tcp"
execute 'firewall-cmd', '--permanent', "--add-port=#{server.ssh_port}/tcp"
execute :sed, '-i', "'s/^#Port 22$/Port #{server.ssh_port}/'", '/etc/ssh/sshd_config'
execute :systemctl, 'restart', 'sshd'
end
end
on host do
within '/tmp/' do
execute 'firewall-cmd', "--add-port=#{ssh_port}/tcp"
execute 'firewall-cmd', '--permanent', "--add-port=#{ssh_port}/tcp"
execute :sed, '-i', "'s/^#Port 22$/Port #{ssh_port}/'", '/etc/ssh/sshd_config'
execute :systemctl, 'restart', 'sshd'
end
end
end
@@ -227,30 +224,36 @@ def add_ssh_keys(user, server, host)
if server.ssh_keys.nil?
return
end
key_contents = []
server.ssh_keys.split(',').each do |key_id|
key = user.digital_ocean_ssh_public_key(key_id)
if key.error?
server.minecraft.log(key)
else
key_contents.push(shell_escape(key))
end
end
server.update_columns(ssh_keys: nil)
begin
Timeout::timeout(32) do
ActiveRecord::Base.connection_pool.with_connection do |conn|
on host do
within '/tmp/' do
execute :mkdir, '-p', '/home/mcuser/.ssh/'
server.ssh_keys.split(',').each do |key_id|
key = user.digital_ocean_ssh_public_key(key_id)
if key.error?
server.minecraft.log(key)
else
execute :echo, "'#{key.gsub('\'', '\'"\'"\'')}'", '>>', '/home/mcuser/.ssh/authorized_keys'
end
end
execute :chown, '-R', 'mcuser:mcuser', '/home/mcuser/.ssh/'
execute :chmod, '700', '/home/mcuser/.ssh/'
execute :chmod, '600', '/home/mcuser/.ssh/authorized_keys'
server.update_columns(ssh_keys: nil)
on host do
within '/tmp/' do
execute :mkdir, '-p', '/home/mcuser/.ssh/'
key_contents.each do |key_escaped|
execute :echo, key_escaped, '>>', '/home/mcuser/.ssh/authorized_keys'
end
execute :chown, '-R', 'mcuser:mcuser', '/home/mcuser/.ssh/'
execute :chmod, '700', '/home/mcuser/.ssh/'
execute :chmod, '600', '/home/mcuser/.ssh/authorized_keys'
end
end
end
rescue Timeout::Error
raise 'Server setup (SSH): took too long adding SSH keys from Digital Ocean'
end
end

def shell_escape(str)
return "'#{str.gsub('\'', '\'"\'"\'')}'"
end
end
@@ -198,8 +198,8 @@ def track_sidekiq_worker(worker, perform_in, max_times)

def wait_for_autoshutdown_server(minecraft)
if have_user_server?
sleep 64
track_sidekiq_worker('AutoshutdownMinecraftWorker', 0, 16)
sleep 32
track_sidekiq_worker('AutoshutdownMinecraftWorker', 1, 16)
# workers do Server.find, here uses minecraft.server
minecraft.reload
else
@@ -33,10 +33,12 @@ source env.sh
if use_docker; then
echo "Preparing Docker image and container..."
pushd test-docker
rm -f id_rsa
rm -f id_rsa.pub
cp "$DIGITAL_OCEAN_SSH_PRIVATE_KEY_PATH" id_rsa
cp "$DIGITAL_OCEAN_SSH_PUBLIC_KEY_PATH" id_rsa.pub
if [[ ! -f "id_rsa" ]]; then
cp "$DIGITAL_OCEAN_SSH_PRIVATE_KEY_PATH" id_rsa
fi
if [[ ! -f "id_rsa.pub" ]]; then
cp "$DIGITAL_OCEAN_SSH_PUBLIC_KEY_PATH" id_rsa.pub
fi
docker build -t gamocosm .
docker run -d -p 22:22 -p 4022:4022 -p 5000:5000 -p 25565:25565/udp --name gamocosm_container gamocosm
popd

0 comments on commit e72c7d8

Please sign in to comment.