class CreateShixunService < ApplicationService attr_reader :user, :params, :permit_params def initialize(user, permit_params, params) @user = user @params = params @permit_params = permit_params end def call shixun = Shixun.new(permit_params) identifier = Util::UUID.generate_identifier(Shixun, 8) shixun.identifier= identifier shixun.user_id = user.id main_mirror = MirrorRepository.find params[:main_type] sub_mirrors = MirrorRepository.where(id: params[:sub_type]) begin ActiveRecord::Base.transaction do shixun.save! # 获取脚本内容 shixun_script = get_shixun_script(shixun, main_mirror, sub_mirrors) # 创建额外信息 ShixunInfo.create!(shixun_id: shixun.id, evaluate_script: shixun_script, description: params[:description]) # 创建合作者 shixun.shixun_members.create!(user_id: user.id, role: 1) # 创建镜像 ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => main_mirror.id) # 创建主服务配置 config_params = if shixun.is_jupyter? {shixun_id: shixun.id, mirror_repository_id: main_mirror.id, cpu_limit: 2, memory_limit: 1024, lower_cpu_limit: 0.2, request_limit: 100} else {shixun_id: shixun.id, mirror_repository_id: main_mirror.id} end ShixunServiceConfig.create!(config_params) # 创建子镜像相关数据(实训镜像关联表,子镜像服务配置) sub_mirrors.each do |sub| ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id) # 实训子镜像服务配置 name = sub.name #查看镜像是否有名称,如果没有名称就不用服务配置 ShixunServiceConfig.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id) if name.present? end # 创建版本库 repo_path = repo_namespace(user.login, shixun.identifier) GitService.add_repository(repo_path: repo_path) shixun.update_column(:repo_name, repo_path.split(".")[0]) # 如果是云上实验室,创建相关记录 if !Laboratory.current.main_site? Laboratory.current.laboratory_shixuns.create!(shixun: shixun, ownership: true) end # 如果是jupyter,先创建一个目录,为了挂载(因为后续数据集,开启Pod后环境在没销毁前,你上传数据集是挂载不上目录的,因此要先创建目录,方便中间层挂载) if shixun.is_jupyter? folder = EduSetting.get('shixun_folder') path = "#{folder}/#{identifier}" FileUtils.mkdir_p(path, :mode => 0777) unless File.directory?(path) end return shixun end rescue => e Rails.logger.error("shixun_create_error: #{e.message}") raise("创建实训失败!") end end private def get_shixun_script shixun, main_mirror, sub_mirrors if !shixun.is_jupyter? mirror = main_mirror.mirror_scripts if main_mirror.blank? modify_shixun_script shixun, mirror.first&.(:script) else sub_name = sub_mirrors.pluck(:type_name) if main_mirror.type_name == "Java" && sub_name.include?("Mysql") mirror.last.try(:script) else shixun_script = mirror.first&.script modify_shixun_script shixun, shixun_script end end end end def modify_shixun_script shixun, script if script.present? source_class_name = [] challenge_program_name = [] shixun.challenges.map(&:exec_path).each do |exec_path| challenge_program_name << "\"#{exec_path}\"" if shixun.main_mirror_name == "Java" if exec_path.nil? || exec_path.split("src/")[1].nil? source = "\"\"" else source = "\"#{exec_path.split("src/")[1].split(".java")[0]}\"" end logger.info("----source: #{source}") source_class_name << source.gsub("/", ".") if source.present? elsif shixun.main_mirror_name.try(:first) == "C#" if exec_path.nil? || exec_path.split(".")[1].nil? source = "\"\"" else source = "\"#{exec_path.split(".")[0]}.exe\"" end source_class_name << source if source.present? end end script = if script.include?("sourceClassName") && script.include?("challengeProgramName") script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)") else script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)") end end return script end # 版本库目录空间 def repo_namespace(user, shixun_identifier) "#{user}/#{shixun_identifier}.git" end end