diff --git a/app/controllers/managements_controller.rb b/app/controllers/managements_controller.rb index 5382a025..67ea8b57 100644 --- a/app/controllers/managements_controller.rb +++ b/app/controllers/managements_controller.rb @@ -3389,7 +3389,7 @@ end @is_remote = true @users_pages = Paginator.new @users_count, @limit, params['page'] || 1 @offset ||= @users_pages.offset - @users = paginateHelper users.includes(:real_name_authentication_apply, :professional_authentication_apply, + @users = paginateHelper users.preload(:real_name_authentication_apply, :professional_authentication_apply, user_extensions: [:department, :school]), @limit respond_to do |format| diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index 68e4b4b0..85735080 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -333,7 +333,7 @@ class MyshixunsController < ApplicationController shixun_tomcat = Redmine::Configuration['shixun_tomcat'] uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo" user_id = User.current.id - params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), containers:(Base64.urlsafe_encode64(container_limit @myshixun.shixun.mirror_repositories))} + params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))} res = uri_exec uri, params if res && res['code'].to_i != 0 raise("实训云平台繁忙(繁忙等级:92)") @@ -362,7 +362,7 @@ class MyshixunsController < ApplicationController begin uri = "#{shixun_tomcat}/bridge/vnc/getvnc" shixun = @myshixun.shixun - params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(container_limit(shixun.mirror_repositories))}"} + params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}"} res = uri_exec uri, params if res && res['code'].to_i != 0 raise("实训云平台繁忙(繁忙等级:99)") diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index e47938ac..744dd683 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -791,7 +791,7 @@ class ShixunsController < ApplicationController shixun_script = modify_shixun_script @shixun, shixun_script end end - @shixun.evaluate_script = shixun_script + #@shixun.evaluate_script = shixun_script ActiveRecord::Base.transaction do begin @@ -808,10 +808,13 @@ class ShixunsController < ApplicationController @shixun.shixun_members << m # 镜像-实训关联表 ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present? + # 创建Pod配置信息 + ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if sub_type.present? sub_mirrors = sub_type.split(",").map(&:to_i) sub_mirrors.each do |mirror| ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) + ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) end end # 自动构建版本库 @@ -1025,6 +1028,7 @@ class ShixunsController < ApplicationController end def update + logger.info("#######-----#{params[:config]}") @shixun.attributes = params[:shixun] #@shixun.language = params[:language] @shixun.trainee = params[:trainee] @@ -1058,6 +1062,19 @@ class ShixunsController < ApplicationController end end + # 超级管理员才能保存 中间层服务器pod信息的配置 + if User.current.admin? || User.current.business? + @shixun.shixun_service_configs.each_with_index do |config, index| + config.update_attributes(:cpu_limit => params[:cpu_limit][index], + :lower_cpu_limit => params[:lower_cpu_limit][index], + :memory_limit => params[:memory_limit][index], + # :resource_limit => params[:resource_limit][index], + :request_limit => params[:request_limit][index], + :mirror_repository_id => params[:mirror_id][index]) + end + end + + ActiveRecord::Base.transaction do begin diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 34fa1a8d..cc93b840 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -268,6 +268,24 @@ module ApplicationHelper return container.to_json end + def shixun_container_limit shixun + container = [] + shixun.shixun_service_configs.each do |config| + mirror = config.mirror_repository + if mirror.name.present? + container << {:image => mirror.name, + :cpuLimit => config.cpu_limit, + :cpuRequest => config.lower_cpu_limit, + :memoryLimit => "#{config.memory_limit}M", + :memoryRequest => "#{config.request_limit}", + :resourceLimit => "#{config.resource_limit}K", + :type => mirror.try(:main_type) == "1" ? "main" : "sub"} + end + end + Rails.logger.info("#########container: #{container.to_json}") + return container.to_json + end + # 实训作品列表的提交状态 def list_work_status work, homework, course_group_id if work.work_status == 0 diff --git a/app/models/challenge.rb b/app/models/challenge.rb index 704fffb3..e5054c9b 100644 --- a/app/models/challenge.rb +++ b/app/models/challenge.rb @@ -20,7 +20,7 @@ class Challenge < ActiveRecord::Base # validates_presence_of :score validates_presence_of :task_pass validates_length_of :subject, :maximum => 255 - scope :min, lambda { select([:id, :subject, :position, :shixun_id, :st, :score, :path, :task_pass, :modify_time, :web_route, :answer]) } + scope :min, lambda { select([:id, :subject, :position, :shixun_id, :st, :score, :exec_time, :path, :task_pass, :modify_time, :web_route, :answer]) } scope :choose_type, lambda{where(st: 1)} scope :practice_type, lambda{where(st: 0)} diff --git a/app/models/shixun.rb b/app/models/shixun.rb index bf06b583..e7682a74 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -52,10 +52,10 @@ class Shixun < ActiveRecord::Base has_many :exercise_bank_shixun_challenges, :dependent => :destroy has_many :tag_repertoires, :through => :shixun_tag_repertoires has_many :shixun_tag_repertoires, :dependent => :destroy - + has_many :shixun_service_configs, :dependent => :destroy scope :visible, lambda{where(status: [2,3])} - scope :min, lambda { select([:id, :name, :gpid, :modify_time, :reset_time, :language, :propaedeutics, :status, :identifier, + scope :min, lambda { select([:id, :name, :gpid, :modify_time, :reset_time, :language, :status, :identifier, :test_set_permission, :hide_code, :forbid_copy, :hidden, :webssh, :user_id, :code_hidden, :task_pass, :exec_time, :multi_webssh, :vnc]) } scope :published, lambda{where(status: 2)} @@ -66,6 +66,18 @@ class Shixun < ActiveRecord::Base #scope :visible, -> { where(status: -1) } after_create :send_tiding + def description + self.has_attribute?(:description) ? self[:description] : "" + end + + def propaedeutics + self.has_attribute?(:propaedeutics) ? self[:propaedeutics] : "" + end + + def evaluate_script + self.has_attribute?(:evaluate_script) ? self[:evaluate_script] : "" + end + def should_compile? self.mirror_repositories.published_main_mirror.first.try(:should_compile) end diff --git a/app/models/shixun_service_config.rb b/app/models/shixun_service_config.rb new file mode 100644 index 00000000..94d67190 --- /dev/null +++ b/app/models/shixun_service_config.rb @@ -0,0 +1,7 @@ +class ShixunServiceConfig < ActiveRecord::Base + # attr_accessible :title, :body + # image_type: 镜像类型: 1 主镜像、2子镜像 + belongs_to :shixun + belongs_to :mirror_repository + +end diff --git a/app/services/games_service.rb b/app/services/games_service.rb index c77e7437..8589023a 100644 --- a/app/services/games_service.rb +++ b/app/services/games_service.rb @@ -42,7 +42,7 @@ class GamesService is_teacher = (user.user_extensions.identity == 0) tpm_identifier = shixun.try(:identifier) # 实训超时设置 - time_limit = shixun.exec_time + time_limit = game_challenge.exec_time # 高性能取上一关、下一关 prev_game = Game.prev_identifier(shixun.id, game.myshixun_id, game_challenge.position) @@ -82,7 +82,7 @@ class GamesService shixun_tomcat = Redmine::Configuration['shixun_tomcat'] service_host = Redmine::Configuration['vnc_url'] uri = "#{shixun_tomcat}/bridge/vnc/getvnc" - params = {tpiID: myshixun.id, :containers => "#{Base64.urlsafe_encode64(container_limit(shixun.mirror_repositories))}"} + params = {tpiID: myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}"} res = uri_exec uri, params if res && res['code'].to_i != 0 raise("实训云平台繁忙(繁忙等级:99)") @@ -573,7 +573,7 @@ class GamesService content_modified = params[:content_modified] # 决定文件内容是否有修改,有修改如果中间成pull没有更新,则轮询等待更新 params = {:tpiID => "#{myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{taskId}",:instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}", :times => params[:first].to_i, :podType => shixun.webssh, - :containers => "#{Base64.urlsafe_encode64(container_limit(shixun.mirror_repositories))}", :tpmScript => "#{tpmScript}", + :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}", :tpmScript => "#{tpmScript}", :timeLimit => "#{shixun.exec_time}", :content_modified => content_modified, :persistenceName => shixun.identifier, :isPublished => (shixun.status < 2 ? 0 : 1), :sec_key => params[:sec_key]} diff --git a/app/views/challenges/_new_or_edit_task_page.html.erb b/app/views/challenges/_new_or_edit_task_page.html.erb index b31e3373..4ddde7e5 100644 --- a/app/views/challenges/_new_or_edit_task_page.html.erb +++ b/app/views/challenges/_new_or_edit_task_page.html.erb @@ -82,6 +82,52 @@ 必填项 +
+

服务配置

+
+ +
+ +
+
+
+ <%# if User.current.admin? %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <%# end %> +
+ <% end %>
提交 diff --git a/app/views/challenges/_pass_task_show.html.erb b/app/views/challenges/_pass_task_show.html.erb index 2e116e9f..32527f1b 100644 --- a/app/views/challenges/_pass_task_show.html.erb +++ b/app/views/challenges/_pass_task_show.html.erb @@ -55,6 +55,20 @@ <% end %>
+
+

评测时限(S):

+ + <%# if User.current.admin? %> + + + + + + + + + <%# end %> +
<% end %> \ No newline at end of file + $("#unit-all").show(); + } + + $("input[name='public_degree']").live("click", function () { + var item = $(this).attr("id"); + if ($(this).is(":checked") && item == "public-part") { + $("#person-unit").show(); + $("#person-unit").find("input").val(""); + //$(".unit-part").remove(); + $("#unit-all").show(); + } else { + $("#unit-all").hide(); + } + }); + + $("body").on("click", function (e) { + //alert($(e.target).attr("id")); + if ($(e.target).attr("id") != "person-unit") { + $("#scope-down-list").hide(); + } + }); + //设置编辑时显示的单位 + $(".unit-part input").each(function () { + $(this).attr("size", parseInt($(this).val().length) * 2); + }) + }); + + //申请新建 + function post_apply() { + var html = "<%= escape_javascript(render :partial => 'shixuns/apply_setnew') %>"; + pop_box_new(html, 460, 416); + } + + var setting_editormd = editormd("setting_introduction", { + width: "100%", + height: 210, + syncScrolling: "single", + //你的lib目录的路径,我这边用JSP做测试的 + path: "/editormd/lib/", + tex: true, + toolbarIcons: function () { + // Or return editormd.toolbarModes[name]; // full, simple, mini + // Using "||" set icons align right. + return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] + }, + toolbarCustomIcons: { + testIcon: "
", + testIcon1: "
" + }, + onload: function () { + $("#setting_introduction [type=\"latex\"]").bind("click", function () { + setting_editormd.cm.replaceSelection("```latex"); + setting_editormd.cm.replaceSelection("\n"); + setting_editormd.cm.replaceSelection("\n"); + setting_editormd.cm.replaceSelection("```"); + var __Cursor = setting_editormd.cm.getDoc().getCursor(); + setting_editormd.cm.setCursor(__Cursor.line - 1, 0); + }); + + $("#setting_introduction [type=\"inline\"]").bind("click", function () { + setting_editormd.cm.replaceSelection("$$$$"); + var __Cursor = setting_editormd.cm.getDoc().getCursor(); + setting_editormd.cm.setCursor(__Cursor.line, __Cursor.ch - 2); + setting_editormd.cm.focus(); + }); + $("[type=\"inline\"]").attr("title", "行内公式"); + $("[type=\"latex\"]").attr("title", "多行公式"); + + }, + //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 + saveHTMLToTextarea: true, + autoFocus: false, + // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 + dialogMaskOpacity: 0.6, + placeholder: "请输入完成当前任务依赖的知识点或者其它相关信息", + imageUpload: true, + imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], + imageUploadURL: "<%= upload_with_markdown_path(:container_id => @shixun.id, :container_type => @shixun.class) %>" //url + }); + md_elocalStorage(setting_editormd, "shixun_edit_<%= User.current.id %>", "in"); + + var script_Codemirror = CodeMirror.fromTextArea(document.getElementById("shixun_script"), { + lineNumbers: true, + theme: "default", + // extraKeys: {"Ctrl-Q": "autocomplete"}, // 快捷键 + indentUnit: 4, //代码缩进为一个tab的距离 + matchBrackets: true, + autoRefresh: true, + smartIndent: true,//智能换行 + styleActiveLine: true, + lint: true + }); + script_Codemirror.setSize("auto", "600px"); + // 非管理员只能查看 + \ No newline at end of file diff --git a/db/migrate/20190626064125_create_shixun_service_configs.rb b/db/migrate/20190626064125_create_shixun_service_configs.rb new file mode 100644 index 00000000..a15a30f6 --- /dev/null +++ b/db/migrate/20190626064125_create_shixun_service_configs.rb @@ -0,0 +1,14 @@ +class CreateShixunServiceConfigs < ActiveRecord::Migration + def change + create_table :shixun_service_configs do |t| + t.references :shixun + t.integer :cpu_limit, :default => 1 + t.integer :memory_limit, :default => 1024 + t.integer :request_limit, :default => 10 + t.float :lower_cpu_limit, :default => 0.1 + t.integer :resource_limit, :default => 10000 + t.references :mirror_repository + t.timestamps + end + end +end diff --git a/db/migrate/20190626070641_add_limit_for_shixuns.rb b/db/migrate/20190626070641_add_limit_for_shixuns.rb new file mode 100644 index 00000000..1de29c80 --- /dev/null +++ b/db/migrate/20190626070641_add_limit_for_shixuns.rb @@ -0,0 +1,19 @@ +class AddLimitForShixuns < ActiveRecord::Migration + def up + Shixun.find_each do |shixun| + shixun.challenges.update_all(:exec_time => shixun.exec_time) + shixun.mirror_repositories.each do |mirror| + ShixunServiceConfig.create!(:shixun_id => shixun.id, + :cpu_limit => mirror.cpu_limit, + :memory_limit => mirror.memory_limit, + :request_limit => mirror.memory_limit / 3, + :mirror_repository_id => mirror.id) + end + end + + + end + + def down + end +end diff --git a/spec/factories/shixun_service_configs.rb b/spec/factories/shixun_service_configs.rb new file mode 100644 index 00000000..e1467908 --- /dev/null +++ b/spec/factories/shixun_service_configs.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :shixun_service_config do + + end +end diff --git a/spec/models/shixun_service_config_spec.rb b/spec/models/shixun_service_config_spec.rb new file mode 100644 index 00000000..ca83dde1 --- /dev/null +++ b/spec/models/shixun_service_config_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ShixunServiceConfig, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end