Merge branch 'master' into statistics

This commit is contained in:
Ralf Teusner
2015-12-15 15:36:24 +01:00
10 changed files with 113 additions and 75 deletions

View File

@ -5,8 +5,8 @@ gem 'bcrypt', '~> 3.1.7'
gem 'bootstrap-will_paginate'
gem 'carrierwave'
gem 'coffee-rails', '~> 4.0.0'
gem 'concurrent-ruby'
gem 'concurrent-ruby-ext', platform: :ruby
gem 'concurrent-ruby', '~> 1.0.0'
gem 'concurrent-ruby-ext', '~> 1.0.0', platform: :ruby
gem 'docker-api','~> 1.21.1', require: 'docker'
gem 'factory_girl_rails', '~> 4.0'
gem 'forgery'
@ -19,9 +19,9 @@ gem 'kramdown'
gem 'newrelic_rpm'
gem 'pg', platform: :ruby
gem 'pry'
gem 'puma'
gem 'puma', '~> 2.15.3'
gem 'pundit'
gem 'rails', '~> 4.1.2'
gem 'rails', '~> 4.1.13'
gem 'rails-i18n', '~> 4.0.0'
gem 'ransack'
gem 'rubytree'

View File

@ -2,32 +2,32 @@ GEM
remote: https://rubygems.org/
specs:
ZenTest (4.11.0)
actionmailer (4.1.10)
actionpack (= 4.1.10)
actionview (= 4.1.10)
actionmailer (4.1.14)
actionpack (= 4.1.14)
actionview (= 4.1.14)
mail (~> 2.5, >= 2.5.4)
actionpack (4.1.10)
actionview (= 4.1.10)
activesupport (= 4.1.10)
actionpack (4.1.14)
actionview (= 4.1.14)
activesupport (= 4.1.14)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionview (4.1.10)
activesupport (= 4.1.10)
actionview (4.1.14)
activesupport (= 4.1.14)
builder (~> 3.1)
erubis (~> 2.7.0)
activemodel (4.1.10)
activesupport (= 4.1.10)
activemodel (4.1.14)
activesupport (= 4.1.14)
builder (~> 3.1)
activerecord (4.1.10)
activemodel (= 4.1.10)
activesupport (= 4.1.10)
activerecord (4.1.14)
activemodel (= 4.1.14)
activesupport (= 4.1.14)
arel (~> 5.0.0)
activerecord-jdbc-adapter (1.3.15)
activerecord (>= 2.2)
activerecord-jdbcpostgresql-adapter (1.3.15)
activerecord-jdbc-adapter (~> 1.3.15)
jdbc-postgres (>= 9.1)
activesupport (4.1.10)
activesupport (4.1.14)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
@ -95,11 +95,10 @@ GEM
execjs
coffee-script-source (1.9.1)
colorize (0.7.7)
concurrent-ruby (0.8.0)
ref (~> 1.0, >= 1.0.5)
concurrent-ruby (0.8.0-java)
concurrent-ruby-ext (0.8.0)
concurrent-ruby (~> 0.8.0)
concurrent-ruby (1.0.0)
concurrent-ruby (1.0.0-java)
concurrent-ruby-ext (1.0.0)
concurrent-ruby (~> 1.0.0)
database_cleaner (1.4.1)
debug_inspector (0.0.2)
diff-lcs (1.2.5)
@ -141,17 +140,17 @@ GEM
jquery-turbolinks (2.1.0)
railties (>= 3.1.0)
turbolinks
json (1.8.2)
json (1.8.2-java)
json (1.8.3)
json (1.8.3-java)
jwt (1.4.1)
kramdown (1.6.0)
mail (2.6.3)
mime-types (>= 1.16, < 3)
method_source (0.8.2)
mime-types (2.4.3)
mime-types (2.99)
mini_portile (0.6.2)
minitest (5.5.1)
multi_json (1.11.0)
minitest (5.8.3)
multi_json (1.11.2)
multi_xml (0.5.5)
multipart-post (2.0.0)
net-scp (1.2.1)
@ -185,31 +184,29 @@ GEM
method_source (~> 0.8.1)
slop (~> 3.4)
spoon (~> 0.0)
puma (2.11.1)
rack (>= 1.1, < 2.0)
puma (2.11.1-java)
rack (>= 1.1, < 2.0)
puma (2.15.3)
puma (2.15.3-java)
pundit (0.3.0)
activesupport (>= 3.0.0)
rack (1.5.2)
rack (1.5.5)
rack-test (0.6.3)
rack (>= 1.0)
rails (4.1.10)
actionmailer (= 4.1.10)
actionpack (= 4.1.10)
actionview (= 4.1.10)
activemodel (= 4.1.10)
activerecord (= 4.1.10)
activesupport (= 4.1.10)
rails (4.1.14)
actionmailer (= 4.1.14)
actionpack (= 4.1.14)
actionview (= 4.1.14)
activemodel (= 4.1.14)
activerecord (= 4.1.14)
activesupport (= 4.1.14)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.10)
railties (= 4.1.14)
sprockets-rails (~> 2.0)
rails-i18n (4.0.4)
i18n (~> 0.6)
railties (~> 4.0)
railties (4.1.10)
actionpack (= 4.1.10)
activesupport (= 4.1.10)
railties (4.1.14)
actionpack (= 4.1.14)
activesupport (= 4.1.14)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
@ -221,7 +218,6 @@ GEM
i18n
polyamorous (~> 1.2)
rdoc (4.2.0)
ref (1.0.5)
rspec (3.1.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
@ -286,12 +282,12 @@ GEM
spoon (0.0.4)
ffi
spring (1.3.4)
sprockets (2.12.3)
sprockets (2.12.4)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.2.4)
sprockets-rails (2.3.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
@ -351,8 +347,8 @@ DEPENDENCIES
carrierwave
codeclimate-test-reporter
coffee-rails (~> 4.0.0)
concurrent-ruby
concurrent-ruby-ext
concurrent-ruby (~> 1.0.0)
concurrent-ruby-ext (~> 1.0.0)
database_cleaner
docker-api (~> 1.21.1)
factory_girl_rails (~> 4.0)
@ -368,9 +364,9 @@ DEPENDENCIES
nyan-cat-formatter
pg
pry
puma
puma (~> 2.15.3)
pundit
rails (~> 4.1.2)
rails (~> 4.1.13)
rails-i18n (~> 4.0.0)
rake
ransack

View File

@ -100,12 +100,12 @@ $(function() {
}
};
var confirmSubmission = function(event) {
event.preventDefault();
if (confirm($(this).data('message-confirm'))) {
submitCode();
}
};
//var confirmSubmission = function(event) {
// event.preventDefault();
// if (confirm($(this).data('message-confirm'))) {
// submitCode();
// }
//};
var createSubmission = function(initiator, filter, callback) {
showSpinner(initiator);
@ -637,7 +637,8 @@ $(function() {
var initializeWorkflowButtons = function() {
$('#start').on('click', showWorkspaceTab);
$('#submit').on('click', confirmSubmission);
//$('#submit').on('click', confirmSubmission);
$('#submit').on('click', submitCode);
};
var initializeWorkspaceButtons = function() {

View File

@ -33,6 +33,7 @@ function Turtle(pipe, canvas) {
'x': xpos - dx,
'y': ypos - dy
}));
pipe.send('\n');
});
}

