Skip to content

Commit

Permalink
session verification
Browse files Browse the repository at this point in the history
  • Loading branch information
arielt committed Jan 25, 2014
1 parent 3c60262 commit c55f7f7
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 63 deletions.
16 changes: 9 additions & 7 deletions bin/bs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ cli_struct = {
'status' => 'BS::Session.new.status',
'make' => {'.+' => 'session_make'},
'clean' => 'session_clean',
'server' => 'session_server'
'server' => 'session_server',
'verify' => 'session_verify'
}
}

Expand Down Expand Up @@ -52,6 +53,7 @@ def print_usage
puts ' bs session make <task name>'
puts ' bs session clean'
puts ' bs session server'
puts ' bs session verify'
end

def quit_on_wrong_input
Expand Down Expand Up @@ -105,12 +107,7 @@ end

def verify(params)
enforce_root
if BS::Sandbox::Desktop.lock()
BS::Sandbox::Desktop.perform(params)
BS::Sandbox::Desktop.unlock()
else
puts "Busy, try again later" . red
end
BS::Sandbox::Desktop.perform(params[0], params[1])
end

def task_add(args)
Expand Down Expand Up @@ -152,9 +149,14 @@ def session_server
end

system("cd /home/atubaltsev/bs/webapp && /usr/local/rvm/bin/rvmsudo rails s -p 4101")
end

def session_verify
enforce_root
BS::Sandbox::Desktop.perform(BS::Session.new.config['task'], "#{BS::Session::SESSION_DIR}/solution.cpp")
end


# entry point
if ARGV.empty?
print_usage
Expand Down
96 changes: 52 additions & 44 deletions lib/bs/sandbox/desktop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,59 +11,67 @@ module BS
module Sandbox
module Desktop

ROOTFS = "/var/lib/lxc/#{DESKTOP_SB}/rootfs/"
VER_PATH = ROOTFS + "#{VER_DST_DIR}/"
LOCK_FILE = "/var/lib/lxc/#{DESKTOP_SB}/.lock"
# verification status
STATUS_OK = 0
STATUS_NOK = 1

extend self

def lock()
return false if File.exists?(LOCK_FILE)
FileUtils.touch(LOCK_FILE)
return true
end
SYSTEM_STATUS = {
true => STATUS_OK,
false => STATUS_NOK
}

def unlock()
FileUtils.rm_rf(LOCK_FILE)
end
ROOTFS = "/var/lib/lxc/#{DESKTOP_SB}/rootfs/"
VER_PATH = ROOTFS + "#{VER_DST_DIR}/"

def perform(params)
task_timeout = BS::Task.params(params[0])['verification_timeout']

BS::Sandbox::Policy.new(DESKTOP_SB).apply

FileUtils.rm_rf(VER_PATH + ".")
FileUtils.rm_rf("#{LOG_DIR}/execute")
FileUtils.cp(params[1], "#{VER_PATH}solution.cpp")
FileUtils.cp("#{TASK_DIR}/#{params[0]}/verification.cpp", "#{VER_PATH}verification.cpp")
FileUtils.cp("/opt/bs/files/#{VERIFICATOR[CPP]}", VER_PATH)

puts "Verification started...".green
rv = false
begin
Timeout.timeout(task_timeout || DEFAULT_TIME_LIMIT) do
command = "sudo lxc-execute -n #{DESKTOP_SB} -o #{LOG_DIR}/execute -l NOTICE #{VER_DST_DIR}/#{VERIFICATOR[CPP]}"
rv = system(command)
end
system("tail -n 25 #{VER_PATH}log.txt > #{VER_PATH}trunc_log.txt")
message = File.read("#{VER_PATH}trunc_log.txt")
rescue Timeout::Error
message = "Oops... It takes too long, we can't verify this"
system("sudo lxc-stop -n #{DESKTOP_SB} &")
sleep(1)
init_pid = fetch_init_pid("#{LOG_DIR}/execute", DESKTOP_SB)
system("sudo kill -9 #{init_pid} 2> /dev/null")
end
extend self

def perform(task_name, solution_file)
task_timeout = BS::Task.params(task_name)['verification_timeout']

BS::Sandbox::Policy.new(DESKTOP_SB).apply

puts message
FileUtils.rm_rf(VER_PATH + ".")
FileUtils.rm_rf("#{LOG_DIR}/execute")
FileUtils.cp(solution_file, "#{VER_PATH}solution.cpp")
FileUtils.cp("#{TASK_DIR}/#{task_name}/verification.cpp", "#{VER_PATH}verification.cpp")
FileUtils.cp("/opt/bs/files/#{VERIFICATOR[CPP]}", VER_PATH)

if rv
puts "Success".green
else
puts "Failure".red
puts "Verification started...".green
rv = false
begin
Timeout.timeout(task_timeout || DEFAULT_TIME_LIMIT) do
command = "sudo lxc-execute -n #{DESKTOP_SB} -o #{LOG_DIR}/execute -l NOTICE #{VER_DST_DIR}/#{VERIFICATOR[CPP]}"
rv = system(command)
end
system("tail -n 25 #{VER_PATH}log.txt > #{VER_PATH}trunc_log.txt")
message = File.read("#{VER_PATH}trunc_log.txt")
rescue Timeout::Error
message = "Oops... It takes too long, we can't verify this"
system("sudo lxc-stop -n #{DESKTOP_SB} &")
sleep(1)
init_pid = fetch_init_pid("#{LOG_DIR}/execute", DESKTOP_SB)
system("sudo kill -9 #{init_pid} 2> /dev/null")
end

