Skip to content

Commit

Permalink
Enable boot image download for iso images
Browse files Browse the repository at this point in the history
* Implement fetch and extract boot image
* Apply correct file permissions
* Introduce and add tests for fetch_boot_image
* Implement class for file extraction
  • Loading branch information
bastian-src committed Aug 16, 2022
1 parent 9268440 commit 3a4bdf8
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 5 deletions.
31 changes: 31 additions & 0 deletions lib/proxy/archive_extract.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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]

super(args, input=nil, output=dst_path)
end

def start
lock = Proxy::FileLock.try_locking(File.join(File.dirname(@output), ".#{File.basename(@output)}.lock"))
if lock.nil?
false
else
super do
Proxy::FileLock.unlock(lock)
File.unlink(lock)
end
end
end
end
end
12 changes: 9 additions & 3 deletions lib/proxy/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ class CommandTask
# stderr is redirected to proxy error log, stdout to proxy debug log
# command can be either string or array (command + arguments)
# input is passed into STDIN and must be string
def initialize(command, input = nil)
def initialize(command, input = nil, output = nil)
@command = command
@input = input
@output = output
end

def start(&ensured_block)
Expand All @@ -27,8 +28,13 @@ def start(&ensured_block)
logger.info "[#{thr.pid}] Started task #{cmdline_string}"
stdin.write(input) if input
stdin.close
stdout.each do |line|
logger.debug "[#{thr.pid}] #{line}"
unless @output.nil?
File.binwrite(@output, stdout.read)
stdout.close
else
stdout.each do |line|
logger.debug "[#{thr.pid}] #{line}"
end
end
stderr.each do |line|
logger.warn "[#{thr.pid}] #{line}"
Expand Down
1 change: 1 addition & 0 deletions lib/smart_proxy_main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
21 changes: 21 additions & 0 deletions modules/tftp/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,27 @@ 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
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
Expand Down
4 changes: 4 additions & 0 deletions modules/tftp/tftp_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion test/tftp/tftp_api_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion test/tftp/tftp_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3a4bdf8

Please sign in to comment.