View File

@ -1,9 +1,6 @@
- unless local_assigns[:modal]
h1 = t('shared.help.headline')
h2 = t('shared.help.general_help')
== Forgery(:lorem_ipsum).paragraphs(10, html: true)
- if local_assigns.has_key?(:execution_environment)
h2 = t('shared.help.execution_environment_specific_help', execution_environment: execution_environment)
= render_markdown(execution_environment.help)

View File

@ -76,8 +76,7 @@
br
- if session[:lti_parameters].try(:has_key?, 'lis_outcome_service_url')
p.text-center = render('editor_button', classes: 'btn-lg btn-success', data: {:'data-message-confirm' => t('exercises.editor.confirm_submit'), :'data-url' => submit_exercise_path(@exercise)}, icon: 'fa fa-send', id: 'submit', label: t('exercises.editor.submit'))
p.text-center = render('editor_button', classes: 'btn-lg btn-success', data: {:'data-url' => submit_exercise_path(@exercise)}, icon: 'fa fa-send', id: 'submit', label: t('exercises.editor.submit'))
- if qa_url
#questions-column
#questions-holder data-url="#{qa_url}/qa/index/#{@exercise.id}/#{@user_id}"

View File

@ -33,6 +33,8 @@ module CodeOcean
case (RUBY_ENGINE)
when 'ruby'
# ...
#this is enabled in prod for testing
config.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement
when 'jruby'
# plattform specific
java.lang.Class.for_name('javax.crypto.JceSecurity').get_declared_field('isRestricted').tap{|f| f.accessible = true; f.set nil, false}

