diff --git a/lib/proxy/archive_extract.rb b/lib/proxy/archive_extract.rb new file mode 100644 index 000000000..02244036f --- /dev/null +++ b/lib/proxy/archive_extract.rb @@ -0,0 +1,27 @@ +module Proxy + class ArchiveExtract < Proxy::Util::CommandTask + include Util + + def initialize(image_path, file_in_image, dst_path) + + args = [which('isoinfo')] + + # read the file + args << "-R" + # set image path + args += ["-i", image_path.to_s] + # set file path within the image + args += ["-x", file_in_image.to_s] + # save destination path + @dst_path = dst_path + + super(args) + end + + def start + super do + File.open(@dst_path, "w+") { |file| file.write(@output) } + end + end + end +end diff --git a/lib/proxy/util.rb b/lib/proxy/util.rb index e191a70dd..7966af303 100644 --- a/lib/proxy/util.rb +++ b/lib/proxy/util.rb @@ -16,6 +16,7 @@ class CommandTask def initialize(command, input = nil) @command = command @input = input + @output = [] end def start(&ensured_block) @@ -29,6 +30,7 @@ def start(&ensured_block) stdin.close stdout.each do |line| logger.debug "[#{thr.pid}] #{line}" + @output.append(line) end stderr.each do |line| logger.warn "[#{thr.pid}] #{line}" @@ -47,6 +49,10 @@ def start(&ensured_block) def join @task.value end + + def output + @output + end end # convert setting to boolean (with a default value) diff --git a/lib/smart_proxy_main.rb b/lib/smart_proxy_main.rb index 0ebc22b2c..cb1217cf4 100644 --- a/lib/smart_proxy_main.rb +++ b/lib/smart_proxy_main.rb @@ -14,6 +14,7 @@ require 'proxy/dependency_injection' require 'proxy/util' require 'proxy/http_download' +require 'proxy/archive_extract' require 'proxy/helpers' require 'proxy/memory_store' require 'proxy/plugin_validators' diff --git a/modules/tftp/server.rb b/modules/tftp/server.rb index eba4e5e4a..3d119dde6 100644 --- a/modules/tftp/server.rb +++ b/modules/tftp/server.rb @@ -150,6 +150,30 @@ def pxeconfig_file(mac) end end + def self.fetch_boot_image(image_dst, url, files) + + # Verify dst is a valid directory + image_path = Pathname.new(image_dst).cleanpath + extr_image_dir = Pathname.new(image_dst.delete_suffix(".iso")) + + FileUtils.mkdir_p image_path.parent + choose_protocol_and_fetch(url, image_path).join + + files.each do |file| + file_path = Pathname.new file + extr_file_path = Pathname.new(File.join(extr_image_dir, file_path)).cleanpath + + # Create destination directory + FileUtils.mkdir_p extr_file_path.parent + # extract iso + extract_task = ::Proxy::ArchiveExtract.new(image_path, file_path, extr_file_path).start + raise "TFTP image file extraction error: #{file_path}" unless extract_task.join == 0 + end + + # adapt extracted file permission + FileUtils.chmod_R 0755, extr_image_dir + end + def self.fetch_boot_file(dst, src) filename = boot_filename(dst, src) destination = Pathname.new(File.expand_path(filename, Proxy::TFTP::Plugin.settings.tftproot)).cleanpath diff --git a/modules/tftp/tftp_api.rb b/modules/tftp/tftp_api.rb index 1bc6276c7..4f8f2c4da 100644 --- a/modules/tftp/tftp_api.rb +++ b/modules/tftp/tftp_api.rb @@ -34,6 +34,10 @@ def create_default(variant) end end + post "/fetch_boot_image" do + log_halt(400, "TFTP: Failed to fetch boot file: ") { Proxy::TFTP.fetch_boot_image(params[:path], params[:url], params[:files]) } + end + post "/fetch_boot_file" do log_halt(400, "TFTP: Failed to fetch boot file: ") { Proxy::TFTP.fetch_boot_file(params[:prefix], params[:path]) } end diff --git a/test/tftp/tftp_api_test.rb b/test/tftp/tftp_api_test.rb index 3ffcfb0cb..9e9270ada 100644 --- a/test/tftp/tftp_api_test.rb +++ b/test/tftp/tftp_api_test.rb @@ -111,7 +111,13 @@ def test_api_can_fetch_boot_file assert last_response.ok? end - def test_api_can_get_servername + def test_api_can_fetch_boot_image + Proxy::TFTP.expects(:fetch_boot_image).with('some/image.iso', 'http://localhost/file.iso').returns(true) + post "/fetch_boot_image", :path => 'some/image.iso', :url => 'http://localhost/file.iso' + assert last_response.ok? + end + + def test_api_can_get_servername Proxy::TFTP::Plugin.settings.stubs(:tftp_servername).returns("servername") result = get "/serverName" assert_match /servername/, result.body diff --git a/test/tftp/tftp_test.rb b/test/tftp/tftp_test.rb index 11dc6e204..874eb68e8 100644 --- a/test/tftp/tftp_test.rb +++ b/test/tftp/tftp_test.rb @@ -5,7 +5,8 @@ class TftpTest < Test::Unit::TestCase def setup @tftp = Proxy::TFTP::Server.new - Proxy::TFTP::Plugin.load_test_settings(:tftproot => "/some/root") + Proxy::TFTP::Plugin.load_test_settings(:tftproot => "/some/root", + :tftp_image_path => "/another/root") end def test_should_have_a_logger