Download boxes using CURL!
This commit is contained in:
parent
94dd210be7
commit
6c1eb2b007
|
@ -1,5 +1,6 @@
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
|
require "vagrant/util/downloader"
|
||||||
require "vagrant/util/platform"
|
require "vagrant/util/platform"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
|
@ -14,18 +15,21 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
# Instantiate the downloader
|
@temp_path = env[:tmp_path].join("box" + Time.now.to_i.to_s)
|
||||||
downloader = download_klass(env[:box_url]).new(env[:ui])
|
@logger.info("Downloading box to: #{@temp_path}")
|
||||||
env[:ui].info I18n.t("vagrant.actions.box.download.with",
|
|
||||||
:class => downloader.class.to_s)
|
|
||||||
|
|
||||||
# Download the box to a temporary path. We store the temporary
|
# Download the box to a temporary path. We store the temporary
|
||||||
# path as an instance variable so that the `#recover` method can
|
# path as an instance variable so that the `#recover` method can
|
||||||
# access it.
|
# access it.
|
||||||
@temp_path = env[:tmp_path].join("box" + Time.now.to_i.to_s)
|
env[:ui].info(I18n.t("vagrant.actions.box.download.downloading"))
|
||||||
@logger.info("Downloading box to: #{@temp_path}")
|
begin
|
||||||
File.open(@temp_path, Vagrant::Util::Platform.tar_file_options) do |f|
|
downloader = Util::Downloader.new(env[:box_url], @temp_path, :ui => env[:ui])
|
||||||
downloader.download!(env[:box_url], f)
|
downloader.download!
|
||||||
|
rescue Errors::DownloaderInterrupted
|
||||||
|
# The downloader was interrupted, so just return, because that
|
||||||
|
# means we were interrupted as well.
|
||||||
|
env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add the box
|
# Add the box
|
||||||
|
@ -54,28 +58,8 @@ module Vagrant
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_klass(url)
|
|
||||||
# This is hardcoded for now. In the future I'd like to make this
|
|
||||||
# pluginnable as well.
|
|
||||||
classes = [Downloaders::HTTP, Downloaders::File]
|
|
||||||
|
|
||||||
# Find the class to use.
|
|
||||||
classes.each_index do |i|
|
|
||||||
klass = classes[i]
|
|
||||||
|
|
||||||
# Use the class if it matches the given URI or if this
|
|
||||||
# is the last class...
|
|
||||||
return klass if classes.length == (i + 1) || klass.match?(url)
|
|
||||||
end
|
|
||||||
|
|
||||||
# If no downloader knows how to download this file, then we
|
|
||||||
# raise an exception.
|
|
||||||
raise Errors::BoxDownloadUnknownType
|
|
||||||
end
|
|
||||||
|
|
||||||
def recover(env)
|
def recover(env)
|
||||||
if @temp_path && File.exist?(@temp_path)
|
if @temp_path && File.exist?(@temp_path)
|
||||||
env[:ui].info I18n.t("vagrant.actions.box.download.cleaning")
|
|
||||||
File.unlink(@temp_path)
|
File.unlink(@temp_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -95,10 +95,6 @@ module Vagrant
|
||||||
error_key(:already_exists, "vagrant.actions.box.unpackage")
|
error_key(:already_exists, "vagrant.actions.box.unpackage")
|
||||||
end
|
end
|
||||||
|
|
||||||
class BoxDownloadUnknownType < VagrantError
|
|
||||||
error_key(:unknown_type, "vagrant.actions.box.download")
|
|
||||||
end
|
|
||||||
|
|
||||||
class BoxMetadataFileNotFound < VagrantError
|
class BoxMetadataFileNotFound < VagrantError
|
||||||
error_key(:box_metadata_file_not_found)
|
error_key(:box_metadata_file_not_found)
|
||||||
end
|
end
|
||||||
|
@ -167,6 +163,10 @@ module Vagrant
|
||||||
error_key(:downloader_error)
|
error_key(:downloader_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DownloaderInterrupted < DownloaderError
|
||||||
|
error_key(:downloader_interrupted)
|
||||||
|
end
|
||||||
|
|
||||||
class DownloaderFileDoesntExist < VagrantError
|
class DownloaderFileDoesntExist < VagrantError
|
||||||
error_key(:file_missing, "vagrant.downloaders.file")
|
error_key(:file_missing, "vagrant.downloaders.file")
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
|
require "vagrant/util/busy"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
|
@ -10,12 +11,12 @@ module Vagrant
|
||||||
class Downloader
|
class Downloader
|
||||||
def initialize(source, destination, options=nil)
|
def initialize(source, destination, options=nil)
|
||||||
@logger = Log4r::Logger.new("vagrant::util::downloader")
|
@logger = Log4r::Logger.new("vagrant::util::downloader")
|
||||||
@source = source
|
@source = source.to_s
|
||||||
@destination = destination
|
@destination = destination.to_s
|
||||||
|
|
||||||
# Get the various optional values
|
# Get the various optional values
|
||||||
@options ||= {}
|
options ||= {}
|
||||||
@ui = @options[:ui]
|
@ui = options[:ui]
|
||||||
end
|
end
|
||||||
|
|
||||||
# This executes the actual download, downloading the source file
|
# This executes the actual download, downloading the source file
|
||||||
|
@ -70,24 +71,38 @@ module Vagrant
|
||||||
# 11 - Time left
|
# 11 - Time left
|
||||||
# 12 - Current speed
|
# 12 - Current speed
|
||||||
|
|
||||||
output = "Progress: #{columns[1]}% (Rate: #{columns[12]}/s, Estimated time remaining: #{columns[11]}"
|
output = "Progress: #{columns[1]}% (Rate: #{columns[12]}/s, Estimated time remaining: #{columns[11]})"
|
||||||
@ui.clear_line
|
@ui.clear_line
|
||||||
@ui.info(output, :new_line => false)
|
@ui.info(output, :new_line => false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create the callback that is called if we are interrupted
|
||||||
|
interrupted = false
|
||||||
|
int_callback = Proc.new do
|
||||||
|
@logger.info("Downloader interrupted!")
|
||||||
|
interrupted = true
|
||||||
|
end
|
||||||
|
|
||||||
@logger.info("Downloader starting download: ")
|
@logger.info("Downloader starting download: ")
|
||||||
@logger.info(" -- Source: #{@source}")
|
@logger.info(" -- Source: #{@source}")
|
||||||
@logger.info(" -- Destination: #{@destination}")
|
@logger.info(" -- Destination: #{@destination}")
|
||||||
|
|
||||||
# Execute!
|
# Execute!
|
||||||
result = Subprocess.execute("curl", *options, &data_proc)
|
result = Busy.busy(int_callback) do
|
||||||
|
Subprocess.execute("curl", *options, &data_proc)
|
||||||
|
end
|
||||||
|
|
||||||
|
# If the download was interrupted, then raise a specific error
|
||||||
|
raise Errors::DownloaderInterrupted if interrupted
|
||||||
|
|
||||||
# If it didn't exit successfully, we need to parse the data and
|
# If it didn't exit successfully, we need to parse the data and
|
||||||
# show an error message.
|
# show an error message.
|
||||||
if result.exit_code != 0
|
if result.exit_code != 0
|
||||||
parts = result.stderr.split(/\ncurl:\s+\(\d+\)\s*/, 2)
|
@logger.warn("Downloader exit code: #{result.exit_code}")
|
||||||
raise Errors::DownloaderError, :message => parts[1]
|
parts = result.stderr.split(/\n*curl:\s+\(\d+\)\s*/, 2)
|
||||||
|
parts[1] ||= ""
|
||||||
|
raise Errors::DownloaderError, :message => parts[1].chomp
|
||||||
end
|
end
|
||||||
|
|
||||||
# Everything succeeded
|
# Everything succeeded
|
||||||
|
|
|
@ -136,6 +136,9 @@ en:
|
||||||
again.
|
again.
|
||||||
|
|
||||||
%{message}
|
%{message}
|
||||||
|
downloader_interrupted: |-
|
||||||
|
The download was interrupted by an external signal. It did not
|
||||||
|
complete.
|
||||||
environment_locked: |-
|
environment_locked: |-
|
||||||
An instance of Vagrant is already running. Only one instance of Vagrant
|
An instance of Vagrant is already running. Only one instance of Vagrant
|
||||||
may run at any given time to avoid problems with VirtualBox inconsistencies
|
may run at any given time to avoid problems with VirtualBox inconsistencies
|
||||||
|
@ -853,9 +856,9 @@ en:
|
||||||
destroy:
|
destroy:
|
||||||
destroying: "Deleting box '%{name}'..."
|
destroying: "Deleting box '%{name}'..."
|
||||||
download:
|
download:
|
||||||
with: "Downloading with %{class}..."
|
|
||||||
cleaning: "Cleaning up downloaded box..."
|
cleaning: "Cleaning up downloaded box..."
|
||||||
unknown_type: "Unknown or unsupported URI type given for box download."
|
downloading: "Downloading or copying the box..."
|
||||||
|
interrupted: "Box download was interrupted. Exiting."
|
||||||
verify:
|
verify:
|
||||||
verifying: "Verifying box..."
|
verifying: "Verifying box..."
|
||||||
failed: |-
|
failed: |-
|
||||||
|
|
Loading…
Reference in New Issue