View File

@ -18,8 +18,8 @@ production:
active: true
refill:
async: false
batch_size: 32
interval: 30
batch_size: 8
interval: 15
timeout: 60
workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %>
ws_host: ws://localhost:4243

View File

@ -88,6 +88,8 @@ class DockerClient
def self.create_container(execution_environment)
tries ||= 0
Rails.logger.info "docker_client: self.create_container with creation options:"
Rails.logger.info(container_creation_options(execution_environment))
container = Docker::Container.create(container_creation_options(execution_environment))
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.
@ -97,7 +99,7 @@ class DockerClient
container.status = :created
container
rescue Docker::Error::NotFoundError => error
Rails.logger.info('create_container: Got Docker::Error::NotFoundError: ' + error)
Rails.logger.info('create_container: Got Docker::Error::NotFoundError: ' + error.to_s)
destroy_container(container)
#(tries += 1) <= RETRY_COUNT ? retry : raise(error)
end
@ -113,6 +115,8 @@ class DockerClient
create_workspace_file(container: container, file: file)
end
end
rescue Docker::Error::NotFoundError => error
Rails.logger.info('create_workspace_files: Rescued from Docker::Error::NotFoundError: ' + error.to_s)
end
private :create_workspace_files
@ -131,6 +135,9 @@ class DockerClient
if(container)
container.delete(force: true, v: true)
end
rescue Docker::Error::NotFoundError => error
Rails.logger.error('destroy_container: Rescued from Docker::Error::NotFoundError: ' + error.to_s)
Rails.logger.error('No further actions are done concerning that.')
end
def execute_arbitrary_command(command, &block)
@ -297,7 +304,12 @@ class DockerClient
def self.return_container(container, execution_environment)
Rails.logger.debug('returning container ' + container.to_s)
clean_container_workspace(container)
begin
clean_container_workspace(container)
rescue Docker::Error::NotFoundError => error
Rails.logger.info('return_container: Rescued from Docker::Error::NotFoundError: ' + error.to_s)
Rails.logger.info('Nothing is done here additionally. The container will be exchanged upon its next retrieval.')
end
DockerContainerPool.return_container(container, execution_environment)
container.status = :returned
end

View File

