|
|
|
@ -3,6 +3,7 @@ class ShixunsController < ApplicationController
|
|
|
|
|
include ApplicationHelper
|
|
|
|
|
include ElasticsearchAble
|
|
|
|
|
include CoursesHelper
|
|
|
|
|
include JupyterService
|
|
|
|
|
|
|
|
|
|
before_action :require_login, :check_auth, except: [:download_file, :index, :menus, :show, :show_right, :ranking_list,
|
|
|
|
|
:discusses, :collaborators, :fork_list, :propaedeutics]
|
|
|
|
@ -24,6 +25,10 @@ class ShixunsController < ApplicationController
|
|
|
|
|
|
|
|
|
|
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
helper_method :jupyter_url_with_shixun, :jupyter_port_with_shixun
|
|
|
|
|
|
|
|
|
|
## 获取课程列表
|
|
|
|
|
def index
|
|
|
|
|
@shixuns = current_laboratory.shixuns.unhidden
|
|
|
|
@ -364,76 +369,112 @@ class ShixunsController < ApplicationController
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def create
|
|
|
|
|
# 评测脚本的一些操作
|
|
|
|
|
main_type, sub_type = params[:main_type], params[:small_type]
|
|
|
|
|
mirror = MirrorScript.where(:mirror_repository_id => main_type)
|
|
|
|
|
|
|
|
|
|
identifier = generate_identifier Shixun, 8
|
|
|
|
|
@shixun = Shixun.new(shixun_params)
|
|
|
|
|
@shixun.identifier = identifier
|
|
|
|
|
@shixun.user_id = current_user.id
|
|
|
|
|
@shixun.reset_time, @shixun.modify_time = Time.now, Time.now
|
|
|
|
|
|
|
|
|
|
if sub_type.blank?
|
|
|
|
|
shixun_script = mirror.first.try(:script)
|
|
|
|
|
else
|
|
|
|
|
main_mirror = MirrorRepository.find(main_type).type_name
|
|
|
|
|
sub_mirror = MirrorRepository.where(id: sub_type).pluck(:type_name)
|
|
|
|
|
if main_mirror == "Java" && sub_mirror.include?("Mysql")
|
|
|
|
|
shixun_script = mirror.last.try(:script)
|
|
|
|
|
else
|
|
|
|
|
shixun_script = mirror.first.try(:script)
|
|
|
|
|
shixun_script = modify_shixun_script @shixun, shixun_script
|
|
|
|
|
end
|
|
|
|
|
begin
|
|
|
|
|
@shixun = CreateShixunService.call(current_user, shixun_params, params)
|
|
|
|
|
rescue => e
|
|
|
|
|
logger_error("shixun_create_error: #{e.message}")
|
|
|
|
|
tip_exception("创建实训失败!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
@shixun.save!
|
|
|
|
|
# shixun_info关联ß
|
|
|
|
|
ShixunInfo.create!(shixun_id: @shixun.id, evaluate_script: shixun_script, description: params[:description])
|
|
|
|
|
# 实训的公开范围
|
|
|
|
|
if params[:scope_partment].present?
|
|
|
|
|
arr = []
|
|
|
|
|
ids = School.where(:name => params[:scope_partment]).pluck(:id).uniq
|
|
|
|
|
ids.each do |id|
|
|
|
|
|
arr << { :school_id => id, :shixun_id => @shixun.id }
|
|
|
|
|
end
|
|
|
|
|
ShixunSchool.create!(arr)
|
|
|
|
|
end
|
|
|
|
|
# 保存jupyter到版本库
|
|
|
|
|
def update_jupyter
|
|
|
|
|
jupyter_save_with_shixun(@shixun, params[:jupyter_port])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 实训合作者
|
|
|
|
|
@shixun.shixun_members.create!(user_id: current_user.id, role: 1)
|
|
|
|
|
|
|
|
|
|
# 镜像-实训关联表
|
|
|
|
|
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present?
|
|
|
|
|
# 实训主镜像服务配置
|
|
|
|
|
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i)
|
|
|
|
|
if sub_type.present?
|
|
|
|
|
sub_type.each do |mirror|
|
|
|
|
|
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
|
|
|
|
|
# 实训子镜像服务配置
|
|
|
|
|
name = MirrorRepository.find_by(id: mirror).try(:name) #查看镜像是否有名称,如果没有名称就不用服务配置
|
|
|
|
|
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) if name.present?
|
|
|
|
|
def update
|
|
|
|
|
# 镜像方面
|
|
|
|
|
mirror_ids = MirrorRepository.where(id: params[:main_type])
|
|
|
|
|
.or( MirrorRepository.where(id: params[:sub_type])).pluck(:id).uniq
|
|
|
|
|
old_mirror_ids = @shixun.shixun_mirror_repositories
|
|
|
|
|
.where(mirror_repository_id: params[:main_type])
|
|
|
|
|
.or(@shixun.shixun_mirror_repositories.where(mirror_repository_id: params[:sub_type]))
|
|
|
|
|
.pluck(:mirror_repository_id).uniq
|
|
|
|
|
new_mirror_id = (mirror_ids - old_mirror_ids).map{|id| {mirror_repository_id: id}} # 转换成数组hash方便操作
|
|
|
|
|
logger.info("##########new_mirror_id: #{new_mirror_id}")
|
|
|
|
|
logger.info("##########old_mirror_ids: #{old_mirror_ids}")
|
|
|
|
|
logger.info("##########mirror_ids: #{mirror_ids}")
|
|
|
|
|
# 服务配置方面
|
|
|
|
|
service_create_params = service_config_params[:shixun_service_configs]
|
|
|
|
|
.select{|config| !old_mirror_ids.include?(config[:mirror_repository_id]) &&
|
|
|
|
|
MirrorRepository.find(config[:mirror_repository_id]).name.present?}
|
|
|
|
|
service_update_params = service_config_params[:shixun_service_configs]
|
|
|
|
|
.select{|config| old_mirror_ids.include?(config[:mirror_repository_id])}
|
|
|
|
|
logger.info("#########service_create_params: #{service_create_params}")
|
|
|
|
|
logger.info("#########service_update_params: #{service_update_params}")
|
|
|
|
|
begin
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
@shixun.update_attributes(shixun_params)
|
|
|
|
|
@shixun.shixun_info.update_attributes(shixun_info_params)
|
|
|
|
|
# 镜像变动
|
|
|
|
|
@shixun.shixun_mirror_repositories.where.not(mirror_repository_id: old_mirror_ids).destroy_all
|
|
|
|
|
@shixun.shixun_mirror_repositories.create!(new_mirror_id)
|
|
|
|
|
# 镜像变动要更换服务配置
|
|
|
|
|
@shixun.shixun_service_configs.where.not(mirror_repository_id: old_mirror_ids).destroy_all
|
|
|
|
|
@shixun.shixun_service_configs.create!(service_create_params)
|
|
|
|
|
service_update_params&.map do |service|
|
|
|
|
|
smr = @shixun.shixun_service_configs.find_by(mirror_repository_id: service[:mirror_repository_id])
|
|
|
|
|
smr.update_attributes(service)
|
|
|
|
|
end
|
|
|
|
|
# 添加第二仓库(管理员权限)
|
|
|
|
|
if current_user.admin_or_business?
|
|
|
|
|
if params[:is_secret_repository]
|
|
|
|
|
add_secret_repository if @shixun.shixun_secret_repository.blank?
|
|
|
|
|
else
|
|
|
|
|
# 如果有仓库,就要删
|
|
|
|
|
if @shixun.shixun_secret_repository&.repo_name
|
|
|
|
|
@shixun.shixun_secret_repository.lock!
|
|
|
|
|
GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path)
|
|
|
|
|
@shixun.shixun_secret_repository.destroy
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
rescue => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("基本信息更新失败:#{e.message}")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 创建版本库
|
|
|
|
|
repo_path = repo_namespace(User.current.login, @shixun.identifier)
|
|
|
|
|
GitService.add_repository(repo_path: repo_path)
|
|
|
|
|
# todo: 为什么保存的时候要去除后面的.git呢??
|
|
|
|
|
@shixun.update_column(:repo_name, repo_path.split(".")[0])
|
|
|
|
|
# 实训权限设置
|
|
|
|
|
def update_permission_setting
|
|
|
|
|
# 查找需要增删的高校id
|
|
|
|
|
school_id = School.where(:name => params[:scope_partment]).pluck(:id)
|
|
|
|
|
old_school_ids = @shixun.shixun_schools.pluck(:school_id)
|
|
|
|
|
school_params = (school_id - old_school_ids).map{|id| {school_id: id}}
|
|
|
|
|
begin
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
@shixun.update_attributes!(shixun_params)
|
|
|
|
|
@shixun.shixun_schools.where.not(school_id: school_id).destroy_all if school_id.present?
|
|
|
|
|
@shixun.shixun_schools.create!(school_params)
|
|
|
|
|
end
|
|
|
|
|
rescue => e
|
|
|
|
|
uid_logger_error("实训权限设置失败--------#{e.message}")
|
|
|
|
|
tip_exception("实训权限设置失败")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 将实训标志为该云上实验室建立
|
|
|
|
|
Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true)
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("实训创建失败")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
# 实训学习页面设置
|
|
|
|
|
def update_learn_setting
|
|
|
|
|
begin
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
@shixun.update_attributes!(shixun_params)
|
|
|
|
|
end
|
|
|
|
|
rescue => e
|
|
|
|
|
uid_logger_error("实训学习页面设置失败--------#{e.message}")
|
|
|
|
|
tip_exception("实训学习页面设置失败")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# Jupyter数据集
|
|
|
|
|
def jupyter_data_sets
|
|
|
|
|
page = params[:page] || 1
|
|
|
|
|
limit = params[:limit] || 10
|
|
|
|
|
data_sets = @shixun.jupyter_data_sets
|
|
|
|
|
@data_count = data_sets.count
|
|
|
|
|
@data_sets= data_sets.page(page).per(limit)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def apply_shixun_mirror
|
|
|
|
|
form_params = params.permit(*%i[language runtime run_method attachment_id])
|
|
|
|
|
form = ApplyShixunMirrorForm.new(form_params)
|
|
|
|
@ -462,61 +503,6 @@ class ShixunsController < ApplicationController
|
|
|
|
|
tip_exception("申请失败")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def update
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
@shixun.shixun_mirror_repositories.destroy_all
|
|
|
|
|
if params[:main_type].present?
|
|
|
|
|
ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => params[:main_type].to_i)
|
|
|
|
|
end
|
|
|
|
|
if params[:small_type].present?
|
|
|
|
|
params[:small_type].each do |mirror|
|
|
|
|
|
ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
@shixun.update_attributes(shixun_params)
|
|
|
|
|
@shixun.shixun_info.update_attributes(shixun_info_params)
|
|
|
|
|
@shixun.shixun_schools.delete_all
|
|
|
|
|
# scope_partment: 高校的名称
|
|
|
|
|
if params[:scope_partment].present?
|
|
|
|
|
arr = []
|
|
|
|
|
ids = School.where(:name => params[:scope_partment]).pluck(:id).uniq
|
|
|
|
|
ids.each do |id|
|
|
|
|
|
arr << { :school_id => id, :shixun_id => @shixun.id }
|
|
|
|
|
end
|
|
|
|
|
ShixunSchool.create!(arr)
|
|
|
|
|
end
|
|
|
|
|
# 超级管理员和运营人员才能保存 中间层服务器pod信息的配置
|
|
|
|
|
# 如果镜像改动了,则也需要更改
|
|
|
|
|
mirror = @shixun.shixun_service_configs.map(&:mirror_repository_id).sort
|
|
|
|
|
new_mirror = params[:shixun_service_configs].map{|c| c[:mirror_repository_id]}.sort
|
|
|
|
|
if current_user.admin? || current_user.business? || (mirror != new_mirror)
|
|
|
|
|
@shixun.shixun_service_configs.destroy_all
|
|
|
|
|
service_config_params[:shixun_service_configs].each do |config|
|
|
|
|
|
name = MirrorRepository.find_by_id(config[:mirror_repository_id])&.name
|
|
|
|
|
# 不保存没有镜像的配置
|
|
|
|
|
@shixun.shixun_service_configs.create!(config) if name.present?
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
# 添加第二仓库
|
|
|
|
|
if params[:is_secret_repository]
|
|
|
|
|
add_secret_repository if @shixun.shixun_secret_repository.blank?
|
|
|
|
|
else
|
|
|
|
|
# 如果有仓库,就要删
|
|
|
|
|
if @shixun.shixun_secret_repository&.repo_name
|
|
|
|
|
@shixun.shixun_secret_repository.lock!
|
|
|
|
|
GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path)
|
|
|
|
|
@shixun.shixun_secret_repository.destroy
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error("实训保存失败--------#{e.message}")
|
|
|
|
|
tip_exception("实训保存失败")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 永久关闭实训
|
|
|
|
|
def close
|
|
|
|
@ -552,6 +538,8 @@ class ShixunsController < ApplicationController
|
|
|
|
|
# @evaluate_scirpt = @shixun.evaluate_script || "无"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取脚本内容
|
|
|
|
|
def get_script_contents
|
|
|
|
|
mirrir_script = MirrorScript.find(params[:script_id])
|
|
|
|
@ -1021,10 +1009,9 @@ class ShixunsController < ApplicationController
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
def shixun_params
|
|
|
|
|
raise("实训名称不能为空") if params[:shixun][:name].blank?
|
|
|
|
|
params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission,
|
|
|
|
|
:task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden,
|
|
|
|
|
:hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission)
|
|
|
|
|
:hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission, :is_jupyter)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def validate_review_shixun_params
|
|
|
|
@ -1033,8 +1020,6 @@ private
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def shixun_info_params
|
|
|
|
|
raise("实训描述不能为空") if params[:shixun_info][:description].blank?
|
|
|
|
|
raise("评测脚本不能为空") if params[:shixun_info][:evaluate_script].blank?
|
|
|
|
|
params.require(:shixun_info).permit(:description, :evaluate_script)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|