Brian Cain d9e088ba5d (#8479) Disable install providers when using global id on vagrant up
Prior to this commit, when using a global id to bring up a vagrant vm,
vagrant would fail during the "install provider" step due to the fact
that the global vagrant machine was not configured for the local vagrant
environment. Since this global vm exists elsewhere, we disable the
install provider step so that vagrant can just bring up the global
vagrant machine.
2017-08-22 10:08:05 -07:00

194 lines
6.4 KiB
Ruby

require 'optparse'
require 'set'
require "vagrant"
require File.expand_path("../start_mixins", __FILE__)
module VagrantPlugins
module CommandUp
class Command < Vagrant.plugin("2", :command)
include StartMixins
def self.synopsis
"starts and provisions the vagrant environment"
end
def execute
options = {}
options[:destroy_on_error] = true
options[:install_provider] = true
options[:parallel] = true
options[:provision_ignore_sentinel] = false
opts = OptionParser.new do |o|
o.banner = "Usage: vagrant up [options] [name|id]"
o.separator ""
o.separator "Options:"
o.separator ""
build_start_options(o, options)
o.on("--[no-]destroy-on-error",
"Destroy machine if any fatal error happens (default to true)") do |destroy|
options[:destroy_on_error] = destroy
end
o.on("--[no-]parallel",
"Enable or disable parallelism if provider supports it") do |parallel|
options[:parallel] = parallel
end
o.on("--provider PROVIDER", String,
"Back the machine with a specific provider") do |provider|
options[:provider] = provider
end
o.on("--[no-]install-provider",
"If possible, install the provider if it isn't installed") do |p|
options[:install_provider] = p
end
end
# Parse the options
argv = parse_options(opts)
return if !argv
# Validate the provisioners
validate_provisioner_flags!(options, argv)
# Go over each VM and bring it up
@logger.debug("'Up' each target VM...")
# Get the names of the machines we want to bring up
names = argv
if names.empty?
autostart = false
@env.vagrantfile.machine_names_and_options.each do |n, o|
autostart = true if o.key?(:autostart)
o[:autostart] = true if !o.key?(:autostart)
names << n.to_s if o[:autostart]
end
# If we have an autostart key but no names, it means that
# all machines are autostart: false and we don't start anything.
names = nil if autostart && names.empty?
end
# Build up the batch job of what we'll do
machines = []
if names
# To prevent vagrant from attempting to validate a global vms config
# (which doesn't exist within the local dir) when attempting to
# install a machines provider, this check below will disable the
# install_providers function if a user gives us a machine id instead
# of the machines name.
machine_names = []
with_target_vms(names, provider: options[:provider]){|m| machine_names << m.name }
options[:install_provider] = false if !(machine_names - names).empty?
# If we're installing providers, then do that. We don't
# parallelize this step because it is likely the same provider
# anyways.
if options[:install_provider]
install_providers(names, provider: options[:provider])
end
@env.batch(options[:parallel]) do |batch|
with_target_vms(names, provider: options[:provider]) do |machine|
@env.ui.info(I18n.t(
"vagrant.commands.up.upping",
name: machine.name,
provider: machine.provider_name))
machines << machine
batch.action(machine, :up, options)
end
end
end
if machines.empty?
@env.ui.info(I18n.t("vagrant.up_no_machines"))
return 0
end
# Output the post-up messages that we have, if any
machines.each do |m|
next if !m.config.vm.post_up_message
next if m.config.vm.post_up_message == ""
# Add a newline to separate things.
@env.ui.info("", prefix: false)
m.ui.success(I18n.t(
"vagrant.post_up_message",
name: m.name.to_s,
message: m.config.vm.post_up_message))
end
# Success, exit status 0
0
end
protected
def install_providers(names, provider: nil)
# First create a set of all the providers we need to check for.
# Most likely this will be a set of one.
providers = Set.new
with_target_vms(names, provider: provider) do |machine|
# Check if we have this machine in the index
entry = @env.machine_index.get(machine.name.to_s)
# Get the provider for this machine. This logic isn't completely
# straightforward. If we have a forced provider, we always use
# that no matter what. If we have an entry in the index (meaning
# the machine may be created), we use that provider no matter
# what since that will be used by the core. If we have none, then
# we ask the Vagrant env what the default provider would be and use
# that.
#
# Note that this logic is a bit redundant if we have "provider"
# set but I think its probably cleaner to put this logic in one
# place.
p = provider
p = entry.provider.to_sym if !p && entry
p = @env.default_provider(
machine: machine.name.to_sym, check_usable: false) if !p
# Add it to the set
providers.add(p)
end
# Go through and determine if we can install the providers
providers.delete_if do |name|
!@env.can_install_provider?(name)
end
# Install the providers if we have to
providers.each do |name|
# Find the provider. Ignore if we can't find it, this error
# will pop up later in the process.
parts = Vagrant.plugin("2").manager.providers[name]
next if !parts
# If the provider is already installed, then our work here is done
cls = parts[0]
next if cls.installed?
# Some human-friendly output
ui = Vagrant::UI::Prefixed.new(@env.ui, "")
ui.output(I18n.t(
"vagrant.installing_provider",
provider: name.to_s))
ui.detail(I18n.t("vagrant.installing_provider_detail"))
# Install the provider
@env.install_provider(name)
end
end
end
end
end