@ -1,6 +1,6 @@
require 'concurrent/future'
require 'concurrent/timer_task'
require 'concurrent/utilities'
class DockerContainerPool
@ -18,10 +18,19 @@ class DockerContainerPool
@config ||= CodeOcean::Config.new(:docker).read(erb: true)[:pool]
end
def self.containers
@containers
end
def self.all_containers
@all_containers
end
def self.remove_from_all_containers(container, execution_environment)
@all_containers[execution_environment.id]-=[container]
if(@containers[execution_environment.id].include?(container))
@containers[execution_environment.id]-=[container]
Rails.logger.debug('Removed container ' + container.to_s + ' from all_pool for execution environment ' + execution_environment.to_s + '. Remaining containers in all_pool ' + @all_containers[execution_environment.id].size.to_s)
end
end
@ -29,6 +38,7 @@ class DockerContainerPool
@all_containers[execution_environment.id]+=[container]
if(!@containers[execution_environment.id].include?(container))
@containers[execution_environment.id]+=[container]
Rails.logger.debug('Added container ' + container.to_s + ' to all_pool for execution environment ' + execution_environment.to_s + '. Containers in all_pool: ' + @all_containers[execution_environment.id].size.to_s)
else
Rails.logger.info('failed trying to add existing container ' + container.to_s + ' to execution_environment ' + execution_environment.to_s)
end
@ -57,9 +67,28 @@ class DockerContainerPool
Rails.logger.debug('get_container fetched container ' + container.to_s + ' for execution environment ' + execution_environment.to_s)
# just access and the following if we got a container. Otherwise, the execution_environment might be just created and not fully exist yet.
if(container)
Rails.logger.debug('get_container remaining avail. containers: ' + @containers[execution_environment.id].size.to_s)
Rails.logger.debug('get_container all container count: ' + @all_containers[execution_environment.id].size.to_s)
begin
# check whether the container is running. exited containers go to the else part.
# Dead containers raise a NotFOundError on the container.json call. This is handled in the rescue block.
if(container.json['State']['Running'])
Rails.logger.debug('get_container remaining avail. containers: ' + @containers[execution_environment.id].size.to_s)
Rails.logger.debug('get_container all container count: ' + @all_containers[execution_environment.id].size.to_s)
else
Rails.logger.error('docker_container_pool.get_container retrieved a container not running. Container will be removed from list: ' + container.to_s)
remove_from_all_containers(container, execution_environment)
Rails.logger.error('Creating a new container and returning that.')
container = create_container(execution_environment)
DockerContainerPool.add_to_all_containers(container, execution_environment)
end
rescue Docker::Error::NotFoundError => error
Rails.logger.error('docker_container_pool.get_container rescued from Docker::Error::NotFoundError. Most likely, the container is not there any longer. Removing faulty entry from list: ' + container.to_s)
remove_from_all_containers(container, execution_environment)
Rails.logger.error('Creating a new container and returning that.')
container = create_container(execution_environment)
DockerContainerPool.add_to_all_containers(container, execution_environment)
end
end
# returning nil is no problem. then the pool is just depleted.
container
else
create_container(execution_environment)
@ -71,7 +100,7 @@ class DockerContainerPool
end
def self.refill
ExecutionEnvironment.where('pool_size > 0').each do |execution_environment|
ExecutionEnvironment.where('pool_size > 0').order(pool_size: :desc).each do |execution_environment|
if config[:refill][:async]
Concurrent::Future.execute { refill_for_execution_environment(execution_environment) }
else
@ -85,18 +114,19 @@ class DockerContainerPool
if refill_count > 0
Rails.logger.info('Adding ' + refill_count.to_s + ' containers for execution_environment ' + execution_environment.name )
c = refill_count.times.map { create_container(execution_environment) }
Rails.logger.debug('Created containers: ' + c.to_s )
Rails.logger.info('Created containers: ' + c.to_s )
#c.each { |container| return_container(container, execution_environment) }
@containers[execution_environment.id] += c
@all_containers[execution_environment.id] += c
Rails.logger.debug('@containers ' + @containers.object_id.to_s + ' has:'+ @containers[execution_environment.id].to_s)
Rails.logger.debug('@all_containers ' + @containers.object_id.to_s + ' has:'+ @all_containers[execution_environment.id].to_s)
Rails.logger.debug('@containers for ' + execution_environment.name.to_s + ' (' + @containers.object_id.to_s + ') has the following content: '+ @containers[execution_environment.id].to_s)
Rails.logger.debug('@all_containers for ' + execution_environment.name.to_s + ' (' + @all_containers.object_id.to_s + ') has the following content: ' + @all_containers[execution_environment.id].to_s)
#refill_count.times.map { create_container(execution_environment) }
end
end
def self.start_refill_task
@refill_task = Concurrent::TimerTask.new(execution_interval: config[:refill][:interval], run_now: false, timeout_interval: config[:refill][:timeout]) { refill }
@refill_task = Concurrent::TimerTask.new(execution_interval: config[:refill][:interval], run_now: true, timeout_interval: config[:refill][:timeout]) { refill }
@refill_task.execute
end
end