Merge branch 'master' into statistics
This commit is contained in:
2
Gemfile
2
Gemfile
@ -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'
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user