Merge branch 'master' into statistics

This commit is contained in:
Ralf Teusner
2016-01-25 11:22:58 +01:00
7 changed files with 89 additions and 33 deletions

View File

@ -7,7 +7,7 @@ gem 'carrierwave'
gem 'coffee-rails', '~> 4.0.0' gem 'coffee-rails', '~> 4.0.0'
gem 'concurrent-ruby', '~> 1.0.0' gem 'concurrent-ruby', '~> 1.0.0'
gem 'concurrent-ruby-ext', '~> 1.0.0', platform: :ruby gem 'concurrent-ruby-ext', '~> 1.0.0', platform: :ruby
gem 'docker-api','~> 1.21.1', require: 'docker' gem 'docker-api','~> 1.25.0', require: 'docker'
gem 'factory_girl_rails', '~> 4.0' gem 'factory_girl_rails', '~> 4.0'
gem 'forgery' gem 'forgery'
gem 'highline' gem 'highline'

View File

@ -103,13 +103,13 @@ GEM
debug_inspector (0.0.2) debug_inspector (0.0.2)
diff-lcs (1.2.5) diff-lcs (1.2.5)
docile (1.1.5) docile (1.1.5)
docker-api (1.21.1) docker-api (1.25.0)
excon (>= 0.38.0) excon (>= 0.38.0)
json json
erubis (2.7.0) erubis (2.7.0)
eventmachine (1.0.8) eventmachine (1.0.8)
eventmachine (1.0.8-java) eventmachine (1.0.8-java)
excon (0.45.2) excon (0.45.4)
execjs (2.5.2) execjs (2.5.2)
factory_girl (4.5.0) factory_girl (4.5.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
@ -350,7 +350,7 @@ DEPENDENCIES
concurrent-ruby (~> 1.0.0) concurrent-ruby (~> 1.0.0)
concurrent-ruby-ext (~> 1.0.0) concurrent-ruby-ext (~> 1.0.0)
database_cleaner database_cleaner
docker-api (~> 1.21.1) docker-api (~> 1.25.0)
factory_girl_rails (~> 4.0) factory_girl_rails (~> 4.0)
faye-websocket faye-websocket
forgery forgery

View File

@ -423,9 +423,6 @@ $(function() {
var file_id = $(element).data('id'); var file_id = $(element).data('id');
//setAnnotations(editor, file_id); //setAnnotations(editor, file_id);
session.on('annotationRemoval', handleAnnotationRemoval);
session.on('annotationChange', handleAnnotationChange);
/* /*
* Register event handlers * Register event handlers
*/ */

View File

@ -13,6 +13,18 @@ class RequestForComment < ActiveRecord::Base
self.requested_at = Time.now self.requested_at = Time.now
end end
def submission
Submission.find(file.context_id)
end
def last_submission
Submission.find_by_sql(" select * from submissions
where exercise_id = #{exercise_id} AND
user_id = #{user_id}
order by created_at desc
limit 1").first
end
private private
def self.row_number_user_sql def self.row_number_user_sql
select("id, user_id, exercise_id, file_id, requested_at, created_at, updated_at, user_type, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql select("id, user_id, exercise_id, file_id, requested_at, created_at, updated_at, user_type, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql

View File

@ -1,20 +1,7 @@
<div class="list-group"> <div class="list-group">
<h4 class="list-group-item-heading"><%= Exercise.find(@request_for_comment.exercise_id) %></h4> <h4 class="list-group-item-heading"><%= Exercise.find(@request_for_comment.exercise_id) %></h4>
<p class="list-group-item-text"> <p class="list-group-item-text">
<% <%= @request_for_comment.user %> | <%= @request_for_comment.requested_at %> | <%= @request_for_comment.submission.id %>
user = @request_for_comment.user
submission_id = self.class.connection.execute("select id from submissions
where exercise_id =
#{@request_for_comment.exercise_id} AND
user_id = #{@request_for_comment.user_id} AND
#{@request_for_comment.user_id} > created_at
order by created_at desc
limit 1").first['id'].to_i
submission = Submission.find(submission_id)
%>
<%= user %> | <%= @request_for_comment.requested_at %>
</p> </p>
</div> </div>

View File

@ -2,7 +2,7 @@ require 'concurrent'
require 'pathname' require 'pathname'
class DockerClient class DockerClient
CONTAINER_WORKSPACE_PATH = '/workspace' CONTAINER_WORKSPACE_PATH = '/workspace' #'/home/python/workspace' #'/tmp/workspace'
DEFAULT_MEMORY_LIMIT = 256 DEFAULT_MEMORY_LIMIT = 256
# Ralf: I suggest to replace this with the environment variable. Ask Hauke why this is not the case! # Ralf: I suggest to replace this with the environment variable. Ask Hauke why this is not the case!
LOCAL_WORKSPACE_ROOT = Rails.root.join('tmp', 'files', Rails.env) LOCAL_WORKSPACE_ROOT = Rails.root.join('tmp', 'files', Rails.env)
@ -21,11 +21,14 @@ class DockerClient
end end
def self.clean_container_workspace(container) def self.clean_container_workspace(container)
container.exec(['bash', '-c', 'rm -rf ' + CONTAINER_WORKSPACE_PATH + '/*'])
=begin
local_workspace_path = local_workspace_path(container) local_workspace_path = local_workspace_path(container)
if local_workspace_path && Pathname.new(local_workspace_path).exist? if local_workspace_path && Pathname.new(local_workspace_path).exist?
Pathname.new(local_workspace_path).children.each{ |p| p.rmtree} Pathname.new(local_workspace_path).children.each{ |p| p.rmtree}
#FileUtils.rmdir(Pathname.new(local_workspace_path)) #FileUtils.rmdir(Pathname.new(local_workspace_path))
end end
=end
end end
def command_substitutions(filename) def command_substitutions(filename)
@ -42,6 +45,8 @@ class DockerClient
'Image' => find_image_by_tag(execution_environment.docker_image).info['RepoTags'].first, 'Image' => find_image_by_tag(execution_environment.docker_image).info['RepoTags'].first,
'Memory' => execution_environment.memory_limit.megabytes, 'Memory' => execution_environment.memory_limit.megabytes,
'NetworkDisabled' => !execution_environment.network_enabled?, 'NetworkDisabled' => !execution_environment.network_enabled?,
#'HostConfig' => { 'CpusetCpus' => '0', 'CpuQuota' => 10000 },
#DockerClient.config['allowed_cpus']
'OpenStdin' => true, 'OpenStdin' => true,
'StdinOnce' => true, 'StdinOnce' => true,
# required to expose standard streams over websocket # required to expose standard streams over websocket
@ -88,12 +93,12 @@ class DockerClient
def self.create_container(execution_environment) def self.create_container(execution_environment)
tries ||= 0 tries ||= 0
Rails.logger.info "docker_client: self.create_container with creation options:" #Rails.logger.info "docker_client: self.create_container with creation options:"
Rails.logger.info(container_creation_options(execution_environment)) #Rails.logger.info(container_creation_options(execution_environment))
container = Docker::Container.create(container_creation_options(execution_environment)) container = Docker::Container.create(container_creation_options(execution_environment))
local_workspace_path = generate_local_workspace_path local_workspace_path = generate_local_workspace_path
# container.start always creates the passed local_workspace_path on disk. Seems like we have to live with that, therefore we can also just create the empty folder ourselves. # container.start always creates the passed local_workspace_path on disk. Seems like we have to live with that, therefore we can also just create the empty folder ourselves.
FileUtils.mkdir(local_workspace_path) # FileUtils.mkdir(local_workspace_path)
container.start(container_start_options(execution_environment, local_workspace_path)) container.start(container_start_options(execution_environment, local_workspace_path))
container.start_time = Time.now container.start_time = Time.now
container.status = :created container.status = :created
@ -128,6 +133,54 @@ class DockerClient
end end
private :create_workspace_file private :create_workspace_file
def create_workspace_files_transmit(container, submission)
begin
# create a temporary dir, put all files in it, and put it into the container. the dir is automatically removed when leaving the block.
Dir.mktmpdir {|dir|
submission.collect_files.each do |file|
disk_file = File.new(dir + '/' + (file.path || '') + file.name_with_extension, 'w')
disk_file.write(file.content)
disk_file.close
end
begin
# create target folder, TODO re-active this when we remove shared folder bindings
#container.exec(['bash', '-c', 'mkdir ' + CONTAINER_WORKSPACE_PATH])
#container.exec(['bash', '-c', 'chown -R python ' + CONTAINER_WORKSPACE_PATH])
#container.exec(['bash', '-c', 'chgrp -G python ' + CONTAINER_WORKSPACE_PATH])
rescue StandardError => error
Rails.logger.error('create workspace folder: Rescued from StandardError: ' + error.to_s)
end
#sleep 1000
begin
# tar the files in dir and put the tar to CONTAINER_WORKSPACE_PATH in the container
container.archive_in(dir, CONTAINER_WORKSPACE_PATH, overwrite: false)
rescue StandardError => error
Rails.logger.error('insert tar: Rescued from StandardError: ' + error.to_s)
end
#Rails.logger.info('command: tar -xf ' + CONTAINER_WORKSPACE_PATH + '/' + dir.split('/tmp/')[1] + ' -C ' + CONTAINER_WORKSPACE_PATH)
begin
# untar the tar file placed in the CONTAINER_WORKSPACE_PATH
container.exec(['bash', '-c', 'tar -xf ' + CONTAINER_WORKSPACE_PATH + '/' + dir.split('/tmp/')[1] + ' -C ' + CONTAINER_WORKSPACE_PATH])
rescue StandardError => error
Rails.logger.error('untar: Rescued from StandardError: ' + error.to_s)
end
#sleep 1000
}
rescue StandardError => error
Rails.logger.error('create_workspace_files_transmit: Rescued from StandardError: ' + error.to_s)
end
end
def self.destroy_container(container) def self.destroy_container(container)
Rails.logger.info('destroying container ' + container.to_s) Rails.logger.info('destroying container ' + container.to_s)
container.stop.kill container.stop.kill
@ -191,8 +244,8 @@ class DockerClient
We need to start a second thread to kill the websocket connection, We need to start a second thread to kill the websocket connection,
as it is impossible to determine whether further input is requested. as it is impossible to determine whether further input is requested.
""" """
#begin
@thread = Thread.new do @thread = Thread.new do
#begin
timeout = @execution_environment.permitted_execution_time.to_i # seconds timeout = @execution_environment.permitted_execution_time.to_i # seconds
sleep(timeout) sleep(timeout)
if container.status != :returned if container.status != :returned
@ -203,12 +256,12 @@ class DockerClient
end end
kill_container(container) kill_container(container)
end end
end
#ensure #ensure
# guarantee that the thread is releasing the DB connection after it is done # guarantee that the thread is releasing the DB connection after it is done
# ActiveRecord::Base.connectionpool.releaseconnection # ActiveRecord::Base.connectionpool.releaseconnection
#end #end
end end
end
def exit_container(container) def exit_container(container)
Rails.logger.debug('exiting container ' + container.to_s) Rails.logger.debug('exiting container ' + container.to_s)
@ -242,7 +295,7 @@ class DockerClient
Run commands by attaching a websocket to Docker. Run commands by attaching a websocket to Docker.
""" """
command = submission.execution_environment.run_command % command_substitutions(filename) command = submission.execution_environment.run_command % command_substitutions(filename)
create_workspace_files = proc { create_workspace_files(container, submission) } create_workspace_files = proc { create_workspace_files_transmit(container, submission) }
execute_websocket_command(command, create_workspace_files, block) execute_websocket_command(command, create_workspace_files, block)
end end
@ -251,7 +304,7 @@ class DockerClient
Stick to existing Docker API with exec command. Stick to existing Docker API with exec command.
""" """
command = submission.execution_environment.test_command % command_substitutions(filename) command = submission.execution_environment.test_command % command_substitutions(filename)
create_workspace_files = proc { create_workspace_files(container, submission) } create_workspace_files = proc { create_workspace_files_transmit(container, submission) }
execute_command(command, create_workspace_files, block) execute_command(command, create_workspace_files, block)
end end

View File

@ -30,6 +30,12 @@ EOF
service docker restart service docker restart
fi fi
# run docker without sudo
sudo groupadd docker
sudo gpasswd -a ${USER} docker
newgrp docker
sudo service docker restart
docker pull openhpi/docker_java docker pull openhpi/docker_java
docker pull openhpi/docker_ruby docker pull openhpi/docker_ruby
docker pull openhpi/docker_python docker pull openhpi/docker_python
@ -109,5 +115,6 @@ server {
EOF EOF
rm -f /etc/nginx/sites-enabled/default rm -f /etc/nginx/sites-enabled/default
ln -s /etc/nginx/sites-available/code_ocean /etc/nginx/sites-enabled ln -s /etc/nginx/sites-available/code_ocean /etc/nginx/sites-enabled
service nginx restart #service nginx restart
#cd /vagrant/ && rails s
fi fi