core: config.vm.box_url can be array of urls [GH-1958]
This commit is contained in:
parent
21bed5c0aa
commit
d7b74ca8b9
|
@ -25,6 +25,7 @@ IMPROVEMENTS:
|
||||||
specified for `vagrant box list` [GH-2327]
|
specified for `vagrant box list` [GH-2327]
|
||||||
- core: Multiple SSH keys can be specified with `config.ssh.private_key_path`
|
- core: Multiple SSH keys can be specified with `config.ssh.private_key_path`
|
||||||
[GH-907]
|
[GH-907]
|
||||||
|
- core: `config.vm.box_url` can be an array of URLs. [GH-1958]
|
||||||
- commands/box/add: Can now specify a client cert when downloading a
|
- commands/box/add: Can now specify a client cert when downloading a
|
||||||
box. [GH-1889]
|
box. [GH-1889]
|
||||||
- commands/init: Add `--output` option for specifing output path, or
|
- commands/init: Add `--output` option for specifing output path, or
|
||||||
|
|
|
@ -17,57 +17,33 @@ module Vagrant
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
@download_interrupted = false
|
@download_interrupted = false
|
||||||
@temp_path = env[:tmp_path].join("box" + Digest::SHA1.hexdigest(env[:box_url]))
|
|
||||||
@logger.info("Downloading box to: #{@temp_path}")
|
|
||||||
|
|
||||||
url = env[:box_url]
|
# Go through each URL and attempt to download it
|
||||||
if File.file?(url) || url !~ /^[a-z0-9]+:.*$/i
|
download_error = nil
|
||||||
@logger.info("URL is a file or protocol not found and assuming file.")
|
download_url = nil
|
||||||
file_path = File.expand_path(url)
|
urls = env[:box_url]
|
||||||
file_path = Util::Platform.cygwin_windows_path(file_path)
|
urls = [env[:box_url]] if !urls.is_a?(Array)
|
||||||
url = "file:#{file_path}"
|
urls.each do |url|
|
||||||
end
|
begin
|
||||||
|
@temp_path = download_box_url(url, env)
|
||||||
downloader_options = {}
|
download_error = nil
|
||||||
downloader_options[:continue] = true
|
download_url = url
|
||||||
downloader_options[:insecure] = env[:box_download_insecure]
|
rescue Errors::DownloaderError => e
|
||||||
downloader_options[:ui] = env[:ui]
|
env[:ui].error(I18n.t(
|
||||||
downloader_options[:client_cert] = env[:box_client_cert]
|
"vagrant.actions.box.download.download_failed"))
|
||||||
|
download_error = e
|
||||||
# If the temporary path exists, verify it is not too old. If its
|
|
||||||
# too old, delete it first because the data may have changed.
|
|
||||||
if @temp_path.file?
|
|
||||||
delete = false
|
|
||||||
if env[:box_clean]
|
|
||||||
@logger.info("Cleaning existing temp box file.")
|
|
||||||
delete = true
|
|
||||||
elsif @temp_path.mtime.to_i < (Time.now.to_i - 6 * 60 * 60)
|
|
||||||
@logger.info("Existing temp file is too old. Removing.")
|
|
||||||
delete = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@temp_path.unlink if delete
|
# If we were interrupted during this download, then just return
|
||||||
|
# at this point, we don't need to try anymore.
|
||||||
|
if @download_interrupted
|
||||||
|
@logger.warn("Download interrupted, not trying any more box URLs.")
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Download the box to a temporary path. We store the temporary
|
# If all the URLs failed, then raise an exception
|
||||||
# path as an instance variable so that the `#recover` method can
|
raise download_error if download_error
|
||||||
# access it.
|
|
||||||
env[:ui].info(I18n.t("vagrant.actions.box.download.downloading"))
|
|
||||||
|
|
||||||
if @temp_path.file?
|
|
||||||
env[:ui].info(I18n.t("vagrant.actions.box.download.resuming"))
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
downloader = Util::Downloader.new(url, @temp_path, downloader_options)
|
|
||||||
downloader.download!
|
|
||||||
rescue Errors::DownloaderInterrupted
|
|
||||||
# The downloader was interrupted, so just return, because that
|
|
||||||
# means we were interrupted as well.
|
|
||||||
@download_interrupted = true
|
|
||||||
env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
box_formats = env[:box_provider]
|
box_formats = env[:box_provider]
|
||||||
if box_formats
|
if box_formats
|
||||||
|
@ -103,7 +79,7 @@ module Vagrant
|
||||||
I18n.t("vagrant.actions.box.add.added", name: box_added.name, provider: box_added.provider))
|
I18n.t("vagrant.actions.box.add.added", name: box_added.name, provider: box_added.provider))
|
||||||
|
|
||||||
# Persists URL used on download and the time it was added
|
# Persists URL used on download and the time it was added
|
||||||
write_extra_info(box_added, url)
|
write_extra_info(box_added, download_url)
|
||||||
|
|
||||||
# Passes on the newly added box to the rest of the middleware chain
|
# Passes on the newly added box to the rest of the middleware chain
|
||||||
env[:box_added] = box_added
|
env[:box_added] = box_added
|
||||||
|
@ -118,6 +94,65 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def download_box_url(url, env)
|
||||||
|
temp_path = env[:tmp_path].join("box" + Digest::SHA1.hexdigest(url))
|
||||||
|
@logger.info("Downloading box: #{url} => #{temp_path}")
|
||||||
|
|
||||||
|
if File.file?(url) || url !~ /^[a-z0-9]+:.*$/i
|
||||||
|
@logger.info("URL is a file or protocol not found and assuming file.")
|
||||||
|
file_path = File.expand_path(url)
|
||||||
|
file_path = Util::Platform.cygwin_windows_path(file_path)
|
||||||
|
url = "file:#{file_path}"
|
||||||
|
end
|
||||||
|
|
||||||
|
downloader_options = {}
|
||||||
|
downloader_options[:continue] = true
|
||||||
|
downloader_options[:insecure] = env[:box_download_insecure]
|
||||||
|
downloader_options[:ui] = env[:ui]
|
||||||
|
downloader_options[:client_cert] = env[:box_client_cert]
|
||||||
|
|
||||||
|
# If the temporary path exists, verify it is not too old. If its
|
||||||
|
# too old, delete it first because the data may have changed.
|
||||||
|
if temp_path.file?
|
||||||
|
delete = false
|
||||||
|
if env[:box_clean]
|
||||||
|
@logger.info("Cleaning existing temp box file.")
|
||||||
|
delete = true
|
||||||
|
elsif temp_path.mtime.to_i < (Time.now.to_i - 6 * 60 * 60)
|
||||||
|
@logger.info("Existing temp file is too old. Removing.")
|
||||||
|
delete = true
|
||||||
|
end
|
||||||
|
|
||||||
|
temp_path.unlink if delete
|
||||||
|
end
|
||||||
|
|
||||||
|
# Download the box to a temporary path. We store the temporary
|
||||||
|
# path as an instance variable so that the `#recover` method can
|
||||||
|
# access it.
|
||||||
|
env[:ui].info(I18n.t(
|
||||||
|
"vagrant.actions.box.download.downloading",
|
||||||
|
url: url))
|
||||||
|
if temp_path.file?
|
||||||
|
env[:ui].info(I18n.t("vagrant.actions.box.download.resuming"))
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
downloader = Util::Downloader.new(url, temp_path, downloader_options)
|
||||||
|
downloader.download!
|
||||||
|
rescue Errors::DownloaderInterrupted
|
||||||
|
# The downloader was interrupted, so just return, because that
|
||||||
|
# means we were interrupted as well.
|
||||||
|
@download_interrupted = true
|
||||||
|
env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
|
||||||
|
rescue Errors::DownloaderError
|
||||||
|
# The download failed for some reason, clean out the temp path
|
||||||
|
temp_path.unlink if temp_path.file?
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
|
||||||
|
temp_path
|
||||||
|
end
|
||||||
|
|
||||||
def write_extra_info(box_added, url)
|
def write_extra_info(box_added, url)
|
||||||
info = {'url' => url, 'downloaded_at' => Time.now.utc}
|
info = {'url' => url, 'downloaded_at' => Time.now.utc}
|
||||||
box_added.directory.join('info.json').open("w+") do |f|
|
box_added.directory.join('info.json').open("w+") do |f|
|
||||||
|
|
|
@ -261,6 +261,11 @@ module VagrantPlugins
|
||||||
@hostname = nil if @hostname == UNSET_VALUE
|
@hostname = nil if @hostname == UNSET_VALUE
|
||||||
@hostname = @hostname.to_s if @hostname
|
@hostname = @hostname.to_s if @hostname
|
||||||
|
|
||||||
|
# Make sure the box URL is an array if it is set
|
||||||
|
if @box_url && !@box_url.is_a?(Array)
|
||||||
|
@box_url = [@box_url]
|
||||||
|
end
|
||||||
|
|
||||||
# Set the guest properly
|
# Set the guest properly
|
||||||
@guest = @guest.to_sym if @guest
|
@guest = @guest.to_sym if @guest
|
||||||
|
|
||||||
|
|
|
@ -1120,7 +1120,9 @@ en:
|
||||||
destroying: "Deleting box '%{name}'..."
|
destroying: "Deleting box '%{name}'..."
|
||||||
download:
|
download:
|
||||||
cleaning: "Cleaning up downloaded box..."
|
cleaning: "Cleaning up downloaded box..."
|
||||||
downloading: "Downloading or copying the box..."
|
downloading: "Downloading box from URL: %{url}"
|
||||||
|
download_failed: |-
|
||||||
|
Download failed. Will try another box URL if there is one.
|
||||||
interrupted: "Box download was interrupted. Exiting."
|
interrupted: "Box download was interrupted. Exiting."
|
||||||
resuming: "Box download is resuming from prior download progress"
|
resuming: "Box download is resuming from prior download progress"
|
||||||
verify:
|
verify:
|
||||||
|
|
|
@ -39,6 +39,10 @@ URL, then SSL certs will be verified.
|
||||||
If the box is not installed on the system, it will be retrieved from this
|
If the box is not installed on the system, it will be retrieved from this
|
||||||
URL when `vagrant up` is run.
|
URL when `vagrant up` is run.
|
||||||
|
|
||||||
|
This can also be an array of multiple URLs. The URLs will be tried in
|
||||||
|
order. Note that any client certificates, insecure download settings, and
|
||||||
|
so on will apply to all URLs in this list.
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
`config.vm.graceful_halt_timeout` - The time in seconds that Vagrant will
|
`config.vm.graceful_halt_timeout` - The time in seconds that Vagrant will
|
||||||
|
|
Loading…
Reference in New Issue