diff --git a/bin/auto_hck b/bin/auto_hck index f70632c1..e49a7860 100755 --- a/bin/auto_hck +++ b/bin/auto_hck @@ -9,6 +9,7 @@ module AutoHCK run do cli = CLI.new cli.parse(ARGV) + cli.restore_session if cli.test.load_session ENV.store 'LC_ALL', 'en_US.UTF-8' diff --git a/lib/all.rb b/lib/all.rb index 3167ebc0..f3e7f7a3 100644 --- a/lib/all.rb +++ b/lib/all.rb @@ -58,6 +58,7 @@ module AutoHCK autoload_relative :PhysHCK, 'setupmanagers/physhck/physhck' autoload_relative :Playlist, 'engines/hcktest/playlist' autoload_relative :Project, 'project' + autoload_relative :Session, 'session' autoload_relative :QemuHCK, 'setupmanagers/qemuhck/qemuhck' autoload_relative :QemuHCKError, 'setupmanagers/qemuhck/exceptions' autoload_relative :QemuMachine, 'setupmanagers/qemuhck/qemu_machine' diff --git a/lib/cli.rb b/lib/cli.rb index 1ef46817..d5e21f0c 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -4,7 +4,8 @@ module AutoHCK # class CLI class CLI - attr_reader :common, :install, :test, :mode + attr_reader :install, :mode + attr_accessor :common, :test def initialize @common = CommonOptions.new @@ -85,7 +86,7 @@ class TestOptions attr_accessor :platform, :drivers, :driver_path, :commit, :diff_file, :svvp, :dump, :gthb_context_prefix, :gthb_context_suffix, :playlist, :select_test_names, :reject_test_names, :triggers_file, :reject_report_sections, :boot_device, - :allow_test_duplication, :manual, :package_with_playlist + :allow_test_duplication, :manual, :package_with_playlist, :load_session def create_parser OptionParser.new do |parser| @@ -187,6 +188,10 @@ def define_options(parser) parser.on('--package-with-playlist', TrueClass, 'Load playlist into HLKX project package', &method(:package_with_playlist=)) + + parser.on('--load-session ', String, + 'Load session from workspace', + &method(:load_session=)) end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength end @@ -245,5 +250,9 @@ def parse(args) @mode = left.shift @sub_parser[@mode]&.order!(left) unless @mode.nil? end + + def restore_session + AutoHCK::Session.load_session_cli(self) + end end end diff --git a/lib/engines/hcktest/hcktest.rb b/lib/engines/hcktest/hcktest.rb index 4b8c5190..11a027e2 100644 --- a/lib/engines/hcktest/hcktest.rb +++ b/lib/engines/hcktest/hcktest.rb @@ -170,7 +170,10 @@ def run_clients_and_configure_setup(scope, **opts) retries = 0 begin scope.transaction do |tmp_scope| - run_clients tmp_scope, keep_alive: true, **opts + run_clients tmp_scope, keep_alive: true, + boot_from_snapshot: @project.restored, + reuse_tpm: @project.restored, + **opts configure_setup_and_synchronize end @@ -188,7 +191,7 @@ def upload_driver_package r_name = "#{@project.engine_tag}.zip" zip_path = "#{@project.workspace_path}/#{r_name}" - create_zip_from_directory(zip_path, @driver_path) + create_zip_from_directory(zip_path, @driver_path) unless File.exist?(zip_path) @project.result_uploader.upload_file(zip_path, r_name) end @@ -235,7 +238,7 @@ def prepare_tests def auto_run ResourceScope.open do |scope| - run_studio scope + run_studio(scope, boot_from_snapshot: @project.restored, reuse_tpm: @project.restored) sleep 5 until @studio.up? run_tests_without_config diff --git a/lib/engines/hcktest/playlist.rb b/lib/engines/hcktest/playlist.rb index dc6dad46..fa3b919d 100644 --- a/lib/engines/hcktest/playlist.rb +++ b/lib/engines/hcktest/playlist.rb @@ -99,13 +99,21 @@ def intersect_select_tests(select_test_names) end end + def custom_select_test_names_file(file) + test_names_file_path = "#{@project.workspace_path}/select_test_names.txt" + return File.readlines(test_names_file_path, chomp: true) if File.exist?(test_names_file_path) + + @logger.info('Copying custom select test names file to workspace') + FileUtils.cp(file, test_names_file_path) + end + def custom_select_test_names(log) user_select_test_names_file = @project.options.test.select_test_names select_test_names = if user_select_test_names_file.nil? @project.engine.target['select_test_names'] else - File.readlines(user_select_test_names_file, chomp: true) + custom_select_test_names_file(user_select_test_names_file) end return unless select_test_names diff --git a/lib/project.rb b/lib/project.rb index 42756584..8a5e79de 100644 --- a/lib/project.rb +++ b/lib/project.rb @@ -9,7 +9,7 @@ class Project attr_reader :config, :logger, :timestamp, :setup_manager, :engine, :id, :workspace_path, :github, :result_uploader, :engine_tag, :engine_platform, :engine_type, :options, :extra_sw_manager, - :run_terminated + :run_terminated, :restored def initialize(scope, options) @scope = scope @@ -17,7 +17,7 @@ def initialize(scope, options) Json.update_json_override(options.common.config) unless options.common.config.nil? init_multilog(options.common.verbose) init_class_variables - init_workspace + init_session @id = options.common.id scope << self end @@ -157,16 +157,20 @@ def check_run_termination @github.handle_cancel end - def init_workspace - unless @options.common.workspace_path.nil? - @workspace_path = @options.common.workspace_path - return - end + def load_session + @workspace_path = @options.test.load_session + raise AutoHCKError, 'Workspace path does not exist could not load session' unless File.directory?(@workspace_path) + + @logger.info("Loading session from #{@workspace_path}") + end + + def create_session @workspace_path = File.join(@config['workspace_path'], @engine_name, @engine_tag, @timestamp) + begin FileUtils.mkdir_p(@workspace_path) rescue Errno::EEXIST @@ -174,6 +178,18 @@ def init_workspace end @logger.info("Workspace path: #{@workspace_path}") + Session.save(@workspace_path, @options) + end + + def init_session + unless @options.common.workspace_path.nil? + @workspace_path = @options.common.workspace_path + @restored = @options.test.load_session + return + end + + @options.test.load_session ? load_session : create_session + begin File.delete("#{@config['workspace_path']}/latest") rescue Errno::ENOENT diff --git a/lib/session.rb b/lib/session.rb new file mode 100644 index 00000000..8cbe94b8 --- /dev/null +++ b/lib/session.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +# rubocop:disable Metrics/AbcSize,Metrics/MethodLength, Lint/MissingCopEnableDirective + +module AutoHCK + class Session + def self.save(workspace_path, options) + File.write("#{workspace_path}/session.json", compose_session_json(options)) + end + + def self.load_session_cli(cli) + json_data = JSON.parse(File.read("#{cli.test.load_session}/session.json")) + cli.test.platform = json_data['test']['platform'] + cli.test.drivers = json_data['test']['drivers'] + cli.test.driver_path = json_data['test']['driver_path'] + cli.test.commit = json_data['test']['commit'] + cli.test.diff_file = json_data['test']['diff_file'] + cli.test.svvp = json_data['test']['svvp'] + cli.test.dump = json_data['test']['dump'] + cli.test.gthb_context_prefix = json_data['test']['gthb_context_prefix'] + cli.test.gthb_context_suffix = json_data['test']['gthb_context_suffix'] + cli.test.playlist = json_data['test']['playlist'] + cli.test.select_test_names = json_data['test']['select_test_names'] + cli.test.reject_test_names = json_data['test']['reject_test_names'] + cli.test.triggers_file = json_data['test']['triggers_file'] + cli.test.reject_report_sections = json_data['test']['reject_report_sections'] + cli.test.boot_device = json_data['test']['boot_device'] + cli.test.allow_test_duplication = json_data['test']['allow_test_duplication'] + cli.test.manual = json_data['test']['manual'] + cli.test.package_with_playlist = json_data['test']['package_with_playlist'] + cli.common.verbose = json_data['common']['verbose'] + cli.common.config = json_data['common']['config'] + cli.common.client_world_net = json_data['common']['client_world_net'] + cli.common.id = json_data['common']['id'] + cli.common.share_on_host_path = json_data['common']['share_on_host_path'] + end + + private_class_method def self.compose_session_json(options) + { + 'test' => { + 'platform' => options.test.platform, + 'drivers' => options.test.drivers, + 'driver_path' => options.test.driver_path, + 'commit' => options.test.commit, + 'diff_file' => options.test.diff_file, + 'svvp' => options.test.svvp, + 'dump' => options.test.dump, + 'gthb_context_prefix' => options.test.gthb_context_prefix, + 'gthb_context_suffix' => options.test.gthb_context_suffix, + 'playlist' => options.test.playlist, + 'select_test_names' => options.test.select_test_names, + 'reject_test_names' => options.test.reject_test_names, + 'triggers_file' => options.test.triggers_file, + 'reject_report_sections' => options.test.reject_report_sections, + 'boot_device' => options.test.boot_device, + 'allow_test_duplication' => options.test.allow_test_duplication, + 'manual' => options.test.manual, + 'package_with_playlist' => options.test.package_with_playlist + }, + 'common' => { + 'verbose' => options.common.verbose, + 'config' => options.common.config, + 'client_world_net' => options.common.client_world_net, + 'id' => options.common.id, + 'share_on_host_path' => options.common.share_on_host_path + } + }.to_json + end + end +end diff --git a/lib/setupmanagers/qemuhck/qemu_machine.rb b/lib/setupmanagers/qemuhck/qemu_machine.rb index 05cfb3f6..a5301dd7 100644 --- a/lib/setupmanagers/qemuhck/qemu_machine.rb +++ b/lib/setupmanagers/qemuhck/qemu_machine.rb @@ -154,7 +154,8 @@ def close boot_from_snapshot: false, attach_iso_list: [], dump_only: false, - secure: false + secure: false, + reuse_tpm: false }.freeze MACHINE_JSON = 'lib/setupmanagers/qemuhck/machine.json' @@ -581,6 +582,8 @@ def save_run_script(file_name, file_content) def run_config_commands device_config_commands.each do |dirty_cmd| + next if dirty_cmd.include?('@swtpm_setup_bin@') && @run_opts[:reuse_tpm] + cmd = full_replacement_map.create_cmd(dirty_cmd) run_cmd(cmd) end