puts message

if rv
puts "Success".green
else
puts "Failure".red
end

# under the session lock
session = BS::Session.new
session.config['verified_digest'] = session.config['request_digest']
session.config['verified_status'] = SYSTEM_STATUS[rv]
session.config['verified_message'] = message
session.save_config

session.unlock()
end


end
end
Expand Down
11 changes: 11 additions & 0 deletions lib/bs/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Session

SESSION_DIR = '/opt/bs/session/'
SESSION_FILE = "#{SESSION_DIR}config"
LOCK_FILE = "/opt/bs/session/.lock"

@config = nil

Expand Down Expand Up @@ -72,6 +73,16 @@ def accept
end
end

def lock()
return false if File.exists?(LOCK_FILE)
FileUtils.touch(LOCK_FILE)
return true
end

def unlock()
FileUtils.rm_rf(LOCK_FILE)
end

def countdown
(@config['deadline'] - Time.now).to_i
end
Expand Down
96 changes: 84 additions & 12 deletions webapp/app/controllers/active_sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ class ActiveSessionsController < ApplicationController
:autolink => true, :space_after_headers => true, :no_intra_emphasis => true
}

SECTION_SOLUTION = 0
SECTION_VERIFICATION = 1
SECTION_LINKAGE = 2
SECTION_TEST = 3
SECTION_BS = 4

CPP_SECTIONS = {
"[--build-solution--]" => SECTION_SOLUTION,
"[--build-verification--]" => SECTION_VERIFICATION,
"[--build-linkage--]" => SECTION_LINKAGE,
"[--test--]" => SECTION_TEST,
"[--bs--]" => SECTION_BS
}


@current_session = nil

before_filter :set_session
Expand All @@ -29,33 +44,87 @@ def index
end


def parse_cpp_message(message)
verified_issues = []
section = nil;
automatic = FALSE;

puts "PARSING"
puts message

return verified_issues unless message
message.split(/\r?\n|\r/).each do |line|
if CPP_SECTIONS[line]
section = CPP_SECTIONS[line]
next
end

case section
when SECTION_SOLUTION
if (line[/solution.cpp:.+:.+:.+:.+/])
verified_issues.push({type: "error", section: "test", line: nil, data: line})
automatic = TRUE
elsif automatic
verified_issues.push({type: "error", section: "test", line: nil, data: line})
else
automatic = FALSE
end
when SECTION_VERIFICATION
parts = line.split(':')
type = parts[3].strip unless parts[3].nil?
if (type != "note")
line = parts[1]
parts[0] = "build:internal"
verified_issues.push({type: type, section: "build", line: line, data: parts.join(':')})
end
when SECTION_LINKAGE
parts = line.split(':')
if parts[0] == "verification.cpp"
parts.delete_at(0)
parts.delete_at(0)
verified_issues.push({type: "error", section: "build", line: nil, data: "build: #{parts.join(':')}"})
end
when SECTION_TEST
if (p = /verification.cpp[^:]*:[^:]*:/.match line)
verified_issues.push({type: "error", section: "test", line: nil, data: p.post_match})
end
when SECTION_BS
# put bs section messages as is
verified_issues.push({type: "error", section: "test", line: nil, data: line})
else
# unknown section - probably long output
verified_issues.push({type: "error", section: "test", line: nil, data: "Something is basically wrong with this code"})
break;
end
end
verified_issues.to_json()
end

# Ajax POST call
def create
# lock the session
puts "LOCK"
return respond_to {|format| format.json {render :json => {status: STATUS_BUSY}}} unless BS::Sandbox::Desktop.lock()
return respond_to {|format| format.json {render :json => {status: STATUS_BUSY}}} unless @current_session.lock()

puts "GOING FORWARD"

# sumbit solution
# submit solution
if params["submit"] == "TRUE" then
puts "SUBMIT"
config = @current_session.load_config
config['is_active'] = false;
config['finished_at'] = Time.now;
config['forced_finish'] = FALSE;
@current_session.save_config
BS::Sandbox::Desktop.unlock()
@current_session.unlock()
return respond_to {|format| format.json {render :json => {status: STATUS_OK}}}
end

puts "GOING DIGEST"
# calculate digest
request_digest = Digest::MD5.hexdigest(params["check"].to_s)
puts request_digest
@current_session.config['verified_digest']

# return saved state if there is no change in code
if request_digest == @current_session.config['verified_digest']
parse_message()
@current_session.config['verified_issues'] = parse_cpp_message(@current_session.config['verified_message'])


# if there was a timeout - allow to verify once again
if @current_session.config['verified_message'].include?("[--bs--]:Oops... We've been waiting for too long")
Expand All @@ -69,7 +138,7 @@ def create
}.to_json
@current_session.save_config

BS::Sandbox::Desktop.unlock()
@current_session.unlock()
return respond_to {|format| format.json {render :json => @current_session.config['response']}}
end

Expand All @@ -78,8 +147,11 @@ def create
file << params['check']
file.close

params = [@current_session.config['task'], '/opt/bs/session/solution.cpp']
BS::Sandbox::Desktop.perform(params)
@current_session.config['request_digest'] = request_digest
@current_session.save_config

# schedule for background processing. fork on desktop.
system("/home/atubaltsev/bs/bin/bs session verify &")

respond_to {|format| format.json { render :json => {status: STATUS_BUSY}}}
end
Expand Down

0 comments on commit c55f7f7

Please sign in to comment.